@zintrust/core 0.1.41 → 0.1.42
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/package.json +17 -1
- package/src/boot/bootstrap.js +27 -11
- package/src/boot/registry/runtime.d.ts.map +1 -1
- package/src/boot/registry/runtime.js +11 -0
- package/src/cli/CLI.d.ts.map +1 -1
- package/src/cli/CLI.js +12 -0
- package/src/cli/commands/ConfigCommand.d.ts.map +1 -1
- package/src/cli/commands/ConfigCommand.js +3 -5
- package/src/cli/commands/D1LearnCommand.d.ts +9 -0
- package/src/cli/commands/D1LearnCommand.d.ts.map +1 -0
- package/src/cli/commands/D1LearnCommand.js +143 -0
- package/src/cli/commands/D1MigrateCommand.d.ts.map +1 -1
- package/src/cli/commands/D1MigrateCommand.js +55 -16
- package/src/cli/commands/InitContainerCommand.d.ts.map +1 -1
- package/src/cli/commands/InitContainerCommand.js +21 -6
- package/src/cli/commands/InitEcosystemCommand.d.ts +6 -0
- package/src/cli/commands/InitEcosystemCommand.d.ts.map +1 -0
- package/src/cli/commands/InitEcosystemCommand.js +51 -0
- package/src/cli/commands/MigrateCommand.d.ts.map +1 -1
- package/src/cli/commands/MigrateCommand.js +78 -36
- package/src/cli/commands/MigrateWorkerCommand.d.ts.map +1 -1
- package/src/cli/commands/MigrateWorkerCommand.js +36 -2
- package/src/cli/commands/PutCommand.d.ts +6 -0
- package/src/cli/commands/PutCommand.d.ts.map +1 -0
- package/src/cli/commands/PutCommand.js +173 -0
- package/src/cli/commands/QueueRecoveryCommand.d.ts.map +1 -1
- package/src/cli/commands/QueueRecoveryCommand.js +113 -14
- package/src/cli/commands/ScheduleListCommand.d.ts +6 -0
- package/src/cli/commands/ScheduleListCommand.d.ts.map +1 -0
- package/src/cli/commands/ScheduleListCommand.js +62 -0
- package/src/cli/commands/ScheduleRunCommand.d.ts +6 -0
- package/src/cli/commands/ScheduleRunCommand.d.ts.map +1 -0
- package/src/cli/commands/ScheduleRunCommand.js +32 -0
- package/src/cli/commands/ScheduleStartCommand.d.ts +6 -0
- package/src/cli/commands/ScheduleStartCommand.d.ts.map +1 -0
- package/src/cli/commands/ScheduleStartCommand.js +40 -0
- package/src/cli/commands/SecretsCommand.d.ts.map +1 -1
- package/src/cli/commands/SecretsCommand.js +2 -2
- package/src/cli/commands/schedule/ScheduleCliSupport.d.ts +6 -0
- package/src/cli/commands/schedule/ScheduleCliSupport.d.ts.map +1 -0
- package/src/cli/commands/schedule/ScheduleCliSupport.js +55 -0
- package/src/cli/config/ConfigManager.d.ts.map +1 -1
- package/src/cli/config/ConfigManager.js +8 -1
- package/src/cli/d1/D1SqlMigrations.d.ts.map +1 -1
- package/src/cli/d1/D1SqlMigrations.js +11 -1
- package/src/cli/d1/WranglerConfig.d.ts.map +1 -1
- package/src/cli/d1/WranglerConfig.js +34 -2
- package/src/cli/services/VersionChecker.d.ts.map +1 -1
- package/src/cli/services/VersionChecker.js +5 -1
- package/src/cli/utils/DatabaseCliUtils.d.ts.map +1 -1
- package/src/cli/utils/DatabaseCliUtils.js +6 -1
- package/src/cli/utils/EnvFileLoader.d.ts.map +1 -1
- package/src/cli/utils/EnvFileLoader.js +33 -14
- package/src/cli.d.ts +5 -0
- package/src/cli.d.ts.map +1 -0
- package/src/cli.js +4 -0
- package/src/collections/index.d.ts +2 -2
- package/src/collections/index.d.ts.map +1 -1
- package/src/collections/index.js +1 -1
- package/src/common/RemoteSignedJson.d.ts.map +1 -1
- package/src/common/RemoteSignedJson.js +49 -23
- package/src/common/utility.d.ts.map +1 -1
- package/src/common/utility.js +2 -6
- package/src/config/cloudflare.d.ts.map +1 -1
- package/src/config/cloudflare.js +19 -8
- package/src/config/env.js +2 -2
- package/src/helper/index.d.ts +225 -0
- package/src/helper/index.d.ts.map +1 -0
- package/src/helper/index.js +347 -0
- package/src/index.d.ts +3 -6
- package/src/index.d.ts.map +1 -1
- package/src/index.js +7 -9
- package/src/migrations/MigrationDiscovery.d.ts.map +1 -1
- package/src/migrations/MigrationDiscovery.js +2 -1
- package/src/orm/DatabaseAdapter.d.ts +1 -0
- package/src/orm/DatabaseAdapter.d.ts.map +1 -1
- package/src/orm/SchemaStatemenWriter.d.ts +15 -0
- package/src/orm/SchemaStatemenWriter.d.ts.map +1 -0
- package/src/orm/SchemaStatemenWriter.js +78 -0
- package/src/orm/adapters/D1Adapter.d.ts.map +1 -1
- package/src/orm/adapters/D1Adapter.js +52 -2
- package/src/orm/adapters/D1RemoteAdapter.d.ts.map +1 -1
- package/src/orm/adapters/D1RemoteAdapter.js +137 -89
- package/src/orm/adapters/MySQLProxyAdapter.d.ts.map +1 -1
- package/src/orm/adapters/MySQLProxyAdapter.js +100 -81
- package/src/orm/adapters/PostgreSQLProxyAdapter.d.ts.map +1 -1
- package/src/orm/adapters/PostgreSQLProxyAdapter.js +26 -10
- package/src/orm/adapters/SqlProxyAdapterUtils.d.ts.map +1 -1
- package/src/orm/adapters/SqlProxyAdapterUtils.js +2 -1
- package/src/orm/adapters/SqlProxyRegistryMode.d.ts +12 -0
- package/src/orm/adapters/SqlProxyRegistryMode.d.ts.map +1 -0
- package/src/orm/adapters/SqlProxyRegistryMode.js +24 -0
- package/src/orm/adapters/SqlServerProxyAdapter.d.ts +3 -0
- package/src/orm/adapters/SqlServerProxyAdapter.d.ts.map +1 -1
- package/src/orm/adapters/SqlServerProxyAdapter.js +125 -117
- package/src/orm/migrations/MigrationStore.js +1 -1
- package/src/proxy/ProxyRequestParsing.d.ts +9 -0
- package/src/proxy/ProxyRequestParsing.d.ts.map +1 -0
- package/src/proxy/ProxyRequestParsing.js +16 -0
- package/src/proxy/RequestValidator.d.ts.map +1 -1
- package/src/proxy/RequestValidator.js +2 -1
- package/src/proxy/SigningService.js +2 -2
- package/src/proxy/SqlProxyDbOverrides.d.ts +17 -0
- package/src/proxy/SqlProxyDbOverrides.d.ts.map +1 -0
- package/src/proxy/SqlProxyDbOverrides.js +1 -0
- package/src/proxy/SqlProxyServerDeps.d.ts +12 -0
- package/src/proxy/SqlProxyServerDeps.d.ts.map +1 -0
- package/src/proxy/SqlProxyServerDeps.js +9 -0
- package/src/proxy/StatementPayloadValidator.d.ts +13 -0
- package/src/proxy/StatementPayloadValidator.d.ts.map +1 -0
- package/src/proxy/StatementPayloadValidator.js +18 -0
- package/src/proxy/StatementRegistryLoader.d.ts +2 -0
- package/src/proxy/StatementRegistryLoader.d.ts.map +1 -0
- package/src/proxy/StatementRegistryLoader.js +36 -0
- package/src/proxy/StatementRegistryResolver.d.ts +15 -0
- package/src/proxy/StatementRegistryResolver.d.ts.map +1 -0
- package/src/proxy/StatementRegistryResolver.js +34 -0
- package/src/proxy/d1/ZintrustD1Proxy.d.ts +2 -1
- package/src/proxy/d1/ZintrustD1Proxy.d.ts.map +1 -1
- package/src/proxy/d1/ZintrustD1Proxy.js +2 -1
- package/src/proxy/isMutatingSql.d.ts +2 -0
- package/src/proxy/isMutatingSql.d.ts.map +1 -0
- package/src/proxy/isMutatingSql.js +12 -0
- package/src/proxy/kv/ZintrustKvProxy.d.ts +2 -1
- package/src/proxy/kv/ZintrustKvProxy.d.ts.map +1 -1
- package/src/proxy/kv/ZintrustKvProxy.js +2 -1
- package/src/proxy/mysql/MySqlProxyServer.d.ts +2 -8
- package/src/proxy/mysql/MySqlProxyServer.d.ts.map +1 -1
- package/src/proxy/mysql/MySqlProxyServer.js +84 -51
- package/src/proxy/postgres/PostgresProxyServer.d.ts +2 -8
- package/src/proxy/postgres/PostgresProxyServer.d.ts.map +1 -1
- package/src/proxy/postgres/PostgresProxyServer.js +86 -48
- package/src/proxy/smtp/SmtpProxyServer.d.ts.map +1 -1
- package/src/proxy/smtp/SmtpProxyServer.js +6 -5
- package/src/proxy/sqlserver/SqlServerProxyServer.d.ts +2 -8
- package/src/proxy/sqlserver/SqlServerProxyServer.d.ts.map +1 -1
- package/src/proxy/sqlserver/SqlServerProxyServer.js +84 -49
- package/src/proxy.d.ts +4 -0
- package/src/proxy.d.ts.map +1 -0
- package/src/proxy.js +3 -0
- package/src/scheduler/Schedule.d.ts +36 -0
- package/src/scheduler/Schedule.d.ts.map +1 -0
- package/src/scheduler/Schedule.js +197 -0
- package/src/scheduler/ScheduleHttpGateway.d.ts +8 -0
- package/src/scheduler/ScheduleHttpGateway.d.ts.map +1 -0
- package/src/scheduler/ScheduleHttpGateway.js +196 -0
- package/src/scheduler/ScheduleRunner.d.ts +6 -0
- package/src/scheduler/ScheduleRunner.d.ts.map +1 -1
- package/src/scheduler/ScheduleRunner.js +166 -29
- package/src/scheduler/SchedulerRuntime.d.ts +15 -0
- package/src/scheduler/SchedulerRuntime.d.ts.map +1 -0
- package/src/scheduler/SchedulerRuntime.js +79 -0
- package/src/scheduler/cron/Cron.d.ts +19 -0
- package/src/scheduler/cron/Cron.d.ts.map +1 -0
- package/src/scheduler/cron/Cron.js +200 -0
- package/src/scheduler/leader/SchedulerLeader.d.ts +14 -0
- package/src/scheduler/leader/SchedulerLeader.d.ts.map +1 -0
- package/src/scheduler/leader/SchedulerLeader.js +187 -0
- package/src/scheduler/state/ScheduleStateStore.d.ts +27 -0
- package/src/scheduler/state/ScheduleStateStore.d.ts.map +1 -0
- package/src/scheduler/state/ScheduleStateStore.js +27 -0
- package/src/scheduler/types.d.ts +10 -0
- package/src/scheduler/types.d.ts.map +1 -1
- package/src/schedules/index.d.ts +1 -0
- package/src/schedules/index.d.ts.map +1 -1
- package/src/schedules/index.js +1 -0
- package/src/schedules/job-tracking-cleanup.d.ts +4 -0
- package/src/schedules/job-tracking-cleanup.d.ts.map +1 -0
- package/src/schedules/job-tracking-cleanup.js +116 -0
- package/src/schedules/log-cleanup.d.ts +1 -2
- package/src/schedules/log-cleanup.d.ts.map +1 -1
- package/src/schedules/log-cleanup.js +12 -15
- package/src/security/Sanitizer.d.ts.map +1 -1
- package/src/security/Sanitizer.js +1 -9
- package/src/security/SignedRequest.d.ts.map +1 -1
- package/src/security/SignedRequest.js +2 -2
- package/src/templates/docker/docker-compose.ecosystem.yml.tpl +301 -0
- package/src/templates/docker/docker-compose.schedules.yml.tpl +84 -0
- package/src/templates/project/basic/app/Schedules/index.ts.tpl +0 -0
- package/src/templates/project/basic/config/database.ts.tpl +1 -1
- package/src/toolkit/Secrets/Manifest.d.ts.map +1 -1
- package/src/toolkit/Secrets/Manifest.js +5 -7
- package/src/tools/mail/drivers/Smtp.d.ts.map +1 -1
- package/src/tools/mail/drivers/Smtp.js +7 -1
- package/src/tools/queue/JobReconciliationRunner.d.ts.map +1 -1
- package/src/tools/queue/JobReconciliationRunner.js +7 -39
- package/src/tools/queue/JobRecoveryDaemon.d.ts.map +1 -1
- package/src/tools/queue/JobRecoveryDaemon.js +116 -18
- package/src/tools/queue/JobStateTracker.d.ts +10 -1
- package/src/tools/queue/JobStateTracker.d.ts.map +1 -1
- package/src/tools/queue/JobStateTracker.js +24 -2
- package/src/tools/queue/JobStateTrackerDbPersistence.d.ts.map +1 -1
- package/src/tools/queue/JobStateTrackerDbPersistence.js +93 -2
|
@@ -5,8 +5,44 @@ import { Cloudflare } from '../../config/cloudflare.js';
|
|
|
5
5
|
import { FeatureFlags } from '../../config/features.js';
|
|
6
6
|
import { Logger } from '../../config/logger.js';
|
|
7
7
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
8
|
+
import { isObject } from '../../helper/index.js';
|
|
8
9
|
import { AdaptersEnum } from '../../migrations/enum/index.js';
|
|
9
10
|
import { QueryBuilder } from '../QueryBuilder.js';
|
|
11
|
+
const isRecord = (value) => isObject(value);
|
|
12
|
+
const toNumber = (value) => {
|
|
13
|
+
if (typeof value === 'number' && Number.isFinite(value))
|
|
14
|
+
return value;
|
|
15
|
+
return null;
|
|
16
|
+
};
|
|
17
|
+
const toInsertId = (value) => {
|
|
18
|
+
if (typeof value === 'number' || typeof value === 'string' || typeof value === 'bigint') {
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
};
|
|
23
|
+
const isMutatingSql = (sql) => {
|
|
24
|
+
const normalized = sql.trimStart().toLowerCase();
|
|
25
|
+
return (normalized.startsWith('insert') ||
|
|
26
|
+
normalized.startsWith('update') ||
|
|
27
|
+
normalized.startsWith('delete') ||
|
|
28
|
+
normalized.startsWith('create') ||
|
|
29
|
+
normalized.startsWith('drop') ||
|
|
30
|
+
normalized.startsWith('alter') ||
|
|
31
|
+
normalized.startsWith('replace'));
|
|
32
|
+
};
|
|
33
|
+
const extractMeta = (value) => {
|
|
34
|
+
if (!isRecord(value))
|
|
35
|
+
return { changes: 0 };
|
|
36
|
+
const changes = toNumber(value['changes']) ??
|
|
37
|
+
toNumber(value['rows_written']) ??
|
|
38
|
+
toNumber(value['rows_read']) ??
|
|
39
|
+
0;
|
|
40
|
+
const lastInsertId = toInsertId(value['lastRowId']) ??
|
|
41
|
+
toInsertId(value['last_row_id']) ??
|
|
42
|
+
toInsertId(value['lastInsertRowid']) ??
|
|
43
|
+
toInsertId(value['last_insert_rowid']);
|
|
44
|
+
return { changes, lastInsertId };
|
|
45
|
+
};
|
|
10
46
|
/**
|
|
11
47
|
* Get D1 binding from config or global environment
|
|
12
48
|
*/
|
|
@@ -43,11 +79,25 @@ export const D1Adapter = Object.freeze({
|
|
|
43
79
|
}
|
|
44
80
|
try {
|
|
45
81
|
const stmt = db.prepare(sql);
|
|
82
|
+
if (isMutatingSql(sql)) {
|
|
83
|
+
const runResult = await stmt.bind(...parameters).run();
|
|
84
|
+
const runRecord = runResult;
|
|
85
|
+
const meta = extractMeta(runRecord.meta);
|
|
86
|
+
return {
|
|
87
|
+
rows: [],
|
|
88
|
+
rowCount: meta.changes,
|
|
89
|
+
lastInsertId: meta.lastInsertId,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
46
92
|
const result = await stmt.bind(...parameters).all();
|
|
47
|
-
const
|
|
93
|
+
const rawResult = result;
|
|
94
|
+
const rows = rawResult.results ?? [];
|
|
95
|
+
const metaValue = rawResult.meta;
|
|
96
|
+
const meta = extractMeta(metaValue);
|
|
48
97
|
return {
|
|
49
98
|
rows,
|
|
50
|
-
rowCount: rows.length,
|
|
99
|
+
rowCount: rows.length > 0 ? rows.length : meta.changes,
|
|
100
|
+
lastInsertId: meta.lastInsertId,
|
|
51
101
|
};
|
|
52
102
|
}
|
|
53
103
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"D1RemoteAdapter.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/D1RemoteAdapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"D1RemoteAdapter.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/D1RemoteAdapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAe,MAAM,sBAAsB,CAAC;AA2T1F,eAAO,MAAM,eAAe;oBACV,cAAc,GAAG,gBAAgB;EAgBjD,CAAC;AAEH,eAAe,eAAe,CAAC"}
|
|
@@ -5,10 +5,15 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { RemoteSignedJson } from '../../common/RemoteSignedJson.js';
|
|
7
7
|
import { Env } from '../../config/env.js';
|
|
8
|
+
import { Logger } from '../../config/logger.js';
|
|
8
9
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
9
10
|
import { AdaptersEnum } from '../../migrations/enum/index.js';
|
|
11
|
+
import { isRecord } from '../adapters/SqlProxyAdapterUtils.js';
|
|
12
|
+
import { createStatementId } from '../adapters/SqlProxyRegistryMode.js';
|
|
10
13
|
import { QueryBuilder } from '../QueryBuilder.js';
|
|
11
|
-
import {
|
|
14
|
+
import { SchemaWriter } from '../SchemaStatemenWriter.js';
|
|
15
|
+
import { isMutatingSql } from '../../proxy/isMutatingSql.js';
|
|
16
|
+
let warnedFallbackCredentials = false;
|
|
12
17
|
const resolveSigningPrefix = (baseUrl) => {
|
|
13
18
|
try {
|
|
14
19
|
const parsed = new URL(baseUrl);
|
|
@@ -22,11 +27,25 @@ const resolveSigningPrefix = (baseUrl) => {
|
|
|
22
27
|
}
|
|
23
28
|
};
|
|
24
29
|
const createRemoteConfig = () => {
|
|
30
|
+
const directKeyId = Env.get('D1_REMOTE_KEY_ID', '').trim();
|
|
31
|
+
const directSecret = Env.get('D1_REMOTE_SECRET', '').trim();
|
|
32
|
+
// Intentionally pass empty values when missing so RemoteSignedJson's credential normalizer
|
|
33
|
+
// derives the fallback keyId/secret (APP_NAME/APP_KEY) in a consistent, safe way.
|
|
34
|
+
const keyId = directKeyId === '' ? '' : directKeyId;
|
|
35
|
+
const secret = directSecret === '' ? '' : directSecret;
|
|
36
|
+
if (directKeyId === '' || directSecret === '') {
|
|
37
|
+
if (!warnedFallbackCredentials) {
|
|
38
|
+
warnedFallbackCredentials = true;
|
|
39
|
+
Logger.warn('D1_REMOTE_KEY_ID / D1_REMOTE_SECRET missing; using fallback signing credentials (APP_NAME / APP_KEY).');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const envName = (Env.get('NODE_ENV', 'development') || 'development').trim().toLowerCase();
|
|
43
|
+
const defaultMode = envName === 'production' ? 'registry' : 'sql';
|
|
25
44
|
const settings = {
|
|
26
45
|
baseUrl: Env.get('D1_REMOTE_URL'),
|
|
27
|
-
keyId
|
|
28
|
-
secret
|
|
29
|
-
mode: Env.get('D1_REMOTE_MODE',
|
|
46
|
+
keyId,
|
|
47
|
+
secret,
|
|
48
|
+
mode: Env.get('D1_REMOTE_MODE', defaultMode) ?? defaultMode,
|
|
30
49
|
timeoutMs: Env.getInt('ZT_PROXY_TIMEOUT_MS', Env.REQUEST_TIMEOUT),
|
|
31
50
|
};
|
|
32
51
|
const remote = {
|
|
@@ -36,7 +55,7 @@ const createRemoteConfig = () => {
|
|
|
36
55
|
timeoutMs: settings.timeoutMs,
|
|
37
56
|
signaturePathPrefixToStrip: resolveSigningPrefix(settings.baseUrl),
|
|
38
57
|
missingUrlMessage: 'D1 remote proxy URL is missing (D1_REMOTE_URL)',
|
|
39
|
-
missingCredentialsMessage: 'D1 remote signing credentials are missing (D1_REMOTE_KEY_ID / D1_REMOTE_SECRET)',
|
|
58
|
+
missingCredentialsMessage: 'D1 remote signing credentials are missing (D1_REMOTE_KEY_ID / D1_REMOTE_SECRET). Fallbacks: APP_NAME and APP_KEY.',
|
|
40
59
|
messages: {
|
|
41
60
|
unauthorized: 'D1 remote proxy unauthorized',
|
|
42
61
|
forbidden: 'D1 remote proxy forbidden',
|
|
@@ -48,33 +67,33 @@ const createRemoteConfig = () => {
|
|
|
48
67
|
};
|
|
49
68
|
return { mode: settings.mode, remote };
|
|
50
69
|
};
|
|
51
|
-
const isMutatingSql = (sql) => {
|
|
52
|
-
const s = sql.trimStart().toLowerCase();
|
|
53
|
-
return (s.startsWith('insert') ||
|
|
54
|
-
s.startsWith('update') ||
|
|
55
|
-
s.startsWith('delete') ||
|
|
56
|
-
s.startsWith('create') ||
|
|
57
|
-
s.startsWith('drop') ||
|
|
58
|
-
s.startsWith('alter') ||
|
|
59
|
-
s.startsWith('replace'));
|
|
60
|
-
};
|
|
61
70
|
const createStatementPayload = async (sql, parameters) => {
|
|
62
|
-
const statementId = await
|
|
71
|
+
const statementId = await createStatementId(sql);
|
|
72
|
+
await SchemaWriter(sql);
|
|
63
73
|
return { statementId, params: parameters };
|
|
64
74
|
};
|
|
65
|
-
const isRecord = (value) => typeof value === 'object' && value !== null;
|
|
66
75
|
const isQueryResponse = (value) => isRecord(value) &&
|
|
67
76
|
Array.isArray(value['rows']) &&
|
|
68
77
|
typeof value['rowCount'] === 'number' &&
|
|
69
78
|
value['rows'].every((r) => isRecord(r));
|
|
70
79
|
const isQueryOneResponse = (value) => isRecord(value) && 'row' in value && (value['row'] === null || isRecord(value['row']));
|
|
71
|
-
const
|
|
80
|
+
const getExecMeta = (value) => {
|
|
72
81
|
if (!isRecord(value) || typeof value['ok'] !== 'boolean')
|
|
73
|
-
return 0;
|
|
82
|
+
return { changes: 0 };
|
|
74
83
|
const meta = value['meta'];
|
|
75
|
-
if (!isRecord(meta)
|
|
76
|
-
return 0;
|
|
77
|
-
|
|
84
|
+
if (!isRecord(meta))
|
|
85
|
+
return { changes: 0 };
|
|
86
|
+
const changes = typeof meta['changes'] === 'number' ? meta['changes'] : 0;
|
|
87
|
+
const lastRowIdCandidate = meta['lastRowId'] ??
|
|
88
|
+
meta['last_row_id'] ??
|
|
89
|
+
meta['lastInsertRowid'] ??
|
|
90
|
+
meta['last_insert_rowid'];
|
|
91
|
+
const lastRowId = typeof lastRowIdCandidate === 'number' ||
|
|
92
|
+
typeof lastRowIdCandidate === 'string' ||
|
|
93
|
+
typeof lastRowIdCandidate === 'bigint'
|
|
94
|
+
? lastRowIdCandidate
|
|
95
|
+
: undefined;
|
|
96
|
+
return { changes, lastRowId };
|
|
78
97
|
};
|
|
79
98
|
const queryRegistry = async (settings, sql, parameters) => {
|
|
80
99
|
const payload = await createStatementPayload(sql, parameters);
|
|
@@ -86,15 +105,18 @@ const queryRegistry = async (settings, sql, parameters) => {
|
|
|
86
105
|
const row = out.row;
|
|
87
106
|
return { rows: row ? [row] : [], rowCount: row ? 1 : 0 };
|
|
88
107
|
}
|
|
89
|
-
|
|
108
|
+
const meta = getExecMeta(out);
|
|
109
|
+
return { rows: [], rowCount: meta.changes, lastInsertId: meta.lastRowId };
|
|
90
110
|
};
|
|
91
111
|
const querySqlMode = async (settings, sql, parameters) => {
|
|
112
|
+
await SchemaWriter(sql);
|
|
92
113
|
if (isMutatingSql(sql)) {
|
|
93
114
|
const out = await RemoteSignedJson.request(settings, '/zin/d1/exec', {
|
|
94
115
|
sql,
|
|
95
116
|
params: parameters,
|
|
96
117
|
});
|
|
97
|
-
|
|
118
|
+
const meta = getExecMeta(out);
|
|
119
|
+
return { rows: [], rowCount: meta.changes, lastInsertId: meta.lastRowId };
|
|
98
120
|
}
|
|
99
121
|
const out = await RemoteSignedJson.request(settings, '/zin/d1/query', {
|
|
100
122
|
sql,
|
|
@@ -102,75 +124,101 @@ const querySqlMode = async (settings, sql, parameters) => {
|
|
|
102
124
|
});
|
|
103
125
|
return { rows: out.rows, rowCount: out.rowCount };
|
|
104
126
|
};
|
|
127
|
+
const requireConnected = (getConnected) => {
|
|
128
|
+
if (!getConnected())
|
|
129
|
+
throw ErrorFactory.createConnectionError('Database not connected');
|
|
130
|
+
};
|
|
131
|
+
const createConnectMethod = (setConnected) => async () => {
|
|
132
|
+
setConnected(true);
|
|
133
|
+
return Promise.resolve(); // NOSONAR
|
|
134
|
+
};
|
|
135
|
+
const createDisconnectMethod = (setConnected) => async () => {
|
|
136
|
+
setConnected(false);
|
|
137
|
+
return Promise.resolve(); // NOSONAR
|
|
138
|
+
};
|
|
139
|
+
const createQueryMethod = (getConnected, mode, remote) => async (sql, parameters) => {
|
|
140
|
+
requireConnected(getConnected);
|
|
141
|
+
if (mode === 'registry') {
|
|
142
|
+
return queryRegistry(remote, sql, parameters);
|
|
143
|
+
}
|
|
144
|
+
return querySqlMode(remote, sql, parameters);
|
|
145
|
+
};
|
|
146
|
+
const createQueryOneMethod = (getConnected, mode, remote) => async (sql, parameters) => {
|
|
147
|
+
requireConnected(getConnected);
|
|
148
|
+
if (mode === 'registry') {
|
|
149
|
+
const payload = await createStatementPayload(sql, parameters);
|
|
150
|
+
const out = await RemoteSignedJson.request(remote, '/zin/d1/statement', payload);
|
|
151
|
+
if (isQueryOneResponse(out))
|
|
152
|
+
return out.row;
|
|
153
|
+
if (isQueryResponse(out))
|
|
154
|
+
return out.rows[0] ?? null;
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
await SchemaWriter(sql);
|
|
158
|
+
const out = await RemoteSignedJson.request(remote, '/zin/d1/queryOne', {
|
|
159
|
+
sql,
|
|
160
|
+
params: parameters,
|
|
161
|
+
});
|
|
162
|
+
return out.row;
|
|
163
|
+
};
|
|
164
|
+
const createPingMethod = (getConnected, methods) => async () => {
|
|
165
|
+
requireConnected(getConnected);
|
|
166
|
+
const sql = QueryBuilder.create('').select('1').toSQL();
|
|
167
|
+
await methods.queryOne(sql, []);
|
|
168
|
+
};
|
|
169
|
+
const createTransactionMethod = (getConnected, methods) => async (callback) => {
|
|
170
|
+
requireConnected(getConnected);
|
|
171
|
+
try {
|
|
172
|
+
return await callback(methods);
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
throw ErrorFactory.createTryCatchError('Transaction failed', error);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
const createEnsureMigrationsTableMethod = (getConnected, methods) => async () => {
|
|
179
|
+
requireConnected(getConnected);
|
|
180
|
+
// D1 is SQLite under the hood; this schema matches the core migrator's expectations.
|
|
181
|
+
// Note: d1-remote migrations are expected to run in SQL mode (the CLI enforces this).
|
|
182
|
+
await methods.query(`CREATE TABLE IF NOT EXISTS migrations (
|
|
183
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
184
|
+
name TEXT NOT NULL,
|
|
185
|
+
scope TEXT NOT NULL DEFAULT 'global',
|
|
186
|
+
service TEXT NOT NULL DEFAULT '',
|
|
187
|
+
batch INTEGER NOT NULL,
|
|
188
|
+
status TEXT NOT NULL,
|
|
189
|
+
applied_at TEXT NULL,
|
|
190
|
+
created_at TEXT NOT NULL,
|
|
191
|
+
UNIQUE(name, scope, service)
|
|
192
|
+
)`, []);
|
|
193
|
+
};
|
|
194
|
+
const createRawQueryMethod = (methods) => async (sql, parameters = []) => {
|
|
195
|
+
const out = await methods.query(sql, parameters);
|
|
196
|
+
return out.rows;
|
|
197
|
+
};
|
|
198
|
+
const createAdapterMethods = (getConnected, setConnected, mode, remote) => {
|
|
199
|
+
const methods = {};
|
|
200
|
+
methods.connect = createConnectMethod(setConnected);
|
|
201
|
+
methods.disconnect = createDisconnectMethod(setConnected);
|
|
202
|
+
methods.query = createQueryMethod(getConnected, mode, remote);
|
|
203
|
+
methods.queryOne = createQueryOneMethod(getConnected, mode, remote);
|
|
204
|
+
methods.ping = createPingMethod(getConnected, methods);
|
|
205
|
+
methods.transaction = createTransactionMethod(getConnected, methods);
|
|
206
|
+
methods.ensureMigrationsTable = createEnsureMigrationsTableMethod(getConnected, methods);
|
|
207
|
+
methods.rawQuery = createRawQueryMethod(methods);
|
|
208
|
+
methods.getType = () => AdaptersEnum.d1Remote;
|
|
209
|
+
methods.isConnected = () => getConnected();
|
|
210
|
+
methods.getPlaceholder = (_index) => '?';
|
|
211
|
+
return methods;
|
|
212
|
+
};
|
|
213
|
+
const createAdapter = (getConnected, setConnected, mode, remote) => createAdapterMethods(getConnected, setConnected, mode, remote);
|
|
105
214
|
export const D1RemoteAdapter = Object.freeze({
|
|
106
215
|
create(_config) {
|
|
107
216
|
let connected = false;
|
|
108
217
|
const { mode, remote } = createRemoteConfig();
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
},
|
|
114
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
115
|
-
async disconnect() {
|
|
116
|
-
connected = false;
|
|
117
|
-
},
|
|
118
|
-
async query(sql, parameters) {
|
|
119
|
-
if (!connected)
|
|
120
|
-
throw ErrorFactory.createConnectionError('Database not connected');
|
|
121
|
-
if (mode === 'registry') {
|
|
122
|
-
return queryRegistry(remote, sql, parameters);
|
|
123
|
-
}
|
|
124
|
-
return querySqlMode(remote, sql, parameters);
|
|
125
|
-
},
|
|
126
|
-
async queryOne(sql, parameters) {
|
|
127
|
-
if (!connected)
|
|
128
|
-
throw ErrorFactory.createConnectionError('Database not connected');
|
|
129
|
-
if (mode === 'registry') {
|
|
130
|
-
const payload = await createStatementPayload(sql, parameters);
|
|
131
|
-
const out = await RemoteSignedJson.request(remote, '/zin/d1/statement', payload);
|
|
132
|
-
if (isQueryOneResponse(out))
|
|
133
|
-
return out.row;
|
|
134
|
-
if (isQueryResponse(out))
|
|
135
|
-
return out.rows[0] ?? null;
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
const out = await RemoteSignedJson.request(remote, '/zin/d1/queryOne', {
|
|
139
|
-
sql,
|
|
140
|
-
params: parameters,
|
|
141
|
-
});
|
|
142
|
-
return out.row;
|
|
143
|
-
},
|
|
144
|
-
async ping() {
|
|
145
|
-
if (!connected)
|
|
146
|
-
throw ErrorFactory.createConnectionError('Database not connected');
|
|
147
|
-
const sql = QueryBuilder.create('').select('1').toSQL();
|
|
148
|
-
await this.queryOne(sql, []);
|
|
149
|
-
},
|
|
150
|
-
async transaction(callback) {
|
|
151
|
-
if (!connected)
|
|
152
|
-
throw ErrorFactory.createConnectionError('Database not connected');
|
|
153
|
-
try {
|
|
154
|
-
return await callback(this);
|
|
155
|
-
}
|
|
156
|
-
catch (error) {
|
|
157
|
-
throw ErrorFactory.createTryCatchError('Transaction failed', error);
|
|
158
|
-
}
|
|
159
|
-
},
|
|
160
|
-
async rawQuery(sql, parameters = []) {
|
|
161
|
-
const out = await this.query(sql, parameters);
|
|
162
|
-
return out.rows;
|
|
163
|
-
},
|
|
164
|
-
getType() {
|
|
165
|
-
return AdaptersEnum.d1Remote;
|
|
166
|
-
},
|
|
167
|
-
isConnected() {
|
|
168
|
-
return connected;
|
|
169
|
-
},
|
|
170
|
-
getPlaceholder(_index) {
|
|
171
|
-
return '?';
|
|
172
|
-
},
|
|
173
|
-
};
|
|
218
|
+
const getConnected = () => connected;
|
|
219
|
+
return createAdapter(getConnected, (value) => {
|
|
220
|
+
connected = value;
|
|
221
|
+
}, mode, remote);
|
|
174
222
|
},
|
|
175
223
|
});
|
|
176
224
|
export default D1RemoteAdapter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MySQLProxyAdapter.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/MySQLProxyAdapter.ts"],"names":[],"mappings":"AACA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"MySQLProxyAdapter.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/MySQLProxyAdapter.ts"],"names":[],"mappings":"AACA;;;;GAIG;AAkBH,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAe,MAAM,sBAAsB,CAAC;AAiN1F,eAAO,MAAM,iBAAiB;oBACZ,cAAc,GAAG,gBAAgB;EAajD,CAAC;AAEH,eAAe,iBAAiB,CAAC"}
|
|
@@ -8,8 +8,9 @@ import { Env } from '../../config/env.js';
|
|
|
8
8
|
import { Logger } from '../../config/logger.js';
|
|
9
9
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
10
10
|
import { AdaptersEnum } from '../../migrations/enum/index.js';
|
|
11
|
-
import { QueryBuilder } from '../QueryBuilder.js';
|
|
12
11
|
import { ensureSignedSettings, isRecord, requestSignedProxy, } from '../adapters/SqlProxyAdapterUtils.js';
|
|
12
|
+
import { createStatementPayload, getExecMetaWithLastRowId, resolveSqlProxyMode, } from '../adapters/SqlProxyRegistryMode.js';
|
|
13
|
+
import { QueryBuilder } from '../QueryBuilder.js';
|
|
13
14
|
const buildProxySettings = () => {
|
|
14
15
|
const baseUrl = Env.MYSQL_PROXY_URL;
|
|
15
16
|
const keyId = Env.MYSQL_PROXY_KEY_ID ?? '';
|
|
@@ -32,16 +33,6 @@ const buildSignedProxyConfig = (settings) => ({
|
|
|
32
33
|
});
|
|
33
34
|
const isQueryResponse = (value) => isRecord(value) && Array.isArray(value['rows']) && typeof value['rowCount'] === 'number';
|
|
34
35
|
const isQueryOneResponse = (value) => isRecord(value) && 'row' in value;
|
|
35
|
-
const getExecMeta = (value) => {
|
|
36
|
-
if (!isRecord(value) || typeof value['ok'] !== 'boolean')
|
|
37
|
-
return { changes: 0 };
|
|
38
|
-
const meta = value['meta'];
|
|
39
|
-
if (!isRecord(meta))
|
|
40
|
-
return { changes: 0 };
|
|
41
|
-
const changes = typeof meta['changes'] === 'number' ? meta['changes'] : 0;
|
|
42
|
-
const lastRowId = meta['lastRowId'];
|
|
43
|
-
return { changes, lastRowId: lastRowId };
|
|
44
|
-
};
|
|
45
36
|
const requestProxy = async (settings, path, payload) => {
|
|
46
37
|
const signedProxyConfig = buildSignedProxyConfig(settings);
|
|
47
38
|
try {
|
|
@@ -59,85 +50,113 @@ const requestProxy = async (settings, path, payload) => {
|
|
|
59
50
|
throw error;
|
|
60
51
|
}
|
|
61
52
|
};
|
|
53
|
+
const resolveProxyMode = () => {
|
|
54
|
+
return resolveSqlProxyMode('MYSQL_PROXY_MODE');
|
|
55
|
+
};
|
|
56
|
+
const requireConnected = (state) => {
|
|
57
|
+
if (!state.connected)
|
|
58
|
+
throw ErrorFactory.createConnectionError('Database not connected');
|
|
59
|
+
};
|
|
60
|
+
const toQueryResult = (out) => {
|
|
61
|
+
if (isQueryResponse(out)) {
|
|
62
|
+
return {
|
|
63
|
+
rows: out.rows,
|
|
64
|
+
rowCount: out.rowCount,
|
|
65
|
+
lastInsertId: out.lastInsertId,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (isQueryOneResponse(out)) {
|
|
69
|
+
const row = out.row;
|
|
70
|
+
return { rows: row ? [row] : [], rowCount: row ? 1 : 0 };
|
|
71
|
+
}
|
|
72
|
+
const meta = getExecMetaWithLastRowId(out);
|
|
73
|
+
return { rows: [], rowCount: meta.changes, lastInsertId: meta.lastRowId };
|
|
74
|
+
};
|
|
75
|
+
const createQuery = (state) => async (sql, parameters) => {
|
|
76
|
+
requireConnected(state);
|
|
77
|
+
const mode = resolveProxyMode();
|
|
78
|
+
const out = mode === 'registry'
|
|
79
|
+
? await requestProxy(state.settings, '/zin/mysql/statement', await createStatementPayload(sql, parameters))
|
|
80
|
+
: await requestProxy(state.settings, '/zin/mysql/query', {
|
|
81
|
+
sql,
|
|
82
|
+
params: parameters,
|
|
83
|
+
});
|
|
84
|
+
return toQueryResult(out);
|
|
85
|
+
};
|
|
86
|
+
const createQueryOne = (state) => async (sql, parameters) => {
|
|
87
|
+
requireConnected(state);
|
|
88
|
+
const mode = resolveProxyMode();
|
|
89
|
+
if (mode !== 'registry') {
|
|
90
|
+
const out = await requestProxy(state.settings, '/zin/mysql/queryOne', {
|
|
91
|
+
sql,
|
|
92
|
+
params: parameters,
|
|
93
|
+
});
|
|
94
|
+
return out.row ?? null;
|
|
95
|
+
}
|
|
96
|
+
const out = await requestProxy(state.settings, '/zin/mysql/statement', await createStatementPayload(sql, parameters));
|
|
97
|
+
if (isQueryOneResponse(out))
|
|
98
|
+
return out.row ?? null;
|
|
99
|
+
if (isQueryResponse(out))
|
|
100
|
+
return out.rows[0] ?? null;
|
|
101
|
+
return null;
|
|
102
|
+
};
|
|
103
|
+
const createPing = (queryOne) => async () => {
|
|
104
|
+
await queryOne(QueryBuilder.create('').select('1').toSQL(), []);
|
|
105
|
+
};
|
|
106
|
+
const createTransaction = (state, getAdapter) => async (callback) => {
|
|
107
|
+
requireConnected(state);
|
|
108
|
+
try {
|
|
109
|
+
return await callback(getAdapter());
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
throw ErrorFactory.createTryCatchError('MySQL proxy transaction failed', error);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
const createRawQuery = (state, query) => async (sql, parameters = []) => {
|
|
116
|
+
requireConnected(state);
|
|
117
|
+
const out = await query(sql, parameters);
|
|
118
|
+
return out.rows;
|
|
119
|
+
};
|
|
120
|
+
const createAdapter = (state) => {
|
|
121
|
+
const query = createQuery(state);
|
|
122
|
+
const queryOne = createQueryOne(state);
|
|
123
|
+
const ping = createPing(queryOne);
|
|
124
|
+
const adapter = {
|
|
125
|
+
async connect() {
|
|
126
|
+
ensureSignedSettings(buildSignedProxyConfig(state.settings));
|
|
127
|
+
state.connected = true;
|
|
128
|
+
},
|
|
129
|
+
async disconnect() {
|
|
130
|
+
state.connected = false;
|
|
131
|
+
},
|
|
132
|
+
query,
|
|
133
|
+
queryOne,
|
|
134
|
+
ping,
|
|
135
|
+
transaction: createTransaction(state, () => adapter),
|
|
136
|
+
rawQuery: createRawQuery(state, query),
|
|
137
|
+
getType() {
|
|
138
|
+
return AdaptersEnum.mysql;
|
|
139
|
+
},
|
|
140
|
+
isConnected() {
|
|
141
|
+
return state.connected;
|
|
142
|
+
},
|
|
143
|
+
getPlaceholder(_index) {
|
|
144
|
+
return '?';
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
return adapter;
|
|
148
|
+
};
|
|
62
149
|
export const MySQLProxyAdapter = Object.freeze({
|
|
63
150
|
create(_config) {
|
|
64
|
-
let connected = false;
|
|
65
151
|
const settings = buildProxySettings();
|
|
152
|
+
const state = { connected: false, settings };
|
|
66
153
|
Logger.info('[MySQLProxyAdapter] Created with runtime settings', {
|
|
67
154
|
baseUrl: settings.baseUrl,
|
|
68
155
|
timeoutMs: settings.timeoutMs,
|
|
69
156
|
hasKeyId: (settings.keyId ?? '').trim() !== '',
|
|
70
157
|
hasSecret: (settings.secret ?? '').trim() !== '',
|
|
71
158
|
});
|
|
72
|
-
return
|
|
73
|
-
async connect() {
|
|
74
|
-
ensureSignedSettings(buildSignedProxyConfig(settings));
|
|
75
|
-
connected = true;
|
|
76
|
-
},
|
|
77
|
-
async disconnect() {
|
|
78
|
-
connected = false;
|
|
79
|
-
},
|
|
80
|
-
async query(sql, parameters) {
|
|
81
|
-
if (!connected)
|
|
82
|
-
throw ErrorFactory.createConnectionError('Database not connected');
|
|
83
|
-
const out = await requestProxy(settings, '/zin/mysql/query', {
|
|
84
|
-
sql,
|
|
85
|
-
params: parameters,
|
|
86
|
-
});
|
|
87
|
-
if (isQueryResponse(out)) {
|
|
88
|
-
return {
|
|
89
|
-
rows: out.rows,
|
|
90
|
-
rowCount: out.rowCount,
|
|
91
|
-
lastInsertId: out.lastInsertId,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
if (isQueryOneResponse(out)) {
|
|
95
|
-
const row = out.row;
|
|
96
|
-
return { rows: row ? [row] : [], rowCount: row ? 1 : 0 };
|
|
97
|
-
}
|
|
98
|
-
const meta = getExecMeta(out);
|
|
99
|
-
return { rows: [], rowCount: meta.changes, lastInsertId: meta.lastRowId };
|
|
100
|
-
},
|
|
101
|
-
async queryOne(sql, parameters) {
|
|
102
|
-
if (!connected)
|
|
103
|
-
throw ErrorFactory.createConnectionError('Database not connected');
|
|
104
|
-
const out = await requestProxy(settings, '/zin/mysql/queryOne', {
|
|
105
|
-
sql,
|
|
106
|
-
params: parameters,
|
|
107
|
-
});
|
|
108
|
-
return out.row ?? null;
|
|
109
|
-
},
|
|
110
|
-
async ping() {
|
|
111
|
-
if (!connected)
|
|
112
|
-
throw ErrorFactory.createConnectionError('Database not connected');
|
|
113
|
-
await this.queryOne(QueryBuilder.create('').select('1').toSQL(), []);
|
|
114
|
-
},
|
|
115
|
-
async transaction(callback) {
|
|
116
|
-
if (!connected)
|
|
117
|
-
throw ErrorFactory.createConnectionError('Database not connected');
|
|
118
|
-
try {
|
|
119
|
-
return await callback(this);
|
|
120
|
-
}
|
|
121
|
-
catch (error) {
|
|
122
|
-
throw ErrorFactory.createTryCatchError('MySQL proxy transaction failed', error);
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
async rawQuery(sql, parameters = []) {
|
|
126
|
-
if (!connected)
|
|
127
|
-
throw ErrorFactory.createConnectionError('Database not connected');
|
|
128
|
-
const out = await this.query(sql, parameters);
|
|
129
|
-
return out.rows;
|
|
130
|
-
},
|
|
131
|
-
getType() {
|
|
132
|
-
return AdaptersEnum.mysql;
|
|
133
|
-
},
|
|
134
|
-
isConnected() {
|
|
135
|
-
return connected;
|
|
136
|
-
},
|
|
137
|
-
getPlaceholder(_index) {
|
|
138
|
-
return '?';
|
|
139
|
-
},
|
|
140
|
-
};
|
|
159
|
+
return createAdapter(state);
|
|
141
160
|
},
|
|
142
161
|
});
|
|
143
162
|
export default MySQLProxyAdapter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PostgreSQLProxyAdapter.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/PostgreSQLProxyAdapter.ts"],"names":[],"mappings":"AACA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"PostgreSQLProxyAdapter.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/PostgreSQLProxyAdapter.ts"],"names":[],"mappings":"AACA;;;;GAIG;AAaH,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAe,MAAM,sBAAsB,CAAC;AAiH1F,eAAO,MAAM,sBAAsB;oBACjB,cAAc,GAAG,gBAAgB;EAwFjD,CAAC;AAEH,eAAe,sBAAsB,CAAC"}
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
import { Env } from '../../config/env.js';
|
|
8
8
|
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
|
|
9
9
|
import { AdaptersEnum } from '../../migrations/enum/index.js';
|
|
10
|
-
import { QueryBuilder } from '../QueryBuilder.js';
|
|
11
10
|
import { ensureSignedSettings, isRecord, requestSignedProxy, } from '../adapters/SqlProxyAdapterUtils.js';
|
|
11
|
+
import { createStatementPayload, resolveSqlProxyMode } from '../adapters/SqlProxyRegistryMode.js';
|
|
12
|
+
import { QueryBuilder } from '../QueryBuilder.js';
|
|
12
13
|
const resolveBaseUrl = () => {
|
|
13
14
|
const explicit = Env.POSTGRES_PROXY_URL.trim();
|
|
14
15
|
if (explicit !== '')
|
|
@@ -81,6 +82,9 @@ const toQueryResult = (out) => {
|
|
|
81
82
|
const requestProxy = async (settings, path, payload) => {
|
|
82
83
|
return requestSignedProxy(buildSignedProxyConfig(settings), path, payload);
|
|
83
84
|
};
|
|
85
|
+
const resolveProxyMode = () => {
|
|
86
|
+
return resolveSqlProxyMode('POSTGRES_PROXY_MODE');
|
|
87
|
+
};
|
|
84
88
|
export const PostgreSQLProxyAdapter = Object.freeze({
|
|
85
89
|
create(_config) {
|
|
86
90
|
let connected = true;
|
|
@@ -96,20 +100,32 @@ export const PostgreSQLProxyAdapter = Object.freeze({
|
|
|
96
100
|
async query(sql, parameters) {
|
|
97
101
|
if (!connected)
|
|
98
102
|
throw ErrorFactory.createConnectionError('Database not connected');
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
const mode = resolveProxyMode();
|
|
104
|
+
const out = mode === 'registry'
|
|
105
|
+
? await requestProxy(settings, '/zin/postgres/statement', await createStatementPayload(sql, parameters))
|
|
106
|
+
: await requestProxy(settings, '/zin/postgres/query', {
|
|
107
|
+
sql,
|
|
108
|
+
params: parameters,
|
|
109
|
+
});
|
|
103
110
|
return toQueryResult(out);
|
|
104
111
|
},
|
|
105
112
|
async queryOne(sql, parameters) {
|
|
106
113
|
if (!connected)
|
|
107
114
|
throw ErrorFactory.createConnectionError('Database not connected');
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
const mode = resolveProxyMode();
|
|
116
|
+
if (mode !== 'registry') {
|
|
117
|
+
const out = await requestProxy(settings, '/zin/postgres/queryOne', {
|
|
118
|
+
sql,
|
|
119
|
+
params: parameters,
|
|
120
|
+
});
|
|
121
|
+
return out.row ?? null;
|
|
122
|
+
}
|
|
123
|
+
const out = await requestProxy(settings, '/zin/postgres/statement', await createStatementPayload(sql, parameters));
|
|
124
|
+
if (isQueryOneResponse(out))
|
|
125
|
+
return out.row ?? null;
|
|
126
|
+
if (isQueryResponse(out))
|
|
127
|
+
return out.rows[0] ?? null;
|
|
128
|
+
return null;
|
|
113
129
|
},
|
|
114
130
|
async ping() {
|
|
115
131
|
if (!connected)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqlProxyAdapterUtils.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/SqlProxyAdapterUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"SqlProxyAdapterUtils.d.ts","sourceRoot":"","sources":["../../../../src/orm/adapters/SqlProxyAdapterUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAM3F,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,aAAa,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,yBAAyB,EAAE,MAAM,CAAC;IAClC,QAAQ,EAAE,wBAAwB,CAAC,UAAU,CAAC,CAAC;CAChD,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,QAAQ,iBAAiB,KAAG,wBAiB/D,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,iBAAiB,KAAG,wBAYhE,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAU,CAAC,EACxC,QAAQ,iBAAiB,EACzB,MAAM,MAAM,EACZ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC/B,OAAO,CAAC,CAAC,CAGX,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAoB,CAAC"}
|