@hoststack.dev/sdk 0.1.0 → 0.2.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/dist/index.js CHANGED
@@ -31,30 +31,34 @@ var CronResource = class {
31
31
  constructor(client) {
32
32
  this.client = client;
33
33
  }
34
- client;
35
34
  /** List cron executions for a service. */
36
35
  async list(teamId, serviceId, options) {
36
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
37
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
37
38
  const params = new URLSearchParams();
38
39
  if (options?.limit) params.set("limit", String(options.limit));
39
40
  const qs = params.toString();
40
41
  return this.client.request(
41
42
  "GET",
42
- `/api/services/${teamId}/${serviceId}/cron-executions${qs ? `?${qs}` : ""}`
43
+ `/api/services/${tid}/${sid}/cron-executions${qs ? `?${qs}` : ""}`
43
44
  );
44
45
  }
45
46
  /** Get a single cron execution by ID. */
46
47
  async get(teamId, serviceId, executionId) {
47
- return this.client.request(
48
- "GET",
49
- `/api/services/${teamId}/${serviceId}/cron-executions/${executionId}`
50
- );
48
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
49
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
50
+ const eid = await this.client.resolveId(executionId, {
51
+ kind: "cronExecution",
52
+ teamId: tid,
53
+ serviceId: sid
54
+ });
55
+ return this.client.request("GET", `/api/services/${tid}/${sid}/cron-executions/${eid}`);
51
56
  }
52
57
  /** Trigger an immediate cron execution. */
53
58
  async trigger(teamId, serviceId) {
54
- return this.client.request(
55
- "POST",
56
- `/api/services/${teamId}/${serviceId}/cron-executions/trigger`
57
- );
59
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
60
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
61
+ return this.client.request("POST", `/api/services/${tid}/${sid}/cron-executions/trigger`);
58
62
  }
59
63
  };
60
64
 
@@ -63,42 +67,58 @@ var DatabasesResource = class {
63
67
  constructor(client) {
64
68
  this.client = client;
65
69
  }
66
- client;
67
70
  /** List all databases for a project. */
68
71
  async list(teamId, projectId) {
69
- return this.client.request("GET", `/api/databases/${teamId}?projectId=${projectId}`);
72
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
73
+ const pid = await this.client.resolveId(projectId, { kind: "project", teamId: tid });
74
+ return this.client.request("GET", `/api/databases/${tid}?projectId=${pid}`);
70
75
  }
71
76
  /** Get a single database by ID. */
72
77
  async get(teamId, databaseId) {
73
- return this.client.request("GET", `/api/databases/${teamId}/${databaseId}`);
78
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
79
+ const did = await this.client.resolveId(databaseId, { kind: "database", teamId: tid });
80
+ return this.client.request("GET", `/api/databases/${tid}/${did}`);
74
81
  }
75
82
  /** Create a new database. */
76
83
  async create(teamId, data) {
77
- return this.client.request("POST", `/api/databases/${teamId}`, data);
84
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
85
+ return this.client.request("POST", `/api/databases/${tid}`, data);
78
86
  }
79
87
  /** Update a database. */
80
88
  async update(teamId, databaseId, data) {
81
- return this.client.request("PATCH", `/api/databases/${teamId}/${databaseId}`, data);
89
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
90
+ const did = await this.client.resolveId(databaseId, { kind: "database", teamId: tid });
91
+ return this.client.request("PATCH", `/api/databases/${tid}/${did}`, data);
82
92
  }
83
93
  /** Delete a database. */
84
94
  async delete(teamId, databaseId) {
85
- return this.client.request("DELETE", `/api/databases/${teamId}/${databaseId}`);
95
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
96
+ const did = await this.client.resolveId(databaseId, { kind: "database", teamId: tid });
97
+ return this.client.request("DELETE", `/api/databases/${tid}/${did}`);
86
98
  }
87
99
  /** Suspend a database. */
88
100
  async suspend(teamId, databaseId) {
89
- return this.client.request("POST", `/api/databases/${teamId}/${databaseId}/suspend`);
101
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
102
+ const did = await this.client.resolveId(databaseId, { kind: "database", teamId: tid });
103
+ return this.client.request("POST", `/api/databases/${tid}/${did}/suspend`);
90
104
  }
91
105
  /** Resume a suspended database. */
92
106
  async resume(teamId, databaseId) {
93
- return this.client.request("POST", `/api/databases/${teamId}/${databaseId}/resume`);
107
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
108
+ const did = await this.client.resolveId(databaseId, { kind: "database", teamId: tid });
109
+ return this.client.request("POST", `/api/databases/${tid}/${did}/resume`);
94
110
  }
95
111
  /** Get connection credentials. */
96
112
  async getCredentials(teamId, databaseId) {
97
- return this.client.request("GET", `/api/databases/${teamId}/${databaseId}/credentials`);
113
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
114
+ const did = await this.client.resolveId(databaseId, { kind: "database", teamId: tid });
115
+ return this.client.request("GET", `/api/databases/${tid}/${did}/credentials`);
98
116
  }
99
117
  /** Reset the database password. */
100
118
  async resetPassword(teamId, databaseId) {
101
- return this.client.request("POST", `/api/databases/${teamId}/${databaseId}/reset-password`);
119
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
120
+ const did = await this.client.resolveId(databaseId, { kind: "database", teamId: tid });
121
+ return this.client.request("POST", `/api/databases/${tid}/${did}/reset-password`);
102
122
  }
103
123
  };
104
124
 
@@ -107,46 +127,61 @@ var DeploysResource = class {
107
127
  constructor(client) {
108
128
  this.client = client;
109
129
  }
110
- client;
111
130
  /** List deploys for a service. */
112
131
  async list(teamId, serviceId) {
113
- return this.client.request("GET", `/api/services/${teamId}/${serviceId}/deploys`);
132
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
133
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
134
+ return this.client.request("GET", `/api/services/${tid}/${sid}/deploys`);
114
135
  }
115
136
  /** Get a single deploy by ID. */
116
137
  async get(teamId, serviceId, deployId) {
117
- return this.client.request(
118
- "GET",
119
- `/api/services/${teamId}/${serviceId}/deploys/${deployId}`
120
- );
138
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
139
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
140
+ const did = await this.client.resolveId(deployId, {
141
+ kind: "deploy",
142
+ teamId: tid,
143
+ serviceId: sid
144
+ });
145
+ return this.client.request("GET", `/api/services/${tid}/${sid}/deploys/${did}`);
121
146
  }
122
147
  /** Trigger a new deploy. */
123
148
  async trigger(teamId, serviceId, data) {
124
- return this.client.request(
125
- "POST",
126
- `/api/services/${teamId}/${serviceId}/deploys`,
127
- data ?? {}
128
- );
149
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
150
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
151
+ return this.client.request("POST", `/api/services/${tid}/${sid}/deploys`, data ?? {});
129
152
  }
130
153
  /** Cancel an in-progress deploy. */
131
154
  async cancel(teamId, serviceId, deployId) {
132
- return this.client.request(
133
- "POST",
134
- `/api/services/${teamId}/${serviceId}/deploys/${deployId}/cancel`
135
- );
155
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
156
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
157
+ const did = await this.client.resolveId(deployId, {
158
+ kind: "deploy",
159
+ teamId: tid,
160
+ serviceId: sid
161
+ });
162
+ return this.client.request("POST", `/api/services/${tid}/${sid}/deploys/${did}/cancel`);
136
163
  }
137
164
  /** Rollback to a previous deploy. */
138
165
  async rollback(teamId, serviceId, deployId) {
139
- return this.client.request(
140
- "POST",
141
- `/api/services/${teamId}/${serviceId}/deploys/${deployId}/rollback`
142
- );
166
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
167
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
168
+ const did = await this.client.resolveId(deployId, {
169
+ kind: "deploy",
170
+ teamId: tid,
171
+ serviceId: sid
172
+ });
173
+ return this.client.request("POST", `/api/services/${tid}/${sid}/deploys/${did}/rollback`);
143
174
  }
144
175
  /** Get build logs for a deploy. */
145
176
  async getLogs(teamId, serviceId, deployId) {
146
- return this.client.request(
147
- "GET",
148
- `/api/services/${teamId}/${serviceId}/deploys/${deployId}/logs`
149
- );
177
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
178
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
179
+ const did = await this.client.resolveId(deployId, {
180
+ kind: "deploy",
181
+ teamId: tid,
182
+ serviceId: sid
183
+ });
184
+ return this.client.request("GET", `/api/services/${tid}/${sid}/deploys/${did}/logs`);
150
185
  }
151
186
  };
152
187
 
@@ -155,26 +190,33 @@ var DomainsResource = class {
155
190
  constructor(client) {
156
191
  this.client = client;
157
192
  }
158
- client;
159
193
  /** List all domains for the active team. */
160
194
  async list(teamId) {
161
- return this.client.request("GET", `/api/domains/${teamId}`);
195
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
196
+ return this.client.request("GET", `/api/domains/${tid}`);
162
197
  }
163
198
  /** Add a custom domain. */
164
199
  async add(teamId, data) {
165
- return this.client.request("POST", `/api/domains/${teamId}`, data);
200
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
201
+ return this.client.request("POST", `/api/domains/${tid}`, data);
166
202
  }
167
203
  /** Update a domain. */
168
204
  async update(teamId, domainId, data) {
169
- return this.client.request("PATCH", `/api/domains/${teamId}/${domainId}`, data);
205
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
206
+ const did = await this.client.resolveId(domainId, { kind: "domain", teamId: tid });
207
+ return this.client.request("PATCH", `/api/domains/${tid}/${did}`, data);
170
208
  }
171
209
  /** Remove a domain. */
172
210
  async remove(teamId, domainId) {
173
- return this.client.request("DELETE", `/api/domains/${teamId}/${domainId}`);
211
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
212
+ const did = await this.client.resolveId(domainId, { kind: "domain", teamId: tid });
213
+ return this.client.request("DELETE", `/api/domains/${tid}/${did}`);
174
214
  }
175
215
  /** Verify domain DNS configuration. */
176
216
  async verify(teamId, domainId) {
177
- return this.client.request("POST", `/api/domains/${teamId}/${domainId}/verify`);
217
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
218
+ const did = await this.client.resolveId(domainId, { kind: "domain", teamId: tid });
219
+ return this.client.request("POST", `/api/domains/${tid}/${did}/verify`);
178
220
  }
179
221
  };
180
222
 
@@ -183,33 +225,45 @@ var EnvVarsResource = class {
183
225
  constructor(client) {
184
226
  this.client = client;
185
227
  }
186
- client;
187
228
  /** List all environment variables for a service. */
188
229
  async list(teamId, serviceId) {
189
- return this.client.request("GET", `/api/services/${teamId}/${serviceId}/env`);
230
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
231
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
232
+ return this.client.request("GET", `/api/services/${tid}/${sid}/env`);
190
233
  }
191
234
  /** Create a new environment variable. */
192
235
  async create(teamId, serviceId, data) {
193
- return this.client.request("POST", `/api/services/${teamId}/${serviceId}/env`, data);
236
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
237
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
238
+ return this.client.request("POST", `/api/services/${tid}/${sid}/env`, data);
194
239
  }
195
240
  /** Update an environment variable. */
196
241
  async update(teamId, serviceId, envVarId, data) {
197
- return this.client.request(
198
- "PATCH",
199
- `/api/services/${teamId}/${serviceId}/env/${envVarId}`,
200
- data
201
- );
242
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
243
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
244
+ const eid = await this.client.resolveId(envVarId, {
245
+ kind: "envVar",
246
+ teamId: tid,
247
+ serviceId: sid
248
+ });
249
+ return this.client.request("PATCH", `/api/services/${tid}/${sid}/env/${eid}`, data);
202
250
  }
203
251
  /** Delete an environment variable. */
204
252
  async delete(teamId, serviceId, envVarId) {
205
- return this.client.request(
206
- "DELETE",
207
- `/api/services/${teamId}/${serviceId}/env/${envVarId}`
208
- );
253
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
254
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
255
+ const eid = await this.client.resolveId(envVarId, {
256
+ kind: "envVar",
257
+ teamId: tid,
258
+ serviceId: sid
259
+ });
260
+ return this.client.request("DELETE", `/api/services/${tid}/${sid}/env/${eid}`);
209
261
  }
210
262
  /** Bulk set environment variables (create or update). */
211
263
  async bulkSet(teamId, serviceId, data) {
212
- return this.client.request("PUT", `/api/services/${teamId}/${serviceId}/env/bulk`, data);
264
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
265
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
266
+ return this.client.request("PUT", `/api/services/${tid}/${sid}/env/bulk`, data);
213
267
  }
214
268
  };
215
269
 
@@ -218,26 +272,33 @@ var ProjectsResource = class {
218
272
  constructor(client) {
219
273
  this.client = client;
220
274
  }
221
- client;
222
275
  /** List all projects for the active team. */
223
276
  async list(teamId) {
224
- return this.client.request("GET", `/api/projects/${teamId}`);
277
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
278
+ return this.client.request("GET", `/api/projects/${tid}`);
225
279
  }
226
280
  /** Get a single project by ID. */
227
281
  async get(teamId, projectId) {
228
- return this.client.request("GET", `/api/projects/${teamId}/${projectId}`);
282
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
283
+ const pid = await this.client.resolveId(projectId, { kind: "project", teamId: tid });
284
+ return this.client.request("GET", `/api/projects/${tid}/${pid}`);
229
285
  }
230
286
  /** Create a new project. */
231
287
  async create(teamId, data) {
232
- return this.client.request("POST", `/api/projects/${teamId}`, data);
288
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
289
+ return this.client.request("POST", `/api/projects/${tid}`, data);
233
290
  }
234
291
  /** Update a project. */
235
292
  async update(teamId, projectId, data) {
236
- return this.client.request("PATCH", `/api/projects/${teamId}/${projectId}`, data);
293
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
294
+ const pid = await this.client.resolveId(projectId, { kind: "project", teamId: tid });
295
+ return this.client.request("PATCH", `/api/projects/${tid}/${pid}`, data);
237
296
  }
238
297
  /** Delete a project. */
239
298
  async delete(teamId, projectId) {
240
- return this.client.request("DELETE", `/api/projects/${teamId}/${projectId}`);
299
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
300
+ const pid = await this.client.resolveId(projectId, { kind: "project", teamId: tid });
301
+ return this.client.request("DELETE", `/api/projects/${tid}/${pid}`);
241
302
  }
242
303
  };
243
304
 
@@ -303,49 +364,68 @@ var ServicesResource = class {
303
364
  constructor(client) {
304
365
  this.client = client;
305
366
  }
306
- client;
307
367
  /** List all services for the active team. */
308
368
  async list(teamId) {
309
- return this.client.request("GET", `/api/services/${teamId}`);
369
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
370
+ return this.client.request("GET", `/api/services/${tid}`);
310
371
  }
311
372
  /** Get a single service by ID. */
312
373
  async get(teamId, serviceId) {
313
- return this.client.request("GET", `/api/services/${teamId}/${serviceId}`);
374
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
375
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
376
+ return this.client.request("GET", `/api/services/${tid}/${sid}`);
314
377
  }
315
378
  /** Create a new service. */
316
379
  async create(teamId, data) {
317
- return this.client.request("POST", `/api/services/${teamId}`, data);
380
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
381
+ return this.client.request("POST", `/api/services/${tid}`, data);
318
382
  }
319
383
  /** Update a service. */
320
384
  async update(teamId, serviceId, data) {
321
- return this.client.request("PATCH", `/api/services/${teamId}/${serviceId}`, data);
385
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
386
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
387
+ return this.client.request("PATCH", `/api/services/${tid}/${sid}`, data);
322
388
  }
323
389
  /** Delete a service. */
324
390
  async delete(teamId, serviceId) {
325
- return this.client.request("DELETE", `/api/services/${teamId}/${serviceId}`);
391
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
392
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
393
+ return this.client.request("DELETE", `/api/services/${tid}/${sid}`);
326
394
  }
327
395
  /** Suspend a service. */
328
396
  async suspend(teamId, serviceId) {
329
- return this.client.request("POST", `/api/services/${teamId}/${serviceId}/suspend`);
397
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
398
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
399
+ return this.client.request("POST", `/api/services/${tid}/${sid}/suspend`);
330
400
  }
331
401
  /** Resume a suspended service. */
332
402
  async resume(teamId, serviceId) {
333
- return this.client.request("POST", `/api/services/${teamId}/${serviceId}/resume`);
403
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
404
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
405
+ return this.client.request("POST", `/api/services/${tid}/${sid}/resume`);
334
406
  }
335
407
  /** Get service metrics. */
336
408
  async getMetrics(teamId, serviceId) {
337
- return this.client.request("GET", `/api/services/${teamId}/${serviceId}/metrics`);
409
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
410
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
411
+ return this.client.request("GET", `/api/services/${tid}/${sid}/metrics`);
338
412
  }
339
413
  /** Get service configuration. */
340
414
  async getConfig(teamId, serviceId) {
341
- return this.client.request("GET", `/api/services/${teamId}/${serviceId}/config`);
415
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
416
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
417
+ return this.client.request("GET", `/api/services/${tid}/${sid}/config`);
342
418
  }
343
419
  /** Update service configuration. */
344
420
  async updateConfig(teamId, serviceId, data) {
345
- return this.client.request("PATCH", `/api/services/${teamId}/${serviceId}/config`, data);
421
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
422
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
423
+ return this.client.request("PATCH", `/api/services/${tid}/${sid}/config`, data);
346
424
  }
347
425
  /** Get runtime logs for a service. */
348
426
  async getRuntimeLogs(teamId, serviceId, options) {
427
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
428
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
349
429
  const params = new URLSearchParams();
350
430
  if (options?.lines) params.set("lines", String(options.lines));
351
431
  if (options?.since) params.set("since", options.since);
@@ -353,7 +433,7 @@ var ServicesResource = class {
353
433
  const qs = params.toString();
354
434
  return this.client.request(
355
435
  "GET",
356
- `/api/services/${teamId}/${serviceId}/runtime-logs${qs ? `?${qs}` : ""}`
436
+ `/api/services/${tid}/${sid}/runtime-logs${qs ? `?${qs}` : ""}`
357
437
  );
358
438
  }
359
439
  /**
@@ -368,9 +448,11 @@ var ServicesResource = class {
368
448
  * }
369
449
  * ```
370
450
  */
371
- streamLogs(teamId, serviceId, options) {
372
- const basePath = `/api/services/${teamId}/${serviceId}/runtime-logs`;
373
- return streamLogsViaPolling(
451
+ async *streamLogs(teamId, serviceId, options) {
452
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
453
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
454
+ const basePath = `/api/services/${tid}/${sid}/runtime-logs`;
455
+ yield* streamLogsViaPolling(
374
456
  (path) => this.client.request("GET", path),
375
457
  basePath,
376
458
  options
@@ -379,9 +461,21 @@ var ServicesResource = class {
379
461
  };
380
462
 
381
463
  // src/client.ts
464
+ var PREFIX = {
465
+ team: "team_",
466
+ project: "prj_",
467
+ service: "svc_",
468
+ deploy: "dpl_",
469
+ database: "db_",
470
+ domain: "dom_",
471
+ envVar: "env_",
472
+ cronExecution: "cjob_"
473
+ };
382
474
  var HostStack = class {
383
475
  apiKey;
384
476
  baseUrl;
477
+ // publicId → numeric id, scoped by parent context. Lifetime: client instance.
478
+ idCache = /* @__PURE__ */ new Map();
385
479
  /** Manage projects. */
386
480
  projects;
387
481
  /** Manage services (web, worker, cron). */
@@ -401,7 +495,7 @@ var HostStack = class {
401
495
  throw new Error("apiKey is required");
402
496
  }
403
497
  this.apiKey = options.apiKey;
404
- this.baseUrl = (options.baseUrl ?? "https://api.hoststack.dev").replace(/\/$/, "");
498
+ this.baseUrl = (options.baseUrl ?? "https://hoststack.dev").replace(/\/$/, "");
405
499
  this.projects = new ProjectsResource(this);
406
500
  this.services = new ServicesResource(this);
407
501
  this.deploys = new DeploysResource(this);
@@ -446,7 +540,109 @@ var HostStack = class {
446
540
  }
447
541
  return res.json();
448
542
  }
543
+ /**
544
+ * Resolve a publicId-or-numeric id input to a numeric database id. Numeric
545
+ * inputs short-circuit; publicIds (svc_xyz, dpl_xyz, etc.) are looked up
546
+ * via the relevant list endpoint and cached on this client instance.
547
+ *
548
+ * The API addresses everything by numeric id internally; this resolver lets
549
+ * SDK/MCP consumers pass either form interchangeably without burning extra
550
+ * round-trips on subsequent calls.
551
+ */
552
+ async resolveId(input, scope) {
553
+ if (typeof input === "number") return input;
554
+ if (/^\d+$/.test(input)) return Number.parseInt(input, 10);
555
+ const expectedPrefix = PREFIX[scope.kind];
556
+ if (!input.startsWith(expectedPrefix)) {
557
+ throw new HostStackError(
558
+ 400,
559
+ `Invalid ${scope.kind} id "${input}": expected ${expectedPrefix}xxx or numeric.`
560
+ );
561
+ }
562
+ const cacheKey = `${cacheScope(scope)}:${input}`;
563
+ const cached = this.idCache.get(cacheKey);
564
+ if (cached !== void 0) return cached;
565
+ const items = await this.fetchForResolution(scope);
566
+ const match = items.find((it) => it.publicId === input);
567
+ if (!match) {
568
+ throw new NotFoundError(`${scope.kind} ${input} not found`);
569
+ }
570
+ this.idCache.set(cacheKey, match.id);
571
+ return match.id;
572
+ }
573
+ async fetchForResolution(scope) {
574
+ switch (scope.kind) {
575
+ case "team": {
576
+ const r = await this.request(
577
+ "GET",
578
+ "/api/teams"
579
+ );
580
+ return r.teams ?? [];
581
+ }
582
+ case "project": {
583
+ const r = await this.request(
584
+ "GET",
585
+ `/api/projects/${scope.teamId}`
586
+ );
587
+ return r.projects ?? [];
588
+ }
589
+ case "service": {
590
+ const r = await this.request(
591
+ "GET",
592
+ `/api/services/${scope.teamId}`
593
+ );
594
+ return r.services ?? [];
595
+ }
596
+ case "deploy": {
597
+ const r = await this.request(
598
+ "GET",
599
+ `/api/services/${scope.teamId}/${scope.serviceId}/deploys`
600
+ );
601
+ return r.deploys ?? [];
602
+ }
603
+ case "database": {
604
+ const r = await this.request(
605
+ "GET",
606
+ `/api/databases/${scope.teamId}`
607
+ );
608
+ return r.databases ?? [];
609
+ }
610
+ case "domain": {
611
+ const r = await this.request(
612
+ "GET",
613
+ `/api/domains/${scope.teamId}`
614
+ );
615
+ return r.domains ?? [];
616
+ }
617
+ case "envVar": {
618
+ const r = await this.request(
619
+ "GET",
620
+ `/api/services/${scope.teamId}/${scope.serviceId}/env`
621
+ );
622
+ return r.envVars ?? [];
623
+ }
624
+ case "cronExecution": {
625
+ const r = await this.request("GET", `/api/services/${scope.teamId}/${scope.serviceId}/cron-executions`);
626
+ return r.executions ?? [];
627
+ }
628
+ }
629
+ }
449
630
  };
631
+ function cacheScope(scope) {
632
+ switch (scope.kind) {
633
+ case "team":
634
+ return "team";
635
+ case "project":
636
+ case "service":
637
+ case "database":
638
+ case "domain":
639
+ return `${scope.kind}:${scope.teamId}`;
640
+ case "deploy":
641
+ case "envVar":
642
+ case "cronExecution":
643
+ return `${scope.kind}:${scope.teamId}:${scope.serviceId}`;
644
+ }
645
+ }
450
646
 
451
647
  // src/pagination.ts
452
648
  function buildPaginationQuery(params) {