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