@vivoa/plugin-sdk 0.6.5 → 0.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -21,12 +21,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  ANALYTICS_PLUGIN_TOKEN: () => ANALYTICS_PLUGIN_TOKEN,
24
+ AUTHOR_HANDLE_RE: () => AUTHOR_HANDLE_RE,
24
25
  ActionVariant: () => ActionVariant,
25
26
  AnalyticsFeature: () => AnalyticsFeature,
26
27
  BlockType: () => BlockType,
27
28
  CapabilityKind: () => CapabilityKind,
28
29
  CodFeeType: () => CodFeeType,
29
30
  ConfigScope: () => ConfigScope,
31
+ ContentActionVariant: () => ContentActionVariant,
32
+ ContentBlockType: () => ContentBlockType,
30
33
  FieldType: () => FieldType,
31
34
  FieldVariant: () => FieldVariant,
32
35
  GatewayEnvironment: () => GatewayEnvironment,
@@ -37,7 +40,6 @@ __export(index_exports, {
37
40
  LayoutMode: () => LayoutMode,
38
41
  MessageVariant: () => MessageVariant,
39
42
  PAYMENT_PLUGIN_TOKEN: () => PAYMENT_PLUGIN_TOKEN,
40
- PluginType: () => PluginType,
41
43
  RepeaterSource: () => RepeaterSource,
42
44
  SDK_VERSION: () => SDK_VERSION,
43
45
  SHIPPING_PLUGIN_TOKEN: () => SHIPPING_PLUGIN_TOKEN,
@@ -62,7 +64,10 @@ __export(index_exports, {
62
64
  paymentCapability: () => paymentCapability,
63
65
  shippingCapability: () => shippingCapability,
64
66
  suppliersCapability: () => suppliersCapability,
65
- validateSetupLayout: () => validateSetupLayout
67
+ uiCapability: () => uiCapability,
68
+ validatePluginAuthor: () => validatePluginAuthor,
69
+ validateSetupLayout: () => validateSetupLayout,
70
+ validateUiContributions: () => validateUiContributions
66
71
  });
67
72
  module.exports = __toCommonJS(index_exports);
68
73
 
@@ -74,14 +79,6 @@ var ANALYTICS_PLUGIN_TOKEN = "ANALYTICS_PLUGINS";
74
79
  var INVOICING_PLUGIN_TOKEN = "INVOICING_PLUGINS";
75
80
 
76
81
  // src/plugin.ts
77
- var PluginType = /* @__PURE__ */ ((PluginType2) => {
78
- PluginType2["Payment"] = "payment";
79
- PluginType2["Shipping"] = "shipping";
80
- PluginType2["Analytics"] = "analytics";
81
- PluginType2["Invoicing"] = "invoicing";
82
- PluginType2["Generic"] = "generic";
83
- return PluginType2;
84
- })(PluginType || {});
85
82
  var MessageVariant = /* @__PURE__ */ ((MessageVariant2) => {
86
83
  MessageVariant2["Info"] = "info";
87
84
  MessageVariant2["Warning"] = "warning";
@@ -244,6 +241,30 @@ var InvoiceStatus = /* @__PURE__ */ ((InvoiceStatus2) => {
244
241
  return InvoiceStatus2;
245
242
  })(InvoiceStatus || {});
246
243
 
244
+ // src/author.ts
245
+ var AUTHOR_HANDLE_RE = /^[a-z0-9][a-z0-9-]*$/;
246
+ function validatePluginAuthor(value) {
247
+ const errors = [];
248
+ if (typeof value !== "object" || value === null) {
249
+ return { ok: false, errors: ["author is required and must be an object"] };
250
+ }
251
+ const a = value;
252
+ if (typeof a.handle !== "string" || a.handle.length === 0) {
253
+ errors.push("author.handle is required");
254
+ } else if (!AUTHOR_HANDLE_RE.test(a.handle)) {
255
+ errors.push(
256
+ `author.handle "${a.handle}" must be a lowercase slug (a-z, 0-9, dash; start alphanumeric)`
257
+ );
258
+ }
259
+ if (typeof a.displayName !== "string" || a.displayName.trim().length === 0) {
260
+ errors.push("author.displayName is required");
261
+ }
262
+ if (a.url !== void 0 && typeof a.url !== "string") {
263
+ errors.push("author.url must be a string when present");
264
+ }
265
+ return { ok: errors.length === 0, errors };
266
+ }
267
+
247
268
  // src/setup-layout.ts
248
269
  var import_superstruct2 = require("superstruct");
249
270
  var FieldVariant = /* @__PURE__ */ ((FieldVariant2) => {
@@ -314,6 +335,7 @@ var sGroupBlock = (0, import_superstruct2.object)({
314
335
  type: (0, import_superstruct2.literal)("group" /* Group */),
315
336
  title: (0, import_superstruct2.string)(),
316
337
  description: (0, import_superstruct2.optional)((0, import_superstruct2.string)()),
338
+ helpUrl: (0, import_superstruct2.optional)((0, import_superstruct2.string)()),
317
339
  fields: (0, import_superstruct2.array)((0, import_superstruct2.string)()),
318
340
  collapsible: (0, import_superstruct2.optional)((0, import_superstruct2.boolean)()),
319
341
  defaultOpen: (0, import_superstruct2.optional)((0, import_superstruct2.boolean)()),
@@ -510,13 +532,124 @@ function crossValidateSetupLayout(layout, configSchema) {
510
532
  return errors;
511
533
  }
512
534
 
535
+ // src/ui.ts
536
+ var import_superstruct3 = require("superstruct");
537
+ var ContentBlockType = /* @__PURE__ */ ((ContentBlockType2) => {
538
+ ContentBlockType2["Text"] = "text";
539
+ ContentBlockType2["Banner"] = "banner";
540
+ ContentBlockType2["Badge"] = "badge";
541
+ ContentBlockType2["KeyValue"] = "keyValue";
542
+ ContentBlockType2["CopyField"] = "copyField";
543
+ ContentBlockType2["Link"] = "link";
544
+ ContentBlockType2["Divider"] = "divider";
545
+ ContentBlockType2["Action"] = "action";
546
+ ContentBlockType2["Card"] = "card";
547
+ return ContentBlockType2;
548
+ })(ContentBlockType || {});
549
+ var ContentActionVariant = /* @__PURE__ */ ((ContentActionVariant2) => {
550
+ ContentActionVariant2["Primary"] = "primary";
551
+ ContentActionVariant2["Secondary"] = "secondary";
552
+ ContentActionVariant2["Danger"] = "danger";
553
+ return ContentActionVariant2;
554
+ })(ContentActionVariant || {});
555
+ var sMessageVariant2 = (0, import_superstruct3.enums)(Object.values(MessageVariant));
556
+ var sContentActionVariant = (0, import_superstruct3.enums)(Object.values(ContentActionVariant));
557
+ var sTextBlock = (0, import_superstruct3.object)({
558
+ type: (0, import_superstruct3.literal)("text" /* Text */),
559
+ content: (0, import_superstruct3.optional)((0, import_superstruct3.string)()),
560
+ computedKey: (0, import_superstruct3.optional)((0, import_superstruct3.string)())
561
+ });
562
+ var sBannerBlock2 = (0, import_superstruct3.object)({
563
+ type: (0, import_superstruct3.literal)("banner" /* Banner */),
564
+ variant: sMessageVariant2,
565
+ title: (0, import_superstruct3.optional)((0, import_superstruct3.string)()),
566
+ text: (0, import_superstruct3.string)()
567
+ });
568
+ var sBadgeBlock = (0, import_superstruct3.object)({
569
+ type: (0, import_superstruct3.literal)("badge" /* Badge */),
570
+ variant: sMessageVariant2,
571
+ text: (0, import_superstruct3.optional)((0, import_superstruct3.string)()),
572
+ computedKey: (0, import_superstruct3.optional)((0, import_superstruct3.string)())
573
+ });
574
+ var sKeyValueBlock2 = (0, import_superstruct3.object)({
575
+ type: (0, import_superstruct3.literal)("keyValue" /* KeyValue */),
576
+ rows: (0, import_superstruct3.array)(
577
+ (0, import_superstruct3.object)({
578
+ label: (0, import_superstruct3.string)(),
579
+ value: (0, import_superstruct3.optional)((0, import_superstruct3.string)()),
580
+ computedKey: (0, import_superstruct3.optional)((0, import_superstruct3.string)())
581
+ })
582
+ )
583
+ });
584
+ var sCopyFieldBlock2 = (0, import_superstruct3.object)({
585
+ type: (0, import_superstruct3.literal)("copyField" /* CopyField */),
586
+ label: (0, import_superstruct3.string)(),
587
+ value: (0, import_superstruct3.optional)((0, import_superstruct3.string)()),
588
+ computedKey: (0, import_superstruct3.optional)((0, import_superstruct3.string)())
589
+ });
590
+ var sLinkBlock = (0, import_superstruct3.object)({
591
+ type: (0, import_superstruct3.literal)("link" /* Link */),
592
+ label: (0, import_superstruct3.string)(),
593
+ href: (0, import_superstruct3.optional)((0, import_superstruct3.string)()),
594
+ computedKey: (0, import_superstruct3.optional)((0, import_superstruct3.string)()),
595
+ external: (0, import_superstruct3.optional)((0, import_superstruct3.boolean)())
596
+ });
597
+ var sDividerBlock2 = (0, import_superstruct3.object)({ type: (0, import_superstruct3.literal)("divider" /* Divider */) });
598
+ var sActionBlock2 = (0, import_superstruct3.object)({
599
+ type: (0, import_superstruct3.literal)("action" /* Action */),
600
+ id: (0, import_superstruct3.string)(),
601
+ label: (0, import_superstruct3.string)(),
602
+ variant: (0, import_superstruct3.optional)(sContentActionVariant)
603
+ });
604
+ var sCardBlock2 = (0, import_superstruct3.object)({
605
+ type: (0, import_superstruct3.literal)("card" /* Card */),
606
+ title: (0, import_superstruct3.optional)((0, import_superstruct3.string)()),
607
+ description: (0, import_superstruct3.optional)((0, import_superstruct3.string)()),
608
+ blocks: (0, import_superstruct3.array)((0, import_superstruct3.lazy)(() => sContentBlock))
609
+ });
610
+ var sContentBlock = (0, import_superstruct3.union)([
611
+ sTextBlock,
612
+ sBannerBlock2,
613
+ sBadgeBlock,
614
+ sKeyValueBlock2,
615
+ sCopyFieldBlock2,
616
+ sLinkBlock,
617
+ sDividerBlock2,
618
+ sActionBlock2,
619
+ sCardBlock2
620
+ ]);
621
+ var sUiContribution = (0, import_superstruct3.object)({
622
+ slot: (0, import_superstruct3.string)(),
623
+ blocks: (0, import_superstruct3.array)(sContentBlock),
624
+ order: (0, import_superstruct3.optional)((0, import_superstruct3.number)())
625
+ });
626
+ function validateUiContributions(input) {
627
+ const [error, result] = (0, import_superstruct3.validate)(input, (0, import_superstruct3.array)(sUiContribution));
628
+ if (error) {
629
+ return {
630
+ success: false,
631
+ errors: error.failures().map((f) => {
632
+ const path = f.path.join(".");
633
+ return path ? `${path}: ${f.message}` : f.message;
634
+ })
635
+ };
636
+ }
637
+ return { success: true, data: result };
638
+ }
639
+
513
640
  // src/capability.ts
514
641
  var CapabilityKind = {
515
642
  Payment: "payment",
516
643
  Shipping: "shipping",
517
644
  Suppliers: "suppliers",
518
645
  Analytics: "analytics",
519
- Invoicing: "invoicing"
646
+ Invoicing: "invoicing",
647
+ /**
648
+ * Cross-cutting DISPLAY capability: a plugin of ANY surface may ALSO expose
649
+ * `ui` to contribute declarative blocks into host slots. Not a catalog
650
+ * "surface" — the host's AppSurface derivation excludes it on purpose.
651
+ */
652
+ Ui: "ui"
520
653
  };
521
654
  function capability(kind, impl) {
522
655
  return { kind, impl };
@@ -536,6 +669,9 @@ function analyticsCapability(impl) {
536
669
  function invoicingCapability(impl) {
537
670
  return { kind: CapabilityKind.Invoicing, impl };
538
671
  }
672
+ function uiCapability(impl) {
673
+ return { kind: CapabilityKind.Ui, impl };
674
+ }
539
675
  var PLUGIN_FACTORY_BRAND = /* @__PURE__ */ Symbol.for("vivoa.plugin.factory");
540
676
  function definePlugin(factory) {
541
677
  Object.defineProperty(factory, PLUGIN_FACTORY_BRAND, {
@@ -581,7 +717,7 @@ function checkPermissions(required, grantedRaw) {
581
717
  }
582
718
 
583
719
  // src/version.ts
584
- var SDK_VERSION = "0.6.5";
720
+ var SDK_VERSION = "0.6.7";
585
721
  function isSdkCompatible(pluginSdkVersion, hostSdkVersion) {
586
722
  const parse = (v) => {
587
723
  const m = /^(\d+)\.(\d+)\.(\d+)/.exec(v);
@@ -599,12 +735,15 @@ function isSdkCompatible(pluginSdkVersion, hostSdkVersion) {
599
735
  // Annotate the CommonJS export names for ESM import in node:
600
736
  0 && (module.exports = {
601
737
  ANALYTICS_PLUGIN_TOKEN,
738
+ AUTHOR_HANDLE_RE,
602
739
  ActionVariant,
603
740
  AnalyticsFeature,
604
741
  BlockType,
605
742
  CapabilityKind,
606
743
  CodFeeType,
607
744
  ConfigScope,
745
+ ContentActionVariant,
746
+ ContentBlockType,
608
747
  FieldType,
609
748
  FieldVariant,
610
749
  GatewayEnvironment,
@@ -615,7 +754,6 @@ function isSdkCompatible(pluginSdkVersion, hostSdkVersion) {
615
754
  LayoutMode,
616
755
  MessageVariant,
617
756
  PAYMENT_PLUGIN_TOKEN,
618
- PluginType,
619
757
  RepeaterSource,
620
758
  SDK_VERSION,
621
759
  SHIPPING_PLUGIN_TOKEN,
@@ -640,5 +778,8 @@ function isSdkCompatible(pluginSdkVersion, hostSdkVersion) {
640
778
  paymentCapability,
641
779
  shippingCapability,
642
780
  suppliersCapability,
643
- validateSetupLayout
781
+ uiCapability,
782
+ validatePluginAuthor,
783
+ validateSetupLayout,
784
+ validateUiContributions
644
785
  });
package/dist/index.mjs CHANGED
@@ -1,3 +1,9 @@
1
+ import {
2
+ checkPermissions,
3
+ isPermissionGranted,
4
+ parsePermission
5
+ } from "./chunk-DGJZW46B.mjs";
6
+
1
7
  // src/tokens.ts
2
8
  var PAYMENT_PLUGIN_TOKEN = "PAYMENT_PLUGINS";
3
9
  var SHIPPING_PLUGIN_TOKEN = "SHIPPING_PLUGINS";
@@ -6,14 +12,6 @@ var ANALYTICS_PLUGIN_TOKEN = "ANALYTICS_PLUGINS";
6
12
  var INVOICING_PLUGIN_TOKEN = "INVOICING_PLUGINS";
7
13
 
8
14
  // src/plugin.ts
9
- var PluginType = /* @__PURE__ */ ((PluginType2) => {
10
- PluginType2["Payment"] = "payment";
11
- PluginType2["Shipping"] = "shipping";
12
- PluginType2["Analytics"] = "analytics";
13
- PluginType2["Invoicing"] = "invoicing";
14
- PluginType2["Generic"] = "generic";
15
- return PluginType2;
16
- })(PluginType || {});
17
15
  var MessageVariant = /* @__PURE__ */ ((MessageVariant2) => {
18
16
  MessageVariant2["Info"] = "info";
19
17
  MessageVariant2["Warning"] = "warning";
@@ -184,6 +182,30 @@ var InvoiceStatus = /* @__PURE__ */ ((InvoiceStatus2) => {
184
182
  return InvoiceStatus2;
185
183
  })(InvoiceStatus || {});
186
184
 
185
+ // src/author.ts
186
+ var AUTHOR_HANDLE_RE = /^[a-z0-9][a-z0-9-]*$/;
187
+ function validatePluginAuthor(value) {
188
+ const errors = [];
189
+ if (typeof value !== "object" || value === null) {
190
+ return { ok: false, errors: ["author is required and must be an object"] };
191
+ }
192
+ const a = value;
193
+ if (typeof a.handle !== "string" || a.handle.length === 0) {
194
+ errors.push("author.handle is required");
195
+ } else if (!AUTHOR_HANDLE_RE.test(a.handle)) {
196
+ errors.push(
197
+ `author.handle "${a.handle}" must be a lowercase slug (a-z, 0-9, dash; start alphanumeric)`
198
+ );
199
+ }
200
+ if (typeof a.displayName !== "string" || a.displayName.trim().length === 0) {
201
+ errors.push("author.displayName is required");
202
+ }
203
+ if (a.url !== void 0 && typeof a.url !== "string") {
204
+ errors.push("author.url must be a string when present");
205
+ }
206
+ return { ok: errors.length === 0, errors };
207
+ }
208
+
187
209
  // src/setup-layout.ts
188
210
  import {
189
211
  array,
@@ -267,6 +289,7 @@ var sGroupBlock = object({
267
289
  type: literal("group" /* Group */),
268
290
  title: string2(),
269
291
  description: optional2(string2()),
292
+ helpUrl: optional2(string2()),
270
293
  fields: array(string2()),
271
294
  collapsible: optional2(boolean2()),
272
295
  defaultOpen: optional2(boolean2()),
@@ -463,13 +486,136 @@ function crossValidateSetupLayout(layout, configSchema) {
463
486
  return errors;
464
487
  }
465
488
 
489
+ // src/ui.ts
490
+ import {
491
+ array as array2,
492
+ boolean as boolean3,
493
+ enums as enums3,
494
+ lazy as lazy2,
495
+ literal as literal2,
496
+ number as number3,
497
+ object as object2,
498
+ optional as optional3,
499
+ string as string3,
500
+ union as union2,
501
+ validate as validate3
502
+ } from "superstruct";
503
+ var ContentBlockType = /* @__PURE__ */ ((ContentBlockType2) => {
504
+ ContentBlockType2["Text"] = "text";
505
+ ContentBlockType2["Banner"] = "banner";
506
+ ContentBlockType2["Badge"] = "badge";
507
+ ContentBlockType2["KeyValue"] = "keyValue";
508
+ ContentBlockType2["CopyField"] = "copyField";
509
+ ContentBlockType2["Link"] = "link";
510
+ ContentBlockType2["Divider"] = "divider";
511
+ ContentBlockType2["Action"] = "action";
512
+ ContentBlockType2["Card"] = "card";
513
+ return ContentBlockType2;
514
+ })(ContentBlockType || {});
515
+ var ContentActionVariant = /* @__PURE__ */ ((ContentActionVariant2) => {
516
+ ContentActionVariant2["Primary"] = "primary";
517
+ ContentActionVariant2["Secondary"] = "secondary";
518
+ ContentActionVariant2["Danger"] = "danger";
519
+ return ContentActionVariant2;
520
+ })(ContentActionVariant || {});
521
+ var sMessageVariant2 = enums3(Object.values(MessageVariant));
522
+ var sContentActionVariant = enums3(Object.values(ContentActionVariant));
523
+ var sTextBlock = object2({
524
+ type: literal2("text" /* Text */),
525
+ content: optional3(string3()),
526
+ computedKey: optional3(string3())
527
+ });
528
+ var sBannerBlock2 = object2({
529
+ type: literal2("banner" /* Banner */),
530
+ variant: sMessageVariant2,
531
+ title: optional3(string3()),
532
+ text: string3()
533
+ });
534
+ var sBadgeBlock = object2({
535
+ type: literal2("badge" /* Badge */),
536
+ variant: sMessageVariant2,
537
+ text: optional3(string3()),
538
+ computedKey: optional3(string3())
539
+ });
540
+ var sKeyValueBlock2 = object2({
541
+ type: literal2("keyValue" /* KeyValue */),
542
+ rows: array2(
543
+ object2({
544
+ label: string3(),
545
+ value: optional3(string3()),
546
+ computedKey: optional3(string3())
547
+ })
548
+ )
549
+ });
550
+ var sCopyFieldBlock2 = object2({
551
+ type: literal2("copyField" /* CopyField */),
552
+ label: string3(),
553
+ value: optional3(string3()),
554
+ computedKey: optional3(string3())
555
+ });
556
+ var sLinkBlock = object2({
557
+ type: literal2("link" /* Link */),
558
+ label: string3(),
559
+ href: optional3(string3()),
560
+ computedKey: optional3(string3()),
561
+ external: optional3(boolean3())
562
+ });
563
+ var sDividerBlock2 = object2({ type: literal2("divider" /* Divider */) });
564
+ var sActionBlock2 = object2({
565
+ type: literal2("action" /* Action */),
566
+ id: string3(),
567
+ label: string3(),
568
+ variant: optional3(sContentActionVariant)
569
+ });
570
+ var sCardBlock2 = object2({
571
+ type: literal2("card" /* Card */),
572
+ title: optional3(string3()),
573
+ description: optional3(string3()),
574
+ blocks: array2(lazy2(() => sContentBlock))
575
+ });
576
+ var sContentBlock = union2([
577
+ sTextBlock,
578
+ sBannerBlock2,
579
+ sBadgeBlock,
580
+ sKeyValueBlock2,
581
+ sCopyFieldBlock2,
582
+ sLinkBlock,
583
+ sDividerBlock2,
584
+ sActionBlock2,
585
+ sCardBlock2
586
+ ]);
587
+ var sUiContribution = object2({
588
+ slot: string3(),
589
+ blocks: array2(sContentBlock),
590
+ order: optional3(number3())
591
+ });
592
+ function validateUiContributions(input) {
593
+ const [error, result] = validate3(input, array2(sUiContribution));
594
+ if (error) {
595
+ return {
596
+ success: false,
597
+ errors: error.failures().map((f) => {
598
+ const path = f.path.join(".");
599
+ return path ? `${path}: ${f.message}` : f.message;
600
+ })
601
+ };
602
+ }
603
+ return { success: true, data: result };
604
+ }
605
+
466
606
  // src/capability.ts
467
607
  var CapabilityKind = {
468
608
  Payment: "payment",
469
609
  Shipping: "shipping",
470
610
  Suppliers: "suppliers",
471
611
  Analytics: "analytics",
472
- Invoicing: "invoicing"
612
+ Invoicing: "invoicing",
613
+ /**
614
+ * Cross-cutting DISPLAY capability: a plugin of ANY surface may ALSO expose
615
+ * `ui` to contribute declarative blocks into host slots. Not a catalog
616
+ * "surface" — the host's AppSurface derivation excludes it on purpose.
617
+ */
618
+ Ui: "ui"
473
619
  };
474
620
  function capability(kind, impl) {
475
621
  return { kind, impl };
@@ -489,6 +635,9 @@ function analyticsCapability(impl) {
489
635
  function invoicingCapability(impl) {
490
636
  return { kind: CapabilityKind.Invoicing, impl };
491
637
  }
638
+ function uiCapability(impl) {
639
+ return { kind: CapabilityKind.Ui, impl };
640
+ }
492
641
  var PLUGIN_FACTORY_BRAND = /* @__PURE__ */ Symbol.for("vivoa.plugin.factory");
493
642
  function definePlugin(factory) {
494
643
  Object.defineProperty(factory, PLUGIN_FACTORY_BRAND, {
@@ -501,40 +650,8 @@ function isPluginFactory(value) {
501
650
  return typeof value === "function" && value[PLUGIN_FACTORY_BRAND] === true;
502
651
  }
503
652
 
504
- // src/permissions.ts
505
- var PERMISSION_RE = /^([a-z0-9]+)\.([a-z0-9]+)(?::(.+))?$/i;
506
- function parsePermission(raw) {
507
- const m = PERMISSION_RE.exec(raw);
508
- if (!m) return null;
509
- const [, domain, action, resource] = m;
510
- return resource === void 0 ? { domain, action } : { domain, action, resource };
511
- }
512
- function isPermissionGranted(required, granted) {
513
- return granted.some((g) => {
514
- if (g.domain !== required.domain || g.action !== required.action) {
515
- return false;
516
- }
517
- if (required.resource === void 0) return true;
518
- return g.resource === "*" || g.resource === required.resource;
519
- });
520
- }
521
- function checkPermissions(required, grantedRaw) {
522
- const grantedParsed = grantedRaw.map(parsePermission).filter((p) => p !== null);
523
- const granted = [];
524
- const missing = [];
525
- for (const raw of required) {
526
- const parsed = parsePermission(raw);
527
- if (parsed && isPermissionGranted(parsed, grantedParsed)) {
528
- granted.push(raw);
529
- } else {
530
- missing.push(raw);
531
- }
532
- }
533
- return { ok: missing.length === 0, granted, missing };
534
- }
535
-
536
653
  // src/version.ts
537
- var SDK_VERSION = "0.6.5";
654
+ var SDK_VERSION = "0.6.7";
538
655
  function isSdkCompatible(pluginSdkVersion, hostSdkVersion) {
539
656
  const parse = (v) => {
540
657
  const m = /^(\d+)\.(\d+)\.(\d+)/.exec(v);
@@ -551,12 +668,15 @@ function isSdkCompatible(pluginSdkVersion, hostSdkVersion) {
551
668
  }
552
669
  export {
553
670
  ANALYTICS_PLUGIN_TOKEN,
671
+ AUTHOR_HANDLE_RE,
554
672
  ActionVariant,
555
673
  AnalyticsFeature,
556
674
  BlockType,
557
675
  CapabilityKind,
558
676
  CodFeeType,
559
677
  ConfigScope,
678
+ ContentActionVariant,
679
+ ContentBlockType,
560
680
  FieldType,
561
681
  FieldVariant,
562
682
  GatewayEnvironment,
@@ -567,7 +687,6 @@ export {
567
687
  LayoutMode,
568
688
  MessageVariant,
569
689
  PAYMENT_PLUGIN_TOKEN,
570
- PluginType,
571
690
  RepeaterSource,
572
691
  SDK_VERSION,
573
692
  SHIPPING_PLUGIN_TOKEN,
@@ -592,5 +711,8 @@ export {
592
711
  paymentCapability,
593
712
  shippingCapability,
594
713
  suppliersCapability,
595
- validateSetupLayout
714
+ uiCapability,
715
+ validatePluginAuthor,
716
+ validateSetupLayout,
717
+ validateUiContributions
596
718
  };
@@ -0,0 +1,54 @@
1
+ import { _ as HostApi, a0 as HttpRequest, R as DomainEventName, u as Capability, Q as DomainEventHandler, a1 as HttpResponse, N as DispatchContext } from '../host-api-yX49e7zE.mjs';
2
+
3
+ /** Every recorded interaction, keyed by `"port.method"`. */
4
+ interface MockHostCalls {
5
+ 'http.request': HttpRequest[];
6
+ 'secrets.get': string[];
7
+ 'storage.getUrl': string[];
8
+ 'storage.put': Array<{
9
+ key: string;
10
+ body: Uint8Array | string;
11
+ }>;
12
+ 'sequence.next': string[];
13
+ 'host.on': DomainEventName[];
14
+ }
15
+ interface MockHostOptions {
16
+ /**
17
+ * Permissions the mock "grants". When set, the mock enforces them exactly as
18
+ * the real host is specified to: an un-granted `http.outbound:<host>` or
19
+ * `secrets.read:<key>` THROWS. Omit to grant everything (pure recorder mode).
20
+ */
21
+ grantedPermissions?: string[];
22
+ /** Canned secret values returned by `secrets.get`. */
23
+ secrets?: Record<string, string>;
24
+ /**
25
+ * Canned HTTP responses. Resolved against the request URL — exact match
26
+ * first, then the first entry whose key is a substring of the URL. Defaults
27
+ * to `{ status: 200, headers: {}, body: {} }`.
28
+ */
29
+ httpResponses?: Record<string, HttpResponse>;
30
+ /** Seed values for named sequence scopes (monotonic from here). */
31
+ sequences?: Record<string, number>;
32
+ }
33
+ interface MockHostApi extends HostApi {
34
+ /** Every port call recorded in order. */
35
+ readonly calls: MockHostCalls;
36
+ /** Capabilities the plugin registered via `registerCapability`. */
37
+ readonly registered: Capability[];
38
+ /** Event handlers the plugin subscribed via `host.on`. */
39
+ readonly handlers: Map<DomainEventName, DomainEventHandler[]>;
40
+ /** Drives a subscribed handler as if the host emitted the event. */
41
+ emit(event: DomainEventName, payload: unknown): Promise<void>;
42
+ }
43
+ /**
44
+ * Builds a {@link MockHostApi}. Pass `grantedPermissions` to assert your plugin
45
+ * declared what it actually uses; leave it out to just record calls.
46
+ */
47
+ declare function createMockHostApi(opts?: MockHostOptions): MockHostApi;
48
+ /**
49
+ * Minimal {@link DispatchContext} for dispatch-method tests. Pass the merged
50
+ * config your plugin expects; the country fields mirror the host's resolution.
51
+ */
52
+ declare function createDispatchContext(config?: Record<string, unknown>, overrides?: Partial<DispatchContext>): DispatchContext;
53
+
54
+ export { type MockHostApi, type MockHostCalls, type MockHostOptions, createDispatchContext, createMockHostApi };
@@ -0,0 +1,54 @@
1
+ import { _ as HostApi, a0 as HttpRequest, R as DomainEventName, u as Capability, Q as DomainEventHandler, a1 as HttpResponse, N as DispatchContext } from '../host-api-yX49e7zE.js';
2
+
3
+ /** Every recorded interaction, keyed by `"port.method"`. */
4
+ interface MockHostCalls {
5
+ 'http.request': HttpRequest[];
6
+ 'secrets.get': string[];
7
+ 'storage.getUrl': string[];
8
+ 'storage.put': Array<{
9
+ key: string;
10
+ body: Uint8Array | string;
11
+ }>;
12
+ 'sequence.next': string[];
13
+ 'host.on': DomainEventName[];
14
+ }
15
+ interface MockHostOptions {
16
+ /**
17
+ * Permissions the mock "grants". When set, the mock enforces them exactly as
18
+ * the real host is specified to: an un-granted `http.outbound:<host>` or
19
+ * `secrets.read:<key>` THROWS. Omit to grant everything (pure recorder mode).
20
+ */
21
+ grantedPermissions?: string[];
22
+ /** Canned secret values returned by `secrets.get`. */
23
+ secrets?: Record<string, string>;
24
+ /**
25
+ * Canned HTTP responses. Resolved against the request URL — exact match
26
+ * first, then the first entry whose key is a substring of the URL. Defaults
27
+ * to `{ status: 200, headers: {}, body: {} }`.
28
+ */
29
+ httpResponses?: Record<string, HttpResponse>;
30
+ /** Seed values for named sequence scopes (monotonic from here). */
31
+ sequences?: Record<string, number>;
32
+ }
33
+ interface MockHostApi extends HostApi {
34
+ /** Every port call recorded in order. */
35
+ readonly calls: MockHostCalls;
36
+ /** Capabilities the plugin registered via `registerCapability`. */
37
+ readonly registered: Capability[];
38
+ /** Event handlers the plugin subscribed via `host.on`. */
39
+ readonly handlers: Map<DomainEventName, DomainEventHandler[]>;
40
+ /** Drives a subscribed handler as if the host emitted the event. */
41
+ emit(event: DomainEventName, payload: unknown): Promise<void>;
42
+ }
43
+ /**
44
+ * Builds a {@link MockHostApi}. Pass `grantedPermissions` to assert your plugin
45
+ * declared what it actually uses; leave it out to just record calls.
46
+ */
47
+ declare function createMockHostApi(opts?: MockHostOptions): MockHostApi;
48
+ /**
49
+ * Minimal {@link DispatchContext} for dispatch-method tests. Pass the merged
50
+ * config your plugin expects; the country fields mirror the host's resolution.
51
+ */
52
+ declare function createDispatchContext(config?: Record<string, unknown>, overrides?: Partial<DispatchContext>): DispatchContext;
53
+
54
+ export { type MockHostApi, type MockHostCalls, type MockHostOptions, createDispatchContext, createMockHostApi };