@hoststack.dev/sdk 0.3.0 → 0.4.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.d.cts CHANGED
@@ -32,6 +32,12 @@ interface CreateServiceInput {
32
32
  name: string;
33
33
  type: string;
34
34
  projectId?: string;
35
+ /**
36
+ * v66 P5: bind the new service to a specific environment in the
37
+ * project. Omit to default to the project's Production env. Find or
38
+ * list envs with `client.environments.list(teamId, projectId)`.
39
+ */
40
+ environmentId?: number;
35
41
  gitUrl?: string;
36
42
  branch?: string;
37
43
  buildCommand?: string;
@@ -137,6 +143,11 @@ interface CreateDatabaseInput {
137
143
  name: string;
138
144
  engine: DatabaseEngine;
139
145
  projectId: number;
146
+ /**
147
+ * v66 P5: bind the new database to a specific environment in the
148
+ * project. Omit to default to the project's Production env.
149
+ */
150
+ environmentId?: number;
140
151
  version?: string;
141
152
  plan?: 'free' | 'starter' | 'standard' | 'pro';
142
153
  region?: string;
@@ -354,6 +365,15 @@ declare class DeploysResource {
354
365
  cancel(teamId: IdInput, serviceId: IdInput, deployId: IdInput): Promise<void>;
355
366
  /** Rollback to a previous deploy. */
356
367
  rollback(teamId: IdInput, serviceId: IdInput, deployId: IdInput): Promise<void>;
368
+ /**
369
+ * v66 P5: promote a built deploy to a sibling service in another
370
+ * environment. Reuses the source deploy's docker image (no rebuild).
371
+ * If no sibling service exists in the target env yet, the API auto-
372
+ * creates one by cloning the source service's config.
373
+ */
374
+ promote(teamId: IdInput, serviceId: IdInput, deployId: IdInput, targetEnvironmentId: number): Promise<{
375
+ deploy: Deploy;
376
+ }>;
357
377
  /**
358
378
  * Get build logs for a deploy.
359
379
  *
@@ -401,6 +421,76 @@ declare class DomainsResource {
401
421
  verify(teamId: IdInput, domainId: IdInput): Promise<void>;
402
422
  }
403
423
 
424
+ interface Environment {
425
+ id: number;
426
+ publicId: string;
427
+ projectId: number;
428
+ name: string;
429
+ type: 'production' | 'staging' | 'development' | 'preview';
430
+ isDefault: boolean;
431
+ isProtected: boolean;
432
+ createdAt: string;
433
+ updatedAt: string;
434
+ }
435
+ interface CreateEnvironmentInput {
436
+ name: string;
437
+ type: 'production' | 'staging' | 'development' | 'preview';
438
+ isProtected?: boolean;
439
+ }
440
+ interface UpdateEnvironmentInput {
441
+ name?: string;
442
+ isDefault?: boolean;
443
+ isProtected?: boolean;
444
+ }
445
+ /**
446
+ * v66 P5: programmatic env management. Each project has at least a
447
+ * Production env auto-created at project creation; you can add more
448
+ * via `create` and bind services/databases to them via the
449
+ * `environmentId` field on those resources' create inputs.
450
+ *
451
+ * @example
452
+ * ```ts
453
+ * const { environment: staging } = await client.environments.create(
454
+ * teamId,
455
+ * projectId,
456
+ * { name: 'Staging', type: 'staging' }
457
+ * );
458
+ * await client.services.create(teamId, {
459
+ * projectId,
460
+ * environmentId: staging.id,
461
+ * name: 'api',
462
+ * type: 'web_service',
463
+ * // ...
464
+ * });
465
+ * ```
466
+ */
467
+ declare class EnvironmentsResource {
468
+ private client;
469
+ constructor(client: HostStack);
470
+ /** List all environments for a project. */
471
+ list(teamId: IdInput, projectId: IdInput): Promise<{
472
+ environments: Environment[];
473
+ }>;
474
+ /** Get a single environment by id. */
475
+ get(teamId: IdInput, projectId: IdInput, envId: IdInput): Promise<{
476
+ environment: Environment;
477
+ }>;
478
+ /** Create a new environment in the given project. */
479
+ create(teamId: IdInput, projectId: IdInput, data: CreateEnvironmentInput): Promise<{
480
+ environment: Environment;
481
+ }>;
482
+ /** Update environment metadata (name, default flag, protected flag). */
483
+ update(teamId: IdInput, projectId: IdInput, envId: IdInput, data: UpdateEnvironmentInput): Promise<{
484
+ environment: Environment;
485
+ }>;
486
+ /**
487
+ * Delete an environment. The API blocks delete when the env still
488
+ * has services or databases attached — destroy them first or move
489
+ * them to another env. Cannot delete the project's default env.
490
+ */
491
+ delete(teamId: IdInput, projectId: IdInput, envId: IdInput): Promise<void>;
492
+ }
493
+
404
494
  declare class EnvVarsResource {
405
495
  private client;
406
496
  constructor(client: HostStack);
@@ -505,13 +595,31 @@ declare class ServicesResource {
505
595
  updateConfig(teamId: IdInput, serviceId: IdInput, data: UpdateServiceConfigInput): Promise<{
506
596
  config: ServiceConfig;
507
597
  }>;
508
- /** Get runtime logs for a service. */
598
+ /**
599
+ * Get runtime logs for a service.
600
+ *
601
+ * `since`/`until` accept either an ISO-8601 timestamp or a short
602
+ * relative offset like `-5m`, `-1h`, `-2d`.
603
+ *
604
+ * `search` does case-insensitive substring filtering server-side
605
+ * (≤100 chars). `countOnly` returns just `{ count: N }` for cheap
606
+ * polling — useful when you want to know "how many error lines in the
607
+ * last 5 minutes" without paying the bytes.
608
+ */
509
609
  getRuntimeLogs(teamId: IdInput, serviceId: IdInput, options?: {
510
610
  lines?: number;
611
+ limit?: number;
511
612
  since?: string;
613
+ until?: string;
512
614
  stream?: 'stdout' | 'stderr';
615
+ level?: 'stdout' | 'stderr' | 'info' | 'warn' | 'error' | 'debug';
616
+ search?: string;
617
+ grep?: string;
618
+ countOnly?: boolean;
513
619
  }): Promise<{
514
620
  logs: LogEntry[] | string;
621
+ } | {
622
+ count: number;
515
623
  }>;
516
624
  /**
517
625
  * Stream runtime logs for a service by polling the logs endpoint.
@@ -609,6 +717,9 @@ type ResolveScope = {
609
717
  kind: 'envVar';
610
718
  teamId: number;
611
719
  serviceId: number;
720
+ } | {
721
+ kind: 'environment';
722
+ teamId: number;
612
723
  } | {
613
724
  kind: 'cronExecution';
614
725
  teamId: number;
@@ -630,6 +741,8 @@ declare class HostStack {
630
741
  readonly domains: DomainsResource;
631
742
  /** Manage service environment variables. */
632
743
  readonly envVars: EnvVarsResource;
744
+ /** v66: manage environments (production/staging/development/preview) per project. */
745
+ readonly environments: EnvironmentsResource;
633
746
  /** Manage cron job executions. */
634
747
  readonly cron: CronResource;
635
748
  /** Manage persistent disks attached to services. */
@@ -697,4 +810,4 @@ declare function buildPaginationQuery(params?: PaginationParams): string;
697
810
  */
698
811
  declare function wrapArray<T>(items: T[], params?: PaginationParams): PaginatedResponse<T>;
699
812
 
700
- export { type ActivityLogEntry, type AddDomainInput, AuthenticationError, type BulkSetEnvVarsInput, type CreateDatabaseInput, type CreateEnvVarInput, type CreateProjectInput, type CreateServiceInput, type CronExecution, type Database, type DatabaseCredentials, type Deploy, type Domain, type EnvVar, HostStack, HostStackError, type HostStackOptions, type LogEntry$1 as LogEntry, type MeResponse, NotFoundError, type PaginatedResponse, type PaginationParams, type Project, RateLimitError, type Service, type ServiceConfig, type ServiceMetrics, type StreamLogsOptions, type Team, type TriggerDeployInput, type UpdateDatabaseInput, type UpdateDomainInput, type UpdateEnvVarInput, type UpdateProjectInput, type UpdateServiceConfigInput, type UpdateServiceInput, type User, buildPaginationQuery, wrapArray };
813
+ export { type ActivityLogEntry, type AddDomainInput, AuthenticationError, type BulkSetEnvVarsInput, type CreateDatabaseInput, type CreateEnvVarInput, type CreateEnvironmentInput, type CreateProjectInput, type CreateServiceInput, type CronExecution, type Database, type DatabaseCredentials, type Deploy, type Domain, type EnvVar, type Environment, HostStack, HostStackError, type HostStackOptions, type LogEntry$1 as LogEntry, type MeResponse, NotFoundError, type PaginatedResponse, type PaginationParams, type Project, RateLimitError, type Service, type ServiceConfig, type ServiceMetrics, type StreamLogsOptions, type Team, type TriggerDeployInput, type UpdateDatabaseInput, type UpdateDomainInput, type UpdateEnvVarInput, type UpdateEnvironmentInput, type UpdateProjectInput, type UpdateServiceConfigInput, type UpdateServiceInput, type User, buildPaginationQuery, wrapArray };
package/dist/index.d.ts CHANGED
@@ -32,6 +32,12 @@ interface CreateServiceInput {
32
32
  name: string;
33
33
  type: string;
34
34
  projectId?: string;
35
+ /**
36
+ * v66 P5: bind the new service to a specific environment in the
37
+ * project. Omit to default to the project's Production env. Find or
38
+ * list envs with `client.environments.list(teamId, projectId)`.
39
+ */
40
+ environmentId?: number;
35
41
  gitUrl?: string;
36
42
  branch?: string;
37
43
  buildCommand?: string;
@@ -137,6 +143,11 @@ interface CreateDatabaseInput {
137
143
  name: string;
138
144
  engine: DatabaseEngine;
139
145
  projectId: number;
146
+ /**
147
+ * v66 P5: bind the new database to a specific environment in the
148
+ * project. Omit to default to the project's Production env.
149
+ */
150
+ environmentId?: number;
140
151
  version?: string;
141
152
  plan?: 'free' | 'starter' | 'standard' | 'pro';
142
153
  region?: string;
@@ -354,6 +365,15 @@ declare class DeploysResource {
354
365
  cancel(teamId: IdInput, serviceId: IdInput, deployId: IdInput): Promise<void>;
355
366
  /** Rollback to a previous deploy. */
356
367
  rollback(teamId: IdInput, serviceId: IdInput, deployId: IdInput): Promise<void>;
368
+ /**
369
+ * v66 P5: promote a built deploy to a sibling service in another
370
+ * environment. Reuses the source deploy's docker image (no rebuild).
371
+ * If no sibling service exists in the target env yet, the API auto-
372
+ * creates one by cloning the source service's config.
373
+ */
374
+ promote(teamId: IdInput, serviceId: IdInput, deployId: IdInput, targetEnvironmentId: number): Promise<{
375
+ deploy: Deploy;
376
+ }>;
357
377
  /**
358
378
  * Get build logs for a deploy.
359
379
  *
@@ -401,6 +421,76 @@ declare class DomainsResource {
401
421
  verify(teamId: IdInput, domainId: IdInput): Promise<void>;
402
422
  }
403
423
 
424
+ interface Environment {
425
+ id: number;
426
+ publicId: string;
427
+ projectId: number;
428
+ name: string;
429
+ type: 'production' | 'staging' | 'development' | 'preview';
430
+ isDefault: boolean;
431
+ isProtected: boolean;
432
+ createdAt: string;
433
+ updatedAt: string;
434
+ }
435
+ interface CreateEnvironmentInput {
436
+ name: string;
437
+ type: 'production' | 'staging' | 'development' | 'preview';
438
+ isProtected?: boolean;
439
+ }
440
+ interface UpdateEnvironmentInput {
441
+ name?: string;
442
+ isDefault?: boolean;
443
+ isProtected?: boolean;
444
+ }
445
+ /**
446
+ * v66 P5: programmatic env management. Each project has at least a
447
+ * Production env auto-created at project creation; you can add more
448
+ * via `create` and bind services/databases to them via the
449
+ * `environmentId` field on those resources' create inputs.
450
+ *
451
+ * @example
452
+ * ```ts
453
+ * const { environment: staging } = await client.environments.create(
454
+ * teamId,
455
+ * projectId,
456
+ * { name: 'Staging', type: 'staging' }
457
+ * );
458
+ * await client.services.create(teamId, {
459
+ * projectId,
460
+ * environmentId: staging.id,
461
+ * name: 'api',
462
+ * type: 'web_service',
463
+ * // ...
464
+ * });
465
+ * ```
466
+ */
467
+ declare class EnvironmentsResource {
468
+ private client;
469
+ constructor(client: HostStack);
470
+ /** List all environments for a project. */
471
+ list(teamId: IdInput, projectId: IdInput): Promise<{
472
+ environments: Environment[];
473
+ }>;
474
+ /** Get a single environment by id. */
475
+ get(teamId: IdInput, projectId: IdInput, envId: IdInput): Promise<{
476
+ environment: Environment;
477
+ }>;
478
+ /** Create a new environment in the given project. */
479
+ create(teamId: IdInput, projectId: IdInput, data: CreateEnvironmentInput): Promise<{
480
+ environment: Environment;
481
+ }>;
482
+ /** Update environment metadata (name, default flag, protected flag). */
483
+ update(teamId: IdInput, projectId: IdInput, envId: IdInput, data: UpdateEnvironmentInput): Promise<{
484
+ environment: Environment;
485
+ }>;
486
+ /**
487
+ * Delete an environment. The API blocks delete when the env still
488
+ * has services or databases attached — destroy them first or move
489
+ * them to another env. Cannot delete the project's default env.
490
+ */
491
+ delete(teamId: IdInput, projectId: IdInput, envId: IdInput): Promise<void>;
492
+ }
493
+
404
494
  declare class EnvVarsResource {
405
495
  private client;
406
496
  constructor(client: HostStack);
@@ -505,13 +595,31 @@ declare class ServicesResource {
505
595
  updateConfig(teamId: IdInput, serviceId: IdInput, data: UpdateServiceConfigInput): Promise<{
506
596
  config: ServiceConfig;
507
597
  }>;
508
- /** Get runtime logs for a service. */
598
+ /**
599
+ * Get runtime logs for a service.
600
+ *
601
+ * `since`/`until` accept either an ISO-8601 timestamp or a short
602
+ * relative offset like `-5m`, `-1h`, `-2d`.
603
+ *
604
+ * `search` does case-insensitive substring filtering server-side
605
+ * (≤100 chars). `countOnly` returns just `{ count: N }` for cheap
606
+ * polling — useful when you want to know "how many error lines in the
607
+ * last 5 minutes" without paying the bytes.
608
+ */
509
609
  getRuntimeLogs(teamId: IdInput, serviceId: IdInput, options?: {
510
610
  lines?: number;
611
+ limit?: number;
511
612
  since?: string;
613
+ until?: string;
512
614
  stream?: 'stdout' | 'stderr';
615
+ level?: 'stdout' | 'stderr' | 'info' | 'warn' | 'error' | 'debug';
616
+ search?: string;
617
+ grep?: string;
618
+ countOnly?: boolean;
513
619
  }): Promise<{
514
620
  logs: LogEntry[] | string;
621
+ } | {
622
+ count: number;
515
623
  }>;
516
624
  /**
517
625
  * Stream runtime logs for a service by polling the logs endpoint.
@@ -609,6 +717,9 @@ type ResolveScope = {
609
717
  kind: 'envVar';
610
718
  teamId: number;
611
719
  serviceId: number;
720
+ } | {
721
+ kind: 'environment';
722
+ teamId: number;
612
723
  } | {
613
724
  kind: 'cronExecution';
614
725
  teamId: number;
@@ -630,6 +741,8 @@ declare class HostStack {
630
741
  readonly domains: DomainsResource;
631
742
  /** Manage service environment variables. */
632
743
  readonly envVars: EnvVarsResource;
744
+ /** v66: manage environments (production/staging/development/preview) per project. */
745
+ readonly environments: EnvironmentsResource;
633
746
  /** Manage cron job executions. */
634
747
  readonly cron: CronResource;
635
748
  /** Manage persistent disks attached to services. */
@@ -697,4 +810,4 @@ declare function buildPaginationQuery(params?: PaginationParams): string;
697
810
  */
698
811
  declare function wrapArray<T>(items: T[], params?: PaginationParams): PaginatedResponse<T>;
699
812
 
700
- export { type ActivityLogEntry, type AddDomainInput, AuthenticationError, type BulkSetEnvVarsInput, type CreateDatabaseInput, type CreateEnvVarInput, type CreateProjectInput, type CreateServiceInput, type CronExecution, type Database, type DatabaseCredentials, type Deploy, type Domain, type EnvVar, HostStack, HostStackError, type HostStackOptions, type LogEntry$1 as LogEntry, type MeResponse, NotFoundError, type PaginatedResponse, type PaginationParams, type Project, RateLimitError, type Service, type ServiceConfig, type ServiceMetrics, type StreamLogsOptions, type Team, type TriggerDeployInput, type UpdateDatabaseInput, type UpdateDomainInput, type UpdateEnvVarInput, type UpdateProjectInput, type UpdateServiceConfigInput, type UpdateServiceInput, type User, buildPaginationQuery, wrapArray };
813
+ export { type ActivityLogEntry, type AddDomainInput, AuthenticationError, type BulkSetEnvVarsInput, type CreateDatabaseInput, type CreateEnvVarInput, type CreateEnvironmentInput, type CreateProjectInput, type CreateServiceInput, type CronExecution, type Database, type DatabaseCredentials, type Deploy, type Domain, type EnvVar, type Environment, HostStack, HostStackError, type HostStackOptions, type LogEntry$1 as LogEntry, type MeResponse, NotFoundError, type PaginatedResponse, type PaginationParams, type Project, RateLimitError, type Service, type ServiceConfig, type ServiceMetrics, type StreamLogsOptions, type Team, type TriggerDeployInput, type UpdateDatabaseInput, type UpdateDomainInput, type UpdateEnvVarInput, type UpdateEnvironmentInput, type UpdateProjectInput, type UpdateServiceConfigInput, type UpdateServiceInput, type User, buildPaginationQuery, wrapArray };
package/dist/index.js CHANGED
@@ -182,6 +182,26 @@ var DeploysResource = class {
182
182
  });
183
183
  return this.client.request("POST", `/api/services/${tid}/${sid}/deploys/${did}/rollback`);
184
184
  }
185
+ /**
186
+ * v66 P5: promote a built deploy to a sibling service in another
187
+ * environment. Reuses the source deploy's docker image (no rebuild).
188
+ * If no sibling service exists in the target env yet, the API auto-
189
+ * creates one by cloning the source service's config.
190
+ */
191
+ async promote(teamId, serviceId, deployId, targetEnvironmentId) {
192
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
193
+ const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
194
+ const did = await this.client.resolveId(deployId, {
195
+ kind: "deploy",
196
+ teamId: tid,
197
+ serviceId: sid
198
+ });
199
+ return this.client.request(
200
+ "POST",
201
+ `/api/services/${tid}/${sid}/deploys/${did}/promote`,
202
+ { targetEnvironmentId }
203
+ );
204
+ }
185
205
  /**
186
206
  * Get build logs for a deploy.
187
207
  *
@@ -243,6 +263,50 @@ var DomainsResource = class {
243
263
  }
244
264
  };
245
265
 
266
+ // src/resources/environments.ts
267
+ var EnvironmentsResource = class {
268
+ constructor(client) {
269
+ this.client = client;
270
+ }
271
+ /** List all environments for a project. */
272
+ async list(teamId, projectId) {
273
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
274
+ const pid = await this.client.resolveId(projectId, { kind: "project", teamId: tid });
275
+ return this.client.request("GET", `/api/environments/${tid}/${pid}`);
276
+ }
277
+ /** Get a single environment by id. */
278
+ async get(teamId, projectId, envId) {
279
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
280
+ const pid = await this.client.resolveId(projectId, { kind: "project", teamId: tid });
281
+ const eid = await this.client.resolveId(envId, { kind: "environment", teamId: tid });
282
+ return this.client.request("GET", `/api/environments/${tid}/${pid}/${eid}`);
283
+ }
284
+ /** Create a new environment in the given project. */
285
+ async create(teamId, projectId, data) {
286
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
287
+ const pid = await this.client.resolveId(projectId, { kind: "project", teamId: tid });
288
+ return this.client.request("POST", `/api/environments/${tid}/${pid}`, data);
289
+ }
290
+ /** Update environment metadata (name, default flag, protected flag). */
291
+ async update(teamId, projectId, envId, data) {
292
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
293
+ const pid = await this.client.resolveId(projectId, { kind: "project", teamId: tid });
294
+ const eid = await this.client.resolveId(envId, { kind: "environment", teamId: tid });
295
+ return this.client.request("PATCH", `/api/environments/${tid}/${pid}/${eid}`, data);
296
+ }
297
+ /**
298
+ * Delete an environment. The API blocks delete when the env still
299
+ * has services or databases attached — destroy them first or move
300
+ * them to another env. Cannot delete the project's default env.
301
+ */
302
+ async delete(teamId, projectId, envId) {
303
+ const tid = await this.client.resolveId(teamId, { kind: "team" });
304
+ const pid = await this.client.resolveId(projectId, { kind: "project", teamId: tid });
305
+ const eid = await this.client.resolveId(envId, { kind: "environment", teamId: tid });
306
+ return this.client.request("DELETE", `/api/environments/${tid}/${pid}/${eid}`);
307
+ }
308
+ };
309
+
246
310
  // src/resources/env-vars.ts
247
311
  var EnvVarsResource = class {
248
312
  constructor(client) {
@@ -333,7 +397,7 @@ async function* streamLogsViaPolling(fetch2, basePath, options = {}) {
333
397
  const buildPath = (lines, since) => {
334
398
  const params = new URLSearchParams();
335
399
  if (options.stream) params.set("stream", options.stream);
336
- if (lines !== void 0) params.set("lines", String(lines));
400
+ if (lines !== void 0) params.set("limit", String(lines));
337
401
  if (since) params.set("since", since);
338
402
  const qs = params.toString();
339
403
  return `${basePath}${qs ? `?${qs}` : ""}`;
@@ -445,14 +509,30 @@ var ServicesResource = class {
445
509
  const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
446
510
  return this.client.request("PATCH", `/api/services/${tid}/${sid}/config`, data);
447
511
  }
448
- /** Get runtime logs for a service. */
512
+ /**
513
+ * Get runtime logs for a service.
514
+ *
515
+ * `since`/`until` accept either an ISO-8601 timestamp or a short
516
+ * relative offset like `-5m`, `-1h`, `-2d`.
517
+ *
518
+ * `search` does case-insensitive substring filtering server-side
519
+ * (≤100 chars). `countOnly` returns just `{ count: N }` for cheap
520
+ * polling — useful when you want to know "how many error lines in the
521
+ * last 5 minutes" without paying the bytes.
522
+ */
449
523
  async getRuntimeLogs(teamId, serviceId, options) {
450
524
  const tid = await this.client.resolveId(teamId, { kind: "team" });
451
525
  const sid = await this.client.resolveId(serviceId, { kind: "service", teamId: tid });
452
526
  const params = new URLSearchParams();
453
- if (options?.lines) params.set("lines", String(options.lines));
527
+ const lim = options?.limit ?? options?.lines;
528
+ if (lim != null) params.set("limit", String(lim));
454
529
  if (options?.since) params.set("since", options.since);
530
+ if (options?.until) params.set("until", options.until);
455
531
  if (options?.stream) params.set("stream", options.stream);
532
+ if (options?.level) params.set("level", options.level);
533
+ const grep = options?.grep ?? options?.search;
534
+ if (grep) params.set("search", grep);
535
+ if (options?.countOnly) params.set("count_only", "1");
456
536
  const qs = params.toString();
457
537
  return this.client.request(
458
538
  "GET",
@@ -541,6 +621,7 @@ var PREFIX = {
541
621
  domain: "dom_",
542
622
  volume: "vol_",
543
623
  envVar: "env_",
624
+ environment: "environment_",
544
625
  cronExecution: "cjob_"
545
626
  };
546
627
  var HostStack = class {
@@ -560,6 +641,8 @@ var HostStack = class {
560
641
  domains;
561
642
  /** Manage service environment variables. */
562
643
  envVars;
644
+ /** v66: manage environments (production/staging/development/preview) per project. */
645
+ environments;
563
646
  /** Manage cron job executions. */
564
647
  cron;
565
648
  /** Manage persistent disks attached to services. */
@@ -576,6 +659,7 @@ var HostStack = class {
576
659
  this.databases = new DatabasesResource(this);
577
660
  this.domains = new DomainsResource(this);
578
661
  this.envVars = new EnvVarsResource(this);
662
+ this.environments = new EnvironmentsResource(this);
579
663
  this.cron = new CronResource(this);
580
664
  this.volumes = new VolumesResource(this);
581
665
  }
@@ -704,6 +788,15 @@ var HostStack = class {
704
788
  const r = await this.request("GET", `/api/services/${scope.teamId}/${scope.serviceId}/cron-executions`);
705
789
  return r.executions ?? [];
706
790
  }
791
+ case "environment": {
792
+ const projectsRes = await this.request("GET", `/api/projects/${scope.teamId}`);
793
+ const envs = [];
794
+ for (const p of projectsRes.projects ?? []) {
795
+ const r = await this.request("GET", `/api/environments/${scope.teamId}/${p.id}`);
796
+ envs.push(...r.environments ?? []);
797
+ }
798
+ return envs;
799
+ }
707
800
  }
708
801
  }
709
802
  };
@@ -715,6 +808,7 @@ function cacheScope(scope) {
715
808
  case "service":
716
809
  case "database":
717
810
  case "domain":
811
+ case "environment":
718
812
  return `${scope.kind}:${scope.teamId}`;
719
813
  case "deploy":
720
814
  case "volume":