@amerged/ohmyhost-mcp 0.1.19 → 0.1.21
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/README.md +1 -1
- package/dist/{chunk-PXGLL6SR.js → chunk-4WY7AAPR.js} +11 -11
- package/dist/index.js +1 -1
- package/dist/stdio-main.js +1575 -310
- package/package.json +1 -1
- package/src/apps/mcp/local-client.ts +119 -17
- package/src/apps/mcp/local-server.ts +321 -88
- package/src/apps/mcp/stdio-main.ts +11 -2
- package/src/apps/product-cli/cli.ts +370 -92
- package/src/apps/product-cli/command.ts +163 -6
- package/src/apps/product-cli/composition.ts +748 -120
- package/src/apps/product-cli/credential-store.ts +5 -3
- package/src/apps/product-cli/index.ts +4 -0
- package/src/apps/product-cli/product-api.ts +32 -4
- package/src/apps/product-cli/profile-store.ts +609 -0
- package/src/apps/product-cli/project-link-store.ts +169 -20
- package/src/apps/product-cli/runtime-contract.ts +63 -7
- package/src/apps/product-cli/workspace.ts +75 -13
- package/src/packages/agent-skills/generated-skill-resources.ts +10 -10
- package/src/packages/contracts/operation-failure.ts +3 -3
- package/src/packages/sdk-ts/generated/index.ts +21 -0
- package/src/packages/sdk-ts/generated/sdk.gen.ts +142 -0
- package/src/packages/sdk-ts/generated/types.gen.ts +200 -2
package/dist/stdio-main.js
CHANGED
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
serverIdentityOf,
|
|
27
27
|
setNegotiatedProtocolVersion,
|
|
28
28
|
validateEnvelopeMeta
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-4WY7AAPR.js";
|
|
30
30
|
|
|
31
31
|
// node_modules/.pnpm/@modelcontextprotocol+server@2.0.0/node_modules/@modelcontextprotocol/server/dist/stdio.mjs
|
|
32
32
|
var StdioServerTransport = class {
|
|
@@ -516,7 +516,7 @@ function toError(value) {
|
|
|
516
516
|
var failures = {
|
|
517
517
|
operation_abandoned: [
|
|
518
518
|
"The operation stopped renewing its execution lease and was ended.",
|
|
519
|
-
"Inspect project status and
|
|
519
|
+
"Inspect project status and, when this operation names a deployment_id, its diagnostics with 'ohmyhost deployment logs --project PROJECT_ULID --deployment DEPLOYMENT_ULID --follow --json' or MCP deployment_logs before creating a fresh plan. Keep this operation ID; the expired execution cannot resume."
|
|
520
520
|
],
|
|
521
521
|
database_write_rejected: [
|
|
522
522
|
"The database rejected this write; it was not committed.",
|
|
@@ -580,7 +580,7 @@ var failures = {
|
|
|
580
580
|
],
|
|
581
581
|
build_failed: [
|
|
582
582
|
"The build did not produce a verified deployable artifact.",
|
|
583
|
-
"
|
|
583
|
+
"Read the BUILD_FAILED diagnostic of this operation's deployment_id with 'ohmyhost deployment logs --project PROJECT_ULID --deployment DEPLOYMENT_ULID --follow --json' or MCP deployment_logs; its excerpt is the tail of the install and build output. Correct that failure and verify the commands for the admitted commit before planning a new deployment."
|
|
584
584
|
],
|
|
585
585
|
insufficient_organization_credits: [
|
|
586
586
|
"The organization does not have sufficient available credits for this operation.",
|
|
@@ -596,7 +596,7 @@ var failures = {
|
|
|
596
596
|
],
|
|
597
597
|
runtime_candidate_failed: [
|
|
598
598
|
"The deployed candidate failed its runtime checks.",
|
|
599
|
-
"
|
|
599
|
+
"Read the HEALTH_CHECK_FAILED diagnostic of this operation's deployment_id with 'ohmyhost deployment logs --project PROJECT_ULID --deployment DEPLOYMENT_ULID --follow --json' or MCP deployment_logs. Its route must answer 2xx to a cookieless GET without a redirect; status_code and, for owners, excerpt show what it answered. Fix that, often a missing secret or a redirect, then plan a new deployment."
|
|
600
600
|
],
|
|
601
601
|
runtime_candidate_rejected: [
|
|
602
602
|
"The runtime rejected the built Worker script.",
|
|
@@ -799,7 +799,7 @@ function exact2(v, keys) {
|
|
|
799
799
|
// apps/product-cli/package.json
|
|
800
800
|
var package_default = {
|
|
801
801
|
name: "@ohmyhost/product-cli",
|
|
802
|
-
version: "0.1.
|
|
802
|
+
version: "0.1.21",
|
|
803
803
|
private: true,
|
|
804
804
|
ohmyhost: {
|
|
805
805
|
deployment: "production",
|
|
@@ -1210,6 +1210,15 @@ function expectPositiveInteger(value, field, options = {}) {
|
|
|
1210
1210
|
return value;
|
|
1211
1211
|
}
|
|
1212
1212
|
|
|
1213
|
+
// packages/workos-auth-contracts/dist/user-api-keys.js
|
|
1214
|
+
var WORKOS_USER_API_KEY_PATTERN = /^sk_[A-Za-z0-9_-]{20,128}$/u;
|
|
1215
|
+
|
|
1216
|
+
// apps/product-cli/dist/profile-store.js
|
|
1217
|
+
import { randomUUID } from "node:crypto";
|
|
1218
|
+
import { link, mkdir as mkdir2, open as open2, readFile, readdir, unlink } from "node:fs/promises";
|
|
1219
|
+
import { homedir } from "node:os";
|
|
1220
|
+
import { join } from "node:path";
|
|
1221
|
+
|
|
1213
1222
|
// apps/product-cli/dist/credential-store.js
|
|
1214
1223
|
var CredentialStoreUnavailableError = class extends Error {
|
|
1215
1224
|
constructor() {
|
|
@@ -1223,10 +1232,12 @@ var CredentialStoreIntegrityError = class extends Error {
|
|
|
1223
1232
|
this.name = "CredentialStoreIntegrityError";
|
|
1224
1233
|
}
|
|
1225
1234
|
};
|
|
1226
|
-
var
|
|
1235
|
+
var LEGACY_CREDENTIAL_ACCOUNT = "credential";
|
|
1227
1236
|
var NativeNapiKeyringCredentialStore = class {
|
|
1237
|
+
account;
|
|
1228
1238
|
createEntry;
|
|
1229
|
-
constructor(createEntry = void 0, serviceName = "ohmyhost") {
|
|
1239
|
+
constructor(createEntry = void 0, serviceName = "ohmyhost", account = LEGACY_CREDENTIAL_ACCOUNT) {
|
|
1240
|
+
this.account = account;
|
|
1230
1241
|
this.createEntry = createEntry ?? createNativeEntryFactory(serviceName);
|
|
1231
1242
|
}
|
|
1232
1243
|
async read() {
|
|
@@ -1248,7 +1259,7 @@ var NativeNapiKeyringCredentialStore = class {
|
|
|
1248
1259
|
throw new CredentialStoreIntegrityError();
|
|
1249
1260
|
}
|
|
1250
1261
|
entry() {
|
|
1251
|
-
return this.createEntry(
|
|
1262
|
+
return this.createEntry(this.account);
|
|
1252
1263
|
}
|
|
1253
1264
|
};
|
|
1254
1265
|
var parseVerifiedCredential = (serialized) => {
|
|
@@ -1301,6 +1312,340 @@ var parseCredential = (serialized) => {
|
|
|
1301
1312
|
};
|
|
1302
1313
|
};
|
|
1303
1314
|
|
|
1315
|
+
// apps/product-cli/dist/profile-store.js
|
|
1316
|
+
var ProfileNameConflictError = class extends Error {
|
|
1317
|
+
profile;
|
|
1318
|
+
constructor(profile) {
|
|
1319
|
+
super("The profile name is used by another saved login");
|
|
1320
|
+
this.profile = profile;
|
|
1321
|
+
this.name = "ProfileNameConflictError";
|
|
1322
|
+
}
|
|
1323
|
+
};
|
|
1324
|
+
var ProfileLimitError = class extends Error {
|
|
1325
|
+
saved;
|
|
1326
|
+
constructor(saved) {
|
|
1327
|
+
super("The saved logins of this environment reached their limit");
|
|
1328
|
+
this.saved = saved;
|
|
1329
|
+
this.name = "ProfileLimitError";
|
|
1330
|
+
}
|
|
1331
|
+
};
|
|
1332
|
+
var MAX_PROFILES = 64;
|
|
1333
|
+
var MAX_INDEX_ATTEMPTS = 64;
|
|
1334
|
+
var INDEX_FILE = /^index-([1-9][0-9]{0,14})\.json$/u;
|
|
1335
|
+
var SERVICE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;
|
|
1336
|
+
var PROFILE_NAME = /^[a-z0-9][a-z0-9_-]{0,62}$/u;
|
|
1337
|
+
var USER_ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/u;
|
|
1338
|
+
var ORGANIZATION_ID = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u;
|
|
1339
|
+
var isProfileName = (value) => PROFILE_NAME.test(value);
|
|
1340
|
+
var isProfileUserId = (value) => USER_ID.test(value);
|
|
1341
|
+
var profileAccount = (profile) => `profile:${profile.userId}:${profile.organizationId ?? "none"}`;
|
|
1342
|
+
var sameLogin = (left, right) => profileAccount(left) === profileAccount(right);
|
|
1343
|
+
var profileIndexDirectory = (serviceName) => join(homedir(), ".ohmyhost", "profiles", serviceName);
|
|
1344
|
+
var nextProfileIndex = (current, profile, replaces) => [
|
|
1345
|
+
...current.filter((saved) => !sameLogin(saved, profile) && (replaces === void 0 || !sameLogin(saved, replaces))),
|
|
1346
|
+
profile
|
|
1347
|
+
];
|
|
1348
|
+
var admitProfile = (next, profile) => {
|
|
1349
|
+
const conflict = next.find((saved) => saved.name === profile.name && saved !== profile);
|
|
1350
|
+
if (conflict !== void 0)
|
|
1351
|
+
throw new ProfileNameConflictError(conflict);
|
|
1352
|
+
if (next.length > MAX_PROFILES)
|
|
1353
|
+
throw new ProfileLimitError(next.length - 1);
|
|
1354
|
+
};
|
|
1355
|
+
var NativeKeyringProfileRegistry = class {
|
|
1356
|
+
serviceName;
|
|
1357
|
+
#createEntry;
|
|
1358
|
+
#index;
|
|
1359
|
+
constructor(createEntry = void 0, serviceName = "ohmyhost", indexDirectory) {
|
|
1360
|
+
this.serviceName = serviceName;
|
|
1361
|
+
if (!SERVICE_NAME.test(serviceName))
|
|
1362
|
+
throw new CredentialStoreUnavailableError();
|
|
1363
|
+
this.#createEntry = createEntry ?? createNativeEntryFactory(serviceName);
|
|
1364
|
+
this.#index = new ProfileIndexFiles(indexDirectory ?? profileIndexDirectory(serviceName));
|
|
1365
|
+
}
|
|
1366
|
+
async list() {
|
|
1367
|
+
return (await this.#index.read()).profiles;
|
|
1368
|
+
}
|
|
1369
|
+
credential(profile) {
|
|
1370
|
+
return new NativeNapiKeyringCredentialStore(this.#createEntry, this.serviceName, profileAccount(profile));
|
|
1371
|
+
}
|
|
1372
|
+
legacy() {
|
|
1373
|
+
return new NativeNapiKeyringCredentialStore(this.#createEntry, this.serviceName, LEGACY_CREDENTIAL_ACCOUNT);
|
|
1374
|
+
}
|
|
1375
|
+
async save(profile, credential, replaces) {
|
|
1376
|
+
assertProfile(profile);
|
|
1377
|
+
const before = await this.list();
|
|
1378
|
+
admitProfile(nextProfileIndex(before, profile, replaces), profile);
|
|
1379
|
+
await this.credential(profile).replace(credential);
|
|
1380
|
+
try {
|
|
1381
|
+
await this.#index.update((current) => {
|
|
1382
|
+
const next = nextProfileIndex(current, profile, replaces);
|
|
1383
|
+
admitProfile(next, profile);
|
|
1384
|
+
return next;
|
|
1385
|
+
});
|
|
1386
|
+
} catch (error) {
|
|
1387
|
+
if (!before.some((saved) => sameLogin(saved, profile)))
|
|
1388
|
+
await this.credential(profile).clear();
|
|
1389
|
+
throw error;
|
|
1390
|
+
}
|
|
1391
|
+
if (replaces !== void 0 && !sameLogin(replaces, profile))
|
|
1392
|
+
await this.credential(replaces).clear();
|
|
1393
|
+
}
|
|
1394
|
+
async remove(profile) {
|
|
1395
|
+
await this.credential(profile).clear();
|
|
1396
|
+
await this.#index.update((current) => current.some((saved) => sameLogin(saved, profile)) ? current.filter((saved) => !sameLogin(saved, profile)) : void 0);
|
|
1397
|
+
}
|
|
1398
|
+
};
|
|
1399
|
+
var ProfileIndexFiles = class {
|
|
1400
|
+
directory;
|
|
1401
|
+
constructor(directory) {
|
|
1402
|
+
this.directory = directory;
|
|
1403
|
+
}
|
|
1404
|
+
async read() {
|
|
1405
|
+
for (let attempt = 0; attempt < MAX_INDEX_ATTEMPTS; attempt += 1) {
|
|
1406
|
+
const version2 = await this.#newest();
|
|
1407
|
+
if (version2 === 0)
|
|
1408
|
+
return { version: version2, profiles: [] };
|
|
1409
|
+
let serialized;
|
|
1410
|
+
try {
|
|
1411
|
+
serialized = await readFile(this.#file(version2), "utf8");
|
|
1412
|
+
} catch (error) {
|
|
1413
|
+
if (fileErrorCode(error) === "ENOENT")
|
|
1414
|
+
continue;
|
|
1415
|
+
throw new CredentialStoreUnavailableError();
|
|
1416
|
+
}
|
|
1417
|
+
return { version: version2, profiles: parseProfileIndex(serialized) };
|
|
1418
|
+
}
|
|
1419
|
+
throw new CredentialStoreUnavailableError();
|
|
1420
|
+
}
|
|
1421
|
+
/** Applies `change` to the newest index; `undefined` means nothing to change. */
|
|
1422
|
+
async update(change) {
|
|
1423
|
+
try {
|
|
1424
|
+
await mkdir2(this.directory, { recursive: true, mode: 448 });
|
|
1425
|
+
} catch {
|
|
1426
|
+
throw new CredentialStoreUnavailableError();
|
|
1427
|
+
}
|
|
1428
|
+
for (let attempt = 0; attempt < MAX_INDEX_ATTEMPTS; attempt += 1) {
|
|
1429
|
+
const { version: version2, profiles } = await this.read();
|
|
1430
|
+
const next = change(profiles);
|
|
1431
|
+
if (next === void 0)
|
|
1432
|
+
return;
|
|
1433
|
+
const temporary = join(this.directory, `.index-${randomUUID()}.tmp`);
|
|
1434
|
+
try {
|
|
1435
|
+
await writeDurably(temporary, serializeProfileIndex(next));
|
|
1436
|
+
await link(temporary, this.#file(version2 + 1));
|
|
1437
|
+
} catch (error) {
|
|
1438
|
+
if (fileErrorCode(error) === "EEXIST")
|
|
1439
|
+
continue;
|
|
1440
|
+
throw new CredentialStoreUnavailableError();
|
|
1441
|
+
} finally {
|
|
1442
|
+
await removeTemporary(temporary);
|
|
1443
|
+
}
|
|
1444
|
+
if (await this.#newest() !== version2 + 1)
|
|
1445
|
+
continue;
|
|
1446
|
+
await this.#prune(version2);
|
|
1447
|
+
return;
|
|
1448
|
+
}
|
|
1449
|
+
throw new CredentialStoreUnavailableError();
|
|
1450
|
+
}
|
|
1451
|
+
async #newest() {
|
|
1452
|
+
let names;
|
|
1453
|
+
try {
|
|
1454
|
+
names = await readdir(this.directory);
|
|
1455
|
+
} catch (error) {
|
|
1456
|
+
if (fileErrorCode(error) === "ENOENT")
|
|
1457
|
+
return 0;
|
|
1458
|
+
throw new CredentialStoreUnavailableError();
|
|
1459
|
+
}
|
|
1460
|
+
return names.reduce((newest, name) => Math.max(newest, indexVersion(name)), 0);
|
|
1461
|
+
}
|
|
1462
|
+
/**
|
|
1463
|
+
* Keeps the superseded version for readers that listed it just now; older ones go. Cleanup only:
|
|
1464
|
+
* a file left behind is ignored, since readers take the newest version, and another process may
|
|
1465
|
+
* be removing the same files at this moment.
|
|
1466
|
+
*/
|
|
1467
|
+
async #prune(superseded) {
|
|
1468
|
+
let names;
|
|
1469
|
+
try {
|
|
1470
|
+
names = await readdir(this.directory);
|
|
1471
|
+
} catch {
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
for (const name of names) {
|
|
1475
|
+
const version2 = indexVersion(name);
|
|
1476
|
+
if (version2 === 0 || version2 >= superseded)
|
|
1477
|
+
continue;
|
|
1478
|
+
try {
|
|
1479
|
+
await unlink(join(this.directory, name));
|
|
1480
|
+
} catch {
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
#file(version2) {
|
|
1485
|
+
return join(this.directory, `index-${String(version2)}.json`);
|
|
1486
|
+
}
|
|
1487
|
+
};
|
|
1488
|
+
var indexVersion = (name) => Number(INDEX_FILE.exec(name)?.[1] ?? 0);
|
|
1489
|
+
var removeTemporary = async (path) => {
|
|
1490
|
+
try {
|
|
1491
|
+
await unlink(path);
|
|
1492
|
+
} catch {
|
|
1493
|
+
}
|
|
1494
|
+
};
|
|
1495
|
+
var fileErrorCode = (error) => typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
|
|
1496
|
+
var writeDurably = async (path, text) => {
|
|
1497
|
+
const handle = await open2(path, "wx", 384);
|
|
1498
|
+
try {
|
|
1499
|
+
await handle.writeFile(text, "utf8");
|
|
1500
|
+
await handle.sync();
|
|
1501
|
+
} finally {
|
|
1502
|
+
await handle.close();
|
|
1503
|
+
}
|
|
1504
|
+
};
|
|
1505
|
+
var serializeProfileIndex = (profiles) => JSON.stringify({
|
|
1506
|
+
version: 1,
|
|
1507
|
+
profiles: [...profiles].sort((left, right) => left.name < right.name ? -1 : 1).map((profile) => ({
|
|
1508
|
+
name: profile.name,
|
|
1509
|
+
user_id: profile.userId,
|
|
1510
|
+
organization_id: profile.organizationId,
|
|
1511
|
+
organization_name: profile.organizationName
|
|
1512
|
+
}))
|
|
1513
|
+
});
|
|
1514
|
+
var parseProfileIndex = (serialized) => {
|
|
1515
|
+
try {
|
|
1516
|
+
const value = JSON.parse(serialized);
|
|
1517
|
+
if (!isRecord(value, ["version", "profiles"]) || value["version"] !== 1)
|
|
1518
|
+
throw new Error("Invalid profile index");
|
|
1519
|
+
const entries = value["profiles"];
|
|
1520
|
+
if (!Array.isArray(entries) || entries.length > MAX_PROFILES)
|
|
1521
|
+
throw new Error("Invalid profile index");
|
|
1522
|
+
const profiles = entries.map((entry) => {
|
|
1523
|
+
if (!isRecord(entry, ["name", "user_id", "organization_id", "organization_name"]))
|
|
1524
|
+
throw new Error("Invalid profile");
|
|
1525
|
+
const profile = {
|
|
1526
|
+
name: entry["name"],
|
|
1527
|
+
userId: entry["user_id"],
|
|
1528
|
+
organizationId: entry["organization_id"],
|
|
1529
|
+
organizationName: entry["organization_name"]
|
|
1530
|
+
};
|
|
1531
|
+
assertProfile(profile);
|
|
1532
|
+
return profile;
|
|
1533
|
+
});
|
|
1534
|
+
if (new Set(profiles.map((profile) => profile.name)).size !== profiles.length || new Set(profiles.map(profileAccount)).size !== profiles.length)
|
|
1535
|
+
throw new Error("Duplicate profile");
|
|
1536
|
+
return profiles;
|
|
1537
|
+
} catch {
|
|
1538
|
+
throw new CredentialStoreIntegrityError();
|
|
1539
|
+
}
|
|
1540
|
+
};
|
|
1541
|
+
var assertProfile = (profile) => {
|
|
1542
|
+
if (typeof profile.name !== "string" || !PROFILE_NAME.test(profile.name) || typeof profile.userId !== "string" || !USER_ID.test(profile.userId) || !(profile.organizationId === null || typeof profile.organizationId === "string" && ORGANIZATION_ID.test(profile.organizationId)) || !(profile.organizationName === null || typeof profile.organizationName === "string" && profile.organizationName.length > 0 && profile.organizationName.length <= 128 && !new RegExp("\\p{Cc}", "u").test(profile.organizationName)) || profile.organizationId === null && profile.organizationName !== null)
|
|
1543
|
+
throw new CredentialStoreIntegrityError();
|
|
1544
|
+
};
|
|
1545
|
+
var isRecord = (value, keys) => typeof value === "object" && value !== null && !Array.isArray(value) && Object.keys(value).sort().join(",") === [...keys].sort().join(",");
|
|
1546
|
+
var selectProfile = (profiles, request) => {
|
|
1547
|
+
if (request.name !== void 0 && request.bound !== void 0 && request.name !== request.bound)
|
|
1548
|
+
return { outcome: "conflict", field: "binding", profile: null };
|
|
1549
|
+
const named = request.name ?? request.bound;
|
|
1550
|
+
if (named !== void 0) {
|
|
1551
|
+
const profile = profiles.find((saved) => saved.name === named);
|
|
1552
|
+
if (profile === void 0)
|
|
1553
|
+
return { outcome: "not_found" };
|
|
1554
|
+
if (request.organizationId !== void 0 && profile.organizationId !== request.organizationId)
|
|
1555
|
+
return { outcome: "conflict", field: "organization", profile };
|
|
1556
|
+
if (request.userId !== void 0 && profile.userId !== request.userId)
|
|
1557
|
+
return { outcome: "conflict", field: "user", profile };
|
|
1558
|
+
return { outcome: "selected", profile };
|
|
1559
|
+
}
|
|
1560
|
+
const candidates = profiles.filter((profile) => (request.organizationId === void 0 || profile.organizationId === request.organizationId) && (request.userId === void 0 || profile.userId === request.userId));
|
|
1561
|
+
const only = candidates[0];
|
|
1562
|
+
if (candidates.length === 1 && only !== void 0)
|
|
1563
|
+
return { outcome: "selected", profile: only };
|
|
1564
|
+
if (candidates.length > 1)
|
|
1565
|
+
return { outcome: "ambiguous", candidates };
|
|
1566
|
+
return profiles.length === 0 ? { outcome: "none" } : { outcome: "not_found" };
|
|
1567
|
+
};
|
|
1568
|
+
var selectProfileForOrganization = (profiles, request) => {
|
|
1569
|
+
const user = request.userId === void 0 ? {} : { userId: request.userId };
|
|
1570
|
+
if (request.name !== void 0 || request.bound !== void 0)
|
|
1571
|
+
return selectProfile(profiles, {
|
|
1572
|
+
...request.name === void 0 ? {} : { name: request.name },
|
|
1573
|
+
...request.bound === void 0 ? {} : { bound: request.bound },
|
|
1574
|
+
...user
|
|
1575
|
+
});
|
|
1576
|
+
const candidates = profiles.filter((profile) => request.userId === void 0 || profile.userId === request.userId);
|
|
1577
|
+
const inOrganization = candidates.filter((profile) => profile.organizationId === request.organizationId);
|
|
1578
|
+
if (inOrganization.length > 1)
|
|
1579
|
+
return { outcome: "ambiguous", candidates: inOrganization };
|
|
1580
|
+
const unscoped = candidates.filter((profile) => profile.organizationId === null);
|
|
1581
|
+
const [member] = inOrganization;
|
|
1582
|
+
if (member !== void 0)
|
|
1583
|
+
return { outcome: "selected", profile: member };
|
|
1584
|
+
const [open4] = unscoped;
|
|
1585
|
+
if (unscoped.length === 1 && open4 !== void 0)
|
|
1586
|
+
return { outcome: "selected", profile: open4 };
|
|
1587
|
+
return selectProfile(profiles, user);
|
|
1588
|
+
};
|
|
1589
|
+
var defaultProfileName = (profiles, login) => {
|
|
1590
|
+
const same = profiles.find((profile) => profile.userId === login.userId && profile.organizationId === login.organizationId);
|
|
1591
|
+
if (same !== void 0)
|
|
1592
|
+
return same.name;
|
|
1593
|
+
const base = slug(login.organizationName ?? "") || (login.organizationId === null ? "account" : "workspace");
|
|
1594
|
+
const free = (name) => profiles.every((profile) => profile.name !== name);
|
|
1595
|
+
if (free(base))
|
|
1596
|
+
return base;
|
|
1597
|
+
const suffix = (login.organizationId ?? login.userId).replace(/[^A-Za-z0-9]/gu, "").slice(-6).toLowerCase();
|
|
1598
|
+
for (let attempt = 1; attempt <= profiles.length + 1; attempt += 1) {
|
|
1599
|
+
const candidate = `${base.slice(0, 48)}-${suffix}${attempt === 1 ? "" : `-${String(attempt)}`}`;
|
|
1600
|
+
if (free(candidate))
|
|
1601
|
+
return candidate;
|
|
1602
|
+
}
|
|
1603
|
+
throw new CredentialStoreIntegrityError();
|
|
1604
|
+
};
|
|
1605
|
+
var slug = (value) => value.normalize("NFKD").replace(/[\u0300-\u036f]/gu, "").toLowerCase().replace(/[^a-z0-9]+/gu, "-").replace(/^-+/u, "").slice(0, 40).replace(/-+$/u, "");
|
|
1606
|
+
var publicProfile = (profile) => ({
|
|
1607
|
+
name: profile.name,
|
|
1608
|
+
user_id: profile.userId,
|
|
1609
|
+
organization_id: profile.organizationId,
|
|
1610
|
+
organization_name: profile.organizationName
|
|
1611
|
+
});
|
|
1612
|
+
var profileLimitAction = (commandPrefix) => `Nothing was saved: this environment already keeps ${String(MAX_PROFILES)} saved logins, the most one computer holds. Remove one you no longer need with '${commandPrefix} logout --profile-name NAME --json' ('${commandPrefix} profile list --json' shows them), then retry.`;
|
|
1613
|
+
var ProfileSelectionError = class extends Error {
|
|
1614
|
+
code;
|
|
1615
|
+
exitCode;
|
|
1616
|
+
suggestedAction;
|
|
1617
|
+
constructor(code, exitCode, suggestedAction) {
|
|
1618
|
+
super(`${code}: ${suggestedAction}`);
|
|
1619
|
+
this.code = code;
|
|
1620
|
+
this.exitCode = exitCode;
|
|
1621
|
+
this.suggestedAction = suggestedAction;
|
|
1622
|
+
this.name = "ProfileSelectionError";
|
|
1623
|
+
}
|
|
1624
|
+
};
|
|
1625
|
+
var profileSelectionError = (selection, request, commandPrefix, selector) => {
|
|
1626
|
+
const choose = selector === "cli" ? `pass --profile-name NAME (see '${commandPrefix} profile list --json') or set OHMYHOST_PROFILE for this process` : "pass profile_name (see profile_list) or set OHMYHOST_PROFILE in this MCP server's configuration";
|
|
1627
|
+
const login = `${commandPrefix} login${request.organizationId === void 0 ? "" : ` --organization ${request.organizationId}`}${request.userId === void 0 ? "" : ` --user ${request.userId}`}${(request.name ?? request.bound) === void 0 ? "" : ` --profile-name ${String(request.name ?? request.bound)}`} --json`;
|
|
1628
|
+
if (selection.outcome === "none")
|
|
1629
|
+
return new ProfileSelectionError("authentication_required", 5, `No login is saved on this computer. Run '${login}'.`);
|
|
1630
|
+
if (selection.outcome === "not_found")
|
|
1631
|
+
return new ProfileSelectionError("profile_not_found", 5, `No saved login matches ${describeRequest(request)}. Run '${login}' to add it, signing in as that user; '${commandPrefix} profile list --json' shows the saved logins.`);
|
|
1632
|
+
if (selection.outcome === "ambiguous")
|
|
1633
|
+
return new ProfileSelectionError("profile_selection_required", 2, `Several saved logins could run this: ${selection.candidates.map((profile2) => profile2.name).join(", ")}. Ask the customer which account to use, then ${choose}.`);
|
|
1634
|
+
if (selection.field === "binding")
|
|
1635
|
+
return new ProfileSelectionError("profile_context_mismatch", 2, `This call names profile ${String(request.name)}, but the process is bound to OHMYHOST_PROFILE=${String(request.bound)}. Use the bound profile or start a process for the other one.`);
|
|
1636
|
+
const profile = selection.profile;
|
|
1637
|
+
return new ProfileSelectionError("profile_context_mismatch", 2, selection.field === "organization" ? `Profile ${String(profile?.name)} is signed in to organization ${String(profile?.organizationId ?? "none")}, but this targets organization ${String(request.organizationId)}. Use the profile of that organization or change the target; nothing was sent.` : `Profile ${String(profile?.name)} belongs to user ${String(profile?.userId)}, not ${String(request.userId)}. Use that user's profile; nothing was sent.`);
|
|
1638
|
+
};
|
|
1639
|
+
var describeRequest = (request) => {
|
|
1640
|
+
const parts = [
|
|
1641
|
+
...(request.name ?? request.bound) === void 0 ? [] : [`profile ${String(request.name ?? request.bound)}`],
|
|
1642
|
+
...request.organizationId === void 0 ? [] : [`organization ${request.organizationId}`],
|
|
1643
|
+
...request.userId === void 0 ? [] : [`user ${request.userId}`]
|
|
1644
|
+
];
|
|
1645
|
+
return parts.length === 0 ? "this request" : parts.join(", ");
|
|
1646
|
+
};
|
|
1647
|
+
var describeProfile = (profile) => `profile ${profile.name} (user ${profile.userId}, ${profile.organizationId === null ? "no organization" : `organization ${profile.organizationName === null ? "" : `${profile.organizationName} `}${profile.organizationId}`})`;
|
|
1648
|
+
|
|
1304
1649
|
// apps/product-cli/dist/device-token-expiry.js
|
|
1305
1650
|
var DeviceTokenExpiryError = class extends Error {
|
|
1306
1651
|
constructor() {
|
|
@@ -1375,46 +1720,6 @@ var resolveDeviceTokenExpiresAt = (accessToken, expiresInSeconds, now) => {
|
|
|
1375
1720
|
return new Date(jwtExpiryMilliseconds).toISOString();
|
|
1376
1721
|
};
|
|
1377
1722
|
|
|
1378
|
-
// apps/product-cli/dist/workspace.js
|
|
1379
|
-
var InteractiveSessionRequiredError = class extends Error {
|
|
1380
|
-
constructor() {
|
|
1381
|
-
super("Workspace selection requires an interactive login");
|
|
1382
|
-
this.name = "InteractiveSessionRequiredError";
|
|
1383
|
-
}
|
|
1384
|
-
};
|
|
1385
|
-
var chooseWorkspace = (organizations, requested) => {
|
|
1386
|
-
if (requested !== void 0) {
|
|
1387
|
-
const match = organizations.find((organization) => organization.id === requested);
|
|
1388
|
-
return match === void 0 ? { outcome: "not_a_member", organizations } : { outcome: "selected", organization: match };
|
|
1389
|
-
}
|
|
1390
|
-
if (organizations.length === 0)
|
|
1391
|
-
return { outcome: "no_workspace" };
|
|
1392
|
-
const only = organizations[0];
|
|
1393
|
-
if (organizations.length === 1 && only !== void 0)
|
|
1394
|
-
return { outcome: "selected", organization: only };
|
|
1395
|
-
return { outcome: "choice_required", organizations };
|
|
1396
|
-
};
|
|
1397
|
-
var selectWorkspace = async (session, organization, signal) => {
|
|
1398
|
-
const stored = await session.store.read();
|
|
1399
|
-
if (stored === void 0)
|
|
1400
|
-
throw new InteractiveSessionRequiredError();
|
|
1401
|
-
const refreshed = await session.refresher.refresh(stored.refreshToken, signal, organization.workos_id);
|
|
1402
|
-
await session.store.replace({
|
|
1403
|
-
...refreshed,
|
|
1404
|
-
workosOrganizationId: organization.workos_id,
|
|
1405
|
-
organizationId: organization.id
|
|
1406
|
-
});
|
|
1407
|
-
};
|
|
1408
|
-
var selectedWorkspaceId = async (session) => (await session.store.read())?.organizationId ?? null;
|
|
1409
|
-
var workspaceOf = (credential) => ({
|
|
1410
|
-
...credential.workosOrganizationId === void 0 ? {} : { workosOrganizationId: credential.workosOrganizationId },
|
|
1411
|
-
...credential.organizationId === void 0 ? {} : { organizationId: credential.organizationId }
|
|
1412
|
-
});
|
|
1413
|
-
var publicWorkspace = (organization) => ({
|
|
1414
|
-
id: organization.id,
|
|
1415
|
-
name: organization.name
|
|
1416
|
-
});
|
|
1417
|
-
|
|
1418
1723
|
// packages/contracts/dist/feedback.js
|
|
1419
1724
|
var FEEDBACK_HISTORY_PAGE_SIZE = 25;
|
|
1420
1725
|
var FEEDBACK_REPLY_MAX_LENGTH = 2e3;
|
|
@@ -1648,7 +1953,7 @@ var PROBLEM_POLICY = {
|
|
|
1648
1953
|
github_connection_required: {
|
|
1649
1954
|
status: 409,
|
|
1650
1955
|
retryable: false,
|
|
1651
|
-
action: "Run 'ohmyhost github connect --organization ULID --idempotency-key KEY --json' for
|
|
1956
|
+
action: "This workspace has no GitHub connection yet. Run 'ohmyhost github connect --organization ULID --idempotency-key KEY --json' for it, complete its browser link, then repeat the original source link. If the project belongs to another account, use that account's login instead; error.acting_as names the login this ran as."
|
|
1652
1957
|
},
|
|
1653
1958
|
github_connection_revoked: {
|
|
1654
1959
|
status: 409,
|
|
@@ -1722,7 +2027,11 @@ var PROBLEM_POLICY = {
|
|
|
1722
2027
|
retryable: false,
|
|
1723
2028
|
action: "Run 'ohmyhost organization list --json' and select one with 'ohmyhost organization use --organization ULID --json', or create the first workspace."
|
|
1724
2029
|
},
|
|
1725
|
-
resource_not_found: {
|
|
2030
|
+
resource_not_found: {
|
|
2031
|
+
status: 404,
|
|
2032
|
+
retryable: false,
|
|
2033
|
+
action: "Check the resource identifier and the account: a project is visible only to its own organization, and error.acting_as names the login this ran as. Use the login of the account that owns it."
|
|
2034
|
+
},
|
|
1726
2035
|
idempotency_key_reused: {
|
|
1727
2036
|
status: 409,
|
|
1728
2037
|
retryable: false,
|
|
@@ -1859,6 +2168,11 @@ var PROBLEM_POLICY = {
|
|
|
1859
2168
|
retryable: false,
|
|
1860
2169
|
action: "Finish database provisioning, then request the export again. No backup was accepted."
|
|
1861
2170
|
},
|
|
2171
|
+
powered_by_flag_required: {
|
|
2172
|
+
status: 409,
|
|
2173
|
+
retryable: false,
|
|
2174
|
+
action: "Keep the flag on, remove the custom domain with 'ohmyhost domain paid delete', or buy Paid, then switch the flag off."
|
|
2175
|
+
},
|
|
1862
2176
|
rate_limited: { status: 429, retryable: true, action: "Retry after the server delay." },
|
|
1863
2177
|
insufficient_organization_credits: {
|
|
1864
2178
|
status: 402,
|
|
@@ -1873,7 +2187,7 @@ var PROBLEM_POLICY = {
|
|
|
1873
2187
|
paid_plan_required: {
|
|
1874
2188
|
status: 402,
|
|
1875
2189
|
retryable: false,
|
|
1876
|
-
action: "Ask the organization Owner to activate Paid through billing checkout, then retry. Top-ups and signup credits do not activate Paid."
|
|
2190
|
+
action: "Ask the organization Owner to activate Paid through billing checkout, then retry. Top-ups and signup credits do not activate Paid. For a website domain alone, a Free workspace may instead show the powered-by flag on the project."
|
|
1877
2191
|
},
|
|
1878
2192
|
interactive_login_required: {
|
|
1879
2193
|
status: 403,
|
|
@@ -1981,6 +2295,18 @@ var parseDevAccessState = (value) => {
|
|
|
1981
2295
|
throw new ResponseContractError();
|
|
1982
2296
|
return input;
|
|
1983
2297
|
};
|
|
2298
|
+
var parsePoweredByFlag = (value) => {
|
|
2299
|
+
const input = exactRecord2(value, ["project_id", "enabled", "enabled_at"]);
|
|
2300
|
+
if (!isUlid(input["project_id"]) || typeof input["enabled"] !== "boolean" || (input["enabled"] ? !isIsoInstant(input["enabled_at"]) : input["enabled_at"] !== null))
|
|
2301
|
+
throw new ResponseContractError();
|
|
2302
|
+
return input;
|
|
2303
|
+
};
|
|
2304
|
+
var parseOrganizationReferral = (value) => {
|
|
2305
|
+
const input = exactRecord2(value, ["organization_id", "referral_url"]);
|
|
2306
|
+
if (!isUlid(input["organization_id"]) || input["referral_url"] !== `https://ohmyho.st/?r=ref-${String(input["organization_id"]).toLowerCase()}`)
|
|
2307
|
+
throw new ResponseContractError();
|
|
2308
|
+
return input;
|
|
2309
|
+
};
|
|
1984
2310
|
var parseDevAccessTicket = (value) => {
|
|
1985
2311
|
const input = exactRecord2(value, [
|
|
1986
2312
|
"ticket_id",
|
|
@@ -2034,7 +2360,7 @@ var parseAccountProfile = (value) => {
|
|
|
2034
2360
|
});
|
|
2035
2361
|
if (new Set(workspaces.map((workspace) => workspace.id)).size !== organizationIds.length)
|
|
2036
2362
|
throw new ResponseContractError();
|
|
2037
|
-
return workspaces;
|
|
2363
|
+
return { userId: input["user_id"], organizations: workspaces };
|
|
2038
2364
|
};
|
|
2039
2365
|
var parseSafeProblem = (value) => {
|
|
2040
2366
|
const input = exactRecord2(value, [
|
|
@@ -2072,6 +2398,7 @@ var parseSafeProblem = (value) => {
|
|
|
2072
2398
|
var parseOperation = (value) => {
|
|
2073
2399
|
const input = exactRecord2(value, [
|
|
2074
2400
|
"blocking_operation_id",
|
|
2401
|
+
"deployment_id",
|
|
2075
2402
|
"id",
|
|
2076
2403
|
"state",
|
|
2077
2404
|
"created_at",
|
|
@@ -2087,9 +2414,10 @@ var parseOperation = (value) => {
|
|
|
2087
2414
|
const updatedAt = input["updated_at"];
|
|
2088
2415
|
const result = input["result"];
|
|
2089
2416
|
const blockingOperationId = input["blocking_operation_id"];
|
|
2090
|
-
|
|
2417
|
+
const deploymentId = input["deployment_id"];
|
|
2418
|
+
if (blockingOperationId !== void 0 && (state !== "queued" || !isUlid(blockingOperationId) || blockingOperationId === id3) || deploymentId !== void 0 && !isUlid(deploymentId))
|
|
2091
2419
|
throw new ResponseContractError();
|
|
2092
|
-
if (!isUlid(id3) || !isOperationState(state) || !isIsoInstant(createdAt) || !isIsoInstant(updatedAt) || result !== void 0 && !
|
|
2420
|
+
if (!isUlid(id3) || !isOperationState(state) || !isIsoInstant(createdAt) || !isIsoInstant(updatedAt) || result !== void 0 && !isRecord2(result)) {
|
|
2093
2421
|
throw new ResponseContractError();
|
|
2094
2422
|
}
|
|
2095
2423
|
let progress;
|
|
@@ -2134,6 +2462,7 @@ var parseOperation = (value) => {
|
|
|
2134
2462
|
created_at: createdAt,
|
|
2135
2463
|
updated_at: updatedAt,
|
|
2136
2464
|
...blockingOperationId === void 0 ? {} : { blocking_operation_id: blockingOperationId },
|
|
2465
|
+
...deploymentId === void 0 ? {} : { deployment_id: deploymentId },
|
|
2137
2466
|
...progress === void 0 ? {} : { progress },
|
|
2138
2467
|
...result === void 0 ? {} : { result },
|
|
2139
2468
|
...error === void 0 ? {} : { error },
|
|
@@ -2150,12 +2479,12 @@ function parseOperationFailure(value) {
|
|
|
2150
2479
|
return safe;
|
|
2151
2480
|
}
|
|
2152
2481
|
var exactRecord2 = (value, allowed) => {
|
|
2153
|
-
if (!
|
|
2482
|
+
if (!isRecord2(value) || Object.keys(value).some((key) => !allowed.includes(key))) {
|
|
2154
2483
|
throw new ResponseContractError();
|
|
2155
2484
|
}
|
|
2156
2485
|
return value;
|
|
2157
2486
|
};
|
|
2158
|
-
var
|
|
2487
|
+
var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2159
2488
|
var boundedString = (value, minimum, maximum) => typeof value === "string" && value.length >= minimum && value.length <= maximum;
|
|
2160
2489
|
var isUlid = (value) => typeof value === "string" && /^[0-9A-HJKMNP-TV-Z]{26}$/u.test(value);
|
|
2161
2490
|
var isIsoInstant = (value) => typeof value === "string" && value.length <= 64 && Number.isFinite(Date.parse(value));
|
|
@@ -2178,6 +2507,79 @@ var isPaidValidationRecord = (value) => {
|
|
|
2178
2507
|
return (record5["type"] === "CNAME" || record5["type"] === "TXT") && boundedString(record5["name"], 1, 253) && boundedString(record5["content"], 1, 2048) && ["traffic", "ownership", "ssl", "dcv_delegation"].includes(String(record5["purpose"]));
|
|
2179
2508
|
};
|
|
2180
2509
|
|
|
2510
|
+
// apps/product-cli/dist/workspace.js
|
|
2511
|
+
var InteractiveSessionRequiredError = class extends Error {
|
|
2512
|
+
constructor() {
|
|
2513
|
+
super("Workspace selection requires an interactive login");
|
|
2514
|
+
this.name = "InteractiveSessionRequiredError";
|
|
2515
|
+
}
|
|
2516
|
+
};
|
|
2517
|
+
var ProfileOrganizationFixedError = class extends Error {
|
|
2518
|
+
profile;
|
|
2519
|
+
organization;
|
|
2520
|
+
constructor(profile, organization) {
|
|
2521
|
+
super("The saved login is bound to another organization");
|
|
2522
|
+
this.profile = profile;
|
|
2523
|
+
this.organization = organization;
|
|
2524
|
+
this.name = "ProfileOrganizationFixedError";
|
|
2525
|
+
}
|
|
2526
|
+
};
|
|
2527
|
+
var AccountVerificationError = class extends Error {
|
|
2528
|
+
constructor() {
|
|
2529
|
+
super("The signed-in account does not match the requested one");
|
|
2530
|
+
this.name = "AccountVerificationError";
|
|
2531
|
+
}
|
|
2532
|
+
};
|
|
2533
|
+
var chooseWorkspace = (organizations, requested) => {
|
|
2534
|
+
if (requested !== void 0) {
|
|
2535
|
+
const match = organizations.find((organization) => organization.id === requested);
|
|
2536
|
+
return match === void 0 ? { outcome: "not_a_member", organizations } : { outcome: "selected", organization: match };
|
|
2537
|
+
}
|
|
2538
|
+
if (organizations.length === 0)
|
|
2539
|
+
return { outcome: "no_workspace" };
|
|
2540
|
+
const only = organizations[0];
|
|
2541
|
+
if (organizations.length === 1 && only !== void 0)
|
|
2542
|
+
return { outcome: "selected", organization: only };
|
|
2543
|
+
return { outcome: "choice_required", organizations };
|
|
2544
|
+
};
|
|
2545
|
+
var verifiedUserId = (identity) => {
|
|
2546
|
+
const actor = parseCurrentIdentity(identity).actor_id;
|
|
2547
|
+
if (!actor.startsWith("user:") || actor.length === 5)
|
|
2548
|
+
throw new AccountVerificationError();
|
|
2549
|
+
return actor.slice(5);
|
|
2550
|
+
};
|
|
2551
|
+
var assertVerifiedLogin = (identity, userId, organizationId) => {
|
|
2552
|
+
const organizations = parseCurrentIdentity(identity).organization_ids;
|
|
2553
|
+
if (verifiedUserId(identity) !== userId || (organizationId === null ? organizations.length !== 0 : organizations.length !== 1 || organizations[0] !== organizationId))
|
|
2554
|
+
throw new AccountVerificationError();
|
|
2555
|
+
};
|
|
2556
|
+
var selectWorkspace = async (session, organization, signal, identity) => {
|
|
2557
|
+
if (session.profile.organizationId === organization.id)
|
|
2558
|
+
return session.profile;
|
|
2559
|
+
if (session.profile.organizationId !== null)
|
|
2560
|
+
throw new ProfileOrganizationFixedError(session.profile, organization);
|
|
2561
|
+
const stored = await session.store.read();
|
|
2562
|
+
if (stored === void 0)
|
|
2563
|
+
throw new InteractiveSessionRequiredError();
|
|
2564
|
+
const refreshed = await session.refresher.refresh(stored.refreshToken, signal, organization.workos_id);
|
|
2565
|
+
assertVerifiedLogin(await identity(refreshed.accessToken), session.profile.userId, organization.id);
|
|
2566
|
+
const bound = {
|
|
2567
|
+
...session.profile,
|
|
2568
|
+
organizationId: organization.id,
|
|
2569
|
+
organizationName: organization.name
|
|
2570
|
+
};
|
|
2571
|
+
await session.profiles.save(bound, { ...refreshed, workosOrganizationId: organization.workos_id, organizationId: organization.id }, session.profile);
|
|
2572
|
+
return bound;
|
|
2573
|
+
};
|
|
2574
|
+
var workspaceOf = (credential) => ({
|
|
2575
|
+
...credential.workosOrganizationId === void 0 ? {} : { workosOrganizationId: credential.workosOrganizationId },
|
|
2576
|
+
...credential.organizationId === void 0 ? {} : { organizationId: credential.organizationId }
|
|
2577
|
+
});
|
|
2578
|
+
var publicWorkspace = (organization) => ({
|
|
2579
|
+
id: organization.id,
|
|
2580
|
+
name: organization.name
|
|
2581
|
+
});
|
|
2582
|
+
|
|
2181
2583
|
// apps/product-cli/dist/cli.js
|
|
2182
2584
|
var NetworkTransportError = class extends Error {
|
|
2183
2585
|
constructor() {
|
|
@@ -2206,14 +2608,16 @@ var PublicResponseTooLargeError = class extends Error {
|
|
|
2206
2608
|
var CLI_VERSION = package_default.version;
|
|
2207
2609
|
var HELP_USAGE = Object.freeze({
|
|
2208
2610
|
init: "ohmyhost init [--directory PATH] [--root PATH] [--project SLUG] [--region us|eu] [--dry-run] --json (pass the project's hosting region so storage.jurisdiction matches it; us when omitted)",
|
|
2209
|
-
login: "ohmyhost login [--organization ULID] --json",
|
|
2210
|
-
logout: "ohmyhost logout [--revoke] --json",
|
|
2211
|
-
whoami: "ohmyhost whoami --json",
|
|
2611
|
+
login: "ohmyhost login [--organization ULID] [--user USER_ID] [--profile-name NAME] --json (adds one saved login; nothing is saved unless the browser signed in as that user and organization)",
|
|
2612
|
+
logout: "ohmyhost logout [--profile-name NAME] [--revoke] --json (removes only the selected saved login)",
|
|
2613
|
+
whoami: "ohmyhost whoami [--profile-name NAME] --json (the effective user, organization and saved login)",
|
|
2614
|
+
"profile list": "ohmyhost profile list --json (saved logins on this computer: name, user and organization, never a token; pass --profile-name NAME or set OHMYHOST_PROFILE to choose one)",
|
|
2212
2615
|
"github connect": "ohmyhost github connect --organization ULID --idempotency-key KEY --json (connect once, then link covered repositories without another browser consent)",
|
|
2213
2616
|
"github status": "ohmyhost github status --organization ULID --json",
|
|
2214
2617
|
"export create": "ohmyhost export create --project ULID --idempotency-key KEY --stdin --json (password on stdin only; one accepted SQL ZIP per project per 24 hours)",
|
|
2215
2618
|
"export get": "ohmyhost export get EXPORT_ULID --project ULID --json (poll the original job; signed ZIP download lasts 24 hours)",
|
|
2216
2619
|
"credits account": "ohmyhost credits account --organization ULID --json",
|
|
2620
|
+
"referral link": "ohmyhost referral link --organization ULID --json (the workspace's link to share; a new user who signs up through it starts with a free Paid month and 1,000 credits, and their first payment gives this workspace the same)",
|
|
2217
2621
|
"credits balance": "ohmyhost credits balance --organization ULID --json",
|
|
2218
2622
|
"billing recharge get": "ohmyhost billing recharge get --organization ULID --json",
|
|
2219
2623
|
"billing recharge set": "ohmyhost billing recharge set --organization ULID --enabled true|false --monthly-limit-minor CENTS --revision N --idempotency-key KEY [--consent off_session_v1] --json (explicit Owner consent required before enabling)",
|
|
@@ -2223,9 +2627,9 @@ var HELP_USAGE = Object.freeze({
|
|
|
2223
2627
|
"credits usage": "ohmyhost credits usage --organization ULID --month YYYY-MM [--cursor ULID] --json",
|
|
2224
2628
|
"budget get": "ohmyhost budget get --project ULID --json",
|
|
2225
2629
|
"budget set": "ohmyhost budget set --project ULID --credits NUMBER|none [--mode continue|stop] --idempotency-key KEY --json",
|
|
2226
|
-
"organization create": "ohmyhost organization create --name NAME --idempotency-key KEY [--source SOURCE] --json (SOURCE is optional attribution from a link's r value; the new workspace
|
|
2227
|
-
"organization list": "ohmyhost organization list --json (the workspaces
|
|
2228
|
-
"organization use": "ohmyhost organization use --organization ULID --json",
|
|
2630
|
+
"organization create": "ohmyhost organization create --name NAME --idempotency-key KEY [--source SOURCE] --json (SOURCE is optional attribution from a link's r value; a login without organization is bound to the new workspace, another login keeps its own)",
|
|
2631
|
+
"organization list": "ohmyhost organization list [--profile-name NAME] --json (the workspaces of the chosen login's user and the one that login is scoped to)",
|
|
2632
|
+
"organization use": "ohmyhost organization use --organization ULID [--profile-name NAME] --json (binds a login that has no organization yet; another organization needs its own login)",
|
|
2229
2633
|
"operation get": "ohmyhost operation get OPERATION_ULID --json",
|
|
2230
2634
|
"operation reconcile": "ohmyhost operation reconcile OPERATION_ULID --idempotency-key KEY --yes --json",
|
|
2231
2635
|
"token create": "ohmyhost token create --organization ULID --name NAME --idempotency-key KEY --out .env.local --json",
|
|
@@ -2243,6 +2647,8 @@ var HELP_USAGE = Object.freeze({
|
|
|
2243
2647
|
"project dev-share rotate": "ohmyhost project dev-share rotate --project ULID --idempotency-key KEY --yes --json",
|
|
2244
2648
|
"project dev-share revoke": "ohmyhost project dev-share revoke --project ULID --idempotency-key KEY --yes --json",
|
|
2245
2649
|
"project dev-access mode": "ohmyhost project dev-access mode --project ULID --mode protected|public --idempotency-key KEY --yes --json",
|
|
2650
|
+
"project flag status": "ohmyhost project flag status --project ULID --json",
|
|
2651
|
+
"project flag set": "ohmyhost project flag set --project ULID --enabled true|false --idempotency-key KEY --json (shows the small Powered by ohmyho.st flag on the production site; while it shows, a Free workspace may connect its own domain without the domain fee and each Paid period adds 250 credits)",
|
|
2246
2652
|
"project handle check": "ohmyhost project handle check --handle HANDLE --json (is this address free? answers with a reason and free alternatives; the address becomes HANDLE.check.omh.st)",
|
|
2247
2653
|
"project handle set": "ohmyhost project handle set --project ULID --handle HANDLE --if-match ETAG --idempotency-key KEY --json (moves the project to a free address; the old one stops working and anyone may claim it)",
|
|
2248
2654
|
"database compute set": "ohmyhost database compute set --project ULID --environment dev|prod --profile standard|performance --idempotency-key KEY --yes [--wait] --json\n standard: Free 0.25 CU/1 GB/60s idle, Paid 0.5 CU/2 GB/60s idle. performance: Paid 1 CU/4 GB/300s idle, 2.5x database compute credits per equal active minute; longer idle time also consumes credits.",
|
|
@@ -2275,7 +2681,7 @@ var HELP_USAGE = Object.freeze({
|
|
|
2275
2681
|
delete: "ohmyhost delete --project ULID --if-match ETAG --confirmation-token TOKEN --idempotency-key KEY --yes --json",
|
|
2276
2682
|
"secret list": "ohmyhost secret list --project ULID --environment ENVIRONMENT_ULID --json",
|
|
2277
2683
|
"function runs": "ohmyhost function runs --project ULID --environment ENVIRONMENT_ULID [--limit 1-100] --json",
|
|
2278
|
-
"secret set": `printf '%s' "$SECRET_VALUE" | ohmyhost secret set NAME --project ULID --environment ENVIRONMENT_ULID --idempotency-key KEY --stdin [--wait] --json`,
|
|
2684
|
+
"secret set": `printf '%s' "$SECRET_VALUE" | ohmyhost secret set NAME --project ULID --environment ENVIRONMENT_ULID --idempotency-key KEY [--profile-user USER_ID --profile-organization ULID | --token-user USER_ID --token-organization ULID] --stdin [--wait] --json (with --profile-user and --profile-organization the saved login that runs it must belong to that user and organization; with --token-user and --token-organization it runs only with an OHMYHOST_TOKEN of that user and organization, never with a saved login)`,
|
|
2279
2685
|
"secret delete": "ohmyhost secret delete NAME --project ULID --environment ENVIRONMENT_ULID --idempotency-key KEY [--wait] --json",
|
|
2280
2686
|
"mail setup": "ohmyhost mail setup --project ULID --environment ULID --domain DOMAIN --sending true --receiving false --idempotency-key KEY --json",
|
|
2281
2687
|
"mail status": "ohmyhost mail status --project ULID --environment ULID --json",
|
|
@@ -2291,6 +2697,14 @@ var HELP_USAGE = Object.freeze({
|
|
|
2291
2697
|
});
|
|
2292
2698
|
var HELP_COMMANDS = Object.freeze(Object.entries(HELP_USAGE).map(([command, usage]) => Object.freeze({ command, usage })));
|
|
2293
2699
|
var SIGN_IN_WINDOW_MS = 30 * 60 * 1e3;
|
|
2700
|
+
var ACCOUNT_SENSITIVE_PROBLEMS = /* @__PURE__ */ new Set([
|
|
2701
|
+
"resource_not_found",
|
|
2702
|
+
"forbidden",
|
|
2703
|
+
"organization_required",
|
|
2704
|
+
"github_connection_required",
|
|
2705
|
+
"github_connection_revoked",
|
|
2706
|
+
"repository_not_installed"
|
|
2707
|
+
]);
|
|
2294
2708
|
|
|
2295
2709
|
// packages/sdk-ts/dist/generated/core/bodySerializer.gen.js
|
|
2296
2710
|
var jsonBodySerializer = {
|
|
@@ -3176,6 +3590,23 @@ var getGithubOrganizationConnection = (parameters, options) => {
|
|
|
3176
3590
|
...params
|
|
3177
3591
|
});
|
|
3178
3592
|
};
|
|
3593
|
+
var getOrganizationReferral = (parameters, options) => {
|
|
3594
|
+
const params = buildClientParams([parameters], [
|
|
3595
|
+
{
|
|
3596
|
+
args: [
|
|
3597
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
3598
|
+
{ in: "path", key: "organization_id" }
|
|
3599
|
+
]
|
|
3600
|
+
}
|
|
3601
|
+
]);
|
|
3602
|
+
return (options?.client ?? client).get({
|
|
3603
|
+
responseStyle: "data",
|
|
3604
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
3605
|
+
url: "/v1/organizations/{organization_id}/referral",
|
|
3606
|
+
...options,
|
|
3607
|
+
...params
|
|
3608
|
+
});
|
|
3609
|
+
};
|
|
3179
3610
|
var getOrganizationAccount = (parameters, options) => {
|
|
3180
3611
|
const params = buildClientParams([parameters], [{ args: [{ in: "path", key: "organization_id" }] }]);
|
|
3181
3612
|
return (options?.client ?? client).get({
|
|
@@ -3780,6 +4211,47 @@ var setProjectDevAccessMode = (parameters, options) => {
|
|
|
3780
4211
|
}
|
|
3781
4212
|
});
|
|
3782
4213
|
};
|
|
4214
|
+
var getProjectPoweredByFlag = (parameters, options) => {
|
|
4215
|
+
const params = buildClientParams([parameters], [
|
|
4216
|
+
{
|
|
4217
|
+
args: [
|
|
4218
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
4219
|
+
{ in: "path", key: "project_id" }
|
|
4220
|
+
]
|
|
4221
|
+
}
|
|
4222
|
+
]);
|
|
4223
|
+
return (options?.client ?? client).get({
|
|
4224
|
+
responseStyle: "data",
|
|
4225
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
4226
|
+
url: "/v1/projects/{project_id}/powered-by-flag",
|
|
4227
|
+
...options,
|
|
4228
|
+
...params
|
|
4229
|
+
});
|
|
4230
|
+
};
|
|
4231
|
+
var setProjectPoweredByFlag = (parameters, options) => {
|
|
4232
|
+
const params = buildClientParams([parameters], [
|
|
4233
|
+
{
|
|
4234
|
+
args: [
|
|
4235
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
4236
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
4237
|
+
{ in: "path", key: "project_id" },
|
|
4238
|
+
{ key: "setPoweredByFlagRequest", map: "body" }
|
|
4239
|
+
]
|
|
4240
|
+
}
|
|
4241
|
+
]);
|
|
4242
|
+
return (options?.client ?? client).put({
|
|
4243
|
+
responseStyle: "data",
|
|
4244
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
4245
|
+
url: "/v1/projects/{project_id}/powered-by-flag",
|
|
4246
|
+
...options,
|
|
4247
|
+
...params,
|
|
4248
|
+
headers: {
|
|
4249
|
+
"Content-Type": "application/json",
|
|
4250
|
+
...options?.headers,
|
|
4251
|
+
...params.headers
|
|
4252
|
+
}
|
|
4253
|
+
});
|
|
4254
|
+
};
|
|
3783
4255
|
var createProjectDevAccessTicket = (parameters, options) => {
|
|
3784
4256
|
const params = buildClientParams([parameters], [
|
|
3785
4257
|
{
|
|
@@ -3855,31 +4327,7 @@ var getProjectSource = (parameters, options) => {
|
|
|
3855
4327
|
...params
|
|
3856
4328
|
});
|
|
3857
4329
|
};
|
|
3858
|
-
var
|
|
3859
|
-
const params = buildClientParams([parameters], [
|
|
3860
|
-
{
|
|
3861
|
-
args: [
|
|
3862
|
-
{ in: "headers", key: "X-Request-Id" },
|
|
3863
|
-
{ in: "headers", key: "Idempotency-Key" },
|
|
3864
|
-
{ in: "path", key: "project_id" },
|
|
3865
|
-
{ key: "createCloudflareDnsAuthorizationRequest", map: "body" }
|
|
3866
|
-
]
|
|
3867
|
-
}
|
|
3868
|
-
]);
|
|
3869
|
-
return (options?.client ?? client).post({
|
|
3870
|
-
responseStyle: "data",
|
|
3871
|
-
security: [{ scheme: "bearer", type: "http" }],
|
|
3872
|
-
url: "/v1/projects/{project_id}/cloudflare-dns/authorization",
|
|
3873
|
-
...options,
|
|
3874
|
-
...params,
|
|
3875
|
-
headers: {
|
|
3876
|
-
"Content-Type": "application/json",
|
|
3877
|
-
...options?.headers,
|
|
3878
|
-
...params.headers
|
|
3879
|
-
}
|
|
3880
|
-
});
|
|
3881
|
-
};
|
|
3882
|
-
var getCloudflareDnsAuthorizationStatus = (parameters, options) => {
|
|
4330
|
+
var getProjectSourceAutoDeploy = (parameters, options) => {
|
|
3883
4331
|
const params = buildClientParams([parameters], [
|
|
3884
4332
|
{
|
|
3885
4333
|
args: [
|
|
@@ -3891,27 +4339,26 @@ var getCloudflareDnsAuthorizationStatus = (parameters, options) => {
|
|
|
3891
4339
|
return (options?.client ?? client).get({
|
|
3892
4340
|
responseStyle: "data",
|
|
3893
4341
|
security: [{ scheme: "bearer", type: "http" }],
|
|
3894
|
-
url: "/v1/projects/{project_id}/
|
|
4342
|
+
url: "/v1/projects/{project_id}/source/auto-deploy",
|
|
3895
4343
|
...options,
|
|
3896
4344
|
...params
|
|
3897
4345
|
});
|
|
3898
4346
|
};
|
|
3899
|
-
var
|
|
4347
|
+
var configureProjectSourceAutoDeploy = (parameters, options) => {
|
|
3900
4348
|
const params = buildClientParams([parameters], [
|
|
3901
4349
|
{
|
|
3902
4350
|
args: [
|
|
3903
4351
|
{ in: "headers", key: "X-Request-Id" },
|
|
3904
4352
|
{ in: "headers", key: "Idempotency-Key" },
|
|
3905
|
-
{ in: "headers", key: "If-Match" },
|
|
3906
4353
|
{ in: "path", key: "project_id" },
|
|
3907
|
-
{
|
|
4354
|
+
{ key: "configureSourceAutoDeployRequest", map: "body" }
|
|
3908
4355
|
]
|
|
3909
4356
|
}
|
|
3910
4357
|
]);
|
|
3911
4358
|
return (options?.client ?? client).put({
|
|
3912
4359
|
responseStyle: "data",
|
|
3913
4360
|
security: [{ scheme: "bearer", type: "http" }],
|
|
3914
|
-
url: "/v1/projects/{project_id}/
|
|
4361
|
+
url: "/v1/projects/{project_id}/source/auto-deploy",
|
|
3915
4362
|
...options,
|
|
3916
4363
|
...params,
|
|
3917
4364
|
headers: {
|
|
@@ -3921,13 +4368,97 @@ var changeProjectHandle = (parameters, options) => {
|
|
|
3921
4368
|
}
|
|
3922
4369
|
});
|
|
3923
4370
|
};
|
|
3924
|
-
var
|
|
4371
|
+
var createCloudflareDnsAuthorization = (parameters, options) => {
|
|
3925
4372
|
const params = buildClientParams([parameters], [
|
|
3926
4373
|
{
|
|
3927
4374
|
args: [
|
|
3928
4375
|
{ in: "headers", key: "X-Request-Id" },
|
|
4376
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
3929
4377
|
{ in: "path", key: "project_id" },
|
|
3930
|
-
{ key: "
|
|
4378
|
+
{ key: "createCloudflareDnsAuthorizationRequest", map: "body" }
|
|
4379
|
+
]
|
|
4380
|
+
}
|
|
4381
|
+
]);
|
|
4382
|
+
return (options?.client ?? client).post({
|
|
4383
|
+
responseStyle: "data",
|
|
4384
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
4385
|
+
url: "/v1/projects/{project_id}/cloudflare-dns/authorization",
|
|
4386
|
+
...options,
|
|
4387
|
+
...params,
|
|
4388
|
+
headers: {
|
|
4389
|
+
"Content-Type": "application/json",
|
|
4390
|
+
...options?.headers,
|
|
4391
|
+
...params.headers
|
|
4392
|
+
}
|
|
4393
|
+
});
|
|
4394
|
+
};
|
|
4395
|
+
var getCloudflareDnsAuthorizationStatus = (parameters, options) => {
|
|
4396
|
+
const params = buildClientParams([parameters], [
|
|
4397
|
+
{
|
|
4398
|
+
args: [
|
|
4399
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
4400
|
+
{ in: "path", key: "project_id" }
|
|
4401
|
+
]
|
|
4402
|
+
}
|
|
4403
|
+
]);
|
|
4404
|
+
return (options?.client ?? client).get({
|
|
4405
|
+
responseStyle: "data",
|
|
4406
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
4407
|
+
url: "/v1/projects/{project_id}/cloudflare-dns",
|
|
4408
|
+
...options,
|
|
4409
|
+
...params
|
|
4410
|
+
});
|
|
4411
|
+
};
|
|
4412
|
+
var changeProjectHandle = (parameters, options) => {
|
|
4413
|
+
const params = buildClientParams([parameters], [
|
|
4414
|
+
{
|
|
4415
|
+
args: [
|
|
4416
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
4417
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
4418
|
+
{ in: "headers", key: "If-Match" },
|
|
4419
|
+
{ in: "path", key: "project_id" },
|
|
4420
|
+
{ in: "body", key: "handle" }
|
|
4421
|
+
]
|
|
4422
|
+
}
|
|
4423
|
+
]);
|
|
4424
|
+
return (options?.client ?? client).put({
|
|
4425
|
+
responseStyle: "data",
|
|
4426
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
4427
|
+
url: "/v1/projects/{project_id}/handle",
|
|
4428
|
+
...options,
|
|
4429
|
+
...params,
|
|
4430
|
+
headers: {
|
|
4431
|
+
"Content-Type": "application/json",
|
|
4432
|
+
...options?.headers,
|
|
4433
|
+
...params.headers
|
|
4434
|
+
}
|
|
4435
|
+
});
|
|
4436
|
+
};
|
|
4437
|
+
var configureProjectDomains = (parameters, options) => {
|
|
4438
|
+
const params = buildClientParams([parameters], [
|
|
4439
|
+
{
|
|
4440
|
+
args: [
|
|
4441
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
4442
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
4443
|
+
{ in: "path", key: "project_id" }
|
|
4444
|
+
]
|
|
4445
|
+
}
|
|
4446
|
+
]);
|
|
4447
|
+
return (options?.client ?? client).put({
|
|
4448
|
+
responseStyle: "data",
|
|
4449
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
4450
|
+
url: "/v1/projects/{project_id}/domains",
|
|
4451
|
+
...options,
|
|
4452
|
+
...params
|
|
4453
|
+
});
|
|
4454
|
+
};
|
|
4455
|
+
var planPaidProjectDomain = (parameters, options) => {
|
|
4456
|
+
const params = buildClientParams([parameters], [
|
|
4457
|
+
{
|
|
4458
|
+
args: [
|
|
4459
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
4460
|
+
{ in: "path", key: "project_id" },
|
|
4461
|
+
{ key: "paidDomainRequest", map: "body" }
|
|
3931
4462
|
]
|
|
3932
4463
|
}
|
|
3933
4464
|
]);
|
|
@@ -4113,6 +4644,24 @@ var getDeploymentLogs = (parameters, options) => {
|
|
|
4113
4644
|
...params
|
|
4114
4645
|
});
|
|
4115
4646
|
};
|
|
4647
|
+
var streamDeploymentLogs = (parameters, options) => {
|
|
4648
|
+
const params = buildClientParams([parameters], [
|
|
4649
|
+
{
|
|
4650
|
+
args: [
|
|
4651
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
4652
|
+
{ in: "path", key: "project_id" },
|
|
4653
|
+
{ in: "path", key: "deployment_id" }
|
|
4654
|
+
]
|
|
4655
|
+
}
|
|
4656
|
+
]);
|
|
4657
|
+
return (options?.client ?? client).sse.get({
|
|
4658
|
+
responseStyle: "data",
|
|
4659
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
4660
|
+
url: "/v1/projects/{project_id}/deployments/{deployment_id}/logs/events",
|
|
4661
|
+
...options,
|
|
4662
|
+
...params
|
|
4663
|
+
});
|
|
4664
|
+
};
|
|
4116
4665
|
var getDatabaseCompute = (parameters, options) => {
|
|
4117
4666
|
const params = buildClientParams([parameters], [
|
|
4118
4667
|
{
|
|
@@ -4398,6 +4947,32 @@ var deleteEnvironmentSecret = (parameters, options) => {
|
|
|
4398
4947
|
...params
|
|
4399
4948
|
});
|
|
4400
4949
|
};
|
|
4950
|
+
var putEnvironmentSecret = (parameters, options) => {
|
|
4951
|
+
const params = buildClientParams([parameters], [
|
|
4952
|
+
{
|
|
4953
|
+
args: [
|
|
4954
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
4955
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
4956
|
+
{ in: "path", key: "project_id" },
|
|
4957
|
+
{ in: "path", key: "environment_id" },
|
|
4958
|
+
{ in: "path", key: "secret_name" },
|
|
4959
|
+
{ key: "putEnvironmentSecretRequest", map: "body" }
|
|
4960
|
+
]
|
|
4961
|
+
}
|
|
4962
|
+
]);
|
|
4963
|
+
return (options?.client ?? client).put({
|
|
4964
|
+
responseStyle: "data",
|
|
4965
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
4966
|
+
url: "/v1/projects/{project_id}/environments/{environment_id}/secrets/{secret_name}",
|
|
4967
|
+
...options,
|
|
4968
|
+
...params,
|
|
4969
|
+
headers: {
|
|
4970
|
+
"Content-Type": "application/json",
|
|
4971
|
+
...options?.headers,
|
|
4972
|
+
...params.headers
|
|
4973
|
+
}
|
|
4974
|
+
});
|
|
4975
|
+
};
|
|
4401
4976
|
var getOperation = (parameters, options) => {
|
|
4402
4977
|
const params = buildClientParams([parameters], [
|
|
4403
4978
|
{
|
|
@@ -4765,120 +5340,526 @@ function assertManagedMailResponse(value, input) {
|
|
|
4765
5340
|
if (typeof a["id"] !== "string" || !/^[A-Za-z0-9_-]{1,128}$/u.test(a["id"]) || a["filename"] !== null && typeof a["filename"] !== "string" || typeof a["content_type"] !== "string" || a["download_path"] !== `/v1/projects/${input.projectId}/environments/${input.environmentId}/mail/messages/${input.messageId}/attachments/${a["id"]}`)
|
|
4766
5341
|
invalid3();
|
|
4767
5342
|
}
|
|
4768
|
-
}
|
|
4769
|
-
function object2(v) {
|
|
4770
|
-
if (typeof v !== "object" || v === null || Array.isArray(v))
|
|
4771
|
-
invalid3();
|
|
4772
|
-
return v;
|
|
4773
|
-
}
|
|
4774
|
-
function exact3(v, required, optional = []) {
|
|
4775
|
-
if (required.some((k) => !(k in v)) || Object.keys(v).some((k) => !required.includes(k) && !optional.includes(k)))
|
|
4776
|
-
invalid3();
|
|
4777
|
-
}
|
|
4778
|
-
function id2(v) {
|
|
4779
|
-
if (typeof v !== "string" || !ULID.test(v))
|
|
4780
|
-
invalid3();
|
|
4781
|
-
}
|
|
4782
|
-
function domain(v) {
|
|
4783
|
-
if (typeof v !== "string" || !/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/u.test(v))
|
|
4784
|
-
invalid3();
|
|
4785
|
-
}
|
|
4786
|
-
function time(v) {
|
|
4787
|
-
if (typeof v !== "string" || !Number.isFinite(Date.parse(v)) || new Date(v).toISOString() !== v)
|
|
4788
|
-
invalid3();
|
|
4789
|
-
}
|
|
4790
|
-
function https(v) {
|
|
4791
|
-
if (typeof v !== "string" || !v.startsWith("https://"))
|
|
4792
|
-
invalid3();
|
|
4793
|
-
}
|
|
4794
|
-
function records(v) {
|
|
4795
|
-
if (!Array.isArray(v))
|
|
4796
|
-
invalid3();
|
|
4797
|
-
for (const value of v) {
|
|
4798
|
-
const r = object2(value);
|
|
4799
|
-
exact3(r, ["type", "name", "value", "purpose", "status"], ["priority"]);
|
|
4800
|
-
if (!["TXT", "CNAME", "MX"].includes(String(r["type"])) || ["name", "value", "purpose", "status"].some((k) => typeof r[k] !== "string") || r["type"] === "MX" && (!Number.isInteger(r["priority"]) || Number(r["priority"]) < 0 || Number(r["priority"]) > 65535))
|
|
4801
|
-
invalid3();
|
|
5343
|
+
}
|
|
5344
|
+
function object2(v) {
|
|
5345
|
+
if (typeof v !== "object" || v === null || Array.isArray(v))
|
|
5346
|
+
invalid3();
|
|
5347
|
+
return v;
|
|
5348
|
+
}
|
|
5349
|
+
function exact3(v, required, optional = []) {
|
|
5350
|
+
if (required.some((k) => !(k in v)) || Object.keys(v).some((k) => !required.includes(k) && !optional.includes(k)))
|
|
5351
|
+
invalid3();
|
|
5352
|
+
}
|
|
5353
|
+
function id2(v) {
|
|
5354
|
+
if (typeof v !== "string" || !ULID.test(v))
|
|
5355
|
+
invalid3();
|
|
5356
|
+
}
|
|
5357
|
+
function domain(v) {
|
|
5358
|
+
if (typeof v !== "string" || !/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/u.test(v))
|
|
5359
|
+
invalid3();
|
|
5360
|
+
}
|
|
5361
|
+
function time(v) {
|
|
5362
|
+
if (typeof v !== "string" || !Number.isFinite(Date.parse(v)) || new Date(v).toISOString() !== v)
|
|
5363
|
+
invalid3();
|
|
5364
|
+
}
|
|
5365
|
+
function https(v) {
|
|
5366
|
+
if (typeof v !== "string" || !v.startsWith("https://"))
|
|
5367
|
+
invalid3();
|
|
5368
|
+
}
|
|
5369
|
+
function records(v) {
|
|
5370
|
+
if (!Array.isArray(v))
|
|
5371
|
+
invalid3();
|
|
5372
|
+
for (const value of v) {
|
|
5373
|
+
const r = object2(value);
|
|
5374
|
+
exact3(r, ["type", "name", "value", "purpose", "status"], ["priority"]);
|
|
5375
|
+
if (!["TXT", "CNAME", "MX"].includes(String(r["type"])) || ["name", "value", "purpose", "status"].some((k) => typeof r[k] !== "string") || r["type"] === "MX" && (!Number.isInteger(r["priority"]) || Number(r["priority"]) < 0 || Number(r["priority"]) > 65535))
|
|
5376
|
+
invalid3();
|
|
5377
|
+
}
|
|
5378
|
+
}
|
|
5379
|
+
function invalid3() {
|
|
5380
|
+
throw new TypeError("Mail response contract invalid");
|
|
5381
|
+
}
|
|
5382
|
+
|
|
5383
|
+
// packages/sdk-ts/dist/managed-mail.js
|
|
5384
|
+
function requestManagedMail(client2, input) {
|
|
5385
|
+
const scope = { project_id: input.projectId, environment_id: input.environmentId };
|
|
5386
|
+
switch (input.action) {
|
|
5387
|
+
case "configure":
|
|
5388
|
+
return configureManagedMailDomain({
|
|
5389
|
+
...scope,
|
|
5390
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5391
|
+
managedMailDomainRequest: {
|
|
5392
|
+
domain: input.domain,
|
|
5393
|
+
sending: input.sending,
|
|
5394
|
+
receiving: input.receiving
|
|
5395
|
+
}
|
|
5396
|
+
}, { client: client2 });
|
|
5397
|
+
case "status":
|
|
5398
|
+
return getManagedMailDomain(scope, { client: client2 });
|
|
5399
|
+
case "webhook_set":
|
|
5400
|
+
return prepareManagedMailWebhook({
|
|
5401
|
+
...scope,
|
|
5402
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5403
|
+
managedMailWebhookRequest: { url: input.url }
|
|
5404
|
+
}, { client: client2 });
|
|
5405
|
+
case "webhook_verify":
|
|
5406
|
+
return verifyManagedMailWebhook({ ...scope, "Idempotency-Key": input.idempotencyKey }, { client: client2 });
|
|
5407
|
+
case "webhook_disable":
|
|
5408
|
+
return disableManagedMailReceiving({ ...scope, "Idempotency-Key": input.idempotencyKey }, { client: client2 });
|
|
5409
|
+
case "domain_delete":
|
|
5410
|
+
return deleteManagedMailDomain({ ...scope, "Idempotency-Key": input.idempotencyKey }, { client: client2 });
|
|
5411
|
+
case "messages_list":
|
|
5412
|
+
return listManagedMailMessages({ ...scope, ...input.after ? { after: input.after } : {} }, { client: client2 });
|
|
5413
|
+
case "message_get":
|
|
5414
|
+
return getManagedMailMessage({ ...scope, message_id: input.messageId }, { client: client2 });
|
|
5415
|
+
case "message_retry":
|
|
5416
|
+
return retryManagedMailMessage({ ...scope, message_id: input.messageId, "Idempotency-Key": input.idempotencyKey }, { client: client2 });
|
|
5417
|
+
}
|
|
5418
|
+
}
|
|
5419
|
+
async function executeManagedMail(client2, input) {
|
|
5420
|
+
const result = await requestManagedMail(client2, input);
|
|
5421
|
+
assertManagedMailResponse(result, input);
|
|
5422
|
+
return result;
|
|
5423
|
+
}
|
|
5424
|
+
|
|
5425
|
+
// packages/workos-auth-contracts/dist/device-flow.js
|
|
5426
|
+
var WORKOS_AUTHKIT_DEVICE_TOKEN_ENDPOINT = "https://api.workos.com/user_management/authenticate";
|
|
5427
|
+
var allowedDeviceTokenFields = /* @__PURE__ */ new Set([
|
|
5428
|
+
"access_token",
|
|
5429
|
+
"refresh_token",
|
|
5430
|
+
"token_type",
|
|
5431
|
+
"expires_in",
|
|
5432
|
+
"organization_id",
|
|
5433
|
+
"authentication_method",
|
|
5434
|
+
"user"
|
|
5435
|
+
]);
|
|
5436
|
+
var parseDeviceTokens = (value) => {
|
|
5437
|
+
const input = expectRecord(value);
|
|
5438
|
+
for (const field of Object.keys(input)) {
|
|
5439
|
+
if (!allowedDeviceTokenFields.has(field)) {
|
|
5440
|
+
throw new WorkosContractError("unexpected_device_token_field", "Device Flow response contained an unexpected field");
|
|
5441
|
+
}
|
|
5442
|
+
}
|
|
5443
|
+
const expiresIn = expectPositiveInteger(input["expires_in"], "expires_in", { optional: true });
|
|
5444
|
+
const organizationId = expectString(input["organization_id"], "organization_id", {
|
|
5445
|
+
optional: true
|
|
5446
|
+
});
|
|
5447
|
+
return {
|
|
5448
|
+
accessToken: expectString(input["access_token"], "access_token"),
|
|
5449
|
+
refreshToken: expectString(input["refresh_token"], "refresh_token"),
|
|
5450
|
+
tokenType: expectString(input["token_type"], "token_type", { optional: true }) ?? "Bearer",
|
|
5451
|
+
...expiresIn === void 0 ? {} : { expiresInSeconds: expiresIn },
|
|
5452
|
+
...organizationId === void 0 ? {} : { organizationId }
|
|
5453
|
+
};
|
|
5454
|
+
};
|
|
5455
|
+
|
|
5456
|
+
// apps/product-cli/dist/product-api.js
|
|
5457
|
+
var GeneratedSdkProductApi = class {
|
|
5458
|
+
#client;
|
|
5459
|
+
constructor(baseUrl, accessToken, fetch2) {
|
|
5460
|
+
this.#client = createClient({ auth: accessToken, baseUrl, fetch: fetch2, throwOnError: true });
|
|
5461
|
+
}
|
|
5462
|
+
async changeDatabaseCompute(input) {
|
|
5463
|
+
return changeDatabaseCompute({
|
|
5464
|
+
project_id: input.projectId,
|
|
5465
|
+
environment: input.environment,
|
|
5466
|
+
profile: input.profile,
|
|
5467
|
+
confirm: true,
|
|
5468
|
+
"Idempotency-Key": input.idempotencyKey
|
|
5469
|
+
}, { client: this.#client });
|
|
5470
|
+
}
|
|
5471
|
+
async getDatabaseCompute(input) {
|
|
5472
|
+
const value = await getDatabaseCompute({ project_id: input.projectId, environment: input.environment }, { client: this.#client });
|
|
5473
|
+
assertDatabaseCompute(value);
|
|
5474
|
+
if (value.project_id !== input.projectId || value.environment !== input.environment)
|
|
5475
|
+
throw new TypeError("Compute response scope mismatch");
|
|
5476
|
+
return value;
|
|
5477
|
+
}
|
|
5478
|
+
async getProjectContext(projectId) {
|
|
5479
|
+
const result = await getProjectContext({ project_id: projectId }, { client: this.#client });
|
|
5480
|
+
assertProjectContext(result);
|
|
5481
|
+
if (result.project_id !== projectId)
|
|
5482
|
+
throw new TypeError("Project context scope mismatch");
|
|
5483
|
+
return result;
|
|
5484
|
+
}
|
|
5485
|
+
async setProjectNotes(input) {
|
|
5486
|
+
const result = await setProjectNotes({
|
|
5487
|
+
project_id: input.projectId,
|
|
5488
|
+
markdown: input.markdown,
|
|
5489
|
+
expected_version: input.expectedVersion,
|
|
5490
|
+
"Idempotency-Key": input.idempotencyKey
|
|
5491
|
+
}, { client: this.#client });
|
|
5492
|
+
assertProjectNotesReceipt(result);
|
|
5493
|
+
return result;
|
|
5494
|
+
}
|
|
5495
|
+
createProjectExport(input) {
|
|
5496
|
+
return createProjectExport({
|
|
5497
|
+
project_id: input.projectId,
|
|
5498
|
+
password: input.password,
|
|
5499
|
+
"Idempotency-Key": input.idempotencyKey
|
|
5500
|
+
}, { client: this.#client });
|
|
5501
|
+
}
|
|
5502
|
+
async getProjectExport(input) {
|
|
5503
|
+
const result = await getProjectExport({ project_id: input.projectId, export_id: input.exportId }, { client: this.#client });
|
|
5504
|
+
assertProjectExport(result);
|
|
5505
|
+
return result;
|
|
5506
|
+
}
|
|
5507
|
+
async getCurrentIdentity() {
|
|
5508
|
+
return getCurrentIdentity({}, { client: this.#client });
|
|
5509
|
+
}
|
|
5510
|
+
async getAccountProfile() {
|
|
5511
|
+
return parseAccountProfile(await getAccountProfile({ client: this.#client }));
|
|
5512
|
+
}
|
|
5513
|
+
getOrganizationReferral(organizationId) {
|
|
5514
|
+
return getOrganizationReferral({ organization_id: organizationId }, { client: this.#client });
|
|
5515
|
+
}
|
|
5516
|
+
getOrganizationAccount(organizationId) {
|
|
5517
|
+
return getOrganizationAccount({ organization_id: organizationId }, { client: this.#client });
|
|
5518
|
+
}
|
|
5519
|
+
getOrganizationCredits(organizationId) {
|
|
5520
|
+
return getOrganizationCredits({ organization_id: organizationId }, { client: this.#client });
|
|
5521
|
+
}
|
|
5522
|
+
async createUserApiKey(input) {
|
|
5523
|
+
return parseUserApiKeyCreation(await createUserApiKey({
|
|
5524
|
+
organization_id: input.organizationId,
|
|
5525
|
+
name: input.name,
|
|
5526
|
+
"Idempotency-Key": input.idempotencyKey
|
|
5527
|
+
}, { client: this.#client }));
|
|
5528
|
+
}
|
|
5529
|
+
async listUserApiKeys(input) {
|
|
5530
|
+
return parseUserApiKeyPage(await listUserApiKeys({ organization_id: input.organizationId, ...input.after ? { after: input.after } : {} }, { client: this.#client }));
|
|
5531
|
+
}
|
|
5532
|
+
async revokeUserApiKey(input) {
|
|
5533
|
+
await revokeUserApiKey({ organization_id: input.organizationId, key_id: input.keyId }, { client: this.#client });
|
|
5534
|
+
}
|
|
5535
|
+
createBillingCheckout(input) {
|
|
5536
|
+
return createBillingCheckout({
|
|
5537
|
+
organization_id: input.organizationId,
|
|
5538
|
+
offer: input.offer,
|
|
5539
|
+
packs: input.packs,
|
|
5540
|
+
"Idempotency-Key": input.idempotencyKey
|
|
5541
|
+
}, { client: this.#client });
|
|
5542
|
+
}
|
|
5543
|
+
getBillingCheckout(input) {
|
|
5544
|
+
return getBillingCheckout({ organization_id: input.organizationId, checkout_id: input.checkoutId }, { client: this.#client });
|
|
5545
|
+
}
|
|
5546
|
+
getBillingRecharge(organizationId) {
|
|
5547
|
+
return getBillingRecharge({ organization_id: organizationId }, { client: this.#client });
|
|
5548
|
+
}
|
|
5549
|
+
configureBillingRecharge(input) {
|
|
5550
|
+
return configureBillingRecharge({
|
|
5551
|
+
organization_id: input.organizationId,
|
|
5552
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5553
|
+
enabled: input.enabled,
|
|
5554
|
+
monthly_limit_minor: input.monthlyLimitMinor,
|
|
5555
|
+
consent: input.consent,
|
|
5556
|
+
revision: input.revision
|
|
5557
|
+
}, { client: this.#client });
|
|
5558
|
+
}
|
|
5559
|
+
createBillingPortal(organizationId) {
|
|
5560
|
+
return createBillingPortal({ organization_id: organizationId, body: {} }, { client: this.#client });
|
|
5561
|
+
}
|
|
5562
|
+
getOrganizationCreditUsage(input) {
|
|
5563
|
+
return getOrganizationCreditUsage({
|
|
5564
|
+
organization_id: input.organizationId,
|
|
5565
|
+
month: input.month,
|
|
5566
|
+
...input.cursor ? { cursor: input.cursor } : {}
|
|
5567
|
+
}, { client: this.#client });
|
|
5568
|
+
}
|
|
5569
|
+
getProjectCreditBudget(projectId) {
|
|
5570
|
+
return getProjectCreditBudget({ project_id: projectId }, { client: this.#client });
|
|
5571
|
+
}
|
|
5572
|
+
setProjectCreditBudget(input) {
|
|
5573
|
+
return setProjectCreditBudget({
|
|
5574
|
+
project_id: input.projectId,
|
|
5575
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5576
|
+
setProjectCreditBudgetRequest: { amount_micros: input.amountMicros, mode: input.mode }
|
|
5577
|
+
}, { client: this.#client });
|
|
5578
|
+
}
|
|
5579
|
+
createOrganization(input) {
|
|
5580
|
+
return createOrganization({
|
|
5581
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5582
|
+
createOrganizationRequest: {
|
|
5583
|
+
name: input.name,
|
|
5584
|
+
...input.signupSource === void 0 ? {} : { signup_source: input.signupSource }
|
|
5585
|
+
}
|
|
5586
|
+
}, { client: this.#client });
|
|
5587
|
+
}
|
|
5588
|
+
async listProjects(input) {
|
|
5589
|
+
return listProjects(input, { client: this.#client });
|
|
5590
|
+
}
|
|
5591
|
+
async changeProjectHandle(input) {
|
|
5592
|
+
return changeProjectHandle({
|
|
5593
|
+
project_id: input.projectId,
|
|
5594
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5595
|
+
"If-Match": input.ifMatch,
|
|
5596
|
+
handle: input.handle
|
|
5597
|
+
}, { client: this.#client });
|
|
5598
|
+
}
|
|
5599
|
+
async checkProjectHandle(input) {
|
|
5600
|
+
return getProjectHandleAvailability({ handle: input.handle }, { client: this.#client });
|
|
5601
|
+
}
|
|
5602
|
+
async getProjectStatus(projectId) {
|
|
5603
|
+
return getProjectStatus({ project_id: projectId }, { client: this.#client });
|
|
5604
|
+
}
|
|
5605
|
+
async writeProjectDatabase(input) {
|
|
5606
|
+
return writeProjectDatabase({
|
|
5607
|
+
project_id: input.projectId,
|
|
5608
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5609
|
+
projectDatabaseWriteRequest: {
|
|
5610
|
+
environment: input.environment,
|
|
5611
|
+
statement: input.statement,
|
|
5612
|
+
parameters: [...input.parameters]
|
|
5613
|
+
}
|
|
5614
|
+
}, { client: this.#client });
|
|
5615
|
+
}
|
|
5616
|
+
async queryProjectDatabase(input) {
|
|
5617
|
+
return queryProjectDatabase({
|
|
5618
|
+
project_id: input.projectId,
|
|
5619
|
+
projectDatabaseQueryRequest: {
|
|
5620
|
+
environment: input.environment,
|
|
5621
|
+
statement: input.statement,
|
|
5622
|
+
parameters: [...input.parameters]
|
|
5623
|
+
}
|
|
5624
|
+
}, { client: this.#client });
|
|
5625
|
+
}
|
|
5626
|
+
/** The connection URI exists only in this response; nothing in the CLI persists it. */
|
|
5627
|
+
async createProjectDatabaseAccess(input) {
|
|
5628
|
+
const value = await createProjectDatabaseAccess({
|
|
5629
|
+
project_id: input.projectId,
|
|
5630
|
+
projectDatabaseAccessRequest: {
|
|
5631
|
+
environment: input.environment,
|
|
5632
|
+
mode: input.mode,
|
|
5633
|
+
ttl_seconds: input.ttlSeconds,
|
|
5634
|
+
label: input.label
|
|
5635
|
+
}
|
|
5636
|
+
}, { client: this.#client });
|
|
5637
|
+
assertProjectDatabaseAccessCredential(value);
|
|
5638
|
+
return value;
|
|
5639
|
+
}
|
|
5640
|
+
async listProjectDatabaseAccess(input) {
|
|
5641
|
+
const value = await listProjectDatabaseAccess({
|
|
5642
|
+
project_id: input.projectId,
|
|
5643
|
+
...input.environment === void 0 ? {} : { environment: input.environment }
|
|
5644
|
+
}, { client: this.#client });
|
|
5645
|
+
assertProjectDatabaseAccessPage(value);
|
|
5646
|
+
return value;
|
|
5647
|
+
}
|
|
5648
|
+
async revokeProjectDatabaseAccess(input) {
|
|
5649
|
+
const value = await revokeProjectDatabaseAccess({ project_id: input.projectId, access_id: input.accessId }, { client: this.#client });
|
|
5650
|
+
assertProjectDatabaseAccess(value);
|
|
5651
|
+
return value;
|
|
5652
|
+
}
|
|
5653
|
+
async planPaidDomain(input) {
|
|
5654
|
+
return planPaidProjectDomain({ project_id: input.projectId, paidDomainRequest: { hostname: input.hostname } }, { client: this.#client });
|
|
5655
|
+
}
|
|
5656
|
+
async applyPaidDomain(input) {
|
|
5657
|
+
return applyPaidProjectDomain({
|
|
5658
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5659
|
+
project_id: input.projectId,
|
|
5660
|
+
paidDomainRequest: { hostname: input.hostname }
|
|
5661
|
+
}, { client: this.#client });
|
|
5662
|
+
}
|
|
5663
|
+
async getPaidDomain(projectId) {
|
|
5664
|
+
return getPaidProjectDomain({ project_id: projectId }, { client: this.#client });
|
|
5665
|
+
}
|
|
5666
|
+
async deletePaidDomain(input) {
|
|
5667
|
+
return deletePaidProjectDomain({
|
|
5668
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5669
|
+
project_id: input.projectId,
|
|
5670
|
+
paidDomainRequest: { hostname: input.hostname }
|
|
5671
|
+
}, { client: this.#client });
|
|
5672
|
+
}
|
|
5673
|
+
async ensureDevShareLink(projectId) {
|
|
5674
|
+
return ensureProjectDevShareLink({ project_id: projectId }, { client: this.#client });
|
|
5675
|
+
}
|
|
5676
|
+
async rotateDevShareLink(projectId, idempotencyKey2) {
|
|
5677
|
+
return rotateProjectDevShareLink({ project_id: projectId, "Idempotency-Key": idempotencyKey2 }, { client: this.#client });
|
|
5678
|
+
}
|
|
5679
|
+
async revokeDevShareLink(projectId, idempotencyKey2) {
|
|
5680
|
+
return revokeProjectDevShareLink({ project_id: projectId, "Idempotency-Key": idempotencyKey2 }, { client: this.#client });
|
|
5681
|
+
}
|
|
5682
|
+
async setDevAccessMode(projectId, mode, idempotencyKey2) {
|
|
5683
|
+
return setProjectDevAccessMode({
|
|
5684
|
+
project_id: projectId,
|
|
5685
|
+
"Idempotency-Key": idempotencyKey2,
|
|
5686
|
+
setDevAccessModeRequest: { mode }
|
|
5687
|
+
}, { client: this.#client });
|
|
5688
|
+
}
|
|
5689
|
+
async getPoweredByFlag(projectId) {
|
|
5690
|
+
return getProjectPoweredByFlag({ project_id: projectId }, { client: this.#client });
|
|
5691
|
+
}
|
|
5692
|
+
async setPoweredByFlag(projectId, enabled, idempotencyKey2) {
|
|
5693
|
+
return setProjectPoweredByFlag({
|
|
5694
|
+
project_id: projectId,
|
|
5695
|
+
"Idempotency-Key": idempotencyKey2,
|
|
5696
|
+
setPoweredByFlagRequest: { enabled }
|
|
5697
|
+
}, { client: this.#client });
|
|
5698
|
+
}
|
|
5699
|
+
async createDevAccessTicket(projectId) {
|
|
5700
|
+
return createProjectDevAccessTicket({ project_id: projectId }, { client: this.#client });
|
|
5701
|
+
}
|
|
5702
|
+
async submitFeedback(input) {
|
|
5703
|
+
return parseFeedbackReceipt(await submitFeedback({ "Idempotency-Key": input.idempotencyKey, feedbackSubmission: input.report }, { client: this.#client }));
|
|
5704
|
+
}
|
|
5705
|
+
async getFeedback(feedbackId, cursor) {
|
|
5706
|
+
return parseFeedbackStatus(await getFeedback({ feedback_id: feedbackId, ...cursor === void 0 ? {} : { cursor } }, { client: this.#client }));
|
|
5707
|
+
}
|
|
5708
|
+
async createProject(input) {
|
|
5709
|
+
return createProject({
|
|
5710
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5711
|
+
createProjectRequest: {
|
|
5712
|
+
organization_id: input.organizationId,
|
|
5713
|
+
name: input.name,
|
|
5714
|
+
...input.dataMode === void 0 ? {} : { data_mode: input.dataMode },
|
|
5715
|
+
...input.devAccessMode === void 0 ? {} : { dev_access_mode: input.devAccessMode },
|
|
5716
|
+
...input.region === void 0 ? {} : { region: input.region }
|
|
5717
|
+
}
|
|
5718
|
+
}, { client: this.#client });
|
|
5719
|
+
}
|
|
5720
|
+
async getOperation(operationId) {
|
|
5721
|
+
return getOperation({ operation_id: operationId }, { client: this.#client });
|
|
5722
|
+
}
|
|
5723
|
+
async reconcileOperation(input) {
|
|
5724
|
+
return reconcileOperation({
|
|
5725
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5726
|
+
operation_id: input.operationId
|
|
5727
|
+
}, { client: this.#client });
|
|
5728
|
+
}
|
|
5729
|
+
async connectGithub(input) {
|
|
5730
|
+
return connectGithubOrganization({
|
|
5731
|
+
organization_id: input.organizationId,
|
|
5732
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5733
|
+
connectGithubOrganizationRequest: {}
|
|
5734
|
+
}, { client: this.#client });
|
|
5735
|
+
}
|
|
5736
|
+
async getGithubConnection(organizationId) {
|
|
5737
|
+
return getGithubOrganizationConnection({ organization_id: organizationId }, { client: this.#client });
|
|
5738
|
+
}
|
|
5739
|
+
async linkSource(input) {
|
|
5740
|
+
return linkProjectSource({
|
|
5741
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5742
|
+
project_id: input.projectId,
|
|
5743
|
+
linkProjectSourceRequest: {
|
|
5744
|
+
repository_owner: input.repositoryOwner,
|
|
5745
|
+
repository_name: input.repositoryName
|
|
5746
|
+
}
|
|
5747
|
+
}, { client: this.#client });
|
|
5748
|
+
}
|
|
5749
|
+
async configureAutoDeploy(input) {
|
|
5750
|
+
return configureProjectSourceAutoDeploy({
|
|
5751
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5752
|
+
project_id: input.projectId,
|
|
5753
|
+
configureSourceAutoDeployRequest: { branch: input.branch, enabled: input.enabled }
|
|
5754
|
+
}, { client: this.#client });
|
|
5755
|
+
}
|
|
5756
|
+
async getAutoDeploy(projectId) {
|
|
5757
|
+
return getProjectSourceAutoDeploy({ project_id: projectId }, { client: this.#client });
|
|
5758
|
+
}
|
|
5759
|
+
async authorizeCloudflareDns(input) {
|
|
5760
|
+
return createCloudflareDnsAuthorization({
|
|
5761
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5762
|
+
project_id: input.projectId,
|
|
5763
|
+
createCloudflareDnsAuthorizationRequest: { zone: input.zone }
|
|
5764
|
+
}, { client: this.#client });
|
|
5765
|
+
}
|
|
5766
|
+
async getCloudflareDnsStatus(projectId) {
|
|
5767
|
+
return getCloudflareDnsAuthorizationStatus({ project_id: projectId }, { client: this.#client });
|
|
5768
|
+
}
|
|
5769
|
+
async applyProjectDomains(input) {
|
|
5770
|
+
return configureProjectDomains({ "Idempotency-Key": input.idempotencyKey, project_id: input.projectId }, { client: this.#client });
|
|
5771
|
+
}
|
|
5772
|
+
async planDeployment(input) {
|
|
5773
|
+
return planDeployment({
|
|
5774
|
+
project_id: input.projectId,
|
|
5775
|
+
planDeploymentRequest: { commit_sha: input.commitSha, environment: input.environment }
|
|
5776
|
+
}, { client: this.#client });
|
|
5777
|
+
}
|
|
5778
|
+
async createDeployment(input) {
|
|
5779
|
+
return createDeployment({
|
|
5780
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5781
|
+
project_id: input.projectId,
|
|
5782
|
+
createDeploymentRequest: { plan_id: input.planId }
|
|
5783
|
+
}, { client: this.#client });
|
|
5784
|
+
}
|
|
5785
|
+
async getDeployment(input) {
|
|
5786
|
+
return getDeployment({ project_id: input.projectId, deployment_id: input.deploymentId }, { client: this.#client });
|
|
5787
|
+
}
|
|
5788
|
+
async streamOperationEvents(operationId, signal) {
|
|
5789
|
+
return (await streamOperationEvents({ operation_id: operationId }, { client: this.#client, signal, headers: { Accept: "text/event-stream" } })).stream;
|
|
5790
|
+
}
|
|
5791
|
+
async getDeploymentLogs(input) {
|
|
5792
|
+
return getDeploymentLogs({
|
|
5793
|
+
project_id: input.projectId,
|
|
5794
|
+
deployment_id: input.deploymentId,
|
|
5795
|
+
limit: input.limit,
|
|
5796
|
+
...input.cursor === void 0 ? {} : { cursor: input.cursor }
|
|
5797
|
+
}, { client: this.#client });
|
|
5798
|
+
}
|
|
5799
|
+
async streamDeploymentLogs(input, signal) {
|
|
5800
|
+
return (await streamDeploymentLogs({ project_id: input.projectId, deployment_id: input.deploymentId }, { client: this.#client, signal, headers: { Accept: "text/event-stream" } })).stream;
|
|
5801
|
+
}
|
|
5802
|
+
async planRollback(input) {
|
|
5803
|
+
return planDeploymentRollback({ project_id: input.projectId, target_deployment_id: input.deploymentId }, { client: this.#client });
|
|
5804
|
+
}
|
|
5805
|
+
async rollback(input) {
|
|
5806
|
+
return rollbackDeployment({
|
|
5807
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5808
|
+
"If-Match": input.ifMatch,
|
|
5809
|
+
"X-Confirmation-Token": input.confirmationToken,
|
|
5810
|
+
project_id: input.projectId,
|
|
5811
|
+
target_deployment_id: input.deploymentId
|
|
5812
|
+
}, { client: this.#client });
|
|
5813
|
+
}
|
|
5814
|
+
async planPromotion(input) {
|
|
5815
|
+
return planDeploymentPromotion({ project_id: input.projectId, source_deployment_id: input.sourceDeploymentId }, { client: this.#client });
|
|
4802
5816
|
}
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
switch (input.action) {
|
|
4812
|
-
case "configure":
|
|
4813
|
-
return configureManagedMailDomain({
|
|
4814
|
-
...scope,
|
|
4815
|
-
"Idempotency-Key": input.idempotencyKey,
|
|
4816
|
-
managedMailDomainRequest: {
|
|
4817
|
-
domain: input.domain,
|
|
4818
|
-
sending: input.sending,
|
|
4819
|
-
receiving: input.receiving
|
|
4820
|
-
}
|
|
4821
|
-
}, { client: client2 });
|
|
4822
|
-
case "status":
|
|
4823
|
-
return getManagedMailDomain(scope, { client: client2 });
|
|
4824
|
-
case "webhook_set":
|
|
4825
|
-
return prepareManagedMailWebhook({
|
|
4826
|
-
...scope,
|
|
4827
|
-
"Idempotency-Key": input.idempotencyKey,
|
|
4828
|
-
managedMailWebhookRequest: { url: input.url }
|
|
4829
|
-
}, { client: client2 });
|
|
4830
|
-
case "webhook_verify":
|
|
4831
|
-
return verifyManagedMailWebhook({ ...scope, "Idempotency-Key": input.idempotencyKey }, { client: client2 });
|
|
4832
|
-
case "webhook_disable":
|
|
4833
|
-
return disableManagedMailReceiving({ ...scope, "Idempotency-Key": input.idempotencyKey }, { client: client2 });
|
|
4834
|
-
case "domain_delete":
|
|
4835
|
-
return deleteManagedMailDomain({ ...scope, "Idempotency-Key": input.idempotencyKey }, { client: client2 });
|
|
4836
|
-
case "messages_list":
|
|
4837
|
-
return listManagedMailMessages({ ...scope, ...input.after ? { after: input.after } : {} }, { client: client2 });
|
|
4838
|
-
case "message_get":
|
|
4839
|
-
return getManagedMailMessage({ ...scope, message_id: input.messageId }, { client: client2 });
|
|
4840
|
-
case "message_retry":
|
|
4841
|
-
return retryManagedMailMessage({ ...scope, message_id: input.messageId, "Idempotency-Key": input.idempotencyKey }, { client: client2 });
|
|
5817
|
+
async promote(input) {
|
|
5818
|
+
return promoteDeployment({
|
|
5819
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5820
|
+
"If-Match": input.ifMatch,
|
|
5821
|
+
"X-Confirmation-Token": input.confirmationToken,
|
|
5822
|
+
project_id: input.projectId,
|
|
5823
|
+
source_deployment_id: input.sourceDeploymentId
|
|
5824
|
+
}, { client: this.#client });
|
|
4842
5825
|
}
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
5826
|
+
async planDelete(projectId) {
|
|
5827
|
+
return planProjectDeletion({ project_id: projectId }, { client: this.#client });
|
|
5828
|
+
}
|
|
5829
|
+
async deleteProject(input) {
|
|
5830
|
+
return deleteProject({
|
|
5831
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5832
|
+
"If-Match": input.ifMatch,
|
|
5833
|
+
"X-Confirmation-Token": input.confirmationToken,
|
|
5834
|
+
project_id: input.projectId
|
|
5835
|
+
}, { client: this.#client });
|
|
5836
|
+
}
|
|
5837
|
+
async listEnvironmentSecrets(input) {
|
|
5838
|
+
return listEnvironmentSecrets({ project_id: input.projectId, environment_id: input.environmentId }, { client: this.#client });
|
|
5839
|
+
}
|
|
5840
|
+
async listFunctionRuns(input) {
|
|
5841
|
+
return listFunctionRuns({ project_id: input.projectId, environment_id: input.environmentId, limit: input.limit }, { client: this.#client });
|
|
5842
|
+
}
|
|
5843
|
+
async putEnvironmentSecret(input) {
|
|
5844
|
+
return putEnvironmentSecret({
|
|
5845
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5846
|
+
project_id: input.projectId,
|
|
5847
|
+
environment_id: input.environmentId,
|
|
5848
|
+
secret_name: input.name,
|
|
5849
|
+
putEnvironmentSecretRequest: { value: input.value }
|
|
5850
|
+
}, { client: this.#client });
|
|
5851
|
+
}
|
|
5852
|
+
async deleteEnvironmentSecret(input) {
|
|
5853
|
+
return deleteEnvironmentSecret({
|
|
5854
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5855
|
+
project_id: input.projectId,
|
|
5856
|
+
environment_id: input.environmentId,
|
|
5857
|
+
secret_name: input.name
|
|
5858
|
+
}, { client: this.#client });
|
|
5859
|
+
}
|
|
5860
|
+
managedMail(input) {
|
|
5861
|
+
return executeManagedMail(this.#client, input);
|
|
4870
5862
|
}
|
|
4871
|
-
const expiresIn = expectPositiveInteger(input["expires_in"], "expires_in", { optional: true });
|
|
4872
|
-
const organizationId = expectString(input["organization_id"], "organization_id", {
|
|
4873
|
-
optional: true
|
|
4874
|
-
});
|
|
4875
|
-
return {
|
|
4876
|
-
accessToken: expectString(input["access_token"], "access_token"),
|
|
4877
|
-
refreshToken: expectString(input["refresh_token"], "refresh_token"),
|
|
4878
|
-
tokenType: expectString(input["token_type"], "token_type", { optional: true }) ?? "Bearer",
|
|
4879
|
-
...expiresIn === void 0 ? {} : { expiresInSeconds: expiresIn },
|
|
4880
|
-
...organizationId === void 0 ? {} : { organizationId }
|
|
4881
|
-
};
|
|
4882
5863
|
};
|
|
4883
5864
|
|
|
4884
5865
|
// apps/product-cli/dist/repository-init.js
|
|
@@ -4942,33 +5923,95 @@ function environmentToken(environment2 = {}) {
|
|
|
4942
5923
|
throw new ProductApiAuthenticationError("invalid_environment_token");
|
|
4943
5924
|
return value;
|
|
4944
5925
|
}
|
|
5926
|
+
function environmentProfile(environment2 = {}) {
|
|
5927
|
+
const value = environment2.OHMYHOST_PROFILE;
|
|
5928
|
+
if (value === void 0 || value === "")
|
|
5929
|
+
return void 0;
|
|
5930
|
+
if (!isProfileName(value))
|
|
5931
|
+
throw new ProductApiAuthenticationError("invalid_profile_binding");
|
|
5932
|
+
return value;
|
|
5933
|
+
}
|
|
5934
|
+
var profileRequest = (input, bound) => ({
|
|
5935
|
+
...input?.name === void 0 ? {} : { name: input.name },
|
|
5936
|
+
...bound === void 0 ? {} : { bound },
|
|
5937
|
+
...input?.organizationId === void 0 ? {} : { organizationId: input.organizationId },
|
|
5938
|
+
...input?.userId === void 0 ? {} : { userId: input.userId }
|
|
5939
|
+
});
|
|
4945
5940
|
var createAuthenticatedProductTransport = async (signal, overrides = {}) => {
|
|
4946
|
-
const
|
|
5941
|
+
const platform = resolveProductCliEnvironment(overrides.environment);
|
|
4947
5942
|
const apiToken = environmentToken(overrides.environment);
|
|
5943
|
+
const bound = environmentProfile(overrides.environment);
|
|
5944
|
+
const baseUrl = overrides.productApiOrigin ?? platform.apiOrigin;
|
|
4948
5945
|
const boundedFetch = createBoundedFetch(overrides.fetch ?? fetch, signal, REQUEST_TIMEOUT_MS, MAX_PUBLIC_RESPONSE_BYTES);
|
|
4949
|
-
|
|
5946
|
+
const registry = overrides.profiles ?? new NativeKeyringProfileRegistry(void 0, platform.credentialService);
|
|
5947
|
+
const binding = overrides.request?.bindOrganization === true;
|
|
5948
|
+
const request = profileRequest(overrides.request, bound);
|
|
5949
|
+
if (apiToken !== void 0) {
|
|
5950
|
+
await verifyEnvironmentTokenContext({
|
|
5951
|
+
token: apiToken,
|
|
5952
|
+
request: binding ? profileRequest({}, bound) : request,
|
|
5953
|
+
registry,
|
|
5954
|
+
baseUrl,
|
|
5955
|
+
fetch: boundedFetch
|
|
5956
|
+
});
|
|
4950
5957
|
return {
|
|
4951
|
-
baseUrl
|
|
5958
|
+
baseUrl,
|
|
4952
5959
|
accessToken: apiToken,
|
|
4953
5960
|
fetch: boundedFetch,
|
|
4954
|
-
|
|
4955
|
-
|
|
5961
|
+
workspace: void 0,
|
|
5962
|
+
context: { credential: "environment_token", profile: null }
|
|
4956
5963
|
};
|
|
4957
|
-
|
|
4958
|
-
const stored = await store.read();
|
|
4959
|
-
if (stored === void 0)
|
|
4960
|
-
throw new ProductApiAuthenticationError("authentication_required");
|
|
5964
|
+
}
|
|
4961
5965
|
const now = overrides.now ?? (() => /* @__PURE__ */ new Date());
|
|
4962
5966
|
const refresher = overrides.tokenRefresher ?? new PublicWorkosTokenRefresher(overrides.environment, overrides.fetch, now);
|
|
4963
|
-
const
|
|
5967
|
+
const profiles = await loadProfiles(registry, {
|
|
5968
|
+
baseUrl,
|
|
5969
|
+
fetch: boundedFetch,
|
|
5970
|
+
signal,
|
|
5971
|
+
now,
|
|
5972
|
+
refresher
|
|
5973
|
+
});
|
|
5974
|
+
const selection = binding && request.organizationId !== void 0 ? selectProfileForOrganization(profiles, {
|
|
5975
|
+
...request,
|
|
5976
|
+
organizationId: request.organizationId
|
|
5977
|
+
}) : selectProfile(profiles, request);
|
|
5978
|
+
if (selection.outcome !== "selected")
|
|
5979
|
+
throw profileSelectionError(selection, request, platform.commandPrefix, overrides.selector ?? "cli");
|
|
5980
|
+
const profile = selection.profile;
|
|
5981
|
+
const store = registry.credential(profile);
|
|
5982
|
+
const stored = await store.read();
|
|
5983
|
+
if (stored === void 0)
|
|
5984
|
+
throw missingLogin(profile, platform.commandPrefix);
|
|
5985
|
+
const credential = await currentCredential(stored, store, signal, now, refresher, () => registry.remove(profile));
|
|
4964
5986
|
return {
|
|
4965
|
-
baseUrl
|
|
5987
|
+
baseUrl,
|
|
4966
5988
|
accessToken: credential.accessToken,
|
|
4967
5989
|
fetch: boundedFetch,
|
|
4968
|
-
workspace: { store, refresher }
|
|
5990
|
+
workspace: { store, refresher, profiles: registry, profile },
|
|
5991
|
+
context: { credential: "profile", profile }
|
|
5992
|
+
};
|
|
5993
|
+
};
|
|
5994
|
+
var listSavedProfiles = async (signal, overrides = {}) => {
|
|
5995
|
+
const platform = resolveProductCliEnvironment(overrides.environment);
|
|
5996
|
+
const apiToken = environmentToken(overrides.environment);
|
|
5997
|
+
const bound = environmentProfile(overrides.environment);
|
|
5998
|
+
const registry = overrides.profiles ?? new NativeKeyringProfileRegistry(void 0, platform.credentialService);
|
|
5999
|
+
const now = overrides.now ?? (() => /* @__PURE__ */ new Date());
|
|
6000
|
+
const profiles = apiToken === void 0 ? await loadProfiles(registry, {
|
|
6001
|
+
baseUrl: overrides.productApiOrigin ?? platform.apiOrigin,
|
|
6002
|
+
fetch: createBoundedFetch(overrides.fetch ?? fetch, signal, REQUEST_TIMEOUT_MS, MAX_PUBLIC_RESPONSE_BYTES),
|
|
6003
|
+
signal,
|
|
6004
|
+
now,
|
|
6005
|
+
refresher: overrides.tokenRefresher ?? new PublicWorkosTokenRefresher(overrides.environment, overrides.fetch, now)
|
|
6006
|
+
}) : await registry.list();
|
|
6007
|
+
return {
|
|
6008
|
+
profiles: profiles.map(publicProfile),
|
|
6009
|
+
bound: bound ?? null,
|
|
6010
|
+
environment_token: apiToken !== void 0
|
|
4969
6011
|
};
|
|
4970
6012
|
};
|
|
4971
|
-
var
|
|
6013
|
+
var missingLogin = (profile, commandPrefix) => new ProfileSelectionError("authentication_required", 5, `The saved login ${profile.name} has no credential on this computer. Run '${commandPrefix} login${profile.organizationId === null ? "" : ` --organization ${profile.organizationId}`} --profile-name ${profile.name} --json'.`);
|
|
6014
|
+
var currentCredential = async (stored, store, signal, now, tokenRefresher, forget) => {
|
|
4972
6015
|
const expiresAt = stored.expiresAt === void 0 ? NaN : Date.parse(stored.expiresAt);
|
|
4973
6016
|
if (Number.isFinite(expiresAt) && expiresAt > now().getTime() + REQUEST_TIMEOUT_MS) {
|
|
4974
6017
|
return stored;
|
|
@@ -4984,12 +6027,73 @@ var currentCredential = async (stored, store, signal, now, tokenRefresher) => {
|
|
|
4984
6027
|
return carried;
|
|
4985
6028
|
} catch (error) {
|
|
4986
6029
|
if (error instanceof TokenRefreshRejectedError) {
|
|
4987
|
-
await
|
|
6030
|
+
await forget();
|
|
4988
6031
|
throw new ProductApiAuthenticationError("authentication_required");
|
|
4989
6032
|
}
|
|
4990
6033
|
throw new ProductApiAuthenticationError("token_refresh_failed");
|
|
4991
6034
|
}
|
|
4992
6035
|
};
|
|
6036
|
+
var loadProfiles = async (registry, context) => {
|
|
6037
|
+
const legacy = registry.legacy();
|
|
6038
|
+
const stored = await legacy.read();
|
|
6039
|
+
if (stored !== void 0)
|
|
6040
|
+
await migrateLegacyLogin(registry, legacy, stored, context);
|
|
6041
|
+
return registry.list();
|
|
6042
|
+
};
|
|
6043
|
+
var migrateLegacyLogin = async (registry, legacy, stored, context) => {
|
|
6044
|
+
let credential;
|
|
6045
|
+
try {
|
|
6046
|
+
credential = await currentCredential(stored, legacy, context.signal, context.now, context.refresher, () => legacy.clear());
|
|
6047
|
+
} catch (error) {
|
|
6048
|
+
if (error instanceof ProductApiAuthenticationError && error.code === "authentication_required")
|
|
6049
|
+
return;
|
|
6050
|
+
throw error;
|
|
6051
|
+
}
|
|
6052
|
+
const api = new GeneratedSdkProductApi(context.baseUrl, credential.accessToken, context.fetch);
|
|
6053
|
+
let identity;
|
|
6054
|
+
try {
|
|
6055
|
+
identity = await api.getCurrentIdentity();
|
|
6056
|
+
} catch (error) {
|
|
6057
|
+
if (!isProblem(error, "unauthenticated"))
|
|
6058
|
+
throw error;
|
|
6059
|
+
return;
|
|
6060
|
+
}
|
|
6061
|
+
const userId = verifiedUserId(identity);
|
|
6062
|
+
const organizationId = parseCurrentIdentity(identity).organization_ids[0] ?? null;
|
|
6063
|
+
const organizationName = organizationId === null ? null : (await api.getAccountProfile()).organizations.find((organization) => organization.id === organizationId)?.name ?? null;
|
|
6064
|
+
const login = { userId, organizationId, organizationName };
|
|
6065
|
+
await registry.save({ name: defaultProfileName(await registry.list(), login), ...login }, credential);
|
|
6066
|
+
await legacy.clear();
|
|
6067
|
+
};
|
|
6068
|
+
var isProblem = (error, code) => typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
6069
|
+
var verifyEnvironmentTokenContext = async (input) => {
|
|
6070
|
+
const { request } = input;
|
|
6071
|
+
const named = request.name ?? request.bound;
|
|
6072
|
+
if (named === void 0 && request.organizationId === void 0 && request.userId === void 0)
|
|
6073
|
+
return null;
|
|
6074
|
+
const refuse = (target) => new ProfileSelectionError("environment_token_context_mismatch", 2, `${target} Unset OHMYHOST_TOKEN to use the saved login, or load the key of that account from its private env file. Nothing was sent.`);
|
|
6075
|
+
if (request.name !== void 0 && request.bound !== void 0 && request.name !== request.bound)
|
|
6076
|
+
throw refuse(`This call names profile ${request.name}, but the process is bound to OHMYHOST_PROFILE=${request.bound}.`);
|
|
6077
|
+
const profile = named === void 0 ? void 0 : (await input.registry.list()).find((saved) => saved.name === named);
|
|
6078
|
+
if (named !== void 0 && profile === void 0)
|
|
6079
|
+
throw refuse(`OHMYHOST_TOKEN overrides saved logins in this process, and no saved login is named ${named}.`);
|
|
6080
|
+
const { userId, organizationId } = await readTokenIdentity(input);
|
|
6081
|
+
const owner = `OHMYHOST_TOKEN belongs to user ${userId} in organization ${organizationId ?? "none"},`;
|
|
6082
|
+
if (profile !== void 0 && (profile.userId !== userId || profile.organizationId !== organizationId))
|
|
6083
|
+
throw refuse(`${owner} but this call names ${describeProfile(profile)}.`);
|
|
6084
|
+
if (request.organizationId !== void 0 && request.organizationId !== organizationId)
|
|
6085
|
+
throw refuse(`${owner} but this call targets organization ${request.organizationId}.`);
|
|
6086
|
+
if (request.userId !== void 0 && request.userId !== userId)
|
|
6087
|
+
throw refuse(`${owner} but this call targets user ${request.userId}.`);
|
|
6088
|
+
return { userId, organizationId };
|
|
6089
|
+
};
|
|
6090
|
+
var readTokenIdentity = async (input) => {
|
|
6091
|
+
const identity = parseCurrentIdentity(await new GeneratedSdkProductApi(input.baseUrl, input.token, input.fetch).getCurrentIdentity());
|
|
6092
|
+
return {
|
|
6093
|
+
userId: identity.actor_id.startsWith("user:") ? identity.actor_id.slice(5) : identity.actor_id,
|
|
6094
|
+
organizationId: identity.organization_ids[0] ?? null
|
|
6095
|
+
};
|
|
6096
|
+
};
|
|
4993
6097
|
var FetchWorkosPublicTransport = class {
|
|
4994
6098
|
parentSignal;
|
|
4995
6099
|
timeoutMs;
|
|
@@ -5167,7 +6271,7 @@ var boundedSignal = (parent, timeoutMs) => AbortSignal.any([parent, AbortSignal.
|
|
|
5167
6271
|
var isAbortOrTimeout = (error) => error instanceof DOMException && (error.name === "AbortError" || error.name === "TimeoutError");
|
|
5168
6272
|
|
|
5169
6273
|
// apps/mcp/dist/local-client.js
|
|
5170
|
-
import { lstat as lstat2, open as
|
|
6274
|
+
import { lstat as lstat2, open as open3 } from "node:fs/promises";
|
|
5171
6275
|
import { isAbsolute } from "node:path";
|
|
5172
6276
|
var OperationEventsUnavailableError = class extends Error {
|
|
5173
6277
|
constructor() {
|
|
@@ -5177,8 +6281,11 @@ var OperationEventsUnavailableError = class extends Error {
|
|
|
5177
6281
|
};
|
|
5178
6282
|
async function createAuthenticatedLocalMcpClient(signal, overrides = {}) {
|
|
5179
6283
|
try {
|
|
5180
|
-
const transport = await createAuthenticatedProductTransport(signal,
|
|
5181
|
-
|
|
6284
|
+
const transport = await createAuthenticatedProductTransport(signal, {
|
|
6285
|
+
...overrides,
|
|
6286
|
+
selector: "mcp"
|
|
6287
|
+
});
|
|
6288
|
+
return new GeneratedSdkLocalMcpClient(transport.baseUrl, transport.accessToken, transport.fetch, transport.workspace, transport.context, resolveProductCliEnvironment(overrides.environment).commandPrefix);
|
|
5182
6289
|
} catch (error) {
|
|
5183
6290
|
if (!(error instanceof ProductApiAuthenticationError))
|
|
5184
6291
|
throw error;
|
|
@@ -5191,11 +6298,44 @@ async function createAuthenticatedLocalMcpClient(signal, overrides = {}) {
|
|
|
5191
6298
|
var GeneratedSdkLocalMcpClient = class {
|
|
5192
6299
|
#client;
|
|
5193
6300
|
#workspace;
|
|
6301
|
+
#context;
|
|
6302
|
+
#commandPrefix;
|
|
5194
6303
|
#rescope;
|
|
5195
|
-
constructor(baseUrl, accessToken, fetch2, workspace) {
|
|
6304
|
+
constructor(baseUrl, accessToken, fetch2, workspace, context, commandPrefix = "OHMYHOST_ENVIRONMENT=production ohmyhost") {
|
|
5196
6305
|
this.#rescope = (token) => createClient({ auth: token, baseUrl, fetch: fetch2, throwOnError: true });
|
|
5197
6306
|
this.#client = this.#rescope(accessToken);
|
|
5198
6307
|
this.#workspace = workspace;
|
|
6308
|
+
this.#context = context ?? {
|
|
6309
|
+
credential: workspace === void 0 ? "environment_token" : "profile",
|
|
6310
|
+
profile: workspace?.profile ?? null
|
|
6311
|
+
};
|
|
6312
|
+
this.#commandPrefix = commandPrefix;
|
|
6313
|
+
}
|
|
6314
|
+
actingAs() {
|
|
6315
|
+
return this.#contextReport();
|
|
6316
|
+
}
|
|
6317
|
+
/** Which account this call acts as, without any credential. */
|
|
6318
|
+
#contextReport() {
|
|
6319
|
+
const profile = this.#workspace?.profile ?? this.#context.profile;
|
|
6320
|
+
return {
|
|
6321
|
+
credential: this.#context.credential,
|
|
6322
|
+
profile: profile === null ? null : publicProfile(profile)
|
|
6323
|
+
};
|
|
6324
|
+
}
|
|
6325
|
+
/**
|
|
6326
|
+
* Bind this call's login, which has no organization yet, and continue with its new credential.
|
|
6327
|
+
* A login in another organization keeps it; the provider verifies the account first.
|
|
6328
|
+
*/
|
|
6329
|
+
async #bind(organization, signal) {
|
|
6330
|
+
const session = this.#interactiveSession();
|
|
6331
|
+
const bound = await selectWorkspace(session, organization, signal, (token) => getCurrentIdentity({}, { client: this.#rescope(token) }));
|
|
6332
|
+
const store = session.profiles.credential(bound);
|
|
6333
|
+
const credential = await store.read();
|
|
6334
|
+
if (credential === void 0)
|
|
6335
|
+
throw new InteractiveSessionRequiredError();
|
|
6336
|
+
this.#workspace = { ...session, store, profile: bound };
|
|
6337
|
+
this.#client = this.#rescope(credential.accessToken);
|
|
6338
|
+
return bound;
|
|
5199
6339
|
}
|
|
5200
6340
|
async changeDatabaseCompute(input) {
|
|
5201
6341
|
return changeDatabaseCompute({
|
|
@@ -5261,13 +6401,15 @@ var GeneratedSdkLocalMcpClient = class {
|
|
|
5261
6401
|
async getCurrentIdentity(signal) {
|
|
5262
6402
|
const identity = await getCurrentIdentity({}, { client: this.#client });
|
|
5263
6403
|
if (this.#workspace === void 0 || parseCurrentIdentity(identity).organization_ids.length > 0)
|
|
5264
|
-
return identity;
|
|
6404
|
+
return { ...identity, context: this.#contextReport() };
|
|
5265
6405
|
const selection = chooseWorkspace(await this.#readWorkspaces(), void 0);
|
|
5266
6406
|
if (selection.outcome !== "selected")
|
|
5267
|
-
return identity;
|
|
5268
|
-
await
|
|
5269
|
-
|
|
5270
|
-
|
|
6407
|
+
return { ...identity, context: this.#contextReport() };
|
|
6408
|
+
await this.#bind(selection.organization, signal);
|
|
6409
|
+
return {
|
|
6410
|
+
...await getCurrentIdentity({}, { client: this.#client }),
|
|
6411
|
+
context: this.#contextReport()
|
|
6412
|
+
};
|
|
5271
6413
|
}
|
|
5272
6414
|
async changeProjectHandle(input) {
|
|
5273
6415
|
return changeProjectHandle({
|
|
@@ -5313,6 +6455,9 @@ var GeneratedSdkLocalMcpClient = class {
|
|
|
5313
6455
|
assertOrganizationAccount(account);
|
|
5314
6456
|
return account;
|
|
5315
6457
|
}
|
|
6458
|
+
async getOrganizationReferral(organizationId) {
|
|
6459
|
+
return parseOrganizationReferral(await getOrganizationReferral({ organization_id: organizationId }, { client: this.#client }));
|
|
6460
|
+
}
|
|
5316
6461
|
getOrganizationCredits(organizationId) {
|
|
5317
6462
|
return getOrganizationCredits({ organization_id: organizationId }, { client: this.#client });
|
|
5318
6463
|
}
|
|
@@ -5380,29 +6525,39 @@ var GeneratedSdkLocalMcpClient = class {
|
|
|
5380
6525
|
...input.signupSource === void 0 ? {} : { signup_source: input.signupSource }
|
|
5381
6526
|
}
|
|
5382
6527
|
}, { client: this.#client });
|
|
6528
|
+
const current = this.#interactiveSession().profile;
|
|
6529
|
+
if (current.organizationId !== null && current.organizationId !== created.id)
|
|
6530
|
+
return {
|
|
6531
|
+
organization: { id: created.id, name: created.name },
|
|
6532
|
+
selected: current.organizationId,
|
|
6533
|
+
profile: publicProfile(current),
|
|
6534
|
+
next_action: `Run '${this.#commandPrefix} login --organization ${created.id} --user ${current.userId} --json' to add a login for the new workspace as the same user, then pass its profile_name.`
|
|
6535
|
+
};
|
|
5383
6536
|
return this.selectOrganization(created.id, signal);
|
|
5384
6537
|
}
|
|
5385
6538
|
async listOrganizations() {
|
|
5386
6539
|
const session = this.#interactiveSession();
|
|
5387
6540
|
return {
|
|
5388
6541
|
organizations: (await this.#readWorkspaces()).map(publicWorkspace),
|
|
5389
|
-
selected:
|
|
6542
|
+
selected: session.profile.organizationId,
|
|
6543
|
+
profile: publicProfile(session.profile)
|
|
5390
6544
|
};
|
|
5391
6545
|
}
|
|
5392
6546
|
async selectOrganization(organizationId, signal) {
|
|
5393
|
-
|
|
6547
|
+
this.#interactiveSession();
|
|
5394
6548
|
const selection = chooseWorkspace(await this.#readWorkspaces(), organizationId);
|
|
5395
6549
|
if (selection.outcome !== "selected")
|
|
5396
6550
|
throw new Error(`ORGANIZATION_NOT_FOUND:${organizationId}`);
|
|
5397
|
-
await
|
|
6551
|
+
const profile = await this.#bind(selection.organization, signal);
|
|
5398
6552
|
return {
|
|
5399
6553
|
organization: publicWorkspace(selection.organization),
|
|
5400
|
-
selected: selection.organization.id
|
|
6554
|
+
selected: selection.organization.id,
|
|
6555
|
+
profile: publicProfile(profile)
|
|
5401
6556
|
};
|
|
5402
6557
|
}
|
|
5403
6558
|
async #readWorkspaces() {
|
|
5404
6559
|
this.#interactiveSession();
|
|
5405
|
-
return parseAccountProfile(await getAccountProfile({ client: this.#client }));
|
|
6560
|
+
return parseAccountProfile(await getAccountProfile({ client: this.#client })).organizations;
|
|
5406
6561
|
}
|
|
5407
6562
|
#interactiveSession() {
|
|
5408
6563
|
if (this.#workspace === void 0)
|
|
@@ -5431,6 +6586,16 @@ var GeneratedSdkLocalMcpClient = class {
|
|
|
5431
6586
|
setDevAccessModeRequest: { mode: input.mode }
|
|
5432
6587
|
}, { client: this.#client }));
|
|
5433
6588
|
}
|
|
6589
|
+
async getPoweredByFlag(projectId) {
|
|
6590
|
+
return parsePoweredByFlag(await getProjectPoweredByFlag({ project_id: projectId }, { client: this.#client }));
|
|
6591
|
+
}
|
|
6592
|
+
async setPoweredByFlag(input) {
|
|
6593
|
+
return parsePoweredByFlag(await setProjectPoweredByFlag({
|
|
6594
|
+
project_id: input.projectId,
|
|
6595
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
6596
|
+
setPoweredByFlagRequest: { enabled: input.enabled }
|
|
6597
|
+
}, { client: this.#client }));
|
|
6598
|
+
}
|
|
5434
6599
|
async rotateDevShareLink(input) {
|
|
5435
6600
|
return parseDevAccessState(await rotateProjectDevShareLink({ project_id: input.projectId, "Idempotency-Key": input.idempotencyKey }, { client: this.#client }));
|
|
5436
6601
|
}
|
|
@@ -5681,7 +6846,7 @@ async function readExportPasswordFile(path) {
|
|
|
5681
6846
|
const before = await lstat2(path);
|
|
5682
6847
|
if (!before.isFile() || before.isSymbolicLink() || before.size < 1 || before.size > 1024 || process.platform !== "win32" && (before.mode & 63) !== 0)
|
|
5683
6848
|
throw new Error();
|
|
5684
|
-
file = await
|
|
6849
|
+
file = await open3(path, "r");
|
|
5685
6850
|
const after = await file.stat();
|
|
5686
6851
|
if (after.ino !== before.ino || after.dev !== before.dev || after.size !== before.size)
|
|
5687
6852
|
throw new Error();
|
|
@@ -5702,6 +6867,7 @@ async function readExportPasswordFile(path) {
|
|
|
5702
6867
|
|
|
5703
6868
|
// apps/mcp/dist/local-server.js
|
|
5704
6869
|
var identifier2 = external_exports.string().min(1).max(256);
|
|
6870
|
+
var profileName = external_exports.string().regex(/^[a-z0-9][a-z0-9_-]{0,62}$/u).optional().describe("Saved login to act as (profile_list shows them). Needed only when several logins could run this call; OHMYHOST_PROFILE of this server must match it.");
|
|
5705
6871
|
var idempotencyKey = external_exports.string().min(1).max(256);
|
|
5706
6872
|
var commitSha = external_exports.string().regex(/^[a-f0-9]{40}$/u);
|
|
5707
6873
|
var domainName = external_exports.string().regex(/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/u);
|
|
@@ -5835,6 +7001,7 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
5835
7001
|
...input.cursor ? { cursor: input.cursor } : {}
|
|
5836
7002
|
}));
|
|
5837
7003
|
registerProductTool(server, dependencies, "organization_account_get", "Owner-only: read the effective Free/Paid plan, its Stripe or granted source, available expiring Free credits and purchased credits that never expire, reservations and next expiry. Granted Paid features do not imply a Stripe subscription or extra monthly Paid allowance. This read grants no access or credits.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getOrganizationAccount(input.organization_id));
|
|
7004
|
+
registerProductTool(server, dependencies, "referral_link_get", "Read the workspace's referral link to share. A new user whose first workspace comes from it starts with a free Paid month and 1,000 credits; that workspace's first payment gives this workspace the same. Any member may read it.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getOrganizationReferral(input.organization_id));
|
|
5838
7005
|
registerProductTool(server, dependencies, "organization_credits_get", "Read the owner's shared organization credit pool, seven-day grace_started_at/grace_expires_at and published rate_cards. Existing services/domains are not immediately shut down at zero credit; an explicit project stop budget is separate. One credit is 1000000 microcredits. Each rate states credit_micros for units_per_charge; publication alone does not enable billing. active_meters identifies billed sources; provider outages and platform overrun are not customer debt. Works at zero credit.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getOrganizationCredits(input.organization_id));
|
|
5839
7006
|
registerProductTool(server, dependencies, "project_budget_get", "Read the owner's project UTC-month budget, measured usage and open reservations. A budget never allocates a second wallet.", external_exports.object({ project_id: identifier2 }), (client2, input) => client2.getProjectCreditBudget(input.project_id));
|
|
5840
7007
|
registerProductTool(server, dependencies, "project_budget_set", "Set an owner's optional monthly project budget in microcredits (1000000 = one credit). continue is the default and uses the org pool after the threshold; stop blocks new billable work. null clears the budget and requires continue. Changing it never resets usage or adds credits. Replay the same key after uncertainty; read the budget again for current usage.", external_exports.object({
|
|
@@ -5848,7 +7015,7 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
5848
7015
|
mode: input.mode,
|
|
5849
7016
|
idempotencyKey: input.idempotency_key
|
|
5850
7017
|
}), { readOnlyHint: false, destructiveHint: false, idempotentHint: true });
|
|
5851
|
-
registerProductTool(server, dependencies, "organization_create", `Create an organization owned by the signed-in user
|
|
7018
|
+
registerProductTool(server, dependencies, "organization_create", `Create an organization owned by the signed-in user. Signup is open. signup_source is optional attribution from a link's r parameter, never a secret; omit it when the customer arrived directly. The server decides any once-per-user bonus; do not promise credits for arbitrary sources. Repeat the same name/source/key after uncertainty. A login that has no organization yet is bound to the new one, so selected names the workspace later calls use; a login already in another organization keeps it and next_action names the login for the new one. Continue with identity_get, github_status and github_connect if needed, then projects. An OHMYHOST_TOKEN process cannot do this; it needs ${commandPrefix} login --json.`, external_exports.object({
|
|
5852
7019
|
name: external_exports.string().min(1).max(128),
|
|
5853
7020
|
signup_source: external_exports.string().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/u).optional(),
|
|
5854
7021
|
idempotency_key: idempotencyKey
|
|
@@ -5857,8 +7024,25 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
5857
7024
|
...input.signup_source === void 0 ? {} : { signupSource: input.signup_source },
|
|
5858
7025
|
idempotencyKey: input.idempotency_key
|
|
5859
7026
|
}, signal), mutationAnnotations());
|
|
5860
|
-
registerProductTool(server, dependencies, "organization_list", "List the workspaces the
|
|
5861
|
-
registerProductTool(server, dependencies, "organization_use", `
|
|
7027
|
+
registerProductTool(server, dependencies, "organization_list", "List the workspaces the chosen login's user belongs to and which one that login is scoped to. selected is null while none is chosen; every project and billing call then answers resource_not_found. Ask the customer which workspace to use instead of guessing, then call organization_use.", external_exports.object({}), (client2) => client2.listOrganizations());
|
|
7028
|
+
registerProductTool(server, dependencies, "organization_use", `Bind a saved login that has no organization yet to one workspace, so later calls act inside it. A login already in another organization keeps it (profile_organization_fixed): add a login for the other workspace as the same user with ${commandPrefix} login --organization ULID --user USER_ID --json. Read organization_list first, then github_status for the selected workspace and github_connect if needed; the identifier is the platform ULID, not the provider identifier. An OHMYHOST_TOKEN process cannot select anything and needs ${commandPrefix} login --json instead.`, external_exports.object({ organization_id: identifier2 }), (client2, input, signal) => client2.selectOrganization(input.organization_id, signal), mutationAnnotations(), (input) => ({
|
|
7029
|
+
...input.profile_name === void 0 ? {} : { name: input.profile_name },
|
|
7030
|
+
organizationId: input.organization_id,
|
|
7031
|
+
bindOrganization: true
|
|
7032
|
+
}));
|
|
7033
|
+
server.registerTool("profile_list", {
|
|
7034
|
+
description: `List the saved ohmyho.st logins on this computer: each has a name, a user and an organization, never a token. When the customer named a user or organization, pass the matching name as profile_name on later calls; with several logins and no profile_name a call answers profile_selection_required. With no match, the customer adds one with ${commandPrefix} login --organization ULID --user USER_ID --json, which saves nothing if the browser signs in as another account. bound is this server's OHMYHOST_PROFILE; environment_token means OHMYHOST_TOKEN replaces saved logins here.`,
|
|
7035
|
+
inputSchema: external_exports.object({}),
|
|
7036
|
+
annotations: readAnnotations()
|
|
7037
|
+
}, (async (_input, context) => {
|
|
7038
|
+
try {
|
|
7039
|
+
if (dependencies.listProfiles === void 0)
|
|
7040
|
+
throw new CredentialStoreUnavailableError();
|
|
7041
|
+
return toolResult(await dependencies.listProfiles(context.mcpReq.signal));
|
|
7042
|
+
} catch (error) {
|
|
7043
|
+
return toolError(error, dependencies);
|
|
7044
|
+
}
|
|
7045
|
+
}));
|
|
5862
7046
|
registerProductTool(server, dependencies, "database_query", "Read one owner-authorized Dev or Prod database query (at most 100 rows, five-second timeout). Explicitly choose the environment. Shared data resolves to the same physical database. Application RLS policies apply; use an authorized SQL export when a full archive is required.", external_exports.object({
|
|
5863
7047
|
project_id: identifier2,
|
|
5864
7048
|
environment: external_exports.enum(["dev", "prod"]),
|
|
@@ -5956,7 +7140,7 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
5956
7140
|
});
|
|
5957
7141
|
return { revoked: true, key_id: input.key_id };
|
|
5958
7142
|
}, destructiveAnnotations());
|
|
5959
|
-
registerProductTool(server, dependencies, "identity_get", "Get the
|
|
7143
|
+
registerProductTool(server, dependencies, "identity_get", "Get the ohmyho.st customer/agent identity this call acts as: user, organization and, in context, the saved login or OHMYHOST_TOKEN that supplied it. Compare it with the user and organization the customer named before any change. This does not authenticate the hosted application's end users or provision a customer AuthKit tenant; application authentication is the customer's chosen integration.", external_exports.object({}), (client2, _input, signal) => client2.getCurrentIdentity(signal));
|
|
5960
7144
|
registerProductTool(server, dependencies, "project_handle_check", "Check whether a project address is free before offering it to the customer. A handle is one to five lowercase words of letters and digits joined by single hyphens, three to fifty-nine characters, and never a reserved word such as admin, api, dev or www; it becomes <handle>.check.omh.st for Prod and dev-<handle>.check.omh.st for Dev. The answer names why a handle cannot be used and returns free alternatives, so offer one of those instead of guessing again. Check the name here first, then move an existing project onto it with project_handle_set.", external_exports.object({ handle: external_exports.string().min(1).max(120) }), (client2, input) => client2.checkProjectHandle({ handle: input.handle }));
|
|
5961
7145
|
registerProductTool(server, dependencies, "project_handle_set", "Move a project to an address the customer chose, after project_handle_check said it is free. The Dev and Prod gateways are re-published at the new address and it is stored only once both serve it; the previous address stops answering and anyone may claim it, so a link already shared stops working. Needs the project's current ETag from project_status and one idempotency key; reuse the same key after an uncertain answer. Refused while another operation is running for the project, and refused for an address that is taken, unusable, or the one the project already has. Returns an operation to follow with operation_get.", external_exports.object({
|
|
5962
7146
|
project_id: identifier2,
|
|
@@ -6019,6 +7203,12 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
6019
7203
|
mode: input.mode,
|
|
6020
7204
|
idempotencyKey: input.idempotency_key
|
|
6021
7205
|
}), destructiveAnnotations());
|
|
7206
|
+
registerProductTool(server, dependencies, "powered_by_flag_get", 'Read whether the production site shows the opt-in "Powered by ohmyho.st" flag.', external_exports.object({ project_id: identifier2 }), (client2, input) => client2.getPoweredByFlag(input.project_id));
|
|
7207
|
+
registerProductTool(server, dependencies, "powered_by_flag_set", `Owner only, ask the human first: show or hide a small "Powered by ohmyho.st" flag on the right edge of the production site. While it is on, a Free workspace may connect its own domain to this project free of the domain fee, and each Paid period adds 250 credits. Hiding it is refused while a Free workspace's domain depends on it. Replay the same key and value after uncertainty to get the first answer without switching again; every new switch needs a new key.`, external_exports.object({ project_id: identifier2, enabled: external_exports.boolean(), idempotency_key: idempotencyKey }), (client2, input) => client2.setPoweredByFlag({
|
|
7208
|
+
projectId: input.project_id,
|
|
7209
|
+
enabled: input.enabled,
|
|
7210
|
+
idempotencyKey: input.idempotency_key
|
|
7211
|
+
}), mutationAnnotations());
|
|
6022
7212
|
registerProductTool(server, dependencies, "project_dev_share_link_rotate", "Owner only: replace the persistent Dev link and immediately revoke old links and sessions. Repeat the same key after uncertainty.", external_exports.object({ project_id: identifier2, idempotency_key: idempotencyKey }), (client2, input) => client2.rotateDevShareLink({
|
|
6023
7213
|
projectId: input.project_id,
|
|
6024
7214
|
idempotencyKey: input.idempotency_key
|
|
@@ -6032,8 +7222,8 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
6032
7222
|
organizationId: input.organization_id,
|
|
6033
7223
|
idempotencyKey: input.idempotency_key
|
|
6034
7224
|
}), mutationAnnotations());
|
|
6035
|
-
registerProductTool(server, dependencies, "github_status", "Read this workspace's GitHub connection. If not_connected or revoked, an Owner or Admin must run github_connect. A connected installation covers only repositories selected in its settings.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getGithubConnection(input.organization_id));
|
|
6036
|
-
registerProductTool(server, dependencies, "source_link", "Link a repository covered by the workspace GitHub connection. Call github_status first and github_connect once if needed. This returns an operation without another browser consent and never starts a build. Wait for that operation before planning a deploy. If repository access is missing, update the installation using the returned settings action, then retry the same project and key. Never ask for an installation ID or provider token.", external_exports.object({
|
|
7225
|
+
registerProductTool(server, dependencies, "github_status", "Read this workspace's GitHub connection. If not_connected or revoked, an Owner or Admin must run github_connect. A connected installation covers only repositories selected in its settings. Each workspace has its own connection, so the same repository can be connected and linked in the workspaces of separate accounts.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getGithubConnection(input.organization_id));
|
|
7226
|
+
registerProductTool(server, dependencies, "source_link", "Link a repository covered by the workspace GitHub connection. Call github_status first and github_connect once if needed. This returns an operation without another browser consent and never starts a build. Wait for that operation before planning a deploy. If repository access is missing, update the installation using the returned settings action, then retry the same project and key. Never ask for an installation ID or provider token. Errors name the account the call ran as (acting_as): resource_not_found means that account cannot see the project (use the login of the account that owns it), github_connection_required means that workspace has no GitHub connection yet, and repository_not_installed means its GitHub App installation does not cover the repository.", external_exports.object({
|
|
6037
7227
|
project_id: identifier2,
|
|
6038
7228
|
repository_owner: identifier2,
|
|
6039
7229
|
repository_name: identifier2,
|
|
@@ -6069,7 +7259,7 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
6069
7259
|
...input.limit === void 0 ? {} : { limit: input.limit }
|
|
6070
7260
|
}));
|
|
6071
7261
|
registerProductTool(server, dependencies, "deployment_get", "Get one deployment", external_exports.object({ project_id: identifier2, deployment_id: identifier2 }), (client2, input) => client2.getDeployment({ projectId: input.project_id, deploymentId: input.deployment_id }));
|
|
6072
|
-
registerProductTool(server, dependencies, "deployment_logs", "List the newest normalized diagnostics of one deployment (build, control, runtime and function failures with catalog codes). A BUILD_FAILED item carries excerpt: the sanitized tail of the customer's own install/build output, newest lines last, with excerpt_truncated when earlier output was omitted. Read
|
|
7262
|
+
registerProductTool(server, dependencies, "deployment_logs", "List the newest normalized diagnostics of one deployment (build, control, runtime and function failures with catalog codes). A failed operation_get names the deployment as deployment_id. A BUILD_FAILED item carries excerpt: the sanitized tail of the customer's own install/build output, newest lines last, with excerpt_truncated when earlier output was omitted. A HEALTH_CHECK_FAILED item carries the probed route and status_code and, only for a project owner, excerpt: the head (at most 4096 characters, control characters removed, never a header) of what the app answered. The probe is a cookieless GET that follows no redirect, 5 s per try and up to four tries, so a 3xx or an empty 503 is unhealthy too. Read the item before changing source; scheduled runs are in function_runs_list, not here.", external_exports.object({
|
|
6073
7263
|
project_id: identifier2,
|
|
6074
7264
|
deployment_id: identifier2,
|
|
6075
7265
|
limit: external_exports.number().int().min(1).max(100).default(100)
|
|
@@ -6078,7 +7268,7 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
6078
7268
|
deploymentId: input.deployment_id,
|
|
6079
7269
|
limit: input.limit
|
|
6080
7270
|
}));
|
|
6081
|
-
registerProductTool(server, dependencies, "operation_get", "Get durable operation status and current deployment progress/reconciliation guidance. Follow progress.phase and progress.suggested_action. waiting_for_mail requires mail_domain_status now for the current verification issue and DNS records; publishing means the build completed but runtime preparation/publication is unfinished. Poll this operation after progress.next_poll_after_seconds. A queued/running operation with reconciliation.state=required needs one confirmed operation_reconcile using the same operation; pending means poll this operation after 60 seconds. Never infer deployment success from a completed reconciliation attempt or start another build to recover it.", external_exports.object({ operation_id: identifier2 }), (client2, input) => client2.getOperation(input.operation_id));
|
|
7271
|
+
registerProductTool(server, dependencies, "operation_get", "Get durable operation status and current deployment progress/reconciliation guidance. Follow progress.phase and progress.suggested_action. waiting_for_mail requires mail_domain_status now for the current verification issue and DNS records; publishing means the build completed but runtime preparation/publication is unfinished. Poll this operation after progress.next_poll_after_seconds. A queued/running operation with reconciliation.state=required needs one confirmed operation_reconcile using the same operation; pending means poll this operation after 60 seconds. Never infer deployment success from a completed reconciliation attempt or start another build to recover it. A deploy, promotion or rollback names its deployment_id in every state; when state is failed, read that deployment with deployment_logs and follow error.suggested_action before changing source.", external_exports.object({ operation_id: identifier2 }), (client2, input) => client2.getOperation(input.operation_id));
|
|
6082
7272
|
registerProductTool(server, dependencies, "operation_logs", "Read available operation events for at most ten seconds, stopping earlier at max_events or a terminal event. This is a bounded snapshot, not a wait for deployment completion. Use operation_get for current progress and keep the same operation. Stream failures are errors, not empty logs.", external_exports.object({
|
|
6083
7273
|
operation_id: identifier2,
|
|
6084
7274
|
max_events: external_exports.number().int().min(1).max(100).default(50)
|
|
@@ -6251,31 +7441,33 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
6251
7441
|
name: input.name,
|
|
6252
7442
|
idempotencyKey: input.idempotency_key
|
|
6253
7443
|
}), destructiveAnnotations());
|
|
6254
|
-
server
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
7444
|
+
registerProductTool(server, dependencies, "secret_set_command", "Return the stdin-only CLI command for setting a secret; the value never enters MCP. The call runs as the chosen login and first reads the project, so an account that cannot see it answers resource_not_found. The command names that login with --profile-name plus its user and organization (--profile-user, --profile-organization), so a login of the same name that belongs to anyone else is refused, for example on another computer; a server with OHMYHOST_TOKEN instead names its key's user and organization with --token-user and --token-organization, and the CLI then runs only with an OHMYHOST_TOKEN of that account. Either way the later write runs as exactly this account or not at all (acting_as shows which).", external_exports.object({
|
|
7445
|
+
project_id: identifier2,
|
|
7446
|
+
environment_id: identifier2,
|
|
7447
|
+
name: secretName,
|
|
7448
|
+
idempotency_key: idempotencyKey
|
|
7449
|
+
}), async (client2, input, signal) => {
|
|
7450
|
+
await client2.getProject(input.project_id);
|
|
7451
|
+
const account = await handoverAccount(client2, signal);
|
|
7452
|
+
return {
|
|
7453
|
+
command: [
|
|
7454
|
+
`${commandPrefix} secret set`,
|
|
7455
|
+
shellQuote(input.name),
|
|
7456
|
+
"--project",
|
|
7457
|
+
shellQuote(input.project_id),
|
|
7458
|
+
"--environment",
|
|
7459
|
+
shellQuote(input.environment_id),
|
|
7460
|
+
"--idempotency-key",
|
|
7461
|
+
shellQuote(input.idempotency_key),
|
|
7462
|
+
...account.flags,
|
|
7463
|
+
"--stdin",
|
|
7464
|
+
"--wait",
|
|
7465
|
+
"--json"
|
|
7466
|
+
].join(" "),
|
|
7467
|
+
acting_as: client2.actingAs?.() ?? null,
|
|
7468
|
+
instruction: `Pass the secret value on stdin in a local terminal; ${account.runs}. Never place the value or a key in MCP arguments, prompts, command-line arguments, source, or logs.`
|
|
7469
|
+
};
|
|
7470
|
+
});
|
|
6279
7471
|
registerProductTool(server, dependencies, "rollback_plan", "Plan a rollback", external_exports.object({ project_id: identifier2, deployment_id: identifier2 }), (client2, input) => client2.planRollback({ projectId: input.project_id, deploymentId: input.deployment_id }));
|
|
6280
7472
|
registerProductTool(server, dependencies, "rollback_execute", "Execute a reviewed rollback", external_exports.object({
|
|
6281
7473
|
project_id: identifier2,
|
|
@@ -6304,11 +7496,20 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
6304
7496
|
}), destructiveAnnotations());
|
|
6305
7497
|
return server;
|
|
6306
7498
|
}
|
|
6307
|
-
function registerProductTool(server, dependencies, name, description,
|
|
7499
|
+
function registerProductTool(server, dependencies, name, description, schema, execute, annotations = readAnnotations(), selection = (input) => {
|
|
7500
|
+
const organizationId = input["organization_id"];
|
|
7501
|
+
return {
|
|
7502
|
+
...input.profile_name === void 0 ? {} : { name: input.profile_name },
|
|
7503
|
+
...typeof organizationId === "string" ? { organizationId } : {}
|
|
7504
|
+
};
|
|
7505
|
+
}) {
|
|
7506
|
+
const inputSchema = schema.extend({ profile_name: profileName });
|
|
6308
7507
|
const callback = (async (input, context) => {
|
|
6309
7508
|
const parsed = inputSchema.parse(input);
|
|
7509
|
+
let client2;
|
|
6310
7510
|
try {
|
|
6311
|
-
|
|
7511
|
+
client2 = await dependencies.authenticatedClient(context.mcpReq.signal, selection(parsed));
|
|
7512
|
+
const result = toolResult(await execute(client2, parsed, context.mcpReq.signal));
|
|
6312
7513
|
const scope = parsed;
|
|
6313
7514
|
if (typeof scope["project_id"] === "string" && identifier2.safeParse(scope["project_id"]).success)
|
|
6314
7515
|
result.content.push({
|
|
@@ -6320,48 +7521,106 @@ function registerProductTool(server, dependencies, name, description, inputSchem
|
|
|
6320
7521
|
});
|
|
6321
7522
|
return result;
|
|
6322
7523
|
} catch (error) {
|
|
6323
|
-
|
|
6324
|
-
try {
|
|
6325
|
-
safe = error instanceof Error && error.name === "InteractiveSessionRequiredError" ? {
|
|
6326
|
-
code: "interactive_login_required",
|
|
6327
|
-
retryable: false,
|
|
6328
|
-
suggestedAction: `A user API token cannot create, list or select a workspace. Run ${resolveProductCliEnvironment(dependencies.environment).commandPrefix} login --json in a process without OHMYHOST_TOKEN, then retry.`
|
|
6329
|
-
} : error instanceof Error && error.message.startsWith("ORGANIZATION_NOT_FOUND:") ? {
|
|
6330
|
-
code: "organization_not_found",
|
|
6331
|
-
retryable: false,
|
|
6332
|
-
suggestedAction: "Call organization_list and choose one of the returned workspace identifiers. Do not create another workspace to recover."
|
|
6333
|
-
} : error instanceof OperationEventsUnavailableError ? {
|
|
6334
|
-
code: "operation_events_unavailable",
|
|
6335
|
-
retryable: true,
|
|
6336
|
-
suggestedAction: "Read operation_get for current status, then retry operation_logs for this same operation. Do not submit another deployment to recover logs."
|
|
6337
|
-
} : error instanceof Error && error.message.startsWith("EXPORT_PASSWORD_FILE_INVALID:") ? {
|
|
6338
|
-
code: "export_password_file_invalid",
|
|
6339
|
-
retryable: false,
|
|
6340
|
-
suggestedAction: "Choose an existing private UTF-8 password file of 1\u20131024 bytes. The user retains the file and password. Do not paste the password into MCP arguments."
|
|
6341
|
-
} : parseSafeProblem(error);
|
|
6342
|
-
} catch {
|
|
6343
|
-
safe = {
|
|
6344
|
-
code: "client_request_failed",
|
|
6345
|
-
retryable: false,
|
|
6346
|
-
suggestedAction: "Check the connection and run 'ohmyhost login' if authentication expired. Inspect the existing operation before resubmitting any mutation."
|
|
6347
|
-
};
|
|
6348
|
-
}
|
|
6349
|
-
return {
|
|
6350
|
-
...toolResult({
|
|
6351
|
-
error: {
|
|
6352
|
-
code: safe.code,
|
|
6353
|
-
retryable: safe.retryable,
|
|
6354
|
-
suggested_action: safe.suggestedAction,
|
|
6355
|
-
...safe.requestId === void 0 ? {} : { request_id: safe.requestId },
|
|
6356
|
-
...safe.retryAfterSeconds === void 0 ? {} : { retry_after_seconds: safe.retryAfterSeconds }
|
|
6357
|
-
}
|
|
6358
|
-
}),
|
|
6359
|
-
isError: true
|
|
6360
|
-
};
|
|
7524
|
+
return toolError(error, dependencies, client2?.actingAs?.());
|
|
6361
7525
|
}
|
|
6362
7526
|
});
|
|
6363
7527
|
server.registerTool(name, { description, inputSchema, annotations }, callback);
|
|
6364
7528
|
}
|
|
7529
|
+
async function handoverAccount(client2, signal) {
|
|
7530
|
+
const profile = client2.actingAs?.()?.profile ?? null;
|
|
7531
|
+
if (profile !== null) {
|
|
7532
|
+
if (profile.organization_id === null)
|
|
7533
|
+
throw new ProfileSelectionError("profile_context_mismatch", 2, `The saved login ${profile.name} has no organization, so no command can be tied to its account. Nothing was sent.`);
|
|
7534
|
+
return {
|
|
7535
|
+
flags: [
|
|
7536
|
+
"--profile-name",
|
|
7537
|
+
shellQuote(profile.name),
|
|
7538
|
+
"--profile-user",
|
|
7539
|
+
shellQuote(profile.user_id),
|
|
7540
|
+
"--profile-organization",
|
|
7541
|
+
shellQuote(profile.organization_id)
|
|
7542
|
+
],
|
|
7543
|
+
runs: `the command runs only as the saved login it names and only while that login belongs to user ${profile.user_id} in organization ${profile.organization_id}, so a login of the same name that belongs to anyone else, for example on another computer, is refused before anything is read or sent`
|
|
7544
|
+
};
|
|
7545
|
+
}
|
|
7546
|
+
const report = await client2.getCurrentIdentity(signal);
|
|
7547
|
+
const identity = parseCurrentIdentity({
|
|
7548
|
+
actor_id: report.actor_id,
|
|
7549
|
+
organization_ids: report.organization_ids
|
|
7550
|
+
});
|
|
7551
|
+
const userId = identity.actor_id.startsWith("user:") ? identity.actor_id.slice(5) : "";
|
|
7552
|
+
const [organizationId, ...others] = identity.organization_ids;
|
|
7553
|
+
if (!isProfileUserId(userId) || organizationId === void 0 || others.length > 0)
|
|
7554
|
+
throw new ProfileSelectionError("environment_token_context_mismatch", 2, "This server's OHMYHOST_TOKEN does not belong to one user in one organization, so no command can be tied to its account. Nothing was sent.");
|
|
7555
|
+
return {
|
|
7556
|
+
flags: ["--token-user", shellQuote(userId), "--token-organization", shellQuote(organizationId)],
|
|
7557
|
+
runs: `run it only where OHMYHOST_TOKEN holds a key of user ${userId} in organization ${organizationId}, loaded from its private env file; it refuses a saved login and any other account's key before anything is sent`
|
|
7558
|
+
};
|
|
7559
|
+
}
|
|
7560
|
+
function fixedOrganizationAction(error, commandPrefix) {
|
|
7561
|
+
return `This saved login stays in its organization. Add a login for the other workspace with ${commandPrefix} login --organization ${error.organization.id} --user ${error.profile.userId} --json, then pass its profile_name.`;
|
|
7562
|
+
}
|
|
7563
|
+
function toolError(error, dependencies, actingAs) {
|
|
7564
|
+
let safe;
|
|
7565
|
+
try {
|
|
7566
|
+
safe = error instanceof Error && error.name === "ProfileSelectionError" ? {
|
|
7567
|
+
code: error.code,
|
|
7568
|
+
retryable: false,
|
|
7569
|
+
suggestedAction: error.suggestedAction
|
|
7570
|
+
} : error instanceof Error && error.name === "ProfileLimitError" ? {
|
|
7571
|
+
code: "profile_limit_reached",
|
|
7572
|
+
retryable: false,
|
|
7573
|
+
suggestedAction: profileLimitAction(resolveProductCliEnvironment(dependencies.environment).commandPrefix)
|
|
7574
|
+
} : error instanceof Error && error.name === "ProfileOrganizationFixedError" ? {
|
|
7575
|
+
code: "profile_organization_fixed",
|
|
7576
|
+
retryable: false,
|
|
7577
|
+
suggestedAction: fixedOrganizationAction(error, resolveProductCliEnvironment(dependencies.environment).commandPrefix)
|
|
7578
|
+
} : error instanceof Error && error.name === "AccountVerificationError" ? {
|
|
7579
|
+
code: "login_verification_failed",
|
|
7580
|
+
retryable: true,
|
|
7581
|
+
suggestedAction: `The signed-in account could not be verified; nothing was saved. Run ${resolveProductCliEnvironment(dependencies.environment).commandPrefix} login --json again.`
|
|
7582
|
+
} : error instanceof Error && error.name === "CredentialStoreUnavailableError" ? {
|
|
7583
|
+
code: "credential_store_unavailable",
|
|
7584
|
+
retryable: true,
|
|
7585
|
+
suggestedAction: "Unlock or repair this computer's credential store and retry. Saved logins were not changed."
|
|
7586
|
+
} : error instanceof Error && error.name === "InteractiveSessionRequiredError" ? {
|
|
7587
|
+
code: "interactive_login_required",
|
|
7588
|
+
retryable: false,
|
|
7589
|
+
suggestedAction: `A user API token cannot create, list or select a workspace. Run ${resolveProductCliEnvironment(dependencies.environment).commandPrefix} login --json in a process without OHMYHOST_TOKEN, then retry.`
|
|
7590
|
+
} : error instanceof Error && error.message.startsWith("ORGANIZATION_NOT_FOUND:") ? {
|
|
7591
|
+
code: "organization_not_found",
|
|
7592
|
+
retryable: false,
|
|
7593
|
+
suggestedAction: "Call organization_list and choose one of the returned workspace identifiers. Do not create another workspace to recover."
|
|
7594
|
+
} : error instanceof OperationEventsUnavailableError ? {
|
|
7595
|
+
code: "operation_events_unavailable",
|
|
7596
|
+
retryable: true,
|
|
7597
|
+
suggestedAction: "Read operation_get for current status, then retry operation_logs for this same operation. Do not submit another deployment to recover logs."
|
|
7598
|
+
} : error instanceof Error && error.message.startsWith("EXPORT_PASSWORD_FILE_INVALID:") ? {
|
|
7599
|
+
code: "export_password_file_invalid",
|
|
7600
|
+
retryable: false,
|
|
7601
|
+
suggestedAction: "Choose an existing private UTF-8 password file of 1\u20131024 bytes. The user retains the file and password. Do not paste the password into MCP arguments."
|
|
7602
|
+
} : parseSafeProblem(error);
|
|
7603
|
+
} catch {
|
|
7604
|
+
safe = {
|
|
7605
|
+
code: "client_request_failed",
|
|
7606
|
+
retryable: false,
|
|
7607
|
+
suggestedAction: "Check the connection and run 'ohmyhost login' if authentication expired. Inspect the existing operation before resubmitting any mutation."
|
|
7608
|
+
};
|
|
7609
|
+
}
|
|
7610
|
+
return {
|
|
7611
|
+
...toolResult({
|
|
7612
|
+
error: {
|
|
7613
|
+
code: safe.code,
|
|
7614
|
+
retryable: safe.retryable,
|
|
7615
|
+
suggested_action: safe.suggestedAction,
|
|
7616
|
+
...safe.requestId === void 0 ? {} : { request_id: safe.requestId },
|
|
7617
|
+
...safe.retryAfterSeconds === void 0 ? {} : { retry_after_seconds: safe.retryAfterSeconds },
|
|
7618
|
+
...actingAs !== void 0 && ACCOUNT_SENSITIVE_PROBLEMS.has(safe.code) ? { acting_as: actingAs } : {}
|
|
7619
|
+
}
|
|
7620
|
+
}),
|
|
7621
|
+
isError: true
|
|
7622
|
+
};
|
|
7623
|
+
}
|
|
6365
7624
|
function toolResult(result) {
|
|
6366
7625
|
const serialized = JSON.stringify(result);
|
|
6367
7626
|
return {
|
|
@@ -6392,11 +7651,17 @@ function destructiveAnnotations() {
|
|
|
6392
7651
|
// apps/mcp/dist/stdio-main.js
|
|
6393
7652
|
var environment = {
|
|
6394
7653
|
...process.env["OHMYHOST_ENVIRONMENT"] === void 0 ? {} : { OHMYHOST_ENVIRONMENT: process.env["OHMYHOST_ENVIRONMENT"] },
|
|
6395
|
-
...process.env["OHMYHOST_TOKEN"] === void 0 ? {} : { OHMYHOST_TOKEN: process.env["OHMYHOST_TOKEN"] }
|
|
7654
|
+
...process.env["OHMYHOST_TOKEN"] === void 0 ? {} : { OHMYHOST_TOKEN: process.env["OHMYHOST_TOKEN"] },
|
|
7655
|
+
...process.env["OHMYHOST_PROFILE"] === void 0 ? {} : { OHMYHOST_PROFILE: process.env["OHMYHOST_PROFILE"] }
|
|
6396
7656
|
};
|
|
6397
7657
|
resolveProductCliEnvironment(environment);
|
|
6398
7658
|
serveStdio(() => createLocalOhmyhostMcpServer({
|
|
6399
7659
|
environment,
|
|
6400
|
-
|
|
7660
|
+
// Every tool call chooses its own saved login; nothing this process remembers can retarget it.
|
|
7661
|
+
authenticatedClient: (signal, request) => createAuthenticatedLocalMcpClient(signal, {
|
|
7662
|
+
environment,
|
|
7663
|
+
...request === void 0 ? {} : { request }
|
|
7664
|
+
}),
|
|
7665
|
+
listProfiles: (signal) => listSavedProfiles(signal, { environment })
|
|
6401
7666
|
}), { onerror: (error) => process.stderr.write(`${error.message}
|
|
6402
7667
|
`) });
|