@hoststack.dev/sdk 0.4.0 → 0.6.0
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 +18 -14
- package/dist/index.cjs +104 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +192 -10
- package/dist/index.d.ts +192 -10
- package/dist/index.js +104 -21
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -53,19 +53,22 @@ Generate an API key from your [HostStack dashboard → Settings → API Keys](ht
|
|
|
53
53
|
|
|
54
54
|
## Resources
|
|
55
55
|
|
|
56
|
-
| Resource
|
|
57
|
-
|
|
|
58
|
-
| `client.projects`
|
|
59
|
-
| `client.services`
|
|
60
|
-
| `client.deploys`
|
|
61
|
-
| `client.databases`
|
|
62
|
-
| `client.domains`
|
|
63
|
-
| `client.envVars`
|
|
64
|
-
| `client.
|
|
65
|
-
| `client.
|
|
66
|
-
| `client.
|
|
67
|
-
|
|
68
|
-
|
|
56
|
+
| Resource | Methods |
|
|
57
|
+
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
58
|
+
| `client.projects` | `list`, `get`, `create`, `update`, `delete` |
|
|
59
|
+
| `client.services` | `list`, `get`, `create`, `update`, `delete`, `suspend`, `resume`, `getMetrics`, `getConfig`, `updateConfig`, `getRuntimeLogs`, `streamLogs` |
|
|
60
|
+
| `client.deploys` | `list`, `get`, `trigger`, `cancel`, `rollback`, `promote`, `getLogs` |
|
|
61
|
+
| `client.databases` | `list`, `get`, `create`, `update`, `delete`, `suspend`, `resume`, `getCredentials`, `resetPassword` |
|
|
62
|
+
| `client.domains` | `list`, `add`, `update`, `remove`, `verify` |
|
|
63
|
+
| `client.envVars` | `list`, `create`, `update`, `delete`, `bulkSet` |
|
|
64
|
+
| `client.volumes` | `list`, `create`, `update`, `delete` |
|
|
65
|
+
| `client.environments` | `list`, `get`, `create`, `update`, `delete` |
|
|
66
|
+
| `client.cron` | `list`, `get`, `trigger` |
|
|
67
|
+
| `client.notifications` | `listChannels`, `createChannel`, `updateChannel`, `deleteChannel`, `testChannel` |
|
|
68
|
+
|
|
69
|
+
Every method's first argument is the team id — accepts either the numeric id or the `team_…` publicId (the SDK resolves publicIds to numeric ids internally and caches the lookup). Full API reference: **[hoststack.dev/docs/sdk](https://hoststack.dev/docs/sdk)**.
|
|
70
|
+
|
|
71
|
+
`client.deploys.promote(teamId, serviceId, deployId, targetEnvironmentId)` performs image-based promotion: it pins the same built image into a sibling environment without rebuilding.
|
|
69
72
|
|
|
70
73
|
## Error handling
|
|
71
74
|
|
|
@@ -96,7 +99,8 @@ try {
|
|
|
96
99
|
## Related packages
|
|
97
100
|
|
|
98
101
|
- **[@hoststack.dev/cli](https://www.npmjs.com/package/@hoststack.dev/cli)** — command-line interface for HostStack
|
|
99
|
-
- **[
|
|
102
|
+
- **[@hoststack.dev/mcp](https://www.npmjs.com/package/@hoststack.dev/mcp)** — MCP server for Claude, Cursor, and other AI agents
|
|
103
|
+
- **Terraform provider** — see [hoststack.dev/docs](https://hoststack.dev/docs) for installation and resource reference
|
|
100
104
|
|
|
101
105
|
## Support
|
|
102
106
|
|
package/dist/index.cjs
CHANGED
|
@@ -198,11 +198,9 @@ var DeploysResource = class {
|
|
|
198
198
|
teamId: tid,
|
|
199
199
|
serviceId: sid
|
|
200
200
|
});
|
|
201
|
-
return this.client.request(
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
{ targetEnvironmentId }
|
|
205
|
-
);
|
|
201
|
+
return this.client.request("POST", `/api/services/${tid}/${sid}/deploys/${did}/promote`, {
|
|
202
|
+
targetEnvironmentId
|
|
203
|
+
});
|
|
206
204
|
}
|
|
207
205
|
/**
|
|
208
206
|
* Get build logs for a deploy.
|
|
@@ -356,6 +354,62 @@ var EnvVarsResource = class {
|
|
|
356
354
|
}
|
|
357
355
|
};
|
|
358
356
|
|
|
357
|
+
// src/resources/notifications.ts
|
|
358
|
+
var NotificationsResource = class {
|
|
359
|
+
constructor(client) {
|
|
360
|
+
this.client = client;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* List notification channels for the team. Webhook URLs are
|
|
364
|
+
* server-side masked in the response so this is safe to log.
|
|
365
|
+
*/
|
|
366
|
+
async listChannels(teamId) {
|
|
367
|
+
const tid = await this.client.resolveId(teamId, { kind: "team" });
|
|
368
|
+
return this.client.request("GET", `/api/notifications/${tid}/channels`);
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Create a Slack/Discord/email notification channel.
|
|
372
|
+
*
|
|
373
|
+
* For type=email, `webhookUrl` is the recipient email address; for
|
|
374
|
+
* type=slack/discord it's the incoming webhook URL.
|
|
375
|
+
*
|
|
376
|
+
* `events` is the explicit subscription list — an empty array means
|
|
377
|
+
* "receive nothing". The platform pre-selects the critical-event
|
|
378
|
+
* set on the dashboard, but SDK callers must pass the list
|
|
379
|
+
* explicitly so behaviour is deterministic.
|
|
380
|
+
*/
|
|
381
|
+
async createChannel(teamId, data) {
|
|
382
|
+
const tid = await this.client.resolveId(teamId, { kind: "team" });
|
|
383
|
+
return this.client.request("POST", `/api/notifications/${tid}/channels`, data);
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Update a channel's name / active state / event subscriptions. The
|
|
387
|
+
* webhook URL and type are immutable — create a new channel if
|
|
388
|
+
* those need to change.
|
|
389
|
+
*/
|
|
390
|
+
async updateChannel(teamId, channelId, data) {
|
|
391
|
+
const tid = await this.client.resolveId(teamId, { kind: "team" });
|
|
392
|
+
return this.client.request(
|
|
393
|
+
"PATCH",
|
|
394
|
+
`/api/notifications/${tid}/channels/${channelId}`,
|
|
395
|
+
data
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
/** Delete a notification channel. */
|
|
399
|
+
async deleteChannel(teamId, channelId) {
|
|
400
|
+
const tid = await this.client.resolveId(teamId, { kind: "team" });
|
|
401
|
+
return this.client.request("DELETE", `/api/notifications/${tid}/channels/${channelId}`);
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Fire a test event to the channel so the user can confirm the
|
|
405
|
+
* webhook is wired correctly. Returns the dispatch outcome.
|
|
406
|
+
*/
|
|
407
|
+
async testChannel(teamId, channelId) {
|
|
408
|
+
const tid = await this.client.resolveId(teamId, { kind: "team" });
|
|
409
|
+
return this.client.request("POST", `/api/notifications/${tid}/channels/${channelId}/test`);
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
|
|
359
413
|
// src/resources/projects.ts
|
|
360
414
|
var ProjectsResource = class {
|
|
361
415
|
constructor(client) {
|
|
@@ -453,10 +507,23 @@ var ServicesResource = class {
|
|
|
453
507
|
constructor(client) {
|
|
454
508
|
this.client = client;
|
|
455
509
|
}
|
|
456
|
-
/**
|
|
457
|
-
|
|
510
|
+
/**
|
|
511
|
+
* List services for the active team.
|
|
512
|
+
*
|
|
513
|
+
* Optional filters narrow by project, environment, status, or type.
|
|
514
|
+
* The server treats unknown enum values as no match (returns empty)
|
|
515
|
+
* rather than 400-ing.
|
|
516
|
+
*/
|
|
517
|
+
async list(teamId, filters) {
|
|
458
518
|
const tid = await this.client.resolveId(teamId, { kind: "team" });
|
|
459
|
-
|
|
519
|
+
const params = new URLSearchParams();
|
|
520
|
+
if (filters?.projectId !== void 0) params.set("projectId", String(filters.projectId));
|
|
521
|
+
if (filters?.environmentId !== void 0)
|
|
522
|
+
params.set("environmentId", String(filters.environmentId));
|
|
523
|
+
if (filters?.status) params.set("status", filters.status);
|
|
524
|
+
if (filters?.type) params.set("type", filters.type);
|
|
525
|
+
const qs = params.toString();
|
|
526
|
+
return this.client.request("GET", `/api/services/${tid}${qs ? `?${qs}` : ""}`);
|
|
460
527
|
}
|
|
461
528
|
/** Get a single service by ID. */
|
|
462
529
|
async get(teamId, serviceId) {
|
|
@@ -499,6 +566,25 @@ var ServicesResource = class {
|
|
|
499
566
|
const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
|
|
500
567
|
return this.client.request("GET", `/api/services/${tid}/${sid}/metrics`);
|
|
501
568
|
}
|
|
569
|
+
/**
|
|
570
|
+
* Get a metrics time series for a service.
|
|
571
|
+
*
|
|
572
|
+
* `from`/`to` accept ISO-8601 timestamps. Omit both for the trailing
|
|
573
|
+
* hour. Server picks the resolution: raw samples ≤7d, hourly pre-
|
|
574
|
+
* aggregates ≤30d, daily beyond that. Up to ~500 points returned.
|
|
575
|
+
*/
|
|
576
|
+
async getMetricsHistory(teamId, serviceId, options) {
|
|
577
|
+
const tid = await this.client.resolveId(teamId, { kind: "team" });
|
|
578
|
+
const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
|
|
579
|
+
const params = new URLSearchParams();
|
|
580
|
+
if (options?.from) params.set("from", options.from);
|
|
581
|
+
if (options?.to) params.set("to", options.to);
|
|
582
|
+
const qs = params.toString();
|
|
583
|
+
return this.client.request(
|
|
584
|
+
"GET",
|
|
585
|
+
`/api/services/${tid}/${sid}/metrics/history${qs ? `?${qs}` : ""}`
|
|
586
|
+
);
|
|
587
|
+
}
|
|
502
588
|
/** Get service configuration. */
|
|
503
589
|
async getConfig(teamId, serviceId) {
|
|
504
590
|
const tid = await this.client.resolveId(teamId, { kind: "team" });
|
|
@@ -557,11 +643,7 @@ var ServicesResource = class {
|
|
|
557
643
|
const tid = await this.client.resolveId(teamId, { kind: "team" });
|
|
558
644
|
const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
|
|
559
645
|
const basePath = `/api/services/${tid}/${sid}/runtime-logs`;
|
|
560
|
-
yield* streamLogsViaPolling(
|
|
561
|
-
(path) => this.client.request("GET", path),
|
|
562
|
-
basePath,
|
|
563
|
-
options
|
|
564
|
-
);
|
|
646
|
+
yield* streamLogsViaPolling((path) => this.client.request("GET", path), basePath, options);
|
|
565
647
|
}
|
|
566
648
|
};
|
|
567
649
|
|
|
@@ -649,6 +731,12 @@ var HostStack = class {
|
|
|
649
731
|
cron;
|
|
650
732
|
/** Manage persistent disks attached to services. */
|
|
651
733
|
volumes;
|
|
734
|
+
/**
|
|
735
|
+
* Manage notification channels — Slack/Discord webhooks + email
|
|
736
|
+
* recipients with per-channel event filters. Used for deploy
|
|
737
|
+
* failures, restart loops, ACME failures, git auth losses, etc.
|
|
738
|
+
*/
|
|
739
|
+
notifications;
|
|
652
740
|
constructor(options) {
|
|
653
741
|
if (!options.apiKey) {
|
|
654
742
|
throw new Error("apiKey is required");
|
|
@@ -664,6 +752,7 @@ var HostStack = class {
|
|
|
664
752
|
this.environments = new EnvironmentsResource(this);
|
|
665
753
|
this.cron = new CronResource(this);
|
|
666
754
|
this.volumes = new VolumesResource(this);
|
|
755
|
+
this.notifications = new NotificationsResource(this);
|
|
667
756
|
}
|
|
668
757
|
/**
|
|
669
758
|
* Make an authenticated request to the HostStack API.
|
|
@@ -755,17 +844,11 @@ var HostStack = class {
|
|
|
755
844
|
return r.services ?? [];
|
|
756
845
|
}
|
|
757
846
|
case "deploy": {
|
|
758
|
-
const r = await this.request(
|
|
759
|
-
"GET",
|
|
760
|
-
`/api/services/${scope.teamId}/${scope.serviceId}/deploys?perPage=100`
|
|
761
|
-
);
|
|
847
|
+
const r = await this.request("GET", `/api/services/${scope.teamId}/${scope.serviceId}/deploys?perPage=100`);
|
|
762
848
|
return r.data ?? [];
|
|
763
849
|
}
|
|
764
850
|
case "database": {
|
|
765
|
-
const r = await this.request(
|
|
766
|
-
"GET",
|
|
767
|
-
`/api/databases/${scope.teamId}`
|
|
768
|
-
);
|
|
851
|
+
const r = await this.request("GET", `/api/databases/${scope.teamId}`);
|
|
769
852
|
return r.databases ?? [];
|
|
770
853
|
}
|
|
771
854
|
case "domain": {
|