taurusdb-core 0.3.0 → 0.4.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.
@@ -1,4 +1,4 @@
1
- const CREDENTIAL_URI_PREFIXES = ["aws-sm:", "hw-kms:", "uri:"];
1
+ const CREDENTIAL_URI_PREFIXES = ["aws-sm:", "hw-csms:", "hw-kms:", "hw-kms-file:", "uri:"];
2
2
  const SENSITIVE_KEY_PATTERN = /(password|secret|token|credential|apikey|api_key)/i;
3
3
  export function isObject(value) {
4
4
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -5,7 +5,6 @@ export declare class RuntimeOverrideProfileLoader implements RuntimeTargetProfil
5
5
  private readonly runtimeTargets;
6
6
  constructor(base: ProfileLoader);
7
7
  setRuntimeTarget(name: string, target: RuntimeDataSourceTarget): void;
8
- clearRuntimeUser(name: string): void;
9
8
  clearRuntimeTarget(name: string): void;
10
9
  clearAllRuntimeTargets(): void;
11
10
  getRuntimeTarget(name: string): RuntimeDataSourceTarget | undefined;
@@ -8,7 +8,6 @@ export function applyRuntimeTarget(profile, target) {
8
8
  host: target.host ?? profile.host,
9
9
  port: target.port ?? profile.port,
10
10
  database: target.database ?? profile.database,
11
- user: target.user ?? profile.user,
12
11
  });
13
12
  }
14
13
  export class RuntimeOverrideProfileLoader {
@@ -23,20 +22,11 @@ export class RuntimeOverrideProfileLoader {
23
22
  host: target.host ?? current?.host,
24
23
  port: target.port ?? current?.port,
25
24
  database: target.database ?? current?.database,
26
- user: target.user ?? current?.user,
27
25
  instanceId: target.instanceId ?? current?.instanceId,
28
26
  nodeId: target.nodeId ?? current?.nodeId,
29
27
  };
30
28
  this.runtimeTargets.set(name, next);
31
29
  }
32
- clearRuntimeUser(name) {
33
- const current = this.runtimeTargets.get(name);
34
- if (!current) {
35
- return;
36
- }
37
- const { user: _user, ...next } = current;
38
- this.runtimeTargets.set(name, next);
39
- }
40
30
  clearRuntimeTarget(name) {
41
31
  this.runtimeTargets.delete(name);
42
32
  }
@@ -45,13 +45,11 @@ export interface RuntimeDataSourceTarget {
45
45
  host?: string;
46
46
  port?: number;
47
47
  database?: string;
48
- user?: UserCredential;
49
48
  instanceId?: string;
50
49
  nodeId?: string;
51
50
  }
52
51
  export interface RuntimeTargetProfileLoader extends ProfileLoader {
53
52
  setRuntimeTarget(name: string, target: RuntimeDataSourceTarget): void;
54
- clearRuntimeUser(name: string): void;
55
53
  clearRuntimeTarget(name: string): void;
56
54
  clearAllRuntimeTargets(): void;
57
55
  getRuntimeTarget(name: string): RuntimeDataSourceTarget | undefined;
@@ -9,7 +9,14 @@ export interface HuaweiCloudAuthOptions {
9
9
  domainSuffix?: string;
10
10
  iamEndpoint?: string;
11
11
  language?: "en-us" | "zh-cn";
12
+ credentialProvider?: HuaweiCloudCredentialProvider;
12
13
  }
14
+ export interface HuaweiCloudCredentials {
15
+ accessKeyId: string;
16
+ secretAccessKey: string;
17
+ securityToken?: string;
18
+ }
19
+ export type HuaweiCloudCredentialProvider = () => Promise<HuaweiCloudCredentials>;
13
20
  export interface FetchHuaweiCloudOptions {
14
21
  url: string;
15
22
  method?: string;
@@ -1,4 +1,5 @@
1
1
  import { createHash, createHmac } from "node:crypto";
2
+ import { createSystemCredentialProvider } from "./keychain.js";
2
3
  function readString(value) {
3
4
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
4
5
  }
@@ -98,9 +99,21 @@ export async function fetchHuaweiCloud(options) {
98
99
  body: options.body,
99
100
  });
100
101
  }
101
- const { accessKeyId, secretAccessKey } = requireAksk(options.auth);
102
+ const providerCredentials = (!readString(options.auth.accessKeyId) ||
103
+ !readString(options.auth.secretAccessKey)) &&
104
+ options.auth.credentialProvider
105
+ ? await options.auth.credentialProvider()
106
+ : undefined;
107
+ const resolvedAuth = {
108
+ ...options.auth,
109
+ accessKeyId: readString(options.auth.accessKeyId) ?? providerCredentials?.accessKeyId,
110
+ secretAccessKey: readString(options.auth.secretAccessKey) ??
111
+ providerCredentials?.secretAccessKey,
112
+ securityToken: readString(options.auth.securityToken) ?? providerCredentials?.securityToken,
113
+ };
114
+ const { accessKeyId, secretAccessKey } = requireAksk(resolvedAuth);
102
115
  const sdkDate = formatSdkDate(new Date());
103
- const headerMap = buildHeaderMap(headers, url, sdkDate, readString(options.auth.securityToken));
116
+ const headerMap = buildHeaderMap(headers, url, sdkDate, readString(resolvedAuth.securityToken));
104
117
  headerMap.set("authorization", buildAuthorization(method, url, headerMap, body, accessKeyId, secretAccessKey));
105
118
  return fetchImpl(url, {
106
119
  method,
@@ -169,6 +182,12 @@ export async function resolveHuaweiCloudProjectId(auth, fetchImpl) {
169
182
  throw new Error(`Unable to resolve project id for region ${region}. Set TAURUSDB_CLOUD_PROJECT_ID explicitly or restrict the account to a single visible project in that region.`);
170
183
  }
171
184
  export function getHuaweiCloudAuthFromConfig(config) {
185
+ const credentialProvider = config.cloud?.keychainService
186
+ ? createSystemCredentialProvider({
187
+ service: config.cloud.keychainService,
188
+ account: config.cloud.keychainAccount,
189
+ })
190
+ : undefined;
172
191
  return {
173
192
  region: config.cloud?.region,
174
193
  projectId: config.cloud?.projectId,
@@ -179,10 +198,12 @@ export function getHuaweiCloudAuthFromConfig(config) {
179
198
  domainSuffix: config.cloud?.domainSuffix,
180
199
  iamEndpoint: config.cloud?.iamEndpoint,
181
200
  language: config.cloud?.language,
201
+ credentialProvider,
182
202
  };
183
203
  }
184
204
  export function hasHuaweiCloudCredentialAuth(config) {
185
- return canAuthenticateHuaweiCloudRequests(getHuaweiCloudAuthFromConfig(config));
205
+ return Boolean(config.cloud?.keychainService ||
206
+ canAuthenticateHuaweiCloudRequests(getHuaweiCloudAuthFromConfig(config)));
186
207
  }
187
208
  export function inferHuaweiCloudRegionFromEndpoint(endpoint) {
188
209
  const normalized = readString(endpoint);
@@ -0,0 +1,7 @@
1
+ import type { UriSecretResolver } from "../auth/secret-resolver.js";
2
+ import type { Config } from "../config/index.js";
3
+ export type HuaweiCsmsSecretResolverOptions = {
4
+ config: Config;
5
+ fetchImpl?: typeof fetch;
6
+ };
7
+ export declare function createHuaweiCsmsSecretResolver(options: HuaweiCsmsSecretResolverOptions): UriSecretResolver;
@@ -0,0 +1,60 @@
1
+ import { fetchHuaweiCloud, getHuaweiCloudAuthFromConfig, resolveHuaweiCloudProjectId, } from "./auth.js";
2
+ function readString(value) {
3
+ return typeof value === "string" && value.length > 0 ? value : undefined;
4
+ }
5
+ function readSecretName(uri) {
6
+ if (!uri.startsWith("hw-csms:")) {
7
+ throw new Error(`Unsupported Huawei CSMS credential reference: ${uri}`);
8
+ }
9
+ const secretName = decodeURIComponent(uri.slice("hw-csms:".length).trim());
10
+ if (!secretName) {
11
+ throw new Error("Huawei CSMS credential reference is missing a secret name.");
12
+ }
13
+ return secretName;
14
+ }
15
+ function parseSecretString(payload) {
16
+ const record = payload && typeof payload === "object" && !Array.isArray(payload)
17
+ ? payload
18
+ : {};
19
+ const version = record.version && typeof record.version === "object" && !Array.isArray(record.version)
20
+ ? record.version
21
+ : {};
22
+ const secretString = readString(version.secret_string);
23
+ if (!secretString) {
24
+ throw new Error("Huawei CSMS response did not include version.secret_string.");
25
+ }
26
+ return secretString;
27
+ }
28
+ export function createHuaweiCsmsSecretResolver(options) {
29
+ const auth = getHuaweiCloudAuthFromConfig(options.config);
30
+ const endpoint = options.config.cloud.csmsEndpoint?.replace(/\/+$/g, "");
31
+ const fetchImpl = options.fetchImpl ?? fetch;
32
+ return async (uri) => {
33
+ if (!endpoint) {
34
+ throw new Error("Huawei CSMS endpoint is not configured. Set TAURUSDB_CLOUD_REGION or TAURUSDB_CLOUD_CSMS_ENDPOINT.");
35
+ }
36
+ const [secretName, projectId] = await Promise.all([
37
+ Promise.resolve(readSecretName(uri)),
38
+ resolveHuaweiCloudProjectId(auth, fetchImpl),
39
+ ]);
40
+ if (!projectId) {
41
+ throw new Error("Huawei CSMS request could not resolve a project id. Set TAURUSDB_CLOUD_PROJECT_ID or configure region plus Huawei Cloud credentials.");
42
+ }
43
+ const response = await fetchHuaweiCloud({
44
+ url: `${endpoint}/v1/${encodeURIComponent(projectId)}/secrets/${encodeURIComponent(secretName)}/versions/latest`,
45
+ headers: { "content-type": "application/json" },
46
+ auth,
47
+ fetchImpl,
48
+ });
49
+ const payload = (await response.json().catch(() => ({})));
50
+ if (!response.ok) {
51
+ const record = payload && typeof payload === "object" && !Array.isArray(payload)
52
+ ? payload
53
+ : {};
54
+ const code = readString(record.error_code) ?? readString(record.code);
55
+ const message = readString(record.error_msg) ?? readString(record.message);
56
+ throw new Error(`Huawei CSMS request failed with status ${response.status}${code ? ` (${code})` : ""}${message ? `: ${message}` : ""}.`);
57
+ }
58
+ return parseSecretString(payload);
59
+ };
60
+ }
@@ -0,0 +1,28 @@
1
+ import type { HuaweiCloudCredentialProvider } from "./auth.js";
2
+ export type MacOsKeychainCredentialProviderOptions = {
3
+ service: string;
4
+ account?: string;
5
+ platform?: NodeJS.Platform;
6
+ readPassword?: (service: string, account: string) => Promise<string | undefined>;
7
+ };
8
+ export type LinuxSecretServiceCredentialProviderOptions = {
9
+ service: string;
10
+ account?: string;
11
+ platform?: NodeJS.Platform;
12
+ readPassword?: (service: string, account: string, key: string) => Promise<string | undefined>;
13
+ };
14
+ export type WindowsCredentialManagerProviderOptions = {
15
+ service: string;
16
+ account?: string;
17
+ platform?: NodeJS.Platform;
18
+ readPassword?: (service: string, account: string, key: string) => Promise<string | undefined>;
19
+ };
20
+ export type SystemCredentialProviderOptions = {
21
+ service: string;
22
+ account?: string;
23
+ platform?: NodeJS.Platform;
24
+ };
25
+ export declare function createMacOsKeychainCredentialProvider(options: MacOsKeychainCredentialProviderOptions): HuaweiCloudCredentialProvider;
26
+ export declare function createLinuxSecretServiceCredentialProvider(options: LinuxSecretServiceCredentialProviderOptions): HuaweiCloudCredentialProvider;
27
+ export declare function createWindowsCredentialManagerProvider(options: WindowsCredentialManagerProviderOptions): HuaweiCloudCredentialProvider;
28
+ export declare function createSystemCredentialProvider(options: SystemCredentialProviderOptions): HuaweiCloudCredentialProvider;
@@ -0,0 +1,200 @@
1
+ import { execFile } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ const execFileAsync = promisify(execFile);
4
+ async function readMacOsKeychainPassword(service, account) {
5
+ try {
6
+ const { stdout } = await execFileAsync("security", [
7
+ "find-generic-password",
8
+ "-s",
9
+ service,
10
+ "-a",
11
+ account,
12
+ "-w",
13
+ ]);
14
+ const value = stdout.replace(/\r?\n$/, "");
15
+ return value.length > 0 ? value : undefined;
16
+ }
17
+ catch (error) {
18
+ const code = error && typeof error === "object" && "code" in error
19
+ ? String(error.code)
20
+ : undefined;
21
+ if (code === "44") {
22
+ return undefined;
23
+ }
24
+ throw new Error(`Failed to read macOS Keychain item "${service}".`, {
25
+ cause: error,
26
+ });
27
+ }
28
+ }
29
+ async function readLinuxSecretServicePassword(service, account, key) {
30
+ try {
31
+ const { stdout } = await execFileAsync("secret-tool", [
32
+ "lookup",
33
+ "service",
34
+ service,
35
+ "account",
36
+ account,
37
+ "key",
38
+ key,
39
+ ]);
40
+ const value = stdout.replace(/\r?\n$/, "");
41
+ return value.length > 0 ? value : undefined;
42
+ }
43
+ catch (error) {
44
+ const code = error && typeof error === "object" && "code" in error
45
+ ? String(error.code)
46
+ : undefined;
47
+ if (code === "1") {
48
+ return undefined;
49
+ }
50
+ if (code === "ENOENT") {
51
+ throw new Error("Linux Secret Service requires the secret-tool command. Install libsecret-tools or the equivalent package.", { cause: error });
52
+ }
53
+ throw new Error(`Failed to read Linux Secret Service item "${service}".`, {
54
+ cause: error,
55
+ });
56
+ }
57
+ }
58
+ const WINDOWS_CREDENTIAL_READ_SCRIPT = `
59
+ Add-Type -TypeDefinition @'
60
+ using System;
61
+ using System.Runtime.InteropServices;
62
+ public static class TaurusCredentialManager {
63
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
64
+ public struct Credential {
65
+ public UInt32 Flags;
66
+ public UInt32 Type;
67
+ public string TargetName;
68
+ public string Comment;
69
+ public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
70
+ public UInt32 CredentialBlobSize;
71
+ public IntPtr CredentialBlob;
72
+ public UInt32 Persist;
73
+ public UInt32 AttributeCount;
74
+ public IntPtr Attributes;
75
+ public string TargetAlias;
76
+ public string UserName;
77
+ }
78
+ [DllImport("advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
79
+ public static extern bool CredRead(string target, UInt32 type, UInt32 flags, out IntPtr credential);
80
+ [DllImport("advapi32.dll", SetLastError = true)]
81
+ public static extern void CredFree(IntPtr buffer);
82
+ }
83
+ '@
84
+ $pointer = [IntPtr]::Zero
85
+ if (-not [TaurusCredentialManager]::CredRead($env:TAURUSDB_CREDENTIAL_TARGET, 1, 0, [ref]$pointer)) {
86
+ if ([Runtime.InteropServices.Marshal]::GetLastWin32Error() -eq 1168) { exit 0 }
87
+ throw "CredReadW failed."
88
+ }
89
+ try {
90
+ $credential = [Runtime.InteropServices.Marshal]::PtrToStructure($pointer, [type][TaurusCredentialManager+Credential])
91
+ if ($credential.CredentialBlobSize -gt 0) {
92
+ [Runtime.InteropServices.Marshal]::PtrToStringUni($credential.CredentialBlob, [int]($credential.CredentialBlobSize / 2))
93
+ }
94
+ } finally {
95
+ [TaurusCredentialManager]::CredFree($pointer)
96
+ }
97
+ `;
98
+ async function readWindowsCredentialManagerPassword(service, account, key) {
99
+ const target = `${service}/${account}/${key}`;
100
+ const encodedScript = Buffer.from(WINDOWS_CREDENTIAL_READ_SCRIPT, "utf16le").toString("base64");
101
+ try {
102
+ const { stdout } = await execFileAsync("powershell.exe", ["-NoLogo", "-NoProfile", "-NonInteractive", "-EncodedCommand", encodedScript], {
103
+ env: { ...process.env, TAURUSDB_CREDENTIAL_TARGET: target },
104
+ });
105
+ const value = stdout.replace(/\r?\n$/, "");
106
+ return value.length > 0 ? value : undefined;
107
+ }
108
+ catch (error) {
109
+ const code = error && typeof error === "object" && "code" in error
110
+ ? String(error.code)
111
+ : undefined;
112
+ if (code === "ENOENT") {
113
+ throw new Error("Windows Credential Manager requires Windows PowerShell.", {
114
+ cause: error,
115
+ });
116
+ }
117
+ throw new Error(`Failed to read Windows Credential Manager item "${target}".`, {
118
+ cause: error,
119
+ });
120
+ }
121
+ }
122
+ function createCachedCredentialProvider(readValues) {
123
+ let cached;
124
+ return async () => {
125
+ cached ??= readValues();
126
+ return cached;
127
+ };
128
+ }
129
+ export function createMacOsKeychainCredentialProvider(options) {
130
+ const platform = options.platform ?? process.platform;
131
+ const account = options.account ?? "default";
132
+ const readPassword = options.readPassword ?? readMacOsKeychainPassword;
133
+ return createCachedCredentialProvider(async () => {
134
+ if (platform !== "darwin") {
135
+ throw new Error("Huawei Cloud system Keychain credentials currently require macOS.");
136
+ }
137
+ const [accessKeyId, secretAccessKey, securityToken] = await Promise.all([
138
+ readPassword(`${options.service}/access-key-id`, account),
139
+ readPassword(`${options.service}/secret-access-key`, account),
140
+ readPassword(`${options.service}/security-token`, account),
141
+ ]);
142
+ if (!accessKeyId || !secretAccessKey) {
143
+ throw new Error(`Huawei Cloud credentials were not found in macOS Keychain service "${options.service}" for account "${account}".`);
144
+ }
145
+ return { accessKeyId, secretAccessKey, securityToken };
146
+ });
147
+ }
148
+ export function createLinuxSecretServiceCredentialProvider(options) {
149
+ const platform = options.platform ?? process.platform;
150
+ const account = options.account ?? "default";
151
+ const readPassword = options.readPassword ?? readLinuxSecretServicePassword;
152
+ return createCachedCredentialProvider(async () => {
153
+ if (platform !== "linux") {
154
+ throw new Error("Huawei Cloud Linux Secret Service credentials require Linux.");
155
+ }
156
+ const [accessKeyId, secretAccessKey, securityToken] = await Promise.all([
157
+ readPassword(options.service, account, "access-key-id"),
158
+ readPassword(options.service, account, "secret-access-key"),
159
+ readPassword(options.service, account, "security-token"),
160
+ ]);
161
+ if (!accessKeyId || !secretAccessKey) {
162
+ throw new Error(`Huawei Cloud credentials were not found in Linux Secret Service "${options.service}" for account "${account}".`);
163
+ }
164
+ return { accessKeyId, secretAccessKey, securityToken };
165
+ });
166
+ }
167
+ export function createWindowsCredentialManagerProvider(options) {
168
+ const platform = options.platform ?? process.platform;
169
+ const account = options.account ?? "default";
170
+ const readPassword = options.readPassword ?? readWindowsCredentialManagerPassword;
171
+ return createCachedCredentialProvider(async () => {
172
+ if (platform !== "win32") {
173
+ throw new Error("Huawei Cloud Windows Credential Manager credentials require Windows.");
174
+ }
175
+ const [accessKeyId, secretAccessKey, securityToken] = await Promise.all([
176
+ readPassword(options.service, account, "access-key-id"),
177
+ readPassword(options.service, account, "secret-access-key"),
178
+ readPassword(options.service, account, "security-token"),
179
+ ]);
180
+ if (!accessKeyId || !secretAccessKey) {
181
+ throw new Error(`Huawei Cloud credentials were not found in Windows Credential Manager service "${options.service}" for account "${account}".`);
182
+ }
183
+ return { accessKeyId, secretAccessKey, securityToken };
184
+ });
185
+ }
186
+ export function createSystemCredentialProvider(options) {
187
+ const platform = options.platform ?? process.platform;
188
+ if (platform === "darwin") {
189
+ return createMacOsKeychainCredentialProvider({ ...options, platform });
190
+ }
191
+ if (platform === "linux") {
192
+ return createLinuxSecretServiceCredentialProvider({ ...options, platform });
193
+ }
194
+ if (platform === "win32") {
195
+ return createWindowsCredentialManagerProvider({ ...options, platform });
196
+ }
197
+ return async () => {
198
+ throw new Error(`Huawei Cloud system credential storage is not supported on platform "${platform}".`);
199
+ };
200
+ }
@@ -0,0 +1,7 @@
1
+ import type { UriSecretResolver } from "../auth/secret-resolver.js";
2
+ import type { Config } from "../config/index.js";
3
+ export type HuaweiKmsSecretResolverOptions = {
4
+ config: Config;
5
+ fetchImpl?: typeof fetch;
6
+ };
7
+ export declare function createHuaweiKmsSecretResolver(options: HuaweiKmsSecretResolverOptions): UriSecretResolver;
@@ -0,0 +1,86 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { fetchHuaweiCloud, getHuaweiCloudAuthFromConfig, resolveHuaweiCloudProjectId, } from "./auth.js";
5
+ function readString(value) {
6
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
7
+ }
8
+ function resolveFilePath(rawPath) {
9
+ const decoded = decodeURIComponent(rawPath);
10
+ if (decoded === "~") {
11
+ return os.homedir();
12
+ }
13
+ if (decoded.startsWith("~/")) {
14
+ return path.join(os.homedir(), decoded.slice(2));
15
+ }
16
+ return path.isAbsolute(decoded) ? decoded : path.resolve(process.cwd(), decoded);
17
+ }
18
+ function requireValue(value, context) {
19
+ const normalized = value.trim();
20
+ if (!normalized) {
21
+ throw new Error(`${context} must not be empty.`);
22
+ }
23
+ return normalized;
24
+ }
25
+ async function readCipherText(uri) {
26
+ if (uri.startsWith("hw-kms-file:")) {
27
+ const rawPath = uri.slice("hw-kms-file:".length).trim();
28
+ if (!rawPath) {
29
+ throw new Error("Huawei KMS file credential reference is missing a path.");
30
+ }
31
+ return requireValue(await readFile(resolveFilePath(rawPath), "utf8"), "Huawei KMS ciphertext");
32
+ }
33
+ if (uri.startsWith("hw-kms:")) {
34
+ return requireValue(uri.slice("hw-kms:".length), "Huawei KMS ciphertext");
35
+ }
36
+ throw new Error(`Unsupported Huawei KMS credential reference: ${uri}`);
37
+ }
38
+ function parsePlainText(payload) {
39
+ const record = payload && typeof payload === "object" && !Array.isArray(payload)
40
+ ? payload
41
+ : {};
42
+ const plainTextBase64 = typeof record.plain_text_base64 === "string" ? record.plain_text_base64 : undefined;
43
+ if (plainTextBase64 !== undefined && plainTextBase64.length > 0) {
44
+ return Buffer.from(plainTextBase64, "base64").toString("utf8");
45
+ }
46
+ const plainText = typeof record.plain_text === "string" ? record.plain_text : undefined;
47
+ if (plainText !== undefined && plainText.length > 0) {
48
+ return plainText;
49
+ }
50
+ throw new Error("Huawei KMS decrypt response did not include plain_text or plain_text_base64.");
51
+ }
52
+ export function createHuaweiKmsSecretResolver(options) {
53
+ const auth = getHuaweiCloudAuthFromConfig(options.config);
54
+ const endpoint = options.config.cloud.kmsEndpoint?.replace(/\/+$/g, "");
55
+ const fetchImpl = options.fetchImpl ?? fetch;
56
+ return async (uri) => {
57
+ if (!endpoint) {
58
+ throw new Error("Huawei KMS endpoint is not configured. Set TAURUSDB_CLOUD_REGION or TAURUSDB_CLOUD_KMS_ENDPOINT.");
59
+ }
60
+ const [cipherText, projectId] = await Promise.all([
61
+ readCipherText(uri),
62
+ resolveHuaweiCloudProjectId(auth, fetchImpl),
63
+ ]);
64
+ if (!projectId) {
65
+ throw new Error("Huawei KMS decrypt could not resolve a project id. Set TAURUSDB_CLOUD_PROJECT_ID or configure region plus Huawei Cloud credentials.");
66
+ }
67
+ const response = await fetchHuaweiCloud({
68
+ url: `${endpoint}/v1.0/${projectId}/kms/decrypt-data`,
69
+ method: "POST",
70
+ headers: { "content-type": "application/json" },
71
+ body: JSON.stringify({ cipher_text: cipherText }),
72
+ auth,
73
+ fetchImpl,
74
+ });
75
+ const payload = (await response.json().catch(() => ({})));
76
+ if (!response.ok) {
77
+ const record = payload && typeof payload === "object" && !Array.isArray(payload)
78
+ ? payload
79
+ : {};
80
+ const code = readString(record.error_code) ?? readString(record.code);
81
+ const message = readString(record.error_msg) ?? readString(record.message);
82
+ throw new Error(`Huawei KMS decrypt failed with status ${response.status}${code ? ` (${code})` : ""}${message ? `: ${message}` : ""}.`);
83
+ }
84
+ return parsePlainText(payload);
85
+ };
86
+ }
@@ -130,8 +130,14 @@ export function buildRawConfigFromEnv(env) {
130
130
  accessKeyId: cloudAccessKeyId,
131
131
  secretAccessKey: cloudSecretAccessKey,
132
132
  securityToken: cloudSecurityToken,
133
+ keychainService: readString(env.TAURUSDB_CLOUD_KEYCHAIN_SERVICE),
134
+ keychainAccount: readString(env.TAURUSDB_CLOUD_KEYCHAIN_ACCOUNT),
133
135
  apiEndpoint: buildHuaweiCloudEndpoint("gaussdb", cloudRegion, cloudDomainSuffix),
134
136
  iamEndpoint: buildHuaweiCloudEndpoint("iam", cloudRegion, cloudDomainSuffix),
137
+ kmsEndpoint: readString(env.TAURUSDB_CLOUD_KMS_ENDPOINT) ??
138
+ buildHuaweiCloudEndpoint("kms", cloudRegion, cloudDomainSuffix),
139
+ csmsEndpoint: readString(env.TAURUSDB_CLOUD_CSMS_ENDPOINT) ??
140
+ buildHuaweiCloudEndpoint("csms", cloudRegion, cloudDomainSuffix),
135
141
  domainSuffix: cloudDomainSuffix,
136
142
  language: readString(env.TAURUSDB_CLOUD_LANGUAGE) ??
137
143
  readString(env.TAURUSDB_SLOW_SQL_SOURCE_TAURUS_API_LANGUAGE),
@@ -12,12 +12,17 @@ export declare const ConfigSchema: z.ZodObject<{
12
12
  accessKeyId: z.ZodOptional<z.ZodString>;
13
13
  secretAccessKey: z.ZodOptional<z.ZodString>;
14
14
  securityToken: z.ZodOptional<z.ZodString>;
15
+ keychainService: z.ZodOptional<z.ZodString>;
16
+ keychainAccount: z.ZodDefault<z.ZodString>;
15
17
  apiEndpoint: z.ZodOptional<z.ZodString>;
16
18
  iamEndpoint: z.ZodOptional<z.ZodString>;
19
+ kmsEndpoint: z.ZodOptional<z.ZodString>;
20
+ csmsEndpoint: z.ZodOptional<z.ZodString>;
17
21
  domainSuffix: z.ZodDefault<z.ZodString>;
18
22
  language: z.ZodDefault<z.ZodEnum<["en-us", "zh-cn"]>>;
19
23
  }, "strip", z.ZodTypeAny, {
20
24
  provider: "huaweicloud";
25
+ keychainAccount: string;
21
26
  domainSuffix: string;
22
27
  language: "en-us" | "zh-cn";
23
28
  region?: string | undefined;
@@ -28,8 +33,11 @@ export declare const ConfigSchema: z.ZodObject<{
28
33
  accessKeyId?: string | undefined;
29
34
  secretAccessKey?: string | undefined;
30
35
  securityToken?: string | undefined;
36
+ keychainService?: string | undefined;
31
37
  apiEndpoint?: string | undefined;
32
38
  iamEndpoint?: string | undefined;
39
+ kmsEndpoint?: string | undefined;
40
+ csmsEndpoint?: string | undefined;
33
41
  }, {
34
42
  provider?: "huaweicloud" | undefined;
35
43
  region?: string | undefined;
@@ -40,8 +48,12 @@ export declare const ConfigSchema: z.ZodObject<{
40
48
  accessKeyId?: string | undefined;
41
49
  secretAccessKey?: string | undefined;
42
50
  securityToken?: string | undefined;
51
+ keychainService?: string | undefined;
52
+ keychainAccount?: string | undefined;
43
53
  apiEndpoint?: string | undefined;
44
54
  iamEndpoint?: string | undefined;
55
+ kmsEndpoint?: string | undefined;
56
+ csmsEndpoint?: string | undefined;
45
57
  domainSuffix?: string | undefined;
46
58
  language?: "en-us" | "zh-cn" | undefined;
47
59
  }>>;
@@ -271,6 +283,7 @@ export declare const ConfigSchema: z.ZodObject<{
271
283
  }, "strip", z.ZodTypeAny, {
272
284
  cloud: {
273
285
  provider: "huaweicloud";
286
+ keychainAccount: string;
274
287
  domainSuffix: string;
275
288
  language: "en-us" | "zh-cn";
276
289
  region?: string | undefined;
@@ -281,8 +294,11 @@ export declare const ConfigSchema: z.ZodObject<{
281
294
  accessKeyId?: string | undefined;
282
295
  secretAccessKey?: string | undefined;
283
296
  securityToken?: string | undefined;
297
+ keychainService?: string | undefined;
284
298
  apiEndpoint?: string | undefined;
285
299
  iamEndpoint?: string | undefined;
300
+ kmsEndpoint?: string | undefined;
301
+ csmsEndpoint?: string | undefined;
286
302
  };
287
303
  limits: {
288
304
  maxRows: number;
@@ -352,8 +368,12 @@ export declare const ConfigSchema: z.ZodObject<{
352
368
  accessKeyId?: string | undefined;
353
369
  secretAccessKey?: string | undefined;
354
370
  securityToken?: string | undefined;
371
+ keychainService?: string | undefined;
372
+ keychainAccount?: string | undefined;
355
373
  apiEndpoint?: string | undefined;
356
374
  iamEndpoint?: string | undefined;
375
+ kmsEndpoint?: string | undefined;
376
+ csmsEndpoint?: string | undefined;
357
377
  domainSuffix?: string | undefined;
358
378
  language?: "en-us" | "zh-cn" | undefined;
359
379
  } | undefined;
@@ -24,8 +24,12 @@ const CloudSchema = z
24
24
  accessKeyId: z.string().min(1).optional(),
25
25
  secretAccessKey: z.string().min(1).optional(),
26
26
  securityToken: z.string().min(1).optional(),
27
+ keychainService: z.string().min(1).optional(),
28
+ keychainAccount: z.string().min(1).default("default"),
27
29
  apiEndpoint: z.string().min(1).optional(),
28
30
  iamEndpoint: z.string().min(1).optional(),
31
+ kmsEndpoint: z.string().min(1).optional(),
32
+ csmsEndpoint: z.string().min(1).optional(),
29
33
  domainSuffix: z.string().min(1).default("myhuaweicloud.com"),
30
34
  language: z.enum(["en-us", "zh-cn"]).default("zh-cn"),
31
35
  })
@@ -1,5 +1,6 @@
1
1
  import type { Config } from "../config/index.js";
2
2
  import type { SessionContext } from "../context/session-context.js";
3
+ import { type HuaweiCloudCredentialProvider } from "../cloud/auth.js";
3
4
  import type { DiagnosisWindow } from "./types.js";
4
5
  export type MetricAlias = "cpu_util" | "mem_util" | "connection_count" | "active_connection_count" | "connection_usage" | "qps" | "tps" | "slow_queries" | "storage_used_size" | "storage_write_delay" | "storage_read_delay" | "row_lock_time" | "row_lock_waits" | "long_trx_count" | "write_iops" | "read_iops" | "write_throughput" | "read_throughput" | "temp_tables_per_min";
5
6
  export interface MetricPoint {
@@ -31,6 +32,7 @@ type CesMetricsSourceOptions = {
31
32
  accessKeyId?: string;
32
33
  secretAccessKey?: string;
33
34
  securityToken?: string;
35
+ credentialProvider?: HuaweiCloudCredentialProvider;
34
36
  namespace: string;
35
37
  instanceDimension: string;
36
38
  nodeDimension: string;
@@ -49,6 +51,7 @@ export declare class CesMetricsSource implements MetricsSource {
49
51
  private readonly accessKeyId?;
50
52
  private readonly secretAccessKey?;
51
53
  private readonly securityToken?;
54
+ private readonly credentialProvider?;
52
55
  private readonly namespace;
53
56
  private readonly instanceDimension;
54
57
  private readonly nodeDimension;
@@ -1,4 +1,4 @@
1
- import { fetchHuaweiCloud } from "../cloud/auth.js";
1
+ import { fetchHuaweiCloud, getHuaweiCloudAuthFromConfig } from "../cloud/auth.js";
2
2
  const TAURUS_CES_METRICS = {
3
3
  cpu_util: "gaussdb_mysql001_cpu_util",
4
4
  mem_util: "gaussdb_mysql002_mem_util",
@@ -132,6 +132,7 @@ export class CesMetricsSource {
132
132
  accessKeyId;
133
133
  secretAccessKey;
134
134
  securityToken;
135
+ credentialProvider;
135
136
  namespace;
136
137
  instanceDimension;
137
138
  nodeDimension;
@@ -149,6 +150,7 @@ export class CesMetricsSource {
149
150
  this.accessKeyId = options.accessKeyId;
150
151
  this.secretAccessKey = options.secretAccessKey;
151
152
  this.securityToken = options.securityToken;
153
+ this.credentialProvider = options.credentialProvider;
152
154
  this.namespace = options.namespace;
153
155
  this.instanceDimension = options.instanceDimension;
154
156
  this.nodeDimension = options.nodeDimension;
@@ -228,6 +230,7 @@ export class CesMetricsSource {
228
230
  accessKeyId: this.accessKeyId,
229
231
  secretAccessKey: this.secretAccessKey,
230
232
  securityToken: this.securityToken,
233
+ credentialProvider: this.credentialProvider,
231
234
  },
232
235
  fetchImpl: (input, init) => this.fetchImpl(input, {
233
236
  ...init,
@@ -257,7 +260,8 @@ export function createMetricsSource(config) {
257
260
  !ces.projectId ||
258
261
  !ces.instanceId ||
259
262
  (!ces.authToken &&
260
- !(config.cloud?.accessKeyId && config.cloud?.secretAccessKey))) {
263
+ !(config.cloud?.accessKeyId && config.cloud?.secretAccessKey) &&
264
+ !config.cloud?.keychainService)) {
261
265
  return undefined;
262
266
  }
263
267
  return new CesMetricsSource({
@@ -269,6 +273,7 @@ export function createMetricsSource(config) {
269
273
  accessKeyId: config.cloud?.accessKeyId,
270
274
  secretAccessKey: config.cloud?.secretAccessKey,
271
275
  securityToken: config.cloud?.securityToken,
276
+ credentialProvider: getHuaweiCloudAuthFromConfig(config).credentialProvider,
272
277
  namespace: ces.namespace,
273
278
  instanceDimension: ces.instanceDimension,
274
279
  nodeDimension: ces.nodeDimension,
@@ -1,3 +1,4 @@
1
+ import { type HuaweiCloudCredentialProvider } from "../../cloud/auth.js";
1
2
  import type { SessionContext } from "../../context/session-context.js";
2
3
  import type { FindTopSlowSqlInput } from "../types.js";
3
4
  import type { ExternalSlowSqlSample, ResolveSlowSqlInput, SlowSqlSource } from "./types.js";
@@ -9,6 +10,7 @@ type DasSlowSqlSourceOptions = {
9
10
  accessKeyId?: string;
10
11
  secretAccessKey?: string;
11
12
  securityToken?: string;
13
+ credentialProvider?: HuaweiCloudCredentialProvider;
12
14
  datastoreType: "MySQL" | "TaurusDB";
13
15
  requestTimeoutMs: number;
14
16
  defaultLookbackMinutes: number;
@@ -24,6 +26,7 @@ export declare class DasSlowSqlSource implements SlowSqlSource {
24
26
  private readonly accessKeyId?;
25
27
  private readonly secretAccessKey?;
26
28
  private readonly securityToken?;
29
+ private readonly credentialProvider?;
27
30
  private readonly datastoreType;
28
31
  private readonly requestTimeoutMs;
29
32
  private readonly defaultLookbackMinutes;
@@ -9,6 +9,7 @@ export class DasSlowSqlSource {
9
9
  accessKeyId;
10
10
  secretAccessKey;
11
11
  securityToken;
12
+ credentialProvider;
12
13
  datastoreType;
13
14
  requestTimeoutMs;
14
15
  defaultLookbackMinutes;
@@ -23,6 +24,7 @@ export class DasSlowSqlSource {
23
24
  this.accessKeyId = options.accessKeyId;
24
25
  this.secretAccessKey = options.secretAccessKey;
25
26
  this.securityToken = options.securityToken;
27
+ this.credentialProvider = options.credentialProvider;
26
28
  this.datastoreType = options.datastoreType;
27
29
  this.requestTimeoutMs = options.requestTimeoutMs;
28
30
  this.defaultLookbackMinutes = options.defaultLookbackMinutes;
@@ -149,6 +151,7 @@ export class DasSlowSqlSource {
149
151
  accessKeyId: this.accessKeyId,
150
152
  secretAccessKey: this.secretAccessKey,
151
153
  securityToken: this.securityToken,
154
+ credentialProvider: this.credentialProvider,
152
155
  },
153
156
  fetchImpl: (input, init) => this.fetchImpl(input, {
154
157
  ...init,
@@ -1,3 +1,4 @@
1
+ import { getHuaweiCloudAuthFromConfig } from "../../cloud/auth.js";
1
2
  import { DasSlowSqlSource } from "./das-source.js";
2
3
  import { TaurusApiSlowSqlSource } from "./taurus-api-source.js";
3
4
  import { sortExternalSamples } from "./utils.js";
@@ -28,6 +29,7 @@ class CompositeSlowSqlSource {
28
29
  }
29
30
  }
30
31
  export function createSlowSqlSource(config) {
32
+ const credentialProvider = getHuaweiCloudAuthFromConfig(config).credentialProvider;
31
33
  const sources = [];
32
34
  const taurusApi = config.slowSqlSource?.taurusApi;
33
35
  if (taurusApi?.enabled &&
@@ -36,7 +38,8 @@ export function createSlowSqlSource(config) {
36
38
  taurusApi.instanceId &&
37
39
  taurusApi.nodeId &&
38
40
  (taurusApi.authToken ||
39
- (config.cloud?.accessKeyId && config.cloud?.secretAccessKey))) {
41
+ (config.cloud?.accessKeyId && config.cloud?.secretAccessKey) ||
42
+ config.cloud?.keychainService)) {
40
43
  sources.push(new TaurusApiSlowSqlSource({
41
44
  endpoint: taurusApi.endpoint,
42
45
  projectId: taurusApi.projectId,
@@ -46,6 +49,7 @@ export function createSlowSqlSource(config) {
46
49
  accessKeyId: config.cloud?.accessKeyId,
47
50
  secretAccessKey: config.cloud?.secretAccessKey,
48
51
  securityToken: config.cloud?.securityToken,
52
+ credentialProvider,
49
53
  language: taurusApi.language,
50
54
  requestTimeoutMs: taurusApi.requestTimeoutMs,
51
55
  defaultLookbackMinutes: taurusApi.defaultLookbackMinutes,
@@ -57,7 +61,9 @@ export function createSlowSqlSource(config) {
57
61
  das.endpoint &&
58
62
  das.projectId &&
59
63
  das.instanceId &&
60
- (das.authToken || (config.cloud?.accessKeyId && config.cloud?.secretAccessKey))) {
64
+ (das.authToken ||
65
+ (config.cloud?.accessKeyId && config.cloud?.secretAccessKey) ||
66
+ config.cloud?.keychainService)) {
61
67
  sources.push(new DasSlowSqlSource({
62
68
  endpoint: das.endpoint,
63
69
  projectId: das.projectId,
@@ -66,6 +72,7 @@ export function createSlowSqlSource(config) {
66
72
  accessKeyId: config.cloud?.accessKeyId,
67
73
  secretAccessKey: config.cloud?.secretAccessKey,
68
74
  securityToken: config.cloud?.securityToken,
75
+ credentialProvider,
69
76
  datastoreType: das.datastoreType,
70
77
  requestTimeoutMs: das.requestTimeoutMs,
71
78
  defaultLookbackMinutes: das.defaultLookbackMinutes,
@@ -1,3 +1,4 @@
1
+ import { type HuaweiCloudCredentialProvider } from "../../cloud/auth.js";
1
2
  import type { SessionContext } from "../../context/session-context.js";
2
3
  import type { FindTopSlowSqlInput } from "../types.js";
3
4
  import type { ExternalSlowSqlSample, ResolveSlowSqlInput, SlowSqlSource } from "./types.js";
@@ -10,6 +11,7 @@ type TaurusApiSlowSqlSourceOptions = {
10
11
  accessKeyId?: string;
11
12
  secretAccessKey?: string;
12
13
  securityToken?: string;
14
+ credentialProvider?: HuaweiCloudCredentialProvider;
13
15
  language: "en-us" | "zh-cn";
14
16
  requestTimeoutMs: number;
15
17
  defaultLookbackMinutes: number;
@@ -25,6 +27,7 @@ export declare class TaurusApiSlowSqlSource implements SlowSqlSource {
25
27
  private readonly accessKeyId?;
26
28
  private readonly secretAccessKey?;
27
29
  private readonly securityToken?;
30
+ private readonly credentialProvider?;
28
31
  private readonly language;
29
32
  private readonly requestTimeoutMs;
30
33
  private readonly defaultLookbackMinutes;
@@ -10,6 +10,7 @@ export class TaurusApiSlowSqlSource {
10
10
  accessKeyId;
11
11
  secretAccessKey;
12
12
  securityToken;
13
+ credentialProvider;
13
14
  language;
14
15
  requestTimeoutMs;
15
16
  defaultLookbackMinutes;
@@ -24,6 +25,7 @@ export class TaurusApiSlowSqlSource {
24
25
  this.accessKeyId = options.accessKeyId;
25
26
  this.secretAccessKey = options.secretAccessKey;
26
27
  this.securityToken = options.securityToken;
28
+ this.credentialProvider = options.credentialProvider;
27
29
  this.language = options.language;
28
30
  this.requestTimeoutMs = options.requestTimeoutMs;
29
31
  this.defaultLookbackMinutes = options.defaultLookbackMinutes;
@@ -128,6 +130,7 @@ export class TaurusApiSlowSqlSource {
128
130
  accessKeyId: this.accessKeyId,
129
131
  secretAccessKey: this.secretAccessKey,
130
132
  securityToken: this.securityToken,
133
+ credentialProvider: this.credentialProvider,
131
134
  },
132
135
  fetchImpl: (input, init) => this.fetchImpl(input, {
133
136
  ...init,
package/dist/engine.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import { createSqlProfileLoader, } from "./auth/sql-profile-loader.js";
2
2
  import { createSecretResolver, } from "./auth/secret-resolver.js";
3
+ import { createHuaweiKmsSecretResolver } from "./cloud/kms.js";
4
+ import { createHuaweiCsmsSecretResolver } from "./cloud/csms.js";
3
5
  import { createCapabilityProbe, } from "./capability/probe.js";
4
6
  import { getConfig } from "./config/index.js";
5
7
  import { createDatasourceResolver } from "./context/datasource-resolver.js";
@@ -56,7 +58,14 @@ export class TaurusDBEngine {
56
58
  static async create(options = {}) {
57
59
  const config = options.config ?? getConfig();
58
60
  const profileLoader = options.profileLoader ?? createSqlProfileLoader({ config });
59
- const secretResolver = options.secretResolver ?? createSecretResolver();
61
+ const secretResolver = options.secretResolver ??
62
+ createSecretResolver({
63
+ uriResolvers: {
64
+ "hw-csms": createHuaweiCsmsSecretResolver({ config }),
65
+ "hw-kms": createHuaweiKmsSecretResolver({ config }),
66
+ "hw-kms-file": createHuaweiKmsSecretResolver({ config }),
67
+ },
68
+ });
60
69
  const datasourceResolver = options.datasourceResolver ??
61
70
  createDatasourceResolver({
62
71
  config,
@@ -35,7 +35,7 @@ async function resolveTls(tls, secretResolver) {
35
35
  function selectCredential(profile, mode, _opts = {}) {
36
36
  void mode;
37
37
  if (!profile.user) {
38
- throw new ConnectionPoolError(`Datasource "${profile.name}" does not define SQL credentials. Call begin_sql_login and complete the secure local login form before executing SQL.`);
38
+ throw new ConnectionPoolError(`Datasource "${profile.name}" does not define SQL credentials. Configure a database username and password reference before executing SQL.`);
39
39
  }
40
40
  return profile.user;
41
41
  }
package/dist/index.d.ts CHANGED
@@ -27,7 +27,13 @@ export { logger, withTaskContext } from "./utils/logger.js";
27
27
  export { CloudTaurusInstanceClient, createCloudTaurusInstanceClient, } from "./cloud/instances.js";
28
28
  export type { CloudTaurusInstanceSummary, ListCloudTaurusInstancesInput, } from "./cloud/instances.js";
29
29
  export { canAuthenticateHuaweiCloudRequests, fetchHuaweiCloud, getHuaweiCloudAuthFromConfig, hasHuaweiCloudCredentialAuth, inferHuaweiCloudRegionFromEndpoint, resolveHuaweiCloudProjectId, } from "./cloud/auth.js";
30
- export type { HuaweiCloudAuthOptions } from "./cloud/auth.js";
30
+ export type { HuaweiCloudAuthOptions, HuaweiCloudCredentialProvider, HuaweiCloudCredentials, } from "./cloud/auth.js";
31
+ export { createLinuxSecretServiceCredentialProvider, createMacOsKeychainCredentialProvider, createSystemCredentialProvider, createWindowsCredentialManagerProvider, } from "./cloud/keychain.js";
32
+ export type { LinuxSecretServiceCredentialProviderOptions, MacOsKeychainCredentialProviderOptions, SystemCredentialProviderOptions, WindowsCredentialManagerProviderOptions, } from "./cloud/keychain.js";
33
+ export { createHuaweiKmsSecretResolver } from "./cloud/kms.js";
34
+ export type { HuaweiKmsSecretResolverOptions } from "./cloud/kms.js";
35
+ export { createHuaweiCsmsSecretResolver } from "./cloud/csms.js";
36
+ export type { HuaweiCsmsSecretResolverOptions } from "./cloud/csms.js";
31
37
  export { FlashbackNoViewError, formatTimestamp as formatFlashbackTimestamp, } from "./taurus/flashback.js";
32
38
  export type { FlashbackInput, FlashbackNoViewDetails, } from "./taurus/flashback.js";
33
39
  export { buildListRecycleBinSql, buildRestoreRecycleBinTableSql, RECYCLE_BIN_DATABASE, } from "./taurus/recycle-bin.js";
package/dist/index.js CHANGED
@@ -14,6 +14,9 @@ export { generateQueryId, generateTaskId } from "./utils/id.js";
14
14
  export { logger, withTaskContext } from "./utils/logger.js";
15
15
  export { CloudTaurusInstanceClient, createCloudTaurusInstanceClient, } from "./cloud/instances.js";
16
16
  export { canAuthenticateHuaweiCloudRequests, fetchHuaweiCloud, getHuaweiCloudAuthFromConfig, hasHuaweiCloudCredentialAuth, inferHuaweiCloudRegionFromEndpoint, resolveHuaweiCloudProjectId, } from "./cloud/auth.js";
17
+ export { createLinuxSecretServiceCredentialProvider, createMacOsKeychainCredentialProvider, createSystemCredentialProvider, createWindowsCredentialManagerProvider, } from "./cloud/keychain.js";
18
+ export { createHuaweiKmsSecretResolver } from "./cloud/kms.js";
19
+ export { createHuaweiCsmsSecretResolver } from "./cloud/csms.js";
17
20
  export { FlashbackNoViewError, formatTimestamp as formatFlashbackTimestamp, } from "./taurus/flashback.js";
18
21
  export { buildListRecycleBinSql, buildRestoreRecycleBinTableSql, RECYCLE_BIN_DATABASE, } from "./taurus/recycle-bin.js";
19
22
  export { createPlaceholderDiagnosticResult } from "./diagnostics/types.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taurusdb-core",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Shared TaurusDB data-plane engine for schema, SQL execution, guardrails, and diagnostics.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -32,7 +32,7 @@
32
32
  }
33
33
  },
34
34
  "scripts": {
35
- "build": "tsc -p tsconfig.json",
35
+ "build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json",
36
36
  "check": "tsc --noEmit -p tsconfig.json",
37
37
  "test": "node --test tests/*.test.mjs"
38
38
  },