@promptbook/cli 0.112.0-89 → 0.112.0-91
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/apps/agents-server/src/database/ensureAutomaticDatabaseMigrations.ts +8 -1
- package/apps/agents-server/src/database/runDatabaseMigrations.ts +31 -1
- package/apps/agents-server/src/database/sqlite/$provideLocalSqliteSupabase.ts +2 -2
- package/apps/agents-server/src/middleware/createMiddlewareRequestContext.ts +1 -1
- package/apps/agents-server/src/tools/$provideServer.ts +27 -0
- package/apps/agents-server/src/utils/serverRegistry.ts +117 -3
- package/esm/apps/agents-server/src/utils/serverRegistry.d.ts +6 -0
- package/esm/index.es.js +100 -3
- package/esm/index.es.js.map +1 -1
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/cli/cli-commands/agents-server/startAgentsServer.ts +19 -9
- package/src/other/templates/getTemplatesPipelineCollection.ts +779 -980
- package/src/version.ts +2 -2
- package/src/versions.txt +2 -0
- package/umd/apps/agents-server/src/utils/serverRegistry.d.ts +6 -0
- package/umd/index.umd.js +100 -3
- package/umd/index.umd.js.map +1 -1
- package/umd/src/version.d.ts +1 -1
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
resolveDatabaseMigrationConnectionStringFromEnvironment,
|
|
4
4
|
runDatabaseMigrations,
|
|
5
5
|
} from './runDatabaseMigrations';
|
|
6
|
+
import { listEnvironmentRegisteredServers } from '../utils/serverRegistry';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Opt-out environment flag for automatic runtime migrations.
|
|
@@ -24,7 +25,13 @@ const automaticDatabaseMigrationPromiseByPrefix = new Map<string, Promise<void>>
|
|
|
24
25
|
* @private internal startup helper for Agents Server runtime
|
|
25
26
|
*/
|
|
26
27
|
export async function ensureAutomaticDatabaseMigrations(): Promise<void> {
|
|
27
|
-
|
|
28
|
+
const environmentServerPrefixes = listEnvironmentRegisteredServers().map((server) => server.tablePrefix);
|
|
29
|
+
|
|
30
|
+
if (environmentServerPrefixes.length === 0) {
|
|
31
|
+
return ensureAutomaticDatabaseMigrationsForPrefix(process.env.SUPABASE_TABLE_PREFIX || '');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
await Promise.all(environmentServerPrefixes.map((prefix) => ensureAutomaticDatabaseMigrationsForPrefix(prefix)));
|
|
28
35
|
}
|
|
29
36
|
|
|
30
37
|
/**
|
|
@@ -16,6 +16,7 @@ import { listRegisteredServersFromDatabase } from './listRegisteredServersFromDa
|
|
|
16
16
|
import { migratePrefix } from './migratePrefix';
|
|
17
17
|
import { readMigrationFiles, resolveMigrationsDirectory } from './resolveMigrationsDirectory';
|
|
18
18
|
import { selectPrefixesForMigration } from './selectPrefixesForMigration';
|
|
19
|
+
import { listEnvironmentRegisteredServers } from '../utils/serverRegistry';
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Allowed values describing who applied a migration record.
|
|
@@ -175,7 +176,10 @@ export async function resolveDatabaseMigrationRuntimeConfiguration(
|
|
|
175
176
|
try {
|
|
176
177
|
await client.connect();
|
|
177
178
|
|
|
178
|
-
const registeredServers =
|
|
179
|
+
const registeredServers = mergeRegisteredServers(
|
|
180
|
+
await listRegisteredServersFromDatabase(client),
|
|
181
|
+
listEnvironmentRegisteredServers(),
|
|
182
|
+
);
|
|
179
183
|
const hasExplicitDefaultPrefix = process.env[SUPABASE_TABLE_PREFIX_ENV_NAME] !== undefined;
|
|
180
184
|
const configuredPrefixes = uniquePrefixes([
|
|
181
185
|
...(hasExplicitDefaultPrefix
|
|
@@ -355,6 +359,32 @@ function uniquePrefixes(prefixes: ReadonlyArray<string>): Array<string> {
|
|
|
355
359
|
return result;
|
|
356
360
|
}
|
|
357
361
|
|
|
362
|
+
/**
|
|
363
|
+
* Combines database and environment registry rows, keeping database rows authoritative.
|
|
364
|
+
*
|
|
365
|
+
* @param databaseServers - Persistent `_Server` rows.
|
|
366
|
+
* @param environmentServers - Virtual rows derived from `SERVERS`.
|
|
367
|
+
* @returns Merged rows without duplicate domains.
|
|
368
|
+
*/
|
|
369
|
+
function mergeRegisteredServers(
|
|
370
|
+
databaseServers: ReadonlyArray<ServerRecord>,
|
|
371
|
+
environmentServers: ReadonlyArray<ServerRecord>,
|
|
372
|
+
): Array<ServerRecord> {
|
|
373
|
+
const seenDomains = new Set(databaseServers.map((server) => server.domain));
|
|
374
|
+
const mergedServers = [...databaseServers];
|
|
375
|
+
|
|
376
|
+
for (const environmentServer of environmentServers) {
|
|
377
|
+
if (seenDomains.has(environmentServer.domain)) {
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
mergedServers.push(environmentServer);
|
|
382
|
+
seenDomains.add(environmentServer.domain);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return mergedServers;
|
|
386
|
+
}
|
|
387
|
+
|
|
358
388
|
/**
|
|
359
389
|
* Creates one PostgreSQL client using the lazily loaded `pg` package.
|
|
360
390
|
*
|
|
@@ -750,11 +750,11 @@ class LocalSqliteQueryBuilder implements PromiseLike<LocalSqliteQueryResult> {
|
|
|
750
750
|
*/
|
|
751
751
|
private selectMatchingRowids(): Array<number | bigint> {
|
|
752
752
|
const where = this.createWhereClause();
|
|
753
|
-
const sql = `SELECT rowid FROM ${quoteIdentifier(this.tableName)} ${where.sql}`;
|
|
753
|
+
const sql = `SELECT rowid AS "__rowid" FROM ${quoteIdentifier(this.tableName)} ${where.sql}`;
|
|
754
754
|
return this.database
|
|
755
755
|
.prepare(sql)
|
|
756
756
|
.all(...where.values)
|
|
757
|
-
.map((row) => row.
|
|
757
|
+
.map((row) => row.__rowid as number | bigint);
|
|
758
758
|
}
|
|
759
759
|
|
|
760
760
|
/**
|
|
@@ -37,7 +37,7 @@ export async function createMiddlewareRequestContext(request: NextRequest): Prom
|
|
|
37
37
|
const requestIp = getRequestIp(request);
|
|
38
38
|
const host = request.headers.get('host');
|
|
39
39
|
const supabase = getMiddlewareSupabase();
|
|
40
|
-
const registeredServers = supabase ? await loadRegisteredServers() : [];
|
|
40
|
+
const registeredServers = supabase || process.env.SERVERS ? await loadRegisteredServers() : [];
|
|
41
41
|
const { canQueryServerTables, customDomainResolution, tablePrefixForRequest } = await resolveMiddlewareServerRouting(
|
|
42
42
|
{
|
|
43
43
|
host,
|
|
@@ -38,6 +38,33 @@ const getCachedProvidedServer = cache(async (): Promise<ProvidedServer> => {
|
|
|
38
38
|
const xPromptbookServer = headersList.get('x-promptbook-server');
|
|
39
39
|
|
|
40
40
|
if (isAgentsServerSqliteMode()) {
|
|
41
|
+
if (isLocalDevelopmentHost(requestHost)) {
|
|
42
|
+
return {
|
|
43
|
+
id: null,
|
|
44
|
+
publicUrl: resolveFallbackPublicUrl(requestHost),
|
|
45
|
+
tablePrefix: SUPABASE_TABLE_PREFIX,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const registeredServers = await listRegisteredServersUsingServiceRole();
|
|
50
|
+
if (registeredServers.length > 0) {
|
|
51
|
+
const { currentServer: resolvedSqliteServer } = resolveServerSelection({
|
|
52
|
+
host: requestHost,
|
|
53
|
+
forwardedServerHost: xPromptbookServer,
|
|
54
|
+
registeredServers,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
if (!resolvedSqliteServer) {
|
|
58
|
+
throw new Error(`Server with host "${requestHost}" is not registered in SERVERS`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
id: resolvedSqliteServer.id,
|
|
63
|
+
publicUrl: createServerPublicUrl(resolvedSqliteServer.domain),
|
|
64
|
+
tablePrefix: resolvedSqliteServer.tablePrefix,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
41
68
|
return {
|
|
42
69
|
id: null,
|
|
43
70
|
publicUrl: resolveFallbackPublicUrl(requestHost),
|
|
@@ -62,6 +62,16 @@ const SERVER_REGISTRY_SELECT = 'id,name,environment,domain,tablePrefix,createdAt
|
|
|
62
62
|
*/
|
|
63
63
|
const SERVER_REGISTRY_TABLE_NAME = '_Server';
|
|
64
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Environment variable with comma-separated standalone server domains.
|
|
67
|
+
*/
|
|
68
|
+
const SERVERS_ENV_NAME = 'SERVERS';
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Stable timestamp used by virtual server records derived from environment variables.
|
|
72
|
+
*/
|
|
73
|
+
const ENVIRONMENT_SERVER_TIMESTAMP = '1970-01-01T00:00:00.000Z';
|
|
74
|
+
|
|
65
75
|
/**
|
|
66
76
|
* In-memory cache TTL for repeated registry lookups inside one runtime process.
|
|
67
77
|
*/
|
|
@@ -127,8 +137,10 @@ export async function listRegisteredServers(supabase: Pick<SupabaseClient, 'from
|
|
|
127
137
|
export async function listRegisteredServersUsingServiceRole(options?: {
|
|
128
138
|
readonly forceRefresh?: boolean;
|
|
129
139
|
}): Promise<Array<ServerRecord>> {
|
|
140
|
+
const environmentServers = listEnvironmentRegisteredServers();
|
|
141
|
+
|
|
130
142
|
if (isAgentsServerSqliteMode()) {
|
|
131
|
-
return
|
|
143
|
+
return environmentServers;
|
|
132
144
|
}
|
|
133
145
|
|
|
134
146
|
const shouldReuseCache =
|
|
@@ -137,7 +149,7 @@ export async function listRegisteredServersUsingServiceRole(options?: {
|
|
|
137
149
|
Date.now() - cachedServerRegistry.loadedAt < SERVER_REGISTRY_CACHE_TTL_MS;
|
|
138
150
|
|
|
139
151
|
if (shouldReuseCache) {
|
|
140
|
-
return cachedServerRegistry!.serversPromise;
|
|
152
|
+
return mergeRegisteredServers(await cachedServerRegistry!.serversPromise, environmentServers);
|
|
141
153
|
}
|
|
142
154
|
|
|
143
155
|
const serversPromise = listRegisteredServers(getServerRegistryClient());
|
|
@@ -147,7 +159,7 @@ export async function listRegisteredServersUsingServiceRole(options?: {
|
|
|
147
159
|
};
|
|
148
160
|
|
|
149
161
|
try {
|
|
150
|
-
return await serversPromise;
|
|
162
|
+
return mergeRegisteredServers(await serversPromise, environmentServers);
|
|
151
163
|
} catch (error) {
|
|
152
164
|
if (cachedServerRegistry?.serversPromise === serversPromise) {
|
|
153
165
|
cachedServerRegistry = null;
|
|
@@ -156,6 +168,35 @@ export async function listRegisteredServersUsingServiceRole(options?: {
|
|
|
156
168
|
}
|
|
157
169
|
}
|
|
158
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Loads virtual server records from the comma-separated `SERVERS` environment variable.
|
|
173
|
+
*
|
|
174
|
+
* @returns Server records with deterministic table prefixes derived from normalized domains.
|
|
175
|
+
*/
|
|
176
|
+
export function listEnvironmentRegisteredServers(): Array<ServerRecord> {
|
|
177
|
+
const rawServers = process.env[SERVERS_ENV_NAME];
|
|
178
|
+
if (!rawServers) {
|
|
179
|
+
return [];
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const normalizedDomains = uniqueStrings(
|
|
183
|
+
rawServers
|
|
184
|
+
.split(',')
|
|
185
|
+
.map((server) => normalizeServerDomain(server))
|
|
186
|
+
.filter((server): server is string => Boolean(server)),
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
return normalizedDomains.map((domain, index) => ({
|
|
190
|
+
id: -(index + 1),
|
|
191
|
+
name: domain,
|
|
192
|
+
environment: SERVER_ENVIRONMENT.PRODUCTION,
|
|
193
|
+
domain,
|
|
194
|
+
tablePrefix: buildEnvironmentServerTablePrefix(domain),
|
|
195
|
+
createdAt: ENVIRONMENT_SERVER_TIMESTAMP,
|
|
196
|
+
updatedAt: ENVIRONMENT_SERVER_TIMESTAMP,
|
|
197
|
+
}));
|
|
198
|
+
}
|
|
199
|
+
|
|
159
200
|
/**
|
|
160
201
|
* Finds one registered server by incoming host header.
|
|
161
202
|
*
|
|
@@ -404,3 +445,76 @@ function hasHttpProtocol(value: string): boolean {
|
|
|
404
445
|
function isDefaultPortForProtocol(protocol: string, port: string): boolean {
|
|
405
446
|
return (protocol === 'http:' && port === '80') || (protocol === 'https:' && port === '443');
|
|
406
447
|
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Combines database and environment registry rows, keeping database rows authoritative.
|
|
451
|
+
*
|
|
452
|
+
* @param databaseServers - Persistent `_Server` rows.
|
|
453
|
+
* @param environmentServers - Virtual rows derived from `SERVERS`.
|
|
454
|
+
* @returns Merged rows without duplicate domains.
|
|
455
|
+
*/
|
|
456
|
+
function mergeRegisteredServers(
|
|
457
|
+
databaseServers: ReadonlyArray<ServerRecord>,
|
|
458
|
+
environmentServers: ReadonlyArray<ServerRecord>,
|
|
459
|
+
): Array<ServerRecord> {
|
|
460
|
+
const seenDomains = new Set<string>();
|
|
461
|
+
const mergedServers = [...databaseServers];
|
|
462
|
+
|
|
463
|
+
for (const databaseServer of databaseServers) {
|
|
464
|
+
const normalizedDomain = normalizeServerDomain(databaseServer.domain);
|
|
465
|
+
if (normalizedDomain) {
|
|
466
|
+
seenDomains.add(normalizedDomain);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
for (const environmentServer of environmentServers) {
|
|
471
|
+
const normalizedDomain = normalizeServerDomain(environmentServer.domain);
|
|
472
|
+
if (!normalizedDomain || seenDomains.has(normalizedDomain)) {
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
mergedServers.push(environmentServer);
|
|
477
|
+
seenDomains.add(normalizedDomain);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
return mergedServers;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Builds a deterministic table prefix from a normalized domain.
|
|
485
|
+
*
|
|
486
|
+
* @param domain - Normalized server domain.
|
|
487
|
+
* @returns Prefix such as `server_www_example_com_`.
|
|
488
|
+
*/
|
|
489
|
+
function buildEnvironmentServerTablePrefix(domain: string): string {
|
|
490
|
+
const prefixSuffix = domain
|
|
491
|
+
.toLowerCase()
|
|
492
|
+
.replace(/-/gu, '_dash_')
|
|
493
|
+
.replace(/\./gu, '_')
|
|
494
|
+
.replace(/:/gu, '_port_')
|
|
495
|
+
.replace(/[^a-z0-9_]/gu, '_')
|
|
496
|
+
.replace(/_+/gu, '_')
|
|
497
|
+
.replace(/^_+|_+$/gu, '');
|
|
498
|
+
|
|
499
|
+
return `server_${prefixSuffix}_`;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Deduplicates non-empty strings while preserving input order.
|
|
504
|
+
*
|
|
505
|
+
* @param values - Raw string values.
|
|
506
|
+
* @returns Unique non-empty strings.
|
|
507
|
+
*/
|
|
508
|
+
function uniqueStrings(values: ReadonlyArray<string>): Array<string> {
|
|
509
|
+
const uniqueValues: Array<string> = [];
|
|
510
|
+
|
|
511
|
+
for (const value of values) {
|
|
512
|
+
if (!value || uniqueValues.includes(value)) {
|
|
513
|
+
continue;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
uniqueValues.push(value);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
return uniqueValues;
|
|
520
|
+
}
|
|
@@ -65,6 +65,12 @@ export declare function listRegisteredServers(supabase: Pick<SupabaseClient, 'fr
|
|
|
65
65
|
export declare function listRegisteredServersUsingServiceRole(options?: {
|
|
66
66
|
readonly forceRefresh?: boolean;
|
|
67
67
|
}): Promise<Array<ServerRecord>>;
|
|
68
|
+
/**
|
|
69
|
+
* Loads virtual server records from the comma-separated `SERVERS` environment variable.
|
|
70
|
+
*
|
|
71
|
+
* @returns Server records with deterministic table prefixes derived from normalized domains.
|
|
72
|
+
*/
|
|
73
|
+
export declare function listEnvironmentRegisteredServers(): Array<ServerRecord>;
|
|
68
74
|
/**
|
|
69
75
|
* Finds one registered server by incoming host header.
|
|
70
76
|
*
|
package/esm/index.es.js
CHANGED
|
@@ -58,7 +58,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
58
58
|
* @generated
|
|
59
59
|
* @see https://github.com/webgptorg/promptbook
|
|
60
60
|
*/
|
|
61
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
61
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-91';
|
|
62
62
|
/**
|
|
63
63
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
64
64
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -36106,6 +36106,12 @@ const PTBK_AGENTS_SERVER_DATABASE_ENV = 'PTBK_AGENTS_SERVER_DATABASE';
|
|
|
36106
36106
|
* @private internal constant of `ptbk agents-server`
|
|
36107
36107
|
*/
|
|
36108
36108
|
const PTBK_AGENTS_SERVER_SQLITE_PATH_ENV = 'PTBK_AGENTS_SERVER_SQLITE_PATH';
|
|
36109
|
+
/**
|
|
36110
|
+
* Optional hostname used by the internal Next server.
|
|
36111
|
+
*
|
|
36112
|
+
* @private internal constant of `ptbk agents-server`
|
|
36113
|
+
*/
|
|
36114
|
+
const PTBK_HOSTNAME_ENV = 'PTBK_HOSTNAME';
|
|
36109
36115
|
/**
|
|
36110
36116
|
* Entropy size for the local-only token shared by the CLI pump and the Next app.
|
|
36111
36117
|
*
|
|
@@ -36224,8 +36230,15 @@ async function resolveAgentsServerRuntimePaths() {
|
|
|
36224
36230
|
* Starts the production Next server and wires its logs into the foreground dashboard.
|
|
36225
36231
|
*/
|
|
36226
36232
|
function startNextServer(options) {
|
|
36233
|
+
var _a;
|
|
36227
36234
|
logRunnerEvent(options.logStreams.runner, 'Starting the Agents Server Next process.');
|
|
36228
|
-
const
|
|
36235
|
+
const nextArguments = [options.nextCliPath, 'start', '--port', String(options.options.port)];
|
|
36236
|
+
const hostname = (_a = options.childEnvironment[PTBK_HOSTNAME_ENV]) === null || _a === void 0 ? void 0 : _a.trim();
|
|
36237
|
+
if (hostname) {
|
|
36238
|
+
nextArguments.push('--hostname', hostname);
|
|
36239
|
+
logRunnerEvent(options.logStreams.runner, `Binding Agents Server Next process to ${hostname}.`);
|
|
36240
|
+
}
|
|
36241
|
+
const commandProcess = spawn(process.execPath, nextArguments, {
|
|
36229
36242
|
cwd: options.runtimePaths.appPath,
|
|
36230
36243
|
env: options.childEnvironment,
|
|
36231
36244
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
@@ -67590,6 +67603,38 @@ const SERVER_ENVIRONMENT = {
|
|
|
67590
67603
|
* Global source-of-truth table for server routing and migration targeting.
|
|
67591
67604
|
*/
|
|
67592
67605
|
const SERVER_REGISTRY_TABLE_NAME = '_Server';
|
|
67606
|
+
/**
|
|
67607
|
+
* Environment variable with comma-separated standalone server domains.
|
|
67608
|
+
*/
|
|
67609
|
+
const SERVERS_ENV_NAME = 'SERVERS';
|
|
67610
|
+
/**
|
|
67611
|
+
* Stable timestamp used by virtual server records derived from environment variables.
|
|
67612
|
+
*/
|
|
67613
|
+
const ENVIRONMENT_SERVER_TIMESTAMP = '1970-01-01T00:00:00.000Z';
|
|
67614
|
+
/**
|
|
67615
|
+
* Loads virtual server records from the comma-separated `SERVERS` environment variable.
|
|
67616
|
+
*
|
|
67617
|
+
* @returns Server records with deterministic table prefixes derived from normalized domains.
|
|
67618
|
+
*/
|
|
67619
|
+
function listEnvironmentRegisteredServers() {
|
|
67620
|
+
const rawServers = process.env[SERVERS_ENV_NAME];
|
|
67621
|
+
if (!rawServers) {
|
|
67622
|
+
return [];
|
|
67623
|
+
}
|
|
67624
|
+
const normalizedDomains = uniqueStrings$1(rawServers
|
|
67625
|
+
.split(',')
|
|
67626
|
+
.map((server) => normalizeServerDomain(server))
|
|
67627
|
+
.filter((server) => Boolean(server)));
|
|
67628
|
+
return normalizedDomains.map((domain, index) => ({
|
|
67629
|
+
id: -(index + 1),
|
|
67630
|
+
name: domain,
|
|
67631
|
+
environment: SERVER_ENVIRONMENT.PRODUCTION,
|
|
67632
|
+
domain,
|
|
67633
|
+
tablePrefix: buildEnvironmentServerTablePrefix(domain),
|
|
67634
|
+
createdAt: ENVIRONMENT_SERVER_TIMESTAMP,
|
|
67635
|
+
updatedAt: ENVIRONMENT_SERVER_TIMESTAMP,
|
|
67636
|
+
}));
|
|
67637
|
+
}
|
|
67593
67638
|
/**
|
|
67594
67639
|
* Normalizes one raw `_Server` row and validates required fields.
|
|
67595
67640
|
*
|
|
@@ -67710,6 +67755,39 @@ function hasHttpProtocol(value) {
|
|
|
67710
67755
|
function isDefaultPortForProtocol(protocol, port) {
|
|
67711
67756
|
return (protocol === 'http:' && port === '80') || (protocol === 'https:' && port === '443');
|
|
67712
67757
|
}
|
|
67758
|
+
/**
|
|
67759
|
+
* Builds a deterministic table prefix from a normalized domain.
|
|
67760
|
+
*
|
|
67761
|
+
* @param domain - Normalized server domain.
|
|
67762
|
+
* @returns Prefix such as `server_www_example_com_`.
|
|
67763
|
+
*/
|
|
67764
|
+
function buildEnvironmentServerTablePrefix(domain) {
|
|
67765
|
+
const prefixSuffix = domain
|
|
67766
|
+
.toLowerCase()
|
|
67767
|
+
.replace(/-/gu, '_dash_')
|
|
67768
|
+
.replace(/\./gu, '_')
|
|
67769
|
+
.replace(/:/gu, '_port_')
|
|
67770
|
+
.replace(/[^a-z0-9_]/gu, '_')
|
|
67771
|
+
.replace(/_+/gu, '_')
|
|
67772
|
+
.replace(/^_+|_+$/gu, '');
|
|
67773
|
+
return `server_${prefixSuffix}_`;
|
|
67774
|
+
}
|
|
67775
|
+
/**
|
|
67776
|
+
* Deduplicates non-empty strings while preserving input order.
|
|
67777
|
+
*
|
|
67778
|
+
* @param values - Raw string values.
|
|
67779
|
+
* @returns Unique non-empty strings.
|
|
67780
|
+
*/
|
|
67781
|
+
function uniqueStrings$1(values) {
|
|
67782
|
+
const uniqueValues = [];
|
|
67783
|
+
for (const value of values) {
|
|
67784
|
+
if (!value || uniqueValues.includes(value)) {
|
|
67785
|
+
continue;
|
|
67786
|
+
}
|
|
67787
|
+
uniqueValues.push(value);
|
|
67788
|
+
}
|
|
67789
|
+
return uniqueValues;
|
|
67790
|
+
}
|
|
67713
67791
|
|
|
67714
67792
|
/**
|
|
67715
67793
|
* SQL query used to load all registered servers in a deterministic order.
|
|
@@ -68068,7 +68146,7 @@ async function resolveDatabaseMigrationRuntimeConfiguration(logger = console) {
|
|
|
68068
68146
|
const client = await createPostgresClient(connectionString);
|
|
68069
68147
|
try {
|
|
68070
68148
|
await client.connect();
|
|
68071
|
-
const registeredServers = await listRegisteredServersFromDatabase(client);
|
|
68149
|
+
const registeredServers = mergeRegisteredServers(await listRegisteredServersFromDatabase(client), listEnvironmentRegisteredServers());
|
|
68072
68150
|
const hasExplicitDefaultPrefix = process.env[SUPABASE_TABLE_PREFIX_ENV_NAME] !== undefined;
|
|
68073
68151
|
const configuredPrefixes = uniquePrefixes([
|
|
68074
68152
|
...(hasExplicitDefaultPrefix
|
|
@@ -68229,6 +68307,25 @@ function uniquePrefixes(prefixes) {
|
|
|
68229
68307
|
}
|
|
68230
68308
|
return result;
|
|
68231
68309
|
}
|
|
68310
|
+
/**
|
|
68311
|
+
* Combines database and environment registry rows, keeping database rows authoritative.
|
|
68312
|
+
*
|
|
68313
|
+
* @param databaseServers - Persistent `_Server` rows.
|
|
68314
|
+
* @param environmentServers - Virtual rows derived from `SERVERS`.
|
|
68315
|
+
* @returns Merged rows without duplicate domains.
|
|
68316
|
+
*/
|
|
68317
|
+
function mergeRegisteredServers(databaseServers, environmentServers) {
|
|
68318
|
+
const seenDomains = new Set(databaseServers.map((server) => server.domain));
|
|
68319
|
+
const mergedServers = [...databaseServers];
|
|
68320
|
+
for (const environmentServer of environmentServers) {
|
|
68321
|
+
if (seenDomains.has(environmentServer.domain)) {
|
|
68322
|
+
continue;
|
|
68323
|
+
}
|
|
68324
|
+
mergedServers.push(environmentServer);
|
|
68325
|
+
seenDomains.add(environmentServer.domain);
|
|
68326
|
+
}
|
|
68327
|
+
return mergedServers;
|
|
68328
|
+
}
|
|
68232
68329
|
/**
|
|
68233
68330
|
* Creates one PostgreSQL client using the lazily loaded `pg` package.
|
|
68234
68331
|
*
|