@boltic/sdk 0.1.2 → 0.1.3

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/dist/sdk.mjs CHANGED
@@ -109,6 +109,73 @@ let AuthManager$1 = class AuthManager {
109
109
  }
110
110
  }
111
111
  };
112
+ const REGION_CONFIGS = {
113
+ "asia-south1": {
114
+ local: {
115
+ baseURL: "http://localhost:8000",
116
+ timeout: 3e4,
117
+ debug: true
118
+ },
119
+ sit: {
120
+ baseURL: "https://asia-south1.api.fcz0.de/service/sdk/boltic-tables",
121
+ timeout: 15e3
122
+ },
123
+ uat: {
124
+ baseURL: "https://asia-south1.api.uat.fcz0.de/service/sdk/boltic-tables",
125
+ timeout: 15e3
126
+ },
127
+ prod: {
128
+ baseURL: "https://asia-south1.api.boltic.io/service/sdk/boltic-tables",
129
+ timeout: 1e4
130
+ }
131
+ },
132
+ "us-central1": {
133
+ local: {
134
+ baseURL: "http://localhost:8000",
135
+ timeout: 3e4,
136
+ debug: true
137
+ },
138
+ sit: {
139
+ baseURL: "https://us-central1.api.fcz0.de/service/sdk/boltic-tables",
140
+ timeout: 15e3
141
+ },
142
+ uat: {
143
+ baseURL: "https://us-central1.api.uat.fcz0.de/service/sdk/boltic-tables",
144
+ timeout: 15e3
145
+ },
146
+ prod: {
147
+ baseURL: "https://us-central1.api.boltic.io/service/sdk/boltic-tables",
148
+ timeout: 1e4
149
+ }
150
+ }
151
+ };
152
+ const REGION_BASE_HOSTS = {
153
+ "asia-south1": {
154
+ local: { host: "http://localhost:8000", timeout: 3e4, debug: true },
155
+ sit: { host: "https://asia-south1.api.fcz0.de", timeout: 15e3 },
156
+ uat: { host: "https://asia-south1.api.uat.fcz0.de", timeout: 15e3 },
157
+ prod: { host: "https://asia-south1.api.boltic.io", timeout: 1e4 }
158
+ },
159
+ "us-central1": {
160
+ local: { host: "http://localhost:8000", timeout: 3e4, debug: true },
161
+ sit: { host: "https://us-central1.api.fcz0.de", timeout: 15e3 },
162
+ uat: { host: "https://us-central1.api.uat.fcz0.de", timeout: 15e3 },
163
+ prod: { host: "https://us-central1.api.boltic.io", timeout: 1e4 }
164
+ }
165
+ };
166
+ function resolveServiceURL(region, environment, servicePath) {
167
+ const regionConfig = REGION_BASE_HOSTS[region];
168
+ if (!regionConfig) {
169
+ throw new Error(`Unsupported region: ${region}`);
170
+ }
171
+ const envConfig = regionConfig[environment];
172
+ if (!envConfig) {
173
+ throw new Error(
174
+ `Unsupported environment: ${environment} for region: ${region}`
175
+ );
176
+ }
177
+ return `${envConfig.host}${servicePath}`;
178
+ }
112
179
  function isErrorResponse(response) {
113
180
  return "error" in response && response.error !== void 0;
114
181
  }
@@ -167,77 +234,6 @@ Context: ${JSON.stringify(context, null, 2)}`;
167
234
  }
168
235
  return String(error);
169
236
  }
170
- class AuthManager2 {
171
- constructor(config) {
172
- this.tokenInfo = null;
173
- this.config = {
174
- maxRetries: 3,
175
- ...config
176
- };
177
- this.validateApiKey(config.apiKey);
178
- }
179
- validateApiKey(apiKey) {
180
- if (!apiKey || typeof apiKey !== "string" || apiKey.trim().length === 0) {
181
- throw createErrorWithContext(
182
- "API key is required and must be a non-empty string",
183
- {
184
- name: "AuthenticationError",
185
- code: "INVALID_API_KEY"
186
- }
187
- );
188
- }
189
- if (apiKey.length < 10) {
190
- throw createErrorWithContext(
191
- "API key appears to be invalid (too short)",
192
- {
193
- name: "AuthenticationError",
194
- code: "INVALID_API_KEY_FORMAT"
195
- }
196
- );
197
- }
198
- }
199
- getAuthHeaders() {
200
- return {
201
- "x-boltic-token": this.config.apiKey
202
- };
203
- }
204
- updateApiKey(newApiKey) {
205
- this.validateApiKey(newApiKey);
206
- this.config.apiKey = newApiKey;
207
- this.tokenInfo = null;
208
- }
209
- isAuthenticated() {
210
- return !!this.config.apiKey;
211
- }
212
- async validateApiKeyAsync() {
213
- try {
214
- this.validateApiKey(this.config.apiKey);
215
- return true;
216
- } catch {
217
- return false;
218
- }
219
- }
220
- getTokenInfo() {
221
- return this.tokenInfo ? { ...this.tokenInfo } : null;
222
- }
223
- getMaxRetries() {
224
- return this.config.maxRetries || 3;
225
- }
226
- // Security methods to prevent API key exposure
227
- toString() {
228
- return `AuthManager { authenticated: ${this.isAuthenticated()}, maxRetries: ${this.getMaxRetries()} }`;
229
- }
230
- toJSON() {
231
- return {
232
- authenticated: this.isAuthenticated(),
233
- maxRetries: this.getMaxRetries()
234
- };
235
- }
236
- // Custom inspect method for Node.js console logging
237
- [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
238
- return this.toString();
239
- }
240
- }
241
237
  class AxiosAdapter {
242
238
  constructor() {
243
239
  try {
@@ -260,7 +256,6 @@ class AxiosAdapter {
260
256
  timeout: config.timeout,
261
257
  signal: config.signal,
262
258
  validateStatus: () => true
263
- // Don't throw on non-2xx status codes
264
259
  };
265
260
  const response = await this.axios(axiosConfig);
266
261
  if (response.status < 200 || response.status >= 300) {
@@ -480,6 +475,156 @@ function createHttpAdapter() {
480
475
  );
481
476
  }
482
477
  }
478
+ class AuthManager2 {
479
+ constructor(config) {
480
+ this.tokenInfo = null;
481
+ this.config = {
482
+ maxRetries: 3,
483
+ ...config
484
+ };
485
+ this.validateApiKey(config.apiKey);
486
+ }
487
+ validateApiKey(apiKey) {
488
+ if (!apiKey || typeof apiKey !== "string" || apiKey.trim().length === 0) {
489
+ throw createErrorWithContext(
490
+ "API key is required and must be a non-empty string",
491
+ {
492
+ name: "AuthenticationError",
493
+ code: "INVALID_API_KEY"
494
+ }
495
+ );
496
+ }
497
+ if (apiKey.length < 10) {
498
+ throw createErrorWithContext(
499
+ "API key appears to be invalid (too short)",
500
+ {
501
+ name: "AuthenticationError",
502
+ code: "INVALID_API_KEY_FORMAT"
503
+ }
504
+ );
505
+ }
506
+ }
507
+ getAuthHeaders() {
508
+ return {
509
+ "x-boltic-token": this.config.apiKey
510
+ };
511
+ }
512
+ updateApiKey(newApiKey) {
513
+ this.validateApiKey(newApiKey);
514
+ this.config.apiKey = newApiKey;
515
+ this.tokenInfo = null;
516
+ }
517
+ isAuthenticated() {
518
+ return !!this.config.apiKey;
519
+ }
520
+ async validateApiKeyAsync() {
521
+ try {
522
+ this.validateApiKey(this.config.apiKey);
523
+ return true;
524
+ } catch {
525
+ return false;
526
+ }
527
+ }
528
+ getTokenInfo() {
529
+ return this.tokenInfo ? { ...this.tokenInfo } : null;
530
+ }
531
+ getMaxRetries() {
532
+ return this.config.maxRetries || 3;
533
+ }
534
+ toString() {
535
+ return `AuthManager { authenticated: ${this.isAuthenticated()}, maxRetries: ${this.getMaxRetries()} }`;
536
+ }
537
+ toJSON() {
538
+ return {
539
+ authenticated: this.isAuthenticated(),
540
+ maxRetries: this.getMaxRetries()
541
+ };
542
+ }
543
+ [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
544
+ return this.toString();
545
+ }
546
+ }
547
+ const SERVICE_PATHS = {
548
+ DATABASES: "/service/sdk/boltic-tables/v1",
549
+ WORKFLOW_TEMPORAL: "/service/panel/temporal/v1.0",
550
+ INTEGRATION: "/service/panel/integration/v1"
551
+ };
552
+ class BaseApiClient {
553
+ constructor(apiKey, config = {}, servicePath = SERVICE_PATHS.DATABASES) {
554
+ this.config = { apiKey, ...config };
555
+ this.httpAdapter = createHttpAdapter();
556
+ this.environment = config.environment || "prod";
557
+ this.region = config.region || "asia-south1";
558
+ this.baseURL = resolveServiceURL(
559
+ this.region,
560
+ this.environment,
561
+ servicePath
562
+ );
563
+ }
564
+ /**
565
+ * Resolve a secondary service URL using the same region/environment
566
+ * but a different service path.
567
+ */
568
+ resolveAdditionalServiceURL(servicePath) {
569
+ return resolveServiceURL(this.region, this.environment, servicePath);
570
+ }
571
+ buildHeaders() {
572
+ return {
573
+ "Content-Type": "application/json",
574
+ Accept: "application/json",
575
+ "x-boltic-token": this.config.apiKey,
576
+ ...this.config.headers
577
+ };
578
+ }
579
+ formatErrorResponse(error, prefix = "API") {
580
+ if (this.config.debug) {
581
+ console.error(`[${this.constructor.name}] ${prefix} Error:`, error);
582
+ }
583
+ if (error && typeof error === "object" && "response" in error) {
584
+ const apiError = error;
585
+ if (apiError.response?.data?.error) {
586
+ return apiError.response.data;
587
+ }
588
+ return {
589
+ error: {
590
+ code: `${prefix}_ERROR`,
591
+ message: error instanceof Error ? error.message : `Unknown ${prefix} error`,
592
+ meta: [`Status: ${apiError.response?.status || "unknown"}`]
593
+ }
594
+ };
595
+ }
596
+ if (error instanceof Error) {
597
+ return {
598
+ error: {
599
+ code: `${prefix}_CLIENT_ERROR`,
600
+ message: error.message,
601
+ meta: []
602
+ }
603
+ };
604
+ }
605
+ return {
606
+ error: {
607
+ code: `${prefix}_UNKNOWN_ERROR`,
608
+ message: `An unexpected ${prefix} error occurred`,
609
+ meta: []
610
+ }
611
+ };
612
+ }
613
+ toString() {
614
+ return `${this.constructor.name} { environment: "${this.config.environment || "prod"}", debug: ${this.config.debug || false} }`;
615
+ }
616
+ toJSON() {
617
+ const safeConfig = { ...this.config };
618
+ delete safeConfig.apiKey;
619
+ return {
620
+ client: this.constructor.name,
621
+ config: safeConfig
622
+ };
623
+ }
624
+ [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
625
+ return this.toString();
626
+ }
627
+ }
483
628
  class InterceptorManagerImpl {
484
629
  constructor() {
485
630
  this.requestInterceptors = /* @__PURE__ */ new Map();
@@ -664,46 +809,88 @@ class BaseClient {
664
809
  return { ...this.config };
665
810
  }
666
811
  }
667
- const REGION_CONFIGS = {
668
- "asia-south1": {
669
- local: {
670
- baseURL: "http://localhost:8000",
671
- timeout: 3e4,
672
- debug: true
673
- },
674
- sit: {
675
- baseURL: "https://asia-south1.api.fcz0.de/service/sdk/boltic-tables",
676
- timeout: 15e3
677
- },
678
- uat: {
679
- baseURL: "https://asia-south1.api.uat.fcz0.de/service/sdk/boltic-tables",
680
- timeout: 15e3
681
- },
682
- prod: {
683
- baseURL: "https://asia-south1.api.boltic.io/service/sdk/boltic-tables",
684
- timeout: 1e4
812
+ class BaseResource {
813
+ constructor(client, basePath) {
814
+ this.client = client;
815
+ this.basePath = basePath;
816
+ }
817
+ getBasePath() {
818
+ return this.basePath;
819
+ }
820
+ async makeRequest(method, path, data, options) {
821
+ const url = `${this.basePath}${path}`;
822
+ try {
823
+ let response;
824
+ switch (method) {
825
+ case "GET":
826
+ response = await this.client.get(url, {
827
+ params: options?.params
828
+ });
829
+ break;
830
+ case "POST":
831
+ response = await this.client.post(url, data, {
832
+ params: options?.params
833
+ });
834
+ break;
835
+ case "PUT":
836
+ response = await this.client.put(url, data, {
837
+ params: options?.params
838
+ });
839
+ break;
840
+ case "PATCH":
841
+ response = await this.client.patch(url, data, {
842
+ params: options?.params
843
+ });
844
+ break;
845
+ case "DELETE":
846
+ response = await this.client.delete(url, {
847
+ params: options?.params
848
+ });
849
+ break;
850
+ }
851
+ return response.data;
852
+ } catch (error) {
853
+ return {
854
+ error: {
855
+ code: "CLIENT_ERROR",
856
+ message: formatError(error),
857
+ meta: ["Request failed"]
858
+ }
859
+ };
685
860
  }
686
- },
687
- "us-central1": {
688
- local: {
689
- baseURL: "http://localhost:8000",
690
- timeout: 3e4,
691
- debug: true
692
- },
693
- sit: {
694
- baseURL: "https://us-central1.api.fcz0.de/service/sdk/boltic-tables",
695
- timeout: 15e3
696
- },
697
- uat: {
698
- baseURL: "https://us-central1.api.uat.fcz0.de/service/sdk/boltic-tables",
699
- timeout: 15e3
700
- },
701
- prod: {
702
- baseURL: "https://us-central1.api.boltic.io/service/sdk/boltic-tables",
703
- timeout: 1e4
861
+ }
862
+ buildQueryParams(options = {}) {
863
+ const params = {};
864
+ if (options.fields?.length) {
865
+ params.fields = options.fields.join(",");
866
+ }
867
+ if (options.sort?.length) {
868
+ params.sort = options.sort.map((s) => `${s.field}:${s.order}`).join(",");
869
+ }
870
+ if (options.limit !== void 0) {
871
+ params.limit = options.limit;
872
+ }
873
+ if (options.offset !== void 0) {
874
+ params.offset = options.offset;
875
+ }
876
+ if (options.where) {
877
+ Object.entries(options.where).forEach(([key, value]) => {
878
+ if (value !== void 0 && value !== null) {
879
+ params[`where[${key}]`] = typeof value === "object" ? JSON.stringify(value) : value;
880
+ }
881
+ });
704
882
  }
883
+ return params;
705
884
  }
706
- };
885
+ handleResponse(response) {
886
+ if ("error" in response) {
887
+ if (this.client.getConfig().debug) {
888
+ console.error("API Error:", response.error);
889
+ }
890
+ }
891
+ return response;
892
+ }
893
+ }
707
894
  class ConfigManager {
708
895
  constructor(apiKey, environment = "prod", region = "asia-south1", overrides) {
709
896
  const envConfig = REGION_CONFIGS[region][environment];
@@ -726,7 +913,6 @@ class ConfigManager {
726
913
  updateConfig(updates) {
727
914
  this.config = { ...this.config, ...updates };
728
915
  }
729
- // Security methods to prevent API key exposure
730
916
  toString() {
731
917
  return `ConfigManager { environment: "${this.config.environment}", region: "${this.config.region}", debug: ${this.config.debug} }`;
732
918
  }
@@ -735,7 +921,6 @@ class ConfigManager {
735
921
  delete safeConfig.apiKey;
736
922
  return safeConfig;
737
923
  }
738
- // Custom inspect method for Node.js console logging
739
924
  [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
740
925
  return this.toString();
741
926
  }
@@ -922,26 +1107,9 @@ function transformDateFormat(dateFormat) {
922
1107
  function transformTimeFormat(timeFormat) {
923
1108
  return TimeFormatEnum[timeFormat] || timeFormat;
924
1109
  }
925
- class ColumnsApiClient {
1110
+ class ColumnsApiClient extends BaseApiClient {
926
1111
  constructor(apiKey, config = {}) {
927
- this.config = { apiKey, ...config };
928
- this.httpAdapter = createHttpAdapter();
929
- const environment = config.environment || "prod";
930
- const region = config.region || "asia-south1";
931
- this.baseURL = this.getBaseURL(environment, region);
932
- }
933
- getBaseURL(environment, region) {
934
- const regionConfig = REGION_CONFIGS[region];
935
- if (!regionConfig) {
936
- throw new Error(`Unsupported region: ${region}`);
937
- }
938
- const envConfig = regionConfig[environment];
939
- if (!envConfig) {
940
- throw new Error(
941
- `Unsupported environment: ${environment} for region: ${region}`
942
- );
943
- }
944
- return `${envConfig.baseURL}/v1`;
1112
+ super(apiKey, config);
945
1113
  }
946
1114
  /**
947
1115
  * Create a single column in a table
@@ -978,7 +1146,7 @@ class ColumnsApiClient {
978
1146
  const createdColumns = [];
979
1147
  for (const column of columns) {
980
1148
  const result = await this.createColumn(tableId, column);
981
- if ("error" in result) {
1149
+ if (isErrorResponse(result)) {
982
1150
  return result;
983
1151
  }
984
1152
  createdColumns.push(result.data);
@@ -1130,7 +1298,7 @@ class ColumnsApiClient {
1130
1298
  tableId,
1131
1299
  apiRequest
1132
1300
  );
1133
- if ("error" in listResult) {
1301
+ if (isErrorResponse(listResult)) {
1134
1302
  return listResult;
1135
1303
  }
1136
1304
  const column = listResult.data[0] || null;
@@ -1177,7 +1345,7 @@ class ColumnsApiClient {
1177
1345
  async updateColumnByName(tableId, columnName, updates) {
1178
1346
  try {
1179
1347
  const findResult = await this.findColumnByName(tableId, columnName);
1180
- if ("error" in findResult) {
1348
+ if (isErrorResponse(findResult)) {
1181
1349
  return findResult;
1182
1350
  }
1183
1351
  if (!findResult.data) {
@@ -1211,7 +1379,7 @@ class ColumnsApiClient {
1211
1379
  async deleteColumnByName(tableId, columnName) {
1212
1380
  try {
1213
1381
  const findResult = await this.findColumnByName(tableId, columnName);
1214
- if ("error" in findResult) {
1382
+ if (isErrorResponse(findResult)) {
1215
1383
  return findResult;
1216
1384
  }
1217
1385
  if (!findResult.data) {
@@ -1228,47 +1396,6 @@ class ColumnsApiClient {
1228
1396
  return this.formatErrorResponse(error);
1229
1397
  }
1230
1398
  }
1231
- buildHeaders() {
1232
- return {
1233
- "Content-Type": "application/json",
1234
- Accept: "application/json",
1235
- "x-boltic-token": this.config.apiKey
1236
- };
1237
- }
1238
- formatErrorResponse(error) {
1239
- if (this.config.debug) {
1240
- console.error("Columns API Error:", error);
1241
- }
1242
- if (error && typeof error === "object" && "response" in error) {
1243
- const apiError = error;
1244
- if (apiError.response?.data?.error) {
1245
- return apiError.response.data;
1246
- }
1247
- return {
1248
- error: {
1249
- code: "API_ERROR",
1250
- message: error.message || "Unknown API error",
1251
- meta: [`Status: ${apiError.response?.status || "unknown"}`]
1252
- }
1253
- };
1254
- }
1255
- if (error && typeof error === "object" && "message" in error) {
1256
- return {
1257
- error: {
1258
- code: "CLIENT_ERROR",
1259
- message: error.message,
1260
- meta: ["Client-side error occurred"]
1261
- }
1262
- };
1263
- }
1264
- return {
1265
- error: {
1266
- code: "UNKNOWN_ERROR",
1267
- message: "An unexpected error occurred",
1268
- meta: ["Unknown error type"]
1269
- }
1270
- };
1271
- }
1272
1399
  }
1273
1400
  const TABLE_ENDPOINTS = {
1274
1401
  list: {
@@ -1447,26 +1574,9 @@ function transformFieldDefinition(field) {
1447
1574
  default_value: field.default_value
1448
1575
  };
1449
1576
  }
1450
- class TablesApiClient {
1577
+ class TablesApiClient extends BaseApiClient {
1451
1578
  constructor(apiKey, config = {}) {
1452
- this.config = { apiKey, ...config };
1453
- this.httpAdapter = createHttpAdapter();
1454
- const environment = config.environment || "prod";
1455
- const region = config.region || "asia-south1";
1456
- this.baseURL = this.getBaseURL(environment, region);
1457
- }
1458
- getBaseURL(environment, region) {
1459
- const regionConfig = REGION_CONFIGS[region];
1460
- if (!regionConfig) {
1461
- throw new Error(`Unsupported region: ${region}`);
1462
- }
1463
- const envConfig = regionConfig[environment];
1464
- if (!envConfig) {
1465
- throw new Error(
1466
- `Unsupported environment: ${environment} for region: ${region}`
1467
- );
1468
- }
1469
- return `${envConfig.baseURL}/v1`;
1579
+ super(apiKey, config);
1470
1580
  }
1471
1581
  /**
1472
1582
  * Create a new table
@@ -1551,168 +1661,43 @@ class TablesApiClient {
1551
1661
  const endpoint = TABLE_ENDPOINTS.update;
1552
1662
  let url = `${this.baseURL}${buildEndpointPath(endpoint, { table_id: tableId })}`;
1553
1663
  url = addDbIdToUrl(url, db_id);
1554
- const response = await this.httpAdapter.request({
1555
- url,
1556
- method: endpoint.method,
1557
- headers: this.buildHeaders(),
1558
- data: updateData,
1559
- timeout: this.config.timeout
1560
- });
1561
- const responseData = response.data;
1562
- if (fields && responseData.data) {
1563
- responseData.data = filterObjectFields(
1564
- responseData.data,
1565
- fields
1566
- );
1567
- }
1568
- return responseData;
1569
- } catch (error) {
1570
- return this.formatErrorResponse(error);
1571
- }
1572
- }
1573
- /**
1574
- * Delete a table
1575
- */
1576
- async deleteTable(tableId, options = {}) {
1577
- try {
1578
- const endpoint = TABLE_ENDPOINTS.delete;
1579
- let url = `${this.baseURL}${buildEndpointPath(endpoint, { table_id: tableId })}`;
1580
- url = addDbIdToUrl(url, options.db_id);
1581
- const response = await this.httpAdapter.request({
1582
- url,
1583
- method: endpoint.method,
1584
- headers: this.buildHeaders(),
1585
- timeout: this.config.timeout
1586
- });
1587
- return response.data;
1588
- } catch (error) {
1589
- return this.formatErrorResponse(error);
1590
- }
1591
- }
1592
- // Private helper methods
1593
- buildHeaders() {
1594
- return {
1595
- "Content-Type": "application/json",
1596
- Accept: "application/json",
1597
- "x-boltic-token": this.config.apiKey
1598
- };
1599
- }
1600
- formatErrorResponse(error) {
1601
- if (this.config.debug) {
1602
- console.error("Tables API Error:", error);
1603
- }
1604
- if (error && typeof error === "object" && "response" in error) {
1605
- const apiError = error;
1606
- if (apiError.response?.data?.error) {
1607
- return apiError.response.data;
1608
- }
1609
- return {
1610
- error: {
1611
- code: "API_ERROR",
1612
- message: error.message || "Unknown API error",
1613
- meta: [`Status: ${apiError.response?.status || "unknown"}`]
1614
- }
1615
- };
1616
- }
1617
- if (error && typeof error === "object" && "message" in error) {
1618
- return {
1619
- error: {
1620
- code: "CLIENT_ERROR",
1621
- message: error.message,
1622
- meta: ["Client-side error occurred"]
1623
- }
1624
- };
1625
- }
1626
- return {
1627
- error: {
1628
- code: "UNKNOWN_ERROR",
1629
- message: "An unexpected error occurred",
1630
- meta: ["Unknown error type"]
1631
- }
1632
- };
1633
- }
1634
- }
1635
- class BaseResource {
1636
- constructor(client, basePath) {
1637
- this.client = client;
1638
- this.basePath = basePath;
1639
- }
1640
- // Public getter for basePath
1641
- getBasePath() {
1642
- return this.basePath;
1643
- }
1644
- async makeRequest(method, path, data, options) {
1645
- const url = `${this.basePath}${path}`;
1646
- try {
1647
- let response;
1648
- switch (method) {
1649
- case "GET":
1650
- response = await this.client.get(url, {
1651
- params: options?.params
1652
- });
1653
- break;
1654
- case "POST":
1655
- response = await this.client.post(url, data, {
1656
- params: options?.params
1657
- });
1658
- break;
1659
- case "PUT":
1660
- response = await this.client.put(url, data, {
1661
- params: options?.params
1662
- });
1663
- break;
1664
- case "PATCH":
1665
- response = await this.client.patch(url, data, {
1666
- params: options?.params
1667
- });
1668
- break;
1669
- case "DELETE":
1670
- response = await this.client.delete(url, {
1671
- params: options?.params
1672
- });
1673
- break;
1674
- }
1675
- return response.data;
1676
- } catch (error) {
1677
- return {
1678
- error: {
1679
- code: "CLIENT_ERROR",
1680
- message: formatError(error),
1681
- meta: ["Request failed"]
1682
- }
1683
- };
1684
- }
1685
- }
1686
- buildQueryParams(options = {}) {
1687
- const params = {};
1688
- if (options.fields?.length) {
1689
- params.fields = options.fields.join(",");
1690
- }
1691
- if (options.sort?.length) {
1692
- params.sort = options.sort.map((s) => `${s.field}:${s.order}`).join(",");
1693
- }
1694
- if (options.limit !== void 0) {
1695
- params.limit = options.limit;
1696
- }
1697
- if (options.offset !== void 0) {
1698
- params.offset = options.offset;
1699
- }
1700
- if (options.where) {
1701
- Object.entries(options.where).forEach(([key, value]) => {
1702
- if (value !== void 0 && value !== null) {
1703
- params[`where[${key}]`] = typeof value === "object" ? JSON.stringify(value) : value;
1704
- }
1664
+ const response = await this.httpAdapter.request({
1665
+ url,
1666
+ method: endpoint.method,
1667
+ headers: this.buildHeaders(),
1668
+ data: updateData,
1669
+ timeout: this.config.timeout
1705
1670
  });
1671
+ const responseData = response.data;
1672
+ if (fields && responseData.data) {
1673
+ responseData.data = filterObjectFields(
1674
+ responseData.data,
1675
+ fields
1676
+ );
1677
+ }
1678
+ return responseData;
1679
+ } catch (error) {
1680
+ return this.formatErrorResponse(error);
1706
1681
  }
1707
- return params;
1708
1682
  }
1709
- handleResponse(response) {
1710
- if ("error" in response) {
1711
- if (this.client.getConfig().debug) {
1712
- console.error("API Error:", response.error);
1713
- }
1683
+ /**
1684
+ * Delete a table
1685
+ */
1686
+ async deleteTable(tableId, options = {}) {
1687
+ try {
1688
+ const endpoint = TABLE_ENDPOINTS.delete;
1689
+ let url = `${this.baseURL}${buildEndpointPath(endpoint, { table_id: tableId })}`;
1690
+ url = addDbIdToUrl(url, options.db_id);
1691
+ const response = await this.httpAdapter.request({
1692
+ url,
1693
+ method: endpoint.method,
1694
+ headers: this.buildHeaders(),
1695
+ timeout: this.config.timeout
1696
+ });
1697
+ return response.data;
1698
+ } catch (error) {
1699
+ return this.formatErrorResponse(error);
1714
1700
  }
1715
- return response;
1716
1701
  }
1717
1702
  }
1718
1703
  class TableResource extends BaseResource {
@@ -2464,26 +2449,9 @@ const buildDatabaseEndpointPath = (endpoint, params = {}) => {
2464
2449
  });
2465
2450
  return path;
2466
2451
  };
2467
- class DatabasesApiClient {
2452
+ class DatabasesApiClient extends BaseApiClient {
2468
2453
  constructor(apiKey, config = {}) {
2469
- this.config = { apiKey, ...config };
2470
- this.httpAdapter = createHttpAdapter();
2471
- const environment = config.environment || "prod";
2472
- const region = config.region || "asia-south1";
2473
- this.baseURL = this.getBaseURL(environment, region);
2474
- }
2475
- getBaseURL(environment, region) {
2476
- const regionConfig = REGION_CONFIGS[region];
2477
- if (!regionConfig) {
2478
- throw new Error(`Unsupported region: ${region}`);
2479
- }
2480
- const envConfig = regionConfig[environment];
2481
- if (!envConfig) {
2482
- throw new Error(
2483
- `Unsupported environment: ${environment} for region: ${region}`
2484
- );
2485
- }
2486
- return `${envConfig.baseURL}/v1`;
2454
+ super(apiKey, config);
2487
2455
  }
2488
2456
  /**
2489
2457
  * Create a new database
@@ -2495,16 +2463,13 @@ class DatabasesApiClient {
2495
2463
  const response = await this.httpAdapter.request({
2496
2464
  url,
2497
2465
  method: endpoint.method,
2498
- headers: {
2499
- "Content-Type": "application/json",
2500
- "x-boltic-token": this.config.apiKey
2501
- },
2466
+ headers: this.buildHeaders(),
2502
2467
  data: request,
2503
2468
  timeout: this.config.timeout
2504
2469
  });
2505
2470
  return response.data;
2506
2471
  } catch (error) {
2507
- return this.handleError(error);
2472
+ return this.formatErrorResponse(error);
2508
2473
  }
2509
2474
  }
2510
2475
  /**
@@ -2530,10 +2495,7 @@ class DatabasesApiClient {
2530
2495
  const response = await this.httpAdapter.request({
2531
2496
  url,
2532
2497
  method: endpoint.method,
2533
- headers: {
2534
- "Content-Type": "application/json",
2535
- "x-boltic-token": this.config.apiKey
2536
- },
2498
+ headers: this.buildHeaders(),
2537
2499
  data: request,
2538
2500
  timeout: this.config.timeout
2539
2501
  });
@@ -2549,7 +2511,7 @@ class DatabasesApiClient {
2549
2511
  }
2550
2512
  return result;
2551
2513
  } catch (error) {
2552
- return this.handleError(error);
2514
+ return this.formatErrorResponse(error);
2553
2515
  }
2554
2516
  }
2555
2517
  /**
@@ -2563,16 +2525,13 @@ class DatabasesApiClient {
2563
2525
  const response = await this.httpAdapter.request({
2564
2526
  url,
2565
2527
  method: endpoint.method,
2566
- headers: {
2567
- "Content-Type": "application/json",
2568
- "x-boltic-token": this.config.apiKey
2569
- },
2528
+ headers: this.buildHeaders(),
2570
2529
  data: request,
2571
2530
  timeout: this.config.timeout
2572
2531
  });
2573
2532
  return response.data;
2574
2533
  } catch (error) {
2575
- return this.handleError(error);
2534
+ return this.formatErrorResponse(error);
2576
2535
  }
2577
2536
  }
2578
2537
  /**
@@ -2586,15 +2545,12 @@ class DatabasesApiClient {
2586
2545
  const response = await this.httpAdapter.request({
2587
2546
  url,
2588
2547
  method: endpoint.method,
2589
- headers: {
2590
- "Content-Type": "application/json",
2591
- "x-boltic-token": this.config.apiKey
2592
- },
2548
+ headers: this.buildHeaders(),
2593
2549
  timeout: this.config.timeout
2594
2550
  });
2595
2551
  return response.data;
2596
2552
  } catch (error) {
2597
- return this.handleError(error);
2553
+ return this.formatErrorResponse(error);
2598
2554
  }
2599
2555
  }
2600
2556
  /**
@@ -2607,10 +2563,7 @@ class DatabasesApiClient {
2607
2563
  const response = await this.httpAdapter.request({
2608
2564
  url,
2609
2565
  method: endpoint.method,
2610
- headers: {
2611
- "Content-Type": "application/json",
2612
- "x-boltic-token": this.config.apiKey
2613
- },
2566
+ headers: this.buildHeaders(),
2614
2567
  data: request,
2615
2568
  timeout: this.config.timeout
2616
2569
  });
@@ -2626,7 +2579,7 @@ class DatabasesApiClient {
2626
2579
  }
2627
2580
  return result;
2628
2581
  } catch (error) {
2629
- return this.handleError(error);
2582
+ return this.formatErrorResponse(error);
2630
2583
  }
2631
2584
  }
2632
2585
  /**
@@ -2640,70 +2593,13 @@ class DatabasesApiClient {
2640
2593
  const response = await this.httpAdapter.request({
2641
2594
  url,
2642
2595
  method: endpoint.method,
2643
- headers: {
2644
- "Content-Type": "application/json",
2645
- "x-boltic-token": this.config.apiKey
2646
- },
2596
+ headers: this.buildHeaders(),
2647
2597
  timeout: this.config.timeout
2648
2598
  });
2649
2599
  return response.data;
2650
2600
  } catch (error) {
2651
- return this.handleError(error);
2652
- }
2653
- }
2654
- /**
2655
- * Handle API errors and convert to standard error format
2656
- */
2657
- handleError(error) {
2658
- if (this.config.debug) {
2659
- console.error("[DatabasesApiClient] Error:", error);
2660
- }
2661
- const hasErrorProperty = (err) => {
2662
- return typeof err === "object" && err !== null && "error" in err && typeof err.error === "object" && err.error !== null;
2663
- };
2664
- const hasResponseError = (err) => {
2665
- return typeof err === "object" && err !== null && "response" in err && typeof err.response === "object" && err.response !== null && "data" in err.response && typeof err.response.data === "object" && err.response.data !== null && "error" in err.response.data;
2666
- };
2667
- const isStandardError = (err) => {
2668
- return err instanceof Error;
2669
- };
2670
- if (hasErrorProperty(error)) {
2671
- const errorWithError = error;
2672
- return {
2673
- error: {
2674
- code: typeof errorWithError.error.code === "number" ? String(errorWithError.error.code) : errorWithError.error.code || "UNKNOWN_ERROR",
2675
- message: errorWithError.error.message || "An error occurred",
2676
- meta: errorWithError.error.meta || []
2677
- }
2678
- };
2679
- }
2680
- if (hasResponseError(error)) {
2681
- const errorWithResponse = error;
2682
- return {
2683
- error: {
2684
- code: typeof errorWithResponse.response.data.error.code === "number" ? String(errorWithResponse.response.data.error.code) : errorWithResponse.response.data.error.code || "UNKNOWN_ERROR",
2685
- message: errorWithResponse.response.data.error.message || "An error occurred",
2686
- meta: errorWithResponse.response.data.error.meta || []
2687
- }
2688
- };
2689
- }
2690
- if (isStandardError(error)) {
2691
- const standardError = error;
2692
- return {
2693
- error: {
2694
- code: standardError.code || "UNKNOWN_ERROR",
2695
- message: standardError.message || "An unexpected error occurred",
2696
- meta: []
2697
- }
2698
- };
2601
+ return this.formatErrorResponse(error);
2699
2602
  }
2700
- return {
2701
- error: {
2702
- code: "UNKNOWN_ERROR",
2703
- message: "An unexpected error occurred",
2704
- meta: []
2705
- }
2706
- };
2707
2603
  }
2708
2604
  }
2709
2605
  class DatabaseResource extends BaseResource {
@@ -2733,7 +2629,7 @@ class DatabaseResource extends BaseResource {
2733
2629
  */
2734
2630
  async create(request) {
2735
2631
  const result = await this.apiClient.createDatabase(request);
2736
- if ("error" in result) {
2632
+ if (isErrorResponse(result)) {
2737
2633
  return {
2738
2634
  error: {
2739
2635
  code: typeof result.error.code === "number" ? String(result.error.code) : result.error.code,
@@ -2800,7 +2696,7 @@ class DatabaseResource extends BaseResource {
2800
2696
  queryParams,
2801
2697
  options
2802
2698
  );
2803
- if ("error" in result) {
2699
+ if (isErrorResponse(result)) {
2804
2700
  return {
2805
2701
  error: {
2806
2702
  code: typeof result.error.code === "number" ? String(result.error.code) : result.error.code,
@@ -2928,7 +2824,7 @@ class DatabaseResource extends BaseResource {
2928
2824
  db_name: request.db_name
2929
2825
  };
2930
2826
  const result = await this.apiClient.updateDatabase(dbId, updateRequest);
2931
- if ("error" in result) {
2827
+ if (isErrorResponse(result)) {
2932
2828
  return {
2933
2829
  error: {
2934
2830
  code: typeof result.error.code === "number" ? String(result.error.code) : result.error.code,
@@ -2977,7 +2873,7 @@ class DatabaseResource extends BaseResource {
2977
2873
  }
2978
2874
  const dbId = dbInfo.data.id;
2979
2875
  const result = await this.apiClient.deleteDatabase(dbId);
2980
- if ("error" in result) {
2876
+ if (isErrorResponse(result)) {
2981
2877
  return {
2982
2878
  error: {
2983
2879
  code: typeof result.error.code === "number" ? String(result.error.code) : result.error.code,
@@ -3020,7 +2916,7 @@ class DatabaseResource extends BaseResource {
3020
2916
  request.filters = options.filters;
3021
2917
  }
3022
2918
  const result = await this.apiClient.listDatabaseJobs(request, options);
3023
- if ("error" in result) {
2919
+ if (isErrorResponse(result)) {
3024
2920
  return {
3025
2921
  error: {
3026
2922
  code: typeof result.error.code === "number" ? String(result.error.code) : result.error.code,
@@ -3065,7 +2961,7 @@ class DatabaseResource extends BaseResource {
3065
2961
  */
3066
2962
  async pollDeleteStatus(jobId) {
3067
2963
  const result = await this.apiClient.pollDeleteStatus(jobId);
3068
- if ("error" in result) {
2964
+ if (isErrorResponse(result)) {
3069
2965
  return {
3070
2966
  error: {
3071
2967
  code: typeof result.error.code === "number" ? String(result.error.code) : result.error.code,
@@ -3105,26 +3001,9 @@ const buildIndexEndpointPath = (endpoint, params = {}) => {
3105
3001
  }
3106
3002
  return path;
3107
3003
  };
3108
- class IndexesApiClient {
3004
+ class IndexesApiClient extends BaseApiClient {
3109
3005
  constructor(apiKey, config = {}) {
3110
- this.config = { apiKey, ...config };
3111
- this.httpAdapter = createHttpAdapter();
3112
- const environment = config.environment || "prod";
3113
- const region = config.region || "asia-south1";
3114
- this.baseURL = this.getBaseURL(environment, region);
3115
- }
3116
- getBaseURL(environment, region) {
3117
- const regionConfig = REGION_CONFIGS[region];
3118
- if (!regionConfig) {
3119
- throw new Error(`Unsupported region: ${region}`);
3120
- }
3121
- const envConfig = regionConfig[environment];
3122
- if (!envConfig) {
3123
- throw new Error(
3124
- `Unsupported environment: ${environment} for region: ${region}`
3125
- );
3126
- }
3127
- return `${envConfig.baseURL}/v1`;
3006
+ super(apiKey, config);
3128
3007
  }
3129
3008
  async addIndex(tableId, request, dbId) {
3130
3009
  try {
@@ -3177,47 +3056,6 @@ class IndexesApiClient {
3177
3056
  return this.formatErrorResponse(error);
3178
3057
  }
3179
3058
  }
3180
- buildHeaders() {
3181
- return {
3182
- "Content-Type": "application/json",
3183
- Accept: "application/json",
3184
- "x-boltic-token": this.config.apiKey
3185
- };
3186
- }
3187
- formatErrorResponse(error) {
3188
- if (this.config.debug) {
3189
- console.error("Indexes API Error:", error);
3190
- }
3191
- if (error && typeof error === "object" && "response" in error) {
3192
- const apiError = error;
3193
- if (apiError.response?.data?.error) {
3194
- return apiError.response.data;
3195
- }
3196
- return {
3197
- error: {
3198
- code: "API_ERROR",
3199
- message: error.message || "Unknown API error",
3200
- meta: [`Status: ${apiError.response?.status || "unknown"}`]
3201
- }
3202
- };
3203
- }
3204
- if (error && typeof error === "object" && "message" in error) {
3205
- return {
3206
- error: {
3207
- code: "CLIENT_ERROR",
3208
- message: error.message,
3209
- meta: ["Client-side error occurred"]
3210
- }
3211
- };
3212
- }
3213
- return {
3214
- error: {
3215
- code: "UNKNOWN_ERROR",
3216
- message: "An unexpected error occurred",
3217
- meta: ["Unknown error type"]
3218
- }
3219
- };
3220
- }
3221
3059
  }
3222
3060
  class IndexResource {
3223
3061
  constructor(client) {
@@ -3354,26 +3192,9 @@ function transformDeleteRequest(sdkRequest) {
3354
3192
  }
3355
3193
  return result;
3356
3194
  }
3357
- class RecordsApiClient {
3195
+ class RecordsApiClient extends BaseApiClient {
3358
3196
  constructor(apiKey, config = {}) {
3359
- this.config = { apiKey, ...config };
3360
- this.httpAdapter = createHttpAdapter();
3361
- const environment = config.environment || "prod";
3362
- const region = config.region || "asia-south1";
3363
- this.baseURL = this.getBaseURL(environment, region);
3364
- }
3365
- getBaseURL(environment, region) {
3366
- const regionConfig = REGION_CONFIGS[region];
3367
- if (!regionConfig) {
3368
- throw new Error(`Unsupported region: ${region}`);
3369
- }
3370
- const envConfig = regionConfig[environment];
3371
- if (!envConfig) {
3372
- throw new Error(
3373
- `Unsupported environment: ${environment} for region: ${region}`
3374
- );
3375
- }
3376
- return `${envConfig.baseURL}/v1`;
3197
+ super(apiKey, config);
3377
3198
  }
3378
3199
  /**
3379
3200
  * Insert a single record
@@ -3649,47 +3470,6 @@ class RecordsApiClient {
3649
3470
  dbId
3650
3471
  );
3651
3472
  }
3652
- buildHeaders() {
3653
- return {
3654
- "Content-Type": "application/json",
3655
- Accept: "application/json",
3656
- "x-boltic-token": this.config.apiKey
3657
- };
3658
- }
3659
- formatErrorResponse(error) {
3660
- if (this.config.debug) {
3661
- console.error("Records API Error:", error);
3662
- }
3663
- if (error && typeof error === "object" && "response" in error) {
3664
- const apiError = error;
3665
- if (apiError.response?.data?.error) {
3666
- return apiError.response.data;
3667
- }
3668
- return {
3669
- error: {
3670
- code: "API_ERROR",
3671
- message: error.message || "Unknown API error",
3672
- meta: [`Status: ${apiError.response?.status || "unknown"}`]
3673
- }
3674
- };
3675
- }
3676
- if (error && typeof error === "object" && "message" in error) {
3677
- return {
3678
- error: {
3679
- code: "CLIENT_ERROR",
3680
- message: error.message,
3681
- meta: ["Client-side error occurred"]
3682
- }
3683
- };
3684
- }
3685
- return {
3686
- error: {
3687
- code: "UNKNOWN_ERROR",
3688
- message: "An unexpected error occurred",
3689
- meta: ["Unknown error type"]
3690
- }
3691
- };
3692
- }
3693
3473
  }
3694
3474
  class RecordResource {
3695
3475
  constructor(client) {
@@ -4273,90 +4053,10 @@ const SQL_ENDPOINTS = {
4273
4053
  const buildSqlEndpointPath = (endpoint, params = {}) => {
4274
4054
  let path = endpoint.path;
4275
4055
  Object.entries(params).forEach(([key, value]) => {
4276
- path = path.replace(`{${key}}`, encodeURIComponent(value));
4277
- });
4278
- return path;
4279
- };
4280
- class BaseApiClient {
4281
- constructor(apiKey, config = {}) {
4282
- this.config = { apiKey, ...config };
4283
- this.httpAdapter = createHttpAdapter();
4284
- const environment = config.environment || "prod";
4285
- const region = config.region || "asia-south1";
4286
- this.baseURL = this.getBaseURL(environment, region);
4287
- }
4288
- getBaseURL(environment, region) {
4289
- const regionConfig = REGION_CONFIGS[region];
4290
- if (!regionConfig) {
4291
- throw new Error(`Unsupported region: ${region}`);
4292
- }
4293
- const envConfig = regionConfig[environment];
4294
- if (!envConfig) {
4295
- throw new Error(
4296
- `Unsupported environment: ${environment} for region: ${region}`
4297
- );
4298
- }
4299
- return `${envConfig.baseURL}/v1`;
4300
- }
4301
- buildHeaders() {
4302
- return {
4303
- "Content-Type": "application/json",
4304
- Accept: "application/json",
4305
- "x-boltic-token": this.config.apiKey,
4306
- ...this.config.headers
4307
- };
4308
- }
4309
- formatErrorResponse(error, prefix = "API") {
4310
- if (this.config.debug) {
4311
- console.error(`${prefix} Error:`, error);
4312
- }
4313
- if (error && typeof error === "object" && "response" in error) {
4314
- const apiError = error;
4315
- if (apiError.response?.data?.error) {
4316
- return apiError.response.data;
4317
- }
4318
- return {
4319
- error: {
4320
- code: `${prefix}_ERROR`,
4321
- message: error.message || `Unknown ${prefix} error`,
4322
- meta: [`Status: ${apiError.response?.status || "unknown"}`]
4323
- }
4324
- };
4325
- }
4326
- if (error && typeof error === "object" && "message" in error) {
4327
- return {
4328
- error: {
4329
- code: `${prefix}_CLIENT_ERROR`,
4330
- message: error.message,
4331
- meta: [`${prefix} client-side error occurred`]
4332
- }
4333
- };
4334
- }
4335
- return {
4336
- error: {
4337
- code: `${prefix}_UNKNOWN_ERROR`,
4338
- message: `An unexpected ${prefix} error occurred`,
4339
- meta: [`Unknown ${prefix} error type`]
4340
- }
4341
- };
4342
- }
4343
- // Security methods to prevent API key exposure
4344
- toString() {
4345
- return `${this.constructor.name} { environment: "${this.config.environment || "prod"}", debug: ${this.config.debug || false} }`;
4346
- }
4347
- toJSON() {
4348
- const safeConfig = { ...this.config };
4349
- delete safeConfig.apiKey;
4350
- return {
4351
- client: this.constructor.name,
4352
- config: safeConfig
4353
- };
4354
- }
4355
- // Custom inspect method for Node.js console logging
4356
- [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
4357
- return this.toString();
4358
- }
4359
- }
4056
+ path = path.replace(`{${key}}`, encodeURIComponent(value));
4057
+ });
4058
+ return path;
4059
+ };
4360
4060
  class SqlApiClient extends BaseApiClient {
4361
4061
  constructor(apiKey, config = {}) {
4362
4062
  super(apiKey, config);
@@ -4794,6 +4494,508 @@ class TableBuilder {
4794
4494
  function createTableBuilder(options, tablesApiClient) {
4795
4495
  return new TableBuilder(options, tablesApiClient);
4796
4496
  }
4497
+ const POLLING_INTERVAL_MS = 1e3;
4498
+ const MAX_POLLING_ATTEMPTS = 30;
4499
+ const SCHEMA_TYPE_MAPPING = {
4500
+ string: { type: "string", fallback_value: "" },
4501
+ number: { type: "number", fallback_value: "" },
4502
+ boolean: { type: "boolean", secondary_type: "string", fallback_value: "" },
4503
+ int: { type: "number", fallback_value: "" },
4504
+ integer: { type: "number", fallback_value: "" },
4505
+ "date-time": { type: "date-time", secondary_type: "string", fallback_value: "" },
4506
+ date: { type: "date", secondary_type: "string", fallback_value: "" },
4507
+ json: { type: "object", fallback_value: {} },
4508
+ text: { type: "string", fallback_value: "" },
4509
+ email: { type: "string", fallback_value: "" },
4510
+ password: { type: "string", fallback_value: "" },
4511
+ url: { type: "string", fallback_value: "" },
4512
+ textarea: { type: "string", fallback_value: "" },
4513
+ select: { type: "string", fallback_value: "" },
4514
+ multiselect: { type: "string", fallback_value: "" },
4515
+ autocomplete: { type: "array", fallback_value: [] },
4516
+ radio: { type: "string", fallback_value: "" },
4517
+ radiobuttons: { type: "string", fallback_value: "" },
4518
+ checkbox: { type: "array", fallback_value: [] },
4519
+ toggle: { type: "boolean", fallback_value: "" },
4520
+ hidden: { type: "string", fallback_value: "" },
4521
+ slider: { type: "number", fallback_value: "" },
4522
+ datepicker: { type: "string", fallback_value: "" },
4523
+ phoneinput: { type: "string", fallback_value: "" },
4524
+ time: { type: "string", fallback_value: "" },
4525
+ datetime: { type: "string", fallback_value: "" },
4526
+ code: { type: "string", fallback_value: "" },
4527
+ multitext: { type: "array", fallback_value: [] },
4528
+ array: { type: "array", fallback_value: [] },
4529
+ keyvalue: { type: "object", fallback_value: {} },
4530
+ object: { type: "object", fallback_value: {} },
4531
+ phone: { type: "string", fallback_value: "" },
4532
+ "number[]": { type: "string", fallback_value: "" },
4533
+ "number []": { type: "string", fallback_value: "" },
4534
+ "object | any": { type: "string", fallback_value: "" }
4535
+ };
4536
+ const WORKFLOW_ENDPOINTS = {
4537
+ executeActivity: {
4538
+ path: "/workflows/execute/activity",
4539
+ method: "POST",
4540
+ authenticated: true
4541
+ },
4542
+ getExecutionById: {
4543
+ path: "/workflows/run/{run_id}",
4544
+ method: "GET",
4545
+ authenticated: true
4546
+ },
4547
+ getIntegrations: {
4548
+ path: "/integrations",
4549
+ method: "GET",
4550
+ authenticated: true
4551
+ },
4552
+ getCredentials: {
4553
+ path: "/integrations/entity/{entity}",
4554
+ method: "GET",
4555
+ authenticated: true
4556
+ },
4557
+ getIntegrationResource: {
4558
+ path: "/integrations/{integration_slug}/schema",
4559
+ method: "GET",
4560
+ authenticated: true
4561
+ },
4562
+ getIntegrationForm: {
4563
+ path: "/integrations/{integration_slug}/fields",
4564
+ method: "GET",
4565
+ authenticated: true
4566
+ }
4567
+ };
4568
+ function buildWorkflowEndpointPath(endpoint, params = {}) {
4569
+ let path = endpoint.path;
4570
+ for (const [key, value] of Object.entries(params)) {
4571
+ path = path.replace(`{${key}}`, value);
4572
+ }
4573
+ return path;
4574
+ }
4575
+ class WorkflowApiClient extends BaseApiClient {
4576
+ constructor(apiKey, config = {}) {
4577
+ super(apiKey, config, SERVICE_PATHS.WORKFLOW_TEMPORAL);
4578
+ this.integrationBaseURL = this.resolveAdditionalServiceURL(
4579
+ SERVICE_PATHS.INTEGRATION
4580
+ );
4581
+ }
4582
+ /**
4583
+ * Execute a workflow activity.
4584
+ *
4585
+ * @param body - The execute-activity request body
4586
+ */
4587
+ async executeActivity(body) {
4588
+ try {
4589
+ const endpoint = WORKFLOW_ENDPOINTS.executeActivity;
4590
+ const url = `${this.baseURL}${endpoint.path}`;
4591
+ const response = await this.httpAdapter.request({
4592
+ url,
4593
+ method: endpoint.method,
4594
+ headers: this.buildHeaders(),
4595
+ data: body,
4596
+ timeout: this.config.timeout
4597
+ });
4598
+ return response.data;
4599
+ } catch (error) {
4600
+ return this.formatErrorResponse(error, "WORKFLOW");
4601
+ }
4602
+ }
4603
+ /**
4604
+ * Fetch the result of a workflow execution by its run ID.
4605
+ *
4606
+ * @param runId - The execution run ID returned by `executeActivity`
4607
+ */
4608
+ async getExecutionById(runId) {
4609
+ try {
4610
+ const endpoint = WORKFLOW_ENDPOINTS.getExecutionById;
4611
+ const path = buildWorkflowEndpointPath(endpoint, { run_id: runId });
4612
+ const url = `${this.baseURL}${path}`;
4613
+ const response = await this.httpAdapter.request({
4614
+ url,
4615
+ method: endpoint.method,
4616
+ headers: this.buildHeaders(),
4617
+ timeout: this.config.timeout
4618
+ });
4619
+ return response.data;
4620
+ } catch (error) {
4621
+ return this.formatErrorResponse(error, "WORKFLOW");
4622
+ }
4623
+ }
4624
+ /**
4625
+ * Fetch the list of available integrations.
4626
+ *
4627
+ * @param params - Optional pagination parameters
4628
+ */
4629
+ async getIntegrations(params = {}) {
4630
+ try {
4631
+ const endpoint = WORKFLOW_ENDPOINTS.getIntegrations;
4632
+ const query = new URLSearchParams({
4633
+ page: String(params.page ?? 1),
4634
+ per_page: String(params.per_page ?? 999)
4635
+ });
4636
+ const url = `${this.baseURL}${endpoint.path}?${query.toString()}`;
4637
+ const response = await this.httpAdapter.request({
4638
+ url,
4639
+ method: endpoint.method,
4640
+ headers: this.buildHeaders(),
4641
+ timeout: this.config.timeout
4642
+ });
4643
+ return response.data;
4644
+ } catch (error) {
4645
+ return this.formatErrorResponse(error, "WORKFLOW");
4646
+ }
4647
+ }
4648
+ /**
4649
+ * Fetch credentials for a given integration entity.
4650
+ *
4651
+ * @param params - Entity name (required) and optional pagination
4652
+ */
4653
+ async getCredentials(params) {
4654
+ try {
4655
+ const endpoint = WORKFLOW_ENDPOINTS.getCredentials;
4656
+ const path = buildWorkflowEndpointPath(endpoint, {
4657
+ entity: params.entity.toUpperCase()
4658
+ });
4659
+ const query = new URLSearchParams({
4660
+ current_page: String(params.current_page ?? 1),
4661
+ page_size: String(params.page_size ?? 999)
4662
+ });
4663
+ const url = `${this.integrationBaseURL}${path}?${query.toString()}`;
4664
+ const response = await this.httpAdapter.request({
4665
+ url,
4666
+ method: endpoint.method,
4667
+ headers: this.buildHeaders(),
4668
+ timeout: this.config.timeout
4669
+ });
4670
+ return response.data;
4671
+ } catch (error) {
4672
+ return this.formatErrorResponse(error, "INTEGRATION");
4673
+ }
4674
+ }
4675
+ /**
4676
+ * Fetch the resource/operation schema for an integration.
4677
+ *
4678
+ * @param params - Integration slug identifier
4679
+ */
4680
+ async getIntegrationResource(params) {
4681
+ try {
4682
+ const endpoint = WORKFLOW_ENDPOINTS.getIntegrationResource;
4683
+ const path = buildWorkflowEndpointPath(endpoint, {
4684
+ integration_slug: params.integration_slug
4685
+ });
4686
+ const url = `${this.baseURL}${path}`;
4687
+ const response = await this.httpAdapter.request({
4688
+ url,
4689
+ method: endpoint.method,
4690
+ headers: this.buildHeaders(),
4691
+ timeout: this.config.timeout
4692
+ });
4693
+ return response.data;
4694
+ } catch (error) {
4695
+ return this.formatErrorResponse(error, "WORKFLOW");
4696
+ }
4697
+ }
4698
+ /**
4699
+ * Fetch the form schema (fields) for a specific integration resource + operation.
4700
+ *
4701
+ * @param params - Integration slug, resource, operation, and credential secret
4702
+ */
4703
+ async getIntegrationForm(params) {
4704
+ try {
4705
+ const endpoint = WORKFLOW_ENDPOINTS.getIntegrationForm;
4706
+ const path = buildWorkflowEndpointPath(endpoint, {
4707
+ integration_slug: params.integration_slug
4708
+ });
4709
+ const query = new URLSearchParams({
4710
+ resource: params.resource,
4711
+ operation: params.operation,
4712
+ // getFormOnly: String(params.getFormOnly ?? true),
4713
+ secret: params.secret
4714
+ });
4715
+ const url = `${this.baseURL}${path}?${query.toString()}`;
4716
+ const response = await this.httpAdapter.request({
4717
+ url,
4718
+ method: endpoint.method,
4719
+ headers: this.buildHeaders(),
4720
+ timeout: this.config.timeout
4721
+ });
4722
+ return response.data;
4723
+ } catch (error) {
4724
+ return this.formatErrorResponse(error, "WORKFLOW");
4725
+ }
4726
+ }
4727
+ }
4728
+ const FORM_META_FIELDS = /* @__PURE__ */ new Set(["resource", "operation"]);
4729
+ function getSchemaMapping(displayType) {
4730
+ return SCHEMA_TYPE_MAPPING[displayType] ?? {
4731
+ type: "string",
4732
+ fallback_value: ""
4733
+ };
4734
+ }
4735
+ function transformFormToDefaults(fields, skipFields = FORM_META_FIELDS) {
4736
+ const result = {};
4737
+ for (const field of fields) {
4738
+ if (skipFields.has(field.name)) continue;
4739
+ const displayType = field.meta?.displayType || "text";
4740
+ const mapping = getSchemaMapping(displayType);
4741
+ result[field.name] = field.meta?.value !== void 0 ? field.meta.value : mapping.fallback_value;
4742
+ }
4743
+ return result;
4744
+ }
4745
+ function transformFormToJsonSchema(fields, skipFields = FORM_META_FIELDS) {
4746
+ const properties = {};
4747
+ for (const field of fields) {
4748
+ if (skipFields.has(field.name)) continue;
4749
+ const displayType = field.meta?.displayType || "text";
4750
+ const mapping = getSchemaMapping(displayType);
4751
+ const isRequired = field.meta?.validation?.required ?? false;
4752
+ const defaultValue = field.meta?.value !== void 0 ? field.meta.value : mapping.fallback_value;
4753
+ const prop = {
4754
+ type: mapping.type,
4755
+ required: isRequired,
4756
+ default: defaultValue
4757
+ };
4758
+ if (field.meta?.description) {
4759
+ prop.description = field.meta.description;
4760
+ }
4761
+ if (field.meta?.options && Array.isArray(field.meta.options) && field.meta.options.length > 0) {
4762
+ prop.enum = field.meta.options.map((opt) => opt.value);
4763
+ }
4764
+ properties[field.name] = prop;
4765
+ }
4766
+ return { type: "object", properties };
4767
+ }
4768
+ function buildDefaultResultPayload() {
4769
+ return {
4770
+ payload: {},
4771
+ global_variables: {}
4772
+ };
4773
+ }
4774
+ function buildExecuteActivityBody(params) {
4775
+ const node = {
4776
+ data: {
4777
+ type: params.data.type,
4778
+ name: params.data.name,
4779
+ properties: params.data.properties
4780
+ }
4781
+ };
4782
+ return {
4783
+ nodes: [node],
4784
+ result: params.result ?? buildDefaultResultPayload()
4785
+ };
4786
+ }
4787
+ function sleep(ms) {
4788
+ return new Promise((resolve) => setTimeout(resolve, ms));
4789
+ }
4790
+ class WorkflowResource extends BaseResource {
4791
+ constructor(client) {
4792
+ super(client, "/workflows");
4793
+ const config = client.getConfig();
4794
+ this.apiClient = new WorkflowApiClient(config.apiKey, {
4795
+ environment: config.environment,
4796
+ region: config.region,
4797
+ timeout: config.timeout,
4798
+ debug: config.debug
4799
+ });
4800
+ }
4801
+ /**
4802
+ * Execute a workflow integration activity.
4803
+ *
4804
+ * When `executeOnly` is `true`, returns the immediate API response.
4805
+ * When `executeOnly` is `false` (default), polls until a terminal state
4806
+ * is reached and returns the final execution result.
4807
+ *
4808
+ * @param params - Execution parameters
4809
+ * @returns The execute response or the final polled result
4810
+ *
4811
+ * @example
4812
+ * ```typescript
4813
+ * const result = await client.workflow.executeIntegration({
4814
+ * data: { type: 'apiActivity', name: 'api1', properties: { method: 'get', endpoint: '...' } },
4815
+ * });
4816
+ *
4817
+ * const fire = await client.workflow.executeIntegration({
4818
+ * data: { type: 'apiActivity', name: 'api1', properties: { method: 'get', endpoint: '...' } },
4819
+ * executeOnly: true,
4820
+ * });
4821
+ * ```
4822
+ */
4823
+ async executeIntegration(params) {
4824
+ const body = buildExecuteActivityBody(params);
4825
+ const executeResult = await this.apiClient.executeActivity(body);
4826
+ if (isErrorResponse(executeResult)) {
4827
+ return executeResult;
4828
+ }
4829
+ if (params.executeOnly) {
4830
+ return executeResult;
4831
+ }
4832
+ const executionId = executeResult.data?.execution_id;
4833
+ if (!executionId) {
4834
+ return {
4835
+ error: {
4836
+ code: "MISSING_EXECUTION_ID",
4837
+ message: "Execute API response did not contain an execution_id",
4838
+ meta: []
4839
+ }
4840
+ };
4841
+ }
4842
+ return this.pollExecution(executionId);
4843
+ }
4844
+ /**
4845
+ * Retrieve the result of a workflow execution by its run/execution ID.
4846
+ *
4847
+ * @param executionId - The execution run ID
4848
+ * @returns The execution data or an error response
4849
+ *
4850
+ * @example
4851
+ * ```typescript
4852
+ * const result = await client.workflow.getIntegrationExecuteById('run-uuid');
4853
+ * ```
4854
+ */
4855
+ async getIntegrationExecuteById(executionId) {
4856
+ return this.apiClient.getExecutionById(executionId);
4857
+ }
4858
+ /**
4859
+ * Fetch the list of available integrations.
4860
+ *
4861
+ * @param params - Optional pagination parameters (`page`, `per_page`)
4862
+ * @returns The integrations list or an error response
4863
+ *
4864
+ * @example
4865
+ * ```typescript
4866
+ * const list = await client.workflow.getIntegrations();
4867
+ * ```
4868
+ */
4869
+ async getIntegrations(params = {}) {
4870
+ return this.apiClient.getIntegrations(params);
4871
+ }
4872
+ /**
4873
+ * Fetch credentials for a given integration entity.
4874
+ *
4875
+ * @param params - Entity name (required), optional `current_page` and `page_size`
4876
+ * @returns The credentials list or an error response
4877
+ *
4878
+ * @example
4879
+ * ```typescript
4880
+ * const creds = await client.workflow.getCredentials({ entity: 'freshsales' });
4881
+ * ```
4882
+ */
4883
+ async getCredentials(params) {
4884
+ return this.apiClient.getCredentials(params);
4885
+ }
4886
+ /**
4887
+ * Fetch the resource/operation schema for an integration.
4888
+ *
4889
+ * Returns the available resources and operations supported by the
4890
+ * specified integration (e.g. which resources like "task", "project"
4891
+ * are available and what operations can be performed on them).
4892
+ *
4893
+ * @param params - Integration slug identifier
4894
+ * @returns The integration resource schema or an error response
4895
+ *
4896
+ * @example
4897
+ * ```typescript
4898
+ * const schema = await client.workflow.getIntegrationResource({
4899
+ * integration_slug: 'blt-int.asana',
4900
+ * });
4901
+ * ```
4902
+ */
4903
+ async getIntegrationResource(params) {
4904
+ return this.apiClient.getIntegrationResource(params);
4905
+ }
4906
+ /**
4907
+ * Fetch the form schema (fields) for a specific integration resource + operation.
4908
+ *
4909
+ * By default, returns a flat JSON object with default/fallback values
4910
+ * for each input field. Set `asJsonSchema: true` to get a JSON Schema
4911
+ * object describing the expected input shape instead.
4912
+ *
4913
+ * Fields like `resource` and `operation` are automatically excluded
4914
+ * since they are already handled by the SDK parameters. The `secret`
4915
+ * field is included and populated with the value from `params.secret`.
4916
+ *
4917
+ * @param params - Integration slug, resource, operation, credential secret, and format flag
4918
+ * @returns Transformed form data or an error response
4919
+ *
4920
+ * @example
4921
+ * ```typescript
4922
+ * // Get flat defaults: { name: '', workspace: [], team: '', ... }
4923
+ * const defaults = await client.workflow.getIntegrationForm({
4924
+ * integration_slug: 'blt-int.asana',
4925
+ * resource: 'project',
4926
+ * operation: 'create',
4927
+ * secret: 'credential-secret-here',
4928
+ * });
4929
+ *
4930
+ * // Get JSON Schema: { type: 'object', properties: { name: { type: 'string', ... } } }
4931
+ * const schema = await client.workflow.getIntegrationForm({
4932
+ * integration_slug: 'blt-int.asana',
4933
+ * resource: 'project',
4934
+ * operation: 'create',
4935
+ * secret: 'credential-secret-here',
4936
+ * asJsonSchema: true,
4937
+ * });
4938
+ * ```
4939
+ */
4940
+ async getIntegrationForm(params) {
4941
+ const rawResult = await this.apiClient.getIntegrationForm(params);
4942
+ console.log("rawResult", JSON.stringify(rawResult, null, 2));
4943
+ if (isErrorResponse(rawResult)) {
4944
+ return rawResult;
4945
+ }
4946
+ const configuration = rawResult.data?.parameters || rawResult.data;
4947
+ const fields = configuration ?? [];
4948
+ const transformed = params.asJsonSchema ? transformFormToJsonSchema(fields) : transformFormToDefaults(fields);
4949
+ if (params.asJsonSchema) {
4950
+ const schema = transformed;
4951
+ if (schema.properties.secret) {
4952
+ schema.properties.secret.default = params.secret;
4953
+ }
4954
+ } else {
4955
+ const defaults = transformed;
4956
+ if ("secret" in defaults) {
4957
+ defaults.secret = params.secret;
4958
+ }
4959
+ }
4960
+ return {
4961
+ data: transformed,
4962
+ message: rawResult.message
4963
+ };
4964
+ }
4965
+ /**
4966
+ * Internal polling loop.
4967
+ * Repeatedly calls `getExecutionById` until the response `data` object is
4968
+ * non-empty (execution finished) or max attempts are exhausted.
4969
+ */
4970
+ async pollExecution(executionId) {
4971
+ const debug = this.client.getConfig().debug;
4972
+ for (let attempt = 0; attempt < MAX_POLLING_ATTEMPTS; attempt++) {
4973
+ const result = await this.apiClient.getExecutionById(executionId);
4974
+ if (isErrorResponse(result)) {
4975
+ return result;
4976
+ }
4977
+ if (result.data && Object.keys(result.data).length > 0) {
4978
+ if (debug) {
4979
+ console.log(
4980
+ `[WorkflowResource] Execution ${executionId} completed after ${attempt + 1} poll(s)`
4981
+ );
4982
+ }
4983
+ return result;
4984
+ }
4985
+ await sleep(POLLING_INTERVAL_MS);
4986
+ }
4987
+ return {
4988
+ error: {
4989
+ code: "EXECUTION_TIMEOUT",
4990
+ message: `Execution ${executionId} did not complete within ${MAX_POLLING_ATTEMPTS} polling attempts`,
4991
+ meta: [
4992
+ `execution_id: ${executionId}`,
4993
+ `max_attempts: ${MAX_POLLING_ATTEMPTS}`
4994
+ ]
4995
+ }
4996
+ };
4997
+ }
4998
+ }
4797
4999
  class BolticClient {
4798
5000
  constructor(apiKey, options = {}) {
4799
5001
  this.currentDatabase = null;
@@ -4816,6 +5018,7 @@ class BolticClient {
4816
5018
  this.sqlResource = new SqlResource(this.baseClient);
4817
5019
  this.indexResource = new IndexResource(this.baseClient);
4818
5020
  this.databaseResource = new DatabaseResource(this.baseClient);
5021
+ this.workflowResource = new WorkflowResource(this.baseClient);
4819
5022
  this.currentDatabase = null;
4820
5023
  }
4821
5024
  /**
@@ -4970,6 +5173,33 @@ class BolticClient {
4970
5173
  executeSQL: (query) => this.sqlResource.executeSQL(query, dbId)
4971
5174
  };
4972
5175
  }
5176
+ /**
5177
+ * Workflow integration operations.
5178
+ *
5179
+ * @example
5180
+ * ```typescript
5181
+ * // Execute and poll for result
5182
+ * const result = await client.workflow.executeIntegration({
5183
+ * nodes: [{ id: 'api1', data: { ... }, activity_data: { ... } }],
5184
+ * });
5185
+ *
5186
+ * // Get execution result by ID
5187
+ * const exec = await client.workflow.getIntegrationExecuteById('run-uuid');
5188
+ *
5189
+ * // List integrations
5190
+ * const integrations = await client.workflow.getIntegrations();
5191
+ * ```
5192
+ */
5193
+ get workflow() {
5194
+ return {
5195
+ executeIntegration: (params) => this.workflowResource.executeIntegration(params),
5196
+ getIntegrationExecuteById: (executionId) => this.workflowResource.getIntegrationExecuteById(executionId),
5197
+ getIntegrations: (params) => this.workflowResource.getIntegrations(params),
5198
+ getCredentials: (params) => this.workflowResource.getCredentials(params),
5199
+ getIntegrationResource: (params) => this.workflowResource.getIntegrationResource(params),
5200
+ getIntegrationForm: (params) => this.workflowResource.getIntegrationForm(params)
5201
+ };
5202
+ }
4973
5203
  // SQL resource access for testing
4974
5204
  getSqlResource() {
4975
5205
  return this.sqlResource;
@@ -5052,6 +5282,7 @@ class BolticClient {
5052
5282
  this.sqlResource = new SqlResource(this.baseClient);
5053
5283
  this.indexResource = new IndexResource(this.baseClient);
5054
5284
  this.databaseResource = new DatabaseResource(this.baseClient);
5285
+ this.workflowResource = new WorkflowResource(this.baseClient);
5055
5286
  }
5056
5287
  // Security methods to prevent API key exposure
5057
5288
  toString() {
@@ -5080,13 +5311,18 @@ const VERSION = "1.0.0";
5080
5311
  export {
5081
5312
  AuthManager$1 as AuthManager,
5082
5313
  BolticClient,
5314
+ SERVICE_PATHS,
5083
5315
  VERSION,
5316
+ WorkflowResource,
5084
5317
  createClient,
5085
5318
  createErrorWithContext$1 as createErrorWithContext,
5086
5319
  formatError$1 as formatError,
5087
5320
  getHttpStatusCode$1 as getHttpStatusCode,
5088
5321
  isErrorResponse,
5089
5322
  isListResponse,
5090
- isNetworkError
5323
+ isNetworkError,
5324
+ resolveServiceURL,
5325
+ transformFormToDefaults,
5326
+ transformFormToJsonSchema
5091
5327
  };
5092
5328
  //# sourceMappingURL=sdk.mjs.map