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