@to11ai/sdk 0.0.2 → 0.1.1

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/src/errors.ts CHANGED
@@ -89,3 +89,175 @@ export class To11aiNetworkError extends To11aiError {
89
89
  Object.setPrototypeOf(this, new.target.prototype);
90
90
  }
91
91
  }
92
+
93
+ /**
94
+ * Thrown when strict-mode rejects a label move for an unregistered label.
95
+ *
96
+ * The API returns 422 with `error.code === "PROMPT_LABEL_NOT_REGISTERED"`
97
+ * when `project.enforce_label_registry = true` and the caller tries to
98
+ * move a label that has no active entry in the project label registry.
99
+ * The transport surfaces these as this typed subclass; existing
100
+ * `instanceof To11aiApiError` blocks still match.
101
+ *
102
+ * Note: this extends `To11aiApiError` directly (not `To11aiValidationError`,
103
+ * which hardcodes status 400). The API returns 422 for this case.
104
+ */
105
+ export class PromptLabelNotRegisteredError extends To11aiApiError {
106
+ readonly projectId: string;
107
+ readonly label: string;
108
+
109
+ constructor(
110
+ message: string,
111
+ projectId: string,
112
+ label: string,
113
+ details?: unknown,
114
+ ) {
115
+ super(
116
+ message,
117
+ 422,
118
+ "PROMPT_LABEL_NOT_REGISTERED",
119
+ details !== undefined ? details : { projectId, label },
120
+ );
121
+ this.name = "PromptLabelNotRegisteredError";
122
+ this.projectId = projectId;
123
+ this.label = label;
124
+ Object.setPrototypeOf(this, new.target.prototype);
125
+ }
126
+
127
+ /** Type guard helper — checks `instanceof` (not parent + errorCode string). */
128
+ static is(err: unknown): err is PromptLabelNotRegisteredError {
129
+ return err instanceof PromptLabelNotRegisteredError;
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Thrown when a rule cannot be located. Covers two variants of the same
135
+ * named class (single class so existing `catch (err: RuleNotFoundError)`
136
+ * blocks match both):
137
+ *
138
+ * * Control-plane variant (404 `RULE_NOT_FOUND`) — `ruleId` is the id
139
+ * the caller supplied and that did not exist in the project.
140
+ * * Gateway variant (404 `RULE_NOT_FOUND_IN_ENV`) — `model` is the
141
+ * `function::<alias>` (or raw model id) the gateway tried to resolve
142
+ * and `env` is the request env. `ruleId` is undefined because the
143
+ * alias may not resolve to any rule in the env.
144
+ */
145
+ export class RuleNotFoundError extends To11aiApiError {
146
+ readonly ruleId: string | undefined;
147
+ readonly model: string | undefined;
148
+ readonly env: string | undefined;
149
+
150
+ constructor(
151
+ message: string,
152
+ errorCode: string,
153
+ fields: { ruleId?: string; model?: string; env?: string },
154
+ details?: unknown,
155
+ ) {
156
+ super(message, 404, errorCode, details);
157
+ this.name = "RuleNotFoundError";
158
+ this.ruleId = fields.ruleId;
159
+ this.model = fields.model;
160
+ this.env = fields.env;
161
+ Object.setPrototypeOf(this, new.target.prototype);
162
+ }
163
+
164
+ static is(err: unknown): err is RuleNotFoundError {
165
+ return err instanceof RuleNotFoundError;
166
+ }
167
+ }
168
+
169
+ export type NoApplicableRouteReason =
170
+ | "all_conditions_false"
171
+ | "all_variants_unreachable"
172
+ | "all_steps_non_routable";
173
+
174
+ /**
175
+ * Thrown when the gateway resolved a rule + version but no variant /
176
+ * step / chain element was applicable to the request — every condition
177
+ * was false, every variant unreachable, or every fallback step
178
+ * non-routable. Surfaces as 422 `NO_APPLICABLE_ROUTE`.
179
+ */
180
+ export class NoApplicableRouteError extends To11aiApiError {
181
+ readonly ruleId: string;
182
+ readonly versionId: string;
183
+ readonly reason: NoApplicableRouteReason | string;
184
+
185
+ constructor(
186
+ message: string,
187
+ fields: { ruleId: string; versionId: string; reason: string },
188
+ details?: unknown,
189
+ ) {
190
+ super(message, 422, "NO_APPLICABLE_ROUTE", details);
191
+ this.name = "NoApplicableRouteError";
192
+ this.ruleId = fields.ruleId;
193
+ this.versionId = fields.versionId;
194
+ this.reason = fields.reason;
195
+ Object.setPrototypeOf(this, new.target.prototype);
196
+ }
197
+
198
+ static is(err: unknown): err is NoApplicableRouteError {
199
+ return err instanceof NoApplicableRouteError;
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Thrown when a rule references a provider that has no activation in the
205
+ * requested env. Surfaces as 422 `ENV_NOT_ENABLED_FOR_PROVIDER`.
206
+ */
207
+ export class EnvNotEnabledForProviderError extends To11aiApiError {
208
+ readonly ruleId: string;
209
+ readonly envSlug: string;
210
+ readonly providerId: string;
211
+
212
+ constructor(
213
+ message: string,
214
+ fields: { ruleId: string; envSlug: string; providerId: string },
215
+ details?: unknown,
216
+ ) {
217
+ super(message, 422, "ENV_NOT_ENABLED_FOR_PROVIDER", details);
218
+ this.name = "EnvNotEnabledForProviderError";
219
+ this.ruleId = fields.ruleId;
220
+ this.envSlug = fields.envSlug;
221
+ this.providerId = fields.providerId;
222
+ Object.setPrototypeOf(this, new.target.prototype);
223
+ }
224
+
225
+ static is(err: unknown): err is EnvNotEnabledForProviderError {
226
+ return err instanceof EnvNotEnabledForProviderError;
227
+ }
228
+ }
229
+
230
+ /**
231
+ * Thrown when version create rejects the snapshot for a structural
232
+ * reason — invalid variant params, malformed `when` clause, illegal
233
+ * weight set, malformed retry policy, … Surfaces with one of the
234
+ * `INVALID_VARIANT_PARAMS` / `INVALID_VARIANT_WEIGHTS` /
235
+ * `INVALID_RULE_STRATEGY` / `INVALID_STEP_COUNT` /
236
+ * `RULE_ENDPOINT_MISMATCH` / `INVALID_WHEN_CLAUSE` /
237
+ * `INVALID_STRATEGY_VARIANTS` / `INVALID_RETRY_POLICY` error codes
238
+ * at HTTP status 400 or 422.
239
+ */
240
+ export class RuleVersionInvalidSnapshotError extends To11aiApiError {
241
+ readonly field: string | undefined;
242
+ readonly reason: string | undefined;
243
+ readonly variantName: string | undefined;
244
+
245
+ constructor(
246
+ message: string,
247
+ errorCode: string,
248
+ fields: { field?: string; reason?: string; variantName?: string },
249
+ details?: unknown,
250
+ statusCode: number = 400,
251
+ ) {
252
+ super(message, statusCode, errorCode, details);
253
+ this.name = "RuleVersionInvalidSnapshotError";
254
+ this.field = fields.field;
255
+ this.reason = fields.reason;
256
+ this.variantName = fields.variantName;
257
+ Object.setPrototypeOf(this, new.target.prototype);
258
+ }
259
+
260
+ static is(err: unknown): err is RuleVersionInvalidSnapshotError {
261
+ return err instanceof RuleVersionInvalidSnapshotError;
262
+ }
263
+ }
package/src/gateway.ts CHANGED
@@ -3,13 +3,32 @@ import type { ResolvedPrompt } from "./prompts/types";
3
3
  export interface GatewayAuthOptions {
4
4
  apiKey: string;
5
5
  projectId: string;
6
+ /**
7
+ * Optional environment slug routed via the gateway's `x-to11-env`
8
+ * header. When omitted, the gateway falls back to the project's
9
+ * `is_gateway_fallback=true` environment; if no fallback exists, the
10
+ * request fails with `400 missing_env_no_project_default`.
11
+ *
12
+ * Slug validation matches the project-environments registry:
13
+ * lowercase-kebab (`a-z`, `0-9`, `-`, 1..63 chars). The SDK rejects
14
+ * empty / whitespace-only values eagerly so misconfiguration surfaces
15
+ * before the request hits the wire.
16
+ */
17
+ env?: string;
6
18
  }
7
19
 
8
20
  /**
9
21
  * Build the auth headers required for every request through the to11 gateway.
10
22
  *
23
+ * Includes `x-to11-env: <slug>` when `options.env` is set — see the
24
+ * environments-registry spec for gateway routing semantics. Empty /
25
+ * whitespace-only env values throw immediately so caller misconfiguration
26
+ * is loud.
27
+ *
11
28
  * @example
12
29
  * const headers = gatewayAuthHeaders({ apiKey, projectId });
30
+ * @example
31
+ * const headers = gatewayAuthHeaders({ apiKey, projectId, env: "staging" });
13
32
  */
14
33
  export function gatewayAuthHeaders(
15
34
  options: GatewayAuthOptions,
@@ -20,10 +39,19 @@ export function gatewayAuthHeaders(
20
39
  if (options.projectId.trim().length === 0) {
21
40
  throw new Error("[to11ai/sdk] `projectId` must not be empty.");
22
41
  }
23
- return {
42
+ const headers: Record<string, string> = {
24
43
  "x-to11-authorization": `Bearer ${options.apiKey}`,
25
44
  "x-to11-project-id": options.projectId,
26
45
  };
46
+ if (options.env !== undefined) {
47
+ if (options.env.trim().length === 0) {
48
+ throw new Error(
49
+ "[to11ai/sdk] `env` must not be empty — omit the field to use the project's gateway-fallback environment.",
50
+ );
51
+ }
52
+ headers["x-to11-env"] = options.env;
53
+ }
54
+ return headers;
27
55
  }
28
56
 
29
57
  /**
@@ -0,0 +1,220 @@
1
+ // ---------------------------------------------------------------------------
2
+ // ProjectEnvironmentResource — fluent SDK surface for project environments.
3
+ // ---------------------------------------------------------------------------
4
+ // Spec: docs/product-specs/2026-05-14-environments-registry.md
5
+ // Plan: docs/exec-plans/active/2026-05-14-env-registry-plan.md §S21
6
+ //
7
+ // Mirrors `PromptResource` in shape so existing call-site intuition
8
+ // transfers: each method takes a flat input object, unwraps the API
9
+ // envelope, and returns the resource shape verbatim.
10
+ // ---------------------------------------------------------------------------
11
+
12
+ import type { ApiEnvelope, Transport } from "../transport";
13
+ import type {
14
+ ArchiveProjectEnvironmentInput,
15
+ ArchiveProjectEnvironmentResult,
16
+ CreateProjectEnvironmentInput,
17
+ CreateProjectEnvironmentResult,
18
+ GetProjectEnvironmentInput,
19
+ GetProjectEnvironmentResult,
20
+ ListProjectEnvironmentsInput,
21
+ ListProjectEnvironmentsResult,
22
+ RestoreProjectEnvironmentInput,
23
+ RestoreProjectEnvironmentResult,
24
+ UpdateProjectEnvironmentInput,
25
+ UpdateProjectEnvironmentResult,
26
+ } from "./types";
27
+
28
+ // Re-export wire types so callers can import from `@to11ai/sdk/projectEnvironments`.
29
+ export type {
30
+ ArchiveProjectEnvironmentInput,
31
+ ArchiveProjectEnvironmentResult,
32
+ CreateProjectEnvironmentInput,
33
+ CreateProjectEnvironmentResult,
34
+ GetProjectEnvironmentInput,
35
+ GetProjectEnvironmentResult,
36
+ ListProjectEnvironmentsInput,
37
+ ListProjectEnvironmentsResult,
38
+ LivePointerCounts,
39
+ ProjectEnvironment,
40
+ RestoreProjectEnvironmentInput,
41
+ RestoreProjectEnvironmentResult,
42
+ UpdateProjectEnvironmentInput,
43
+ UpdateProjectEnvironmentResult,
44
+ } from "./types";
45
+
46
+ function unwrap<T>(envelope: ApiEnvelope<T>): T {
47
+ if (envelope.data === null || envelope.data === undefined) {
48
+ throw new Error("API returned success but data is null");
49
+ }
50
+ return envelope.data;
51
+ }
52
+
53
+ function projectEnvironmentsPath(projectId: string): string {
54
+ return `/v1/projects/${encodeURIComponent(projectId)}/environments`;
55
+ }
56
+
57
+ function projectEnvironmentPath(projectId: string, slug: string): string {
58
+ return `${projectEnvironmentsPath(projectId)}/${encodeURIComponent(slug)}`;
59
+ }
60
+
61
+ /**
62
+ * SDK resource for `/v1/projects/:projectId/environments`. Constructed by
63
+ * `createClient` and exposed as `client.projectEnvironments`.
64
+ */
65
+ export class ProjectEnvironmentResource {
66
+ private readonly transport: Transport;
67
+
68
+ constructor(transport: Transport) {
69
+ this.transport = transport;
70
+ }
71
+
72
+ // ─── List ────────────────────────────────────────────────────────────────
73
+
74
+ /**
75
+ * List the project's environments. Excludes archived rows by default —
76
+ * pass `includeArchived: true` to include rows with a non-null
77
+ * `archivedAt` (used by the admin / restore UI).
78
+ */
79
+ async list(
80
+ input: ListProjectEnvironmentsInput,
81
+ ): Promise<ListProjectEnvironmentsResult> {
82
+ const envelope =
83
+ await this.transport.request<ListProjectEnvironmentsResult>(
84
+ "GET",
85
+ projectEnvironmentsPath(input.projectId),
86
+ {
87
+ query: input.includeArchived
88
+ ? { includeArchived: "true" }
89
+ : undefined,
90
+ },
91
+ );
92
+ return unwrap(envelope);
93
+ }
94
+
95
+ // ─── Get ─────────────────────────────────────────────────────────────────
96
+
97
+ async get(
98
+ input: GetProjectEnvironmentInput,
99
+ ): Promise<GetProjectEnvironmentResult> {
100
+ const envelope = await this.transport.request<GetProjectEnvironmentResult>(
101
+ "GET",
102
+ projectEnvironmentPath(input.projectId, input.slug),
103
+ );
104
+ return unwrap(envelope);
105
+ }
106
+
107
+ // ─── Create ──────────────────────────────────────────────────────────────
108
+
109
+ /**
110
+ * Create a new environment.
111
+ *
112
+ * `slug` must match lowercase-kebab (`a-z`, `0-9`, `-`, 1..63 chars).
113
+ * Reserved system slugs (`prod`, `staging`) and any already-used slug
114
+ * return 409 `ENVIRONMENT_SLUG_TAKEN`.
115
+ *
116
+ * Setting `isGatewayFallback: true` additionally requires the
117
+ * `project:manage_default_environment` capability; the create use
118
+ * case clears the flag on any other env in the same project.
119
+ */
120
+ async create(
121
+ input: CreateProjectEnvironmentInput,
122
+ ): Promise<CreateProjectEnvironmentResult> {
123
+ const { projectId, ...body } = input;
124
+ const envelope =
125
+ await this.transport.request<CreateProjectEnvironmentResult>(
126
+ "POST",
127
+ projectEnvironmentsPath(projectId),
128
+ { body },
129
+ );
130
+ return unwrap(envelope);
131
+ }
132
+
133
+ // ─── Update ──────────────────────────────────────────────────────────────
134
+
135
+ /**
136
+ * PATCH an environment.
137
+ *
138
+ * - System envs (`isSystem: true`) reject `slug`/`isSystem`/immutable-
139
+ * field mutations with 409 `SYSTEM_ENV_IMMUTABLE`.
140
+ * - Renaming via `newSlug` triggers a 7-day alias row server-side so
141
+ * in-flight gateway requests carrying the old slug keep resolving.
142
+ * - Mutating `isGatewayFallback` requires the
143
+ * `project:manage_default_environment` capability AND the target
144
+ * env must have at least one live snapshot (else 409
145
+ * `FALLBACK_ENV_NOT_READY`).
146
+ *
147
+ * The SDK marshals `newSlug` onto the wire as `slug` (the API accepts
148
+ * `slug` on the PATCH body for a rename — the URL slug stays the
149
+ * pre-rename identifier).
150
+ */
151
+ async update(
152
+ input: UpdateProjectEnvironmentInput,
153
+ ): Promise<UpdateProjectEnvironmentResult> {
154
+ const { projectId, slug, newSlug, ...rest } = input;
155
+ const body: Record<string, unknown> = {};
156
+ if (newSlug !== undefined) body.slug = newSlug;
157
+ if (rest.name !== undefined) body.name = rest.name;
158
+ if (rest.color !== undefined) body.color = rest.color;
159
+ if (rest.description !== undefined) body.description = rest.description;
160
+ if (rest.isPointer !== undefined) body.isPointer = rest.isPointer;
161
+ if (rest.requiresApproval !== undefined)
162
+ body.requiresApproval = rest.requiresApproval;
163
+ if (rest.isDefault !== undefined) body.isDefault = rest.isDefault;
164
+ if (rest.isGatewayFallback !== undefined)
165
+ body.isGatewayFallback = rest.isGatewayFallback;
166
+ if (rest.sortOrder !== undefined) body.sortOrder = rest.sortOrder;
167
+
168
+ const envelope =
169
+ await this.transport.request<UpdateProjectEnvironmentResult>(
170
+ "PATCH",
171
+ projectEnvironmentPath(projectId, slug),
172
+ { body },
173
+ );
174
+ return unwrap(envelope);
175
+ }
176
+
177
+ // ─── Archive ─────────────────────────────────────────────────────────────
178
+
179
+ /**
180
+ * Soft-archive an environment. The response carries the archived row
181
+ * plus a `livePointerCounts` summary (informational — pointers are
182
+ * cascade-cleared by the use case).
183
+ *
184
+ * System envs (`isSystem: true`) and the current gateway-fallback env
185
+ * cannot be archived; the API returns 409 `SYSTEM_ENV_IMMUTABLE` or
186
+ * `CANNOT_ARCHIVE_GATEWAY_FALLBACK` respectively.
187
+ *
188
+ * Uses `POST /:slug/archive` rather than `DELETE` so the server can
189
+ * return a structured 200 with the archived row + counts.
190
+ */
191
+ async archive(
192
+ input: ArchiveProjectEnvironmentInput,
193
+ ): Promise<ArchiveProjectEnvironmentResult> {
194
+ const envelope =
195
+ await this.transport.request<ArchiveProjectEnvironmentResult>(
196
+ "POST",
197
+ `${projectEnvironmentPath(input.projectId, input.slug)}/archive`,
198
+ );
199
+ return unwrap(envelope);
200
+ }
201
+
202
+ // ─── Restore ─────────────────────────────────────────────────────────────
203
+
204
+ /**
205
+ * Restore a previously-archived environment. The server resets
206
+ * `archivedAt` to `null` and returns the live row. No-op if the env
207
+ * is already live; returns 404 `ENVIRONMENT_NOT_FOUND` if the slug
208
+ * has never existed.
209
+ */
210
+ async restore(
211
+ input: RestoreProjectEnvironmentInput,
212
+ ): Promise<RestoreProjectEnvironmentResult> {
213
+ const envelope =
214
+ await this.transport.request<RestoreProjectEnvironmentResult>(
215
+ "POST",
216
+ `${projectEnvironmentPath(input.projectId, input.slug)}/restore`,
217
+ );
218
+ return unwrap(envelope);
219
+ }
220
+ }
@@ -0,0 +1,151 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Project Environments wire types (TO11-793 / env-registry §S21).
3
+ // ---------------------------------------------------------------------------
4
+ // Spec: docs/product-specs/2026-05-14-environments-registry.md
5
+ // Plan: docs/exec-plans/active/2026-05-14-env-registry-plan.md §S21
6
+ //
7
+ // Hand-rolled TS mirrors of the Effect Schema types defined in
8
+ // `apps/api/src/domains/tenancy/projects/model/project-environment.ts`. The
9
+ // published `@to11ai/sdk` package intentionally does NOT depend on the
10
+ // internal `@to11/api` workspace package — keep these in lockstep with the
11
+ // API model when adding fields.
12
+ // ---------------------------------------------------------------------------
13
+
14
+ // ─── Wire shape ─────────────────────────────────────────────────────────────
15
+
16
+ /**
17
+ * Project-scoped environment row as returned by
18
+ * `GET /v1/projects/:projectId/environments/:slug`.
19
+ *
20
+ * Notes:
21
+ * - `isSystem: true` for the seeded `prod` / `staging` rows. Those rows
22
+ * cannot be renamed, archived, or have their `slug`/`isSystem` mutated.
23
+ * - `isGatewayFallback: true` marks the env the gateway routes to when no
24
+ * `x-to11-env` header is supplied. At most one env per project may carry
25
+ * this flag; clearing the only fallback is rejected with 409
26
+ * `CANNOT_CLEAR_ONLY_GATEWAY_FALLBACK`.
27
+ * - `archivedAt` is `null` for live envs and an ISO-8601 timestamp for
28
+ * soft-archived ones.
29
+ */
30
+ export interface ProjectEnvironment {
31
+ id: string;
32
+ projectId: string;
33
+ slug: string;
34
+ name: string;
35
+ color: string | null;
36
+ description: string | null;
37
+ isPointer: boolean;
38
+ requiresApproval: boolean;
39
+ isDefault: boolean;
40
+ isGatewayFallback: boolean;
41
+ sortOrder: number;
42
+ isSystem: boolean;
43
+ archivedAt: string | null;
44
+ createdBy: string;
45
+ updatedBy: string;
46
+ createdAt: string;
47
+ updatedAt: string;
48
+ }
49
+
50
+ /**
51
+ * Pointer-count payload attached to archive responses. `prompts` is real
52
+ * today; `rules` / `providers` are 0 in v1 (reserved for Wave 6+ specs to
53
+ * keep the response shape stable when those domains land).
54
+ */
55
+ export interface LivePointerCounts {
56
+ prompts: number;
57
+ rules: number;
58
+ providers: number;
59
+ }
60
+
61
+ /**
62
+ * Response body for `POST /v1/projects/:projectId/environments/:slug/archive`.
63
+ * Carries the soft-archived environment plus the count of live pointers
64
+ * cascade-cleared by the archive operation (informational, for the
65
+ * confirmation modal in the web UI).
66
+ */
67
+ export interface ArchiveProjectEnvironmentResult {
68
+ environment: ProjectEnvironment;
69
+ livePointerCounts: LivePointerCounts;
70
+ }
71
+
72
+ // ─── Inputs ─────────────────────────────────────────────────────────────────
73
+
74
+ export interface ListProjectEnvironmentsInput {
75
+ projectId: string;
76
+ /**
77
+ * When `true`, the response includes archived envs (those with a
78
+ * non-null `archivedAt`). Default behavior excludes them.
79
+ */
80
+ includeArchived?: boolean;
81
+ }
82
+
83
+ export type ListProjectEnvironmentsResult = ProjectEnvironment[];
84
+
85
+ export interface GetProjectEnvironmentInput {
86
+ projectId: string;
87
+ slug: string;
88
+ }
89
+
90
+ export type GetProjectEnvironmentResult = ProjectEnvironment;
91
+
92
+ /**
93
+ * Create input — must specify a unique `slug` matching lowercase-kebab
94
+ * (a-z, 0-9, hyphen, 1..63 chars). Reserved system slugs (`prod`,
95
+ * `staging`) are rejected by the API with `ENVIRONMENT_SLUG_TAKEN`.
96
+ *
97
+ * Setting `isGatewayFallback: true` here additionally requires the
98
+ * `project:manage_default_environment` capability; the create use case
99
+ * atomically clears the flag on any other env in the same project.
100
+ */
101
+ export interface CreateProjectEnvironmentInput {
102
+ projectId: string;
103
+ slug: string;
104
+ name: string;
105
+ color?: string | null;
106
+ description?: string | null;
107
+ isPointer?: boolean;
108
+ requiresApproval?: boolean;
109
+ isDefault?: boolean;
110
+ isGatewayFallback?: boolean;
111
+ sortOrder?: number;
112
+ }
113
+
114
+ export type CreateProjectEnvironmentResult = ProjectEnvironment;
115
+
116
+ /**
117
+ * PATCH input — every field is optional. `slug` rename triggers a 7-day
118
+ * alias row server-side. System envs (`isSystem: true`) reject `slug`,
119
+ * `isSystem`, and other immutable-field mutations with
120
+ * `SYSTEM_ENV_IMMUTABLE`.
121
+ *
122
+ * As with `create`, mutating `isGatewayFallback` requires the additional
123
+ * `project:manage_default_environment` capability.
124
+ */
125
+ export interface UpdateProjectEnvironmentInput {
126
+ projectId: string;
127
+ slug: string;
128
+ newSlug?: string;
129
+ name?: string;
130
+ color?: string | null;
131
+ description?: string | null;
132
+ isPointer?: boolean;
133
+ requiresApproval?: boolean;
134
+ isDefault?: boolean;
135
+ isGatewayFallback?: boolean;
136
+ sortOrder?: number;
137
+ }
138
+
139
+ export type UpdateProjectEnvironmentResult = ProjectEnvironment;
140
+
141
+ export interface ArchiveProjectEnvironmentInput {
142
+ projectId: string;
143
+ slug: string;
144
+ }
145
+
146
+ export interface RestoreProjectEnvironmentInput {
147
+ projectId: string;
148
+ slug: string;
149
+ }
150
+
151
+ export type RestoreProjectEnvironmentResult = ProjectEnvironment;