@boltic/sdk 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +191 -146
- package/dist/databases/index.d.ts +214 -93
- package/dist/databases/index.js +1 -1
- package/dist/databases/index.js.map +1 -1
- package/dist/databases/index.mjs +1 -1
- package/dist/databases/index.mjs.map +1 -1
- package/dist/databases/test-client-BEAX5vfC.mjs +2 -0
- package/dist/databases/test-client-BEAX5vfC.mjs.map +1 -0
- package/dist/databases/test-client-BgkvBtst.js +2 -0
- package/dist/databases/test-client-BgkvBtst.js.map +1 -0
- package/dist/databases/testing.d.ts +204 -94
- package/dist/databases/testing.js +1 -1
- package/dist/databases/testing.mjs +1 -1
- package/dist/sdk.js +1531 -765
- package/dist/sdk.js.map +1 -1
- package/dist/sdk.mjs +1532 -766
- package/dist/sdk.mjs.map +1 -1
- package/dist/types/index.d.ts +916 -70
- package/package.json +2 -1
- package/dist/databases/test-client-Bo_BCApL.js +0 -2
- package/dist/databases/test-client-Bo_BCApL.js.map +0 -1
- package/dist/databases/test-client-C9T839dW.mjs +0 -2
- package/dist/databases/test-client-C9T839dW.mjs.map +0 -1
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,157 @@ 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
|
+
SERVERLESS: "/service/panel/serverless/v1.0"
|
|
552
|
+
};
|
|
553
|
+
class BaseApiClient {
|
|
554
|
+
constructor(apiKey, config = {}, servicePath = SERVICE_PATHS.DATABASES) {
|
|
555
|
+
this.config = { apiKey, ...config };
|
|
556
|
+
this.httpAdapter = createHttpAdapter();
|
|
557
|
+
this.environment = config.environment || "prod";
|
|
558
|
+
this.region = config.region || "asia-south1";
|
|
559
|
+
this.baseURL = resolveServiceURL(
|
|
560
|
+
this.region,
|
|
561
|
+
this.environment,
|
|
562
|
+
servicePath
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Resolve a secondary service URL using the same region/environment
|
|
567
|
+
* but a different service path.
|
|
568
|
+
*/
|
|
569
|
+
resolveAdditionalServiceURL(servicePath) {
|
|
570
|
+
return resolveServiceURL(this.region, this.environment, servicePath);
|
|
571
|
+
}
|
|
572
|
+
buildHeaders() {
|
|
573
|
+
return {
|
|
574
|
+
"Content-Type": "application/json",
|
|
575
|
+
Accept: "application/json",
|
|
576
|
+
"x-boltic-token": this.config.apiKey,
|
|
577
|
+
...this.config.headers
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
formatErrorResponse(error, prefix = "API") {
|
|
581
|
+
if (this.config.debug) {
|
|
582
|
+
console.error(`[${this.constructor.name}] ${prefix} Error:`, error);
|
|
583
|
+
}
|
|
584
|
+
if (error && typeof error === "object" && "response" in error) {
|
|
585
|
+
const apiError = error;
|
|
586
|
+
if (apiError.response?.data?.error) {
|
|
587
|
+
return apiError.response.data;
|
|
588
|
+
}
|
|
589
|
+
return {
|
|
590
|
+
error: {
|
|
591
|
+
code: `${prefix}_ERROR`,
|
|
592
|
+
message: error instanceof Error ? error.message : `Unknown ${prefix} error`,
|
|
593
|
+
meta: [`Status: ${apiError.response?.status || "unknown"}`]
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
if (error instanceof Error) {
|
|
598
|
+
return {
|
|
599
|
+
error: {
|
|
600
|
+
code: `${prefix}_CLIENT_ERROR`,
|
|
601
|
+
message: error.message,
|
|
602
|
+
meta: []
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
return {
|
|
607
|
+
error: {
|
|
608
|
+
code: `${prefix}_UNKNOWN_ERROR`,
|
|
609
|
+
message: `An unexpected ${prefix} error occurred`,
|
|
610
|
+
meta: []
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
toString() {
|
|
615
|
+
return `${this.constructor.name} { environment: "${this.config.environment || "prod"}", debug: ${this.config.debug || false} }`;
|
|
616
|
+
}
|
|
617
|
+
toJSON() {
|
|
618
|
+
const safeConfig = { ...this.config };
|
|
619
|
+
delete safeConfig.apiKey;
|
|
620
|
+
return {
|
|
621
|
+
client: this.constructor.name,
|
|
622
|
+
config: safeConfig
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
|
|
626
|
+
return this.toString();
|
|
627
|
+
}
|
|
628
|
+
}
|
|
483
629
|
class InterceptorManagerImpl {
|
|
484
630
|
constructor() {
|
|
485
631
|
this.requestInterceptors = /* @__PURE__ */ new Map();
|
|
@@ -664,46 +810,88 @@ class BaseClient {
|
|
|
664
810
|
return { ...this.config };
|
|
665
811
|
}
|
|
666
812
|
}
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
813
|
+
class BaseResource {
|
|
814
|
+
constructor(client, basePath) {
|
|
815
|
+
this.client = client;
|
|
816
|
+
this.basePath = basePath;
|
|
817
|
+
}
|
|
818
|
+
getBasePath() {
|
|
819
|
+
return this.basePath;
|
|
820
|
+
}
|
|
821
|
+
async makeRequest(method, path, data, options) {
|
|
822
|
+
const url = `${this.basePath}${path}`;
|
|
823
|
+
try {
|
|
824
|
+
let response;
|
|
825
|
+
switch (method) {
|
|
826
|
+
case "GET":
|
|
827
|
+
response = await this.client.get(url, {
|
|
828
|
+
params: options?.params
|
|
829
|
+
});
|
|
830
|
+
break;
|
|
831
|
+
case "POST":
|
|
832
|
+
response = await this.client.post(url, data, {
|
|
833
|
+
params: options?.params
|
|
834
|
+
});
|
|
835
|
+
break;
|
|
836
|
+
case "PUT":
|
|
837
|
+
response = await this.client.put(url, data, {
|
|
838
|
+
params: options?.params
|
|
839
|
+
});
|
|
840
|
+
break;
|
|
841
|
+
case "PATCH":
|
|
842
|
+
response = await this.client.patch(url, data, {
|
|
843
|
+
params: options?.params
|
|
844
|
+
});
|
|
845
|
+
break;
|
|
846
|
+
case "DELETE":
|
|
847
|
+
response = await this.client.delete(url, {
|
|
848
|
+
params: options?.params
|
|
849
|
+
});
|
|
850
|
+
break;
|
|
851
|
+
}
|
|
852
|
+
return response.data;
|
|
853
|
+
} catch (error) {
|
|
854
|
+
return {
|
|
855
|
+
error: {
|
|
856
|
+
code: "CLIENT_ERROR",
|
|
857
|
+
message: formatError(error),
|
|
858
|
+
meta: ["Request failed"]
|
|
859
|
+
}
|
|
860
|
+
};
|
|
685
861
|
}
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
862
|
+
}
|
|
863
|
+
buildQueryParams(options = {}) {
|
|
864
|
+
const params = {};
|
|
865
|
+
if (options.fields?.length) {
|
|
866
|
+
params.fields = options.fields.join(",");
|
|
867
|
+
}
|
|
868
|
+
if (options.sort?.length) {
|
|
869
|
+
params.sort = options.sort.map((s) => `${s.field}:${s.order}`).join(",");
|
|
870
|
+
}
|
|
871
|
+
if (options.limit !== void 0) {
|
|
872
|
+
params.limit = options.limit;
|
|
873
|
+
}
|
|
874
|
+
if (options.offset !== void 0) {
|
|
875
|
+
params.offset = options.offset;
|
|
876
|
+
}
|
|
877
|
+
if (options.where) {
|
|
878
|
+
Object.entries(options.where).forEach(([key, value]) => {
|
|
879
|
+
if (value !== void 0 && value !== null) {
|
|
880
|
+
params[`where[${key}]`] = typeof value === "object" ? JSON.stringify(value) : value;
|
|
881
|
+
}
|
|
882
|
+
});
|
|
704
883
|
}
|
|
884
|
+
return params;
|
|
705
885
|
}
|
|
706
|
-
|
|
886
|
+
handleResponse(response) {
|
|
887
|
+
if ("error" in response) {
|
|
888
|
+
if (this.client.getConfig().debug) {
|
|
889
|
+
console.error("API Error:", response.error);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
return response;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
707
895
|
class ConfigManager {
|
|
708
896
|
constructor(apiKey, environment = "prod", region = "asia-south1", overrides) {
|
|
709
897
|
const envConfig = REGION_CONFIGS[region][environment];
|
|
@@ -726,7 +914,6 @@ class ConfigManager {
|
|
|
726
914
|
updateConfig(updates) {
|
|
727
915
|
this.config = { ...this.config, ...updates };
|
|
728
916
|
}
|
|
729
|
-
// Security methods to prevent API key exposure
|
|
730
917
|
toString() {
|
|
731
918
|
return `ConfigManager { environment: "${this.config.environment}", region: "${this.config.region}", debug: ${this.config.debug} }`;
|
|
732
919
|
}
|
|
@@ -735,7 +922,6 @@ class ConfigManager {
|
|
|
735
922
|
delete safeConfig.apiKey;
|
|
736
923
|
return safeConfig;
|
|
737
924
|
}
|
|
738
|
-
// Custom inspect method for Node.js console logging
|
|
739
925
|
[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
|
|
740
926
|
return this.toString();
|
|
741
927
|
}
|
|
@@ -922,26 +1108,9 @@ function transformDateFormat(dateFormat) {
|
|
|
922
1108
|
function transformTimeFormat(timeFormat) {
|
|
923
1109
|
return TimeFormatEnum[timeFormat] || timeFormat;
|
|
924
1110
|
}
|
|
925
|
-
class ColumnsApiClient {
|
|
1111
|
+
class ColumnsApiClient extends BaseApiClient {
|
|
926
1112
|
constructor(apiKey, config = {}) {
|
|
927
|
-
|
|
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`;
|
|
1113
|
+
super(apiKey, config);
|
|
945
1114
|
}
|
|
946
1115
|
/**
|
|
947
1116
|
* Create a single column in a table
|
|
@@ -978,7 +1147,7 @@ class ColumnsApiClient {
|
|
|
978
1147
|
const createdColumns = [];
|
|
979
1148
|
for (const column of columns) {
|
|
980
1149
|
const result = await this.createColumn(tableId, column);
|
|
981
|
-
if (
|
|
1150
|
+
if (isErrorResponse(result)) {
|
|
982
1151
|
return result;
|
|
983
1152
|
}
|
|
984
1153
|
createdColumns.push(result.data);
|
|
@@ -1130,7 +1299,7 @@ class ColumnsApiClient {
|
|
|
1130
1299
|
tableId,
|
|
1131
1300
|
apiRequest
|
|
1132
1301
|
);
|
|
1133
|
-
if (
|
|
1302
|
+
if (isErrorResponse(listResult)) {
|
|
1134
1303
|
return listResult;
|
|
1135
1304
|
}
|
|
1136
1305
|
const column = listResult.data[0] || null;
|
|
@@ -1177,7 +1346,7 @@ class ColumnsApiClient {
|
|
|
1177
1346
|
async updateColumnByName(tableId, columnName, updates) {
|
|
1178
1347
|
try {
|
|
1179
1348
|
const findResult = await this.findColumnByName(tableId, columnName);
|
|
1180
|
-
if (
|
|
1349
|
+
if (isErrorResponse(findResult)) {
|
|
1181
1350
|
return findResult;
|
|
1182
1351
|
}
|
|
1183
1352
|
if (!findResult.data) {
|
|
@@ -1211,7 +1380,7 @@ class ColumnsApiClient {
|
|
|
1211
1380
|
async deleteColumnByName(tableId, columnName) {
|
|
1212
1381
|
try {
|
|
1213
1382
|
const findResult = await this.findColumnByName(tableId, columnName);
|
|
1214
|
-
if (
|
|
1383
|
+
if (isErrorResponse(findResult)) {
|
|
1215
1384
|
return findResult;
|
|
1216
1385
|
}
|
|
1217
1386
|
if (!findResult.data) {
|
|
@@ -1228,47 +1397,6 @@ class ColumnsApiClient {
|
|
|
1228
1397
|
return this.formatErrorResponse(error);
|
|
1229
1398
|
}
|
|
1230
1399
|
}
|
|
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
1400
|
}
|
|
1273
1401
|
const TABLE_ENDPOINTS = {
|
|
1274
1402
|
list: {
|
|
@@ -1447,26 +1575,9 @@ function transformFieldDefinition(field) {
|
|
|
1447
1575
|
default_value: field.default_value
|
|
1448
1576
|
};
|
|
1449
1577
|
}
|
|
1450
|
-
class TablesApiClient {
|
|
1578
|
+
class TablesApiClient extends BaseApiClient {
|
|
1451
1579
|
constructor(apiKey, config = {}) {
|
|
1452
|
-
|
|
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`;
|
|
1580
|
+
super(apiKey, config);
|
|
1470
1581
|
}
|
|
1471
1582
|
/**
|
|
1472
1583
|
* Create a new table
|
|
@@ -1589,200 +1700,75 @@ class TablesApiClient {
|
|
|
1589
1700
|
return this.formatErrorResponse(error);
|
|
1590
1701
|
}
|
|
1591
1702
|
}
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1703
|
+
}
|
|
1704
|
+
class TableResource extends BaseResource {
|
|
1705
|
+
constructor(client) {
|
|
1706
|
+
super(client, "/v1/tables");
|
|
1707
|
+
const config = client.getConfig();
|
|
1708
|
+
this.tablesApiClient = new TablesApiClient(config.apiKey, {
|
|
1709
|
+
environment: config.environment,
|
|
1710
|
+
region: config.region,
|
|
1711
|
+
timeout: config.timeout,
|
|
1712
|
+
debug: config.debug,
|
|
1713
|
+
retryAttempts: config.retryAttempts,
|
|
1714
|
+
retryDelay: config.retryDelay,
|
|
1715
|
+
headers: config.headers
|
|
1716
|
+
});
|
|
1599
1717
|
}
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1718
|
+
/**
|
|
1719
|
+
* Create a new table
|
|
1720
|
+
*/
|
|
1721
|
+
async create(data, dbId) {
|
|
1722
|
+
try {
|
|
1723
|
+
const processedData = { ...data };
|
|
1724
|
+
if (data.fields && data.fields.length > 0) {
|
|
1725
|
+
processedData.fields = await this.processFieldsDefaults(data.fields);
|
|
1726
|
+
}
|
|
1727
|
+
const result = await this.tablesApiClient.createTable(
|
|
1728
|
+
processedData,
|
|
1729
|
+
dbId ? { db_id: dbId } : {}
|
|
1730
|
+
);
|
|
1731
|
+
if (isErrorResponse(result)) {
|
|
1732
|
+
throw new ApiError(
|
|
1733
|
+
result.error.message || "Create table failed",
|
|
1734
|
+
400,
|
|
1735
|
+
result.error
|
|
1736
|
+
);
|
|
1737
|
+
}
|
|
1738
|
+
return result;
|
|
1739
|
+
} catch (error) {
|
|
1740
|
+
throw error instanceof ApiError ? error : new ApiError(this.formatError(error), 500);
|
|
1603
1741
|
}
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1742
|
+
}
|
|
1743
|
+
/**
|
|
1744
|
+
* Process fields with defaults for table creation
|
|
1745
|
+
*/
|
|
1746
|
+
async processFieldsDefaults(fields) {
|
|
1747
|
+
const processedFields = [];
|
|
1748
|
+
for (let i = 0; i < fields.length; i++) {
|
|
1749
|
+
const field = fields[i];
|
|
1750
|
+
const processedField = { ...field };
|
|
1751
|
+
if (processedField.is_primary_key === void 0) {
|
|
1752
|
+
processedField.is_primary_key = false;
|
|
1608
1753
|
}
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1754
|
+
if (processedField.is_unique === void 0) {
|
|
1755
|
+
processedField.is_unique = false;
|
|
1756
|
+
}
|
|
1757
|
+
if (processedField.is_nullable === void 0) {
|
|
1758
|
+
processedField.is_nullable = true;
|
|
1759
|
+
}
|
|
1760
|
+
if (processedField.is_indexed === void 0) {
|
|
1761
|
+
processedField.is_indexed = false;
|
|
1762
|
+
}
|
|
1763
|
+
if (processedField.type === "encrypted") {
|
|
1764
|
+
if (processedField.show_decrypted === void 0) {
|
|
1765
|
+
processedField.show_decrypted = false;
|
|
1614
1766
|
}
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
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
|
-
}
|
|
1705
|
-
});
|
|
1706
|
-
}
|
|
1707
|
-
return params;
|
|
1708
|
-
}
|
|
1709
|
-
handleResponse(response) {
|
|
1710
|
-
if ("error" in response) {
|
|
1711
|
-
if (this.client.getConfig().debug) {
|
|
1712
|
-
console.error("API Error:", response.error);
|
|
1713
|
-
}
|
|
1714
|
-
}
|
|
1715
|
-
return response;
|
|
1716
|
-
}
|
|
1717
|
-
}
|
|
1718
|
-
class TableResource extends BaseResource {
|
|
1719
|
-
constructor(client) {
|
|
1720
|
-
super(client, "/v1/tables");
|
|
1721
|
-
const config = client.getConfig();
|
|
1722
|
-
this.tablesApiClient = new TablesApiClient(config.apiKey, {
|
|
1723
|
-
environment: config.environment,
|
|
1724
|
-
region: config.region,
|
|
1725
|
-
timeout: config.timeout,
|
|
1726
|
-
debug: config.debug,
|
|
1727
|
-
retryAttempts: config.retryAttempts,
|
|
1728
|
-
retryDelay: config.retryDelay,
|
|
1729
|
-
headers: config.headers
|
|
1730
|
-
});
|
|
1731
|
-
}
|
|
1732
|
-
/**
|
|
1733
|
-
* Create a new table
|
|
1734
|
-
*/
|
|
1735
|
-
async create(data, dbId) {
|
|
1736
|
-
try {
|
|
1737
|
-
const processedData = { ...data };
|
|
1738
|
-
if (data.fields && data.fields.length > 0) {
|
|
1739
|
-
processedData.fields = await this.processFieldsDefaults(data.fields);
|
|
1740
|
-
}
|
|
1741
|
-
const result = await this.tablesApiClient.createTable(
|
|
1742
|
-
processedData,
|
|
1743
|
-
dbId ? { db_id: dbId } : {}
|
|
1744
|
-
);
|
|
1745
|
-
if (isErrorResponse(result)) {
|
|
1746
|
-
throw new ApiError(
|
|
1747
|
-
result.error.message || "Create table failed",
|
|
1748
|
-
400,
|
|
1749
|
-
result.error
|
|
1750
|
-
);
|
|
1751
|
-
}
|
|
1752
|
-
return result;
|
|
1753
|
-
} catch (error) {
|
|
1754
|
-
throw error instanceof ApiError ? error : new ApiError(this.formatError(error), 500);
|
|
1755
|
-
}
|
|
1756
|
-
}
|
|
1757
|
-
/**
|
|
1758
|
-
* Process fields with defaults for table creation
|
|
1759
|
-
*/
|
|
1760
|
-
async processFieldsDefaults(fields) {
|
|
1761
|
-
const processedFields = [];
|
|
1762
|
-
for (let i = 0; i < fields.length; i++) {
|
|
1763
|
-
const field = fields[i];
|
|
1764
|
-
const processedField = { ...field };
|
|
1765
|
-
if (processedField.is_primary_key === void 0) {
|
|
1766
|
-
processedField.is_primary_key = false;
|
|
1767
|
-
}
|
|
1768
|
-
if (processedField.is_unique === void 0) {
|
|
1769
|
-
processedField.is_unique = false;
|
|
1770
|
-
}
|
|
1771
|
-
if (processedField.is_nullable === void 0) {
|
|
1772
|
-
processedField.is_nullable = true;
|
|
1773
|
-
}
|
|
1774
|
-
if (processedField.is_indexed === void 0) {
|
|
1775
|
-
processedField.is_indexed = false;
|
|
1776
|
-
}
|
|
1777
|
-
if (processedField.type === "encrypted") {
|
|
1778
|
-
if (processedField.show_decrypted === void 0) {
|
|
1779
|
-
processedField.show_decrypted = false;
|
|
1780
|
-
}
|
|
1781
|
-
if (processedField.is_deterministic === void 0) {
|
|
1782
|
-
processedField.is_deterministic = false;
|
|
1783
|
-
}
|
|
1784
|
-
if (processedField.default_value !== void 0 && processedField.default_value !== null) {
|
|
1785
|
-
throw new Error("Encrypted columns do not accept a default value");
|
|
1767
|
+
if (processedField.is_deterministic === void 0) {
|
|
1768
|
+
processedField.is_deterministic = false;
|
|
1769
|
+
}
|
|
1770
|
+
if (processedField.default_value !== void 0 && processedField.default_value !== null) {
|
|
1771
|
+
throw new Error("Encrypted columns do not accept a default value");
|
|
1786
1772
|
}
|
|
1787
1773
|
}
|
|
1788
1774
|
if (processedField.field_order === void 0) {
|
|
@@ -2464,26 +2450,9 @@ const buildDatabaseEndpointPath = (endpoint, params = {}) => {
|
|
|
2464
2450
|
});
|
|
2465
2451
|
return path;
|
|
2466
2452
|
};
|
|
2467
|
-
class DatabasesApiClient {
|
|
2453
|
+
class DatabasesApiClient extends BaseApiClient {
|
|
2468
2454
|
constructor(apiKey, config = {}) {
|
|
2469
|
-
|
|
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`;
|
|
2455
|
+
super(apiKey, config);
|
|
2487
2456
|
}
|
|
2488
2457
|
/**
|
|
2489
2458
|
* Create a new database
|
|
@@ -2495,16 +2464,13 @@ class DatabasesApiClient {
|
|
|
2495
2464
|
const response = await this.httpAdapter.request({
|
|
2496
2465
|
url,
|
|
2497
2466
|
method: endpoint.method,
|
|
2498
|
-
headers:
|
|
2499
|
-
"Content-Type": "application/json",
|
|
2500
|
-
"x-boltic-token": this.config.apiKey
|
|
2501
|
-
},
|
|
2467
|
+
headers: this.buildHeaders(),
|
|
2502
2468
|
data: request,
|
|
2503
2469
|
timeout: this.config.timeout
|
|
2504
2470
|
});
|
|
2505
2471
|
return response.data;
|
|
2506
2472
|
} catch (error) {
|
|
2507
|
-
return this.
|
|
2473
|
+
return this.formatErrorResponse(error);
|
|
2508
2474
|
}
|
|
2509
2475
|
}
|
|
2510
2476
|
/**
|
|
@@ -2530,10 +2496,7 @@ class DatabasesApiClient {
|
|
|
2530
2496
|
const response = await this.httpAdapter.request({
|
|
2531
2497
|
url,
|
|
2532
2498
|
method: endpoint.method,
|
|
2533
|
-
headers:
|
|
2534
|
-
"Content-Type": "application/json",
|
|
2535
|
-
"x-boltic-token": this.config.apiKey
|
|
2536
|
-
},
|
|
2499
|
+
headers: this.buildHeaders(),
|
|
2537
2500
|
data: request,
|
|
2538
2501
|
timeout: this.config.timeout
|
|
2539
2502
|
});
|
|
@@ -2549,7 +2512,7 @@ class DatabasesApiClient {
|
|
|
2549
2512
|
}
|
|
2550
2513
|
return result;
|
|
2551
2514
|
} catch (error) {
|
|
2552
|
-
return this.
|
|
2515
|
+
return this.formatErrorResponse(error);
|
|
2553
2516
|
}
|
|
2554
2517
|
}
|
|
2555
2518
|
/**
|
|
@@ -2563,16 +2526,13 @@ class DatabasesApiClient {
|
|
|
2563
2526
|
const response = await this.httpAdapter.request({
|
|
2564
2527
|
url,
|
|
2565
2528
|
method: endpoint.method,
|
|
2566
|
-
headers:
|
|
2567
|
-
"Content-Type": "application/json",
|
|
2568
|
-
"x-boltic-token": this.config.apiKey
|
|
2569
|
-
},
|
|
2529
|
+
headers: this.buildHeaders(),
|
|
2570
2530
|
data: request,
|
|
2571
2531
|
timeout: this.config.timeout
|
|
2572
2532
|
});
|
|
2573
2533
|
return response.data;
|
|
2574
2534
|
} catch (error) {
|
|
2575
|
-
return this.
|
|
2535
|
+
return this.formatErrorResponse(error);
|
|
2576
2536
|
}
|
|
2577
2537
|
}
|
|
2578
2538
|
/**
|
|
@@ -2586,15 +2546,12 @@ class DatabasesApiClient {
|
|
|
2586
2546
|
const response = await this.httpAdapter.request({
|
|
2587
2547
|
url,
|
|
2588
2548
|
method: endpoint.method,
|
|
2589
|
-
headers:
|
|
2590
|
-
"Content-Type": "application/json",
|
|
2591
|
-
"x-boltic-token": this.config.apiKey
|
|
2592
|
-
},
|
|
2549
|
+
headers: this.buildHeaders(),
|
|
2593
2550
|
timeout: this.config.timeout
|
|
2594
2551
|
});
|
|
2595
2552
|
return response.data;
|
|
2596
2553
|
} catch (error) {
|
|
2597
|
-
return this.
|
|
2554
|
+
return this.formatErrorResponse(error);
|
|
2598
2555
|
}
|
|
2599
2556
|
}
|
|
2600
2557
|
/**
|
|
@@ -2607,10 +2564,7 @@ class DatabasesApiClient {
|
|
|
2607
2564
|
const response = await this.httpAdapter.request({
|
|
2608
2565
|
url,
|
|
2609
2566
|
method: endpoint.method,
|
|
2610
|
-
headers:
|
|
2611
|
-
"Content-Type": "application/json",
|
|
2612
|
-
"x-boltic-token": this.config.apiKey
|
|
2613
|
-
},
|
|
2567
|
+
headers: this.buildHeaders(),
|
|
2614
2568
|
data: request,
|
|
2615
2569
|
timeout: this.config.timeout
|
|
2616
2570
|
});
|
|
@@ -2626,7 +2580,7 @@ class DatabasesApiClient {
|
|
|
2626
2580
|
}
|
|
2627
2581
|
return result;
|
|
2628
2582
|
} catch (error) {
|
|
2629
|
-
return this.
|
|
2583
|
+
return this.formatErrorResponse(error);
|
|
2630
2584
|
}
|
|
2631
2585
|
}
|
|
2632
2586
|
/**
|
|
@@ -2640,70 +2594,13 @@ class DatabasesApiClient {
|
|
|
2640
2594
|
const response = await this.httpAdapter.request({
|
|
2641
2595
|
url,
|
|
2642
2596
|
method: endpoint.method,
|
|
2643
|
-
headers:
|
|
2644
|
-
"Content-Type": "application/json",
|
|
2645
|
-
"x-boltic-token": this.config.apiKey
|
|
2646
|
-
},
|
|
2597
|
+
headers: this.buildHeaders(),
|
|
2647
2598
|
timeout: this.config.timeout
|
|
2648
2599
|
});
|
|
2649
2600
|
return response.data;
|
|
2650
2601
|
} catch (error) {
|
|
2651
|
-
return this.
|
|
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
|
-
};
|
|
2602
|
+
return this.formatErrorResponse(error);
|
|
2699
2603
|
}
|
|
2700
|
-
return {
|
|
2701
|
-
error: {
|
|
2702
|
-
code: "UNKNOWN_ERROR",
|
|
2703
|
-
message: "An unexpected error occurred",
|
|
2704
|
-
meta: []
|
|
2705
|
-
}
|
|
2706
|
-
};
|
|
2707
2604
|
}
|
|
2708
2605
|
}
|
|
2709
2606
|
class DatabaseResource extends BaseResource {
|
|
@@ -2733,7 +2630,7 @@ class DatabaseResource extends BaseResource {
|
|
|
2733
2630
|
*/
|
|
2734
2631
|
async create(request) {
|
|
2735
2632
|
const result = await this.apiClient.createDatabase(request);
|
|
2736
|
-
if (
|
|
2633
|
+
if (isErrorResponse(result)) {
|
|
2737
2634
|
return {
|
|
2738
2635
|
error: {
|
|
2739
2636
|
code: typeof result.error.code === "number" ? String(result.error.code) : result.error.code,
|
|
@@ -2800,7 +2697,7 @@ class DatabaseResource extends BaseResource {
|
|
|
2800
2697
|
queryParams,
|
|
2801
2698
|
options
|
|
2802
2699
|
);
|
|
2803
|
-
if (
|
|
2700
|
+
if (isErrorResponse(result)) {
|
|
2804
2701
|
return {
|
|
2805
2702
|
error: {
|
|
2806
2703
|
code: typeof result.error.code === "number" ? String(result.error.code) : result.error.code,
|
|
@@ -2928,7 +2825,7 @@ class DatabaseResource extends BaseResource {
|
|
|
2928
2825
|
db_name: request.db_name
|
|
2929
2826
|
};
|
|
2930
2827
|
const result = await this.apiClient.updateDatabase(dbId, updateRequest);
|
|
2931
|
-
if (
|
|
2828
|
+
if (isErrorResponse(result)) {
|
|
2932
2829
|
return {
|
|
2933
2830
|
error: {
|
|
2934
2831
|
code: typeof result.error.code === "number" ? String(result.error.code) : result.error.code,
|
|
@@ -2977,7 +2874,7 @@ class DatabaseResource extends BaseResource {
|
|
|
2977
2874
|
}
|
|
2978
2875
|
const dbId = dbInfo.data.id;
|
|
2979
2876
|
const result = await this.apiClient.deleteDatabase(dbId);
|
|
2980
|
-
if (
|
|
2877
|
+
if (isErrorResponse(result)) {
|
|
2981
2878
|
return {
|
|
2982
2879
|
error: {
|
|
2983
2880
|
code: typeof result.error.code === "number" ? String(result.error.code) : result.error.code,
|
|
@@ -3020,7 +2917,7 @@ class DatabaseResource extends BaseResource {
|
|
|
3020
2917
|
request.filters = options.filters;
|
|
3021
2918
|
}
|
|
3022
2919
|
const result = await this.apiClient.listDatabaseJobs(request, options);
|
|
3023
|
-
if (
|
|
2920
|
+
if (isErrorResponse(result)) {
|
|
3024
2921
|
return {
|
|
3025
2922
|
error: {
|
|
3026
2923
|
code: typeof result.error.code === "number" ? String(result.error.code) : result.error.code,
|
|
@@ -3065,7 +2962,7 @@ class DatabaseResource extends BaseResource {
|
|
|
3065
2962
|
*/
|
|
3066
2963
|
async pollDeleteStatus(jobId) {
|
|
3067
2964
|
const result = await this.apiClient.pollDeleteStatus(jobId);
|
|
3068
|
-
if (
|
|
2965
|
+
if (isErrorResponse(result)) {
|
|
3069
2966
|
return {
|
|
3070
2967
|
error: {
|
|
3071
2968
|
code: typeof result.error.code === "number" ? String(result.error.code) : result.error.code,
|
|
@@ -3105,26 +3002,9 @@ const buildIndexEndpointPath = (endpoint, params = {}) => {
|
|
|
3105
3002
|
}
|
|
3106
3003
|
return path;
|
|
3107
3004
|
};
|
|
3108
|
-
class IndexesApiClient {
|
|
3005
|
+
class IndexesApiClient extends BaseApiClient {
|
|
3109
3006
|
constructor(apiKey, config = {}) {
|
|
3110
|
-
|
|
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`;
|
|
3007
|
+
super(apiKey, config);
|
|
3128
3008
|
}
|
|
3129
3009
|
async addIndex(tableId, request, dbId) {
|
|
3130
3010
|
try {
|
|
@@ -3177,62 +3057,21 @@ class IndexesApiClient {
|
|
|
3177
3057
|
return this.formatErrorResponse(error);
|
|
3178
3058
|
}
|
|
3179
3059
|
}
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
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
|
-
}
|
|
3222
|
-
class IndexResource {
|
|
3223
|
-
constructor(client) {
|
|
3224
|
-
this.client = client;
|
|
3225
|
-
const config = client.getConfig();
|
|
3226
|
-
this.apiClient = new IndexesApiClient(config.apiKey, {
|
|
3227
|
-
environment: config.environment,
|
|
3228
|
-
region: config.region,
|
|
3229
|
-
timeout: config.timeout,
|
|
3230
|
-
debug: config.debug,
|
|
3231
|
-
retryAttempts: config.retryAttempts,
|
|
3232
|
-
retryDelay: config.retryDelay,
|
|
3233
|
-
headers: config.headers
|
|
3234
|
-
});
|
|
3235
|
-
this.tableResource = new TableResource(client);
|
|
3060
|
+
}
|
|
3061
|
+
class IndexResource {
|
|
3062
|
+
constructor(client) {
|
|
3063
|
+
this.client = client;
|
|
3064
|
+
const config = client.getConfig();
|
|
3065
|
+
this.apiClient = new IndexesApiClient(config.apiKey, {
|
|
3066
|
+
environment: config.environment,
|
|
3067
|
+
region: config.region,
|
|
3068
|
+
timeout: config.timeout,
|
|
3069
|
+
debug: config.debug,
|
|
3070
|
+
retryAttempts: config.retryAttempts,
|
|
3071
|
+
retryDelay: config.retryDelay,
|
|
3072
|
+
headers: config.headers
|
|
3073
|
+
});
|
|
3074
|
+
this.tableResource = new TableResource(client);
|
|
3236
3075
|
}
|
|
3237
3076
|
async resolveTableId(tableName, dbId) {
|
|
3238
3077
|
const tableResult = await this.tableResource.findByName(tableName, dbId);
|
|
@@ -3354,26 +3193,9 @@ function transformDeleteRequest(sdkRequest) {
|
|
|
3354
3193
|
}
|
|
3355
3194
|
return result;
|
|
3356
3195
|
}
|
|
3357
|
-
class RecordsApiClient {
|
|
3196
|
+
class RecordsApiClient extends BaseApiClient {
|
|
3358
3197
|
constructor(apiKey, config = {}) {
|
|
3359
|
-
|
|
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`;
|
|
3198
|
+
super(apiKey, config);
|
|
3377
3199
|
}
|
|
3378
3200
|
/**
|
|
3379
3201
|
* Insert a single record
|
|
@@ -3649,47 +3471,6 @@ class RecordsApiClient {
|
|
|
3649
3471
|
dbId
|
|
3650
3472
|
);
|
|
3651
3473
|
}
|
|
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
3474
|
}
|
|
3694
3475
|
class RecordResource {
|
|
3695
3476
|
constructor(client) {
|
|
@@ -4277,86 +4058,6 @@ const buildSqlEndpointPath = (endpoint, params = {}) => {
|
|
|
4277
4058
|
});
|
|
4278
4059
|
return path;
|
|
4279
4060
|
};
|
|
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
|
-
}
|
|
4360
4061
|
class SqlApiClient extends BaseApiClient {
|
|
4361
4062
|
constructor(apiKey, config = {}) {
|
|
4362
4063
|
super(apiKey, config);
|
|
@@ -4794,74 +4495,1057 @@ class TableBuilder {
|
|
|
4794
4495
|
function createTableBuilder(options, tablesApiClient) {
|
|
4795
4496
|
return new TableBuilder(options, tablesApiClient);
|
|
4796
4497
|
}
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4498
|
+
const POLLING_INTERVAL_MS = 1e3;
|
|
4499
|
+
const MAX_POLLING_ATTEMPTS = 30;
|
|
4500
|
+
const SCHEMA_TYPE_MAPPING = {
|
|
4501
|
+
string: { type: "string", fallback_value: "" },
|
|
4502
|
+
number: { type: "number", fallback_value: "" },
|
|
4503
|
+
boolean: { type: "boolean", secondary_type: "string", fallback_value: "" },
|
|
4504
|
+
int: { type: "number", fallback_value: "" },
|
|
4505
|
+
integer: { type: "number", fallback_value: "" },
|
|
4506
|
+
"date-time": { type: "date-time", secondary_type: "string", fallback_value: "" },
|
|
4507
|
+
date: { type: "date", secondary_type: "string", fallback_value: "" },
|
|
4508
|
+
json: { type: "object", fallback_value: {} },
|
|
4509
|
+
text: { type: "string", fallback_value: "" },
|
|
4510
|
+
email: { type: "string", fallback_value: "" },
|
|
4511
|
+
password: { type: "string", fallback_value: "" },
|
|
4512
|
+
url: { type: "string", fallback_value: "" },
|
|
4513
|
+
textarea: { type: "string", fallback_value: "" },
|
|
4514
|
+
select: { type: "string", fallback_value: "" },
|
|
4515
|
+
multiselect: { type: "string", fallback_value: "" },
|
|
4516
|
+
autocomplete: { type: "array", fallback_value: [] },
|
|
4517
|
+
radio: { type: "string", fallback_value: "" },
|
|
4518
|
+
radiobuttons: { type: "string", fallback_value: "" },
|
|
4519
|
+
checkbox: { type: "array", fallback_value: [] },
|
|
4520
|
+
toggle: { type: "boolean", fallback_value: "" },
|
|
4521
|
+
hidden: { type: "string", fallback_value: "" },
|
|
4522
|
+
slider: { type: "number", fallback_value: "" },
|
|
4523
|
+
datepicker: { type: "string", fallback_value: "" },
|
|
4524
|
+
phoneinput: { type: "string", fallback_value: "" },
|
|
4525
|
+
time: { type: "string", fallback_value: "" },
|
|
4526
|
+
datetime: { type: "string", fallback_value: "" },
|
|
4527
|
+
code: { type: "string", fallback_value: "" },
|
|
4528
|
+
multitext: { type: "array", fallback_value: [] },
|
|
4529
|
+
array: { type: "array", fallback_value: [] },
|
|
4530
|
+
keyvalue: { type: "object", fallback_value: {} },
|
|
4531
|
+
object: { type: "object", fallback_value: {} },
|
|
4532
|
+
phone: { type: "string", fallback_value: "" },
|
|
4533
|
+
"number[]": { type: "string", fallback_value: "" },
|
|
4534
|
+
"number []": { type: "string", fallback_value: "" },
|
|
4535
|
+
"object | any": { type: "string", fallback_value: "" }
|
|
4536
|
+
};
|
|
4537
|
+
const WORKFLOW_ENDPOINTS = {
|
|
4538
|
+
executeActivity: {
|
|
4539
|
+
path: "/workflows/execute/activity",
|
|
4540
|
+
method: "POST",
|
|
4541
|
+
authenticated: true
|
|
4542
|
+
},
|
|
4543
|
+
getExecutionById: {
|
|
4544
|
+
path: "/workflows/run/{run_id}",
|
|
4545
|
+
method: "GET",
|
|
4546
|
+
authenticated: true
|
|
4547
|
+
},
|
|
4548
|
+
getIntegrations: {
|
|
4549
|
+
path: "/integrations",
|
|
4550
|
+
method: "GET",
|
|
4551
|
+
authenticated: true
|
|
4552
|
+
},
|
|
4553
|
+
getCredentials: {
|
|
4554
|
+
path: "/integrations/entity/{entity}",
|
|
4555
|
+
method: "GET",
|
|
4556
|
+
authenticated: true
|
|
4557
|
+
},
|
|
4558
|
+
getIntegrationResource: {
|
|
4559
|
+
path: "/integrations/{integration_slug}/schema",
|
|
4560
|
+
method: "GET",
|
|
4561
|
+
authenticated: true
|
|
4562
|
+
},
|
|
4563
|
+
getIntegrationForm: {
|
|
4564
|
+
path: "/integrations/{integration_slug}/fields",
|
|
4565
|
+
method: "GET",
|
|
4566
|
+
authenticated: true
|
|
4567
|
+
}
|
|
4568
|
+
};
|
|
4569
|
+
function buildWorkflowEndpointPath(endpoint, params = {}) {
|
|
4570
|
+
let path = endpoint.path;
|
|
4571
|
+
for (const [key, value] of Object.entries(params)) {
|
|
4572
|
+
path = path.replace(`{${key}}`, value);
|
|
4573
|
+
}
|
|
4574
|
+
return path;
|
|
4575
|
+
}
|
|
4576
|
+
class WorkflowApiClient extends BaseApiClient {
|
|
4577
|
+
constructor(apiKey, config = {}) {
|
|
4578
|
+
super(apiKey, config, SERVICE_PATHS.WORKFLOW_TEMPORAL);
|
|
4579
|
+
this.integrationBaseURL = this.resolveAdditionalServiceURL(
|
|
4580
|
+
SERVICE_PATHS.INTEGRATION
|
|
4806
4581
|
);
|
|
4807
|
-
const config = this.configManager.getConfig();
|
|
4808
|
-
this.authManager = new AuthManager2({
|
|
4809
|
-
apiKey: config.apiKey,
|
|
4810
|
-
maxRetries: config.maxRetries
|
|
4811
|
-
});
|
|
4812
|
-
this.baseClient = new BaseClient(config, this.authManager);
|
|
4813
|
-
this.tableResource = new TableResource(this.baseClient);
|
|
4814
|
-
this.columnResource = new ColumnResource(this.baseClient);
|
|
4815
|
-
this.recordResource = new RecordResource(this.baseClient);
|
|
4816
|
-
this.sqlResource = new SqlResource(this.baseClient);
|
|
4817
|
-
this.indexResource = new IndexResource(this.baseClient);
|
|
4818
|
-
this.databaseResource = new DatabaseResource(this.baseClient);
|
|
4819
|
-
this.currentDatabase = null;
|
|
4820
4582
|
}
|
|
4821
4583
|
/**
|
|
4822
|
-
*
|
|
4584
|
+
* Execute a workflow activity.
|
|
4585
|
+
*
|
|
4586
|
+
* @param body - The execute-activity request body
|
|
4823
4587
|
*/
|
|
4824
|
-
|
|
4825
|
-
|
|
4588
|
+
async executeActivity(body) {
|
|
4589
|
+
try {
|
|
4590
|
+
const endpoint = WORKFLOW_ENDPOINTS.executeActivity;
|
|
4591
|
+
const url = `${this.baseURL}${endpoint.path}`;
|
|
4592
|
+
const response = await this.httpAdapter.request({
|
|
4593
|
+
url,
|
|
4594
|
+
method: endpoint.method,
|
|
4595
|
+
headers: this.buildHeaders(),
|
|
4596
|
+
data: body,
|
|
4597
|
+
timeout: this.config.timeout
|
|
4598
|
+
});
|
|
4599
|
+
return response.data;
|
|
4600
|
+
} catch (error) {
|
|
4601
|
+
return this.formatErrorResponse(error, "WORKFLOW");
|
|
4602
|
+
}
|
|
4826
4603
|
}
|
|
4827
4604
|
/**
|
|
4828
|
-
*
|
|
4829
|
-
* All subsequent operations will use this database.
|
|
4830
|
-
*
|
|
4831
|
-
* If no internal name is provided, the SDK will switch back to the default database.
|
|
4832
|
-
*
|
|
4833
|
-
* @param dbInternalName - Database internal name/slug to switch to. If omitted or empty, default DB is used.
|
|
4834
|
-
*
|
|
4835
|
-
* @example
|
|
4836
|
-
* ```typescript
|
|
4837
|
-
* // Switch to a specific database by slug
|
|
4838
|
-
* await client.useDatabase('my_database_slug');
|
|
4605
|
+
* Fetch the result of a workflow execution by its run ID.
|
|
4839
4606
|
*
|
|
4840
|
-
*
|
|
4841
|
-
* await client.useDatabase();
|
|
4842
|
-
* ```
|
|
4607
|
+
* @param runId - The execution run ID returned by `executeActivity`
|
|
4843
4608
|
*/
|
|
4844
|
-
async
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4609
|
+
async getExecutionById(runId) {
|
|
4610
|
+
try {
|
|
4611
|
+
const endpoint = WORKFLOW_ENDPOINTS.getExecutionById;
|
|
4612
|
+
const path = buildWorkflowEndpointPath(endpoint, { run_id: runId });
|
|
4613
|
+
const url = `${this.baseURL}${path}`;
|
|
4614
|
+
const response = await this.httpAdapter.request({
|
|
4615
|
+
url,
|
|
4616
|
+
method: endpoint.method,
|
|
4617
|
+
headers: this.buildHeaders(),
|
|
4618
|
+
timeout: this.config.timeout
|
|
4619
|
+
});
|
|
4620
|
+
return response.data;
|
|
4621
|
+
} catch (error) {
|
|
4622
|
+
return this.formatErrorResponse(error, "WORKFLOW");
|
|
4849
4623
|
}
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4624
|
+
}
|
|
4625
|
+
/**
|
|
4626
|
+
* Fetch the list of available integrations.
|
|
4627
|
+
*
|
|
4628
|
+
* @param params - Optional pagination parameters
|
|
4629
|
+
*/
|
|
4630
|
+
async getIntegrations(params = {}) {
|
|
4631
|
+
try {
|
|
4632
|
+
const endpoint = WORKFLOW_ENDPOINTS.getIntegrations;
|
|
4633
|
+
const query = new URLSearchParams({
|
|
4634
|
+
page: String(params.page ?? 1),
|
|
4635
|
+
per_page: String(params.per_page ?? 999)
|
|
4636
|
+
});
|
|
4637
|
+
const url = `${this.baseURL}${endpoint.path}?${query.toString()}`;
|
|
4638
|
+
const response = await this.httpAdapter.request({
|
|
4639
|
+
url,
|
|
4640
|
+
method: endpoint.method,
|
|
4641
|
+
headers: this.buildHeaders(),
|
|
4642
|
+
timeout: this.config.timeout
|
|
4643
|
+
});
|
|
4644
|
+
return response.data;
|
|
4645
|
+
} catch (error) {
|
|
4646
|
+
return this.formatErrorResponse(error, "WORKFLOW");
|
|
4857
4647
|
}
|
|
4858
|
-
const db = result.data;
|
|
4859
|
-
this.currentDatabase = {
|
|
4860
|
-
databaseId: db.id,
|
|
4861
|
-
dbInternalName: db.db_internal_name || dbInternalName
|
|
4862
|
-
};
|
|
4863
4648
|
}
|
|
4864
|
-
|
|
4649
|
+
/**
|
|
4650
|
+
* Fetch credentials for a given integration entity.
|
|
4651
|
+
*
|
|
4652
|
+
* @param params - Entity name (required) and optional pagination
|
|
4653
|
+
*/
|
|
4654
|
+
async getCredentials(params) {
|
|
4655
|
+
try {
|
|
4656
|
+
const endpoint = WORKFLOW_ENDPOINTS.getCredentials;
|
|
4657
|
+
const path = buildWorkflowEndpointPath(endpoint, {
|
|
4658
|
+
entity: params.entity.toUpperCase()
|
|
4659
|
+
});
|
|
4660
|
+
const query = new URLSearchParams({
|
|
4661
|
+
current_page: String(params.current_page ?? 1),
|
|
4662
|
+
page_size: String(params.page_size ?? 999)
|
|
4663
|
+
});
|
|
4664
|
+
const url = `${this.integrationBaseURL}${path}?${query.toString()}`;
|
|
4665
|
+
const response = await this.httpAdapter.request({
|
|
4666
|
+
url,
|
|
4667
|
+
method: endpoint.method,
|
|
4668
|
+
headers: this.buildHeaders(),
|
|
4669
|
+
timeout: this.config.timeout
|
|
4670
|
+
});
|
|
4671
|
+
return response.data;
|
|
4672
|
+
} catch (error) {
|
|
4673
|
+
return this.formatErrorResponse(error, "INTEGRATION");
|
|
4674
|
+
}
|
|
4675
|
+
}
|
|
4676
|
+
/**
|
|
4677
|
+
* Fetch the resource/operation schema for an integration.
|
|
4678
|
+
*
|
|
4679
|
+
* @param params - Integration slug identifier
|
|
4680
|
+
*/
|
|
4681
|
+
async getIntegrationResource(params) {
|
|
4682
|
+
try {
|
|
4683
|
+
const endpoint = WORKFLOW_ENDPOINTS.getIntegrationResource;
|
|
4684
|
+
const path = buildWorkflowEndpointPath(endpoint, {
|
|
4685
|
+
integration_slug: params.integration_slug
|
|
4686
|
+
});
|
|
4687
|
+
const url = `${this.baseURL}${path}`;
|
|
4688
|
+
const response = await this.httpAdapter.request({
|
|
4689
|
+
url,
|
|
4690
|
+
method: endpoint.method,
|
|
4691
|
+
headers: this.buildHeaders(),
|
|
4692
|
+
timeout: this.config.timeout
|
|
4693
|
+
});
|
|
4694
|
+
return response.data;
|
|
4695
|
+
} catch (error) {
|
|
4696
|
+
return this.formatErrorResponse(error, "WORKFLOW");
|
|
4697
|
+
}
|
|
4698
|
+
}
|
|
4699
|
+
/**
|
|
4700
|
+
* Fetch the form schema (fields) for a specific integration resource + operation.
|
|
4701
|
+
*
|
|
4702
|
+
* @param params - Integration slug, resource, operation, and credential secret
|
|
4703
|
+
*/
|
|
4704
|
+
async getIntegrationForm(params) {
|
|
4705
|
+
try {
|
|
4706
|
+
const endpoint = WORKFLOW_ENDPOINTS.getIntegrationForm;
|
|
4707
|
+
const path = buildWorkflowEndpointPath(endpoint, {
|
|
4708
|
+
integration_slug: params.integration_slug
|
|
4709
|
+
});
|
|
4710
|
+
const query = new URLSearchParams({
|
|
4711
|
+
resource: params.resource,
|
|
4712
|
+
operation: params.operation,
|
|
4713
|
+
// getFormOnly: String(params.getFormOnly ?? true),
|
|
4714
|
+
secret: params.secret
|
|
4715
|
+
});
|
|
4716
|
+
const url = `${this.baseURL}${path}?${query.toString()}`;
|
|
4717
|
+
const response = await this.httpAdapter.request({
|
|
4718
|
+
url,
|
|
4719
|
+
method: endpoint.method,
|
|
4720
|
+
headers: this.buildHeaders(),
|
|
4721
|
+
timeout: this.config.timeout
|
|
4722
|
+
});
|
|
4723
|
+
return response.data;
|
|
4724
|
+
} catch (error) {
|
|
4725
|
+
return this.formatErrorResponse(error, "WORKFLOW");
|
|
4726
|
+
}
|
|
4727
|
+
}
|
|
4728
|
+
}
|
|
4729
|
+
const FORM_META_FIELDS = /* @__PURE__ */ new Set(["resource", "operation"]);
|
|
4730
|
+
function getSchemaMapping(displayType) {
|
|
4731
|
+
return SCHEMA_TYPE_MAPPING[displayType] ?? {
|
|
4732
|
+
type: "string",
|
|
4733
|
+
fallback_value: ""
|
|
4734
|
+
};
|
|
4735
|
+
}
|
|
4736
|
+
function transformFormToDefaults(fields, skipFields = FORM_META_FIELDS) {
|
|
4737
|
+
const result = {};
|
|
4738
|
+
for (const field of fields) {
|
|
4739
|
+
if (skipFields.has(field.name)) continue;
|
|
4740
|
+
const displayType = field.meta?.displayType || "text";
|
|
4741
|
+
const mapping = getSchemaMapping(displayType);
|
|
4742
|
+
result[field.name] = field.meta?.value !== void 0 ? field.meta.value : mapping.fallback_value;
|
|
4743
|
+
}
|
|
4744
|
+
return result;
|
|
4745
|
+
}
|
|
4746
|
+
function transformFormToJsonSchema(fields, skipFields = FORM_META_FIELDS) {
|
|
4747
|
+
const properties = {};
|
|
4748
|
+
for (const field of fields) {
|
|
4749
|
+
if (skipFields.has(field.name)) continue;
|
|
4750
|
+
const displayType = field.meta?.displayType || "text";
|
|
4751
|
+
const mapping = getSchemaMapping(displayType);
|
|
4752
|
+
const isRequired = field.meta?.validation?.required ?? false;
|
|
4753
|
+
const defaultValue = field.meta?.value !== void 0 ? field.meta.value : mapping.fallback_value;
|
|
4754
|
+
const prop = {
|
|
4755
|
+
type: mapping.type,
|
|
4756
|
+
required: isRequired,
|
|
4757
|
+
default: defaultValue
|
|
4758
|
+
};
|
|
4759
|
+
if (field.meta?.description) {
|
|
4760
|
+
prop.description = field.meta.description;
|
|
4761
|
+
}
|
|
4762
|
+
if (field.meta?.options && Array.isArray(field.meta.options) && field.meta.options.length > 0) {
|
|
4763
|
+
prop.enum = field.meta.options.map((opt) => opt.value);
|
|
4764
|
+
}
|
|
4765
|
+
properties[field.name] = prop;
|
|
4766
|
+
}
|
|
4767
|
+
return { type: "object", properties };
|
|
4768
|
+
}
|
|
4769
|
+
function buildDefaultResultPayload() {
|
|
4770
|
+
return {
|
|
4771
|
+
payload: {},
|
|
4772
|
+
global_variables: {}
|
|
4773
|
+
};
|
|
4774
|
+
}
|
|
4775
|
+
function buildExecuteActivityBody(params) {
|
|
4776
|
+
const node = {
|
|
4777
|
+
data: {
|
|
4778
|
+
type: params.data.type,
|
|
4779
|
+
name: params.data.name,
|
|
4780
|
+
properties: params.data.properties
|
|
4781
|
+
}
|
|
4782
|
+
};
|
|
4783
|
+
return {
|
|
4784
|
+
nodes: [node],
|
|
4785
|
+
result: params.result ?? buildDefaultResultPayload()
|
|
4786
|
+
};
|
|
4787
|
+
}
|
|
4788
|
+
function sleep$1(ms) {
|
|
4789
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
4790
|
+
}
|
|
4791
|
+
class WorkflowResource extends BaseResource {
|
|
4792
|
+
constructor(client) {
|
|
4793
|
+
super(client, "/workflows");
|
|
4794
|
+
const config = client.getConfig();
|
|
4795
|
+
this.apiClient = new WorkflowApiClient(config.apiKey, {
|
|
4796
|
+
environment: config.environment,
|
|
4797
|
+
region: config.region,
|
|
4798
|
+
timeout: config.timeout,
|
|
4799
|
+
debug: config.debug
|
|
4800
|
+
});
|
|
4801
|
+
}
|
|
4802
|
+
/**
|
|
4803
|
+
* Execute a workflow integration activity.
|
|
4804
|
+
*
|
|
4805
|
+
* When `executeOnly` is `true`, returns the immediate API response.
|
|
4806
|
+
* When `executeOnly` is `false` (default), polls until a terminal state
|
|
4807
|
+
* is reached and returns the final execution result.
|
|
4808
|
+
*
|
|
4809
|
+
* @param params - Execution parameters
|
|
4810
|
+
* @returns The execute response or the final polled result
|
|
4811
|
+
*
|
|
4812
|
+
* @example
|
|
4813
|
+
* ```typescript
|
|
4814
|
+
* const result = await client.workflow.executeIntegration({
|
|
4815
|
+
* data: { type: 'apiActivity', name: 'api1', properties: { method: 'get', endpoint: '...' } },
|
|
4816
|
+
* });
|
|
4817
|
+
*
|
|
4818
|
+
* const fire = await client.workflow.executeIntegration({
|
|
4819
|
+
* data: { type: 'apiActivity', name: 'api1', properties: { method: 'get', endpoint: '...' } },
|
|
4820
|
+
* executeOnly: true,
|
|
4821
|
+
* });
|
|
4822
|
+
* ```
|
|
4823
|
+
*/
|
|
4824
|
+
async executeIntegration(params) {
|
|
4825
|
+
const body = buildExecuteActivityBody(params);
|
|
4826
|
+
const executeResult = await this.apiClient.executeActivity(body);
|
|
4827
|
+
if (isErrorResponse(executeResult)) {
|
|
4828
|
+
return executeResult;
|
|
4829
|
+
}
|
|
4830
|
+
if (params.executeOnly) {
|
|
4831
|
+
return executeResult;
|
|
4832
|
+
}
|
|
4833
|
+
const executionId = executeResult.data?.execution_id;
|
|
4834
|
+
if (!executionId) {
|
|
4835
|
+
return {
|
|
4836
|
+
error: {
|
|
4837
|
+
code: "MISSING_EXECUTION_ID",
|
|
4838
|
+
message: "Execute API response did not contain an execution_id",
|
|
4839
|
+
meta: []
|
|
4840
|
+
}
|
|
4841
|
+
};
|
|
4842
|
+
}
|
|
4843
|
+
return this.pollExecution(executionId);
|
|
4844
|
+
}
|
|
4845
|
+
/**
|
|
4846
|
+
* Retrieve the result of a workflow execution by its run/execution ID.
|
|
4847
|
+
*
|
|
4848
|
+
* @param executionId - The execution run ID
|
|
4849
|
+
* @returns The execution data or an error response
|
|
4850
|
+
*
|
|
4851
|
+
* @example
|
|
4852
|
+
* ```typescript
|
|
4853
|
+
* const result = await client.workflow.getIntegrationExecuteById('run-uuid');
|
|
4854
|
+
* ```
|
|
4855
|
+
*/
|
|
4856
|
+
async getIntegrationExecuteById(executionId) {
|
|
4857
|
+
return this.apiClient.getExecutionById(executionId);
|
|
4858
|
+
}
|
|
4859
|
+
/**
|
|
4860
|
+
* Fetch the list of available integrations.
|
|
4861
|
+
*
|
|
4862
|
+
* @param params - Optional pagination parameters (`page`, `per_page`)
|
|
4863
|
+
* @returns The integrations list or an error response
|
|
4864
|
+
*
|
|
4865
|
+
* @example
|
|
4866
|
+
* ```typescript
|
|
4867
|
+
* const list = await client.workflow.getIntegrations();
|
|
4868
|
+
* ```
|
|
4869
|
+
*/
|
|
4870
|
+
async getIntegrations(params = {}) {
|
|
4871
|
+
return this.apiClient.getIntegrations(params);
|
|
4872
|
+
}
|
|
4873
|
+
/**
|
|
4874
|
+
* Fetch credentials for a given integration entity.
|
|
4875
|
+
*
|
|
4876
|
+
* @param params - Entity name (required), optional `current_page` and `page_size`
|
|
4877
|
+
* @returns The credentials list or an error response
|
|
4878
|
+
*
|
|
4879
|
+
* @example
|
|
4880
|
+
* ```typescript
|
|
4881
|
+
* const creds = await client.workflow.getCredentials({ entity: 'freshsales' });
|
|
4882
|
+
* ```
|
|
4883
|
+
*/
|
|
4884
|
+
async getCredentials(params) {
|
|
4885
|
+
return this.apiClient.getCredentials(params);
|
|
4886
|
+
}
|
|
4887
|
+
/**
|
|
4888
|
+
* Fetch the resource/operation schema for an integration.
|
|
4889
|
+
*
|
|
4890
|
+
* Returns the available resources and operations supported by the
|
|
4891
|
+
* specified integration (e.g. which resources like "task", "project"
|
|
4892
|
+
* are available and what operations can be performed on them).
|
|
4893
|
+
*
|
|
4894
|
+
* @param params - Integration slug identifier
|
|
4895
|
+
* @returns The integration resource schema or an error response
|
|
4896
|
+
*
|
|
4897
|
+
* @example
|
|
4898
|
+
* ```typescript
|
|
4899
|
+
* const schema = await client.workflow.getIntegrationResource({
|
|
4900
|
+
* integration_slug: 'blt-int.asana',
|
|
4901
|
+
* });
|
|
4902
|
+
* ```
|
|
4903
|
+
*/
|
|
4904
|
+
async getIntegrationResource(params) {
|
|
4905
|
+
return this.apiClient.getIntegrationResource(params);
|
|
4906
|
+
}
|
|
4907
|
+
/**
|
|
4908
|
+
* Fetch the form schema (fields) for a specific integration resource + operation.
|
|
4909
|
+
*
|
|
4910
|
+
* By default, returns a flat JSON object with default/fallback values
|
|
4911
|
+
* for each input field. Set `asJsonSchema: true` to get a JSON Schema
|
|
4912
|
+
* object describing the expected input shape instead.
|
|
4913
|
+
*
|
|
4914
|
+
* Fields like `resource` and `operation` are automatically excluded
|
|
4915
|
+
* since they are already handled by the SDK parameters. The `secret`
|
|
4916
|
+
* field is included and populated with the value from `params.secret`.
|
|
4917
|
+
*
|
|
4918
|
+
* @param params - Integration slug, resource, operation, credential secret, and format flag
|
|
4919
|
+
* @returns Transformed form data or an error response
|
|
4920
|
+
*
|
|
4921
|
+
* @example
|
|
4922
|
+
* ```typescript
|
|
4923
|
+
* // Get flat defaults: { name: '', workspace: [], team: '', ... }
|
|
4924
|
+
* const defaults = await client.workflow.getIntegrationForm({
|
|
4925
|
+
* integration_slug: 'blt-int.asana',
|
|
4926
|
+
* resource: 'project',
|
|
4927
|
+
* operation: 'create',
|
|
4928
|
+
* secret: 'credential-secret-here',
|
|
4929
|
+
* });
|
|
4930
|
+
*
|
|
4931
|
+
* // Get JSON Schema: { type: 'object', properties: { name: { type: 'string', ... } } }
|
|
4932
|
+
* const schema = await client.workflow.getIntegrationForm({
|
|
4933
|
+
* integration_slug: 'blt-int.asana',
|
|
4934
|
+
* resource: 'project',
|
|
4935
|
+
* operation: 'create',
|
|
4936
|
+
* secret: 'credential-secret-here',
|
|
4937
|
+
* asJsonSchema: true,
|
|
4938
|
+
* });
|
|
4939
|
+
* ```
|
|
4940
|
+
*/
|
|
4941
|
+
async getIntegrationForm(params) {
|
|
4942
|
+
const rawResult = await this.apiClient.getIntegrationForm(params);
|
|
4943
|
+
console.log("rawResult", JSON.stringify(rawResult, null, 2));
|
|
4944
|
+
if (isErrorResponse(rawResult)) {
|
|
4945
|
+
return rawResult;
|
|
4946
|
+
}
|
|
4947
|
+
const configuration = rawResult.data?.parameters || rawResult.data;
|
|
4948
|
+
const fields = configuration ?? [];
|
|
4949
|
+
const transformed = params.asJsonSchema ? transformFormToJsonSchema(fields) : transformFormToDefaults(fields);
|
|
4950
|
+
if (params.asJsonSchema) {
|
|
4951
|
+
const schema = transformed;
|
|
4952
|
+
if (schema.properties.secret) {
|
|
4953
|
+
schema.properties.secret.default = params.secret;
|
|
4954
|
+
}
|
|
4955
|
+
} else {
|
|
4956
|
+
const defaults = transformed;
|
|
4957
|
+
if ("secret" in defaults) {
|
|
4958
|
+
defaults.secret = params.secret;
|
|
4959
|
+
}
|
|
4960
|
+
}
|
|
4961
|
+
return {
|
|
4962
|
+
data: transformed,
|
|
4963
|
+
message: rawResult.message
|
|
4964
|
+
};
|
|
4965
|
+
}
|
|
4966
|
+
/**
|
|
4967
|
+
* Internal polling loop.
|
|
4968
|
+
* Repeatedly calls `getExecutionById` until the response `data` object is
|
|
4969
|
+
* non-empty (execution finished) or max attempts are exhausted.
|
|
4970
|
+
*/
|
|
4971
|
+
async pollExecution(executionId) {
|
|
4972
|
+
const debug = this.client.getConfig().debug;
|
|
4973
|
+
for (let attempt = 0; attempt < MAX_POLLING_ATTEMPTS; attempt++) {
|
|
4974
|
+
const result = await this.apiClient.getExecutionById(executionId);
|
|
4975
|
+
if (isErrorResponse(result)) {
|
|
4976
|
+
return result;
|
|
4977
|
+
}
|
|
4978
|
+
if (result.data && Object.keys(result.data).length > 0) {
|
|
4979
|
+
if (debug) {
|
|
4980
|
+
console.log(
|
|
4981
|
+
`[WorkflowResource] Execution ${executionId} completed after ${attempt + 1} poll(s)`
|
|
4982
|
+
);
|
|
4983
|
+
}
|
|
4984
|
+
return result;
|
|
4985
|
+
}
|
|
4986
|
+
await sleep$1(POLLING_INTERVAL_MS);
|
|
4987
|
+
}
|
|
4988
|
+
return {
|
|
4989
|
+
error: {
|
|
4990
|
+
code: "EXECUTION_TIMEOUT",
|
|
4991
|
+
message: `Execution ${executionId} did not complete within ${MAX_POLLING_ATTEMPTS} polling attempts`,
|
|
4992
|
+
meta: [
|
|
4993
|
+
`execution_id: ${executionId}`,
|
|
4994
|
+
`max_attempts: ${MAX_POLLING_ATTEMPTS}`
|
|
4995
|
+
]
|
|
4996
|
+
}
|
|
4997
|
+
};
|
|
4998
|
+
}
|
|
4999
|
+
}
|
|
5000
|
+
const STATUS_POLLING_INTERVAL_MS = 5e3;
|
|
5001
|
+
const MAX_STATUS_POLLING_ATTEMPTS = 60;
|
|
5002
|
+
const TERMINAL_STATUSES = [
|
|
5003
|
+
"running",
|
|
5004
|
+
"failed",
|
|
5005
|
+
"degraded",
|
|
5006
|
+
"suspended"
|
|
5007
|
+
];
|
|
5008
|
+
const DEFAULT_RESOURCES = {
|
|
5009
|
+
CPU: 0.1,
|
|
5010
|
+
MemoryMB: 128,
|
|
5011
|
+
MemoryMaxMB: 128
|
|
5012
|
+
};
|
|
5013
|
+
const DEFAULT_SCALING = {
|
|
5014
|
+
AutoStop: false,
|
|
5015
|
+
Min: 1,
|
|
5016
|
+
Max: 1,
|
|
5017
|
+
MaxIdleTime: 0
|
|
5018
|
+
};
|
|
5019
|
+
const SERVERLESS_ENDPOINTS = {
|
|
5020
|
+
list: {
|
|
5021
|
+
path: "/apps",
|
|
5022
|
+
method: "GET",
|
|
5023
|
+
authenticated: true
|
|
5024
|
+
},
|
|
5025
|
+
get: {
|
|
5026
|
+
path: "/apps/{app_id}",
|
|
5027
|
+
method: "GET",
|
|
5028
|
+
authenticated: true
|
|
5029
|
+
},
|
|
5030
|
+
create: {
|
|
5031
|
+
path: "/apps",
|
|
5032
|
+
method: "POST",
|
|
5033
|
+
authenticated: true
|
|
5034
|
+
},
|
|
5035
|
+
update: {
|
|
5036
|
+
path: "/apps/{app_id}",
|
|
5037
|
+
method: "PUT",
|
|
5038
|
+
authenticated: true
|
|
5039
|
+
},
|
|
5040
|
+
getBuilds: {
|
|
5041
|
+
path: "/apps/{app_id}/builds",
|
|
5042
|
+
method: "GET",
|
|
5043
|
+
authenticated: true
|
|
5044
|
+
},
|
|
5045
|
+
getLogs: {
|
|
5046
|
+
path: "/apps/{app_id}/logs",
|
|
5047
|
+
method: "GET",
|
|
5048
|
+
authenticated: true
|
|
5049
|
+
},
|
|
5050
|
+
getBuildLogs: {
|
|
5051
|
+
path: "/apps/{app_id}/builds/{build_id}/logs",
|
|
5052
|
+
method: "GET",
|
|
5053
|
+
authenticated: true
|
|
5054
|
+
}
|
|
5055
|
+
};
|
|
5056
|
+
function buildServerlessEndpointPath(endpoint, params = {}) {
|
|
5057
|
+
let path = endpoint.path;
|
|
5058
|
+
for (const [key, value] of Object.entries(params)) {
|
|
5059
|
+
path = path.replace(`{${key}}`, value);
|
|
5060
|
+
}
|
|
5061
|
+
return path;
|
|
5062
|
+
}
|
|
5063
|
+
class ServerlessApiClient extends BaseApiClient {
|
|
5064
|
+
constructor(apiKey, config = {}) {
|
|
5065
|
+
super(apiKey, config, SERVICE_PATHS.SERVERLESS);
|
|
5066
|
+
}
|
|
5067
|
+
/**
|
|
5068
|
+
* List all serverless functions with optional pagination and search.
|
|
5069
|
+
*/
|
|
5070
|
+
async list(params = {}) {
|
|
5071
|
+
try {
|
|
5072
|
+
const endpoint = SERVERLESS_ENDPOINTS.list;
|
|
5073
|
+
const query = new URLSearchParams({
|
|
5074
|
+
page: String(params.page ?? 1),
|
|
5075
|
+
limit: String(params.limit ?? 20),
|
|
5076
|
+
sortBy: params.sortBy ?? "CreatedAt",
|
|
5077
|
+
sortOrder: params.sortOrder ?? "desc"
|
|
5078
|
+
});
|
|
5079
|
+
if (params.query) {
|
|
5080
|
+
query.set("q", params.query);
|
|
5081
|
+
}
|
|
5082
|
+
const url = `${this.baseURL}${endpoint.path}?${query.toString()}`;
|
|
5083
|
+
const response = await this.httpAdapter.request({
|
|
5084
|
+
url,
|
|
5085
|
+
method: endpoint.method,
|
|
5086
|
+
headers: this.buildHeaders(),
|
|
5087
|
+
timeout: this.config.timeout
|
|
5088
|
+
});
|
|
5089
|
+
return response.data;
|
|
5090
|
+
} catch (error) {
|
|
5091
|
+
return this.formatErrorResponse(error, "SERVERLESS");
|
|
5092
|
+
}
|
|
5093
|
+
}
|
|
5094
|
+
/**
|
|
5095
|
+
* Get a serverless function by its ID.
|
|
5096
|
+
*/
|
|
5097
|
+
async get(appId) {
|
|
5098
|
+
try {
|
|
5099
|
+
const endpoint = SERVERLESS_ENDPOINTS.get;
|
|
5100
|
+
const path = buildServerlessEndpointPath(endpoint, { app_id: appId });
|
|
5101
|
+
const url = `${this.baseURL}${path}`;
|
|
5102
|
+
console.log("url", url);
|
|
5103
|
+
const response = await this.httpAdapter.request({
|
|
5104
|
+
url,
|
|
5105
|
+
method: endpoint.method,
|
|
5106
|
+
headers: this.buildHeaders(),
|
|
5107
|
+
timeout: this.config.timeout
|
|
5108
|
+
});
|
|
5109
|
+
console.log("response", response.data);
|
|
5110
|
+
return response.data;
|
|
5111
|
+
} catch (error) {
|
|
5112
|
+
return this.formatErrorResponse(error, "SERVERLESS");
|
|
5113
|
+
}
|
|
5114
|
+
}
|
|
5115
|
+
/**
|
|
5116
|
+
* Create a new serverless function.
|
|
5117
|
+
*/
|
|
5118
|
+
async create(payload) {
|
|
5119
|
+
try {
|
|
5120
|
+
const endpoint = SERVERLESS_ENDPOINTS.create;
|
|
5121
|
+
const url = `${this.baseURL}${endpoint.path}`;
|
|
5122
|
+
const response = await this.httpAdapter.request({
|
|
5123
|
+
url,
|
|
5124
|
+
method: endpoint.method,
|
|
5125
|
+
headers: this.buildHeaders(),
|
|
5126
|
+
data: payload,
|
|
5127
|
+
timeout: this.config.timeout
|
|
5128
|
+
});
|
|
5129
|
+
return response.data;
|
|
5130
|
+
} catch (error) {
|
|
5131
|
+
return this.formatErrorResponse(error, "SERVERLESS");
|
|
5132
|
+
}
|
|
5133
|
+
}
|
|
5134
|
+
/**
|
|
5135
|
+
* Update an existing serverless function.
|
|
5136
|
+
*/
|
|
5137
|
+
async update(params) {
|
|
5138
|
+
try {
|
|
5139
|
+
const endpoint = SERVERLESS_ENDPOINTS.update;
|
|
5140
|
+
const path = buildServerlessEndpointPath(endpoint, {
|
|
5141
|
+
app_id: params.appId
|
|
5142
|
+
});
|
|
5143
|
+
const url = `${this.baseURL}${path}`;
|
|
5144
|
+
const response = await this.httpAdapter.request({
|
|
5145
|
+
url,
|
|
5146
|
+
method: endpoint.method,
|
|
5147
|
+
headers: this.buildHeaders(),
|
|
5148
|
+
data: params.payload,
|
|
5149
|
+
timeout: this.config.timeout
|
|
5150
|
+
});
|
|
5151
|
+
return response.data;
|
|
5152
|
+
} catch (error) {
|
|
5153
|
+
return this.formatErrorResponse(error, "SERVERLESS");
|
|
5154
|
+
}
|
|
5155
|
+
}
|
|
5156
|
+
/**
|
|
5157
|
+
* List builds for a serverless function.
|
|
5158
|
+
*/
|
|
5159
|
+
async getBuilds(params) {
|
|
5160
|
+
try {
|
|
5161
|
+
const endpoint = SERVERLESS_ENDPOINTS.getBuilds;
|
|
5162
|
+
const path = buildServerlessEndpointPath(endpoint, {
|
|
5163
|
+
app_id: params.appId
|
|
5164
|
+
});
|
|
5165
|
+
const query = new URLSearchParams({
|
|
5166
|
+
page: String(params.page ?? 1),
|
|
5167
|
+
limit: String(params.limit ?? 20),
|
|
5168
|
+
sortBy: "CreatedAt",
|
|
5169
|
+
sortOrder: "desc"
|
|
5170
|
+
});
|
|
5171
|
+
const url = `${this.baseURL}${path}?${query.toString()}`;
|
|
5172
|
+
const response = await this.httpAdapter.request({
|
|
5173
|
+
url,
|
|
5174
|
+
method: endpoint.method,
|
|
5175
|
+
headers: this.buildHeaders(),
|
|
5176
|
+
timeout: this.config.timeout
|
|
5177
|
+
});
|
|
5178
|
+
return response.data;
|
|
5179
|
+
} catch (error) {
|
|
5180
|
+
return this.formatErrorResponse(error, "SERVERLESS");
|
|
5181
|
+
}
|
|
5182
|
+
}
|
|
5183
|
+
/**
|
|
5184
|
+
* Get runtime logs for a serverless function.
|
|
5185
|
+
*/
|
|
5186
|
+
async getLogs(params) {
|
|
5187
|
+
try {
|
|
5188
|
+
const endpoint = SERVERLESS_ENDPOINTS.getLogs;
|
|
5189
|
+
const path = buildServerlessEndpointPath(endpoint, {
|
|
5190
|
+
app_id: params.appId
|
|
5191
|
+
});
|
|
5192
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
5193
|
+
const defaultStart = now - 24 * 60 * 60;
|
|
5194
|
+
const query = new URLSearchParams({
|
|
5195
|
+
page: String(params.page ?? 1),
|
|
5196
|
+
limit: String(params.limit ?? 50),
|
|
5197
|
+
sortBy: "Timestamp",
|
|
5198
|
+
sortOrder: params.sortOrder ?? "DESC",
|
|
5199
|
+
timestampStart: String(params.timestampStart ?? defaultStart),
|
|
5200
|
+
timestampEnd: String(params.timestampEnd ?? now),
|
|
5201
|
+
metric_interval: "60"
|
|
5202
|
+
});
|
|
5203
|
+
const url = `${this.baseURL}${path}?${query.toString()}`;
|
|
5204
|
+
const response = await this.httpAdapter.request({
|
|
5205
|
+
url,
|
|
5206
|
+
method: endpoint.method,
|
|
5207
|
+
headers: this.buildHeaders(),
|
|
5208
|
+
timeout: this.config.timeout
|
|
5209
|
+
});
|
|
5210
|
+
return response.data;
|
|
5211
|
+
} catch (error) {
|
|
5212
|
+
return this.formatErrorResponse(error, "SERVERLESS");
|
|
5213
|
+
}
|
|
5214
|
+
}
|
|
5215
|
+
/**
|
|
5216
|
+
* Get build logs for a specific build of a serverless function.
|
|
5217
|
+
*/
|
|
5218
|
+
async getBuildLogs(params) {
|
|
5219
|
+
try {
|
|
5220
|
+
const endpoint = SERVERLESS_ENDPOINTS.getBuildLogs;
|
|
5221
|
+
const path = buildServerlessEndpointPath(endpoint, {
|
|
5222
|
+
app_id: params.appId,
|
|
5223
|
+
build_id: params.buildId
|
|
5224
|
+
});
|
|
5225
|
+
const query = new URLSearchParams({
|
|
5226
|
+
limit: "-1",
|
|
5227
|
+
tail: "false",
|
|
5228
|
+
sortOrder: "asc",
|
|
5229
|
+
sortBy: "Timestamp"
|
|
5230
|
+
});
|
|
5231
|
+
const url = `${this.baseURL}${path}?${query.toString()}`;
|
|
5232
|
+
const response = await this.httpAdapter.request({
|
|
5233
|
+
url,
|
|
5234
|
+
method: endpoint.method,
|
|
5235
|
+
headers: this.buildHeaders(),
|
|
5236
|
+
timeout: this.config.timeout
|
|
5237
|
+
});
|
|
5238
|
+
return response.data;
|
|
5239
|
+
} catch (error) {
|
|
5240
|
+
return this.formatErrorResponse(error, "SERVERLESS");
|
|
5241
|
+
}
|
|
5242
|
+
}
|
|
5243
|
+
}
|
|
5244
|
+
function sleep(ms) {
|
|
5245
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
5246
|
+
}
|
|
5247
|
+
class ServerlessResource extends BaseResource {
|
|
5248
|
+
constructor(client) {
|
|
5249
|
+
super(client, "/serverless");
|
|
5250
|
+
const config = client.getConfig();
|
|
5251
|
+
this.apiClient = new ServerlessApiClient(config.apiKey, {
|
|
5252
|
+
environment: config.environment,
|
|
5253
|
+
region: config.region,
|
|
5254
|
+
timeout: config.timeout,
|
|
5255
|
+
debug: config.debug
|
|
5256
|
+
});
|
|
5257
|
+
}
|
|
5258
|
+
/**
|
|
5259
|
+
* List all serverless functions with optional pagination and search.
|
|
5260
|
+
*
|
|
5261
|
+
* @param params - Optional pagination and filter parameters
|
|
5262
|
+
* @returns Paginated list of serverless functions
|
|
5263
|
+
*
|
|
5264
|
+
* @example
|
|
5265
|
+
* ```typescript
|
|
5266
|
+
* const list = await client.serverless.list();
|
|
5267
|
+
* const filtered = await client.serverless.list({ query: 'my-func', limit: 10 });
|
|
5268
|
+
* ```
|
|
5269
|
+
*/
|
|
5270
|
+
async list(params = {}) {
|
|
5271
|
+
return this.apiClient.list(params);
|
|
5272
|
+
}
|
|
5273
|
+
/**
|
|
5274
|
+
* Get a serverless function by its ID.
|
|
5275
|
+
*
|
|
5276
|
+
* @param appId - The serverless function ID
|
|
5277
|
+
* @returns The serverless function details
|
|
5278
|
+
*
|
|
5279
|
+
* @example
|
|
5280
|
+
* ```typescript
|
|
5281
|
+
* const fn = await client.serverless.get('serverless-id');
|
|
5282
|
+
* ```
|
|
5283
|
+
*/
|
|
5284
|
+
async get(appId) {
|
|
5285
|
+
return this.apiClient.get(appId);
|
|
5286
|
+
}
|
|
5287
|
+
/**
|
|
5288
|
+
* Create a new serverless function.
|
|
5289
|
+
*
|
|
5290
|
+
* Supports three runtime types:
|
|
5291
|
+
* - `code` — deploy code directly (blueprint)
|
|
5292
|
+
* - `git` — deploy from a Git repository
|
|
5293
|
+
* - `container` — deploy a Docker container
|
|
5294
|
+
*
|
|
5295
|
+
* @param params - The serverless creation payload
|
|
5296
|
+
* @returns The created serverless function
|
|
5297
|
+
*
|
|
5298
|
+
* @example
|
|
5299
|
+
* ```typescript
|
|
5300
|
+
* const fn = await client.serverless.create({
|
|
5301
|
+
* Name: 'my-api',
|
|
5302
|
+
* Runtime: 'code',
|
|
5303
|
+
* Resources: { CPU: 0.1, MemoryMB: 128, MemoryMaxMB: 128 },
|
|
5304
|
+
* Scaling: { AutoStop: false, Min: 1, Max: 1, MaxIdleTime: 0 },
|
|
5305
|
+
* CodeOpts: { Language: 'nodejs/20', Code: 'module.exports.handler = ...' },
|
|
5306
|
+
* });
|
|
5307
|
+
* ```
|
|
5308
|
+
*/
|
|
5309
|
+
async create(params) {
|
|
5310
|
+
return this.apiClient.create(params);
|
|
5311
|
+
}
|
|
5312
|
+
/**
|
|
5313
|
+
* Create a serverless function and poll until it reaches a terminal state.
|
|
5314
|
+
*
|
|
5315
|
+
* Combines `create()` + `pollStatus()` for a simpler workflow.
|
|
5316
|
+
*
|
|
5317
|
+
* @param params - The serverless creation payload
|
|
5318
|
+
* @returns The final serverless state after reaching a terminal status
|
|
5319
|
+
*
|
|
5320
|
+
* @example
|
|
5321
|
+
* ```typescript
|
|
5322
|
+
* const fn = await client.serverless.createAndWait({
|
|
5323
|
+
* Name: 'my-api',
|
|
5324
|
+
* Runtime: 'code',
|
|
5325
|
+
* CodeOpts: { Language: 'nodejs/20', Code: '...' },
|
|
5326
|
+
* Resources: { CPU: 0.1, MemoryMB: 128, MemoryMaxMB: 128 },
|
|
5327
|
+
* Scaling: { AutoStop: false, Min: 1, Max: 1, MaxIdleTime: 0 },
|
|
5328
|
+
* });
|
|
5329
|
+
* ```
|
|
5330
|
+
*/
|
|
5331
|
+
async createAndWait(params) {
|
|
5332
|
+
const createResult = await this.apiClient.create(params);
|
|
5333
|
+
if (isErrorResponse(createResult)) {
|
|
5334
|
+
return createResult;
|
|
5335
|
+
}
|
|
5336
|
+
const appId = createResult.data?.ID;
|
|
5337
|
+
if (!appId) {
|
|
5338
|
+
return {
|
|
5339
|
+
error: {
|
|
5340
|
+
code: "SERVERLESS_MISSING_ID",
|
|
5341
|
+
message: "Create API response did not contain an ID",
|
|
5342
|
+
meta: []
|
|
5343
|
+
}
|
|
5344
|
+
};
|
|
5345
|
+
}
|
|
5346
|
+
return this.pollStatus(appId);
|
|
5347
|
+
}
|
|
5348
|
+
/**
|
|
5349
|
+
* Update an existing serverless function.
|
|
5350
|
+
*
|
|
5351
|
+
* @param params - The update parameters (appId + partial payload)
|
|
5352
|
+
* @returns The updated serverless function
|
|
5353
|
+
*
|
|
5354
|
+
* @example
|
|
5355
|
+
* ```typescript
|
|
5356
|
+
* const updated = await client.serverless.update({
|
|
5357
|
+
* appId: 'serverless-id',
|
|
5358
|
+
* payload: { Scaling: { AutoStop: true, Min: 0, Max: 3, MaxIdleTime: 300 } },
|
|
5359
|
+
* });
|
|
5360
|
+
* ```
|
|
5361
|
+
*/
|
|
5362
|
+
async update(params) {
|
|
5363
|
+
return this.apiClient.update(params);
|
|
5364
|
+
}
|
|
5365
|
+
/**
|
|
5366
|
+
* Update a serverless function and poll until it reaches a terminal state.
|
|
5367
|
+
*
|
|
5368
|
+
* @param params - The update parameters (appId + partial payload)
|
|
5369
|
+
* @returns The final serverless state after reaching a terminal status
|
|
5370
|
+
*/
|
|
5371
|
+
async updateAndWait(params) {
|
|
5372
|
+
const updateResult = await this.apiClient.update(params);
|
|
5373
|
+
if (isErrorResponse(updateResult)) {
|
|
5374
|
+
return updateResult;
|
|
5375
|
+
}
|
|
5376
|
+
return this.pollStatus(params.appId);
|
|
5377
|
+
}
|
|
5378
|
+
/**
|
|
5379
|
+
* List builds for a serverless function.
|
|
5380
|
+
*
|
|
5381
|
+
* @param params - The app ID and optional pagination
|
|
5382
|
+
* @returns List of builds
|
|
5383
|
+
*
|
|
5384
|
+
* @example
|
|
5385
|
+
* ```typescript
|
|
5386
|
+
* const builds = await client.serverless.getBuilds({ appId: 'serverless-id' });
|
|
5387
|
+
* ```
|
|
5388
|
+
*/
|
|
5389
|
+
async getBuilds(params) {
|
|
5390
|
+
return this.apiClient.getBuilds(params);
|
|
5391
|
+
}
|
|
5392
|
+
/**
|
|
5393
|
+
* Get runtime logs for a serverless function.
|
|
5394
|
+
*
|
|
5395
|
+
* @param params - The app ID and optional time range / pagination
|
|
5396
|
+
* @returns Log entries
|
|
5397
|
+
*
|
|
5398
|
+
* @example
|
|
5399
|
+
* ```typescript
|
|
5400
|
+
* const logs = await client.serverless.getLogs({ appId: 'serverless-id' });
|
|
5401
|
+
* const recentLogs = await client.serverless.getLogs({
|
|
5402
|
+
* appId: 'serverless-id',
|
|
5403
|
+
* limit: 100,
|
|
5404
|
+
* sortOrder: 'DESC',
|
|
5405
|
+
* });
|
|
5406
|
+
* ```
|
|
5407
|
+
*/
|
|
5408
|
+
async getLogs(params) {
|
|
5409
|
+
return this.apiClient.getLogs(params);
|
|
5410
|
+
}
|
|
5411
|
+
/**
|
|
5412
|
+
* Get build logs for a specific build.
|
|
5413
|
+
*
|
|
5414
|
+
* @param params - The app ID and build ID
|
|
5415
|
+
* @returns Build log entries
|
|
5416
|
+
*
|
|
5417
|
+
* @example
|
|
5418
|
+
* ```typescript
|
|
5419
|
+
* const logs = await client.serverless.getBuildLogs({
|
|
5420
|
+
* appId: 'serverless-id',
|
|
5421
|
+
* buildId: 'build-id',
|
|
5422
|
+
* });
|
|
5423
|
+
* ```
|
|
5424
|
+
*/
|
|
5425
|
+
async getBuildLogs(params) {
|
|
5426
|
+
return this.apiClient.getBuildLogs(params);
|
|
5427
|
+
}
|
|
5428
|
+
/**
|
|
5429
|
+
* Poll a serverless function until it reaches a terminal status
|
|
5430
|
+
* (running, failed, degraded, or suspended).
|
|
5431
|
+
*
|
|
5432
|
+
* @param appId - The serverless function ID to poll
|
|
5433
|
+
* @param options - Optional polling configuration overrides
|
|
5434
|
+
* @returns The final serverless state or a timeout error
|
|
5435
|
+
*
|
|
5436
|
+
* @example
|
|
5437
|
+
* ```typescript
|
|
5438
|
+
* const result = await client.serverless.pollStatus('serverless-id');
|
|
5439
|
+
* ```
|
|
5440
|
+
*/
|
|
5441
|
+
async pollStatus(appId, options = {}) {
|
|
5442
|
+
const interval = options.intervalMs ?? STATUS_POLLING_INTERVAL_MS;
|
|
5443
|
+
const maxAttempts = options.maxAttempts ?? MAX_STATUS_POLLING_ATTEMPTS;
|
|
5444
|
+
const debug = this.client.getConfig().debug;
|
|
5445
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
5446
|
+
const result = await this.apiClient.get(appId);
|
|
5447
|
+
if (isErrorResponse(result)) {
|
|
5448
|
+
return result;
|
|
5449
|
+
}
|
|
5450
|
+
const status = result.data?.Status;
|
|
5451
|
+
if (debug) {
|
|
5452
|
+
console.log(
|
|
5453
|
+
`[ServerlessResource] Poll #${attempt + 1}: status=${status}`
|
|
5454
|
+
);
|
|
5455
|
+
}
|
|
5456
|
+
if (status && TERMINAL_STATUSES.includes(status)) {
|
|
5457
|
+
if (debug) {
|
|
5458
|
+
console.log(
|
|
5459
|
+
`[ServerlessResource] Reached terminal state: ${status} after ${attempt + 1} poll(s)`
|
|
5460
|
+
);
|
|
5461
|
+
}
|
|
5462
|
+
return result;
|
|
5463
|
+
}
|
|
5464
|
+
await sleep(interval);
|
|
5465
|
+
}
|
|
5466
|
+
return {
|
|
5467
|
+
error: {
|
|
5468
|
+
code: "SERVERLESS_STATUS_TIMEOUT",
|
|
5469
|
+
message: `Serverless ${appId} did not reach a terminal state within ${maxAttempts} polling attempts`,
|
|
5470
|
+
meta: [
|
|
5471
|
+
`app_id: ${appId}`,
|
|
5472
|
+
`max_attempts: ${maxAttempts}`,
|
|
5473
|
+
`interval_ms: ${interval}`
|
|
5474
|
+
]
|
|
5475
|
+
}
|
|
5476
|
+
};
|
|
5477
|
+
}
|
|
5478
|
+
}
|
|
5479
|
+
class BolticClient {
|
|
5480
|
+
constructor(apiKey, options = {}) {
|
|
5481
|
+
this.currentDatabase = null;
|
|
5482
|
+
this.clientOptions = options;
|
|
5483
|
+
this.configManager = new ConfigManager(
|
|
5484
|
+
apiKey,
|
|
5485
|
+
options.environment || "prod",
|
|
5486
|
+
options.region || "asia-south1",
|
|
5487
|
+
options
|
|
5488
|
+
);
|
|
5489
|
+
const config = this.configManager.getConfig();
|
|
5490
|
+
this.authManager = new AuthManager2({
|
|
5491
|
+
apiKey: config.apiKey,
|
|
5492
|
+
maxRetries: config.maxRetries
|
|
5493
|
+
});
|
|
5494
|
+
this.baseClient = new BaseClient(config, this.authManager);
|
|
5495
|
+
this.tableResource = new TableResource(this.baseClient);
|
|
5496
|
+
this.columnResource = new ColumnResource(this.baseClient);
|
|
5497
|
+
this.recordResource = new RecordResource(this.baseClient);
|
|
5498
|
+
this.sqlResource = new SqlResource(this.baseClient);
|
|
5499
|
+
this.indexResource = new IndexResource(this.baseClient);
|
|
5500
|
+
this.databaseResource = new DatabaseResource(this.baseClient);
|
|
5501
|
+
this.workflowResource = new WorkflowResource(this.baseClient);
|
|
5502
|
+
this.serverlessResource = new ServerlessResource(this.baseClient);
|
|
5503
|
+
this.currentDatabase = null;
|
|
5504
|
+
}
|
|
5505
|
+
/**
|
|
5506
|
+
* Get current database context
|
|
5507
|
+
*/
|
|
5508
|
+
getCurrentDatabase() {
|
|
5509
|
+
return this.currentDatabase;
|
|
5510
|
+
}
|
|
5511
|
+
/**
|
|
5512
|
+
* Switch to a different database using its internal name (slug).
|
|
5513
|
+
* All subsequent operations will use this database.
|
|
5514
|
+
*
|
|
5515
|
+
* If no internal name is provided, the SDK will switch back to the default database.
|
|
5516
|
+
*
|
|
5517
|
+
* @param dbInternalName - Database internal name/slug to switch to. If omitted or empty, default DB is used.
|
|
5518
|
+
*
|
|
5519
|
+
* @example
|
|
5520
|
+
* ```typescript
|
|
5521
|
+
* // Switch to a specific database by slug
|
|
5522
|
+
* await client.useDatabase('my_database_slug');
|
|
5523
|
+
*
|
|
5524
|
+
* // Switch back to default database
|
|
5525
|
+
* await client.useDatabase();
|
|
5526
|
+
* ```
|
|
5527
|
+
*/
|
|
5528
|
+
async useDatabase(dbInternalName) {
|
|
5529
|
+
console.log(`Database internal name:${dbInternalName}`);
|
|
5530
|
+
if (!dbInternalName || dbInternalName === "") {
|
|
5531
|
+
this.currentDatabase = null;
|
|
5532
|
+
return;
|
|
5533
|
+
}
|
|
5534
|
+
const result = await this.databaseResource.findOne(dbInternalName);
|
|
5535
|
+
console.log(`Result:${JSON.stringify(result, null, 2)}`);
|
|
5536
|
+
if (isErrorResponse(result)) {
|
|
5537
|
+
console.log(`Error:${result.error.message}`);
|
|
5538
|
+
throw new Error(
|
|
5539
|
+
result.error.message || `Failed to switch database to internal name '${dbInternalName}'`
|
|
5540
|
+
);
|
|
5541
|
+
}
|
|
5542
|
+
const db = result.data;
|
|
5543
|
+
this.currentDatabase = {
|
|
5544
|
+
databaseId: db.id,
|
|
5545
|
+
dbInternalName: db.db_internal_name || dbInternalName
|
|
5546
|
+
};
|
|
5547
|
+
}
|
|
5548
|
+
// Direct database operations
|
|
4865
5549
|
get databases() {
|
|
4866
5550
|
return {
|
|
4867
5551
|
create: (data) => this.databaseResource.create(data),
|
|
@@ -4970,6 +5654,74 @@ class BolticClient {
|
|
|
4970
5654
|
executeSQL: (query) => this.sqlResource.executeSQL(query, dbId)
|
|
4971
5655
|
};
|
|
4972
5656
|
}
|
|
5657
|
+
/**
|
|
5658
|
+
* Workflow integration operations.
|
|
5659
|
+
*
|
|
5660
|
+
* @example
|
|
5661
|
+
* ```typescript
|
|
5662
|
+
* // Execute and poll for result
|
|
5663
|
+
* const result = await client.workflow.executeIntegration({
|
|
5664
|
+
* nodes: [{ id: 'api1', data: { ... }, activity_data: { ... } }],
|
|
5665
|
+
* });
|
|
5666
|
+
*
|
|
5667
|
+
* // Get execution result by ID
|
|
5668
|
+
* const exec = await client.workflow.getIntegrationExecuteById('run-uuid');
|
|
5669
|
+
*
|
|
5670
|
+
* // List integrations
|
|
5671
|
+
* const integrations = await client.workflow.getIntegrations();
|
|
5672
|
+
* ```
|
|
5673
|
+
*/
|
|
5674
|
+
get workflow() {
|
|
5675
|
+
return {
|
|
5676
|
+
executeIntegration: (params) => this.workflowResource.executeIntegration(params),
|
|
5677
|
+
getIntegrationExecuteById: (executionId) => this.workflowResource.getIntegrationExecuteById(executionId),
|
|
5678
|
+
getIntegrations: (params) => this.workflowResource.getIntegrations(params),
|
|
5679
|
+
getCredentials: (params) => this.workflowResource.getCredentials(params),
|
|
5680
|
+
getIntegrationResource: (params) => this.workflowResource.getIntegrationResource(params),
|
|
5681
|
+
getIntegrationForm: (params) => this.workflowResource.getIntegrationForm(params)
|
|
5682
|
+
};
|
|
5683
|
+
}
|
|
5684
|
+
/**
|
|
5685
|
+
* Serverless function operations.
|
|
5686
|
+
*
|
|
5687
|
+
* @example
|
|
5688
|
+
* ```typescript
|
|
5689
|
+
* // List all serverless functions
|
|
5690
|
+
* const list = await client.serverless.list();
|
|
5691
|
+
*
|
|
5692
|
+
* // Create a new serverless function
|
|
5693
|
+
* const fn = await client.serverless.create({
|
|
5694
|
+
* Name: 'my-api',
|
|
5695
|
+
* Runtime: 'code',
|
|
5696
|
+
* CodeOpts: { Language: 'nodejs/20', Code: '...' },
|
|
5697
|
+
* Resources: { CPU: 0.1, MemoryMB: 128, MemoryMaxMB: 128 },
|
|
5698
|
+
* Scaling: { AutoStop: false, Min: 1, Max: 1, MaxIdleTime: 0 },
|
|
5699
|
+
* });
|
|
5700
|
+
*
|
|
5701
|
+
* // Get a serverless function by ID
|
|
5702
|
+
* const details = await client.serverless.get('serverless-id');
|
|
5703
|
+
*
|
|
5704
|
+
* // Get builds
|
|
5705
|
+
* const builds = await client.serverless.getBuilds({ appId: 'id' });
|
|
5706
|
+
*
|
|
5707
|
+
* // Get runtime logs
|
|
5708
|
+
* const logs = await client.serverless.getLogs({ appId: 'id' });
|
|
5709
|
+
* ```
|
|
5710
|
+
*/
|
|
5711
|
+
get serverless() {
|
|
5712
|
+
return {
|
|
5713
|
+
list: (params) => this.serverlessResource.list(params),
|
|
5714
|
+
get: (appId) => this.serverlessResource.get(appId),
|
|
5715
|
+
create: (params) => this.serverlessResource.create(params),
|
|
5716
|
+
createAndWait: (params) => this.serverlessResource.createAndWait(params),
|
|
5717
|
+
update: (params) => this.serverlessResource.update(params),
|
|
5718
|
+
updateAndWait: (params) => this.serverlessResource.updateAndWait(params),
|
|
5719
|
+
getBuilds: (params) => this.serverlessResource.getBuilds(params),
|
|
5720
|
+
getLogs: (params) => this.serverlessResource.getLogs(params),
|
|
5721
|
+
getBuildLogs: (params) => this.serverlessResource.getBuildLogs(params),
|
|
5722
|
+
pollStatus: (appId, options) => this.serverlessResource.pollStatus(appId, options)
|
|
5723
|
+
};
|
|
5724
|
+
}
|
|
4973
5725
|
// SQL resource access for testing
|
|
4974
5726
|
getSqlResource() {
|
|
4975
5727
|
return this.sqlResource;
|
|
@@ -5052,6 +5804,8 @@ class BolticClient {
|
|
|
5052
5804
|
this.sqlResource = new SqlResource(this.baseClient);
|
|
5053
5805
|
this.indexResource = new IndexResource(this.baseClient);
|
|
5054
5806
|
this.databaseResource = new DatabaseResource(this.baseClient);
|
|
5807
|
+
this.workflowResource = new WorkflowResource(this.baseClient);
|
|
5808
|
+
this.serverlessResource = new ServerlessResource(this.baseClient);
|
|
5055
5809
|
}
|
|
5056
5810
|
// Security methods to prevent API key exposure
|
|
5057
5811
|
toString() {
|
|
@@ -5080,13 +5834,25 @@ const VERSION = "1.0.0";
|
|
|
5080
5834
|
export {
|
|
5081
5835
|
AuthManager$1 as AuthManager,
|
|
5082
5836
|
BolticClient,
|
|
5837
|
+
DEFAULT_RESOURCES,
|
|
5838
|
+
DEFAULT_SCALING,
|
|
5839
|
+
MAX_STATUS_POLLING_ATTEMPTS,
|
|
5840
|
+
SERVICE_PATHS,
|
|
5841
|
+
STATUS_POLLING_INTERVAL_MS,
|
|
5842
|
+
ServerlessApiClient,
|
|
5843
|
+
ServerlessResource,
|
|
5844
|
+
TERMINAL_STATUSES,
|
|
5083
5845
|
VERSION,
|
|
5846
|
+
WorkflowResource,
|
|
5084
5847
|
createClient,
|
|
5085
5848
|
createErrorWithContext$1 as createErrorWithContext,
|
|
5086
5849
|
formatError$1 as formatError,
|
|
5087
5850
|
getHttpStatusCode$1 as getHttpStatusCode,
|
|
5088
5851
|
isErrorResponse,
|
|
5089
5852
|
isListResponse,
|
|
5090
|
-
isNetworkError
|
|
5853
|
+
isNetworkError,
|
|
5854
|
+
resolveServiceURL,
|
|
5855
|
+
transformFormToDefaults,
|
|
5856
|
+
transformFormToJsonSchema
|
|
5091
5857
|
};
|
|
5092
5858
|
//# sourceMappingURL=sdk.mjs.map
|