@aglyn/plugins-marketplace 1.11.0 → 1.13.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.
Files changed (83) hide show
  1. package/package.json +14 -14
  2. package/src/lib/components/listing-content.component.js +78 -36
  3. package/src/lib/components/listing-content.component.js.map +1 -1
  4. package/src/lib/components/listing-detail-page.component.js +22 -9
  5. package/src/lib/components/listing-detail-page.component.js.map +1 -1
  6. package/src/lib/components/listing-review-status.component.d.ts +8 -0
  7. package/src/lib/components/listing-review-status.component.js +23 -3
  8. package/src/lib/components/listing-review-status.component.js.map +1 -1
  9. package/src/lib/components/listing-verification-request.component.d.ts +8 -0
  10. package/src/lib/components/listing-verification-request.component.js +12 -5
  11. package/src/lib/components/listing-verification-request.component.js.map +1 -1
  12. package/src/lib/components/marketplace-hub.component.js +2 -1
  13. package/src/lib/components/marketplace-hub.component.js.map +1 -1
  14. package/src/lib/components/org-seller-panel.component.d.ts +10 -0
  15. package/src/lib/components/org-seller-panel.component.js +26 -4
  16. package/src/lib/components/org-seller-panel.component.js.map +1 -1
  17. package/src/lib/components/starter-picker-shelf.component.js +13 -8
  18. package/src/lib/components/starter-picker-shelf.component.js.map +1 -1
  19. package/src/lib/declarations.d.ts +2 -1
  20. package/src/lib/declarations.js +5 -1
  21. package/src/lib/declarations.js.map +1 -1
  22. package/src/lib/model/marketplace-catalog.js +1 -1
  23. package/src/lib/model/marketplace-catalog.js.map +1 -1
  24. package/src/lib/model/marketplace-publisher-permissions.d.ts +26 -0
  25. package/src/lib/model/marketplace-publisher-permissions.js +64 -0
  26. package/src/lib/model/marketplace-publisher-permissions.js.map +1 -0
  27. package/src/lib/model/marketplace.js +2 -1
  28. package/src/lib/model/marketplace.js.map +1 -1
  29. package/src/lib/model/own-listing.d.ts +52 -0
  30. package/src/lib/model/own-listing.js +72 -0
  31. package/src/lib/model/own-listing.js.map +1 -0
  32. package/src/lib/model/starter-query.js +2 -0
  33. package/src/lib/model/starter-query.js.map +1 -1
  34. package/src/lib/server/connect.js +11 -5
  35. package/src/lib/server/connect.js.map +1 -1
  36. package/src/lib/server/install-dataset-schema.js +10 -2
  37. package/src/lib/server/install-dataset-schema.js.map +1 -1
  38. package/src/lib/server/install-email-starter.js +8 -2
  39. package/src/lib/server/install-email-starter.js.map +1 -1
  40. package/src/lib/server/install-email-template.js +8 -2
  41. package/src/lib/server/install-email-template.js.map +1 -1
  42. package/src/lib/server/install-layout.js +8 -2
  43. package/src/lib/server/install-layout.js.map +1 -1
  44. package/src/lib/server/install-plugin.js +24 -20
  45. package/src/lib/server/install-plugin.js.map +1 -1
  46. package/src/lib/server/install-template.js +8 -5
  47. package/src/lib/server/install-template.js.map +1 -1
  48. package/src/lib/server/install-theme.js +8 -2
  49. package/src/lib/server/install-theme.js.map +1 -1
  50. package/src/lib/server/install.js +10 -5
  51. package/src/lib/server/install.js.map +1 -1
  52. package/src/lib/server/listing-versions.js +24 -9
  53. package/src/lib/server/listing-versions.js.map +1 -1
  54. package/src/lib/server/own-listing.d.ts +46 -0
  55. package/src/lib/server/own-listing.js +52 -0
  56. package/src/lib/server/own-listing.js.map +1 -0
  57. package/src/lib/server/preview-image.d.ts +1 -1
  58. package/src/lib/server/preview-image.js +9 -8
  59. package/src/lib/server/preview-image.js.map +1 -1
  60. package/src/lib/server/publish-plugin.js +17 -19
  61. package/src/lib/server/publish-plugin.js.map +1 -1
  62. package/src/lib/server/publisher-permissions.d.ts +63 -0
  63. package/src/lib/server/publisher-permissions.js +51 -0
  64. package/src/lib/server/publisher-permissions.js.map +1 -0
  65. package/src/lib/server/publisher-profile-save.d.ts +4 -2
  66. package/src/lib/server/publisher-profile-save.js +12 -5
  67. package/src/lib/server/publisher-profile-save.js.map +1 -1
  68. package/src/lib/server/publisher-profile.d.ts +18 -6
  69. package/src/lib/server/publisher-profile.js +19 -8
  70. package/src/lib/server/publisher-profile.js.map +1 -1
  71. package/src/lib/server/reviews.js +6 -5
  72. package/src/lib/server/reviews.js.map +1 -1
  73. package/src/lib/server/sale-risk.d.ts +0 -6
  74. package/src/lib/server/sale-risk.js +0 -9
  75. package/src/lib/server/sale-risk.js.map +1 -1
  76. package/src/lib/server/sale.js +10 -9
  77. package/src/lib/server/sale.js.map +1 -1
  78. package/src/lib/server/site-starter-source.js +43 -17
  79. package/src/lib/server/site-starter-source.js.map +1 -1
  80. package/src/lib/server/update-artifact.js +11 -4
  81. package/src/lib/server/update-artifact.js.map +1 -1
  82. package/src/lib/server/verification-request.js +23 -7
  83. package/src/lib/server/verification-request.js.map +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aglyn/plugins-marketplace",
3
- "version": "1.11.0",
3
+ "version": "1.13.0",
4
4
  "license": "Apache-2.0",
5
5
  "homepage": "https://aglyn.com",
6
6
  "repository": {
@@ -25,19 +25,19 @@
25
25
  "./package.json": "./package.json"
26
26
  },
27
27
  "dependencies": {
28
- "@aglyn/aglyn": "1.11.0",
29
- "@aglyn/aglyn-markdown-editor": "1.11.0",
30
- "@aglyn/shared-data-enums": "1.11.0",
31
- "@aglyn/shared-data-mdi": "1.11.0",
32
- "@aglyn/shared-ui-jsx": "1.11.0",
33
- "@aglyn/shared-ui-next": "1.11.0",
34
- "@aglyn/shared-ui-snackstack": "1.11.0",
35
- "@aglyn/shared-util-email": "1.11.0",
36
- "@aglyn/shared-util-http": "1.11.0",
37
- "@aglyn/shared-util-timestamp": "1.11.0",
38
- "@aglyn/tenant-data-admin": "1.11.0",
39
- "@aglyn/tenant-feature-instance": "1.11.0",
40
- "@aglyn/tenant-runtime": "1.11.0",
28
+ "@aglyn/aglyn": "1.13.0",
29
+ "@aglyn/aglyn-markdown-editor": "1.13.0",
30
+ "@aglyn/shared-data-enums": "1.13.0",
31
+ "@aglyn/shared-data-mdi": "1.13.0",
32
+ "@aglyn/shared-ui-jsx": "1.13.0",
33
+ "@aglyn/shared-ui-next": "1.13.0",
34
+ "@aglyn/shared-ui-snackstack": "1.13.0",
35
+ "@aglyn/shared-util-email": "1.13.0",
36
+ "@aglyn/shared-util-http": "1.13.0",
37
+ "@aglyn/shared-util-timestamp": "1.13.0",
38
+ "@aglyn/tenant-data-admin": "1.13.0",
39
+ "@aglyn/tenant-feature-instance": "1.13.0",
40
+ "@aglyn/tenant-runtime": "1.13.0",
41
41
  "@swc/helpers": "0.5.23"
42
42
  },
43
43
  "peerDependencies": {
@@ -17,6 +17,9 @@
17
17
  import { _ as _extends } from "@swc/helpers/_/_extends";
18
18
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
19
19
  import { LISTING_README_MAX_CHARS, listingArtifactType, installsUnreviewedFallback, listingArtifactLabel, listingInclusions, hasLivePurchaseOf, hasOrgLicenceOf, licensedOrgIdsFor, installTargetsFor, isListingDeleted, isPrivateListing, resolveInstallPlan, resolveOrgInstallSummary, resolvePluginInstallState, resolveUninstallTargets, safePublisherHref, safePublisherImageSrc } from "../model/marketplace.js";
20
+ import { isPublisherMemberElsewhere, landsInPublisherWorkspace, publisherMemberBuyReason } from "../model/own-listing.js";
21
+ import { BlockedControl } from "@aglyn/shared-ui-jsx/components/blocked-control.component";
22
+ import { PrerequisiteNotice } from "@aglyn/shared-ui-jsx/components/prerequisite-notice.component";
20
23
  import UninstallImpactDialog from "./uninstall-impact-dialog.component.js";
21
24
  import { ListingImage } from "./listing-image.component.js";
22
25
  import { buildRoute, parseMarkdownLite, PLATFORM_BRAND_NAME, offeredPluginVersion, PLUGIN_HOST_ABI_VERSION, pluginDocsHelp, resolveMarkdownLink, resolveMediaSrc, Route } from "@aglyn/aglyn";
@@ -377,7 +380,7 @@ export function ListingReadme({ readme }) {
377
380
  * version history, publisher block, and the install/buy CTA.
378
381
  */ export function MarketplaceListingContent({ hostId, listingId, permissions, orgScoped, orgSlug: orgSlugProp, hosts }) {
379
382
  var _ref, _ref1, _pluginState_scope, _ref2, _ref3, _ref4, _listing_ratingAverage, _listing_ratingAverage1, _ref5, _ref6, _ref7, _ref8, _ref9, _ref10, _ref11, _ref12, _ref13, _ref14, _ref15, _ref16, _ref17, _ref18, _ref19;
380
- var _componentInstall_marketplace;
383
+ var _componentInstall_marketplace, _profile_displayName;
381
384
  // The publisher link was `/{hostDocId}/marketplace/publisher/{id}` — the
382
385
  // pre-AGL-621 shape, dead since. The sibling browse grid was fixed for
383
386
  // exactly this (AGL-673) and this file was missed; both now build the
@@ -869,7 +872,33 @@ export function ListingReadme({ readme }) {
869
872
  revocation
870
873
  ]);
871
874
  const priceUsd = Number((_ref1 = listing == null ? void 0 : listing.priceUsd) != null ? _ref1 : 0);
872
- const mustBuy = priceUsd > 0 && !purchased && (listing == null ? void 0 : listing.profileId) !== viewerOrgId && !installed;
875
+ // Free without a purchase only where the install routes waive it: the
876
+ // publisher's own listing on a site of the publisher's own workspace
877
+ // (AGL-2484, AGL-4047). `viewerOrgId` is the acting site's workspace, the
878
+ // one the install lands in, so a publisher's member acting on a client's
879
+ // site is asked to buy, as the route would ask.
880
+ const mustBuy = priceUsd > 0 && !purchased && !landsInPublisherWorkspace(listing == null ? void 0 : listing.profileId, viewerOrgId) && !installed;
881
+ // A member of the publisher is refused by the sale for any workspace
882
+ // (AGL-3365), so Buy stays on screen, switched off, with the reason
883
+ // (AGL-4047). Their OWN member document: the same one `isPublisherMember`
884
+ // reads, which the rules let anyone read of themselves, so it says nothing of
885
+ // the publisher's roster. Asked only where Buy is on offer, and only once the
886
+ // acting workspace is known, so the publisher's own site never flashes it. A
887
+ // read that fails leaves Buy on, and the sale still decides.
888
+ const publisherOrgId = typeof (listing == null ? void 0 : listing.profileId) === 'string' ? listing.profileId : '';
889
+ const { data: ownPublisherMembership } = useFirestoreDoc(()=>mustBuy && viewerOrgId && publisherOrgId && (user == null ? void 0 : user.uid) ? doc(firestore, 'orgs', publisherOrgId, 'members', user.uid) : null, [
890
+ firestore,
891
+ mustBuy,
892
+ viewerOrgId,
893
+ publisherOrgId,
894
+ user == null ? void 0 : user.uid
895
+ ]);
896
+ const buyBlocked = mustBuy && isPublisherMemberElsewhere({
897
+ publisherOrgId,
898
+ targetOrgId: viewerOrgId,
899
+ publisherMember: Boolean(ownPublisherMembership)
900
+ });
901
+ const buyBlockedReason = publisherMemberBuyReason((profile == null ? void 0 : (_profile_displayName = profile.displayName) == null ? void 0 : _profile_displayName.trim()) || (profile == null ? void 0 : profile.handle));
873
902
  // Updating an installed plugin stays at its current scope; a fresh install
874
903
  // uses the picker (plugins) or the artifact's only target (everything else).
875
904
  const installTargetScope = isPlugin && installed ? (_pluginState_scope = pluginState.scope) != null ? _pluginState_scope : undefined : installTargets.length > 1 ? installScope : undefined;
@@ -1480,43 +1509,56 @@ export function ListingReadme({ readme }) {
1480
1509
  },
1481
1510
  children: (purchasesTruncated ? `Checked against the first ${PURCHASE_LOOKUP_CEILING} of your purchases, ordered by id; you have more. ` : `Checked against the first ${COMPONENT_LOOKUP_CEILING} components on this site, ordered by id; there are more. `) + 'If you already own or installed this, it may ' + 'not be reflected here — check your receipts ' + 'before buying again.'
1482
1511
  }) : null,
1483
- /*#__PURE__*/ _jsx(Box, {
1512
+ /*#__PURE__*/ _jsxs(Box, {
1484
1513
  sx: {
1485
1514
  display: orgPluginScope && orgInstall.installedAnywhere ? 'none' : undefined
1486
1515
  },
1487
- children: /*#__PURE__*/ _jsx(Button, {
1488
- // Full-width and contained (AGL-1005): in a
1489
- // sidebar card this is the page's primary action,
1490
- // and "already installed and current" is the only
1491
- // state where it steps back to an outline.
1492
- fullWidth: true,
1493
- variant: upToDate ? 'outlined' : 'contained',
1494
- color: "primary",
1495
- disabled: Boolean(upToDate) || !(listing == null ? void 0 : listing.profileId) || // Paying is under way in the panel below.
1496
- buying || Boolean(payPanel) || // Nothing selected to install to (AGL-773).
1497
- orgTargeting && !installed && !mustBuy && installPlanSteps.length === 0,
1498
- onClick: // A site starter is bought to create a site
1499
- // with, so that is the permission it asks for,
1500
- // as the pay door does (AGL-4049).
1501
- (artifactType === SITE_STARTER_ARTIFACT_TYPE ? permissions.createHosts : permissions.installPlugins) ? ()=>// Buying opens the payment panel below,
1502
- // which is its own confirmation; a free or
1503
- // entitled install confirms its targets
1504
- // first (AGL-867). Updating a copied
1505
- // artifact reviews the diff before writing
1506
- // anything (AGL-1018).
1507
- mustBuy ? buy(listing) : copiedUpdatable ? openUpdateReview() : setConfirmOpen(true) : ()=>enqueueSnackbar('Your team role does not allow installing from the marketplace', {
1508
- variant: 'warning',
1509
- persist: false
1510
- }),
1511
- children: upToDate ? `Installed (v${installedVersion})` : copiedUpdatable ? // update would do and writes nothing. Without
1512
- // an ordered version pair there is no "to
1513
- // vN" to promise (AGL-1034), so it says the
1514
- // honest, smaller thing.
1515
- updateStatus.state === 'update-available' ? `Review update to v${offeredVersion}` : 'Review this version' : artifactInstall ? // draft, so this stays enabled (AGL-789). A
1516
- // theme has no "again" — there is one per
1517
- // site, and re-pressing this re-applies it.
1518
- artifactType === 'theme' ? `Applied (v${installedVersion}) · re-apply` : `${artifactType === 'emailTemplate' ? 'Draft added' : 'Added'} (v${installedVersion}) · add again` : installed ? `Update to v${offeredVersion}` : mustBuy ? licensedElsewhere ? `Buy for this workspace — $${priceUsd}` : `Buy for $${priceUsd}` : unreviewedInstall ? `Install unreviewed v${listing == null ? void 0 : listing.latestVersion} for testing` : orgTargeting || installTargets.length > 1 ? 'Install' : 'Add to this site'
1519
- })
1516
+ children: [
1517
+ /*#__PURE__*/ _jsx(BlockedControl, {
1518
+ blocked: buyBlocked,
1519
+ reason: buyBlockedReason,
1520
+ fullWidth: true,
1521
+ children: /*#__PURE__*/ _jsx(Button, {
1522
+ // Full-width and contained (AGL-1005): in a
1523
+ // sidebar card this is the page's primary action,
1524
+ // and "already installed and current" is the only
1525
+ // state where it steps back to an outline.
1526
+ fullWidth: true,
1527
+ variant: upToDate ? 'outlined' : 'contained',
1528
+ color: "primary",
1529
+ disabled: Boolean(upToDate) || !(listing == null ? void 0 : listing.profileId) || // Paying is under way in the panel below.
1530
+ buying || Boolean(payPanel) || // Nothing selected to install to (AGL-773).
1531
+ orgTargeting && !installed && !mustBuy && installPlanSteps.length === 0,
1532
+ onClick: // A site starter is bought to create a site
1533
+ // with, so that is the permission it asks for,
1534
+ // as the pay door does (AGL-4049).
1535
+ (artifactType === SITE_STARTER_ARTIFACT_TYPE ? permissions.createHosts : permissions.installPlugins) ? ()=>// Buying opens the payment panel below,
1536
+ // which is its own confirmation; a free or
1537
+ // entitled install confirms its targets
1538
+ // first (AGL-867). Updating a copied
1539
+ // artifact reviews the diff before writing
1540
+ // anything (AGL-1018).
1541
+ mustBuy ? buy(listing) : copiedUpdatable ? openUpdateReview() : setConfirmOpen(true) : ()=>enqueueSnackbar('Your team role does not allow installing from the marketplace', {
1542
+ variant: 'warning',
1543
+ persist: false
1544
+ }),
1545
+ children: upToDate ? `Installed (v${installedVersion})` : copiedUpdatable ? // update would do and writes nothing. Without
1546
+ // an ordered version pair there is no "to
1547
+ // vN" to promise (AGL-1034), so it says the
1548
+ // honest, smaller thing.
1549
+ updateStatus.state === 'update-available' ? `Review update to v${offeredVersion}` : 'Review this version' : artifactInstall ? // draft, so this stays enabled (AGL-789). A
1550
+ // theme has no "again" — there is one per
1551
+ // site, and re-pressing this re-applies it.
1552
+ artifactType === 'theme' ? `Applied (v${installedVersion}) · re-apply` : `${artifactType === 'emailTemplate' ? 'Draft added' : 'Added'} (v${installedVersion}) · add again` : installed ? `Update to v${offeredVersion}` : mustBuy ? licensedElsewhere ? `Buy for this workspace — $${priceUsd}` : `Buy for $${priceUsd}` : unreviewedInstall ? `Install unreviewed v${listing == null ? void 0 : listing.latestVersion} for testing` : orgTargeting || installTargets.length > 1 ? 'Install' : 'Add to this site'
1553
+ })
1554
+ }),
1555
+ buyBlocked ? /*#__PURE__*/ _jsx(PrerequisiteNotice, {
1556
+ sx: {
1557
+ mt: 1
1558
+ },
1559
+ children: buyBlockedReason
1560
+ }) : null
1561
+ ]
1520
1562
  }),
1521
1563
  payPanel,
1522
1564
  !orgPluginScope && isPlugin && installed ? /*#__PURE__*/ _jsx(Button, {