@graph8/sdk 0.13.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.mjs CHANGED
@@ -1211,10 +1211,282 @@ var createAppsClient = (apiKey, apiUrl) => {
1211
1211
  };
1212
1212
  };
1213
1213
 
1214
- // src/fields.ts
1214
+ // src/appPlatform.ts
1215
1215
  var DEFAULT_API18 = "https://be.graph8.com";
1216
- var createFieldsClient = (apiKey, apiUrl) => {
1216
+ var createAppPlatformClient = (apiKey, apiUrl) => {
1217
1217
  const baseUrl = apiUrl || DEFAULT_API18;
1218
+ const unwrap = (resp) => resp.data ?? resp;
1219
+ return {
1220
+ // ---- source binding -------------------------------------------------
1221
+ /**
1222
+ * Bind the repository an app builds from.
1223
+ *
1224
+ * `repo_url` must be fetchable -- `https://`, `ssh://` or `git@`, with no
1225
+ * whitespace. A `file://` or bare path is refused with 422, because a build
1226
+ * that can read the builder's filesystem is a build that can read ours.
1227
+ *
1228
+ * `credential_ref` is a POINTER into your secret manager, not a token.
1229
+ */
1230
+ async setSource(appId, params) {
1231
+ const resp = await request(
1232
+ baseUrl,
1233
+ `/api/v1/apps/${appId}/source`,
1234
+ apiKey,
1235
+ {
1236
+ method: "PUT",
1237
+ body: {
1238
+ repo_url: params.repo_url,
1239
+ provider: params.provider,
1240
+ default_branch: params.default_branch ?? null,
1241
+ credential_ref: params.credential_ref ?? null
1242
+ }
1243
+ }
1244
+ );
1245
+ return unwrap(resp);
1246
+ },
1247
+ /** Unbind the source. Returns the full app with every source field null. */
1248
+ async clearSource(appId) {
1249
+ const resp = await request(
1250
+ baseUrl,
1251
+ `/api/v1/apps/${appId}/source`,
1252
+ apiKey,
1253
+ { method: "DELETE" }
1254
+ );
1255
+ return unwrap(resp);
1256
+ },
1257
+ // ---- deployments ----------------------------------------------------
1258
+ /** Every deployment for this app, newest first. Never 404s for an app with none. */
1259
+ async listDeployments(appId) {
1260
+ return request(baseUrl, `/api/v1/apps/${appId}/deployments`, apiKey);
1261
+ },
1262
+ /**
1263
+ * Queue a deployment. Returns `201` with `status: "queued"` -- nothing builds
1264
+ * as a side effect of this call; the build controller picks it up.
1265
+ *
1266
+ * NOT idempotent: two identical calls create two deployments.
1267
+ */
1268
+ async deploy(appId, params) {
1269
+ const body = { source_ref: params.source_ref };
1270
+ if (params.schema_version_id) body.schema_version_id = params.schema_version_id;
1271
+ const resp = await request(
1272
+ baseUrl,
1273
+ `/api/v1/apps/${appId}/deployments`,
1274
+ apiKey,
1275
+ { method: "POST", body }
1276
+ );
1277
+ return unwrap(resp);
1278
+ },
1279
+ /** Fetch one deployment. The polling endpoint for a build loop. */
1280
+ async getDeployment(appId, deploymentId) {
1281
+ const resp = await request(
1282
+ baseUrl,
1283
+ `/api/v1/apps/${appId}/deployments/${deploymentId}`,
1284
+ apiKey
1285
+ );
1286
+ return unwrap(resp);
1287
+ },
1288
+ /**
1289
+ * The deployment currently serving traffic, or `null`.
1290
+ *
1291
+ * `null` is a real answer with a 200, not a 404: "this app has never shipped"
1292
+ * is information, while a 404 would read as "no such app".
1293
+ */
1294
+ async activeDeployment(appId) {
1295
+ const resp = await request(
1296
+ baseUrl,
1297
+ `/api/v1/apps/${appId}/deployments/active`,
1298
+ apiKey
1299
+ );
1300
+ return resp.data ?? null;
1301
+ },
1302
+ /**
1303
+ * Promote a built deployment to serve traffic. Anything it displaces moves to
1304
+ * `rolled_back` in the same transaction, so there is never a moment with two
1305
+ * live deployments.
1306
+ *
1307
+ * `409` when the state machine forbids it -- a deployment cannot become
1308
+ * `deployed` without having been built, and a `failed` one cannot be revived.
1309
+ * A retry is a new deployment, not a resurrection.
1310
+ */
1311
+ async promote(appId, deploymentId, imageDigest) {
1312
+ const resp = await request(
1313
+ baseUrl,
1314
+ `/api/v1/apps/${appId}/deployments/${deploymentId}/promote`,
1315
+ apiKey,
1316
+ { method: "POST", body: { image_digest: imageDigest } }
1317
+ );
1318
+ return unwrap(resp);
1319
+ },
1320
+ /** Roll back a deployment that is currently serving. Only a `deployed` one may be. */
1321
+ async rollback(appId, deploymentId) {
1322
+ const resp = await request(
1323
+ baseUrl,
1324
+ `/api/v1/apps/${appId}/deployments/${deploymentId}/rollback`,
1325
+ apiKey,
1326
+ { method: "POST", body: {} }
1327
+ );
1328
+ return unwrap(resp);
1329
+ },
1330
+ // ---- logs -----------------------------------------------------------
1331
+ /**
1332
+ * Why a build failed. Returns every step of the build pod in the order
1333
+ * Kubernetes runs them; a step that has not started yet is omitted rather
1334
+ * than returned empty.
1335
+ *
1336
+ * An empty `containers` list is not an error -- build pods are reaped an hour
1337
+ * after they finish, so logs for an older deployment are genuinely gone.
1338
+ * `last_error_sanitized` on the deployment is what survives.
1339
+ *
1340
+ * `503` means graph8 could not reach the cluster, which is deliberately
1341
+ * different from an empty `200`: one means we could not look, the other means
1342
+ * your build produced no output.
1343
+ */
1344
+ async deploymentLogs(appId, deploymentId, tailLines) {
1345
+ const resp = await request(
1346
+ baseUrl,
1347
+ `/api/v1/apps/${appId}/deployments/${deploymentId}/logs`,
1348
+ apiKey,
1349
+ { query: tailLines === void 0 ? void 0 : { tail_lines: tailLines } }
1350
+ );
1351
+ return unwrap(resp);
1352
+ },
1353
+ /**
1354
+ * What the running app is printing. The app's own pods only -- the per-app
1355
+ * egress proxy shares the namespace and is deliberately excluded.
1356
+ *
1357
+ * Empty until a deployment reaches `deployed`.
1358
+ */
1359
+ async logs(appId, tailLines) {
1360
+ const resp = await request(
1361
+ baseUrl,
1362
+ `/api/v1/apps/${appId}/logs`,
1363
+ apiKey,
1364
+ { query: tailLines === void 0 ? void 0 : { tail_lines: tailLines } }
1365
+ );
1366
+ return unwrap(resp);
1367
+ },
1368
+ // ---- domains --------------------------------------------------------
1369
+ /** Every hostname claimed for this app, whatever its verification state. */
1370
+ async listDomains(appId) {
1371
+ return request(baseUrl, `/api/v1/apps/${appId}/domains`, apiKey);
1372
+ },
1373
+ /**
1374
+ * Claim a hostname and get the TXT record that proves you own it.
1375
+ *
1376
+ * Returns `201`, and the domain is NESTED at `data.domain` -- this is the one
1377
+ * route on the surface whose payload is not the record itself. Hostnames are
1378
+ * globally unique, so a host another app holds is refused.
1379
+ */
1380
+ async claimDomain(appId, hostname) {
1381
+ const resp = await request(
1382
+ baseUrl,
1383
+ `/api/v1/apps/${appId}/domains`,
1384
+ apiKey,
1385
+ { method: "POST", body: { hostname } }
1386
+ );
1387
+ return unwrap(resp);
1388
+ },
1389
+ /**
1390
+ * Check DNS for the TXT record and advance the domain to `verified`.
1391
+ *
1392
+ * Idempotent: verifying an already-verified domain re-checks and stays
1393
+ * verified, so it is safe to re-run after a DNS change. Send no body -- the
1394
+ * record in DNS is the payload.
1395
+ */
1396
+ async verifyDomain(appId, hostname) {
1397
+ const resp = await request(
1398
+ baseUrl,
1399
+ `/api/v1/apps/${appId}/domains/${encodeURIComponent(hostname)}/verify`,
1400
+ apiKey,
1401
+ { method: "POST", body: {} }
1402
+ );
1403
+ return unwrap(resp);
1404
+ },
1405
+ /**
1406
+ * Release a claimed hostname.
1407
+ *
1408
+ * A HARD delete. Hostnames are globally unique, so a row left behind in any
1409
+ * status keeps the host burned for every other builder. Releasing one you
1410
+ * already released is a `404`, because after the first call the claim
1411
+ * genuinely does not exist.
1412
+ *
1413
+ * Returns the NORMALIZED hostname, which may differ from what you passed.
1414
+ */
1415
+ async releaseDomain(appId, hostname) {
1416
+ const resp = await request(
1417
+ baseUrl,
1418
+ `/api/v1/apps/${appId}/domains/${encodeURIComponent(hostname)}`,
1419
+ apiKey,
1420
+ { method: "DELETE" }
1421
+ );
1422
+ return unwrap(resp);
1423
+ },
1424
+ // ---- secrets --------------------------------------------------------
1425
+ /**
1426
+ * Which secrets this app declares, and when each was last rotated.
1427
+ *
1428
+ * NEVER returns a value. graph8 stores a POINTER into your secret manager and
1429
+ * has no column for the secret itself.
1430
+ */
1431
+ async listSecrets(appId) {
1432
+ return request(baseUrl, `/api/v1/apps/${appId}/secrets`, apiKey);
1433
+ },
1434
+ /**
1435
+ * Declare a secret, or rotate the pointer to it.
1436
+ *
1437
+ * `providerRef` is a REFERENCE, and the server rejects anything that looks
1438
+ * like a credential -- a value starting `bearer `, `sk-`, `ghp_`, `xox` and
1439
+ * friends is a 422. That refusal is the feature: it catches the mistake of
1440
+ * pasting the secret where its address belongs.
1441
+ */
1442
+ async putSecret(appId, secretKey, providerRef) {
1443
+ const resp = await request(
1444
+ baseUrl,
1445
+ `/api/v1/apps/${appId}/secrets/${encodeURIComponent(secretKey)}`,
1446
+ apiKey,
1447
+ { method: "PUT", body: { provider_ref: providerRef ?? null } }
1448
+ );
1449
+ return unwrap(resp);
1450
+ },
1451
+ /** Undeclare a secret. A key the app never declared is a 404, so a typo is
1452
+ * never reported as a successful removal. */
1453
+ async deleteSecret(appId, secretKey) {
1454
+ const resp = await request(
1455
+ baseUrl,
1456
+ `/api/v1/apps/${appId}/secrets/${encodeURIComponent(secretKey)}`,
1457
+ apiKey,
1458
+ { method: "DELETE" }
1459
+ );
1460
+ return unwrap(resp);
1461
+ },
1462
+ // ---- schema versions ------------------------------------------------
1463
+ /**
1464
+ * Publish a custom-object schema version. Returns `201`.
1465
+ *
1466
+ * Takes only the `objects` list, not a whole `graph8.app.yaml`: the rest of
1467
+ * that file is app metadata the control plane already holds, and accepting it
1468
+ * here would create a second place for it to disagree.
1469
+ */
1470
+ async publishSchemaVersion(appId, objects) {
1471
+ const resp = await request(
1472
+ baseUrl,
1473
+ `/api/v1/apps/${appId}/schema-versions`,
1474
+ apiKey,
1475
+ { method: "POST", body: { objects } }
1476
+ );
1477
+ return unwrap(resp);
1478
+ },
1479
+ /** Every schema version this app has published. Empty array, never 404. */
1480
+ async listSchemaVersions(appId) {
1481
+ return request(baseUrl, `/api/v1/apps/${appId}/schema-versions`, apiKey);
1482
+ }
1483
+ };
1484
+ };
1485
+
1486
+ // src/fields.ts
1487
+ var DEFAULT_API19 = "https://be.graph8.com";
1488
+ var createFieldsClient = (apiKey, apiUrl) => {
1489
+ const baseUrl = apiUrl || DEFAULT_API19;
1218
1490
  return {
1219
1491
  /** List contact fields (base + custom). Pass listId to include list-specific custom fields. */
1220
1492
  async listContactFields(listId) {
@@ -1256,9 +1528,9 @@ var createFieldsClient = (apiKey, apiUrl) => {
1256
1528
  };
1257
1529
 
1258
1530
  // src/objects.ts
1259
- var DEFAULT_API19 = "https://be.graph8.com";
1531
+ var DEFAULT_API20 = "https://be.graph8.com";
1260
1532
  var createObjectsClient = (apiKey, apiUrl) => {
1261
- const baseUrl = apiUrl || DEFAULT_API19;
1533
+ const baseUrl = apiUrl || DEFAULT_API20;
1262
1534
  const encode = (value) => encodeURIComponent(value);
1263
1535
  return {
1264
1536
  /** List the custom object types in your workspace. */
@@ -1368,9 +1640,9 @@ var createObjectsClient = (apiKey, apiUrl) => {
1368
1640
  };
1369
1641
 
1370
1642
  // src/deals.ts
1371
- var DEFAULT_API20 = "https://be.graph8.com";
1643
+ var DEFAULT_API21 = "https://be.graph8.com";
1372
1644
  var createDealsClient = (apiKey, apiUrl) => {
1373
- const baseUrl = apiUrl || DEFAULT_API20;
1645
+ const baseUrl = apiUrl || DEFAULT_API21;
1374
1646
  return {
1375
1647
  /** List all deal pipelines and their stages. */
1376
1648
  async pipelines() {
@@ -1414,9 +1686,9 @@ var createDealsClient = (apiKey, apiUrl) => {
1414
1686
  };
1415
1687
 
1416
1688
  // src/inbox.ts
1417
- var DEFAULT_API21 = "https://be.graph8.com";
1689
+ var DEFAULT_API22 = "https://be.graph8.com";
1418
1690
  var createInboxClient = (apiKey, apiUrl) => {
1419
- const baseUrl = apiUrl || DEFAULT_API21;
1691
+ const baseUrl = apiUrl || DEFAULT_API22;
1420
1692
  return {
1421
1693
  /** List inbox threads across email, SMS, and LinkedIn. */
1422
1694
  async list(params = {}) {
@@ -1469,9 +1741,9 @@ var createInboxClient = (apiKey, apiUrl) => {
1469
1741
  };
1470
1742
 
1471
1743
  // src/quotes.ts
1472
- var DEFAULT_API22 = "https://be.graph8.com";
1744
+ var DEFAULT_API23 = "https://be.graph8.com";
1473
1745
  var createQuotesClient = (apiKey, apiUrl) => {
1474
- const baseUrl = apiUrl || DEFAULT_API22;
1746
+ const baseUrl = apiUrl || DEFAULT_API23;
1475
1747
  return {
1476
1748
  /** List quotes org-wide with optional filters and pagination. */
1477
1749
  async list(params = {}) {
@@ -1543,9 +1815,9 @@ var createQuotesClient = (apiKey, apiUrl) => {
1543
1815
  };
1544
1816
 
1545
1817
  // src/pipelines.ts
1546
- var DEFAULT_API23 = "https://be.graph8.com";
1818
+ var DEFAULT_API24 = "https://be.graph8.com";
1547
1819
  var createPipelinesClient = (apiKey, apiUrl) => {
1548
- const baseUrl = apiUrl || DEFAULT_API23;
1820
+ const baseUrl = apiUrl || DEFAULT_API24;
1549
1821
  return {
1550
1822
  /** List all stage-checklist pipelines with stages, evidence, scripts. */
1551
1823
  async list() {
@@ -1627,9 +1899,9 @@ var createPipelinesClient = (apiKey, apiUrl) => {
1627
1899
  };
1628
1900
 
1629
1901
  // src/workflows.ts
1630
- var DEFAULT_API24 = "https://be.graph8.com";
1902
+ var DEFAULT_API25 = "https://be.graph8.com";
1631
1903
  var createWorkflowsClient = (apiKey, apiUrl) => {
1632
- const baseUrl = apiUrl || DEFAULT_API24;
1904
+ const baseUrl = apiUrl || DEFAULT_API25;
1633
1905
  return {
1634
1906
  /** List workflows org-wide. */
1635
1907
  async list(params = {}) {
@@ -1745,9 +2017,9 @@ var createWorkflowsClient = (apiKey, apiUrl) => {
1745
2017
  };
1746
2018
 
1747
2019
  // src/skills.ts
1748
- var DEFAULT_API25 = "https://be.graph8.com";
2020
+ var DEFAULT_API26 = "https://be.graph8.com";
1749
2021
  var createSkillsClient = (apiKey, apiUrl) => {
1750
- const baseUrl = apiUrl || DEFAULT_API25;
2022
+ const baseUrl = apiUrl || DEFAULT_API26;
1751
2023
  return {
1752
2024
  /** List skills. */
1753
2025
  async list(params = {}) {
@@ -1834,9 +2106,9 @@ var createSkillsClient = (apiKey, apiUrl) => {
1834
2106
  };
1835
2107
 
1836
2108
  // src/intent.ts
1837
- var DEFAULT_API26 = "https://be.graph8.com";
2109
+ var DEFAULT_API27 = "https://be.graph8.com";
1838
2110
  var createIntentClient = (apiKey, apiUrl) => {
1839
- const baseUrl = apiUrl || DEFAULT_API26;
2111
+ const baseUrl = apiUrl || DEFAULT_API27;
1840
2112
  const get = (path) => request(baseUrl, `/api/v1${path}`, apiKey);
1841
2113
  const post = (path, body = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "POST", body });
1842
2114
  const del = (path) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "DELETE" });
@@ -1911,9 +2183,9 @@ var createIntentClient = (apiKey, apiUrl) => {
1911
2183
  };
1912
2184
 
1913
2185
  // src/studio.ts
1914
- var DEFAULT_API27 = "https://be.graph8.com";
2186
+ var DEFAULT_API28 = "https://be.graph8.com";
1915
2187
  var createStudioClient = (apiKey, apiUrl) => {
1916
- const baseUrl = apiUrl || DEFAULT_API27;
2188
+ const baseUrl = apiUrl || DEFAULT_API28;
1917
2189
  const get = (path, params = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { query: params });
1918
2190
  const post = (path, body = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "POST", body });
1919
2191
  const patch = (path, body = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "PATCH", body });
@@ -1968,9 +2240,9 @@ var createStudioClient = (apiKey, apiUrl) => {
1968
2240
  };
1969
2241
 
1970
2242
  // src/meetings.ts
1971
- var DEFAULT_API28 = "https://be.graph8.com";
2243
+ var DEFAULT_API29 = "https://be.graph8.com";
1972
2244
  var createMeetingsClient = (apiKey, apiUrl) => {
1973
- const baseUrl = apiUrl || DEFAULT_API28;
2245
+ const baseUrl = apiUrl || DEFAULT_API29;
1974
2246
  return {
1975
2247
  /** List meetings with optional filters. Returns summary rows without transcript / analysis. */
1976
2248
  async list(params = {}) {
@@ -1985,9 +2257,9 @@ var createMeetingsClient = (apiKey, apiUrl) => {
1985
2257
  };
1986
2258
 
1987
2259
  // src/audiences.ts
1988
- var DEFAULT_API29 = "https://be.graph8.com";
2260
+ var DEFAULT_API30 = "https://be.graph8.com";
1989
2261
  var createAudiencesClient = (apiKey, apiUrl) => {
1990
- const baseUrl = apiUrl || DEFAULT_API29;
2262
+ const baseUrl = apiUrl || DEFAULT_API30;
1991
2263
  const base = "/api/v1/audience-syncs";
1992
2264
  return {
1993
2265
  /** List all audience syncs for the organization. */
@@ -2035,9 +2307,9 @@ var createAudiencesClient = (apiKey, apiUrl) => {
2035
2307
  };
2036
2308
 
2037
2309
  // src/search.ts
2038
- var DEFAULT_API30 = "https://be.graph8.com";
2310
+ var DEFAULT_API31 = "https://be.graph8.com";
2039
2311
  var createSearchClient = (apiKey, apiUrl) => {
2040
- const baseUrl = apiUrl || DEFAULT_API30;
2312
+ const baseUrl = apiUrl || DEFAULT_API31;
2041
2313
  const body = (p) => ({ filters: [], page: 1, limit: 25, ...p });
2042
2314
  return {
2043
2315
  /** Search open-data contacts by filter. */
@@ -2068,9 +2340,9 @@ var createSearchClient = (apiKey, apiUrl) => {
2068
2340
  };
2069
2341
 
2070
2342
  // src/agency.ts
2071
- var DEFAULT_API31 = "https://be.graph8.com";
2343
+ var DEFAULT_API32 = "https://be.graph8.com";
2072
2344
  var createAgencyClient = (apiKey, apiUrl) => {
2073
- const baseUrl = apiUrl || DEFAULT_API31;
2345
+ const baseUrl = apiUrl || DEFAULT_API32;
2074
2346
  return {
2075
2347
  /** Describe the agency credential: agency org + authorized client count. */
2076
2348
  async me() {
@@ -2085,9 +2357,9 @@ var createAgencyClient = (apiKey, apiUrl) => {
2085
2357
  };
2086
2358
 
2087
2359
  // src/marketplace.ts
2088
- var DEFAULT_API32 = "https://be.graph8.com";
2360
+ var DEFAULT_API33 = "https://be.graph8.com";
2089
2361
  var createMarketplaceClient = (apiKey, apiUrl) => {
2090
- const baseUrl = apiUrl || DEFAULT_API32;
2362
+ const baseUrl = apiUrl || DEFAULT_API33;
2091
2363
  const base = "/api/v1/marketplace";
2092
2364
  return {
2093
2365
  /** Your own marketplace SDR profile. */
@@ -2137,9 +2409,9 @@ var createMarketplaceClient = (apiKey, apiUrl) => {
2137
2409
  };
2138
2410
 
2139
2411
  // src/snippet.ts
2140
- var DEFAULT_API33 = "https://be.graph8.com";
2412
+ var DEFAULT_API34 = "https://be.graph8.com";
2141
2413
  var createSnippetClient = (apiKey, apiUrl) => {
2142
- const baseUrl = apiUrl || DEFAULT_API33;
2414
+ const baseUrl = apiUrl || DEFAULT_API34;
2143
2415
  return {
2144
2416
  /** Get your org's tracking snippet (write key + React/script-tag embeds + config). */
2145
2417
  async get() {
@@ -2151,7 +2423,7 @@ var createSnippetClient = (apiKey, apiUrl) => {
2151
2423
 
2152
2424
  // src/core.ts
2153
2425
  var DEFAULT_HOST = "https://t.graph8.com";
2154
- var DEFAULT_API34 = "https://be.graph8.com";
2426
+ var DEFAULT_API35 = "https://be.graph8.com";
2155
2427
  var G8 = class {
2156
2428
  constructor() {
2157
2429
  /** @internal */
@@ -2195,6 +2467,8 @@ var G8 = class {
2195
2467
  /** @internal */
2196
2468
  this._apps = null;
2197
2469
  /** @internal */
2470
+ this._appPlatform = null;
2471
+ /** @internal */
2198
2472
  this._objects = null;
2199
2473
  /** @internal */
2200
2474
  this._deals = null;
@@ -2238,7 +2512,7 @@ var G8 = class {
2238
2512
  debug: config.debug
2239
2513
  });
2240
2514
  }
2241
- const apiUrl = config.apiUrl || DEFAULT_API34;
2515
+ const apiUrl = config.apiUrl || DEFAULT_API35;
2242
2516
  const writeKey = config.writeKey || "";
2243
2517
  const apiKey = config.apiKey || "";
2244
2518
  if (writeKey) {
@@ -2262,6 +2536,7 @@ var G8 = class {
2262
2536
  this._tasks = createTasksClient(apiKey, apiUrl);
2263
2537
  this._fields = createFieldsClient(apiKey, apiUrl);
2264
2538
  this._apps = createAppsClient(apiKey, apiUrl);
2539
+ this._appPlatform = createAppPlatformClient(apiKey, apiUrl);
2265
2540
  this._objects = createObjectsClient(apiKey, apiUrl);
2266
2541
  this._deals = createDealsClient(apiKey, apiUrl);
2267
2542
  this._inbox = createInboxClient(apiKey, apiUrl);
@@ -2388,6 +2663,18 @@ var G8 = class {
2388
2663
  this._assertKey("apps");
2389
2664
  return this._apps;
2390
2665
  }
2666
+ /**
2667
+ * Ship a hosted app: bind a source, deploy, promote, attach a hostname, read
2668
+ * build logs (requires API key). PREVIEW.
2669
+ *
2670
+ * Separate from `apps` on purpose. `apps` is the app's IDENTITY -- create it,
2671
+ * see who installed it, what it cost. This is its LIFECYCLE, and the two have
2672
+ * different blast radii: a mistake here takes a customer's app down.
2673
+ */
2674
+ get appPlatform() {
2675
+ this._assertKey("appPlatform");
2676
+ return this._appPlatform;
2677
+ }
2391
2678
  /** Custom object types, their schema, and their records (requires API key). PREVIEW. */
2392
2679
  get objects() {
2393
2680
  this._assertKey("objects");