primitive-admin 1.2.0-alpha.0 → 1.2.0-alpha.2
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 +6 -4
- package/dist/bin/primitive.js +22 -24
- package/dist/bin/primitive.js.map +1 -1
- package/dist/src/commands/agent-sessions.d.ts +20 -0
- package/dist/src/commands/agent-sessions.js +275 -0
- package/dist/src/commands/agent-sessions.js.map +1 -0
- package/dist/src/commands/apps-children.d.ts +54 -0
- package/dist/src/commands/apps-children.js +578 -0
- package/dist/src/commands/apps-children.js.map +1 -0
- package/dist/src/commands/apps.js +88 -9
- package/dist/src/commands/apps.js.map +1 -1
- package/dist/src/commands/auth-sessions.d.ts +3 -3
- package/dist/src/commands/auth-sessions.js +117 -23
- package/dist/src/commands/auth-sessions.js.map +1 -1
- package/dist/src/commands/auth.js +248 -15
- package/dist/src/commands/auth.js.map +1 -1
- package/dist/src/commands/connections.js +1 -5
- package/dist/src/commands/connections.js.map +1 -1
- package/dist/src/commands/databases.js +7 -109
- package/dist/src/commands/databases.js.map +1 -1
- package/dist/src/commands/documents.d.ts +29 -0
- package/dist/src/commands/documents.js +676 -191
- package/dist/src/commands/documents.js.map +1 -1
- package/dist/src/commands/env.d.ts +9 -1
- package/dist/src/commands/env.js +158 -45
- package/dist/src/commands/env.js.map +1 -1
- package/dist/src/commands/functions.js +7 -1
- package/dist/src/commands/functions.js.map +1 -1
- package/dist/src/commands/init.js +2 -1
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/integrations.js +14 -2
- package/dist/src/commands/integrations.js.map +1 -1
- package/dist/src/commands/prompts.js +4 -0
- package/dist/src/commands/prompts.js.map +1 -1
- package/dist/src/commands/scripts.js +1 -1
- package/dist/src/commands/scripts.js.map +1 -1
- package/dist/src/commands/sessions.js +3 -8
- package/dist/src/commands/sessions.js.map +1 -1
- package/dist/src/commands/sync-app-settings.d.ts +25 -7
- package/dist/src/commands/sync-app-settings.js +81 -20
- package/dist/src/commands/sync-app-settings.js.map +1 -1
- package/dist/src/commands/sync.d.ts +183 -12
- package/dist/src/commands/sync.js +974 -452
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/tokens.js +1 -6
- package/dist/src/commands/tokens.js.map +1 -1
- package/dist/src/commands/users.js +77 -2
- package/dist/src/commands/users.js.map +1 -1
- package/dist/src/lib/api-client.d.ts +161 -35
- package/dist/src/lib/api-client.js +210 -86
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/app-settings-descriptor.d.ts +9 -1
- package/dist/src/lib/app-settings-descriptor.js +22 -10
- package/dist/src/lib/app-settings-descriptor.js.map +1 -1
- package/dist/src/lib/auth-flow.d.ts +41 -1
- package/dist/src/lib/auth-flow.js +45 -16
- package/dist/src/lib/auth-flow.js.map +1 -1
- package/dist/src/lib/child-apps-local.d.ts +184 -0
- package/dist/src/lib/child-apps-local.js +282 -0
- package/dist/src/lib/child-apps-local.js.map +1 -0
- package/dist/src/lib/ci-session-request.d.ts +22 -0
- package/dist/src/lib/ci-session-request.js +51 -0
- package/dist/src/lib/ci-session-request.js.map +1 -0
- package/dist/src/lib/codegen-shared/generatedFiles.d.ts +4 -1
- package/dist/src/lib/codegen-shared/generatedFiles.js +19 -13
- package/dist/src/lib/codegen-shared/generatedFiles.js.map +1 -1
- package/dist/src/lib/config-object-descriptor.js +5 -5
- package/dist/src/lib/config-object-descriptor.js.map +1 -1
- package/dist/src/lib/config-payload.js +2 -3
- package/dist/src/lib/config-payload.js.map +1 -1
- package/dist/src/lib/config-surface.d.ts +2 -1
- package/dist/src/lib/config-surface.js +7 -28
- package/dist/src/lib/config-surface.js.map +1 -1
- package/dist/src/lib/credentials-store.d.ts +17 -2
- package/dist/src/lib/credentials-store.js +72 -6
- package/dist/src/lib/credentials-store.js.map +1 -1
- package/dist/src/lib/document-export-lookups.d.ts +31 -0
- package/dist/src/lib/document-export-lookups.js +53 -0
- package/dist/src/lib/document-export-lookups.js.map +1 -0
- package/dist/src/lib/document-export-permissions.d.ts +7 -5
- package/dist/src/lib/document-export-permissions.js +7 -5
- package/dist/src/lib/document-export-permissions.js.map +1 -1
- package/dist/src/lib/env-resolver-core.d.ts +69 -1
- package/dist/src/lib/env-resolver-core.js +137 -20
- package/dist/src/lib/env-resolver-core.js.map +1 -1
- package/dist/src/lib/env-resolver.d.ts +14 -2
- package/dist/src/lib/env-resolver.js +32 -10
- package/dist/src/lib/env-resolver.js.map +1 -1
- package/dist/src/lib/function-run.d.ts +4 -1
- package/dist/src/lib/function-run.js +24 -4
- package/dist/src/lib/function-run.js.map +1 -1
- package/dist/src/lib/function-sync.d.ts +5 -2
- package/dist/src/lib/function-sync.js +7 -4
- package/dist/src/lib/function-sync.js.map +1 -1
- package/dist/src/lib/generated-config-surfaces.d.ts +49 -50
- package/dist/src/lib/generated-config-surfaces.js +283 -166
- package/dist/src/lib/generated-config-surfaces.js.map +1 -1
- package/dist/src/lib/generated-sdk-types.d.ts +1 -1
- package/dist/src/lib/generated-sdk-types.js +1 -1
- package/dist/src/lib/generated-sdk-types.js.map +1 -1
- package/dist/src/lib/init-adopt.js +12 -3
- package/dist/src/lib/init-adopt.js.map +1 -1
- package/dist/src/lib/local-state.d.ts +17 -1
- package/dist/src/lib/local-state.js +94 -15
- package/dist/src/lib/local-state.js.map +1 -1
- package/dist/src/lib/local-test-cases.d.ts +5 -2
- package/dist/src/lib/local-test-cases.js +7 -4
- package/dist/src/lib/local-test-cases.js.map +1 -1
- package/dist/src/lib/log-inspection.d.ts +25 -0
- package/dist/src/lib/log-inspection.js +24 -0
- package/dist/src/lib/log-inspection.js.map +1 -1
- package/dist/src/lib/logout-admin-session.d.ts +2 -1
- package/dist/src/lib/logout-admin-session.js +7 -1
- package/dist/src/lib/logout-admin-session.js.map +1 -1
- package/dist/src/lib/pull-write.d.ts +31 -0
- package/dist/src/lib/pull-write.js +49 -0
- package/dist/src/lib/pull-write.js.map +1 -0
- package/dist/src/lib/root-import-decision.d.ts +59 -0
- package/dist/src/lib/root-import-decision.js +95 -0
- package/dist/src/lib/root-import-decision.js.map +1 -0
- package/dist/src/lib/scope-request.d.ts +69 -0
- package/dist/src/lib/scope-request.js +188 -0
- package/dist/src/lib/scope-request.js.map +1 -0
- package/dist/src/lib/session-id.d.ts +9 -0
- package/dist/src/lib/session-id.js +28 -0
- package/dist/src/lib/session-id.js.map +1 -0
- package/dist/src/lib/snapshots.d.ts +17 -1
- package/dist/src/lib/snapshots.js +50 -2
- package/dist/src/lib/snapshots.js.map +1 -1
- package/dist/src/lib/sync-paths.d.ts +35 -0
- package/dist/src/lib/sync-paths.js +57 -5
- package/dist/src/lib/sync-paths.js.map +1 -1
- package/dist/src/lib/transient-retry.d.ts +34 -0
- package/dist/src/lib/transient-retry.js +57 -0
- package/dist/src/lib/transient-retry.js.map +1 -0
- package/dist/src/types/index.d.ts +21 -4
- package/package.json +4 -3
|
@@ -85,6 +85,15 @@ export function parseErrorResponse(response, text, path) {
|
|
|
85
85
|
// Non-JSON body. Surface the existing `<!DOCTYPE` special-case (an HTML
|
|
86
86
|
// 404 page from hitting the wrong path) so we don't regress the helpful
|
|
87
87
|
// "API endpoint not found" message at api-client.ts:343.
|
|
88
|
+
//
|
|
89
|
+
// An HTML page with any other status is not a wrong path: it keeps its
|
|
90
|
+
// status, so a gateway's 502 is retried and a 403 is not read as absence
|
|
91
|
+
// (#4148).
|
|
92
|
+
if (text.includes("<!DOCTYPE") && response.status !== 404) {
|
|
93
|
+
return {
|
|
94
|
+
message: `HTTP ${response.status}: the server answered with an HTML error page`,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
88
97
|
if (text.includes("<!DOCTYPE")) {
|
|
89
98
|
const where = path ? `: ${path}` : "";
|
|
90
99
|
return {
|
|
@@ -295,60 +304,113 @@ export class ApiClient {
|
|
|
295
304
|
async request(path, options = {}) {
|
|
296
305
|
const credentials = await this.ensureAuthenticated();
|
|
297
306
|
const url = `${credentials.serverUrl}${path}`;
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
const response = await fetchWithTLS(url, {
|
|
308
|
-
...options,
|
|
309
|
-
headers,
|
|
310
|
-
});
|
|
311
|
-
const text = await response.text();
|
|
312
|
-
if (!response.ok) {
|
|
313
|
-
const parsed = parseErrorResponse(response, text, path);
|
|
314
|
-
// Preserve the `<!DOCTYPE` → 404 ApiError shape (status forced to 404).
|
|
315
|
-
if (parsed.htmlNotFound) {
|
|
316
|
-
throw new ApiError(parsed.message, 404);
|
|
317
|
-
}
|
|
318
|
-
// Narrow details to the record shape for the issue #666 typed-exception
|
|
319
|
-
// dispatch below. Conflict metadata may live under `details.*` (canonical
|
|
320
|
-
// location per A1) or on the top-level envelope (legacy).
|
|
321
|
-
const detailsRecord = parsed.details && !Array.isArray(parsed.details)
|
|
322
|
-
? parsed.details
|
|
323
|
-
: undefined;
|
|
324
|
-
const serverModifiedAt = detailsRecord?.serverModifiedAt ?? parsed.raw?.serverModifiedAt;
|
|
325
|
-
const expectedModifiedAt = detailsRecord?.expectedModifiedAt ?? parsed.raw?.expectedModifiedAt;
|
|
326
|
-
// Typed exceptions for the schema-feature (issue #666).
|
|
327
|
-
if (response.status === 409 && parsed.code === "CONFLICT") {
|
|
328
|
-
throw new ConflictError(parsed.message, serverModifiedAt, expectedModifiedAt, detailsRecord);
|
|
329
|
-
}
|
|
330
|
-
if (response.status === 409 && parsed.code === "OPS_EXIST") {
|
|
331
|
-
throw new OpsExistError(parsed.message, detailsRecord);
|
|
332
|
-
}
|
|
333
|
-
if (response.status === 400 && parsed.code === "TOML_PARSE_ERROR") {
|
|
334
|
-
throw new TomlParseError(parsed.message, detailsRecord);
|
|
335
|
-
}
|
|
336
|
-
if (response.status === 422 && parsed.code === "SCHEMA_REQUIRED") {
|
|
337
|
-
throw new SchemaRequiredError(parsed.message, detailsRecord);
|
|
307
|
+
const send = async (accessToken) => {
|
|
308
|
+
const headers = {
|
|
309
|
+
Authorization: `Bearer ${accessToken}`,
|
|
310
|
+
"Content-Type": "application/json",
|
|
311
|
+
...(options.headers || {}),
|
|
312
|
+
};
|
|
313
|
+
// Include globalAdminAppId if available (required for admin API calls)
|
|
314
|
+
if (credentials.globalAdminAppId) {
|
|
315
|
+
headers["X-Global-Admin-App-Id"] = credentials.globalAdminAppId;
|
|
338
316
|
}
|
|
339
|
-
|
|
340
|
-
|
|
317
|
+
const response = await fetchWithTLS(url, {
|
|
318
|
+
...options,
|
|
319
|
+
headers,
|
|
320
|
+
});
|
|
321
|
+
return { response, text: await response.text() };
|
|
322
|
+
};
|
|
323
|
+
let { response, text } = await send(credentials.accessToken);
|
|
324
|
+
// #3889 — a 403 naming `admin` is retried once with a stored, unexpired
|
|
325
|
+
// step-up. A retry refused 401 means the step-up is gone (revoked or
|
|
326
|
+
// expired early): drop it and show the original refusal. The retry's own
|
|
327
|
+
// refusal (say, an unpinned step-up on an app route) is shown as it is.
|
|
328
|
+
if (response.status === 403 && this.stepUpApplies(response, text, path)) {
|
|
329
|
+
const retried = await send(credentials.stepUp.accessToken);
|
|
330
|
+
if (retried.response.ok) {
|
|
331
|
+
return retried.text ? JSON.parse(retried.text) : null;
|
|
341
332
|
}
|
|
342
|
-
if (response.status ===
|
|
343
|
-
|
|
333
|
+
if (retried.response.status === 401) {
|
|
334
|
+
this.dropStepUp();
|
|
344
335
|
}
|
|
345
|
-
|
|
346
|
-
|
|
336
|
+
else {
|
|
337
|
+
({ response, text } = retried);
|
|
347
338
|
}
|
|
348
|
-
|
|
339
|
+
}
|
|
340
|
+
if (!response.ok) {
|
|
341
|
+
throw this.responseError(response, text, path);
|
|
349
342
|
}
|
|
350
343
|
return text ? JSON.parse(text) : null;
|
|
351
344
|
}
|
|
345
|
+
/**
|
|
346
|
+
* Whether a 403 should be retried with the stored step-up: it names
|
|
347
|
+
* `admin` among the missing scopes, and an unexpired step-up is stored.
|
|
348
|
+
*/
|
|
349
|
+
stepUpApplies(response, text, path) {
|
|
350
|
+
const stepUp = this.credentials?.stepUp;
|
|
351
|
+
if (!stepUp?.accessToken)
|
|
352
|
+
return false;
|
|
353
|
+
if (new Date(stepUp.expiresAt).getTime() <= Date.now())
|
|
354
|
+
return false;
|
|
355
|
+
const details = parseErrorResponse(response, text, path).details;
|
|
356
|
+
const missing = details && !Array.isArray(details) ? details.missing : undefined;
|
|
357
|
+
return Array.isArray(missing) && missing.includes("admin");
|
|
358
|
+
}
|
|
359
|
+
/** Forget a step-up the server no longer accepts. */
|
|
360
|
+
dropStepUp() {
|
|
361
|
+
if (!this.credentials?.stepUp)
|
|
362
|
+
return;
|
|
363
|
+
const { stepUp: _dropped, ...rest } = this.credentials;
|
|
364
|
+
this.credentials = rest;
|
|
365
|
+
saveCredentials(rest);
|
|
366
|
+
}
|
|
367
|
+
/** The typed error a failed response throws. */
|
|
368
|
+
responseError(response, text, path) {
|
|
369
|
+
const parsed = parseErrorResponse(response, text, path);
|
|
370
|
+
// Preserve the `<!DOCTYPE` → 404 ApiError shape.
|
|
371
|
+
if (parsed.htmlNotFound) {
|
|
372
|
+
return new ApiError(parsed.message, 404);
|
|
373
|
+
}
|
|
374
|
+
// Narrow details to the record shape for the issue #666 typed-exception
|
|
375
|
+
// dispatch below. Conflict metadata may live under `details.*` (canonical
|
|
376
|
+
// location per A1) or on the top-level envelope (legacy).
|
|
377
|
+
const detailsRecord = parsed.details && !Array.isArray(parsed.details)
|
|
378
|
+
? parsed.details
|
|
379
|
+
: undefined;
|
|
380
|
+
const serverModifiedAt = detailsRecord?.serverModifiedAt ?? parsed.raw?.serverModifiedAt;
|
|
381
|
+
const expectedModifiedAt = detailsRecord?.expectedModifiedAt ?? parsed.raw?.expectedModifiedAt;
|
|
382
|
+
// Typed exceptions for the schema-feature (issue #666).
|
|
383
|
+
if (response.status === 409 && parsed.code === "CONFLICT") {
|
|
384
|
+
return new ConflictError(parsed.message, serverModifiedAt, expectedModifiedAt, detailsRecord);
|
|
385
|
+
}
|
|
386
|
+
if (response.status === 409 && parsed.code === "OPS_EXIST") {
|
|
387
|
+
return new OpsExistError(parsed.message, detailsRecord);
|
|
388
|
+
}
|
|
389
|
+
if (response.status === 400 && parsed.code === "TOML_PARSE_ERROR") {
|
|
390
|
+
return new TomlParseError(parsed.message, detailsRecord);
|
|
391
|
+
}
|
|
392
|
+
if (response.status === 422 && parsed.code === "SCHEMA_REQUIRED") {
|
|
393
|
+
return new SchemaRequiredError(parsed.message, detailsRecord);
|
|
394
|
+
}
|
|
395
|
+
if (response.status === 422 && parsed.code === "OPERATION_REFERENCES_UNDEFINED") {
|
|
396
|
+
return new OperationRefError(parsed.message, detailsRecord);
|
|
397
|
+
}
|
|
398
|
+
if (response.status === 422 && parsed.code === "SCHEMA_BREAKS_OPERATIONS") {
|
|
399
|
+
return new SchemaBreaksOpsError(parsed.message, detailsRecord);
|
|
400
|
+
}
|
|
401
|
+
if (response.status === 422 && parsed.code === "SCHEMA_HAS_UNCHECKABLE_OPS") {
|
|
402
|
+
return new SchemaHasUncheckableOpsError(parsed.message, detailsRecord);
|
|
403
|
+
}
|
|
404
|
+
return new ApiError(parsed.message, response.status, parsed.code, parsed.details);
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* `POST /admin/api/auth/token` — derive a token no wider than the stored
|
|
408
|
+
* one (`primitive token --scope`, #3889). A wider request is refused with
|
|
409
|
+
* `TOKEN_WIDER_THAN_PRESENTED`.
|
|
410
|
+
*/
|
|
411
|
+
async exchangeToken(body) {
|
|
412
|
+
return this.post("/admin/api/auth/token", body);
|
|
413
|
+
}
|
|
352
414
|
// Helper for GET requests with query params
|
|
353
415
|
async get(path, params) {
|
|
354
416
|
let fullPath = path;
|
|
@@ -410,6 +472,10 @@ export class ApiClient {
|
|
|
410
472
|
qs.set("limit", String(params.limit));
|
|
411
473
|
if (params?.cursor)
|
|
412
474
|
qs.set("cursor", params.cursor);
|
|
475
|
+
// `kind` filters by lineage: `parent` is apps with no parent, `child`
|
|
476
|
+
// child apps. Omitted lists every app the caller is assigned to.
|
|
477
|
+
if (params?.kind)
|
|
478
|
+
qs.set("kind", params.kind);
|
|
413
479
|
const q = qs.toString();
|
|
414
480
|
const resp = await this.get(`/admin/api/admins/me/apps${q ? `?${q}` : ""}`);
|
|
415
481
|
return {
|
|
@@ -463,9 +529,54 @@ export class ApiClient {
|
|
|
463
529
|
});
|
|
464
530
|
return drainAppsUntilConverged(drainOnce);
|
|
465
531
|
}
|
|
532
|
+
/**
|
|
533
|
+
* Create an app. An ordinary app takes `name` (and, for a super-admin,
|
|
534
|
+
* `initialAdminEmail`). A child app takes `parentAppId` and `childSlug`
|
|
535
|
+
* instead, plus the optional `branch`, `idleDays` (7-30, default 30) and
|
|
536
|
+
* `copySecrets` (default true); the server names it `<parent name> /
|
|
537
|
+
* <slug>` and copies the parent's settings.
|
|
538
|
+
*/
|
|
466
539
|
async createApp(data) {
|
|
467
540
|
return this.post("/admin/api/apps", data);
|
|
468
541
|
}
|
|
542
|
+
/**
|
|
543
|
+
* One page of an app's child apps, in creation order
|
|
544
|
+
* (`GET /admin/api/apps/{appId}/children`).
|
|
545
|
+
*/
|
|
546
|
+
async listAppChildren(parentAppId, params) {
|
|
547
|
+
const qs = new URLSearchParams();
|
|
548
|
+
if (params?.limit !== undefined)
|
|
549
|
+
qs.set("limit", String(params.limit));
|
|
550
|
+
if (params?.cursor)
|
|
551
|
+
qs.set("cursor", params.cursor);
|
|
552
|
+
const q = qs.toString();
|
|
553
|
+
const resp = await this.get(`/admin/api/apps/${encodeURIComponent(parentAppId)}/children${q ? `?${q}` : ""}`);
|
|
554
|
+
return {
|
|
555
|
+
items: resp?.items ?? [],
|
|
556
|
+
hasMore: resp?.hasMore ?? false,
|
|
557
|
+
nextCursor: resp?.nextCursor ?? null,
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Add one origin to a child's preview origins
|
|
562
|
+
* (`POST /admin/api/apps/{parentAppId}/children/{slug}/preview-origins`).
|
|
563
|
+
*/
|
|
564
|
+
async addChildPreviewOrigin(parentAppId, slug, origin) {
|
|
565
|
+
return this.post(this.childPreviewOriginsPath(parentAppId, slug), { origin });
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Remove one origin from a child's preview origins
|
|
569
|
+
* (`DELETE /admin/api/apps/{parentAppId}/children/{slug}/preview-origins`).
|
|
570
|
+
*/
|
|
571
|
+
async removeChildPreviewOrigin(parentAppId, slug, origin) {
|
|
572
|
+
return this.request(this.childPreviewOriginsPath(parentAppId, slug), {
|
|
573
|
+
method: "DELETE",
|
|
574
|
+
body: JSON.stringify({ origin }),
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
childPreviewOriginsPath(parentAppId, slug) {
|
|
578
|
+
return `/admin/api/apps/${encodeURIComponent(parentAppId)}/children/${encodeURIComponent(slug)}/preview-origins`;
|
|
579
|
+
}
|
|
469
580
|
async getApp(appId) {
|
|
470
581
|
return this.get(`/admin/api/apps/${appId}`);
|
|
471
582
|
}
|
|
@@ -487,6 +598,14 @@ export class ApiClient {
|
|
|
487
598
|
async addUserByEmail(appId, data) {
|
|
488
599
|
return this.post(`/admin/api/apps/${appId}/users/add-by-email`, data);
|
|
489
600
|
}
|
|
601
|
+
/**
|
|
602
|
+
* Set a member's display name and/or avatar URL
|
|
603
|
+
* (`PATCH /admin/api/apps/:appId/users/:userId/profile`). An omitted field
|
|
604
|
+
* is left alone; `avatarUrl: null` or `""` clears the avatar.
|
|
605
|
+
*/
|
|
606
|
+
async setUserProfile(appId, userId, data) {
|
|
607
|
+
return this.patch(`/admin/api/apps/${appId}/users/${userId}/profile`, data);
|
|
608
|
+
}
|
|
490
609
|
async mintTestJwt(appId, userId, role) {
|
|
491
610
|
return this.post(`/admin/api/apps/${appId}/users/${userId}/mint-test-jwt`, role ? { role } : {});
|
|
492
611
|
}
|
|
@@ -1037,6 +1156,29 @@ export class ApiClient {
|
|
|
1037
1156
|
nextCursor: result?.nextCursor ?? null,
|
|
1038
1157
|
};
|
|
1039
1158
|
}
|
|
1159
|
+
/**
|
|
1160
|
+
* One page of one user's agent sessions (#3809): the app API's sessions
|
|
1161
|
+
* list, which an app owner or admin may read for any user.
|
|
1162
|
+
*/
|
|
1163
|
+
async listAgentSessions(appId, params) {
|
|
1164
|
+
const result = await this.get(`/app/${appId}/api/agent-sessions`, params);
|
|
1165
|
+
return {
|
|
1166
|
+
items: result?.items ?? [],
|
|
1167
|
+
hasMore: result?.hasMore,
|
|
1168
|
+
nextCursor: result?.nextCursor ?? null,
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1171
|
+
/**
|
|
1172
|
+
* One agent session (#3809): its binding, status, members and active turn,
|
|
1173
|
+
* and for an app owner or admin the session object's state. Never its rows.
|
|
1174
|
+
*/
|
|
1175
|
+
async getAgentSession(appId, sessionId) {
|
|
1176
|
+
return this.get(`/app/${appId}/api/agent-sessions/${encodeURIComponent(sessionId)}`);
|
|
1177
|
+
}
|
|
1178
|
+
/** Delete an agent session and its document (#3809); a repeat succeeds again. */
|
|
1179
|
+
async deleteAgentSession(appId, sessionId) {
|
|
1180
|
+
return this.delete(`/app/${appId}/api/agent-sessions/${encodeURIComponent(sessionId)}`);
|
|
1181
|
+
}
|
|
1040
1182
|
async listSessions(appId, userId, params) {
|
|
1041
1183
|
const result = await this.get(`/admin/api/apps/${appId}/sessions`, {
|
|
1042
1184
|
userId,
|
|
@@ -1890,43 +2032,6 @@ export class ApiClient {
|
|
|
1890
2032
|
async deleteDatabase(appId, databaseId) {
|
|
1891
2033
|
return this.delete(`/app/${appId}/api/databases/${databaseId}`);
|
|
1892
2034
|
}
|
|
1893
|
-
/**
|
|
1894
|
-
* Read a database's CEL context dict.
|
|
1895
|
-
*
|
|
1896
|
-
* The HTTP path stays `/metadata` because the wire field name is still
|
|
1897
|
-
* `metadata`; only the client/CLI-facing helper names were reframed.
|
|
1898
|
-
*
|
|
1899
|
-
* @deprecated Use resource metadata categories instead (`primitive metadata
|
|
1900
|
-
* get database <id> <category>`, #1420, #1815).
|
|
1901
|
-
*/
|
|
1902
|
-
async getDatabaseCelContext(appId, databaseId) {
|
|
1903
|
-
return this.get(`/app/${appId}/api/databases/${databaseId}/metadata`);
|
|
1904
|
-
}
|
|
1905
|
-
/**
|
|
1906
|
-
* Update a database's CEL context dict (merge with existing).
|
|
1907
|
-
*
|
|
1908
|
-
* @deprecated Use resource metadata categories instead (`primitive metadata
|
|
1909
|
-
* set database <id> <category>`, #1420, #1815).
|
|
1910
|
-
*/
|
|
1911
|
-
async updateDatabaseCelContext(appId, databaseId, celContext) {
|
|
1912
|
-
return this.patch(`/app/${appId}/api/databases/${databaseId}/metadata`, celContext);
|
|
1913
|
-
}
|
|
1914
|
-
/**
|
|
1915
|
-
* @deprecated Database CEL context is deprecated; use resource metadata
|
|
1916
|
-
* categories instead (`primitive metadata get database <id> <category>`,
|
|
1917
|
-
* #1420, #1815).
|
|
1918
|
-
*/
|
|
1919
|
-
async getDatabaseMetadata(appId, databaseId) {
|
|
1920
|
-
return this.getDatabaseCelContext(appId, databaseId);
|
|
1921
|
-
}
|
|
1922
|
-
/**
|
|
1923
|
-
* @deprecated Database CEL context is deprecated; use resource metadata
|
|
1924
|
-
* categories instead (`primitive metadata set database <id> <category>`,
|
|
1925
|
-
* #1420, #1815).
|
|
1926
|
-
*/
|
|
1927
|
-
async updateDatabaseMetadata(appId, databaseId, metadata) {
|
|
1928
|
-
return this.updateDatabaseCelContext(appId, databaseId, metadata);
|
|
1929
|
-
}
|
|
1930
2035
|
// ============================================
|
|
1931
2036
|
// DATABASE PERMISSIONS
|
|
1932
2037
|
// ============================================
|
|
@@ -2890,8 +2995,13 @@ export class ApiClient {
|
|
|
2890
2995
|
async listDocumentPendingInvitations(appId, documentId) {
|
|
2891
2996
|
return this.get(`/app/${appId}/api/documents/${documentId}/pending-invitations`);
|
|
2892
2997
|
}
|
|
2893
|
-
|
|
2894
|
-
|
|
2998
|
+
/**
|
|
2999
|
+
* One page of a document's uploaded blobs (the `{ items, hasMore,
|
|
3000
|
+
* nextCursor? }` envelope); pass the previous page's `nextCursor` for the
|
|
3001
|
+
* next.
|
|
3002
|
+
*/
|
|
3003
|
+
async listDocumentBlobs(appId, documentId, params) {
|
|
3004
|
+
return this.get(`/app/${appId}/api/documents/${documentId}/blobs`, params);
|
|
2895
3005
|
}
|
|
2896
3006
|
async downloadBlob(appId, documentId, blobId) {
|
|
2897
3007
|
const credentials = await this.ensureAuthenticated();
|
|
@@ -2935,6 +3045,20 @@ export class ApiClient {
|
|
|
2935
3045
|
async listDocumentAliases(appId, documentId) {
|
|
2936
3046
|
return this.get(`/app/${appId}/api/documents/${documentId}/aliases`);
|
|
2937
3047
|
}
|
|
3048
|
+
/**
|
|
3049
|
+
* The document a user's alias points at, or null when the user holds no
|
|
3050
|
+
* alias under that key (#4148).
|
|
3051
|
+
*/
|
|
3052
|
+
async getDocumentAlias(appId, aliasScope, aliasKey, userId) {
|
|
3053
|
+
try {
|
|
3054
|
+
return await this.get(`/app/${appId}/api/document-aliases/${aliasScope}/${encodeURIComponent(aliasKey)}`, { userId });
|
|
3055
|
+
}
|
|
3056
|
+
catch (error) {
|
|
3057
|
+
if (error instanceof ApiError && error.statusCode === 404)
|
|
3058
|
+
return null;
|
|
3059
|
+
throw error;
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
2938
3062
|
async setDocumentAlias(appId, aliasScope, aliasKey, documentId, ownerUserId, mustNotExist) {
|
|
2939
3063
|
return this.put(`/app/${appId}/api/document-aliases/${aliasScope}/${encodeURIComponent(aliasKey)}`, {
|
|
2940
3064
|
documentId,
|