@fusebase/fusebase-gate-sdk 2.3.34-sdk.9 → 2.5.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.
@@ -84,8 +84,41 @@ export interface PublishPortalDraftResponseContract {
84
84
  /** Always true: the staged draft is now live on the portal. */
85
85
  published: boolean;
86
86
  }
87
+ export interface CreatePortalPageRequestContract {
88
+ /**
89
+ * Title for the new empty page (also used as its sidebar item name).
90
+ * @maxLength 100
91
+ */
92
+ title: string;
93
+ /**
94
+ * Optional id of an existing published or active-draft menu item (e.g. a
95
+ * folder) to nest the page under in the sidebar. When omitted the page is
96
+ * created at the portal root.
97
+ */
98
+ parentId?: string;
99
+ }
100
+ export interface CreatePortalPageResponseContract {
101
+ /** Id of the created sidebar menu item. */
102
+ menuItemId: string;
103
+ /** Id of the created portal page node. */
104
+ pageId: string;
105
+ /** URL path assigned to the page (e.g. "/welcome"). */
106
+ url: string;
107
+ /** Draft branch the change was staged on. */
108
+ branchId: string;
109
+ /** Sequence numbers assigned to the staged change events (addPage, addMenuItem). */
110
+ seqs: number[];
111
+ /**
112
+ * Always true: the page is staged in the portal's customizer draft, not yet
113
+ * live. The portal owner reviews and publishes it from the customizer.
114
+ */
115
+ staged: boolean;
116
+ }
87
117
  export interface CreatePortalPageWithNoteRequestContract {
88
- /** Title for the new page (also used as the backing Fusebase note title). */
118
+ /**
119
+ * Title for the new page (also used as the backing Fusebase note title).
120
+ * @maxLength 100
121
+ */
89
122
  title: string;
90
123
  /**
91
124
  * Optional id of an existing menu item (e.g. a folder) to nest the page under
@@ -126,6 +159,27 @@ export interface AddPortalNoteBlockRequestContract {
126
159
  /** Optional block title (defaults to the page's current title). */
127
160
  title?: string;
128
161
  }
162
+ export interface AddPortalBlankNoteBlockRequestContract {
163
+ /** Optional block title (defaults to "New Document"). */
164
+ title?: string;
165
+ }
166
+ export interface AddPortalBlankNoteBlockResponseContract {
167
+ /** Global id of the newly created Fusebase note backing the block. */
168
+ noteId: string;
169
+ /** Id of the created note block. */
170
+ blockId: string;
171
+ /** Id of the page the block was added to. */
172
+ pageId: string;
173
+ /** Draft branch the change was staged on. */
174
+ branchId: string;
175
+ /** Sequence numbers assigned to the staged change events (addBlock). */
176
+ seqs: number[];
177
+ /**
178
+ * Always true: the block is staged in the portal's customizer draft, not yet
179
+ * live. The portal owner reviews and publishes it from the customizer.
180
+ */
181
+ staged: boolean;
182
+ }
129
183
  export interface AddPortalNoteBlockResponseContract {
130
184
  /** Id of the created note content block. */
131
185
  blockId: string;
@@ -141,12 +195,654 @@ export interface AddPortalNoteBlockResponseContract {
141
195
  */
142
196
  staged: boolean;
143
197
  }
198
+ /**
199
+ * The 11 Customizer "Embeds & Integrations" chooser variants. The internal
200
+ * legacy `unknown` is intentionally excluded — it is not a create option.
201
+ */
202
+ export type PortalEmbedType = "custom" | "youtube" | "google-drive" | "ms-doc" | "calendly" | "hubspot" | "airtable" | "loom" | "data-studio" | "figma" | "miro";
203
+ export interface AddPortalEmbedBlockRequestContract {
204
+ /** Required non-empty block title. */
205
+ title: string;
206
+ /** Customizer Embed variant. `unknown` is not accepted. */
207
+ embedType: PortalEmbedType;
208
+ /** Required for named variants, forbidden for `custom`: the URL to embed. */
209
+ url?: string;
210
+ /** Required for `custom`, forbidden for named variants: the embed code/URL. */
211
+ content?: string;
212
+ /** Whether to show the "open in new tab" link on the block. Default: true. */
213
+ showEmbedLink?: boolean;
214
+ /** Block width in grid columns. Default: 3. */
215
+ colspan?: 2 | 3 | 4 | 5 | 6;
216
+ /** Block height in grid rows. Default: 1. */
217
+ rowspan?: 1 | 2 | 3 | 4;
218
+ /** Fixed pixel height, or null to auto-size. Default: null. */
219
+ height?: number | null;
220
+ }
221
+ export interface AddPortalEmbedBlockResponseContract {
222
+ /** Id of the created embed block. */
223
+ blockId: string;
224
+ /** Id of the page the block was added to. */
225
+ pageId: string;
226
+ /** Draft branch the change was staged on. */
227
+ branchId: string;
228
+ /** Sequence numbers assigned to the staged change events (addBlock). */
229
+ seqs: number[];
230
+ /**
231
+ * Always true: the block is staged in the portal's customizer draft, not yet
232
+ * live. The portal owner reviews and publishes it from the customizer.
233
+ */
234
+ staged: boolean;
235
+ }
236
+ /** Customizer "Type" for the Database block: a database table, or a shared dashboard. */
237
+ export type PortalDatabaseBlockTargetContract = {
238
+ /** Customizer Type: Database. */
239
+ type: "database";
240
+ databaseId: string;
241
+ /** Database-bound dashboard (Customizer label: Table). */
242
+ dashboardId: string;
243
+ viewId: string;
244
+ } | {
245
+ /** Customizer Type: Dashboard. */
246
+ type: "dashboard";
247
+ /** Shared dashboard source, e.g. All forms. */
248
+ dashboardId: string;
249
+ viewId: string;
250
+ };
251
+ /**
252
+ * Customizer background picker. Colors are Tailwind palette tokens
253
+ * (e.g. `red-200`, `orange-900`), never HEX; raw CSS is not accepted.
254
+ */
255
+ export type PortalBackgroundContract = {
256
+ type: "color";
257
+ color: string;
258
+ } | {
259
+ type: "gradient";
260
+ from: string;
261
+ to: string;
262
+ /** Default: `to-b`. */
263
+ direction?: "to-t" | "to-b" | "to-r" | "to-l";
264
+ } | {
265
+ type: "image";
266
+ image: {
267
+ url: string;
268
+ };
269
+ };
270
+ /** Customizer Appearance section. Only `custom` carries the extra controls. */
271
+ export type PortalDatabaseBlockAppearanceContract = {
272
+ backdrop: "none" | "blank";
273
+ } | {
274
+ backdrop: "custom";
275
+ background: PortalBackgroundContract;
276
+ /** Default: `m`. */
277
+ padding?: "none" | "s" | "m" | "l";
278
+ /** Default: true. */
279
+ showTitle?: boolean;
280
+ };
281
+ /** Customizer Layout section. */
282
+ export interface PortalDatabaseBlockLayoutContract {
283
+ /** Customizer Width. Default: 6. */
284
+ colspan?: 2 | 3 | 4 | 5 | 6;
285
+ /** Customizer Height: null = Auto; a manual value is at least 50px. Default: null. */
286
+ height?: number | null;
287
+ }
288
+ export interface AddPortalDatabaseBlockRequestContract {
289
+ /** Exact ids from listPortalDatabaseBlockSources; names and aliases are rejected. */
290
+ target: PortalDatabaseBlockTargetContract;
291
+ /** Block title. Default: "Database". */
292
+ title?: string;
293
+ /** Rows shown per page. Default: 100. */
294
+ itemsPerPage?: 10 | 20 | 50 | 100 | 200 | 500;
295
+ /** Visual wrapper of the portal block. Default: `{ backdrop: "blank" }`. */
296
+ appearance?: PortalDatabaseBlockAppearanceContract;
297
+ /** Grid placement. Default: width 6 columns and automatic height. */
298
+ layout?: PortalDatabaseBlockLayoutContract;
299
+ }
300
+ export interface AddPortalDatabaseBlockResponseContract {
301
+ /** Id of the created database block. */
302
+ blockId: string;
303
+ /** Id of the page the block was added to. */
304
+ pageId: string;
305
+ /** Draft branch the change was staged on. */
306
+ branchId: string;
307
+ /** Sequence numbers assigned to the staged change events (addBlock). */
308
+ seqs: number[];
309
+ /** Always true: the block is staged in the customizer draft, not yet live. */
310
+ staged: boolean;
311
+ }
312
+ /**
313
+ * One exact token of the Customizer common palette: `transparent`, `white`,
314
+ * `black` or `<hue>-<shade>` (e.g. `cyan-700`). HEX, rgb()/hsl(), CSS variables,
315
+ * `text-*`/`bg-*` classes and opacity values are rejected.
316
+ */
317
+ export type PortalColorToken = string;
318
+ /**
319
+ * The palette token pattern, repeated on every colour property: a type alias to
320
+ * `string` carries no JSDoc tag into the generated schema, so the `@pattern`
321
+ * has to sit on the property itself.
322
+ */
323
+ export type PortalTextSize = "s" | "m" | "l" | "xl";
324
+ export type PortalTextStyle = "bold" | "italic" | "underline" | "lineThrough";
325
+ export type PortalTextAlign = "left" | "center" | "right" | "justify";
326
+ /** The five Customizer preset background images. No URL or upload is accepted. */
327
+ export type PortalBackgroundImagePreset = "azure" | "mira" | "solis" | "serenity" | "glow";
328
+ /**
329
+ * Customizer background picker for a Text & Media block. Colours are palette
330
+ * tokens; an image is one of the five built-in presets.
331
+ */
332
+ export type PortalTextBackgroundContract = {
333
+ type: "color";
334
+ /** @pattern ^(transparent|white|black|(slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(50|100|200|300|400|500|600|700|800|900|950))$ */
335
+ color: PortalColorToken;
336
+ } | {
337
+ type: "gradient";
338
+ /** @pattern ^(transparent|white|black|(slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(50|100|200|300|400|500|600|700|800|900|950))$ */
339
+ from: PortalColorToken;
340
+ /** @pattern ^(transparent|white|black|(slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(50|100|200|300|400|500|600|700|800|900|950))$ */
341
+ to: PortalColorToken;
342
+ /** Default: `to-t`. */
343
+ direction?: "to-t" | "to-r" | "to-b" | "to-l";
344
+ } | {
345
+ type: "image";
346
+ preset: PortalBackgroundImagePreset;
347
+ /** Default: false. */
348
+ blur?: boolean;
349
+ };
350
+ /** Customizer Appearance section. Only `custom` carries the extra controls. */
351
+ export type PortalFlexibleTextAppearanceContract = {
352
+ backdrop: "none" | "blank";
353
+ } | {
354
+ backdrop: "custom";
355
+ background: PortalTextBackgroundContract;
356
+ /** Default: `s`. */
357
+ padding?: "none" | "s" | "m" | "l";
358
+ /** Default: false. */
359
+ showTitle?: boolean;
360
+ };
361
+ /** Customizer Layout section shared by the three Text & Media operations. */
362
+ export interface PortalTextAndMediaLayoutContract {
363
+ /** Customizer Width. Default: 6. */
364
+ colspan?: 2 | 3 | 4 | 5 | 6;
365
+ /**
366
+ * Customizer Height: null = Auto; a manual value is at least 50px. Default: null.
367
+ * @minimum 50
368
+ */
369
+ height?: number | null;
370
+ }
371
+ /** Customizer Content section of a Heading or Simple text block. */
372
+ export interface PortalTextContentContract {
373
+ /**
374
+ * Plain text. Only `{{ClientName}}` and `{{ClientLastName}}` are variables.
375
+ * @maxLength 5000
376
+ */
377
+ text?: string;
378
+ /** @pattern ^(transparent|white|black|(slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(50|100|200|300|400|500|600|700|800|900|950))$ */
379
+ color?: PortalColorToken;
380
+ size?: PortalTextSize;
381
+ /** Set semantics: a duplicate value is rejected by portal-service with 400. */
382
+ styles?: PortalTextStyle[];
383
+ align?: PortalTextAlign;
384
+ }
385
+ export interface AddPortalHeadingBlockRequestContract {
386
+ /** Defaults: text "Your Title Goes Here", size `l`, no styles, left alignment. */
387
+ content?: PortalTextContentContract;
388
+ /** Default: `{ backdrop: "blank" }`. */
389
+ appearance?: PortalFlexibleTextAppearanceContract;
390
+ /** Default: width 6 columns and automatic height. */
391
+ layout?: PortalTextAndMediaLayoutContract;
392
+ }
393
+ export interface AddPortalTextBlockRequestContract {
394
+ /** Defaults: the Customizer's Simple text copy, size `m`, no styles, left alignment. */
395
+ content?: PortalTextContentContract;
396
+ /** Default: `{ backdrop: "blank" }`. */
397
+ appearance?: PortalFlexibleTextAppearanceContract;
398
+ /** Default: width 6 columns and automatic height. */
399
+ layout?: PortalTextAndMediaLayoutContract;
400
+ }
401
+ /** The Image block always stages the Customizer's stock image: only Layout applies. */
402
+ export interface AddPortalImageBlockRequestContract {
403
+ /** Default: width 6 columns and automatic height. */
404
+ layout?: PortalTextAndMediaLayoutContract;
405
+ }
406
+ export interface PortalTextAndMediaBlockResponseContract {
407
+ /** Id of the created block. */
408
+ blockId: string;
409
+ /** Id of the page the block was added to. */
410
+ pageId: string;
411
+ /** Draft branch the change was staged on. */
412
+ branchId: string;
413
+ /** Sequence numbers assigned to the staged change events (addBlock). */
414
+ seqs: number[];
415
+ /** Always true: the block is staged in the customizer draft, not yet live. */
416
+ staged: boolean;
417
+ }
418
+ /**
419
+ * Customizer background picker. Colours are palette tokens; an image is one of
420
+ * the five built-in presets.
421
+ */
422
+ export type PortalCardBackgroundContract = {
423
+ type: "color";
424
+ /** @pattern ^(transparent|white|black|(slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(50|100|200|300|400|500|600|700|800|900|950))$ */
425
+ color: PortalColorToken;
426
+ } | {
427
+ type: "gradient";
428
+ /** @pattern ^(transparent|white|black|(slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(50|100|200|300|400|500|600|700|800|900|950))$ */
429
+ from: PortalColorToken;
430
+ /** @pattern ^(transparent|white|black|(slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(50|100|200|300|400|500|600|700|800|900|950))$ */
431
+ to: PortalColorToken;
432
+ /** Default: `to-t`. */
433
+ direction?: "to-t" | "to-r" | "to-b" | "to-l";
434
+ } | {
435
+ type: "image";
436
+ preset: PortalBackgroundImagePreset;
437
+ /** Default: false. */
438
+ blur?: boolean;
439
+ };
440
+ /** The four Card Types of the Customizer's Card tile. `compact` is legacy and rejected. */
441
+ export type PortalCardViewContract = "top-image" | "left-image" | "right-image" | "fill-image";
442
+ /**
443
+ * Customizer Appearance section of a Card. Omitting `appearance` keeps the
444
+ * Card's canonical `bare` wrapper, which is not a selectable backdrop.
445
+ */
446
+ export type PortalCardAppearanceContract = {
447
+ backdrop: "none" | "blank";
448
+ } | {
449
+ backdrop: "custom";
450
+ background: PortalCardBackgroundContract;
451
+ /** Default: `s`. */
452
+ padding?: "none" | "s" | "m" | "l";
453
+ /** Default: false. */
454
+ showTitle?: boolean;
455
+ };
456
+ /** Customizer Layout section of a Card. */
457
+ export interface PortalCardLayoutContract {
458
+ /** Customizer Width. Default: 3. */
459
+ colspan?: 2 | 3 | 4 | 5 | 6;
460
+ /**
461
+ * Customizer Height: null = Auto; a manual value is at least 50px. Default: null.
462
+ * @minimum 50
463
+ */
464
+ height?: number | null;
465
+ }
466
+ /**
467
+ * A hidden Card item carries ONLY `visible: false`: sending text or styles next
468
+ * to it would silently drop settings the caller believes they applied.
469
+ */
470
+ export type PortalCardHeadingContract = {
471
+ visible: false;
472
+ } | {
473
+ /** Default: true. */
474
+ visible?: true;
475
+ /**
476
+ * Plain text. Only `{{ClientName}}` and `{{ClientLastName}}` are variables.
477
+ * @minLength 1
478
+ * @maxLength 100
479
+ */
480
+ text?: string;
481
+ /** @pattern ^(transparent|white|black|(slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(50|100|200|300|400|500|600|700|800|900|950))$ */
482
+ color?: PortalColorToken;
483
+ size?: PortalTextSize;
484
+ /** Set semantics: a duplicate value is rejected with 400. */
485
+ styles?: PortalTextStyle[];
486
+ align?: PortalTextAlign;
487
+ };
488
+ export type PortalCardDescriptionContract = {
489
+ visible: false;
490
+ } | {
491
+ /** Default: true. */
492
+ visible?: true;
493
+ /**
494
+ * Plain text. Only `{{ClientName}}` and `{{ClientLastName}}` are variables.
495
+ * @minLength 1
496
+ * @maxLength 2000
497
+ */
498
+ text?: string;
499
+ /** @pattern ^(transparent|white|black|(slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(50|100|200|300|400|500|600|700|800|900|950))$ */
500
+ color?: PortalColorToken;
501
+ size?: PortalTextSize;
502
+ /** Set semantics: a duplicate value is rejected with 400. */
503
+ styles?: PortalTextStyle[];
504
+ align?: PortalTextAlign;
505
+ };
506
+ export type PortalCardButtonContract = {
507
+ visible: false;
508
+ } | {
509
+ /** Default: true. */
510
+ visible?: true;
511
+ /**
512
+ * Plain text; the Button label supports no dynamic variables.
513
+ * @minLength 1
514
+ * @maxLength 100
515
+ */
516
+ text?: string;
517
+ };
518
+ /** The Card always uses the template image: no source field is accepted. */
519
+ export interface PortalCardImageContract {
520
+ /** Default: true. */
521
+ visible?: boolean;
522
+ }
523
+ /** Semantic Destination of the whole Card (and of its Button). */
524
+ export type PortalCardDestinationContract = {
525
+ type: "portalPage";
526
+ /** Exact id of an existing page in the SAME portal. */
527
+ pageId: string;
528
+ } | {
529
+ type: "external";
530
+ /**
531
+ * Absolute https:// URL. `javascript:`, `data:`, a protocol-relative URL
532
+ * and embedded credentials are rejected.
533
+ * @maxLength 2048
534
+ */
535
+ url: string;
536
+ } | {
537
+ type: "email";
538
+ /**
539
+ * Address only; portal-service adds the `mailto:` scheme.
540
+ * @maxLength 254
541
+ */
542
+ email: string;
543
+ };
544
+ /** Customizer Content section of a Card. */
545
+ export interface PortalCardContentContract {
546
+ image?: PortalCardImageContract;
547
+ /** Default: "Helpful Resources", bold. */
548
+ heading?: PortalCardHeadingContract;
549
+ /** Default: the Customizer's Card copy. */
550
+ description?: PortalCardDescriptionContract;
551
+ /** Default: "Explore". */
552
+ button?: PortalCardButtonContract;
553
+ /**
554
+ * Omitted keeps the Customizer default link; `null` leaves the Card without
555
+ * any destination.
556
+ */
557
+ destination?: PortalCardDestinationContract | null;
558
+ }
559
+ export interface AddPortalCardBlockRequestContract {
560
+ /** Card Type. Default: `top-image`. */
561
+ view?: PortalCardViewContract;
562
+ content?: PortalCardContentContract;
563
+ /** Omitted keeps the Card's canonical bare wrapper. */
564
+ appearance?: PortalCardAppearanceContract;
565
+ /** Default: width 3 columns and automatic height. */
566
+ layout?: PortalCardLayoutContract;
567
+ }
568
+ export interface AddPortalCardBlockResponseContract {
569
+ /** Id of the created block. */
570
+ blockId: string;
571
+ /** Id of the page the block was added to. */
572
+ pageId: string;
573
+ /** Draft branch the change was staged on. */
574
+ branchId: string;
575
+ /** Sequence numbers assigned to the staged change events (addBlock). */
576
+ seqs: number[];
577
+ /** Always true: the block is staged in the customizer draft, not yet live. */
578
+ staged: boolean;
579
+ }
580
+ /** Customizer Layout section of a Carousel. */
581
+ export interface PortalCarouselLayoutContract {
582
+ /** Customizer Width. Default: 6. */
583
+ colspan?: 2 | 3 | 4 | 5 | 6;
584
+ /**
585
+ * Customizer Height: null = Auto; a manual value is at least 50px. Default: null.
586
+ * @minimum 50
587
+ */
588
+ height?: number | null;
589
+ }
590
+ /**
591
+ * One Carousel slide. The image is always a built-in one, and the index comes
592
+ * from the array order: neither is accepted from the caller.
593
+ */
594
+ export interface PortalCarouselItemContract {
595
+ /**
596
+ * Plain text; the caption supports no dynamic variables.
597
+ * @minLength 1
598
+ */
599
+ caption?: string;
600
+ /**
601
+ * Plain text. Only `{{ClientName}}` and `{{ClientLastName}}` are variables.
602
+ * @minLength 1
603
+ */
604
+ description?: string;
605
+ /** `null` or omitted leaves the slide without a Button. */
606
+ button?: {
607
+ /**
608
+ * Plain label; the Button supports no dynamic variables.
609
+ * @minLength 1
610
+ */
611
+ text: string;
612
+ } | null;
613
+ /**
614
+ * Destination of both the slide surface and its Button. `null` or omitted
615
+ * leaves the slide without a link.
616
+ */
617
+ destination?: PortalCardDestinationContract | null;
618
+ }
619
+ /** Customizer Content section of a Carousel. */
620
+ export interface PortalCarouselContentContract {
621
+ /**
622
+ * The full desired slide list in visual order, not a patch. Omitting it keeps
623
+ * the three factory slides (Deliberation, Elaboration, Presentation).
624
+ * Server-side limits: 1 to 6 slides.
625
+ */
626
+ items?: PortalCarouselItemContract[];
627
+ }
628
+ export interface AddPortalCarouselBlockRequestContract {
629
+ content?: PortalCarouselContentContract;
630
+ /** Default: width 6 columns and automatic height. */
631
+ layout?: PortalCarouselLayoutContract;
632
+ }
633
+ export interface AddPortalCarouselBlockResponseContract {
634
+ /** Id of the created block. */
635
+ blockId: string;
636
+ /** Id of the page the block was added to. */
637
+ pageId: string;
638
+ /** Draft branch the change was staged on. */
639
+ branchId: string;
640
+ /** Sequence numbers assigned to the staged change events (addBlock). */
641
+ seqs: number[];
642
+ /** Always true: the block is staged in the customizer draft, not yet live. */
643
+ staged: boolean;
644
+ }
645
+ /**
646
+ * Customizer Appearance section of a Countdown. Omitting `appearance` keeps the
647
+ * Countdown's canonical `blank` backdrop with the block title shown.
648
+ */
649
+ export type PortalCountdownAppearanceContract = {
650
+ backdrop: "none" | "blank";
651
+ } | {
652
+ backdrop: "custom";
653
+ background: PortalCardBackgroundContract;
654
+ /** Default: `s`. */
655
+ padding?: "none" | "s" | "m" | "l";
656
+ /** Default: true. */
657
+ showTitle?: boolean;
658
+ };
659
+ /** Customizer Layout section of a Countdown. */
660
+ export interface PortalCountdownLayoutContract {
661
+ /** Customizer Width. Default: 6. */
662
+ colspan?: 2 | 3 | 4 | 5 | 6;
663
+ /**
664
+ * Customizer Height: null = Auto; a manual value is at least 50px. Default: null.
665
+ * @minimum 50
666
+ */
667
+ height?: number | null;
668
+ }
669
+ /** Customizer Content section of a Countdown. */
670
+ export interface PortalCountdownContentContract {
671
+ /**
672
+ * The moment the countdown ends, as an absolute RFC 3339 date-time carrying
673
+ * `Z` or an explicit UTC offset, for example `2026-08-15T09:00:00+07:00`.
674
+ * Never epoch seconds/milliseconds and never a timezone-less local date.
675
+ * Default: 30 days after creation. Server-side limits: not in the past and at
676
+ * most 99 days after creation.
677
+ * @format date-time
678
+ */
679
+ targetAt?: string;
680
+ }
681
+ export interface AddPortalCountdownBlockRequestContract {
682
+ /**
683
+ * Block title shown above the countdown. Plain text; only `{{ClientName}}`
684
+ * and `{{ClientLastName}}` are variables. Default: `Countdown`.
685
+ * @minLength 1
686
+ * @maxLength 100
687
+ */
688
+ title?: string;
689
+ content?: PortalCountdownContentContract;
690
+ /** Omitted keeps the canonical blank backdrop with the title shown. */
691
+ appearance?: PortalCountdownAppearanceContract;
692
+ /** Default: width 6 columns and automatic height. */
693
+ layout?: PortalCountdownLayoutContract;
694
+ }
695
+ export interface AddPortalCountdownBlockResponseContract {
696
+ /** Id of the created block. */
697
+ blockId: string;
698
+ /** Id of the page the block was added to. */
699
+ pageId: string;
700
+ /** Draft branch the change was staged on. */
701
+ branchId: string;
702
+ /** Sequence numbers assigned to the staged change events (addBlock). */
703
+ seqs: number[];
704
+ /** Always true: the block is staged in the customizer draft, not yet live. */
705
+ staged: boolean;
706
+ }
707
+ /** One selectable view of a Database table or a shared Dashboard. */
708
+ export interface PortalDatabaseBlockViewContract {
709
+ id: string;
710
+ title: string;
711
+ isDefault: boolean;
712
+ }
713
+ /** A Database table or a shared Dashboard, with the views it offers. */
714
+ export interface PortalDatabaseBlockSourceContract {
715
+ /** Use as `target.dashboardId`. */
716
+ id: string;
717
+ title: string;
718
+ views: PortalDatabaseBlockViewContract[];
719
+ }
720
+ /**
721
+ * Compact discovery projection. Which group is present depends on the request:
722
+ * `databases` + paging for a database list, `database` + `tables` for one
723
+ * database, `dashboards` for the shared sources.
724
+ */
725
+ export interface ListPortalDatabaseBlockSourcesResponseContract {
726
+ /** `type=database` with no `databaseId`: one page of databases. */
727
+ databases?: {
728
+ id: string;
729
+ title: string;
730
+ alias?: string;
731
+ }[];
732
+ /** Current database page. */
733
+ page?: number;
734
+ /** Database page size; always 20. */
735
+ limit?: number;
736
+ /** Total databases matching the search. */
737
+ total?: number;
738
+ /** Present only while further database pages exist. */
739
+ nextPage?: number;
740
+ /** `type=database` with `databaseId`: the selected database. */
741
+ database?: {
742
+ id: string;
743
+ title: string;
744
+ };
745
+ /** Tables of the selected database. */
746
+ tables?: PortalDatabaseBlockSourceContract[];
747
+ /** `type=dashboard`: every shared dashboard source. */
748
+ dashboards?: PortalDatabaseBlockSourceContract[];
749
+ }
750
+ export interface SetDashboardViewReadonlyRequestContract {
751
+ /** True restricts editing of the view everywhere it is used. */
752
+ readonly: boolean;
753
+ }
754
+ export interface SetDashboardViewReadonlyResponseContract {
755
+ viewId: string;
756
+ readonly: boolean;
757
+ }
758
+ /** Which chat target a Chat block points at. */
759
+ export type PortalChatBlockTargetType = "channel" | "dm";
760
+ /**
761
+ * Exactly one chat target, as a discriminated union (matches the Customizer).
762
+ * A `channel` target carries only `channelId`; a `dm` target only `userId`.
763
+ */
764
+ export type PortalChatBlockTarget = {
765
+ type: "channel";
766
+ /** A channel id from listPortalChatChannels. */
767
+ channelId: string;
768
+ } | {
769
+ type: "dm";
770
+ /** An active org member/owner user id. */
771
+ userId: number;
772
+ };
773
+ export interface AddPortalChatBlockRequestContract {
774
+ /** Required non-empty block title. */
775
+ title: string;
776
+ /** Exactly one of a `channel` (channelId) or `dm` (userId) target. */
777
+ target: PortalChatBlockTarget;
778
+ /**
779
+ * Channels only: restrict posting to members. Defaults to true; forbidden for
780
+ * a `dm` target; a private channel requires true.
781
+ */
782
+ membersOnly?: boolean;
783
+ /** Block width in grid columns. Default: 6. */
784
+ colspan?: 3 | 4 | 5 | 6;
785
+ /** Block height in grid rows. Default: 1. */
786
+ rowspan?: 1 | 2 | 3 | 4;
787
+ /** Fixed pixel height, or null to auto-size. Default: null. */
788
+ height?: number | null;
789
+ }
790
+ export interface AddPortalChatBlockResponseContract {
791
+ /** Id of the created chat block. */
792
+ blockId: string;
793
+ /** Id of the page the block was added to. */
794
+ pageId: string;
795
+ /** Draft branch the change was staged on. */
796
+ branchId: string;
797
+ /** Sequence numbers assigned to the staged change events (addBlock). */
798
+ seqs: number[];
799
+ /**
800
+ * Always true: the block is staged in the portal's customizer draft, not yet
801
+ * live. The portal owner reviews and publishes it from the customizer.
802
+ */
803
+ staged: boolean;
804
+ }
805
+ export interface PortalChatChannelContract {
806
+ /** Channel id to pass to addPortalChatBlock as channelId. */
807
+ id: string;
808
+ /** Human-readable channel name. */
809
+ name: string;
810
+ /** Whether the channel is public (private channels require membersOnly). */
811
+ isPublic: boolean;
812
+ /** Whether this is the portal's default channel (returned first). */
813
+ isDefault: boolean;
814
+ }
815
+ export interface ListPortalChatChannelsResponseContract {
816
+ /** Listable chat channels, default channel first. */
817
+ channels: PortalChatChannelContract[];
818
+ }
819
+ export interface PortalChatUserContract {
820
+ /** User id to pass to addPortalChatBlock as target.userId. */
821
+ id: number;
822
+ /** Effective display name (composed name → username → email → id). */
823
+ displayName: string;
824
+ /** Username, when the user has one. */
825
+ username?: string;
826
+ /** Email, to tell apart users sharing a display name. Always present. */
827
+ email: string;
828
+ }
829
+ export interface ListPortalChatUsersResponseContract {
830
+ /** Matched DM target users (a single bounded page). */
831
+ users: PortalChatUserContract[];
832
+ /**
833
+ * Total number of matching users across all pages.
834
+ * @TJS-type integer
835
+ */
836
+ total: number;
837
+ /** Opaque cursor for the next page; absent when there are no more results. */
838
+ nextCursor?: string;
839
+ }
144
840
  /**
145
841
  * Block types the portal-service draft reducer (`blockFromDto`) understands.
146
842
  * Any other value is rejected with 400 (the reducer throws on unknown types,
147
843
  * which would otherwise fail the whole draft at publish time).
148
844
  */
149
- export type PortalBlockType = "note" | "content" | "embed" | "chat" | "info" | "docs" | "help" | "request" | "meetings" | "links" | "task-list" | "projection" | "files-dashboard" | "tasks-dashboard" | "chats-dashboard" | "files-recent" | "files-bucket" | "flexible";
845
+ export type PortalBlockType = "note" | "content" | "info" | "docs" | "help" | "request" | "meetings" | "links" | "task-list" | "projection" | "files-dashboard" | "tasks-dashboard" | "chats-dashboard" | "files-recent" | "files-bucket" | "flexible";
150
846
  export interface AddPortalBlockRequestContract {
151
847
  /** Id of the existing portal page node to add the block to. */
152
848
  pageId: string;
@@ -165,7 +861,7 @@ export interface AddPortalBlockRequestContract {
165
861
  bricks?: unknown[];
166
862
  /**
167
863
  * Optional type-specific fields for the staged block, e.g. flat strings
168
- * `embedType`/`content`/`contentUrl` for embed, `image`/`link` for info,
864
+ * `image`/`link` for info,
169
865
  * `sourcePortalId`/`sourcePageId`/`sourceBlockId` for projection,
170
866
  * `taskListIds` for task-list. Also overrides scaffold defaults (colspan,
171
867
  * rowspan, …) when provided. Every field is validated against the block's
@@ -201,7 +897,18 @@ export interface AddPortalAppPageRequestContract {
201
897
  * time from these ids — nothing is hard-coded here.
202
898
  */
203
899
  appId: string;
204
- /** Title for the new page and its sidebar entry (default: "App"). */
900
+ /**
901
+ * private (default) -> Customizer "Your Products/Apps".
902
+ * managed -> Customizer "Managed Products": the app comes from a product owned
903
+ * by another organization, resolved via findPublishedApps.
904
+ */
905
+ productType?: "private" | "managed";
906
+ /**
907
+ * Owner organization of the product, as returned by findPublishedApps.
908
+ * Required for managed products; defaults to the path orgId for private ones.
909
+ */
910
+ productOrgId?: string;
911
+ /** Title for the new page and its sidebar entry (default: "App"; managed: "Managed Products"). */
205
912
  title?: string;
206
913
  /**
207
914
  * Optional id of an existing menu item (e.g. a folder) to nest the page under
@@ -230,6 +937,50 @@ export interface AddPortalAppPageResponseContract {
230
937
  */
231
938
  staged: boolean;
232
939
  }
940
+ export interface AddPortalAppBlockRequestContract {
941
+ /**
942
+ * Global id of the published Fusebase product that owns the app (the product
943
+ * shown in the apps catalog). Persisted on the portal block as `appId`.
944
+ */
945
+ productId: string;
946
+ /**
947
+ * Global id of the published app (feature) to embed. Persisted on the portal
948
+ * block as `featureId`. The app's URL is resolved by the portal at render
949
+ * time from these ids — nothing is hard-coded here.
950
+ */
951
+ appId: string;
952
+ /**
953
+ * private (default) -> Customizer "Your Products/Apps".
954
+ * managed -> Customizer "Managed Products": the app comes from a product owned
955
+ * by another organization, resolved via findPublishedApps.
956
+ */
957
+ productType?: "private" | "managed";
958
+ /**
959
+ * Owner organization of the product, as returned by findPublishedApps.
960
+ * Required for managed products; defaults to the path orgId for private ones.
961
+ */
962
+ productOrgId?: string;
963
+ /** Title for the block (default: "App"; managed: "Managed Products"). */
964
+ title?: string;
965
+ }
966
+ export interface AddPortalAppBlockResponseContract {
967
+ /** Id of the created flexible block carrying the app-feature embed. */
968
+ blockId: string;
969
+ /**
970
+ * Page the block was staged on — echoes the requested pageId. Confirms where
971
+ * the block landed and can be chained into further page operations.
972
+ */
973
+ pageId: string;
974
+ /** Draft branch the change was staged on. */
975
+ branchId: string;
976
+ /** Sequence numbers assigned to the staged change events. */
977
+ seqs: number[];
978
+ /**
979
+ * Always true: the block is staged in the portal's customizer draft, not yet
980
+ * live. The portal owner reviews and publishes it from the customizer.
981
+ */
982
+ staged: boolean;
983
+ }
233
984
  export interface UpdatePortalCustomCodeRequestContract {
234
985
  /**
235
986
  * Custom CSS applied to every published portal page (portal-service
@@ -423,3 +1174,89 @@ export interface PortalContentItemContract {
423
1174
  export interface ListPortalContentResponseContract {
424
1175
  items: PortalContentItemContract[];
425
1176
  }
1177
+ export interface PortalAiAgentContract {
1178
+ /** Agent global id — pass verbatim to addPortalAiAgentBlock as agentId. */
1179
+ id: string;
1180
+ /** Agent title; becomes the block title when the agent is added. */
1181
+ title: string;
1182
+ /** Short description, when the agent has one. */
1183
+ description?: string;
1184
+ /** Icon key, for display only. */
1185
+ iconName?: string;
1186
+ /** Icon colour, for display only. */
1187
+ iconColor?: string;
1188
+ }
1189
+ export interface ListPortalAiAgentsResponseContract {
1190
+ /** Matched agents (a single bounded page). */
1191
+ agents: PortalAiAgentContract[];
1192
+ /** Opaque cursor for the next page; absent when there are no more results. */
1193
+ nextCursor?: string;
1194
+ }
1195
+ export interface GetPortalPageBlockCountResponseContract {
1196
+ /**
1197
+ * Number of matching active blocks on the page, counted over published data
1198
+ * plus the portal's active customizer draft.
1199
+ * @TJS-type integer
1200
+ */
1201
+ count: number;
1202
+ }
1203
+ export interface AddPortalAiAgentBlockRequestContract {
1204
+ /** Exact agent id from listPortalAiAgents. Never invent one. */
1205
+ agentId: string;
1206
+ }
1207
+ export interface AddPortalAiAgentBlockResponseContract {
1208
+ /** Id of the created AI Agent block. */
1209
+ blockId: string;
1210
+ /** Id of the page the block was added to. */
1211
+ pageId: string;
1212
+ /** Draft branch the change was staged on. */
1213
+ branchId: string;
1214
+ /** Sequence numbers assigned to the staged change events (addBlock). */
1215
+ seqs: number[];
1216
+ /**
1217
+ * Always true: the block is staged in the portal's customizer draft, not yet
1218
+ * live. The portal owner reviews and publishes it from the customizer.
1219
+ */
1220
+ staged: boolean;
1221
+ }
1222
+ export declare const PortalDatabaseBlockTargetContract: {
1223
+ readonly Database: "database";
1224
+ };
1225
+ export declare const PortalBackgroundContract: {
1226
+ readonly Color: "color";
1227
+ };
1228
+ export declare const PortalDatabaseBlockAppearanceContract: {
1229
+ readonly None: "none";
1230
+ readonly Blank: "blank";
1231
+ readonly Custom: "custom";
1232
+ };
1233
+ export declare const PortalTextBackgroundContract: {
1234
+ readonly Color: "color";
1235
+ };
1236
+ export declare const PortalFlexibleTextAppearanceContract: {
1237
+ readonly None: "none";
1238
+ readonly Blank: "blank";
1239
+ readonly Custom: "custom";
1240
+ };
1241
+ export declare const PortalCardBackgroundContract: {
1242
+ readonly Color: "color";
1243
+ };
1244
+ export declare const PortalCardViewContract: {
1245
+ readonly TopImage: "top-image";
1246
+ readonly LeftImage: "left-image";
1247
+ readonly RightImage: "right-image";
1248
+ readonly FillImage: "fill-image";
1249
+ };
1250
+ export declare const PortalCardAppearanceContract: {
1251
+ readonly None: "none";
1252
+ readonly Blank: "blank";
1253
+ readonly Custom: "custom";
1254
+ };
1255
+ export declare const PortalCardDestinationContract: {
1256
+ readonly Portalpage: "portalPage";
1257
+ };
1258
+ export declare const PortalCountdownAppearanceContract: {
1259
+ readonly None: "none";
1260
+ readonly Blank: "blank";
1261
+ readonly Custom: "custom";
1262
+ };