@omg-dev/cloud 0.6.41

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Benny Kok
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/auth.d.ts ADDED
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Sign-in and the short-lived app JWT, against better-auth's REST surface.
3
+ *
4
+ * Raw `fetch` on purpose. better-auth's browser client manages a cookie jar,
5
+ * and each consumer here has its own: the native app's platform jar, the
6
+ * dashboard's document cookies, or nothing at all for a self-hosted UI that
7
+ * lets its `omg serve` hold the credential. Keeping to three endpoints of
8
+ * surface area is what lets one module serve all of them.
9
+ *
10
+ * /token authenticates with the session cookie the platform replays, so the
11
+ * server needs no `bearer` plugin for this path.
12
+ */
13
+ import { type CloudEndpoints, type FetchLike } from "./config";
14
+ export declare class OmgAuthError extends Error {
15
+ readonly status: number;
16
+ constructor(message: string, status: number);
17
+ }
18
+ /**
19
+ * The server did not confirm the session was revoked. Distinct from
20
+ * OmgAuthError so a caller can tell "sign-out failed, the account may still
21
+ * be signed in server-side" apart from an ordinary sign-in failure. A caller
22
+ * must NOT treat this the same as a successful sign-out.
23
+ */
24
+ export declare class SignOutFailedError extends Error {
25
+ constructor(message: string);
26
+ }
27
+ export type SignedInUser = {
28
+ id: string;
29
+ email: string;
30
+ name?: string;
31
+ };
32
+ export type SocialProvider = "apple" | "google";
33
+ export interface CloudAuthOptions {
34
+ endpoints?: Partial<CloudEndpoints>;
35
+ fetch?: FetchLike;
36
+ /**
37
+ * Value for the `Origin` header on every auth request.
38
+ *
39
+ * better-auth's origin check rejects state-changing requests that arrive
40
+ * with no Origin header. A browser always sends one; React Native's fetch
41
+ * never does. A consumer with no origin of its own sets one of the server's
42
+ * trusted origins here. A browser consumer leaves it unset, because the
43
+ * browser forbids overriding it anyway.
44
+ */
45
+ requestOrigin?: string;
46
+ /** How long a minted JWT is reused before a fresh mint. Default 30 s. */
47
+ tokenTtlMs?: number;
48
+ now?: () => number;
49
+ }
50
+ export interface CloudAuth {
51
+ sendSignInCode(email: string): Promise<void>;
52
+ verifySignInCode(email: string, otp: string): Promise<SignedInUser>;
53
+ signInWithIdToken(provider: SocialProvider, idToken: string, options?: {
54
+ nonce?: string;
55
+ name?: {
56
+ firstName?: string;
57
+ lastName?: string;
58
+ };
59
+ email?: string;
60
+ }): Promise<SignedInUser>;
61
+ getSession(): Promise<SignedInUser | null>;
62
+ /** Throws SignOutFailedError unless the server confirmed revocation. */
63
+ signOut(): Promise<void>;
64
+ /** The account JWT, or null when nobody is signed in. Cached and deduplicated. */
65
+ getAuthToken(): Promise<string | null>;
66
+ /** Drop the cached JWT so the next call re-mints. */
67
+ clearAuthToken(): void;
68
+ }
69
+ /**
70
+ * One auth client per process.
71
+ *
72
+ * The token cache and the in-flight mint live on the instance, not in a hook
73
+ * or a React context: a hook shares code, never state, and the dashboard once
74
+ * paid five concurrent /token round trips on every cold Computer for exactly
75
+ * that reason. Create this once and hand the same object to every consumer.
76
+ */
77
+ export declare function createCloudAuth(options?: CloudAuthOptions): CloudAuth;
78
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAsC,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAEnG,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,YAAY,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAI1C;CACF;AAED;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACpC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACpE,iBAAiB,CACf,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE;YAAE,SAAS,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAC7F,OAAO,CAAC,YAAY,CAAC,CAAC;IACzB,UAAU,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC3C,wEAAwE;IACxE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,kFAAkF;IAClF,YAAY,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACvC,qDAAqD;IACrD,cAAc,IAAI,IAAI,CAAC;CACxB;AAkBD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,SAAS,CA4JzE"}
package/dist/auth.js ADDED
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Sign-in and the short-lived app JWT, against better-auth's REST surface.
3
+ *
4
+ * Raw `fetch` on purpose. better-auth's browser client manages a cookie jar,
5
+ * and each consumer here has its own: the native app's platform jar, the
6
+ * dashboard's document cookies, or nothing at all for a self-hosted UI that
7
+ * lets its `omg serve` hold the credential. Keeping to three endpoints of
8
+ * surface area is what lets one module serve all of them.
9
+ *
10
+ * /token authenticates with the session cookie the platform replays, so the
11
+ * server needs no `bearer` plugin for this path.
12
+ */
13
+ import { AUTH_APP_ID, resolveCloudEndpoints } from "./config";
14
+ export class OmgAuthError extends Error {
15
+ status;
16
+ constructor(message, status) {
17
+ super(message);
18
+ this.name = "OmgAuthError";
19
+ this.status = status;
20
+ }
21
+ }
22
+ /**
23
+ * The server did not confirm the session was revoked. Distinct from
24
+ * OmgAuthError so a caller can tell "sign-out failed, the account may still
25
+ * be signed in server-side" apart from an ordinary sign-in failure. A caller
26
+ * must NOT treat this the same as a successful sign-out.
27
+ */
28
+ export class SignOutFailedError extends Error {
29
+ constructor(message) {
30
+ super(message);
31
+ this.name = "SignOutFailedError";
32
+ }
33
+ }
34
+ /**
35
+ * better-auth's own routes are mounted under /api/auth, while the JWT exchange
36
+ * at /token is a first-party route at the root. Mixing the two up is a silent
37
+ * 404, so the prefix lives here once.
38
+ */
39
+ const BETTER_AUTH_BASE = "/api/auth";
40
+ function parseJson(text) {
41
+ if (!text)
42
+ return {};
43
+ try {
44
+ return JSON.parse(text);
45
+ }
46
+ catch {
47
+ return {};
48
+ }
49
+ }
50
+ /**
51
+ * One auth client per process.
52
+ *
53
+ * The token cache and the in-flight mint live on the instance, not in a hook
54
+ * or a React context: a hook shares code, never state, and the dashboard once
55
+ * paid five concurrent /token round trips on every cold Computer for exactly
56
+ * that reason. Create this once and hand the same object to every consumer.
57
+ */
58
+ export function createCloudAuth(options = {}) {
59
+ const endpoints = resolveCloudEndpoints(options.endpoints);
60
+ const fetchImpl = options.fetch ?? globalThis.fetch;
61
+ const now = options.now ?? Date.now;
62
+ const tokenTtlMs = options.tokenTtlMs ?? 30_000;
63
+ const baseHeaders = { "Content-Type": "application/json" };
64
+ if (options.requestOrigin)
65
+ baseHeaders.Origin = options.requestOrigin;
66
+ let cachedToken = null;
67
+ let inFlight = null;
68
+ async function authFetch(path, body) {
69
+ let response;
70
+ try {
71
+ response = await fetchImpl(`${endpoints.authOrigin}${BETTER_AUTH_BASE}${path}`, {
72
+ method: "POST",
73
+ headers: baseHeaders,
74
+ credentials: "include",
75
+ body: JSON.stringify(body),
76
+ });
77
+ }
78
+ catch {
79
+ throw new OmgAuthError("Couldn't reach omg. Check your connection.", 0);
80
+ }
81
+ const data = parseJson(await response.text().catch(() => ""));
82
+ if (!response.ok) {
83
+ const record = data;
84
+ throw new OmgAuthError(record?.message ?? record?.error ?? `Sign-in failed (${response.status})`, response.status);
85
+ }
86
+ return data;
87
+ }
88
+ async function mintToken() {
89
+ let response;
90
+ try {
91
+ response = await fetchImpl(`${endpoints.authOrigin}/token`, {
92
+ method: "POST",
93
+ headers: baseHeaders,
94
+ credentials: "include",
95
+ body: JSON.stringify({ appId: AUTH_APP_ID }),
96
+ });
97
+ }
98
+ catch {
99
+ throw new OmgAuthError("Couldn't reach omg. Check your connection.", 0);
100
+ }
101
+ // Not signed in is an ordinary answer, not a failure: the caller turns
102
+ // null into the sign-in screen.
103
+ if (response.status === 401)
104
+ return null;
105
+ if (!response.ok) {
106
+ throw new OmgAuthError(`Couldn't authenticate (${response.status})`, response.status);
107
+ }
108
+ const data = (await response.json().catch(() => null));
109
+ return data?.token ?? null;
110
+ }
111
+ const clearAuthToken = () => {
112
+ cachedToken = null;
113
+ inFlight = null;
114
+ };
115
+ return {
116
+ async sendSignInCode(email) {
117
+ // Rate limited per IP and reports success either way. Never auto-retry.
118
+ await authFetch("/email-otp/send-verification-otp", {
119
+ email: email.trim().toLowerCase(),
120
+ type: "sign-in",
121
+ });
122
+ },
123
+ async verifySignInCode(email, otp) {
124
+ const data = (await authFetch("/sign-in/email-otp", {
125
+ email: email.trim().toLowerCase(),
126
+ otp: otp.trim(),
127
+ }));
128
+ if (!data?.user?.id)
129
+ throw new OmgAuthError("That code didn't work. Try again.", 401);
130
+ return data.user;
131
+ },
132
+ async signInWithIdToken(provider, idToken, extra = {}) {
133
+ const user = extra.name || extra.email
134
+ ? { ...(extra.name ? { name: extra.name } : {}), ...(extra.email ? { email: extra.email } : {}) }
135
+ : undefined;
136
+ const data = (await authFetch("/sign-in/social", {
137
+ provider,
138
+ idToken: {
139
+ token: idToken,
140
+ ...(extra.nonce ? { nonce: extra.nonce } : {}),
141
+ ...(user ? { user } : {}),
142
+ },
143
+ }));
144
+ if (!data?.user?.id)
145
+ throw new OmgAuthError("That sign-in didn't work. Try again.", 401);
146
+ return data.user;
147
+ },
148
+ async getSession() {
149
+ try {
150
+ const response = await fetchImpl(`${endpoints.authOrigin}${BETTER_AUTH_BASE}/get-session`, {
151
+ headers: baseHeaders,
152
+ credentials: "include",
153
+ });
154
+ if (!response.ok)
155
+ return null;
156
+ const data = (await response.json().catch(() => null));
157
+ return data?.user?.id ? data.user : null;
158
+ }
159
+ catch {
160
+ return null;
161
+ }
162
+ },
163
+ /**
164
+ * Fails closed: a network failure throws the same as a server rejection
165
+ * rather than clearing local state. Showing "signed in" while offline is
166
+ * a recoverable annoyance; showing "signed out" while a token is still
167
+ * live is a false claim about account state.
168
+ */
169
+ async signOut() {
170
+ let response;
171
+ try {
172
+ response = await fetchImpl(`${endpoints.authOrigin}${BETTER_AUTH_BASE}/sign-out`, {
173
+ method: "POST",
174
+ headers: baseHeaders,
175
+ credentials: "include",
176
+ });
177
+ }
178
+ catch {
179
+ throw new SignOutFailedError("Couldn't reach omg to sign out. Check your connection and try again.");
180
+ }
181
+ // 401 means the session is already gone. The goal state already holds.
182
+ if (!response.ok && response.status !== 401) {
183
+ throw new SignOutFailedError(`Sign-out was rejected (${response.status}). Your session may still be active — try again.`);
184
+ }
185
+ clearAuthToken();
186
+ },
187
+ getAuthToken() {
188
+ if (cachedToken && now() - cachedToken.fetchedAt < tokenTtlMs) {
189
+ return Promise.resolve(cachedToken.token);
190
+ }
191
+ if (inFlight)
192
+ return inFlight;
193
+ inFlight = mintToken()
194
+ .then((token) => {
195
+ cachedToken = token ? { token, fetchedAt: now() } : null;
196
+ return token;
197
+ })
198
+ .finally(() => {
199
+ inFlight = null;
200
+ });
201
+ return inFlight;
202
+ },
203
+ clearAuthToken,
204
+ };
205
+ }
206
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Where an omg Cloud client points.
3
+ *
4
+ * Every consumer of this package reaches the same three origins, but from a
5
+ * different place: the hosted dashboard from its own domain, the native app
6
+ * from a phone, and a self-hosted `omg serve` UI from a loopback or tailnet
7
+ * address. None of them share a cookie jar or an env prefix, so the endpoints
8
+ * are a plain object the consumer builds once and passes in, never a module
9
+ * global read from `process.env`.
10
+ */
11
+ export interface CloudEndpoints {
12
+ /** Auth server that holds the account session and mints the app JWT. */
13
+ authOrigin: string;
14
+ /** Control plane: account, machine bindings, cloud Computer lifecycle. */
15
+ controlPlaneOrigin: string;
16
+ /** Session origin: the Computer itself, reached through the omg proxy. */
17
+ sessionOrigin: string;
18
+ }
19
+ export declare const DEFAULT_CLOUD_ENDPOINTS: CloudEndpoints;
20
+ /** Fill in the defaults and drop trailing slashes so path joins are exact. */
21
+ export declare function resolveCloudEndpoints(overrides?: Partial<CloudEndpoints>): CloudEndpoints;
22
+ /** Grant mint route on the session origin. */
23
+ export declare const SESSION_AUTH_PATH = "/__omg/session-auth";
24
+ /**
25
+ * The JWT audience. Every omg client is the same account on the same
26
+ * platform, so they all ask for the same one; a different appId would mint a
27
+ * token the session origin does not accept.
28
+ */
29
+ export declare const AUTH_APP_ID = "vibes";
30
+ /**
31
+ * The account's managed cloud sandbox is addressed by this virtual binding id
32
+ * rather than its real sandbox id, so instance ids and node URLs stay server
33
+ * side.
34
+ */
35
+ export declare const CLOUD_BINDING_ID = "cloud";
36
+ /** A fetch a consumer may inject, for tests or a runtime with no global. */
37
+ export type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
38
+ /**
39
+ * Produces the account JWT, or null when nobody is signed in.
40
+ *
41
+ * Injected, not owned here: the hosted dashboard mints it from a browser
42
+ * session, the native app from a platform cookie jar, and a self-hosted UI
43
+ * from its own `omg serve`, which holds the credential on the box.
44
+ */
45
+ export type GetAuthToken = () => Promise<string | null>;
46
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,kBAAkB,EAAE,MAAM,CAAC;IAC3B,0EAA0E;IAC1E,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,uBAAuB,EAAE,cAIrC,CAAC;AAIF,8EAA8E;AAC9E,wBAAgB,qBAAqB,CACnC,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,cAAc,CAQhB;AAED,8CAA8C;AAC9C,eAAO,MAAM,iBAAiB,wBAAwB,CAAC;AAEvD;;;;GAIG;AACH,eAAO,MAAM,WAAW,UAAU,CAAC;AAEnC;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAExC,4EAA4E;AAC5E,MAAM,MAAM,SAAS,GAAG,CACtB,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAC7B,IAAI,CAAC,EAAE,WAAW,KACf,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEvB;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Where an omg Cloud client points.
3
+ *
4
+ * Every consumer of this package reaches the same three origins, but from a
5
+ * different place: the hosted dashboard from its own domain, the native app
6
+ * from a phone, and a self-hosted `omg serve` UI from a loopback or tailnet
7
+ * address. None of them share a cookie jar or an env prefix, so the endpoints
8
+ * are a plain object the consumer builds once and passes in, never a module
9
+ * global read from `process.env`.
10
+ */
11
+ export const DEFAULT_CLOUD_ENDPOINTS = {
12
+ authOrigin: "https://auth.omg.dev",
13
+ controlPlaneOrigin: "https://backend.omg.dev",
14
+ sessionOrigin: "https://sessions.omgs.app",
15
+ };
16
+ const trimSlash = (value) => value.trim().replace(/\/+$/, "");
17
+ /** Fill in the defaults and drop trailing slashes so path joins are exact. */
18
+ export function resolveCloudEndpoints(overrides = {}) {
19
+ return {
20
+ authOrigin: trimSlash(overrides.authOrigin ?? DEFAULT_CLOUD_ENDPOINTS.authOrigin),
21
+ controlPlaneOrigin: trimSlash(overrides.controlPlaneOrigin ?? DEFAULT_CLOUD_ENDPOINTS.controlPlaneOrigin),
22
+ sessionOrigin: trimSlash(overrides.sessionOrigin ?? DEFAULT_CLOUD_ENDPOINTS.sessionOrigin),
23
+ };
24
+ }
25
+ /** Grant mint route on the session origin. */
26
+ export const SESSION_AUTH_PATH = "/__omg/session-auth";
27
+ /**
28
+ * The JWT audience. Every omg client is the same account on the same
29
+ * platform, so they all ask for the same one; a different appId would mint a
30
+ * token the session origin does not accept.
31
+ */
32
+ export const AUTH_APP_ID = "vibes";
33
+ /**
34
+ * The account's managed cloud sandbox is addressed by this virtual binding id
35
+ * rather than its real sandbox id, so instance ids and node URLs stay server
36
+ * side.
37
+ */
38
+ export const CLOUD_BINDING_ID = "cloud";
39
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAWH,MAAM,CAAC,MAAM,uBAAuB,GAAmB;IACrD,UAAU,EAAE,sBAAsB;IAClC,kBAAkB,EAAE,yBAAyB;IAC7C,aAAa,EAAE,2BAA2B;CAC3C,CAAC;AAEF,MAAM,SAAS,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAEtE,8EAA8E;AAC9E,MAAM,UAAU,qBAAqB,CACnC,SAAS,GAA4B,EAAE;IAEvC,OAAO;QACL,UAAU,EAAE,SAAS,CAAC,SAAS,CAAC,UAAU,IAAI,uBAAuB,CAAC,UAAU,CAAC;QACjF,kBAAkB,EAAE,SAAS,CAC3B,SAAS,CAAC,kBAAkB,IAAI,uBAAuB,CAAC,kBAAkB,CAC3E;QACD,aAAa,EAAE,SAAS,CAAC,SAAS,CAAC,aAAa,IAAI,uBAAuB,CAAC,aAAa,CAAC;KAC3F,CAAC;AACJ,CAAC;AAED,8CAA8C;AAC9C,MAAM,CAAC,MAAM,iBAAiB,GAAG,qBAAqB,CAAC;AAEvD;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC;AAEnC;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * The account's machines, as the control plane reports them.
3
+ *
4
+ * Every dashboard read goes through `POST <controlPlane>/api/computer/<name>`
5
+ * with the account JWT as a bearer. The names are the control plane's own
6
+ * function names, so a new one needs no client change beyond a call.
7
+ */
8
+ import { type CloudEndpoints, type FetchLike, type GetAuthToken } from "./config";
9
+ import { type SharedComputerView } from "./shared-binding";
10
+ /** A machine the account owns, paired through `omg connect`. */
11
+ export type ComputerBinding = {
12
+ id: string;
13
+ boxId?: string;
14
+ online?: boolean;
15
+ lastSeenAt?: number | null;
16
+ createdAt?: number;
17
+ defaultFolder?: string | null;
18
+ computerUrl?: string | null;
19
+ };
20
+ /**
21
+ * A machine somebody else shared with this account, presented as an ordinary
22
+ * binding so it flows through the same transport cache, grant mint and picker
23
+ * rows. `id` is the opaque `shared:<ownerUserId>:<bindingId>` spelling.
24
+ *
25
+ * Never synthesized with a `computerUrl`: a guest never gets the owner's
26
+ * direct box URL. Only the session proxy knows how to reach it.
27
+ */
28
+ export type SharedComputerBinding = ComputerBinding & {
29
+ shared: true;
30
+ ownerUserId: string;
31
+ ownerBindingId: string;
32
+ /** The owner's name, or their email if they have none set. */
33
+ ownerLabel: string;
34
+ /** Display name when they have one. Never an email. */
35
+ ownerName?: string;
36
+ email: string;
37
+ machineLabel?: string;
38
+ };
39
+ export declare function toSharedBinding(computer: SharedComputerView): SharedComputerBinding;
40
+ /** Lifecycle of the account's cloud Computer. Server owned, never inferred. */
41
+ export type CloudComputerStatus = "none" | "provisioning" | "waking" | "live" | "paused" | "recycled" | "upgrade_required";
42
+ /** Shape returned by control-plane getCloudComputer. Render what the server sent. */
43
+ export type CloudComputer = {
44
+ status?: CloudComputerStatus | string;
45
+ blockedReason?: "compute_exhausted" | "plan_downgraded" | string | null;
46
+ instanceId?: string | null;
47
+ plan?: string | null;
48
+ machine?: {
49
+ vcpus?: number;
50
+ memoryMib?: number;
51
+ diskGib?: number;
52
+ alwaysOn?: boolean;
53
+ } | null;
54
+ recyclesAt?: number | null;
55
+ };
56
+ /** A cloud Computer that the session proxy would answer with a permanent 425. */
57
+ export declare function isCloudComputerBlocked(cloud: CloudComputer | null | undefined): boolean;
58
+ export interface ControlPlaneOptions {
59
+ endpoints?: Partial<CloudEndpoints>;
60
+ getAuthToken: GetAuthToken;
61
+ fetch?: FetchLike;
62
+ }
63
+ export type MachineList = {
64
+ bindings: ComputerBinding[];
65
+ sharedComputers: SharedComputerBinding[];
66
+ cloud: CloudComputer | null;
67
+ /**
68
+ * Set only when BOTH calls every account depends on failed. The shared list
69
+ * is best effort: almost every account has nothing shared with it, and a
70
+ * failure there costs the "Shared with you" section, never the screen.
71
+ */
72
+ error: string | null;
73
+ };
74
+ export interface ControlPlaneClient {
75
+ /** Call any control plane computer function by name. */
76
+ call<T>(name: string, body?: unknown): Promise<T>;
77
+ listBindings(): Promise<ComputerBinding[]>;
78
+ listSharedComputers(): Promise<SharedComputerBinding[]>;
79
+ getCloudComputer(): Promise<CloudComputer | null>;
80
+ /**
81
+ * The one client-callable path that wakes or provisions the cloud Computer.
82
+ * Minting a grant, reading state, and polling bootstrap never do.
83
+ */
84
+ getOrProvisionCloudComputer(): Promise<CloudComputer | null>;
85
+ setComputerPreference(value: string): Promise<void>;
86
+ /** All three reads at once, each allowed to fail on its own. */
87
+ listMachines(): Promise<MachineList>;
88
+ }
89
+ export declare function createControlPlaneClient(options: ControlPlaneOptions): ControlPlaneClient;
90
+ /**
91
+ * Auto-select when there is no real choice to make. An account with exactly
92
+ * one online machine should not be asked which one; an account whose cloud
93
+ * Computer is plan-blocked should not have it silently chosen either.
94
+ * Returns null when a person has to choose.
95
+ */
96
+ export declare function autoSelectBinding(list: Pick<MachineList, "bindings" | "cloud">): string | null;
97
+ /**
98
+ * A machine's own name: what to call the COMPUTER, not the work it is pointed
99
+ * at. The hostname is the machine's real identity, so it goes first. The
100
+ * folder stays as a fallback; a folder name beats a truncated uuid.
101
+ */
102
+ export declare function bindingLabel(binding: {
103
+ id: string;
104
+ boxId?: string;
105
+ defaultFolder?: string | null;
106
+ computerUrl?: string | null;
107
+ }): string;
108
+ /** Turn a cloud status code into something a person can act on. */
109
+ export declare function cloudStatusLabel(status?: string, blockedReason?: string | null): string;
110
+ /** Machine spec line, e.g. "4 vCPU · 8 GB RAM · 64 GB disk". */
111
+ export declare function machineSpec(machine?: {
112
+ vcpus?: number;
113
+ memoryMib?: number;
114
+ diskGib?: number;
115
+ } | null): string | null;
116
+ //# sourceMappingURL=control-plane.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-plane.d.ts","sourceRoot":"","sources":["../src/control-plane.ts"],"names":[],"mappings":"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"}