Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions openapi/public.json
Original file line number Diff line number Diff line change
Expand Up @@ -33468,7 +33468,8 @@
"compute_config_id": {
"type": "string",
"minLength": 1,
"maxLength": 54
"maxLength": 54,
"description": "Compute config that supplies the provider account for this machine. Omit it to explicitly request an Akua system-managed machine on platform infrastructure; free-tier instance types and machine quotas then apply."
},
"name": {
"type": "string",
Expand All @@ -33481,8 +33482,7 @@
},
"required": [
"cluster_id",
"instance_type",
"compute_config_id"
"instance_type"
],
"additionalProperties": false
}
Expand Down Expand Up @@ -37341,6 +37341,19 @@
"description": "Required when `owner_type` is set. Ignored otherwise.",
"name": "owner_id",
"in": "query"
},
{
"schema": {
"type": "string",
"minLength": 1,
"maxLength": 53,
"description": "Optional workspace/scope context for the request. Carries a single workspace wire id (`ws_…`) today. Only needed for broad tokens — a workspace-owned token implies its workspace.",
"example": "ws_j572abc123def456"
},
"required": false,
"description": "Optional workspace/scope context for the request. Carries a single workspace wire id (`ws_…`) today. Only needed for broad tokens — a workspace-owned token implies its workspace.",
"name": "akua-context",
"in": "header"
}
],
"responses": {
Expand Down
8 changes: 6 additions & 2 deletions src/generated/commands.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2947,8 +2947,7 @@ export const commandRegistry: readonly CommandDefinition<PublicOperationId>[] =
"required": false,
"example": {
"cluster_id": "<cluster_id>",
"instance_type": "<instance_type>",
"compute_config_id": "<compute_config_id>"
"instance_type": "<instance_type>"
}
}
},
Expand Down Expand Up @@ -3658,6 +3657,11 @@ export const commandRegistry: readonly CommandDefinition<PublicOperationId>[] =
"name": "owner_id",
"in": "query",
"required": false
},
{
"name": "akua-context",
"in": "header",
"required": false
}
]
},
Expand Down
12 changes: 7 additions & 5 deletions src/generated/openapi-api.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -938,8 +938,8 @@ export type MachinesCreateParams = { readonly "akua-context"?: string, readonly
export const MachinesCreateParams = Schema.Struct({ "akua-context": Schema.optionalKey(Schema.String.annotate({ "description": "Optional workspace/scope context for the request. Carries a single workspace wire id (`ws_…`) today. Only needed for broad tokens — a workspace-owned token implies its workspace." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check(Schema.isMaxLength(53).annotate({ "expected": "a value with a length of at most 53" }))), "idempotency-key": Schema.optionalKey(Schema.String.annotate({ "description": "Optional caller-supplied idempotency key. Any non-empty key up to 64 characters is accepted. Endpoint-specific documentation describes how the key is used." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check(Schema.isMaxLength(64).annotate({ "expected": "a value with a length of at most 64" }))) })
export type MachinesCreateHeaders = { readonly "akua-context"?: string, readonly "idempotency-key"?: string }
export const MachinesCreateHeaders = Schema.Struct({ "akua-context": Schema.optionalKey(Schema.String.annotate({ "description": "Optional workspace/scope context for the request. Carries a single workspace wire id (`ws_…`) today. Only needed for broad tokens — a workspace-owned token implies its workspace." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check(Schema.isMaxLength(53).annotate({ "expected": "a value with a length of at most 53" }))), "idempotency-key": Schema.optionalKey(Schema.String.annotate({ "description": "Optional caller-supplied idempotency key. Any non-empty key up to 64 characters is accepted. Endpoint-specific documentation describes how the key is used." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check(Schema.isMaxLength(64).annotate({ "expected": "a value with a length of at most 64" }))) })
export type MachinesCreateRequestJson = { readonly "cluster_id": string, readonly "instance_type": string, readonly "compute_config_id": string, readonly "name"?: string, readonly "node_claim"?: { readonly [x: string]: Schema.Json } }
export const MachinesCreateRequestJson = Schema.Struct({ "cluster_id": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check(Schema.isMaxLength(54).annotate({ "expected": "a value with a length of at most 54" })), "instance_type": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), "compute_config_id": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check(Schema.isMaxLength(54).annotate({ "expected": "a value with a length of at most 54" })), "name": Schema.optionalKey(Schema.String.check(Schema.isMaxLength(120).annotate({ "expected": "a value with a length of at most 120" }))), "node_claim": Schema.optionalKey(Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))) })
export type MachinesCreateRequestJson = { readonly "cluster_id": string, readonly "instance_type": string, readonly "compute_config_id"?: string, readonly "name"?: string, readonly "node_claim"?: { readonly [x: string]: Schema.Json } }
export const MachinesCreateRequestJson = Schema.Struct({ "cluster_id": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check(Schema.isMaxLength(54).annotate({ "expected": "a value with a length of at most 54" })), "instance_type": Schema.String.check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })), "compute_config_id": Schema.optionalKey(Schema.String.annotate({ "description": "Compute config that supplies the provider account for this machine. Omit it to explicitly request an Akua system-managed machine on platform infrastructure; free-tier instance types and machine quotas then apply." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check(Schema.isMaxLength(54).annotate({ "expected": "a value with a length of at most 54" }))), "name": Schema.optionalKey(Schema.String.check(Schema.isMaxLength(120).annotate({ "expected": "a value with a length of at most 120" }))), "node_claim": Schema.optionalKey(Schema.Record(Schema.String, Schema.Json.annotate({ "expected": "JSON value" }))) })
export type MachinesCreate202 = MachineOperation
export const MachinesCreate202 = MachineOperation
export type MachinesCreate401 = ApiErrorResponse
Expand Down Expand Up @@ -1460,10 +1460,12 @@ export type EntitlementsList401 = ApiErrorResponse
export const EntitlementsList401 = ApiErrorResponse
export type EntitlementsList403 = ApiErrorResponse
export const EntitlementsList403 = ApiErrorResponse
export type OperationsListParams = { readonly "cursor"?: string, readonly "limit"?: number, readonly "owner_type"?: "install" | "repository_change_request" | "repository" | "workspace" | "machine" | "cluster" | "package", readonly "owner_id"?: string }
export const OperationsListParams = Schema.Struct({ "cursor": Schema.optionalKey(Schema.String.annotate({ "description": "Pagination cursor from a previous response's `next_cursor`." })), "limit": Schema.optionalKey(Schema.Number.annotate({ "description": "Items per page (1-100, default 50)", "default": 50 }).check(Schema.isInt().annotate({ "expected": "an integer" })).check(Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" })).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" }))), "owner_type": Schema.optionalKey(Schema.Literals(["install", "repository_change_request", "repository", "workspace", "machine", "cluster", "package"])), "owner_id": Schema.optionalKey(Schema.String.annotate({ "description": "Required when `owner_type` is set. Ignored otherwise." })) })
export type OperationsListParams = { readonly "cursor"?: string, readonly "limit"?: number, readonly "owner_type"?: "install" | "repository_change_request" | "repository" | "workspace" | "machine" | "cluster" | "package", readonly "owner_id"?: string, readonly "akua-context"?: string }
export const OperationsListParams = Schema.Struct({ "cursor": Schema.optionalKey(Schema.String.annotate({ "description": "Pagination cursor from a previous response's `next_cursor`." })), "limit": Schema.optionalKey(Schema.Number.annotate({ "description": "Items per page (1-100, default 50)", "default": 50 }).check(Schema.isInt().annotate({ "expected": "an integer" })).check(Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" })).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" }))), "owner_type": Schema.optionalKey(Schema.Literals(["install", "repository_change_request", "repository", "workspace", "machine", "cluster", "package"])), "owner_id": Schema.optionalKey(Schema.String.annotate({ "description": "Required when `owner_type` is set. Ignored otherwise." })), "akua-context": Schema.optionalKey(Schema.String.annotate({ "description": "Optional workspace/scope context for the request. Carries a single workspace wire id (`ws_…`) today. Only needed for broad tokens — a workspace-owned token implies its workspace." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check(Schema.isMaxLength(53).annotate({ "expected": "a value with a length of at most 53" }))) })
export type OperationsListQuery = { readonly "cursor"?: string, readonly "limit"?: number, readonly "owner_type"?: "install" | "repository_change_request" | "repository" | "workspace" | "machine" | "cluster" | "package", readonly "owner_id"?: string }
export const OperationsListQuery = Schema.Struct({ "cursor": Schema.optionalKey(Schema.String.annotate({ "description": "Pagination cursor from a previous response's `next_cursor`." })), "limit": Schema.optionalKey(Schema.Number.annotate({ "description": "Items per page (1-100, default 50)", "default": 50 }).check(Schema.isInt().annotate({ "expected": "an integer" })).check(Schema.isGreaterThanOrEqualTo(1).annotate({ "expected": "a value greater than or equal to 1" })).check(Schema.isLessThanOrEqualTo(100).annotate({ "expected": "a value less than or equal to 100" }))), "owner_type": Schema.optionalKey(Schema.Literals(["install", "repository_change_request", "repository", "workspace", "machine", "cluster", "package"])), "owner_id": Schema.optionalKey(Schema.String.annotate({ "description": "Required when `owner_type` is set. Ignored otherwise." })) })
export type OperationsListHeaders = { readonly "akua-context"?: string }
export const OperationsListHeaders = Schema.Struct({ "akua-context": Schema.optionalKey(Schema.String.annotate({ "description": "Optional workspace/scope context for the request. Carries a single workspace wire id (`ws_…`) today. Only needed for broad tokens — a workspace-owned token implies its workspace." }).check(Schema.isMinLength(1).annotate({ "expected": "a value with a length of at least 1" })).check(Schema.isMaxLength(53).annotate({ "expected": "a value with a length of at most 53" }))) })
export type OperationsList200 = OperationList
export const OperationsList200 = OperationList
export type OperationsList400 = ApiErrorResponse
Expand Down Expand Up @@ -4179,7 +4181,7 @@ class EntitlementsGroup extends HttpApiGroup.make("Entitlements")
.annotate(OpenApi.Description, "Effective workspace capabilities and limits.") {}

class OperationsGroup extends HttpApiGroup.make("Operations")
.add(HttpApiEndpoint.get("operationsList", "/operations", { query: OperationsListQuery, success: OperationsList200, error: [OperationsList400.pipe(HttpApiSchema.status(400)), OperationsList401.pipe(HttpApiSchema.status(401)), OperationsList403.pipe(HttpApiSchema.status(403))] })
.add(HttpApiEndpoint.get("operationsList", "/operations", { query: OperationsListQuery, headers: OperationsListHeaders, success: OperationsList200, error: [OperationsList400.pipe(HttpApiSchema.status(400)), OperationsList401.pipe(HttpApiSchema.status(401)), OperationsList403.pipe(HttpApiSchema.status(403))] })
.middleware(BearerAuthSecurityMiddleware)
.annotate(OpenApi.Identifier, "operations.list")
.annotate(OpenApi.Summary, "List operations")
Expand Down
8 changes: 6 additions & 2 deletions src/generated/public-operation-executor.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2683,14 +2683,18 @@ function executeOperation(
case "operations.list":
return Effect.gen(function* () {
const input = yield* Schema.decodeUnknownEffect(
Schema.Struct({ query: Schema.optionalKey(Schema.Unknown) }),
Schema.Struct({ query: Schema.optionalKey(Schema.Unknown), headers: Schema.optionalKey(Schema.Unknown) }),
strictParseOptions,
)(rawInput);
const query = yield* atEnvelopeKey("query", Schema.decodeUnknownEffect(
Api.OperationsListQuery,
strictParseOptions,
)(input.query ?? {}));
const value = yield* executeClientOperation(client, client.client["Operations"]["operationsList"]({ query }));
const headers = yield* atEnvelopeKey("headers", Schema.decodeUnknownEffect(
Api.OperationsListHeaders,
strictParseOptions,
)(input.headers ?? {}));
const value = yield* executeClientOperation(client, client.client["Operations"]["operationsList"]({ query, headers }));
return mode === "raw" ? value : { _tag: "Value", value };
});
case "operations.wait":
Expand Down
28 changes: 25 additions & 3 deletions test/generated-command.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,11 @@ describe("generated public commands", () => {
expect(received?.headers.get("authorization")).toBe("Bearer test-token");
});

test("machines.create sends exact headers and JSON body and decodes 202", async () => {
test("machines.create permits an omitted optional compute config and decodes 202", async () => {
let received: Request | undefined;
const body = {
cluster_id: "clu_123",
instance_type: "cx23",
compute_config_id: "ccfg_123",
};
const operation = machineOperation();
const result = await runGenerated(
Expand Down Expand Up @@ -141,6 +140,29 @@ describe("generated public commands", () => {
expect(await received?.json()).toEqual(body);
});

test("operations.list forwards the workspace context header", async () => {
let received: Request | undefined;
const result = await runGenerated(
"operations.list",
["--input", "-"],
JSON.stringify({ headers: { "akua-context": "ws_123" } }),
(input, init) => {
received = new Request(input, init);
return Promise.resolve(
Response.json({ data: [], has_more: false, next_cursor: null }),
);
},
);

expect(result.data).toEqual({
data: [],
has_more: false,
next_cursor: null,
});
expect(received?.url).toBe("https://api.akua.dev/v1/operations");
expect(received?.headers.get("akua-context")).toBe("ws_123");
});

test("clusters.resume builds the literal :action-suffixed request path", async () => {
let received: Request | undefined;
const operation = clusterOperation();
Expand Down Expand Up @@ -537,7 +559,7 @@ describe("generated public commands", () => {
{ path: ["body", "secret"], message: "Expected no excess property" },
],
inputExample:
'{"body":{"cluster_id":"<cluster_id>","instance_type":"<instance_type>","compute_config_id":"<compute_config_id>"}}',
'{"body":{"cluster_id":"<cluster_id>","instance_type":"<instance_type>"}}',
});
});

Expand Down
Loading