@boltic/sdk 0.1.3 → 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/dist/sdk.mjs CHANGED
@@ -547,7 +547,8 @@ class AuthManager2 {
547
547
  const SERVICE_PATHS = {
548
548
  DATABASES: "/service/sdk/boltic-tables/v1",
549
549
  WORKFLOW_TEMPORAL: "/service/panel/temporal/v1.0",
550
- INTEGRATION: "/service/panel/integration/v1"
550
+ INTEGRATION: "/service/panel/integration/v1",
551
+ SERVERLESS: "/service/panel/serverless/v1.0"
551
552
  };
552
553
  class BaseApiClient {
553
554
  constructor(apiKey, config = {}, servicePath = SERVICE_PATHS.DATABASES) {
@@ -4784,7 +4785,7 @@ function buildExecuteActivityBody(params) {
4784
4785
  result: params.result ?? buildDefaultResultPayload()
4785
4786
  };
4786
4787
  }
4787
- function sleep(ms) {
4788
+ function sleep$1(ms) {
4788
4789
  return new Promise((resolve) => setTimeout(resolve, ms));
4789
4790
  }
4790
4791
  class WorkflowResource extends BaseResource {
@@ -4982,7 +4983,7 @@ class WorkflowResource extends BaseResource {
4982
4983
  }
4983
4984
  return result;
4984
4985
  }
4985
- await sleep(POLLING_INTERVAL_MS);
4986
+ await sleep$1(POLLING_INTERVAL_MS);
4986
4987
  }
4987
4988
  return {
4988
4989
  error: {
@@ -4996,6 +4997,485 @@ class WorkflowResource extends BaseResource {
4996
4997
  };
4997
4998
  }
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
+ }
4999
5479
  class BolticClient {
5000
5480
  constructor(apiKey, options = {}) {
5001
5481
  this.currentDatabase = null;
@@ -5019,6 +5499,7 @@ class BolticClient {
5019
5499
  this.indexResource = new IndexResource(this.baseClient);
5020
5500
  this.databaseResource = new DatabaseResource(this.baseClient);
5021
5501
  this.workflowResource = new WorkflowResource(this.baseClient);
5502
+ this.serverlessResource = new ServerlessResource(this.baseClient);
5022
5503
  this.currentDatabase = null;
5023
5504
  }
5024
5505
  /**
@@ -5200,6 +5681,47 @@ class BolticClient {
5200
5681
  getIntegrationForm: (params) => this.workflowResource.getIntegrationForm(params)
5201
5682
  };
5202
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
+ }
5203
5725
  // SQL resource access for testing
5204
5726
  getSqlResource() {
5205
5727
  return this.sqlResource;
@@ -5283,6 +5805,7 @@ class BolticClient {
5283
5805
  this.indexResource = new IndexResource(this.baseClient);
5284
5806
  this.databaseResource = new DatabaseResource(this.baseClient);
5285
5807
  this.workflowResource = new WorkflowResource(this.baseClient);
5808
+ this.serverlessResource = new ServerlessResource(this.baseClient);
5286
5809
  }
5287
5810
  // Security methods to prevent API key exposure
5288
5811
  toString() {
@@ -5311,7 +5834,14 @@ const VERSION = "1.0.0";
5311
5834
  export {
5312
5835
  AuthManager$1 as AuthManager,
5313
5836
  BolticClient,
5837
+ DEFAULT_RESOURCES,
5838
+ DEFAULT_SCALING,
5839
+ MAX_STATUS_POLLING_ATTEMPTS,
5314
5840
  SERVICE_PATHS,
5841
+ STATUS_POLLING_INTERVAL_MS,
5842
+ ServerlessApiClient,
5843
+ ServerlessResource,
5844
+ TERMINAL_STATUSES,
5315
5845
  VERSION,
5316
5846
  WorkflowResource,
5317
5847
  createClient,