@krutai/db-service 1.0.1

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/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # @krutai/db-service
2
+
3
+ TypeScript/JavaScript client for fetching database configuration from KrutAI DB service.
4
+
5
+ ## Database support
6
+
7
+ This package currently provides configuration for **PostgreSQL only**.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @krutai/db-service
13
+ ```
14
+
15
+ ## Quick start
16
+
17
+ ```ts
18
+ import { DbService } from '@krutai/db-service';
19
+
20
+ const client = new DbService({
21
+ apiKey: process.env.KRUTAI_API_KEY!,
22
+ serverUrl: 'http://localhost:8000', // optional
23
+ });
24
+
25
+ await client.initialize();
26
+
27
+ const config = await client.getDbConfig({
28
+ projectId: 'your-project-id',
29
+ dbName: 'your-db-name',
30
+ });
31
+
32
+ console.log(config.dbUrl); // postgres connection URL
33
+ ```
34
+
35
+ ## Environment variables
36
+
37
+ - `KRUTAI_API_KEY`: used automatically if `apiKey` is not passed in constructor.
38
+
39
+ ## API overview
40
+
41
+ - `new DbService(config)` creates a client instance.
42
+ - `initialize()` validates API key with the service (unless `validateOnInit: false`).
43
+ - `isInitialized()` returns whether client is initialized.
44
+ - `getDbConfig({ projectId, dbName })` returns `{ dbUrl }`.
45
+ - `dbService(config)` helper returns a `DbService` instance.
46
+
47
+ ## Configuration
48
+
49
+ `DbServiceConfig` fields:
50
+
51
+ - `apiKey` (string, required)
52
+ - `serverUrl` (string, optional, default: `http://localhost:8000`)
53
+ - `validateOnInit` (boolean, optional, default: `true`)
54
+
55
+ ## Errors
56
+
57
+ - Throws `DbServiceKeyValidationError` for invalid or rejected API keys.
58
+ - Throws `Error` for invalid request input or non-OK responses from DB service.
@@ -0,0 +1,37 @@
1
+ declare class DbServiceKeyValidationError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ interface DbServiceConfig {
5
+ apiKey: string;
6
+ serverUrl?: string;
7
+ validateOnInit?: boolean;
8
+ }
9
+ interface DbConfigRequest {
10
+ projectId: string;
11
+ dbName: string;
12
+ }
13
+ interface DbConfigResponse {
14
+ dbUrl: string;
15
+ }
16
+ declare const DEFAULT_SERVER_URL = "http://localhost:8000";
17
+ declare const DEFAULT_DB_MANAGE_PREFIX = "/db-manage";
18
+ declare function validateApiKeyFormat(apiKey?: string): void;
19
+ declare function validateApiKeyWithService(apiKey?: string, serverUrl?: string): Promise<boolean>;
20
+ declare class DbService {
21
+ private readonly apiKey;
22
+ private readonly serverUrl;
23
+ private readonly dbManagePrefix;
24
+ private readonly config;
25
+ private initialized;
26
+ constructor(config: DbServiceConfig);
27
+ initialize(): Promise<void>;
28
+ isInitialized(): boolean;
29
+ private assertInitialized;
30
+ private headers;
31
+ private url;
32
+ getDbConfig(request: DbConfigRequest): Promise<DbConfigResponse>;
33
+ }
34
+ declare function dbService(config: DbServiceConfig): DbService;
35
+ declare const VERSION = "0.1.0";
36
+
37
+ export { DEFAULT_DB_MANAGE_PREFIX, DEFAULT_SERVER_URL, type DbConfigRequest, type DbConfigResponse, DbService, type DbServiceConfig, DbServiceKeyValidationError, VERSION, dbService, validateApiKeyFormat, validateApiKeyWithService };
@@ -0,0 +1,37 @@
1
+ declare class DbServiceKeyValidationError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ interface DbServiceConfig {
5
+ apiKey: string;
6
+ serverUrl?: string;
7
+ validateOnInit?: boolean;
8
+ }
9
+ interface DbConfigRequest {
10
+ projectId: string;
11
+ dbName: string;
12
+ }
13
+ interface DbConfigResponse {
14
+ dbUrl: string;
15
+ }
16
+ declare const DEFAULT_SERVER_URL = "http://localhost:8000";
17
+ declare const DEFAULT_DB_MANAGE_PREFIX = "/db-manage";
18
+ declare function validateApiKeyFormat(apiKey?: string): void;
19
+ declare function validateApiKeyWithService(apiKey?: string, serverUrl?: string): Promise<boolean>;
20
+ declare class DbService {
21
+ private readonly apiKey;
22
+ private readonly serverUrl;
23
+ private readonly dbManagePrefix;
24
+ private readonly config;
25
+ private initialized;
26
+ constructor(config: DbServiceConfig);
27
+ initialize(): Promise<void>;
28
+ isInitialized(): boolean;
29
+ private assertInitialized;
30
+ private headers;
31
+ private url;
32
+ getDbConfig(request: DbConfigRequest): Promise<DbConfigResponse>;
33
+ }
34
+ declare function dbService(config: DbServiceConfig): DbService;
35
+ declare const VERSION = "0.1.0";
36
+
37
+ export { DEFAULT_DB_MANAGE_PREFIX, DEFAULT_SERVER_URL, type DbConfigRequest, type DbConfigResponse, DbService, type DbServiceConfig, DbServiceKeyValidationError, VERSION, dbService, validateApiKeyFormat, validateApiKeyWithService };
package/dist/index.js ADDED
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DEFAULT_DB_MANAGE_PREFIX: () => DEFAULT_DB_MANAGE_PREFIX,
24
+ DEFAULT_SERVER_URL: () => DEFAULT_SERVER_URL,
25
+ DbService: () => DbService,
26
+ DbServiceKeyValidationError: () => DbServiceKeyValidationError,
27
+ VERSION: () => VERSION,
28
+ dbService: () => dbService,
29
+ validateApiKeyFormat: () => validateApiKeyFormat,
30
+ validateApiKeyWithService: () => validateApiKeyWithService
31
+ });
32
+ module.exports = __toCommonJS(index_exports);
33
+ var DbServiceKeyValidationError = class extends Error {
34
+ constructor(message) {
35
+ super(message);
36
+ this.name = "DbServiceKeyValidationError";
37
+ }
38
+ };
39
+ var DEFAULT_SERVER_URL = "http://localhost:8000";
40
+ var DEFAULT_DB_MANAGE_PREFIX = "/db-manage";
41
+ function validateApiKeyFormat(apiKey) {
42
+ const key = apiKey || process.env.KRUTAI_API_KEY;
43
+ if (!key || typeof key !== "string") {
44
+ throw new DbServiceKeyValidationError("API key must be a non-empty string");
45
+ }
46
+ if (key.trim().length === 0) {
47
+ throw new DbServiceKeyValidationError("API key cannot be empty or whitespace");
48
+ }
49
+ }
50
+ async function validateApiKeyWithService(apiKey, serverUrl = DEFAULT_SERVER_URL) {
51
+ const key = apiKey || process.env.KRUTAI_API_KEY;
52
+ if (!key) {
53
+ throw new DbServiceKeyValidationError("API key is required");
54
+ }
55
+ validateApiKeyFormat(key);
56
+ try {
57
+ const url = `${serverUrl.replace(/\/$/, "")}/validate`;
58
+ const response = await fetch(url, {
59
+ method: "POST",
60
+ headers: {
61
+ "Content-Type": "application/json",
62
+ "x-api-key": key
63
+ },
64
+ body: JSON.stringify({ apiKey: key })
65
+ });
66
+ let data = {};
67
+ try {
68
+ data = await response.json();
69
+ } catch {
70
+ }
71
+ if (!response.ok) {
72
+ throw new DbServiceKeyValidationError(
73
+ data.error || data.message || `API key validation failed: server responded with HTTP ${response.status}`
74
+ );
75
+ }
76
+ if (data.valid === false) {
77
+ throw new DbServiceKeyValidationError(
78
+ data.error ?? data.message ?? "API key rejected by server"
79
+ );
80
+ }
81
+ return true;
82
+ } catch (error) {
83
+ if (error instanceof DbServiceKeyValidationError) throw error;
84
+ throw new DbServiceKeyValidationError(
85
+ `Failed to reach validation endpoint: ${error instanceof Error ? error.message : "Unknown error"}`
86
+ );
87
+ }
88
+ }
89
+ var DbService = class {
90
+ apiKey;
91
+ serverUrl;
92
+ dbManagePrefix;
93
+ config;
94
+ initialized = false;
95
+ constructor(config) {
96
+ this.config = config;
97
+ this.apiKey = config.apiKey || process.env.KRUTAI_API_KEY || "";
98
+ this.serverUrl = (config.serverUrl ?? DEFAULT_SERVER_URL).replace(/\/$/, "");
99
+ this.dbManagePrefix = DEFAULT_DB_MANAGE_PREFIX.replace(/\/$/, "");
100
+ validateApiKeyFormat(this.apiKey);
101
+ if (config.validateOnInit === false) {
102
+ this.initialized = true;
103
+ }
104
+ }
105
+ async initialize() {
106
+ if (this.initialized) return;
107
+ if (this.config.validateOnInit !== false) {
108
+ await validateApiKeyWithService(this.apiKey, this.serverUrl);
109
+ }
110
+ this.initialized = true;
111
+ }
112
+ isInitialized() {
113
+ return this.initialized;
114
+ }
115
+ assertInitialized() {
116
+ if (!this.initialized) {
117
+ throw new Error(
118
+ "DbService not initialized. Call initialize() first or set validateOnInit to false."
119
+ );
120
+ }
121
+ }
122
+ headers() {
123
+ return {
124
+ "Content-Type": "application/json",
125
+ Authorization: `Bearer ${this.apiKey}`,
126
+ "x-api-key": this.apiKey
127
+ };
128
+ }
129
+ url(path) {
130
+ const cleanPath = path.startsWith("/") ? path : `/${path}`;
131
+ return `${this.serverUrl}${this.dbManagePrefix}${cleanPath}`;
132
+ }
133
+ async getDbConfig(request) {
134
+ this.assertInitialized();
135
+ if (!request.projectId || request.projectId.trim().length === 0) {
136
+ throw new Error("projectId is required");
137
+ }
138
+ if (!request.dbName || request.dbName.trim().length === 0) {
139
+ throw new Error("dbName is required");
140
+ }
141
+ const response = await fetch(this.url("/config"), {
142
+ method: "POST",
143
+ headers: this.headers(),
144
+ body: JSON.stringify({
145
+ projectId: request.projectId,
146
+ dbName: request.dbName
147
+ })
148
+ });
149
+ if (!response.ok) {
150
+ let message = `DB service returned HTTP ${response.status} for /config`;
151
+ try {
152
+ const errorData = await response.json();
153
+ message = errorData.error ?? errorData.message ?? message;
154
+ } catch {
155
+ }
156
+ throw new Error(message);
157
+ }
158
+ return await response.json();
159
+ }
160
+ };
161
+ function dbService(config) {
162
+ return new DbService(config);
163
+ }
164
+ var VERSION = "0.1.0";
165
+ // Annotate the CommonJS export names for ESM import in node:
166
+ 0 && (module.exports = {
167
+ DEFAULT_DB_MANAGE_PREFIX,
168
+ DEFAULT_SERVER_URL,
169
+ DbService,
170
+ DbServiceKeyValidationError,
171
+ VERSION,
172
+ dbService,
173
+ validateApiKeyFormat,
174
+ validateApiKeyWithService
175
+ });
176
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export class DbServiceKeyValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'DbServiceKeyValidationError';\n }\n}\n\nexport interface DbServiceConfig {\n apiKey: string;\n serverUrl?: string;\n validateOnInit?: boolean;\n}\n\nexport interface DbConfigRequest {\n projectId: string;\n dbName: string;\n}\n\nexport interface DbConfigResponse {\n dbUrl: string;\n}\n\nexport const DEFAULT_SERVER_URL = 'http://localhost:8000';\nexport const DEFAULT_DB_MANAGE_PREFIX = '/db-manage';\n\nexport function validateApiKeyFormat(apiKey?: string): void {\n const key = apiKey || process.env.KRUTAI_API_KEY;\n\n if (!key || typeof key !== 'string') {\n throw new DbServiceKeyValidationError('API key must be a non-empty string');\n }\n\n if (key.trim().length === 0) {\n throw new DbServiceKeyValidationError('API key cannot be empty or whitespace');\n }\n}\n\nexport async function validateApiKeyWithService(\n apiKey?: string,\n serverUrl: string = DEFAULT_SERVER_URL\n): Promise<boolean> {\n const key = apiKey || process.env.KRUTAI_API_KEY;\n if (!key) {\n throw new DbServiceKeyValidationError('API key is required');\n }\n\n validateApiKeyFormat(key);\n\n try {\n const url = `${serverUrl.replace(/\\/$/, '')}/validate`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': key,\n },\n body: JSON.stringify({ apiKey: key }),\n });\n\n let data: { valid?: boolean; message?: string; error?: string } = {};\n try {\n data = (await response.json()) as {\n valid?: boolean;\n message?: string;\n error?: string;\n };\n } catch {\n // Ignore parsing errors for non-JSON responses\n }\n\n if (!response.ok) {\n throw new DbServiceKeyValidationError(\n data.error ||\n data.message ||\n `API key validation failed: server responded with HTTP ${response.status}`\n );\n }\n\n if (data.valid === false) {\n throw new DbServiceKeyValidationError(\n data.error ?? data.message ?? 'API key rejected by server'\n );\n }\n\n return true;\n } catch (error) {\n if (error instanceof DbServiceKeyValidationError) throw error;\n throw new DbServiceKeyValidationError(\n `Failed to reach validation endpoint: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n}\n\nexport class DbService {\n private readonly apiKey: string;\n private readonly serverUrl: string;\n private readonly dbManagePrefix: string;\n private readonly config: DbServiceConfig;\n private initialized = false;\n\n constructor(config: DbServiceConfig) {\n this.config = config;\n this.apiKey = config.apiKey || process.env.KRUTAI_API_KEY || '';\n this.serverUrl = (config.serverUrl ?? DEFAULT_SERVER_URL).replace(/\\/$/, '');\n this.dbManagePrefix = DEFAULT_DB_MANAGE_PREFIX.replace(/\\/$/, '');\n\n validateApiKeyFormat(this.apiKey);\n\n if (config.validateOnInit === false) {\n this.initialized = true;\n }\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) return;\n\n if (this.config.validateOnInit !== false) {\n await validateApiKeyWithService(this.apiKey, this.serverUrl);\n }\n\n this.initialized = true;\n }\n\n isInitialized(): boolean {\n return this.initialized;\n }\n\n private assertInitialized(): void {\n if (!this.initialized) {\n throw new Error(\n 'DbService not initialized. Call initialize() first or set validateOnInit to false.'\n );\n }\n }\n\n private headers(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n 'x-api-key': this.apiKey,\n };\n }\n\n private url(path: string): string {\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return `${this.serverUrl}${this.dbManagePrefix}${cleanPath}`;\n }\n\n async getDbConfig(request: DbConfigRequest): Promise<DbConfigResponse> {\n this.assertInitialized();\n\n if (!request.projectId || request.projectId.trim().length === 0) {\n throw new Error('projectId is required');\n }\n\n if (!request.dbName || request.dbName.trim().length === 0) {\n throw new Error('dbName is required');\n }\n\n const response = await fetch(this.url('/config'), {\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify({\n projectId: request.projectId,\n dbName: request.dbName,\n }),\n });\n\n if (!response.ok) {\n let message = `DB service returned HTTP ${response.status} for /config`;\n try {\n const errorData = (await response.json()) as {\n message?: string;\n error?: string;\n };\n message = errorData.error ?? errorData.message ?? message;\n } catch {\n // ignore malformed error payloads\n }\n throw new Error(message);\n }\n\n return (await response.json()) as DbConfigResponse;\n }\n}\n\nexport function dbService(config: DbServiceConfig): DbService {\n return new DbService(config);\n}\n\nexport const VERSION = '0.1.0';\n"],"mappings":"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","names":[]}
package/dist/index.mjs ADDED
@@ -0,0 +1,144 @@
1
+ // src/index.ts
2
+ var DbServiceKeyValidationError = class extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = "DbServiceKeyValidationError";
6
+ }
7
+ };
8
+ var DEFAULT_SERVER_URL = "http://localhost:8000";
9
+ var DEFAULT_DB_MANAGE_PREFIX = "/db-manage";
10
+ function validateApiKeyFormat(apiKey) {
11
+ const key = apiKey || process.env.KRUTAI_API_KEY;
12
+ if (!key || typeof key !== "string") {
13
+ throw new DbServiceKeyValidationError("API key must be a non-empty string");
14
+ }
15
+ if (key.trim().length === 0) {
16
+ throw new DbServiceKeyValidationError("API key cannot be empty or whitespace");
17
+ }
18
+ }
19
+ async function validateApiKeyWithService(apiKey, serverUrl = DEFAULT_SERVER_URL) {
20
+ const key = apiKey || process.env.KRUTAI_API_KEY;
21
+ if (!key) {
22
+ throw new DbServiceKeyValidationError("API key is required");
23
+ }
24
+ validateApiKeyFormat(key);
25
+ try {
26
+ const url = `${serverUrl.replace(/\/$/, "")}/validate`;
27
+ const response = await fetch(url, {
28
+ method: "POST",
29
+ headers: {
30
+ "Content-Type": "application/json",
31
+ "x-api-key": key
32
+ },
33
+ body: JSON.stringify({ apiKey: key })
34
+ });
35
+ let data = {};
36
+ try {
37
+ data = await response.json();
38
+ } catch {
39
+ }
40
+ if (!response.ok) {
41
+ throw new DbServiceKeyValidationError(
42
+ data.error || data.message || `API key validation failed: server responded with HTTP ${response.status}`
43
+ );
44
+ }
45
+ if (data.valid === false) {
46
+ throw new DbServiceKeyValidationError(
47
+ data.error ?? data.message ?? "API key rejected by server"
48
+ );
49
+ }
50
+ return true;
51
+ } catch (error) {
52
+ if (error instanceof DbServiceKeyValidationError) throw error;
53
+ throw new DbServiceKeyValidationError(
54
+ `Failed to reach validation endpoint: ${error instanceof Error ? error.message : "Unknown error"}`
55
+ );
56
+ }
57
+ }
58
+ var DbService = class {
59
+ apiKey;
60
+ serverUrl;
61
+ dbManagePrefix;
62
+ config;
63
+ initialized = false;
64
+ constructor(config) {
65
+ this.config = config;
66
+ this.apiKey = config.apiKey || process.env.KRUTAI_API_KEY || "";
67
+ this.serverUrl = (config.serverUrl ?? DEFAULT_SERVER_URL).replace(/\/$/, "");
68
+ this.dbManagePrefix = DEFAULT_DB_MANAGE_PREFIX.replace(/\/$/, "");
69
+ validateApiKeyFormat(this.apiKey);
70
+ if (config.validateOnInit === false) {
71
+ this.initialized = true;
72
+ }
73
+ }
74
+ async initialize() {
75
+ if (this.initialized) return;
76
+ if (this.config.validateOnInit !== false) {
77
+ await validateApiKeyWithService(this.apiKey, this.serverUrl);
78
+ }
79
+ this.initialized = true;
80
+ }
81
+ isInitialized() {
82
+ return this.initialized;
83
+ }
84
+ assertInitialized() {
85
+ if (!this.initialized) {
86
+ throw new Error(
87
+ "DbService not initialized. Call initialize() first or set validateOnInit to false."
88
+ );
89
+ }
90
+ }
91
+ headers() {
92
+ return {
93
+ "Content-Type": "application/json",
94
+ Authorization: `Bearer ${this.apiKey}`,
95
+ "x-api-key": this.apiKey
96
+ };
97
+ }
98
+ url(path) {
99
+ const cleanPath = path.startsWith("/") ? path : `/${path}`;
100
+ return `${this.serverUrl}${this.dbManagePrefix}${cleanPath}`;
101
+ }
102
+ async getDbConfig(request) {
103
+ this.assertInitialized();
104
+ if (!request.projectId || request.projectId.trim().length === 0) {
105
+ throw new Error("projectId is required");
106
+ }
107
+ if (!request.dbName || request.dbName.trim().length === 0) {
108
+ throw new Error("dbName is required");
109
+ }
110
+ const response = await fetch(this.url("/config"), {
111
+ method: "POST",
112
+ headers: this.headers(),
113
+ body: JSON.stringify({
114
+ projectId: request.projectId,
115
+ dbName: request.dbName
116
+ })
117
+ });
118
+ if (!response.ok) {
119
+ let message = `DB service returned HTTP ${response.status} for /config`;
120
+ try {
121
+ const errorData = await response.json();
122
+ message = errorData.error ?? errorData.message ?? message;
123
+ } catch {
124
+ }
125
+ throw new Error(message);
126
+ }
127
+ return await response.json();
128
+ }
129
+ };
130
+ function dbService(config) {
131
+ return new DbService(config);
132
+ }
133
+ var VERSION = "0.1.0";
134
+ export {
135
+ DEFAULT_DB_MANAGE_PREFIX,
136
+ DEFAULT_SERVER_URL,
137
+ DbService,
138
+ DbServiceKeyValidationError,
139
+ VERSION,
140
+ dbService,
141
+ validateApiKeyFormat,
142
+ validateApiKeyWithService
143
+ };
144
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export class DbServiceKeyValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'DbServiceKeyValidationError';\n }\n}\n\nexport interface DbServiceConfig {\n apiKey: string;\n serverUrl?: string;\n validateOnInit?: boolean;\n}\n\nexport interface DbConfigRequest {\n projectId: string;\n dbName: string;\n}\n\nexport interface DbConfigResponse {\n dbUrl: string;\n}\n\nexport const DEFAULT_SERVER_URL = 'http://localhost:8000';\nexport const DEFAULT_DB_MANAGE_PREFIX = '/db-manage';\n\nexport function validateApiKeyFormat(apiKey?: string): void {\n const key = apiKey || process.env.KRUTAI_API_KEY;\n\n if (!key || typeof key !== 'string') {\n throw new DbServiceKeyValidationError('API key must be a non-empty string');\n }\n\n if (key.trim().length === 0) {\n throw new DbServiceKeyValidationError('API key cannot be empty or whitespace');\n }\n}\n\nexport async function validateApiKeyWithService(\n apiKey?: string,\n serverUrl: string = DEFAULT_SERVER_URL\n): Promise<boolean> {\n const key = apiKey || process.env.KRUTAI_API_KEY;\n if (!key) {\n throw new DbServiceKeyValidationError('API key is required');\n }\n\n validateApiKeyFormat(key);\n\n try {\n const url = `${serverUrl.replace(/\\/$/, '')}/validate`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': key,\n },\n body: JSON.stringify({ apiKey: key }),\n });\n\n let data: { valid?: boolean; message?: string; error?: string } = {};\n try {\n data = (await response.json()) as {\n valid?: boolean;\n message?: string;\n error?: string;\n };\n } catch {\n // Ignore parsing errors for non-JSON responses\n }\n\n if (!response.ok) {\n throw new DbServiceKeyValidationError(\n data.error ||\n data.message ||\n `API key validation failed: server responded with HTTP ${response.status}`\n );\n }\n\n if (data.valid === false) {\n throw new DbServiceKeyValidationError(\n data.error ?? data.message ?? 'API key rejected by server'\n );\n }\n\n return true;\n } catch (error) {\n if (error instanceof DbServiceKeyValidationError) throw error;\n throw new DbServiceKeyValidationError(\n `Failed to reach validation endpoint: ${error instanceof Error ? error.message : 'Unknown error'}`\n );\n }\n}\n\nexport class DbService {\n private readonly apiKey: string;\n private readonly serverUrl: string;\n private readonly dbManagePrefix: string;\n private readonly config: DbServiceConfig;\n private initialized = false;\n\n constructor(config: DbServiceConfig) {\n this.config = config;\n this.apiKey = config.apiKey || process.env.KRUTAI_API_KEY || '';\n this.serverUrl = (config.serverUrl ?? DEFAULT_SERVER_URL).replace(/\\/$/, '');\n this.dbManagePrefix = DEFAULT_DB_MANAGE_PREFIX.replace(/\\/$/, '');\n\n validateApiKeyFormat(this.apiKey);\n\n if (config.validateOnInit === false) {\n this.initialized = true;\n }\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) return;\n\n if (this.config.validateOnInit !== false) {\n await validateApiKeyWithService(this.apiKey, this.serverUrl);\n }\n\n this.initialized = true;\n }\n\n isInitialized(): boolean {\n return this.initialized;\n }\n\n private assertInitialized(): void {\n if (!this.initialized) {\n throw new Error(\n 'DbService not initialized. Call initialize() first or set validateOnInit to false.'\n );\n }\n }\n\n private headers(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n 'x-api-key': this.apiKey,\n };\n }\n\n private url(path: string): string {\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n return `${this.serverUrl}${this.dbManagePrefix}${cleanPath}`;\n }\n\n async getDbConfig(request: DbConfigRequest): Promise<DbConfigResponse> {\n this.assertInitialized();\n\n if (!request.projectId || request.projectId.trim().length === 0) {\n throw new Error('projectId is required');\n }\n\n if (!request.dbName || request.dbName.trim().length === 0) {\n throw new Error('dbName is required');\n }\n\n const response = await fetch(this.url('/config'), {\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify({\n projectId: request.projectId,\n dbName: request.dbName,\n }),\n });\n\n if (!response.ok) {\n let message = `DB service returned HTTP ${response.status} for /config`;\n try {\n const errorData = (await response.json()) as {\n message?: string;\n error?: string;\n };\n message = errorData.error ?? errorData.message ?? message;\n } catch {\n // ignore malformed error payloads\n }\n throw new Error(message);\n }\n\n return (await response.json()) as DbConfigResponse;\n }\n}\n\nexport function dbService(config: DbServiceConfig): DbService {\n return new DbService(config);\n}\n\nexport const VERSION = '0.1.0';\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@krutai/db-service",
3
+ "version": "1.0.1",
4
+ "description": "DB service client for KrutAI",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "prepack": "npm run build",
20
+ "build": "tsup",
21
+ "dev": "tsup --watch",
22
+ "clean": "rm -rf dist *.tsbuildinfo",
23
+ "typecheck": "tsc --noEmit"
24
+ },
25
+ "keywords": [
26
+ "krutai",
27
+ "database",
28
+ "db-service"
29
+ ],
30
+ "author": "",
31
+ "license": "MIT",
32
+ "devDependencies": {
33
+ "@types/node": "^20.11.0",
34
+ "tsup": "^8.0.1",
35
+ "typescript": "^5.3.3"
36
+ },
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/AccountantAIOrg/krut_packages.git",
43
+ "directory": "packages/db-service"
44
+ }
45
+ }