@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/index.mjs CHANGED
@@ -1216,10 +1216,284 @@ var createAppsClient = (apiKey, apiUrl) => {
1216
1216
  };
1217
1217
  };
1218
1218
 
1219
- // src/fields.ts
1219
+ // src/appPlatform.ts
1220
1220
  var DEFAULT_API18 = "https://be.graph8.com";
1221
- var createFieldsClient = (apiKey, apiUrl) => {
1221
+ var MIN_TAIL_LINES = 1;
1222
+ var MAX_TAIL_LINES = 2e3;
1223
+ var createAppPlatformClient = (apiKey, apiUrl) => {
1222
1224
  const baseUrl = apiUrl || DEFAULT_API18;
1225
+ const unwrap = (resp) => resp.data ?? resp;
1226
+ return {
1227
+ // ---- source binding -------------------------------------------------
1228
+ /**
1229
+ * Bind the repository an app builds from.
1230
+ *
1231
+ * `repo_url` must be fetchable -- `https://`, `ssh://` or `git@`, with no
1232
+ * whitespace. A `file://` or bare path is refused with 422, because a build
1233
+ * that can read the builder's filesystem is a build that can read ours.
1234
+ *
1235
+ * `credential_ref` is a POINTER into your secret manager, not a token.
1236
+ */
1237
+ async setSource(appId, params) {
1238
+ const resp = await request(
1239
+ baseUrl,
1240
+ `/api/v1/apps/${appId}/source`,
1241
+ apiKey,
1242
+ {
1243
+ method: "PUT",
1244
+ body: {
1245
+ repo_url: params.repo_url,
1246
+ provider: params.provider,
1247
+ default_branch: params.default_branch ?? null,
1248
+ credential_ref: params.credential_ref ?? null
1249
+ }
1250
+ }
1251
+ );
1252
+ return unwrap(resp);
1253
+ },
1254
+ /** Unbind the source. Returns the full app with every source field null. */
1255
+ async clearSource(appId) {
1256
+ const resp = await request(
1257
+ baseUrl,
1258
+ `/api/v1/apps/${appId}/source`,
1259
+ apiKey,
1260
+ { method: "DELETE" }
1261
+ );
1262
+ return unwrap(resp);
1263
+ },
1264
+ // ---- deployments ----------------------------------------------------
1265
+ /** Every deployment for this app, newest first. Never 404s for an app with none. */
1266
+ async listDeployments(appId) {
1267
+ return request(baseUrl, `/api/v1/apps/${appId}/deployments`, apiKey);
1268
+ },
1269
+ /**
1270
+ * Queue a deployment. Returns `201` with `status: "queued"` -- nothing builds
1271
+ * as a side effect of this call; the build controller picks it up.
1272
+ *
1273
+ * NOT idempotent: two identical calls create two deployments.
1274
+ */
1275
+ async deploy(appId, params) {
1276
+ const body = { source_ref: params.source_ref };
1277
+ if (params.schema_version_id) body.schema_version_id = params.schema_version_id;
1278
+ const resp = await request(
1279
+ baseUrl,
1280
+ `/api/v1/apps/${appId}/deployments`,
1281
+ apiKey,
1282
+ { method: "POST", body }
1283
+ );
1284
+ return unwrap(resp);
1285
+ },
1286
+ /** Fetch one deployment. The polling endpoint for a build loop. */
1287
+ async getDeployment(appId, deploymentId) {
1288
+ const resp = await request(
1289
+ baseUrl,
1290
+ `/api/v1/apps/${appId}/deployments/${deploymentId}`,
1291
+ apiKey
1292
+ );
1293
+ return unwrap(resp);
1294
+ },
1295
+ /**
1296
+ * The deployment currently serving traffic, or `null`.
1297
+ *
1298
+ * `null` is a real answer with a 200, not a 404: "this app has never shipped"
1299
+ * is information, while a 404 would read as "no such app".
1300
+ */
1301
+ async activeDeployment(appId) {
1302
+ const resp = await request(
1303
+ baseUrl,
1304
+ `/api/v1/apps/${appId}/deployments/active`,
1305
+ apiKey
1306
+ );
1307
+ return resp.data ?? null;
1308
+ },
1309
+ /**
1310
+ * Promote a built deployment to serve traffic. Anything it displaces moves to
1311
+ * `rolled_back` in the same transaction, so there is never a moment with two
1312
+ * live deployments.
1313
+ *
1314
+ * `409` when the state machine forbids it -- a deployment cannot become
1315
+ * `deployed` without having been built, and a `failed` one cannot be revived.
1316
+ * A retry is a new deployment, not a resurrection.
1317
+ */
1318
+ async promote(appId, deploymentId, imageDigest) {
1319
+ const resp = await request(
1320
+ baseUrl,
1321
+ `/api/v1/apps/${appId}/deployments/${deploymentId}/promote`,
1322
+ apiKey,
1323
+ { method: "POST", body: { image_digest: imageDigest } }
1324
+ );
1325
+ return unwrap(resp);
1326
+ },
1327
+ /** Roll back a deployment that is currently serving. Only a `deployed` one may be. */
1328
+ async rollback(appId, deploymentId) {
1329
+ const resp = await request(
1330
+ baseUrl,
1331
+ `/api/v1/apps/${appId}/deployments/${deploymentId}/rollback`,
1332
+ apiKey,
1333
+ { method: "POST", body: {} }
1334
+ );
1335
+ return unwrap(resp);
1336
+ },
1337
+ // ---- logs -----------------------------------------------------------
1338
+ /**
1339
+ * Why a build failed. Returns every step of the build pod in the order
1340
+ * Kubernetes runs them; a step that has not started yet is omitted rather
1341
+ * than returned empty.
1342
+ *
1343
+ * An empty `containers` list is not an error -- build pods are reaped an hour
1344
+ * after they finish, so logs for an older deployment are genuinely gone.
1345
+ * `last_error_sanitized` on the deployment is what survives.
1346
+ *
1347
+ * `503` means graph8 could not reach the cluster, which is deliberately
1348
+ * different from an empty `200`: one means we could not look, the other means
1349
+ * your build produced no output.
1350
+ */
1351
+ async deploymentLogs(appId, deploymentId, tailLines) {
1352
+ const resp = await request(
1353
+ baseUrl,
1354
+ `/api/v1/apps/${appId}/deployments/${deploymentId}/logs`,
1355
+ apiKey,
1356
+ { query: tailLines === void 0 ? void 0 : { tail_lines: tailLines } }
1357
+ );
1358
+ return unwrap(resp);
1359
+ },
1360
+ /**
1361
+ * What the running app is printing. The app's own pods only -- the per-app
1362
+ * egress proxy shares the namespace and is deliberately excluded.
1363
+ *
1364
+ * Empty until a deployment reaches `deployed`.
1365
+ */
1366
+ async logs(appId, tailLines) {
1367
+ const resp = await request(
1368
+ baseUrl,
1369
+ `/api/v1/apps/${appId}/logs`,
1370
+ apiKey,
1371
+ { query: tailLines === void 0 ? void 0 : { tail_lines: tailLines } }
1372
+ );
1373
+ return unwrap(resp);
1374
+ },
1375
+ // ---- domains --------------------------------------------------------
1376
+ /** Every hostname claimed for this app, whatever its verification state. */
1377
+ async listDomains(appId) {
1378
+ return request(baseUrl, `/api/v1/apps/${appId}/domains`, apiKey);
1379
+ },
1380
+ /**
1381
+ * Claim a hostname and get the TXT record that proves you own it.
1382
+ *
1383
+ * Returns `201`, and the domain is NESTED at `data.domain` -- this is the one
1384
+ * route on the surface whose payload is not the record itself. Hostnames are
1385
+ * globally unique, so a host another app holds is refused.
1386
+ */
1387
+ async claimDomain(appId, hostname) {
1388
+ const resp = await request(
1389
+ baseUrl,
1390
+ `/api/v1/apps/${appId}/domains`,
1391
+ apiKey,
1392
+ { method: "POST", body: { hostname } }
1393
+ );
1394
+ return unwrap(resp);
1395
+ },
1396
+ /**
1397
+ * Check DNS for the TXT record and advance the domain to `verified`.
1398
+ *
1399
+ * Idempotent: verifying an already-verified domain re-checks and stays
1400
+ * verified, so it is safe to re-run after a DNS change. Send no body -- the
1401
+ * record in DNS is the payload.
1402
+ */
1403
+ async verifyDomain(appId, hostname) {
1404
+ const resp = await request(
1405
+ baseUrl,
1406
+ `/api/v1/apps/${appId}/domains/${encodeURIComponent(hostname)}/verify`,
1407
+ apiKey,
1408
+ { method: "POST", body: {} }
1409
+ );
1410
+ return unwrap(resp);
1411
+ },
1412
+ /**
1413
+ * Release a claimed hostname.
1414
+ *
1415
+ * A HARD delete. Hostnames are globally unique, so a row left behind in any
1416
+ * status keeps the host burned for every other builder. Releasing one you
1417
+ * already released is a `404`, because after the first call the claim
1418
+ * genuinely does not exist.
1419
+ *
1420
+ * Returns the NORMALIZED hostname, which may differ from what you passed.
1421
+ */
1422
+ async releaseDomain(appId, hostname) {
1423
+ const resp = await request(
1424
+ baseUrl,
1425
+ `/api/v1/apps/${appId}/domains/${encodeURIComponent(hostname)}`,
1426
+ apiKey,
1427
+ { method: "DELETE" }
1428
+ );
1429
+ return unwrap(resp);
1430
+ },
1431
+ // ---- secrets --------------------------------------------------------
1432
+ /**
1433
+ * Which secrets this app declares, and when each was last rotated.
1434
+ *
1435
+ * NEVER returns a value. graph8 stores a POINTER into your secret manager and
1436
+ * has no column for the secret itself.
1437
+ */
1438
+ async listSecrets(appId) {
1439
+ return request(baseUrl, `/api/v1/apps/${appId}/secrets`, apiKey);
1440
+ },
1441
+ /**
1442
+ * Declare a secret, or rotate the pointer to it.
1443
+ *
1444
+ * `providerRef` is a REFERENCE, and the server rejects anything that looks
1445
+ * like a credential -- a value starting `bearer `, `sk-`, `ghp_`, `xox` and
1446
+ * friends is a 422. That refusal is the feature: it catches the mistake of
1447
+ * pasting the secret where its address belongs.
1448
+ */
1449
+ async putSecret(appId, secretKey, providerRef) {
1450
+ const resp = await request(
1451
+ baseUrl,
1452
+ `/api/v1/apps/${appId}/secrets/${encodeURIComponent(secretKey)}`,
1453
+ apiKey,
1454
+ { method: "PUT", body: { provider_ref: providerRef ?? null } }
1455
+ );
1456
+ return unwrap(resp);
1457
+ },
1458
+ /** Undeclare a secret. A key the app never declared is a 404, so a typo is
1459
+ * never reported as a successful removal. */
1460
+ async deleteSecret(appId, secretKey) {
1461
+ const resp = await request(
1462
+ baseUrl,
1463
+ `/api/v1/apps/${appId}/secrets/${encodeURIComponent(secretKey)}`,
1464
+ apiKey,
1465
+ { method: "DELETE" }
1466
+ );
1467
+ return unwrap(resp);
1468
+ },
1469
+ // ---- schema versions ------------------------------------------------
1470
+ /**
1471
+ * Publish a custom-object schema version. Returns `201`.
1472
+ *
1473
+ * Takes only the `objects` list, not a whole `graph8.app.yaml`: the rest of
1474
+ * that file is app metadata the control plane already holds, and accepting it
1475
+ * here would create a second place for it to disagree.
1476
+ */
1477
+ async publishSchemaVersion(appId, objects) {
1478
+ const resp = await request(
1479
+ baseUrl,
1480
+ `/api/v1/apps/${appId}/schema-versions`,
1481
+ apiKey,
1482
+ { method: "POST", body: { objects } }
1483
+ );
1484
+ return unwrap(resp);
1485
+ },
1486
+ /** Every schema version this app has published. Empty array, never 404. */
1487
+ async listSchemaVersions(appId) {
1488
+ return request(baseUrl, `/api/v1/apps/${appId}/schema-versions`, apiKey);
1489
+ }
1490
+ };
1491
+ };
1492
+
1493
+ // src/fields.ts
1494
+ var DEFAULT_API19 = "https://be.graph8.com";
1495
+ var createFieldsClient = (apiKey, apiUrl) => {
1496
+ const baseUrl = apiUrl || DEFAULT_API19;
1223
1497
  return {
1224
1498
  /** List contact fields (base + custom). Pass listId to include list-specific custom fields. */
1225
1499
  async listContactFields(listId) {
@@ -1261,9 +1535,9 @@ var createFieldsClient = (apiKey, apiUrl) => {
1261
1535
  };
1262
1536
 
1263
1537
  // src/objects.ts
1264
- var DEFAULT_API19 = "https://be.graph8.com";
1538
+ var DEFAULT_API20 = "https://be.graph8.com";
1265
1539
  var createObjectsClient = (apiKey, apiUrl) => {
1266
- const baseUrl = apiUrl || DEFAULT_API19;
1540
+ const baseUrl = apiUrl || DEFAULT_API20;
1267
1541
  const encode = (value) => encodeURIComponent(value);
1268
1542
  return {
1269
1543
  /** List the custom object types in your workspace. */
@@ -1373,9 +1647,9 @@ var createObjectsClient = (apiKey, apiUrl) => {
1373
1647
  };
1374
1648
 
1375
1649
  // src/deals.ts
1376
- var DEFAULT_API20 = "https://be.graph8.com";
1650
+ var DEFAULT_API21 = "https://be.graph8.com";
1377
1651
  var createDealsClient = (apiKey, apiUrl) => {
1378
- const baseUrl = apiUrl || DEFAULT_API20;
1652
+ const baseUrl = apiUrl || DEFAULT_API21;
1379
1653
  return {
1380
1654
  /** List all deal pipelines and their stages. */
1381
1655
  async pipelines() {
@@ -1419,9 +1693,9 @@ var createDealsClient = (apiKey, apiUrl) => {
1419
1693
  };
1420
1694
 
1421
1695
  // src/inbox.ts
1422
- var DEFAULT_API21 = "https://be.graph8.com";
1696
+ var DEFAULT_API22 = "https://be.graph8.com";
1423
1697
  var createInboxClient = (apiKey, apiUrl) => {
1424
- const baseUrl = apiUrl || DEFAULT_API21;
1698
+ const baseUrl = apiUrl || DEFAULT_API22;
1425
1699
  return {
1426
1700
  /** List inbox threads across email, SMS, and LinkedIn. */
1427
1701
  async list(params = {}) {
@@ -1474,9 +1748,9 @@ var createInboxClient = (apiKey, apiUrl) => {
1474
1748
  };
1475
1749
 
1476
1750
  // src/quotes.ts
1477
- var DEFAULT_API22 = "https://be.graph8.com";
1751
+ var DEFAULT_API23 = "https://be.graph8.com";
1478
1752
  var createQuotesClient = (apiKey, apiUrl) => {
1479
- const baseUrl = apiUrl || DEFAULT_API22;
1753
+ const baseUrl = apiUrl || DEFAULT_API23;
1480
1754
  return {
1481
1755
  /** List quotes org-wide with optional filters and pagination. */
1482
1756
  async list(params = {}) {
@@ -1548,9 +1822,9 @@ var createQuotesClient = (apiKey, apiUrl) => {
1548
1822
  };
1549
1823
 
1550
1824
  // src/pipelines.ts
1551
- var DEFAULT_API23 = "https://be.graph8.com";
1825
+ var DEFAULT_API24 = "https://be.graph8.com";
1552
1826
  var createPipelinesClient = (apiKey, apiUrl) => {
1553
- const baseUrl = apiUrl || DEFAULT_API23;
1827
+ const baseUrl = apiUrl || DEFAULT_API24;
1554
1828
  return {
1555
1829
  /** List all stage-checklist pipelines with stages, evidence, scripts. */
1556
1830
  async list() {
@@ -1632,9 +1906,9 @@ var createPipelinesClient = (apiKey, apiUrl) => {
1632
1906
  };
1633
1907
 
1634
1908
  // src/workflows.ts
1635
- var DEFAULT_API24 = "https://be.graph8.com";
1909
+ var DEFAULT_API25 = "https://be.graph8.com";
1636
1910
  var createWorkflowsClient = (apiKey, apiUrl) => {
1637
- const baseUrl = apiUrl || DEFAULT_API24;
1911
+ const baseUrl = apiUrl || DEFAULT_API25;
1638
1912
  return {
1639
1913
  /** List workflows org-wide. */
1640
1914
  async list(params = {}) {
@@ -1750,9 +2024,9 @@ var createWorkflowsClient = (apiKey, apiUrl) => {
1750
2024
  };
1751
2025
 
1752
2026
  // src/skills.ts
1753
- var DEFAULT_API25 = "https://be.graph8.com";
2027
+ var DEFAULT_API26 = "https://be.graph8.com";
1754
2028
  var createSkillsClient = (apiKey, apiUrl) => {
1755
- const baseUrl = apiUrl || DEFAULT_API25;
2029
+ const baseUrl = apiUrl || DEFAULT_API26;
1756
2030
  return {
1757
2031
  /** List skills. */
1758
2032
  async list(params = {}) {
@@ -1839,9 +2113,9 @@ var createSkillsClient = (apiKey, apiUrl) => {
1839
2113
  };
1840
2114
 
1841
2115
  // src/intent.ts
1842
- var DEFAULT_API26 = "https://be.graph8.com";
2116
+ var DEFAULT_API27 = "https://be.graph8.com";
1843
2117
  var createIntentClient = (apiKey, apiUrl) => {
1844
- const baseUrl = apiUrl || DEFAULT_API26;
2118
+ const baseUrl = apiUrl || DEFAULT_API27;
1845
2119
  const get = (path) => request(baseUrl, `/api/v1${path}`, apiKey);
1846
2120
  const post = (path, body = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "POST", body });
1847
2121
  const del = (path) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "DELETE" });
@@ -1916,9 +2190,9 @@ var createIntentClient = (apiKey, apiUrl) => {
1916
2190
  };
1917
2191
 
1918
2192
  // src/studio.ts
1919
- var DEFAULT_API27 = "https://be.graph8.com";
2193
+ var DEFAULT_API28 = "https://be.graph8.com";
1920
2194
  var createStudioClient = (apiKey, apiUrl) => {
1921
- const baseUrl = apiUrl || DEFAULT_API27;
2195
+ const baseUrl = apiUrl || DEFAULT_API28;
1922
2196
  const get = (path, params = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { query: params });
1923
2197
  const post = (path, body = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "POST", body });
1924
2198
  const patch = (path, body = {}) => request(baseUrl, `/api/v1${path}`, apiKey, { method: "PATCH", body });
@@ -1973,9 +2247,9 @@ var createStudioClient = (apiKey, apiUrl) => {
1973
2247
  };
1974
2248
 
1975
2249
  // src/meetings.ts
1976
- var DEFAULT_API28 = "https://be.graph8.com";
2250
+ var DEFAULT_API29 = "https://be.graph8.com";
1977
2251
  var createMeetingsClient = (apiKey, apiUrl) => {
1978
- const baseUrl = apiUrl || DEFAULT_API28;
2252
+ const baseUrl = apiUrl || DEFAULT_API29;
1979
2253
  return {
1980
2254
  /** List meetings with optional filters. Returns summary rows without transcript / analysis. */
1981
2255
  async list(params = {}) {
@@ -1990,9 +2264,9 @@ var createMeetingsClient = (apiKey, apiUrl) => {
1990
2264
  };
1991
2265
 
1992
2266
  // src/audiences.ts
1993
- var DEFAULT_API29 = "https://be.graph8.com";
2267
+ var DEFAULT_API30 = "https://be.graph8.com";
1994
2268
  var createAudiencesClient = (apiKey, apiUrl) => {
1995
- const baseUrl = apiUrl || DEFAULT_API29;
2269
+ const baseUrl = apiUrl || DEFAULT_API30;
1996
2270
  const base = "/api/v1/audience-syncs";
1997
2271
  return {
1998
2272
  /** List all audience syncs for the organization. */
@@ -2040,9 +2314,9 @@ var createAudiencesClient = (apiKey, apiUrl) => {
2040
2314
  };
2041
2315
 
2042
2316
  // src/search.ts
2043
- var DEFAULT_API30 = "https://be.graph8.com";
2317
+ var DEFAULT_API31 = "https://be.graph8.com";
2044
2318
  var createSearchClient = (apiKey, apiUrl) => {
2045
- const baseUrl = apiUrl || DEFAULT_API30;
2319
+ const baseUrl = apiUrl || DEFAULT_API31;
2046
2320
  const body = (p) => ({ filters: [], page: 1, limit: 25, ...p });
2047
2321
  return {
2048
2322
  /** Search open-data contacts by filter. */
@@ -2073,9 +2347,9 @@ var createSearchClient = (apiKey, apiUrl) => {
2073
2347
  };
2074
2348
 
2075
2349
  // src/agency.ts
2076
- var DEFAULT_API31 = "https://be.graph8.com";
2350
+ var DEFAULT_API32 = "https://be.graph8.com";
2077
2351
  var createAgencyClient = (apiKey, apiUrl) => {
2078
- const baseUrl = apiUrl || DEFAULT_API31;
2352
+ const baseUrl = apiUrl || DEFAULT_API32;
2079
2353
  return {
2080
2354
  /** Describe the agency credential: agency org + authorized client count. */
2081
2355
  async me() {
@@ -2090,9 +2364,9 @@ var createAgencyClient = (apiKey, apiUrl) => {
2090
2364
  };
2091
2365
 
2092
2366
  // src/marketplace.ts
2093
- var DEFAULT_API32 = "https://be.graph8.com";
2367
+ var DEFAULT_API33 = "https://be.graph8.com";
2094
2368
  var createMarketplaceClient = (apiKey, apiUrl) => {
2095
- const baseUrl = apiUrl || DEFAULT_API32;
2369
+ const baseUrl = apiUrl || DEFAULT_API33;
2096
2370
  const base = "/api/v1/marketplace";
2097
2371
  return {
2098
2372
  /** Your own marketplace SDR profile. */
@@ -2142,9 +2416,9 @@ var createMarketplaceClient = (apiKey, apiUrl) => {
2142
2416
  };
2143
2417
 
2144
2418
  // src/snippet.ts
2145
- var DEFAULT_API33 = "https://be.graph8.com";
2419
+ var DEFAULT_API34 = "https://be.graph8.com";
2146
2420
  var createSnippetClient = (apiKey, apiUrl) => {
2147
- const baseUrl = apiUrl || DEFAULT_API33;
2421
+ const baseUrl = apiUrl || DEFAULT_API34;
2148
2422
  return {
2149
2423
  /** Get your org's tracking snippet (write key + React/script-tag embeds + config). */
2150
2424
  async get() {
@@ -2156,7 +2430,7 @@ var createSnippetClient = (apiKey, apiUrl) => {
2156
2430
 
2157
2431
  // src/core.ts
2158
2432
  var DEFAULT_HOST = "https://t.graph8.com";
2159
- var DEFAULT_API34 = "https://be.graph8.com";
2433
+ var DEFAULT_API35 = "https://be.graph8.com";
2160
2434
  var G8 = class {
2161
2435
  constructor() {
2162
2436
  /** @internal */
@@ -2200,6 +2474,8 @@ var G8 = class {
2200
2474
  /** @internal */
2201
2475
  this._apps = null;
2202
2476
  /** @internal */
2477
+ this._appPlatform = null;
2478
+ /** @internal */
2203
2479
  this._objects = null;
2204
2480
  /** @internal */
2205
2481
  this._deals = null;
@@ -2243,7 +2519,7 @@ var G8 = class {
2243
2519
  debug: config.debug
2244
2520
  });
2245
2521
  }
2246
- const apiUrl = config.apiUrl || DEFAULT_API34;
2522
+ const apiUrl = config.apiUrl || DEFAULT_API35;
2247
2523
  const writeKey = config.writeKey || "";
2248
2524
  const apiKey = config.apiKey || "";
2249
2525
  if (writeKey) {
@@ -2267,6 +2543,7 @@ var G8 = class {
2267
2543
  this._tasks = createTasksClient(apiKey, apiUrl);
2268
2544
  this._fields = createFieldsClient(apiKey, apiUrl);
2269
2545
  this._apps = createAppsClient(apiKey, apiUrl);
2546
+ this._appPlatform = createAppPlatformClient(apiKey, apiUrl);
2270
2547
  this._objects = createObjectsClient(apiKey, apiUrl);
2271
2548
  this._deals = createDealsClient(apiKey, apiUrl);
2272
2549
  this._inbox = createInboxClient(apiKey, apiUrl);
@@ -2393,6 +2670,18 @@ var G8 = class {
2393
2670
  this._assertKey("apps");
2394
2671
  return this._apps;
2395
2672
  }
2673
+ /**
2674
+ * Ship a hosted app: bind a source, deploy, promote, attach a hostname, read
2675
+ * build logs (requires API key). PREVIEW.
2676
+ *
2677
+ * Separate from `apps` on purpose. `apps` is the app's IDENTITY -- create it,
2678
+ * see who installed it, what it cost. This is its LIFECYCLE, and the two have
2679
+ * different blast radii: a mistake here takes a customer's app down.
2680
+ */
2681
+ get appPlatform() {
2682
+ this._assertKey("appPlatform");
2683
+ return this._appPlatform;
2684
+ }
2396
2685
  /** Custom object types, their schema, and their records (requires API key). PREVIEW. */
2397
2686
  get objects() {
2398
2687
  this._assertKey("objects");
@@ -2649,9 +2938,12 @@ export {
2649
2938
  DEFAULT_APP_API,
2650
2939
  G8Error,
2651
2940
  KNOWN_WEBHOOK_EVENTS,
2941
+ MAX_TAIL_LINES,
2942
+ MIN_TAIL_LINES,
2652
2943
  WebhookSignatureError,
2653
2944
  backoffDelayMs,
2654
2945
  constructEvent,
2946
+ createAppPlatformClient,
2655
2947
  createAppRequester,
2656
2948
  createGraph8AppClient,
2657
2949
  createGraph8ServiceClient,