@inneropen/marvin-sdk 4.2.0 → 4.3.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.
@@ -79,6 +79,11 @@ interface RetryConfig {
79
79
  */
80
80
  retryableStatuses: number[];
81
81
  }
82
+ /** A successful binary read: the body's bytes and the server's content type. */
83
+ interface BinaryResponse {
84
+ data: Uint8Array;
85
+ contentType: string | null;
86
+ }
82
87
  interface HttpClientConfig {
83
88
  baseUrl: string;
84
89
  auth: AuthStrategy;
@@ -158,6 +163,11 @@ declare class HttpClient {
158
163
  * Still clamped to MAX_TIMEOUT.
159
164
  */
160
165
  timeout?: number;
166
+ /**
167
+ * `'binary'` hands back a {@link BinaryResponse} (the raw bytes) instead of parsing JSON. Retries,
168
+ * redirects and errors behave exactly as for a JSON read.
169
+ */
170
+ responseType?: 'json' | 'binary';
161
171
  }, retryAttempt?: number): Promise<T>;
162
172
  /**
163
173
  * A successful response's JSON body, or `undefined` when there is none: 204/205, `content-length: 0`,
@@ -165,10 +175,16 @@ declare class HttpClient {
165
175
  * JSON is a `MarvinApiError` naming the request — never a network error, and never retried.
166
176
  */
167
177
  private readBody;
178
+ /** A successful response's bytes; a 204/205 is an empty array. A failed read is a network error. */
179
+ private readBinary;
168
180
  /**
169
181
  * GET request
170
182
  */
171
183
  get<T>(endpoint: string, params?: Record<string, string | number | boolean | undefined>): Promise<T>;
184
+ /**
185
+ * GET a binary body (a file download). Follows redirects; retried like any GET.
186
+ */
187
+ getBinary(endpoint: string, params?: Record<string, string | number | boolean | undefined>): Promise<BinaryResponse>;
172
188
  /**
173
189
  * POST request
174
190
  */
@@ -189,4 +205,4 @@ declare class HttpClient {
189
205
  delete<T>(endpoint: string): Promise<T>;
190
206
  }
191
207
 
192
- export { type AuthStrategy as A, BearerTokenAuth as B, HttpClient as H, NoAuth as N, SessionAuth as S, type HttpClientConfig as a };
208
+ export { type AuthStrategy as A, BearerTokenAuth as B, HttpClient as H, NoAuth as N, SessionAuth as S, type BinaryResponse as a, type HttpClientConfig as b };
@@ -79,6 +79,11 @@ interface RetryConfig {
79
79
  */
80
80
  retryableStatuses: number[];
81
81
  }
82
+ /** A successful binary read: the body's bytes and the server's content type. */
83
+ interface BinaryResponse {
84
+ data: Uint8Array;
85
+ contentType: string | null;
86
+ }
82
87
  interface HttpClientConfig {
83
88
  baseUrl: string;
84
89
  auth: AuthStrategy;
@@ -158,6 +163,11 @@ declare class HttpClient {
158
163
  * Still clamped to MAX_TIMEOUT.
159
164
  */
160
165
  timeout?: number;
166
+ /**
167
+ * `'binary'` hands back a {@link BinaryResponse} (the raw bytes) instead of parsing JSON. Retries,
168
+ * redirects and errors behave exactly as for a JSON read.
169
+ */
170
+ responseType?: 'json' | 'binary';
161
171
  }, retryAttempt?: number): Promise<T>;
162
172
  /**
163
173
  * A successful response's JSON body, or `undefined` when there is none: 204/205, `content-length: 0`,
@@ -165,10 +175,16 @@ declare class HttpClient {
165
175
  * JSON is a `MarvinApiError` naming the request — never a network error, and never retried.
166
176
  */
167
177
  private readBody;
178
+ /** A successful response's bytes; a 204/205 is an empty array. A failed read is a network error. */
179
+ private readBinary;
168
180
  /**
169
181
  * GET request
170
182
  */
171
183
  get<T>(endpoint: string, params?: Record<string, string | number | boolean | undefined>): Promise<T>;
184
+ /**
185
+ * GET a binary body (a file download). Follows redirects; retried like any GET.
186
+ */
187
+ getBinary(endpoint: string, params?: Record<string, string | number | boolean | undefined>): Promise<BinaryResponse>;
172
188
  /**
173
189
  * POST request
174
190
  */
@@ -189,4 +205,4 @@ declare class HttpClient {
189
205
  delete<T>(endpoint: string): Promise<T>;
190
206
  }
191
207
 
192
- export { type AuthStrategy as A, BearerTokenAuth as B, HttpClient as H, NoAuth as N, SessionAuth as S, type HttpClientConfig as a };
208
+ export { type AuthStrategy as A, BearerTokenAuth as B, HttpClient as H, NoAuth as N, SessionAuth as S, type BinaryResponse as a, type HttpClientConfig as b };
@@ -6,7 +6,7 @@ import {
6
6
  __export,
7
7
  init_core,
8
8
  init_errors
9
- } from "./chunk-DSVYCVQD.js";
9
+ } from "./chunk-LTX3MAUE.js";
10
10
 
11
11
  // src/client/config.ts
12
12
  var config_exports = {};
@@ -320,6 +320,11 @@ var init_resource = __esm({
320
320
  });
321
321
 
322
322
  // src/entries/entries.ts
323
+ function csv(value) {
324
+ if (value === void 0) return void 0;
325
+ const joined = (Array.isArray(value) ? value : [value]).map((v) => v.trim()).filter(Boolean).join(",");
326
+ return joined || void 0;
327
+ }
323
328
  function toListEntry(raw) {
324
329
  const { collections, ...rest } = raw;
325
330
  return {
@@ -347,6 +352,9 @@ var init_entries = __esm({
347
352
  const queryString = this.http.buildQueryString({
348
353
  entry_type: options.entryType,
349
354
  collection: options.collection,
355
+ tag: csv(options.tag),
356
+ slug: csv(options.slug),
357
+ updated_since: options.updatedSince instanceof Date ? options.updatedSince.toISOString() : options.updatedSince,
350
358
  limit: options.limit,
351
359
  offset: options.offset,
352
360
  expand: options.expand
@@ -514,6 +522,14 @@ var init_assets = __esm({
514
522
  const endpoint = `/api/publish/${this.workspaceSlug}/assets/${slugOrId}`;
515
523
  return this.http.fetch(endpoint);
516
524
  }
525
+ /**
526
+ * Download a published asset's file by slug: its bytes and content type. The file route
527
+ * redirects to storage; the redirect is followed. Needs the `read:assets` permission.
528
+ */
529
+ async download(slug) {
530
+ const validSlug = this.http.validatePathParam(slug, "asset slug");
531
+ return this.http.getBinary(`/api/publish/${this.workspaceSlug}/assets/${validSlug}/file`);
532
+ }
517
533
  /**
518
534
  * Convenience: Get all images
519
535
  */
@@ -383,6 +383,9 @@ var init_HttpClient = __esm({
383
383
  errorText
384
384
  );
385
385
  }
386
+ if (options?.responseType === "binary") {
387
+ return await this.readBinary(response, method, endpoint);
388
+ }
386
389
  const data = await this.readBody(response, method, endpoint);
387
390
  if (this.debug && data !== void 0) {
388
391
  const sanitized = this.sanitizeForLogging(data);
@@ -428,12 +431,34 @@ var init_HttpClient = __esm({
428
431
  );
429
432
  }
430
433
  }
434
+ /** A successful response's bytes; a 204/205 is an empty array. A failed read is a network error. */
435
+ async readBinary(response, method, endpoint) {
436
+ const contentType = response.headers.get("content-type");
437
+ if (response.status === 204 || response.status === 205) {
438
+ return { data: new Uint8Array(0), contentType };
439
+ }
440
+ try {
441
+ return { data: new Uint8Array(await response.arrayBuffer()), contentType };
442
+ } catch (error) {
443
+ const cause = error instanceof Error ? error : void 0;
444
+ throw new MarvinNetworkError(
445
+ `Reading the ${response.status} response to ${method} ${endpoint} failed: ${cause?.message ?? String(error)}`,
446
+ cause
447
+ );
448
+ }
449
+ }
431
450
  /**
432
451
  * GET request
433
452
  */
434
453
  async get(endpoint, params) {
435
454
  return this.request("GET", endpoint, { params });
436
455
  }
456
+ /**
457
+ * GET a binary body (a file download). Follows redirects; retried like any GET.
458
+ */
459
+ async getBinary(endpoint, params) {
460
+ return this.request("GET", endpoint, { params, responseType: "binary" });
461
+ }
437
462
  /**
438
463
  * POST request
439
464
  */
package/dist/index.cjs CHANGED
@@ -510,6 +510,9 @@ var init_HttpClient = __esm({
510
510
  errorText
511
511
  );
512
512
  }
513
+ if (options?.responseType === "binary") {
514
+ return await this.readBinary(response, method, endpoint);
515
+ }
513
516
  const data = await this.readBody(response, method, endpoint);
514
517
  if (this.debug && data !== void 0) {
515
518
  const sanitized = this.sanitizeForLogging(data);
@@ -555,12 +558,34 @@ var init_HttpClient = __esm({
555
558
  );
556
559
  }
557
560
  }
561
+ /** A successful response's bytes; a 204/205 is an empty array. A failed read is a network error. */
562
+ async readBinary(response, method, endpoint) {
563
+ const contentType = response.headers.get("content-type");
564
+ if (response.status === 204 || response.status === 205) {
565
+ return { data: new Uint8Array(0), contentType };
566
+ }
567
+ try {
568
+ return { data: new Uint8Array(await response.arrayBuffer()), contentType };
569
+ } catch (error) {
570
+ const cause = error instanceof Error ? error : void 0;
571
+ throw new MarvinNetworkError(
572
+ `Reading the ${response.status} response to ${method} ${endpoint} failed: ${cause?.message ?? String(error)}`,
573
+ cause
574
+ );
575
+ }
576
+ }
558
577
  /**
559
578
  * GET request
560
579
  */
561
580
  async get(endpoint, params) {
562
581
  return this.request("GET", endpoint, { params });
563
582
  }
583
+ /**
584
+ * GET a binary body (a file download). Follows redirects; retried like any GET.
585
+ */
586
+ async getBinary(endpoint, params) {
587
+ return this.request("GET", endpoint, { params, responseType: "binary" });
588
+ }
564
589
  /**
565
590
  * POST request
566
591
  */
@@ -993,6 +1018,11 @@ var init_entry = __esm({
993
1018
  });
994
1019
 
995
1020
  // src/entries/entries.ts
1021
+ function csv(value) {
1022
+ if (value === void 0) return void 0;
1023
+ const joined = (Array.isArray(value) ? value : [value]).map((v) => v.trim()).filter(Boolean).join(",");
1024
+ return joined || void 0;
1025
+ }
996
1026
  function toListEntry(raw) {
997
1027
  const { collections, ...rest } = raw;
998
1028
  return {
@@ -1020,6 +1050,9 @@ var init_entries = __esm({
1020
1050
  const queryString = this.http.buildQueryString({
1021
1051
  entry_type: options.entryType,
1022
1052
  collection: options.collection,
1053
+ tag: csv(options.tag),
1054
+ slug: csv(options.slug),
1055
+ updated_since: options.updatedSince instanceof Date ? options.updatedSince.toISOString() : options.updatedSince,
1023
1056
  limit: options.limit,
1024
1057
  offset: options.offset,
1025
1058
  expand: options.expand
@@ -1253,6 +1286,14 @@ var init_assets = __esm({
1253
1286
  const endpoint = `/api/publish/${this.workspaceSlug}/assets/${slugOrId}`;
1254
1287
  return this.http.fetch(endpoint);
1255
1288
  }
1289
+ /**
1290
+ * Download a published asset's file by slug: its bytes and content type. The file route
1291
+ * redirects to storage; the redirect is followed. Needs the `read:assets` permission.
1292
+ */
1293
+ async download(slug) {
1294
+ const validSlug = this.http.validatePathParam(slug, "asset slug");
1295
+ return this.http.getBinary(`/api/publish/${this.workspaceSlug}/assets/${validSlug}/file`);
1296
+ }
1256
1297
  /**
1257
1298
  * Convenience: Get all images
1258
1299
  */
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
- import { M as MarvinConfig, a as MarvinClient } from './marvin-BiXcixLB.cjs';
2
- export { C as Collection, E as Entry, b as MarvinApiError, c as MarvinAuthError, d as MarvinCache, e as MarvinConfigError, f as MarvinError, g as MarvinNetworkError, h as MarvinNotFoundError, i as MarvinServerError, j as MarvinValidationError, P as PaginatedResponse, k as PaginationMeta, l as PaginationParams, R as Resource, W as Workspace, m as createConfigFromEnv, n as createPaginatedResponse, o as extractData, p as isFullEntryData, q as isPaginatedResponse, r as offsetToPage, s as pageToOffset } from './marvin-BiXcixLB.cjs';
3
- import { H as HttpClient } from './HttpClient-B_rEmJuO.cjs';
4
- export { A as AuthStrategy, B as BearerTokenAuth, a as HttpClientConfig, N as NoAuth, S as SessionAuth } from './HttpClient-B_rEmJuO.cjs';
1
+ import { M as MarvinConfig, a as MarvinClient } from './marvin-gZtGa576.cjs';
2
+ export { C as Collection, E as Entry, b as MarvinApiError, c as MarvinAuthError, d as MarvinCache, e as MarvinConfigError, f as MarvinError, g as MarvinNetworkError, h as MarvinNotFoundError, i as MarvinServerError, j as MarvinValidationError, P as PaginatedResponse, k as PaginationMeta, l as PaginationParams, R as Resource, W as Workspace, m as createConfigFromEnv, n as createPaginatedResponse, o as extractData, p as isFullEntryData, q as isPaginatedResponse, r as offsetToPage, s as pageToOffset } from './marvin-gZtGa576.cjs';
3
+ import { H as HttpClient } from './HttpClient-DXMNOPqu.cjs';
4
+ export { A as AuthStrategy, B as BearerTokenAuth, a as BinaryResponse, b as HttpClientConfig, N as NoAuth, S as SessionAuth } from './HttpClient-DXMNOPqu.cjs';
5
5
  import { A as AuthToken$1 } from './index-BEEbnrXV.cjs';
6
6
  export { C as CollectionContext, a as CollectionEntry, b as CollectionEntryMetadata, E as EntryAsset, c as EntryCollectionContext, d as EntryResource, e as ExpandOptions, G as GetAssetsOptions, f as GetEntriesOptions, g as GetResourcesOptions, L as ListEntry, M as MarvinAsset, h as MarvinCollection, i as MarvinCollectionExpanded, j as MarvinEntry, k as MarvinEntryListItem, l as MarvinEntryType, m as MarvinPublishResponse, n as MarvinResource, o as MarvinSite, P as PublishedAssetRead, p as PublishedCollectionSummary, q as PublishedEntryAsset, r as PublishedEntryResource, s as PublishedEntryType, S as SiteConfiguration, W as WorkspaceInfo } from './index-BEEbnrXV.cjs';
7
7
 
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { M as MarvinConfig, a as MarvinClient } from './marvin-BjJXe-YT.js';
2
- export { C as Collection, E as Entry, b as MarvinApiError, c as MarvinAuthError, d as MarvinCache, e as MarvinConfigError, f as MarvinError, g as MarvinNetworkError, h as MarvinNotFoundError, i as MarvinServerError, j as MarvinValidationError, P as PaginatedResponse, k as PaginationMeta, l as PaginationParams, R as Resource, W as Workspace, m as createConfigFromEnv, n as createPaginatedResponse, o as extractData, p as isFullEntryData, q as isPaginatedResponse, r as offsetToPage, s as pageToOffset } from './marvin-BjJXe-YT.js';
3
- import { H as HttpClient } from './HttpClient-B_rEmJuO.js';
4
- export { A as AuthStrategy, B as BearerTokenAuth, a as HttpClientConfig, N as NoAuth, S as SessionAuth } from './HttpClient-B_rEmJuO.js';
1
+ import { M as MarvinConfig, a as MarvinClient } from './marvin-CdsjwIyH.js';
2
+ export { C as Collection, E as Entry, b as MarvinApiError, c as MarvinAuthError, d as MarvinCache, e as MarvinConfigError, f as MarvinError, g as MarvinNetworkError, h as MarvinNotFoundError, i as MarvinServerError, j as MarvinValidationError, P as PaginatedResponse, k as PaginationMeta, l as PaginationParams, R as Resource, W as Workspace, m as createConfigFromEnv, n as createPaginatedResponse, o as extractData, p as isFullEntryData, q as isPaginatedResponse, r as offsetToPage, s as pageToOffset } from './marvin-CdsjwIyH.js';
3
+ import { H as HttpClient } from './HttpClient-DXMNOPqu.js';
4
+ export { A as AuthStrategy, B as BearerTokenAuth, a as BinaryResponse, b as HttpClientConfig, N as NoAuth, S as SessionAuth } from './HttpClient-DXMNOPqu.js';
5
5
  import { A as AuthToken$1 } from './index-BEEbnrXV.js';
6
6
  export { C as CollectionContext, a as CollectionEntry, b as CollectionEntryMetadata, E as EntryAsset, c as EntryCollectionContext, d as EntryResource, e as ExpandOptions, G as GetAssetsOptions, f as GetEntriesOptions, g as GetResourcesOptions, L as ListEntry, M as MarvinAsset, h as MarvinCollection, i as MarvinCollectionExpanded, j as MarvinEntry, k as MarvinEntryListItem, l as MarvinEntryType, m as MarvinPublishResponse, n as MarvinResource, o as MarvinSite, P as PublishedAssetRead, p as PublishedCollectionSummary, q as PublishedEntryAsset, r as PublishedEntryResource, s as PublishedEntryType, S as SiteConfiguration, W as WorkspaceInfo } from './index-BEEbnrXV.js';
7
7
 
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  init_workspace,
15
15
  isFullEntryData,
16
16
  marvin_exports
17
- } from "./chunk-HFNIFS2A.js";
17
+ } from "./chunk-KXI2FQSO.js";
18
18
  import {
19
19
  BearerTokenAuth,
20
20
  HttpClient,
@@ -37,7 +37,7 @@ import {
37
37
  offsetToPage,
38
38
  pageToOffset,
39
39
  validateEmail
40
- } from "./chunk-DSVYCVQD.js";
40
+ } from "./chunk-LTX3MAUE.js";
41
41
 
42
42
  // src/index.ts
43
43
  init_marvin();
@@ -1,5 +1,5 @@
1
1
  import { s as PublishedEntryType, n as MarvinResource, M as MarvinAsset, h as MarvinCollection, a as CollectionEntry, j as MarvinEntry, E as EntryAsset, c as EntryCollectionContext, d as EntryResource, p as PublishedCollectionSummary, e as ExpandOptions, L as ListEntry, o as MarvinSite, g as GetResourcesOptions$1 } from './index-BEEbnrXV.js';
2
- import { H as HttpClient } from './HttpClient-B_rEmJuO.js';
2
+ import { H as HttpClient, a as BinaryResponse } from './HttpClient-DXMNOPqu.js';
3
3
 
4
4
  /**
5
5
  * Marvin SDK Configuration
@@ -274,6 +274,11 @@ declare class AssetsModule {
274
274
  * Get a single published asset by slug or ID
275
275
  */
276
276
  get(slugOrId: string): Promise<MarvinAsset>;
277
+ /**
278
+ * Download a published asset's file by slug: its bytes and content type. The file route
279
+ * redirects to storage; the redirect is followed. Needs the `read:assets` permission.
280
+ */
281
+ download(slug: string): Promise<BinaryResponse>;
277
282
  /**
278
283
  * Convenience: Get all images
279
284
  */
@@ -409,6 +414,12 @@ declare class CollectionsModule {
409
414
  interface GetEntriesOptions {
410
415
  entryType?: string;
411
416
  collection?: string;
417
+ /** Only entries carrying any of these tag slugs. */
418
+ tag?: string | string[];
419
+ /** Only entries with these slugs. */
420
+ slug?: string | string[];
421
+ /** Only entries updated at or after this time (ISO 8601, or a Date). */
422
+ updatedSince?: string | Date;
412
423
  limit?: number;
413
424
  offset?: number;
414
425
  status?: string;
@@ -1,5 +1,5 @@
1
1
  import { s as PublishedEntryType, n as MarvinResource, M as MarvinAsset, h as MarvinCollection, a as CollectionEntry, j as MarvinEntry, E as EntryAsset, c as EntryCollectionContext, d as EntryResource, p as PublishedCollectionSummary, e as ExpandOptions, L as ListEntry, o as MarvinSite, g as GetResourcesOptions$1 } from './index-BEEbnrXV.cjs';
2
- import { H as HttpClient } from './HttpClient-B_rEmJuO.cjs';
2
+ import { H as HttpClient, a as BinaryResponse } from './HttpClient-DXMNOPqu.cjs';
3
3
 
4
4
  /**
5
5
  * Marvin SDK Configuration
@@ -274,6 +274,11 @@ declare class AssetsModule {
274
274
  * Get a single published asset by slug or ID
275
275
  */
276
276
  get(slugOrId: string): Promise<MarvinAsset>;
277
+ /**
278
+ * Download a published asset's file by slug: its bytes and content type. The file route
279
+ * redirects to storage; the redirect is followed. Needs the `read:assets` permission.
280
+ */
281
+ download(slug: string): Promise<BinaryResponse>;
277
282
  /**
278
283
  * Convenience: Get all images
279
284
  */
@@ -409,6 +414,12 @@ declare class CollectionsModule {
409
414
  interface GetEntriesOptions {
410
415
  entryType?: string;
411
416
  collection?: string;
417
+ /** Only entries carrying any of these tag slugs. */
418
+ tag?: string | string[];
419
+ /** Only entries with these slugs. */
420
+ slug?: string | string[];
421
+ /** Only entries updated at or after this time (ISO 8601, or a Date). */
422
+ updatedSince?: string | Date;
412
423
  limit?: number;
413
424
  offset?: number;
414
425
  status?: string;
package/dist/platform.cjs CHANGED
@@ -39,6 +39,7 @@ __export(platform_exports, {
39
39
  AssetsModule: () => AssetsModule,
40
40
  AuthModule: () => AuthModule,
41
41
  AutomationsModule: () => AutomationsModule,
42
+ BlueprintsModule: () => BlueprintsModule,
42
43
  CollectionsModule: () => CollectionsModule,
43
44
  EmailEventSubscriptionsModule: () => EmailEventSubscriptionsModule,
44
45
  EmailTemplatesClient: () => EmailTemplatesClient,
@@ -403,6 +404,9 @@ var HttpClient = class _HttpClient {
403
404
  errorText
404
405
  );
405
406
  }
407
+ if (options?.responseType === "binary") {
408
+ return await this.readBinary(response, method, endpoint);
409
+ }
406
410
  const data = await this.readBody(response, method, endpoint);
407
411
  if (this.debug && data !== void 0) {
408
412
  const sanitized = this.sanitizeForLogging(data);
@@ -448,12 +452,34 @@ var HttpClient = class _HttpClient {
448
452
  );
449
453
  }
450
454
  }
455
+ /** A successful response's bytes; a 204/205 is an empty array. A failed read is a network error. */
456
+ async readBinary(response, method, endpoint) {
457
+ const contentType = response.headers.get("content-type");
458
+ if (response.status === 204 || response.status === 205) {
459
+ return { data: new Uint8Array(0), contentType };
460
+ }
461
+ try {
462
+ return { data: new Uint8Array(await response.arrayBuffer()), contentType };
463
+ } catch (error) {
464
+ const cause = error instanceof Error ? error : void 0;
465
+ throw new MarvinNetworkError(
466
+ `Reading the ${response.status} response to ${method} ${endpoint} failed: ${cause?.message ?? String(error)}`,
467
+ cause
468
+ );
469
+ }
470
+ }
451
471
  /**
452
472
  * GET request
453
473
  */
454
474
  async get(endpoint, params) {
455
475
  return this.request("GET", endpoint, { params });
456
476
  }
477
+ /**
478
+ * GET a binary body (a file download). Follows redirects; retried like any GET.
479
+ */
480
+ async getBinary(endpoint, params) {
481
+ return this.request("GET", endpoint, { params, responseType: "binary" });
482
+ }
457
483
  /**
458
484
  * POST request
459
485
  */
@@ -534,6 +560,12 @@ var EntriesModule = class {
534
560
  async list() {
535
561
  return this.http.get("/api/platform/entries");
536
562
  }
563
+ /**
564
+ * Entry counts by status, zero-filled, plus `total` (what the sidebar's inbox badge reads).
565
+ */
566
+ async counts() {
567
+ return this.http.get("/api/platform/entries/counts");
568
+ }
537
569
  /**
538
570
  * Get a single entry by ID
539
571
  */
@@ -587,6 +619,38 @@ var EntriesModule = class {
587
619
  const validCollectionId = this.http.validatePathParam(collectionId, "collection ID");
588
620
  return this.http.delete(`/api/platform/entries/${validEntryId}/collections/${validCollectionId}`);
589
621
  }
622
+ /**
623
+ * Apply the entry's staged AI suggestion (`suggestionJson`) and clear it — the approval half of
624
+ * AI write-back. Returns the updated entry.
625
+ */
626
+ async applySuggestion(id) {
627
+ const validId = this.http.validatePathParam(id, "entry ID");
628
+ return this.http.post(`/api/platform/entries/${validId}/apply-suggestion`, {});
629
+ }
630
+ /**
631
+ * Discard the entry's staged AI suggestion without applying it.
632
+ */
633
+ async rejectSuggestion(id) {
634
+ const validId = this.http.validatePathParam(id, "entry ID");
635
+ return this.http.post(`/api/platform/entries/${validId}/reject-suggestion`, {});
636
+ }
637
+ /**
638
+ * Approve an AI-suggested asset on an entry: it becomes a normal attached asset (and reaches
639
+ * published output).
640
+ */
641
+ async approveSuggestedAsset(entryId, assetId) {
642
+ const e = this.http.validatePathParam(entryId, "entry ID");
643
+ const a = this.http.validatePathParam(assetId, "asset ID");
644
+ return this.http.post(`/api/platform/entries/${e}/suggested-assets/${a}/approve`, {});
645
+ }
646
+ /**
647
+ * Reject an AI-suggested asset: unlink it, and delete the asset if nothing else uses it.
648
+ */
649
+ async rejectSuggestedAsset(entryId, assetId) {
650
+ const e = this.http.validatePathParam(entryId, "entry ID");
651
+ const a = this.http.validatePathParam(assetId, "asset ID");
652
+ return this.http.post(`/api/platform/entries/${e}/suggested-assets/${a}/reject`, {});
653
+ }
590
654
  };
591
655
 
592
656
  // src/platform/collections.ts
@@ -627,6 +691,22 @@ var CollectionsModule = class {
627
691
  smartRules: rules
628
692
  });
629
693
  }
694
+ /**
695
+ * Preview unsaved smart-collection rules: how many items they match (`total`) and the first
696
+ * `limit` of them (default 10, at most 50), evaluated by the same code that materializes
697
+ * membership on save. Saves nothing. Needs EDITOR.
698
+ */
699
+ async preview(request) {
700
+ return this.http.post("/api/platform/collections/preview", request);
701
+ }
702
+ /**
703
+ * A collection's members, whatever it groups — entries, assets or resources — as
704
+ * `{id, label, slug, type}`, ordered by label.
705
+ */
706
+ async members(id) {
707
+ const validId = this.http.validatePathParam(id, "collection ID");
708
+ return this.http.get(`/api/platform/collections/${validId}/members`);
709
+ }
630
710
  /**
631
711
  * Update a collection
632
712
  */
@@ -800,6 +880,20 @@ var ResourcesModule = class {
800
880
  async getEntries(id) {
801
881
  return this.http.get(`/api/platform/resources/${id}/entries`);
802
882
  }
883
+ /**
884
+ * Apply the resource's staged AI suggestion (`suggestionJson`) and clear it. Needs EDITOR.
885
+ */
886
+ async applySuggestion(id) {
887
+ const validId = this.http.validatePathParam(id, "resource ID");
888
+ return this.http.post(`/api/platform/resources/${validId}/apply-suggestion`, {});
889
+ }
890
+ /**
891
+ * Discard the resource's staged AI suggestion without applying it. Needs EDITOR.
892
+ */
893
+ async rejectSuggestion(id) {
894
+ const validId = this.http.validatePathParam(id, "resource ID");
895
+ return this.http.post(`/api/platform/resources/${validId}/reject-suggestion`, {});
896
+ }
803
897
  };
804
898
 
805
899
  // src/platform/assets.ts
@@ -914,11 +1008,19 @@ var AssetsModule = class {
914
1008
  return this.http.delete(`/api/platform/assets/${validId}`);
915
1009
  }
916
1010
  /**
917
- * Fetch the raw file for an asset
1011
+ * Download an asset's file: its bytes and content type. A redirect to storage is followed.
918
1012
  */
919
- async getFile(id) {
1013
+ async download(id) {
920
1014
  const validId = this.http.validatePathParam(id, "asset ID");
921
- return this.http.get(`/api/platform/assets/${validId}/file`);
1015
+ return this.http.getBinary(`/api/platform/assets/${validId}/file`);
1016
+ }
1017
+ /**
1018
+ * Fetch the raw file for an asset.
1019
+ * @deprecated Use {@link download}, which is typed. (Before 4.3 this resolved to `undefined` for
1020
+ * any file that wasn't JSON; it now returns the same `BinaryResponse` as `download`.)
1021
+ */
1022
+ async getFile(id) {
1023
+ return this.download(id);
922
1024
  }
923
1025
  /**
924
1026
  * Get download URL for an asset file
@@ -929,6 +1031,20 @@ var AssetsModule = class {
929
1031
  const base = baseUrl || (typeof window !== "undefined" && window.location ? window.location.origin : "");
930
1032
  return `${base}/api/platform/assets/${validId}/file`;
931
1033
  }
1034
+ /**
1035
+ * Apply the asset's staged AI suggestion (`suggestionJson`) and clear it. Needs EDITOR.
1036
+ */
1037
+ async applySuggestion(id) {
1038
+ const validId = this.http.validatePathParam(id, "asset ID");
1039
+ return this.http.post(`/api/platform/assets/${validId}/apply-suggestion`, {});
1040
+ }
1041
+ /**
1042
+ * Discard the asset's staged AI suggestion without applying it. Needs EDITOR.
1043
+ */
1044
+ async rejectSuggestion(id) {
1045
+ const validId = this.http.validatePathParam(id, "asset ID");
1046
+ return this.http.post(`/api/platform/assets/${validId}/reject-suggestion`, {});
1047
+ }
932
1048
  };
933
1049
 
934
1050
  // src/platform/apiClients.ts
@@ -1179,6 +1295,13 @@ var WorkspacesModule = class {
1179
1295
  async getStats() {
1180
1296
  return this.http.get("/api/platform/stats");
1181
1297
  }
1298
+ /**
1299
+ * The current workspace's dashboard: recent activity and the "needs attention" counts (inbox,
1300
+ * drafts, entries needing review, pending AI suggestions, failures in the last 7 days).
1301
+ */
1302
+ async getDashboard() {
1303
+ return this.http.get("/api/platform/stats/dashboard");
1304
+ }
1182
1305
  /**
1183
1306
  * List available workspace backups
1184
1307
  */
@@ -2875,6 +2998,10 @@ var IncomingWebhooksModule = class {
2875
2998
  async list() {
2876
2999
  return this.http.get("/api/incoming-webhooks");
2877
3000
  }
3001
+ /** The signature schemes a webhook can pick (`signatureScheme`). */
3002
+ async signatureSchemes() {
3003
+ return this.http.get("/api/incoming-webhooks/signature-schemes");
3004
+ }
2878
3005
  async get(id) {
2879
3006
  const validId = this.http.validatePathParam(id, "incoming webhook id");
2880
3007
  return this.http.get(`/api/incoming-webhooks/${validId}`);
@@ -2903,6 +3030,59 @@ var IncomingWebhooksModule = class {
2903
3030
  }
2904
3031
  };
2905
3032
 
3033
+ // src/platform/blueprints.ts
3034
+ var BASE2 = "/api/groups/blueprints";
3035
+ var BlueprintsModule = class {
3036
+ constructor(http) {
3037
+ this.http = http;
3038
+ }
3039
+ http;
3040
+ query(options = {}) {
3041
+ return this.http.buildQueryString({ source: options.source, integration_id: options.integrationId });
3042
+ }
3043
+ /** The catalog, annotated with what this workspace can do about each blueprint. */
3044
+ async list(options = {}) {
3045
+ return this.http.get(BASE2, {
3046
+ kind: options.kind,
3047
+ category: options.category,
3048
+ source: options.source,
3049
+ integration_id: options.integrationId
3050
+ });
3051
+ }
3052
+ /** Category names in catalog order: core's first, then each provider's. */
3053
+ async categories() {
3054
+ return this.http.get(`${BASE2}/categories`);
3055
+ }
3056
+ /** One blueprint, including its payload. */
3057
+ async get(slug, options = {}) {
3058
+ const validSlug = this.http.validatePathParam(slug, "blueprint slug");
3059
+ return this.http.get(`${BASE2}/${validSlug}`, { source: options.source });
3060
+ }
3061
+ /**
3062
+ * Create this blueprint's object in the workspace if it isn't there yet. `params` fills the
3063
+ * parameters the blueprint declares, e.g. `{ entry_type: 'post' }`. Needs ADMIN.
3064
+ */
3065
+ async apply(slug, params, options = {}) {
3066
+ const validSlug = this.http.validatePathParam(slug, "blueprint slug");
3067
+ return this.http.post(`${BASE2}/${validSlug}/apply${this.query(options)}`, params);
3068
+ }
3069
+ /**
3070
+ * Apply several blueprints at once; entry types are created before the collections and tasks that
3071
+ * use them, whatever the order here. `params` is keyed by blueprint slug. Needs ADMIN.
3072
+ */
3073
+ async applyMany(slugs, params, options = {}) {
3074
+ return this.http.post(`${BASE2}/apply${this.query(options)}`, {
3075
+ slugs,
3076
+ ...params ? { params } : {}
3077
+ });
3078
+ }
3079
+ /** Replace an applied workflow's steps with what its integration declares now. Needs ADMIN. */
3080
+ async update(slug, params, options = {}) {
3081
+ const validSlug = this.http.validatePathParam(slug, "blueprint slug");
3082
+ return this.http.post(`${BASE2}/${validSlug}/update${this.query(options)}`, params);
3083
+ }
3084
+ };
3085
+
2906
3086
  // src/platform/site.ts
2907
3087
  var REBUILD = "/api/platform/site/rebuild";
2908
3088
  var SiteModule = class {
@@ -2969,6 +3149,8 @@ var PlatformClient = class extends HttpClient {
2969
3149
  automations;
2970
3150
  // Incoming (ingress) webhooks — tokened endpoints that drop events on the bus.
2971
3151
  incomingWebhooks;
3152
+ /** Blueprint catalog: browse and apply collections, entry types, tasks and workflows */
3153
+ blueprints;
2972
3154
  // Site — request a rebuild of the workspace's static site and read its status.
2973
3155
  site;
2974
3156
  // Admin modules
@@ -3013,6 +3195,7 @@ var PlatformClient = class extends HttpClient {
3013
3195
  this.ai = new AIModule(this);
3014
3196
  this.automations = new AutomationsModule(this);
3015
3197
  this.incomingWebhooks = new IncomingWebhooksModule(this);
3198
+ this.blueprints = new BlueprintsModule(this);
3016
3199
  this.site = new SiteModule(this);
3017
3200
  this.adminUsers = new AdminUsersModule(this);
3018
3201
  this.adminSystem = new AdminSystemModule(this);
@@ -3048,6 +3231,7 @@ function createPlatformClient(config) {
3048
3231
  AssetsModule,
3049
3232
  AuthModule,
3050
3233
  AutomationsModule,
3234
+ BlueprintsModule,
3051
3235
  CollectionsModule,
3052
3236
  EmailEventSubscriptionsModule,
3053
3237
  EmailTemplatesClient,