unfazed 0.0.1 → 0.1.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/LICENSE +21 -0
- package/README.md +300 -1
- package/dist/client.d.ts +134 -0
- package/dist/client.js +266 -0
- package/dist/client.js.map +1 -0
- package/dist/errors.d.ts +93 -0
- package/dist/errors.js +137 -0
- package/dist/errors.js.map +1 -0
- package/dist/generated/gql.d.ts +132 -0
- package/dist/generated/gql.js +41 -0
- package/dist/generated/gql.js.map +1 -0
- package/dist/generated/graphql.d.ts +774 -0
- package/dist/generated/graphql.js +607 -0
- package/dist/generated/graphql.js.map +1 -0
- package/dist/generated/index.d.ts +1 -0
- package/dist/generated/index.js +2 -0
- package/dist/generated/index.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/operations.d.ts +136 -0
- package/dist/operations.js +461 -0
- package/dist/operations.js.map +1 -0
- package/dist/unfazed.d.ts +445 -0
- package/dist/unfazed.js +510 -0
- package/dist/unfazed.js.map +1 -0
- package/dist/wait.d.ts +57 -0
- package/dist/wait.js +59 -0
- package/dist/wait.js.map +1 -0
- package/package.json +50 -6
- package/schema/SOURCE.json +9 -0
- package/schema/schema.graphqls +1303 -0
- package/index.js +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../src/operations.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Every GraphQL document the workflow layer sends.\n *\n * These are wrapped in `graphql(...)` so graphql-codegen validates them\n * against the vendored schema at codegen time and emits exact result/variable\n * types. A field that stops existing server-side turns into a compile error\n * here rather than a runtime surprise in an agent's script.\n *\n * The one document NOT defined here is the batched file write: it has a\n * variable number of aliased root fields, so it is assembled at runtime in\n * `unfazed.ts`. See the comment there.\n */\nimport { graphql } from \"./generated/gql.js\";\n\n/**\n * Deployment fields the SDK returns everywhere.\n *\n * `id` + `aliasRevision` + `aliasHeld` are the rollback compare-and-swap\n * triple; `previewUrl` is the immutable by-id URL you can verify BEFORE the\n * alias moves; `error` carries the build failure text when status is FAILED.\n */\nexport const DeploymentFieldsFragment = graphql(`\n fragment DeploymentFields on Deployment {\n id\n workspaceID\n kind\n runtime\n alias\n serviceMode\n healthPath\n cronSchedule\n cronPath\n url\n previewUrl\n sshCommand\n aliasHeld\n aliasRevision\n status\n error\n filesCount\n sizeBytes\n size\n spaMode\n gitRepo\n gitCommit\n createdAt\n }\n`);\n\nexport const WhoamiDocument = graphql(`\n query SdkWhoami {\n whoami {\n kind\n userID\n name\n agentID\n agentName\n claimed\n claimedBy\n scopes\n expiresAt\n usage {\n month\n requests\n limit\n }\n resources {\n workspaces\n workspaceLimit\n services\n serviceLimit\n }\n }\n }\n`);\n\nexport const CreateWorkspaceDocument = graphql(`\n mutation SdkCreateWorkspace($name: String!) {\n createWorkspace(input: { name: $name }) {\n workspace {\n id\n name\n ownerId\n projectId\n createdAt\n updatedAt\n }\n }\n }\n`);\n\nexport const ListWorkspacesDocument = graphql(`\n query SdkListWorkspaces {\n workspaces {\n id\n name\n ownerId\n projectId\n createdAt\n updatedAt\n }\n }\n`);\n\nexport const DeleteWorkspaceDocument = graphql(`\n mutation SdkDeleteWorkspace($workspaceID: ID!) {\n deleteWorkspace(input: { workspaceID: $workspaceID }) {\n ok\n }\n }\n`);\n\nexport const WriteTextFileDocument = graphql(`\n mutation SdkWriteTextFile($workspaceID: ID!, $path: String!, $text: String!) {\n writeWorkspaceTextFile(input: { workspaceID: $workspaceID, path: $path, text: $text }) {\n file {\n path\n sizeBytes\n size\n sha256\n updatedAt\n }\n }\n }\n`);\n\nexport const WriteBase64FileDocument = graphql(`\n mutation SdkWriteBase64File($workspaceID: ID!, $path: String!, $contentBase64: String!) {\n writeWorkspaceBase64File(\n input: { workspaceID: $workspaceID, path: $path, contentBase64: $contentBase64 }\n ) {\n file {\n path\n sizeBytes\n size\n sha256\n updatedAt\n }\n }\n }\n`);\n\nexport const ListFilesDocument = graphql(`\n query SdkListFiles($input: ListWorkspaceFilesInput!) {\n workspaceFilesPage(input: $input) {\n items {\n path\n sizeBytes\n size\n sha256\n updatedAt\n }\n total\n limit\n offset\n hasMore\n nextOffset\n }\n }\n`);\n\nexport const ReadFileDocument = graphql(`\n query SdkReadFile($input: ReadWorkspaceFileInput!) {\n readWorkspaceFile(input: $input) {\n text\n offset\n limit\n totalBytes\n truncated\n nextOffset\n file {\n path\n sizeBytes\n size\n sha256\n updatedAt\n }\n }\n }\n`);\n\nexport const DeleteFileDocument = graphql(`\n mutation SdkDeleteFile($workspaceID: ID!, $path: String!) {\n deleteWorkspaceFile(input: { workspaceID: $workspaceID, path: $path }) {\n ok\n }\n }\n`);\n\nexport const CreateDeploymentDocument = graphql(`\n mutation SdkCreateDeployment($input: CreateDeploymentInput!) {\n createDeployment(input: $input) {\n deployment {\n ...DeploymentFields\n }\n }\n }\n`);\n\nexport const DeployWorkspaceDocument = graphql(`\n mutation SdkDeployWorkspace($input: DeployWorkspaceInput!) {\n deployWorkspace(input: $input) {\n deployment {\n ...DeploymentFields\n }\n }\n }\n`);\n\nexport const GetDeploymentDocument = graphql(`\n query SdkGetDeployment($id: ID!) {\n deployment(id: $id) {\n ...DeploymentFields\n }\n }\n`);\n\n/**\n * The poll document, deliberately narrow.\n *\n * Waiting can run for minutes at a few seconds per tick; selecting the full\n * fragment every time would cost the server (and an agent's rate limit) far\n * more than the four fields the state machine actually reads.\n */\nexport const PollDeploymentDocument = graphql(`\n query SdkPollDeployment($id: ID!) {\n deployment(id: $id) {\n id\n status\n error\n aliasHeld\n url\n previewUrl\n }\n }\n`);\n\nexport const GetDeploymentByAliasDocument = graphql(`\n query SdkGetDeploymentByAlias($alias: String!) {\n deploymentByAlias(alias: $alias) {\n ...DeploymentFields\n }\n }\n`);\n\nexport const ListDeploymentsDocument = graphql(`\n query SdkListDeployments($input: ListDeploymentsInput) {\n deploymentsPage(input: $input) {\n items {\n ...DeploymentFields\n }\n total\n limit\n offset\n hasMore\n nextOffset\n }\n }\n`);\n\nexport const ListReleasesDocument = graphql(`\n query SdkListReleases($alias: String!) {\n deploymentReleases(alias: $alias) {\n ...DeploymentFields\n }\n }\n`);\n\nexport const RollbackDocument = graphql(`\n mutation SdkRollback(\n $deploymentID: ID!\n $expectedCurrentDeploymentID: ID!\n $expectedCurrentAliasRevision: String!\n ) {\n rollbackDeployment(\n input: {\n deploymentID: $deploymentID\n expectedCurrentDeploymentID: $expectedCurrentDeploymentID\n expectedCurrentAliasRevision: $expectedCurrentAliasRevision\n }\n ) {\n ...DeploymentFields\n }\n }\n`);\n\nexport const ServiceStatusDocument = graphql(`\n query SdkServiceStatus($deploymentID: ID!) {\n serviceStatus(deploymentID: $deploymentID) {\n deploymentID\n alias\n serviceMode\n running\n health\n vmID\n inFlight\n alwaysOn\n memSizeMiB\n startedAt\n lastUsedAt\n lastStoppedAt\n restartCount\n lastError\n }\n }\n`);\n\nexport const ServiceLogsDocument = graphql(`\n query SdkServiceLogs($deploymentID: ID!, $tailBytes: Int) {\n serviceLogs(deploymentID: $deploymentID, tailBytes: $tailBytes) {\n deploymentID\n stdout\n stderr\n truncated\n stdoutBytes\n stderrBytes\n tailBytes\n }\n }\n`);\n\nexport const DeploymentEventsDocument = graphql(`\n query SdkDeploymentEvents($deploymentID: ID!, $limit: Int) {\n deploymentEvents(deploymentID: $deploymentID, limit: $limit) {\n id\n deploymentID\n type\n rawType\n severity\n message\n vmID\n createdAt\n }\n }\n`);\n\nexport const RestartServiceDocument = graphql(`\n mutation SdkRestartService($deploymentID: ID!) {\n restartService(input: { deploymentID: $deploymentID }) {\n deploymentID\n running\n health\n vmID\n restartCount\n lastError\n }\n }\n`);\n\nexport const StopServiceDocument = graphql(`\n mutation SdkStopService($deploymentID: ID!) {\n stopService(input: { deploymentID: $deploymentID }) {\n deploymentID\n running\n health\n vmID\n restartCount\n lastError\n }\n }\n`);\n\nexport const DeleteDeploymentDocument = graphql(`\n mutation SdkDeleteDeployment($deploymentID: ID!) {\n deleteDeployment(input: { deploymentID: $deploymentID }) {\n ok\n }\n }\n`);\n\n/* -------------------------------------------------------------------------\n * Env & secrets\n *\n * Workspace-scoped values are SERVICE defaults for every app in the source;\n * app-scoped values override them for one alias. Both are snapshotted into a\n * release at deploy time, so a change only reaches a running app after a\n * redeploy — the workflow layer's doc comments repeat this where it matters.\n * ---------------------------------------------------------------------- */\n\nexport const SetWorkspaceEnvDocument = graphql(`\n mutation SdkSetWorkspaceEnv($workspaceID: ID!, $name: String!, $value: String!) {\n setWorkspaceEnv(input: { workspaceID: $workspaceID, name: $name, value: $value }) {\n env {\n name\n value\n secret\n alias\n inherited\n masked\n updatedAt\n }\n }\n }\n`);\n\nexport const SetWorkspaceSecretDocument = graphql(`\n mutation SdkSetWorkspaceSecret($workspaceID: ID!, $name: String!, $value: String!) {\n setWorkspaceSecret(input: { workspaceID: $workspaceID, name: $name, value: $value }) {\n env {\n name\n value\n secret\n alias\n inherited\n masked\n updatedAt\n }\n }\n }\n`);\n\nexport const DeleteWorkspaceEnvDocument = graphql(`\n mutation SdkDeleteWorkspaceEnv($workspaceID: ID!, $name: String!) {\n deleteWorkspaceEnv(input: { workspaceID: $workspaceID, name: $name }) {\n ok\n }\n }\n`);\n\nexport const ListWorkspaceEnvDocument = graphql(`\n query SdkListWorkspaceEnv($workspaceID: ID!) {\n workspaceEnv(workspaceID: $workspaceID) {\n name\n value\n secret\n alias\n inherited\n masked\n updatedAt\n }\n }\n`);\n\nexport const SetAppEnvDocument = graphql(`\n mutation SdkSetAppEnv($workspaceID: ID!, $alias: String!, $name: String!, $value: String!) {\n setAppEnv(input: { workspaceID: $workspaceID, alias: $alias, name: $name, value: $value }) {\n env {\n name\n value\n secret\n alias\n inherited\n masked\n updatedAt\n }\n }\n }\n`);\n\nexport const SetAppSecretDocument = graphql(`\n mutation SdkSetAppSecret($workspaceID: ID!, $alias: String!, $name: String!, $value: String!) {\n setAppSecret(input: { workspaceID: $workspaceID, alias: $alias, name: $name, value: $value }) {\n env {\n name\n value\n secret\n alias\n inherited\n masked\n updatedAt\n }\n }\n }\n`);\n\nexport const RemoveAppEnvDocument = graphql(`\n mutation SdkRemoveAppEnv($workspaceID: ID!, $alias: String!, $name: String!) {\n removeAppEnv(input: { workspaceID: $workspaceID, alias: $alias, name: $name }) {\n ok\n }\n }\n`);\n\nexport const InheritAppEnvDocument = graphql(`\n mutation SdkInheritAppEnv($workspaceID: ID!, $alias: String!, $name: String!) {\n inheritAppEnv(input: { workspaceID: $workspaceID, alias: $alias, name: $name }) {\n ok\n }\n }\n`);\n\nexport const ListAppEnvDocument = graphql(`\n query SdkListAppEnv($workspaceID: ID!, $alias: String!) {\n appEnv(workspaceID: $workspaceID, alias: $alias) {\n name\n value\n secret\n alias\n inherited\n masked\n updatedAt\n }\n }\n`);\n"]}
|
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
import { UnfazedClient, type ClientOptions, type RequestOptions } from "./client.js";
|
|
2
|
+
import type { CreateDeploymentInput, DeploymentFieldsFragment, ListDeploymentsInput, ServiceMode, ServiceRuntime } from "./generated/graphql.js";
|
|
3
|
+
import { type WaitOptions } from "./wait.js";
|
|
4
|
+
/** A deployment as the workflow layer returns it. */
|
|
5
|
+
export type Deployment = DeploymentFieldsFragment;
|
|
6
|
+
/** A file record returned by any write/list operation. */
|
|
7
|
+
export interface WorkspaceFile {
|
|
8
|
+
path: string;
|
|
9
|
+
sizeBytes: number;
|
|
10
|
+
size: string;
|
|
11
|
+
sha256: string;
|
|
12
|
+
updatedAt: string;
|
|
13
|
+
}
|
|
14
|
+
/** One env var in a workspace- or app-scoped view. Secret values are never returned. */
|
|
15
|
+
export interface EnvVar {
|
|
16
|
+
name: string;
|
|
17
|
+
value: string | null;
|
|
18
|
+
secret: boolean;
|
|
19
|
+
alias: string | null;
|
|
20
|
+
inherited: boolean;
|
|
21
|
+
masked: boolean;
|
|
22
|
+
updatedAt: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A file's contents for {@link Unfazed.writeFiles}.
|
|
26
|
+
*
|
|
27
|
+
* A bare string is text — the overwhelmingly common case, and what makes
|
|
28
|
+
* `{ "server.ts": code }` read well. Binary goes through `bytes` or `base64`,
|
|
29
|
+
* which route to `writeWorkspaceBase64File` instead.
|
|
30
|
+
*/
|
|
31
|
+
export type FileContent = string | {
|
|
32
|
+
text: string;
|
|
33
|
+
} | {
|
|
34
|
+
base64: string;
|
|
35
|
+
} | {
|
|
36
|
+
bytes: Uint8Array | ArrayBuffer;
|
|
37
|
+
};
|
|
38
|
+
/** Files keyed by workspace-relative path. */
|
|
39
|
+
export type FilesMap = Record<string, FileContent>;
|
|
40
|
+
export interface WriteFilesOptions {
|
|
41
|
+
/**
|
|
42
|
+
* Max files per GraphQL request. Default 20.
|
|
43
|
+
*
|
|
44
|
+
* The batch is one document with N aliased root fields; too many at once
|
|
45
|
+
* makes a single oversized request whose failure is all-or-nothing to
|
|
46
|
+
* diagnose. Twenty keeps a typical app to one or two round trips.
|
|
47
|
+
*/
|
|
48
|
+
batchSize?: number;
|
|
49
|
+
/**
|
|
50
|
+
* Max total payload bytes per request. Default 4 MiB. Whichever limit trips
|
|
51
|
+
* first closes the batch, so one large file cannot blow the request up.
|
|
52
|
+
*/
|
|
53
|
+
maxBatchBytes?: number;
|
|
54
|
+
signal?: AbortSignal;
|
|
55
|
+
}
|
|
56
|
+
/** Common options for the deploy helpers. */
|
|
57
|
+
export interface DeployOptions {
|
|
58
|
+
workspaceId: string;
|
|
59
|
+
alias?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Block until the deployment reaches a terminal status.
|
|
62
|
+
*
|
|
63
|
+
* `createDeployment` returns BUILDING immediately; the build, VM boot and
|
|
64
|
+
* health probe run in the background. With `wait: true` the call resolves
|
|
65
|
+
* only on READY and throws {@link UnfazedDeployError} on FAILED — which is
|
|
66
|
+
* what makes a one-script deploy possible.
|
|
67
|
+
*/
|
|
68
|
+
wait?: boolean;
|
|
69
|
+
/** Backoff/timeout knobs used when `wait` is true. */
|
|
70
|
+
waitOptions?: WaitOptions;
|
|
71
|
+
signal?: AbortSignal;
|
|
72
|
+
}
|
|
73
|
+
export interface DeployServiceOptions extends DeployOptions {
|
|
74
|
+
/** Omit to auto-detect: a root go.mod+main.go is GO, otherwise BUN. */
|
|
75
|
+
runtime?: ServiceRuntime;
|
|
76
|
+
/** Omit for ON_DEMAND. Only set ALWAYS_ON to keep the VM warm. */
|
|
77
|
+
serviceMode?: ServiceMode;
|
|
78
|
+
healthPath?: string;
|
|
79
|
+
/** Standard 5-field cron spec. Prefer ON_DEMAND + cron over ALWAYS_ON. */
|
|
80
|
+
cronSchedule?: string;
|
|
81
|
+
/** Path the cron tick POSTs to. Defaults to /cron when cronSchedule is set. */
|
|
82
|
+
cronPath?: string;
|
|
83
|
+
}
|
|
84
|
+
export interface DeployStaticOptions extends DeployOptions {
|
|
85
|
+
/** Serve index.html for missing paths (single-page apps). */
|
|
86
|
+
spaMode?: boolean;
|
|
87
|
+
}
|
|
88
|
+
export interface DeployBoxOptions extends DeployOptions {
|
|
89
|
+
/** VM size. Omit for platform defaults (2048 MiB / 2 vCPU / 8 GiB disk). */
|
|
90
|
+
resources?: {
|
|
91
|
+
memMiB?: number;
|
|
92
|
+
vcpus?: number;
|
|
93
|
+
diskGiB?: number;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export interface RollbackOptions {
|
|
97
|
+
/** The alias to roll back. */
|
|
98
|
+
alias: string;
|
|
99
|
+
/**
|
|
100
|
+
* Release to restore. Omit to pick the most recent READY release that is not
|
|
101
|
+
* the current holder — i.e. "undo the last deploy".
|
|
102
|
+
*/
|
|
103
|
+
to?: string;
|
|
104
|
+
/**
|
|
105
|
+
* Re-list-and-retry attempts when the compare-and-swap guard is rejected.
|
|
106
|
+
* Default 1. Each retry refreshes the guard from a fresh read; the TARGET
|
|
107
|
+
* release stays pinned, so a retry can never silently roll back to something
|
|
108
|
+
* other than what was chosen.
|
|
109
|
+
*/
|
|
110
|
+
retries?: number;
|
|
111
|
+
signal?: AbortSignal;
|
|
112
|
+
}
|
|
113
|
+
export interface UnfazedOptions extends ClientOptions {
|
|
114
|
+
/** Use an existing core client instead of constructing one. */
|
|
115
|
+
client?: UnfazedClient;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Layer 2 — the agent workflow layer.
|
|
119
|
+
*
|
|
120
|
+
* Wraps the chains an agent actually performs (create → write → deploy → wait
|
|
121
|
+
* → read logs → roll back) so a code-mode script does in one call what would
|
|
122
|
+
* otherwise be many round trips through a model's context. Everything here is
|
|
123
|
+
* built on {@link UnfazedClient}, exposed as `.client` for anything not
|
|
124
|
+
* wrapped.
|
|
125
|
+
*
|
|
126
|
+
* ```ts
|
|
127
|
+
* const unfazed = new Unfazed(); // reads UNFZ_API_TOKEN
|
|
128
|
+
* const ws = await unfazed.createWorkspace("hello");
|
|
129
|
+
* await unfazed.writeFiles(ws.id, { "server.ts": code });
|
|
130
|
+
* const app = await unfazed.deployService({ workspaceId: ws.id, alias: "hello", wait: true });
|
|
131
|
+
* console.log(app.url);
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
export declare class Unfazed {
|
|
135
|
+
#private;
|
|
136
|
+
/** The underlying typed GraphQL client. Use it for un-wrapped operations. */
|
|
137
|
+
readonly client: UnfazedClient;
|
|
138
|
+
constructor(options?: UnfazedOptions);
|
|
139
|
+
/** Who this token authenticates as, plus usage and resource limits. */
|
|
140
|
+
whoami(options?: RequestOptions): Promise<{
|
|
141
|
+
kind: import("./index.js").CurrentActorKind;
|
|
142
|
+
userID: string;
|
|
143
|
+
name: string;
|
|
144
|
+
agentID: string | null;
|
|
145
|
+
agentName: string | null;
|
|
146
|
+
claimed: boolean;
|
|
147
|
+
claimedBy: string | null;
|
|
148
|
+
scopes: Array<string>;
|
|
149
|
+
expiresAt: string | null;
|
|
150
|
+
usage: {
|
|
151
|
+
month: string;
|
|
152
|
+
requests: number;
|
|
153
|
+
limit: number;
|
|
154
|
+
} | null;
|
|
155
|
+
resources: {
|
|
156
|
+
workspaces: number;
|
|
157
|
+
workspaceLimit: number;
|
|
158
|
+
services: number;
|
|
159
|
+
serviceLimit: number;
|
|
160
|
+
} | null;
|
|
161
|
+
}>;
|
|
162
|
+
/** Creates a source workspace — the container for files, env and deployments. */
|
|
163
|
+
createWorkspace(name: string, options?: RequestOptions): Promise<{
|
|
164
|
+
id: string;
|
|
165
|
+
name: string;
|
|
166
|
+
ownerId: string;
|
|
167
|
+
projectId: string | null;
|
|
168
|
+
createdAt: string;
|
|
169
|
+
updatedAt: string;
|
|
170
|
+
}>;
|
|
171
|
+
/** Workspaces visible to this token. */
|
|
172
|
+
listWorkspaces(options?: RequestOptions): Promise<{
|
|
173
|
+
id: string;
|
|
174
|
+
name: string;
|
|
175
|
+
ownerId: string;
|
|
176
|
+
projectId: string | null;
|
|
177
|
+
createdAt: string;
|
|
178
|
+
updatedAt: string;
|
|
179
|
+
}[]>;
|
|
180
|
+
/**
|
|
181
|
+
* Deletes a workspace and everything anchored to it — deployments, env, and
|
|
182
|
+
* a BOX's persistent data disk. Not recoverable.
|
|
183
|
+
*/
|
|
184
|
+
deleteWorkspace(workspaceId: string, options?: RequestOptions): Promise<boolean>;
|
|
185
|
+
/**
|
|
186
|
+
* Writes many files in as few requests as possible.
|
|
187
|
+
*
|
|
188
|
+
* The API is one-file-per-mutation, so writing a 12-file app naively costs 12
|
|
189
|
+
* round trips. This batches them into a single GraphQL document with one
|
|
190
|
+
* ALIASED root field per file (`f0: writeWorkspaceTextFile(...)`,
|
|
191
|
+
* `f1: ...`), which the server resolves in one request.
|
|
192
|
+
*
|
|
193
|
+
* ```ts
|
|
194
|
+
* await unfazed.writeFiles(ws.id, {
|
|
195
|
+
* "server.ts": serverCode,
|
|
196
|
+
* "unfazed.json": JSON.stringify({ entry: "server.ts" }),
|
|
197
|
+
* "public/logo.png": { bytes: pngBytes },
|
|
198
|
+
* });
|
|
199
|
+
* ```
|
|
200
|
+
*
|
|
201
|
+
* Batches are NOT atomic: GraphQL resolves each aliased field independently,
|
|
202
|
+
* so a partial failure leaves earlier writes committed. The thrown
|
|
203
|
+
* {@link UnfazedGraphQLError} carries `data` with whichever aliases
|
|
204
|
+
* succeeded, and `error.path` identifies the ones that did not.
|
|
205
|
+
*/
|
|
206
|
+
writeFiles(workspaceId: string, files: FilesMap, options?: WriteFilesOptions): Promise<WorkspaceFile[]>;
|
|
207
|
+
/** Writes one text file. Prefer {@link writeFiles} for more than one. */
|
|
208
|
+
writeFile(workspaceId: string, path: string, text: string, options?: RequestOptions): Promise<WorkspaceFile>;
|
|
209
|
+
/** Writes one binary file. Accepts raw bytes or a base64 string. */
|
|
210
|
+
writeBinaryFile(workspaceId: string, path: string, content: Uint8Array | ArrayBuffer | {
|
|
211
|
+
base64: string;
|
|
212
|
+
}, options?: RequestOptions): Promise<WorkspaceFile>;
|
|
213
|
+
/** Lists workspace files (paginated). */
|
|
214
|
+
listFiles(workspaceId: string, input?: {
|
|
215
|
+
limit?: number;
|
|
216
|
+
offset?: number;
|
|
217
|
+
order?: string;
|
|
218
|
+
}, options?: RequestOptions): Promise<{
|
|
219
|
+
total: number;
|
|
220
|
+
limit: number;
|
|
221
|
+
offset: number;
|
|
222
|
+
hasMore: boolean;
|
|
223
|
+
nextOffset: number | null;
|
|
224
|
+
items: Array<{
|
|
225
|
+
path: string;
|
|
226
|
+
sizeBytes: number;
|
|
227
|
+
size: string;
|
|
228
|
+
sha256: string;
|
|
229
|
+
updatedAt: string;
|
|
230
|
+
}>;
|
|
231
|
+
}>;
|
|
232
|
+
/** Reads a text file, optionally a byte range of it. Null when absent. */
|
|
233
|
+
readFile(workspaceId: string, path: string, input?: {
|
|
234
|
+
offset?: number;
|
|
235
|
+
limit?: number;
|
|
236
|
+
}, options?: RequestOptions): Promise<{
|
|
237
|
+
text: string;
|
|
238
|
+
offset: number;
|
|
239
|
+
limit: number;
|
|
240
|
+
totalBytes: number;
|
|
241
|
+
truncated: boolean;
|
|
242
|
+
nextOffset: number | null;
|
|
243
|
+
file: {
|
|
244
|
+
path: string;
|
|
245
|
+
sizeBytes: number;
|
|
246
|
+
size: string;
|
|
247
|
+
sha256: string;
|
|
248
|
+
updatedAt: string;
|
|
249
|
+
};
|
|
250
|
+
} | null>;
|
|
251
|
+
/** Deletes a workspace file. */
|
|
252
|
+
deleteFile(workspaceId: string, path: string, options?: RequestOptions): Promise<boolean>;
|
|
253
|
+
/**
|
|
254
|
+
* Deploys the workspace as a SERVICE (an HTTP server).
|
|
255
|
+
*
|
|
256
|
+
* With `wait: true` this resolves only once the build, VM boot and health
|
|
257
|
+
* probe have all passed.
|
|
258
|
+
*/
|
|
259
|
+
deployService(options: DeployServiceOptions): Promise<Deployment>;
|
|
260
|
+
/** Deploys the workspace as a STATIC site. */
|
|
261
|
+
deployStatic(options: DeployStaticOptions): Promise<Deployment>;
|
|
262
|
+
/**
|
|
263
|
+
* Deploys a BOX: a persistent always-on Linux VM with a data disk that
|
|
264
|
+
* survives stops and redeploys. A dev machine, not an HTTP service. The
|
|
265
|
+
* result's `sshCommand` is how you get in.
|
|
266
|
+
*/
|
|
267
|
+
deployBox(options: DeployBoxOptions): Promise<Deployment>;
|
|
268
|
+
/** Escape hatch: deploy with a raw CreateDeploymentInput. */
|
|
269
|
+
deploy(input: CreateDeploymentInput, options?: Omit<DeployOptions, "workspaceId">): Promise<Deployment>;
|
|
270
|
+
/**
|
|
271
|
+
* Polls a deployment until it is READY, throwing on FAILED or timeout.
|
|
272
|
+
*
|
|
273
|
+
* BUILDING is the only non-terminal status; READY and FAILED are terminal.
|
|
274
|
+
* The poll query selects six fields rather than the full deployment, because
|
|
275
|
+
* this runs every few seconds for potentially minutes — then the READY
|
|
276
|
+
* deployment is re-read in full so callers get the same shape `deployService`
|
|
277
|
+
* returns without `wait`.
|
|
278
|
+
*/
|
|
279
|
+
waitForDeployment(deploymentId: string, waitOptions?: WaitOptions): Promise<Deployment>;
|
|
280
|
+
/** Reads one deployment by id. Null when absent. */
|
|
281
|
+
getDeployment(deploymentId: string, options?: RequestOptions): Promise<Deployment | null>;
|
|
282
|
+
/** Reads the deployment currently serving an alias. Null when absent. */
|
|
283
|
+
getDeploymentByAlias(alias: string, options?: RequestOptions): Promise<Deployment | null>;
|
|
284
|
+
/** Lists deployments (paginated, filterable by kind/alias/workspace). */
|
|
285
|
+
listDeployments(input?: ListDeploymentsInput, options?: RequestOptions): Promise<{
|
|
286
|
+
total: number;
|
|
287
|
+
limit: number;
|
|
288
|
+
offset: number;
|
|
289
|
+
hasMore: boolean;
|
|
290
|
+
nextOffset: number | null;
|
|
291
|
+
items: Array<{
|
|
292
|
+
id: string;
|
|
293
|
+
workspaceID: string;
|
|
294
|
+
kind: import("./index.js").DeploymentKind;
|
|
295
|
+
runtime: ServiceRuntime | null;
|
|
296
|
+
alias: string | null;
|
|
297
|
+
serviceMode: ServiceMode;
|
|
298
|
+
healthPath: string | null;
|
|
299
|
+
cronSchedule: string | null;
|
|
300
|
+
cronPath: string | null;
|
|
301
|
+
url: string;
|
|
302
|
+
previewUrl: string;
|
|
303
|
+
sshCommand: string | null;
|
|
304
|
+
aliasHeld: boolean;
|
|
305
|
+
aliasRevision: string;
|
|
306
|
+
status: import("./index.js").DeploymentStatus;
|
|
307
|
+
error: string | null;
|
|
308
|
+
filesCount: number;
|
|
309
|
+
sizeBytes: number;
|
|
310
|
+
size: string;
|
|
311
|
+
spaMode: boolean;
|
|
312
|
+
gitRepo: string | null;
|
|
313
|
+
gitCommit: string | null;
|
|
314
|
+
createdAt: string;
|
|
315
|
+
}>;
|
|
316
|
+
}>;
|
|
317
|
+
/** Live VM status: health, in-flight requests, restarts, RAM ceiling. */
|
|
318
|
+
getStatus(deploymentId: string, options?: RequestOptions): Promise<{
|
|
319
|
+
deploymentID: string;
|
|
320
|
+
alias: string | null;
|
|
321
|
+
serviceMode: ServiceMode;
|
|
322
|
+
running: boolean;
|
|
323
|
+
health: string;
|
|
324
|
+
vmID: string | null;
|
|
325
|
+
inFlight: number;
|
|
326
|
+
alwaysOn: boolean;
|
|
327
|
+
memSizeMiB: number;
|
|
328
|
+
startedAt: string | null;
|
|
329
|
+
lastUsedAt: string | null;
|
|
330
|
+
lastStoppedAt: string | null;
|
|
331
|
+
restartCount: number;
|
|
332
|
+
lastError: string | null;
|
|
333
|
+
}>;
|
|
334
|
+
/**
|
|
335
|
+
* Tail of the service's stdout/stderr.
|
|
336
|
+
*
|
|
337
|
+
* The point of doing this from a script rather than through tool calls: you
|
|
338
|
+
* can filter locally. `(await unfazed.getLogs(id)).stderr.split("\n")
|
|
339
|
+
* .filter(l => l.includes("ERROR"))` costs a model zero context, where the
|
|
340
|
+
* same tail through an MCP tool spends all of it.
|
|
341
|
+
*/
|
|
342
|
+
getLogs(deploymentId: string, input?: {
|
|
343
|
+
tailBytes?: number;
|
|
344
|
+
}, options?: RequestOptions): Promise<{
|
|
345
|
+
deploymentID: string;
|
|
346
|
+
stdout: string;
|
|
347
|
+
stderr: string;
|
|
348
|
+
truncated: boolean;
|
|
349
|
+
stdoutBytes: number;
|
|
350
|
+
stderrBytes: number;
|
|
351
|
+
tailBytes: number;
|
|
352
|
+
}>;
|
|
353
|
+
/** Deployment lifecycle events — build, boot, probe, cron, restarts. */
|
|
354
|
+
getEvents(deploymentId: string, limit?: number, options?: RequestOptions): Promise<{
|
|
355
|
+
id: string;
|
|
356
|
+
deploymentID: string;
|
|
357
|
+
type: import("./index.js").DeploymentEventType;
|
|
358
|
+
rawType: string;
|
|
359
|
+
severity: import("./index.js").DeploymentEventSeverity;
|
|
360
|
+
message: string;
|
|
361
|
+
vmID: string | null;
|
|
362
|
+
createdAt: string;
|
|
363
|
+
}[]>;
|
|
364
|
+
/** Restarts a service's VM. */
|
|
365
|
+
restartService(deploymentId: string, options?: RequestOptions): Promise<{
|
|
366
|
+
deploymentID: string;
|
|
367
|
+
running: boolean;
|
|
368
|
+
health: string;
|
|
369
|
+
vmID: string | null;
|
|
370
|
+
restartCount: number;
|
|
371
|
+
lastError: string | null;
|
|
372
|
+
}>;
|
|
373
|
+
/** Stops a service's VM. An on-demand service cold-starts again on request. */
|
|
374
|
+
stopService(deploymentId: string, options?: RequestOptions): Promise<{
|
|
375
|
+
deploymentID: string;
|
|
376
|
+
running: boolean;
|
|
377
|
+
health: string;
|
|
378
|
+
vmID: string | null;
|
|
379
|
+
restartCount: number;
|
|
380
|
+
lastError: string | null;
|
|
381
|
+
}>;
|
|
382
|
+
/** Deletes a deployment. */
|
|
383
|
+
deleteDeployment(deploymentId: string, options?: RequestOptions): Promise<boolean>;
|
|
384
|
+
/** Sets a workspace-default env var. Redeploy the alias to apply it. */
|
|
385
|
+
setEnv(workspaceId: string, name: string, value: string, options?: RequestOptions): Promise<EnvVar>;
|
|
386
|
+
/** Sets a workspace-default secret. The value is never readable again. */
|
|
387
|
+
setSecret(workspaceId: string, name: string, value: string, options?: RequestOptions): Promise<EnvVar>;
|
|
388
|
+
/**
|
|
389
|
+
* Sets many workspace env vars in one request, via aliased mutations —
|
|
390
|
+
* the same batching trick as {@link writeFiles}.
|
|
391
|
+
*
|
|
392
|
+
* Pass `{ secret: true }` to route them all to `setWorkspaceSecret`.
|
|
393
|
+
*/
|
|
394
|
+
setEnvMany(workspaceId: string, vars: Record<string, string>, options?: {
|
|
395
|
+
secret?: boolean;
|
|
396
|
+
signal?: AbortSignal;
|
|
397
|
+
}): Promise<EnvVar[]>;
|
|
398
|
+
/** Deletes a workspace-default env var. */
|
|
399
|
+
deleteEnv(workspaceId: string, name: string, options?: RequestOptions): Promise<boolean>;
|
|
400
|
+
/** Workspace-default env vars. Secret values are redacted. */
|
|
401
|
+
listEnv(workspaceId: string, options?: RequestOptions): Promise<EnvVar[]>;
|
|
402
|
+
/** Sets an env var for ONE alias, overriding the workspace default. */
|
|
403
|
+
setAppEnv(workspaceId: string, alias: string, name: string, value: string, options?: RequestOptions): Promise<EnvVar>;
|
|
404
|
+
/** Sets a secret for ONE alias, overriding the workspace default. */
|
|
405
|
+
setAppSecret(workspaceId: string, alias: string, name: string, value: string, options?: RequestOptions): Promise<EnvVar>;
|
|
406
|
+
/**
|
|
407
|
+
* REMOVE: blocks this name for the app entirely — the app override, the
|
|
408
|
+
* workspace default, and integration enrichment. Not the same as deleting an
|
|
409
|
+
* override; use {@link inheritAppEnv} for that.
|
|
410
|
+
*/
|
|
411
|
+
removeAppEnv(workspaceId: string, alias: string, name: string, options?: RequestOptions): Promise<boolean>;
|
|
412
|
+
/** INHERIT: clears the app override/mask so workspace and integration values apply again. */
|
|
413
|
+
inheritAppEnv(workspaceId: string, alias: string, name: string, options?: RequestOptions): Promise<boolean>;
|
|
414
|
+
/** The effective env view for one alias: overrides, inherited and masked. */
|
|
415
|
+
listAppEnv(workspaceId: string, alias: string, options?: RequestOptions): Promise<EnvVar[]>;
|
|
416
|
+
/**
|
|
417
|
+
* An alias's terminal release history, newest first.
|
|
418
|
+
*
|
|
419
|
+
* Exactly one entry has `aliasHeld: true` — the live release. FAILED entries
|
|
420
|
+
* appear on purpose (they are rejected promotions, so a kept-live previous
|
|
421
|
+
* release is never mistaken for a silent fallback) and cannot be rolled back
|
|
422
|
+
* to. Retention keeps only the most recent few per alias, default 5.
|
|
423
|
+
*/
|
|
424
|
+
listReleases(alias: string, options?: RequestOptions): Promise<Deployment[]>;
|
|
425
|
+
/**
|
|
426
|
+
* Rolls an alias back to a prior release, handling the whole compare-and-swap
|
|
427
|
+
* protocol in one call.
|
|
428
|
+
*
|
|
429
|
+
* The server requires the caller to prove it observed the current state: you
|
|
430
|
+
* must pass the live release's id AND its opaque `aliasRevision`, and the
|
|
431
|
+
* swap fails if either changed since you listed — including same-id ABA. So
|
|
432
|
+
* this method does the full dance: list releases, find the `aliasHeld` entry,
|
|
433
|
+
* pick the target, and submit both guard values.
|
|
434
|
+
*
|
|
435
|
+
* On a rejected guard it re-lists and retries (default once). The TARGET is
|
|
436
|
+
* pinned across retries while the guard is refreshed, so a concurrent deploy
|
|
437
|
+
* can never redirect the rollback to a different release than the one chosen.
|
|
438
|
+
*
|
|
439
|
+
* ```ts
|
|
440
|
+
* await unfazed.rollback({ alias: "my-app" }); // undo last deploy
|
|
441
|
+
* await unfazed.rollback({ alias: "my-app", to: relId }); // to a specific release
|
|
442
|
+
* ```
|
|
443
|
+
*/
|
|
444
|
+
rollback(options: RollbackOptions): Promise<Deployment>;
|
|
445
|
+
}
|