@get-bb/plugin-sdk 0.4.4 → 0.4.8
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 +8 -0
- package/bundled-types/bb-plugin-sdk-app.d.ts +213 -111
- package/bundled-types/bb-plugin-sdk-host.d.ts +124 -0
- package/bundled-types/bb-plugin-sdk-internal-composer-customization-validation.d.ts +6 -1
- package/bundled-types/bb-plugin-sdk-internal-host-policy.d.ts +154 -2
- package/bundled-types/bb-plugin-sdk-internal-plugin-app-collector.d.ts +37 -0
- package/bundled-types/bb-plugin-sdk-provider-bridge.d.ts +6479 -0
- package/bundled-types/bb-plugin-sdk-testing-app.d.ts +2 -1
- package/bundled-types/bb-plugin-sdk-testing-host.d.ts +47 -0
- package/bundled-types/bb-plugin-sdk-testing.d.ts +19 -2
- package/bundled-types/bb-plugin-sdk.d.ts +5973 -5147
- package/dist/host.js +13 -0
- package/dist/index.js +13 -1
- package/dist/internal/composer-customization-validation.js +9 -0
- package/dist/internal/host-policy.js +389 -18
- package/dist/internal/plugin-app-collector.js +519 -0
- package/dist/provider-bridge.js +7656 -0
- package/dist/testing/app.js +321 -257
- package/dist/testing/host.js +165 -0
- package/dist/testing/index.js +529 -26
- package/package.json +29 -1
package/dist/testing/app.js
CHANGED
|
@@ -57,6 +57,14 @@ function requireSlotId(kind, value) {
|
|
|
57
57
|
}
|
|
58
58
|
return value;
|
|
59
59
|
}
|
|
60
|
+
function requireProviderId(kind, value) {
|
|
61
|
+
if (typeof value !== "string" || !PLUGIN_SLOT_ID_PATTERN.test(value)) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`${kind}: "providerId" must match ${String(PLUGIN_SLOT_ID_PATTERN)}, got ${JSON.stringify(value)}`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
return value;
|
|
67
|
+
}
|
|
60
68
|
function requireMessageDirectiveId(kind, value) {
|
|
61
69
|
if (typeof value !== "string" || !PLUGIN_MESSAGE_DIRECTIVE_ID_PATTERN.test(value)) {
|
|
62
70
|
throw new Error(
|
|
@@ -243,6 +251,318 @@ function collectComposerCustomization(registration, seenIds, onRejected) {
|
|
|
243
251
|
}
|
|
244
252
|
}
|
|
245
253
|
|
|
254
|
+
// src/internal/plugin-app-collector.ts
|
|
255
|
+
function collectPluginAppRegistrations(definition, onComposerCustomizationRejected = (reason) => console.warn(reason)) {
|
|
256
|
+
const collected = {
|
|
257
|
+
homepageSections: [],
|
|
258
|
+
settingsSections: [],
|
|
259
|
+
navPanels: [],
|
|
260
|
+
threadPanelActions: [],
|
|
261
|
+
newThreadPanelActions: [],
|
|
262
|
+
composerCustomizations: [],
|
|
263
|
+
pendingInteractions: [],
|
|
264
|
+
sidebarFooterActions: [],
|
|
265
|
+
threadLists: [],
|
|
266
|
+
threadHeaderActions: [],
|
|
267
|
+
fileOpeners: [],
|
|
268
|
+
messageDirectives: [],
|
|
269
|
+
messageActions: [],
|
|
270
|
+
providerIcons: [],
|
|
271
|
+
contentScripts: []
|
|
272
|
+
};
|
|
273
|
+
const seenIds = {
|
|
274
|
+
homepageSection: /* @__PURE__ */ new Set(),
|
|
275
|
+
settingsSection: /* @__PURE__ */ new Set(),
|
|
276
|
+
navPanel: /* @__PURE__ */ new Set(),
|
|
277
|
+
threadPanelAction: /* @__PURE__ */ new Set(),
|
|
278
|
+
newThreadPanelAction: /* @__PURE__ */ new Set(),
|
|
279
|
+
composerCustomization: /* @__PURE__ */ new Set(),
|
|
280
|
+
pendingInteraction: /* @__PURE__ */ new Set(),
|
|
281
|
+
sidebarFooterAction: /* @__PURE__ */ new Set(),
|
|
282
|
+
threadList: /* @__PURE__ */ new Set(),
|
|
283
|
+
threadHeaderAction: /* @__PURE__ */ new Set(),
|
|
284
|
+
fileOpener: /* @__PURE__ */ new Set(),
|
|
285
|
+
messageDirective: /* @__PURE__ */ new Set(),
|
|
286
|
+
messageAction: /* @__PURE__ */ new Set(),
|
|
287
|
+
providerIcon: /* @__PURE__ */ new Set(),
|
|
288
|
+
contentScript: /* @__PURE__ */ new Set()
|
|
289
|
+
};
|
|
290
|
+
definition.setup({
|
|
291
|
+
slots: {
|
|
292
|
+
homepageSection(registration) {
|
|
293
|
+
const kind = "slots.homepageSection";
|
|
294
|
+
const id = requireSlotId(kind, registration?.id);
|
|
295
|
+
requireUniqueId(kind, seenIds.homepageSection, id);
|
|
296
|
+
collected.homepageSections.push({
|
|
297
|
+
id,
|
|
298
|
+
title: requireNonEmptyString(kind, "title", registration.title),
|
|
299
|
+
component: requireComponent(kind, registration.component)
|
|
300
|
+
});
|
|
301
|
+
},
|
|
302
|
+
settingsSection(registration) {
|
|
303
|
+
const kind = "slots.settingsSection";
|
|
304
|
+
const id = requireSlotId(kind, registration?.id);
|
|
305
|
+
requireUniqueId(kind, seenIds.settingsSection, id);
|
|
306
|
+
const title = requireOptionalString(kind, "title", registration.title);
|
|
307
|
+
const description = requireOptionalString(
|
|
308
|
+
kind,
|
|
309
|
+
"description",
|
|
310
|
+
registration.description
|
|
311
|
+
);
|
|
312
|
+
collected.settingsSections.push({
|
|
313
|
+
id,
|
|
314
|
+
...title !== void 0 ? { title } : {},
|
|
315
|
+
...description !== void 0 ? { description } : {},
|
|
316
|
+
component: requireComponent(kind, registration.component)
|
|
317
|
+
});
|
|
318
|
+
},
|
|
319
|
+
navPanel(registration) {
|
|
320
|
+
const kind = "slots.navPanel";
|
|
321
|
+
const id = requireSlotId(kind, registration?.id);
|
|
322
|
+
requireUniqueId(kind, seenIds.navPanel, id);
|
|
323
|
+
const path = requireNonEmptyString(kind, "path", registration.path);
|
|
324
|
+
if (!PLUGIN_SLOT_ID_PATTERN.test(path)) {
|
|
325
|
+
throw new Error(
|
|
326
|
+
`${kind}: "path" must match ${String(PLUGIN_SLOT_ID_PATTERN)} (it becomes a URL segment), got ${JSON.stringify(path)}`
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
if (registration.headerContent !== void 0 && typeof registration.headerContent !== "function") {
|
|
330
|
+
throw new Error(
|
|
331
|
+
`${kind}: "headerContent" must be a React component function when set`
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
if (registration.experimental_sidebarAccessory !== void 0 && typeof registration.experimental_sidebarAccessory !== "function") {
|
|
335
|
+
throw new Error(
|
|
336
|
+
`${kind}: "experimental_sidebarAccessory" must be a React component function when set`
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
const experimentalFixedTabs = (() => {
|
|
340
|
+
if (registration.experimental_fixedTabs === void 0) return [];
|
|
341
|
+
if (!Array.isArray(registration.experimental_fixedTabs)) {
|
|
342
|
+
throw new Error(
|
|
343
|
+
`${kind}: "experimental_fixedTabs" must be an array when set`
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
const seenFixedTabIds = /* @__PURE__ */ new Set();
|
|
347
|
+
return registration.experimental_fixedTabs.map((value, index) => {
|
|
348
|
+
const fixedTabKind = `${kind}.experimental_fixedTabs[${index}]`;
|
|
349
|
+
const fixedTab = value;
|
|
350
|
+
const id2 = requireSlotId(fixedTabKind, fixedTab?.id);
|
|
351
|
+
requireUniqueId(fixedTabKind, seenFixedTabIds, id2);
|
|
352
|
+
const layout = fixedTab?.layout;
|
|
353
|
+
if (layout !== void 0 && layout !== "padded" && layout !== "flush") {
|
|
354
|
+
throw new Error(
|
|
355
|
+
`${fixedTabKind}: "layout" must be "padded" or "flush" when set`
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
return {
|
|
359
|
+
id: id2,
|
|
360
|
+
title: requireNonEmptyString(
|
|
361
|
+
fixedTabKind,
|
|
362
|
+
"title",
|
|
363
|
+
fixedTab?.title
|
|
364
|
+
),
|
|
365
|
+
icon: requireNonEmptyString(
|
|
366
|
+
fixedTabKind,
|
|
367
|
+
"icon",
|
|
368
|
+
fixedTab?.icon
|
|
369
|
+
),
|
|
370
|
+
component: requireComponent(fixedTabKind, fixedTab?.component),
|
|
371
|
+
...layout === void 0 ? {} : { layout }
|
|
372
|
+
};
|
|
373
|
+
});
|
|
374
|
+
})();
|
|
375
|
+
collected.navPanels.push({
|
|
376
|
+
id,
|
|
377
|
+
title: requireNonEmptyString(kind, "title", registration.title),
|
|
378
|
+
icon: requireNonEmptyString(kind, "icon", registration.icon),
|
|
379
|
+
path,
|
|
380
|
+
component: requireComponent(kind, registration.component),
|
|
381
|
+
...experimentalFixedTabs.length > 0 ? { experimental_fixedTabs: experimentalFixedTabs } : {},
|
|
382
|
+
...registration.experimental_sidebarAccessory !== void 0 ? {
|
|
383
|
+
experimental_sidebarAccessory: registration.experimental_sidebarAccessory
|
|
384
|
+
} : {},
|
|
385
|
+
...registration.headerContent !== void 0 ? { headerContent: registration.headerContent } : {}
|
|
386
|
+
});
|
|
387
|
+
},
|
|
388
|
+
threadPanelAction(registration) {
|
|
389
|
+
const kind = "slots.threadPanelAction";
|
|
390
|
+
const id = requireSlotId(kind, registration?.id);
|
|
391
|
+
requireUniqueId(kind, seenIds.threadPanelAction, id);
|
|
392
|
+
if (registration.run !== void 0 && typeof registration.run !== "function") {
|
|
393
|
+
throw new Error(`${kind}: "run" must be a function when set`);
|
|
394
|
+
}
|
|
395
|
+
if (registration.layout !== void 0 && registration.layout !== "padded" && registration.layout !== "flush") {
|
|
396
|
+
throw new Error(`${kind}: "layout" must be "padded" or "flush"`);
|
|
397
|
+
}
|
|
398
|
+
collected.threadPanelActions.push({
|
|
399
|
+
id,
|
|
400
|
+
title: requireNonEmptyString(kind, "title", registration.title),
|
|
401
|
+
...registration.icon !== void 0 ? {
|
|
402
|
+
icon: requireNonEmptyString(kind, "icon", registration.icon)
|
|
403
|
+
} : {},
|
|
404
|
+
component: requireComponent(kind, registration.component),
|
|
405
|
+
...registration.layout !== void 0 ? { layout: registration.layout } : {},
|
|
406
|
+
...registration.run !== void 0 ? { run: registration.run } : {}
|
|
407
|
+
});
|
|
408
|
+
},
|
|
409
|
+
experimental_newThreadPanelAction(registration) {
|
|
410
|
+
const kind = "slots.experimental_newThreadPanelAction";
|
|
411
|
+
const id = requireSlotId(kind, registration?.id);
|
|
412
|
+
requireUniqueId(kind, seenIds.newThreadPanelAction, id);
|
|
413
|
+
if (registration.run !== void 0 && typeof registration.run !== "function") {
|
|
414
|
+
throw new Error(`${kind}: "run" must be a function when set`);
|
|
415
|
+
}
|
|
416
|
+
if (registration.layout !== void 0 && registration.layout !== "padded" && registration.layout !== "flush") {
|
|
417
|
+
throw new Error(`${kind}: "layout" must be "padded" or "flush"`);
|
|
418
|
+
}
|
|
419
|
+
collected.newThreadPanelActions.push({
|
|
420
|
+
id,
|
|
421
|
+
title: requireNonEmptyString(kind, "title", registration.title),
|
|
422
|
+
...registration.icon !== void 0 ? {
|
|
423
|
+
icon: requireNonEmptyString(kind, "icon", registration.icon)
|
|
424
|
+
} : {},
|
|
425
|
+
component: requireComponent(kind, registration.component),
|
|
426
|
+
...registration.layout !== void 0 ? { layout: registration.layout } : {},
|
|
427
|
+
...registration.run !== void 0 ? { run: registration.run } : {}
|
|
428
|
+
});
|
|
429
|
+
},
|
|
430
|
+
pendingInteraction(registration) {
|
|
431
|
+
const kind = "slots.pendingInteraction";
|
|
432
|
+
const id = requireSlotId(kind, registration?.id);
|
|
433
|
+
requireUniqueId(kind, seenIds.pendingInteraction, id);
|
|
434
|
+
collected.pendingInteractions.push({
|
|
435
|
+
id,
|
|
436
|
+
component: requireComponent(kind, registration.component)
|
|
437
|
+
});
|
|
438
|
+
},
|
|
439
|
+
sidebarFooterAction(registration) {
|
|
440
|
+
const kind = "slots.sidebarFooterAction";
|
|
441
|
+
const id = requireSlotId(kind, registration?.id);
|
|
442
|
+
requireUniqueId(kind, seenIds.sidebarFooterAction, id);
|
|
443
|
+
if (typeof registration.run !== "function") {
|
|
444
|
+
throw new Error(`${kind}: "run" must be a function`);
|
|
445
|
+
}
|
|
446
|
+
collected.sidebarFooterActions.push({
|
|
447
|
+
id,
|
|
448
|
+
title: requireNonEmptyString(kind, "title", registration.title),
|
|
449
|
+
icon: requireNonEmptyString(kind, "icon", registration.icon),
|
|
450
|
+
run: registration.run
|
|
451
|
+
});
|
|
452
|
+
},
|
|
453
|
+
experimental_threadList(registration) {
|
|
454
|
+
const kind = "slots.experimental_threadList";
|
|
455
|
+
const id = requireSlotId(kind, registration?.id);
|
|
456
|
+
requireUniqueId(kind, seenIds.threadList, id);
|
|
457
|
+
const description = requireOptionalString(
|
|
458
|
+
kind,
|
|
459
|
+
"description",
|
|
460
|
+
registration.description
|
|
461
|
+
);
|
|
462
|
+
collected.threadLists.push({
|
|
463
|
+
id,
|
|
464
|
+
title: requireNonEmptyString(kind, "title", registration.title),
|
|
465
|
+
...description !== void 0 ? { description } : {},
|
|
466
|
+
component: requireComponent(kind, registration.component)
|
|
467
|
+
});
|
|
468
|
+
},
|
|
469
|
+
experimental_threadHeaderAction(registration) {
|
|
470
|
+
const kind = "slots.experimental_threadHeaderAction";
|
|
471
|
+
const id = requireSlotId(kind, registration?.id);
|
|
472
|
+
requireUniqueId(kind, seenIds.threadHeaderAction, id);
|
|
473
|
+
collected.threadHeaderActions.push({
|
|
474
|
+
id,
|
|
475
|
+
title: requireNonEmptyString(kind, "title", registration.title),
|
|
476
|
+
component: requireComponent(kind, registration.component)
|
|
477
|
+
});
|
|
478
|
+
},
|
|
479
|
+
fileOpener(registration) {
|
|
480
|
+
const kind = "slots.fileOpener";
|
|
481
|
+
const id = requireSlotId(kind, registration?.id);
|
|
482
|
+
requireUniqueId(kind, seenIds.fileOpener, id);
|
|
483
|
+
const rawExtensions = registration?.extensions;
|
|
484
|
+
if (!Array.isArray(rawExtensions) || rawExtensions.length === 0) {
|
|
485
|
+
throw new Error(
|
|
486
|
+
`${kind}: "extensions" must be a non-empty array of lowercase extensions without the dot`
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
const extensions = rawExtensions.map((extension) => {
|
|
490
|
+
if (typeof extension !== "string" || !/^[a-z0-9]+$/.test(extension)) {
|
|
491
|
+
throw new Error(
|
|
492
|
+
`${kind}: extensions must be lowercase alphanumerics without the dot, got ${JSON.stringify(extension)}`
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
return extension;
|
|
496
|
+
});
|
|
497
|
+
collected.fileOpeners.push({
|
|
498
|
+
id,
|
|
499
|
+
title: requireNonEmptyString(kind, "title", registration.title),
|
|
500
|
+
extensions,
|
|
501
|
+
component: requireComponent(kind, registration.component)
|
|
502
|
+
});
|
|
503
|
+
},
|
|
504
|
+
messageDirective(registration) {
|
|
505
|
+
const kind = "slots.messageDirective";
|
|
506
|
+
const id = requireMessageDirectiveId(kind, registration?.id);
|
|
507
|
+
requireUniqueId(kind, seenIds.messageDirective, id);
|
|
508
|
+
collected.messageDirectives.push({
|
|
509
|
+
id,
|
|
510
|
+
component: requireComponent(kind, registration.component)
|
|
511
|
+
});
|
|
512
|
+
},
|
|
513
|
+
messageAction(registration) {
|
|
514
|
+
const kind = "slots.messageAction";
|
|
515
|
+
const id = requireSlotId(kind, registration?.id);
|
|
516
|
+
requireUniqueId(kind, seenIds.messageAction, id);
|
|
517
|
+
if (typeof registration.run !== "function") {
|
|
518
|
+
throw new Error(`${kind}: "run" must be a function`);
|
|
519
|
+
}
|
|
520
|
+
collected.messageActions.push({
|
|
521
|
+
id,
|
|
522
|
+
title: requireNonEmptyString(kind, "title", registration.title),
|
|
523
|
+
...registration.icon !== void 0 ? {
|
|
524
|
+
icon: requireNonEmptyString(kind, "icon", registration.icon)
|
|
525
|
+
} : {},
|
|
526
|
+
run: registration.run
|
|
527
|
+
});
|
|
528
|
+
},
|
|
529
|
+
experimental_providerIcon(registration) {
|
|
530
|
+
const kind = "slots.experimental_providerIcon";
|
|
531
|
+
const providerId = requireProviderId(kind, registration?.providerId);
|
|
532
|
+
requireUniqueId(kind, seenIds.providerIcon, providerId);
|
|
533
|
+
collected.providerIcons.push({
|
|
534
|
+
providerId,
|
|
535
|
+
icon: requireComponent(kind, registration.icon)
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
},
|
|
539
|
+
composer: {
|
|
540
|
+
customize(registration) {
|
|
541
|
+
const customization = collectComposerCustomization(
|
|
542
|
+
registration,
|
|
543
|
+
seenIds.composerCustomization,
|
|
544
|
+
onComposerCustomizationRejected
|
|
545
|
+
);
|
|
546
|
+
if (customization !== null) {
|
|
547
|
+
collected.composerCustomizations.push(customization);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
},
|
|
551
|
+
contentScripts: {
|
|
552
|
+
register(registration) {
|
|
553
|
+
const kind = "contentScripts.register";
|
|
554
|
+
const id = requireSlotId(kind, registration?.id);
|
|
555
|
+
requireUniqueId(kind, seenIds.contentScript, id);
|
|
556
|
+
if (typeof registration.mount !== "function") {
|
|
557
|
+
throw new Error(`${kind}: "mount" must be a function`);
|
|
558
|
+
}
|
|
559
|
+
collected.contentScripts.push({ id, mount: registration.mount });
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
});
|
|
563
|
+
return collected;
|
|
564
|
+
}
|
|
565
|
+
|
|
246
566
|
// src/testing/app.tsx
|
|
247
567
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
248
568
|
function SlotLifecycleGuard({
|
|
@@ -513,262 +833,6 @@ function installTestPluginRuntime() {
|
|
|
513
833
|
pluginSdkApp: testPluginSdkApp
|
|
514
834
|
};
|
|
515
835
|
}
|
|
516
|
-
function collectRegistrations(definition) {
|
|
517
|
-
const captured = {
|
|
518
|
-
homepageSections: [],
|
|
519
|
-
settingsSections: [],
|
|
520
|
-
navPanels: [],
|
|
521
|
-
threadPanelActions: [],
|
|
522
|
-
newThreadPanelActions: [],
|
|
523
|
-
composerCustomizations: [],
|
|
524
|
-
pendingInteractions: [],
|
|
525
|
-
sidebarFooterActions: [],
|
|
526
|
-
threadLists: [],
|
|
527
|
-
threadHeaderActions: [],
|
|
528
|
-
fileOpeners: [],
|
|
529
|
-
messageDirectives: [],
|
|
530
|
-
messageActions: [],
|
|
531
|
-
contentScripts: []
|
|
532
|
-
};
|
|
533
|
-
const seenIds = {
|
|
534
|
-
homepageSection: /* @__PURE__ */ new Set(),
|
|
535
|
-
settingsSection: /* @__PURE__ */ new Set(),
|
|
536
|
-
navPanel: /* @__PURE__ */ new Set(),
|
|
537
|
-
threadPanelAction: /* @__PURE__ */ new Set(),
|
|
538
|
-
newThreadPanelAction: /* @__PURE__ */ new Set(),
|
|
539
|
-
composerCustomization: /* @__PURE__ */ new Set(),
|
|
540
|
-
pendingInteraction: /* @__PURE__ */ new Set(),
|
|
541
|
-
sidebarFooterAction: /* @__PURE__ */ new Set(),
|
|
542
|
-
threadList: /* @__PURE__ */ new Set(),
|
|
543
|
-
threadHeaderAction: /* @__PURE__ */ new Set(),
|
|
544
|
-
fileOpener: /* @__PURE__ */ new Set(),
|
|
545
|
-
messageDirective: /* @__PURE__ */ new Set(),
|
|
546
|
-
messageAction: /* @__PURE__ */ new Set(),
|
|
547
|
-
contentScript: /* @__PURE__ */ new Set()
|
|
548
|
-
};
|
|
549
|
-
definition.setup({
|
|
550
|
-
slots: {
|
|
551
|
-
homepageSection(registration) {
|
|
552
|
-
const kind = "slots.homepageSection";
|
|
553
|
-
const id = requireSlotId(kind, registration?.id);
|
|
554
|
-
requireUniqueId(kind, seenIds.homepageSection, id);
|
|
555
|
-
captured.homepageSections.push({
|
|
556
|
-
id,
|
|
557
|
-
title: requireNonEmptyString(kind, "title", registration.title),
|
|
558
|
-
component: requireComponent(kind, registration.component)
|
|
559
|
-
});
|
|
560
|
-
},
|
|
561
|
-
settingsSection(registration) {
|
|
562
|
-
const kind = "slots.settingsSection";
|
|
563
|
-
const id = requireSlotId(kind, registration?.id);
|
|
564
|
-
requireUniqueId(kind, seenIds.settingsSection, id);
|
|
565
|
-
const title = requireOptionalString(kind, "title", registration.title);
|
|
566
|
-
const description = requireOptionalString(
|
|
567
|
-
kind,
|
|
568
|
-
"description",
|
|
569
|
-
registration.description
|
|
570
|
-
);
|
|
571
|
-
captured.settingsSections.push({
|
|
572
|
-
id,
|
|
573
|
-
...title !== void 0 ? { title } : {},
|
|
574
|
-
...description !== void 0 ? { description } : {},
|
|
575
|
-
component: requireComponent(kind, registration.component)
|
|
576
|
-
});
|
|
577
|
-
},
|
|
578
|
-
navPanel(registration) {
|
|
579
|
-
const kind = "slots.navPanel";
|
|
580
|
-
const id = requireSlotId(kind, registration?.id);
|
|
581
|
-
requireUniqueId(kind, seenIds.navPanel, id);
|
|
582
|
-
const path = requireNonEmptyString(kind, "path", registration.path);
|
|
583
|
-
if (!PLUGIN_SLOT_ID_PATTERN.test(path)) {
|
|
584
|
-
throw new Error(
|
|
585
|
-
`${kind}: "path" must match ${String(PLUGIN_SLOT_ID_PATTERN)} (it becomes a URL segment), got ${JSON.stringify(path)}`
|
|
586
|
-
);
|
|
587
|
-
}
|
|
588
|
-
if (registration.headerContent !== void 0 && typeof registration.headerContent !== "function") {
|
|
589
|
-
throw new Error(
|
|
590
|
-
`${kind}: "headerContent" must be a React component function when set`
|
|
591
|
-
);
|
|
592
|
-
}
|
|
593
|
-
if (registration.experimental_sidebarAccessory !== void 0 && typeof registration.experimental_sidebarAccessory !== "function") {
|
|
594
|
-
throw new Error(
|
|
595
|
-
`${kind}: "experimental_sidebarAccessory" must be a React component function when set`
|
|
596
|
-
);
|
|
597
|
-
}
|
|
598
|
-
captured.navPanels.push({
|
|
599
|
-
id,
|
|
600
|
-
title: requireNonEmptyString(kind, "title", registration.title),
|
|
601
|
-
icon: requireNonEmptyString(kind, "icon", registration.icon),
|
|
602
|
-
path,
|
|
603
|
-
component: requireComponent(kind, registration.component),
|
|
604
|
-
...registration.experimental_sidebarAccessory !== void 0 ? {
|
|
605
|
-
experimental_sidebarAccessory: registration.experimental_sidebarAccessory
|
|
606
|
-
} : {},
|
|
607
|
-
...registration.headerContent !== void 0 ? { headerContent: registration.headerContent } : {}
|
|
608
|
-
});
|
|
609
|
-
},
|
|
610
|
-
threadPanelAction(registration) {
|
|
611
|
-
const kind = "slots.threadPanelAction";
|
|
612
|
-
const id = requireSlotId(kind, registration?.id);
|
|
613
|
-
requireUniqueId(kind, seenIds.threadPanelAction, id);
|
|
614
|
-
if (registration.run !== void 0 && typeof registration.run !== "function") {
|
|
615
|
-
throw new Error(`${kind}: "run" must be a function when set`);
|
|
616
|
-
}
|
|
617
|
-
if (registration.layout !== void 0 && registration.layout !== "padded" && registration.layout !== "flush") {
|
|
618
|
-
throw new Error(`${kind}: "layout" must be "padded" or "flush"`);
|
|
619
|
-
}
|
|
620
|
-
captured.threadPanelActions.push({
|
|
621
|
-
id,
|
|
622
|
-
title: requireNonEmptyString(kind, "title", registration.title),
|
|
623
|
-
...registration.icon !== void 0 ? { icon: requireNonEmptyString(kind, "icon", registration.icon) } : {},
|
|
624
|
-
component: requireComponent(kind, registration.component),
|
|
625
|
-
...registration.layout !== void 0 ? { layout: registration.layout } : {},
|
|
626
|
-
...registration.run !== void 0 ? { run: registration.run } : {}
|
|
627
|
-
});
|
|
628
|
-
},
|
|
629
|
-
experimental_newThreadPanelAction(registration) {
|
|
630
|
-
const kind = "slots.experimental_newThreadPanelAction";
|
|
631
|
-
const id = requireSlotId(kind, registration?.id);
|
|
632
|
-
requireUniqueId(kind, seenIds.newThreadPanelAction, id);
|
|
633
|
-
if (registration.run !== void 0 && typeof registration.run !== "function") {
|
|
634
|
-
throw new Error(`${kind}: "run" must be a function when set`);
|
|
635
|
-
}
|
|
636
|
-
if (registration.layout !== void 0 && registration.layout !== "padded" && registration.layout !== "flush") {
|
|
637
|
-
throw new Error(`${kind}: "layout" must be "padded" or "flush"`);
|
|
638
|
-
}
|
|
639
|
-
captured.newThreadPanelActions.push({
|
|
640
|
-
id,
|
|
641
|
-
title: requireNonEmptyString(kind, "title", registration.title),
|
|
642
|
-
...registration.icon !== void 0 ? { icon: requireNonEmptyString(kind, "icon", registration.icon) } : {},
|
|
643
|
-
component: requireComponent(kind, registration.component),
|
|
644
|
-
...registration.layout !== void 0 ? { layout: registration.layout } : {},
|
|
645
|
-
...registration.run !== void 0 ? { run: registration.run } : {}
|
|
646
|
-
});
|
|
647
|
-
},
|
|
648
|
-
pendingInteraction(registration) {
|
|
649
|
-
const kind = "slots.pendingInteraction";
|
|
650
|
-
const id = requireSlotId(kind, registration?.id);
|
|
651
|
-
requireUniqueId(kind, seenIds.pendingInteraction, id);
|
|
652
|
-
captured.pendingInteractions.push({
|
|
653
|
-
id,
|
|
654
|
-
component: requireComponent(kind, registration.component)
|
|
655
|
-
});
|
|
656
|
-
},
|
|
657
|
-
sidebarFooterAction(registration) {
|
|
658
|
-
const kind = "slots.sidebarFooterAction";
|
|
659
|
-
const id = requireSlotId(kind, registration?.id);
|
|
660
|
-
requireUniqueId(kind, seenIds.sidebarFooterAction, id);
|
|
661
|
-
if (typeof registration.run !== "function") {
|
|
662
|
-
throw new Error(`${kind}: "run" must be a function`);
|
|
663
|
-
}
|
|
664
|
-
captured.sidebarFooterActions.push({
|
|
665
|
-
id,
|
|
666
|
-
title: requireNonEmptyString(kind, "title", registration.title),
|
|
667
|
-
icon: requireNonEmptyString(kind, "icon", registration.icon),
|
|
668
|
-
run: registration.run
|
|
669
|
-
});
|
|
670
|
-
},
|
|
671
|
-
experimental_threadList(registration) {
|
|
672
|
-
const kind = "slots.experimental_threadList";
|
|
673
|
-
const id = requireSlotId(kind, registration?.id);
|
|
674
|
-
requireUniqueId(kind, seenIds.threadList, id);
|
|
675
|
-
const description = requireOptionalString(
|
|
676
|
-
kind,
|
|
677
|
-
"description",
|
|
678
|
-
registration.description
|
|
679
|
-
);
|
|
680
|
-
captured.threadLists.push({
|
|
681
|
-
id,
|
|
682
|
-
title: requireNonEmptyString(kind, "title", registration.title),
|
|
683
|
-
...description !== void 0 ? { description } : {},
|
|
684
|
-
component: requireComponent(kind, registration.component)
|
|
685
|
-
});
|
|
686
|
-
},
|
|
687
|
-
experimental_threadHeaderAction(registration) {
|
|
688
|
-
const kind = "slots.experimental_threadHeaderAction";
|
|
689
|
-
const id = requireSlotId(kind, registration?.id);
|
|
690
|
-
requireUniqueId(kind, seenIds.threadHeaderAction, id);
|
|
691
|
-
captured.threadHeaderActions.push({
|
|
692
|
-
id,
|
|
693
|
-
title: requireNonEmptyString(kind, "title", registration.title),
|
|
694
|
-
component: requireComponent(kind, registration.component)
|
|
695
|
-
});
|
|
696
|
-
},
|
|
697
|
-
fileOpener(registration) {
|
|
698
|
-
const kind = "slots.fileOpener";
|
|
699
|
-
const id = requireSlotId(kind, registration?.id);
|
|
700
|
-
requireUniqueId(kind, seenIds.fileOpener, id);
|
|
701
|
-
const rawExtensions = registration?.extensions;
|
|
702
|
-
if (!Array.isArray(rawExtensions) || rawExtensions.length === 0) {
|
|
703
|
-
throw new Error(
|
|
704
|
-
`${kind}: "extensions" must be a non-empty array of lowercase extensions without the dot`
|
|
705
|
-
);
|
|
706
|
-
}
|
|
707
|
-
const extensions = rawExtensions.map((extension) => {
|
|
708
|
-
if (typeof extension !== "string" || !/^[a-z0-9]+$/.test(extension)) {
|
|
709
|
-
throw new Error(
|
|
710
|
-
`${kind}: extensions must be lowercase alphanumerics without the dot, got ${JSON.stringify(extension)}`
|
|
711
|
-
);
|
|
712
|
-
}
|
|
713
|
-
return extension;
|
|
714
|
-
});
|
|
715
|
-
captured.fileOpeners.push({
|
|
716
|
-
id,
|
|
717
|
-
title: requireNonEmptyString(kind, "title", registration.title),
|
|
718
|
-
extensions,
|
|
719
|
-
component: requireComponent(kind, registration.component)
|
|
720
|
-
});
|
|
721
|
-
},
|
|
722
|
-
messageDirective(registration) {
|
|
723
|
-
const kind = "slots.messageDirective";
|
|
724
|
-
const id = requireMessageDirectiveId(kind, registration?.id);
|
|
725
|
-
requireUniqueId(kind, seenIds.messageDirective, id);
|
|
726
|
-
captured.messageDirectives.push({
|
|
727
|
-
id,
|
|
728
|
-
component: requireComponent(kind, registration.component)
|
|
729
|
-
});
|
|
730
|
-
},
|
|
731
|
-
messageAction(registration) {
|
|
732
|
-
const kind = "slots.messageAction";
|
|
733
|
-
const id = requireSlotId(kind, registration?.id);
|
|
734
|
-
requireUniqueId(kind, seenIds.messageAction, id);
|
|
735
|
-
if (typeof registration.run !== "function") {
|
|
736
|
-
throw new Error(`${kind}: "run" must be a function`);
|
|
737
|
-
}
|
|
738
|
-
captured.messageActions.push({
|
|
739
|
-
id,
|
|
740
|
-
title: requireNonEmptyString(kind, "title", registration.title),
|
|
741
|
-
...registration.icon !== void 0 ? { icon: requireNonEmptyString(kind, "icon", registration.icon) } : {},
|
|
742
|
-
run: registration.run
|
|
743
|
-
});
|
|
744
|
-
}
|
|
745
|
-
},
|
|
746
|
-
composer: {
|
|
747
|
-
customize(registration) {
|
|
748
|
-
const customization = collectComposerCustomization(
|
|
749
|
-
registration,
|
|
750
|
-
seenIds.composerCustomization,
|
|
751
|
-
(reason) => console.warn(reason)
|
|
752
|
-
);
|
|
753
|
-
if (customization !== null) {
|
|
754
|
-
captured.composerCustomizations.push(customization);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
},
|
|
758
|
-
contentScripts: {
|
|
759
|
-
register(registration) {
|
|
760
|
-
const kind = "contentScripts.register";
|
|
761
|
-
const id = requireSlotId(kind, registration?.id);
|
|
762
|
-
requireUniqueId(kind, seenIds.contentScript, id);
|
|
763
|
-
if (typeof registration.mount !== "function") {
|
|
764
|
-
throw new Error(`${kind}: "mount" must be a function`);
|
|
765
|
-
}
|
|
766
|
-
captured.contentScripts.push({ id, mount: registration.mount });
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
});
|
|
770
|
-
return captured;
|
|
771
|
-
}
|
|
772
836
|
async function loadPluginApp(source) {
|
|
773
837
|
installTestPluginRuntime();
|
|
774
838
|
const resolved = typeof source === "function" ? await source() : source;
|
|
@@ -778,7 +842,7 @@ async function loadPluginApp(source) {
|
|
|
778
842
|
"the bundle's default export is not definePluginApp(...) from @get-bb/plugin-sdk/app"
|
|
779
843
|
);
|
|
780
844
|
}
|
|
781
|
-
return
|
|
845
|
+
return collectPluginAppRegistrations(definition);
|
|
782
846
|
}
|
|
783
847
|
async function mountPluginContentScripts(app, options) {
|
|
784
848
|
const controller = new AbortController();
|