@aglyn/plugins-marketplace 1.2.0 → 1.4.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 (76) hide show
  1. package/README.md +1 -1
  2. package/package.json +14 -14
  3. package/src/lib/components/listing-content.component.js +11 -3
  4. package/src/lib/components/listing-content.component.js.map +1 -1
  5. package/src/lib/components/marketplace-pay-panel.component.d.ts +67 -0
  6. package/src/lib/components/marketplace-pay-panel.component.js +228 -0
  7. package/src/lib/components/marketplace-pay-panel.component.js.map +1 -0
  8. package/src/lib/components/publish-artifact-dialog.component.d.ts +1 -1
  9. package/src/lib/components/publish-artifact-dialog.component.js +144 -20
  10. package/src/lib/components/publish-artifact-dialog.component.js.map +1 -1
  11. package/src/lib/components/publish-starter-fields.component.d.ts +35 -0
  12. package/src/lib/components/publish-starter-fields.component.js +176 -0
  13. package/src/lib/components/publish-starter-fields.component.js.map +1 -0
  14. package/src/lib/components/starter-picker-shelf.component.d.ts +2 -2
  15. package/src/lib/components/starter-picker-shelf.component.js +28 -6
  16. package/src/lib/components/starter-picker-shelf.component.js.map +1 -1
  17. package/src/lib/hooks/use-marketplace-actions.d.ts +9 -3
  18. package/src/lib/hooks/use-marketplace-actions.js +47 -89
  19. package/src/lib/hooks/use-marketplace-actions.js.map +1 -1
  20. package/src/lib/hooks/use-marketplace-pay.d.ts +70 -0
  21. package/src/lib/hooks/use-marketplace-pay.js +359 -0
  22. package/src/lib/hooks/use-marketplace-pay.js.map +1 -0
  23. package/src/lib/hooks/use-starter-publish-facts.d.ts +25 -0
  24. package/src/lib/hooks/use-starter-publish-facts.js +116 -0
  25. package/src/lib/hooks/use-starter-publish-facts.js.map +1 -0
  26. package/src/lib/hooks/use-starter-purchase.d.ts +17 -22
  27. package/src/lib/hooks/use-starter-purchase.js +26 -73
  28. package/src/lib/hooks/use-starter-purchase.js.map +1 -1
  29. package/src/lib/model/marketplace-invoice.d.ts +52 -0
  30. package/src/lib/model/marketplace-invoice.js +75 -0
  31. package/src/lib/model/marketplace-invoice.js.map +1 -0
  32. package/src/lib/model/marketplace-pay.d.ts +42 -0
  33. package/src/lib/model/marketplace-pay.js +33 -0
  34. package/src/lib/model/marketplace-pay.js.map +1 -0
  35. package/src/lib/model/platform-seller.d.ts +37 -0
  36. package/src/lib/model/platform-seller.js +36 -0
  37. package/src/lib/model/platform-seller.js.map +1 -0
  38. package/src/lib/model/publisher-agreement.d.ts +15 -3
  39. package/src/lib/model/publisher-agreement.js +23 -3
  40. package/src/lib/model/publisher-agreement.js.map +1 -1
  41. package/src/lib/model/starter-publish.d.ts +159 -0
  42. package/src/lib/model/starter-publish.js +189 -0
  43. package/src/lib/model/starter-publish.js.map +1 -0
  44. package/src/lib/model/starter-query.d.ts +0 -8
  45. package/src/lib/model/starter-query.js +0 -10
  46. package/src/lib/model/starter-query.js.map +1 -1
  47. package/src/lib/server/billing-webhook.d.ts +6 -0
  48. package/src/lib/server/billing-webhook.js +269 -211
  49. package/src/lib/server/billing-webhook.js.map +1 -1
  50. package/src/lib/server/checkout.d.ts +2 -48
  51. package/src/lib/server/checkout.js +21 -241
  52. package/src/lib/server/checkout.js.map +1 -1
  53. package/src/lib/server/pay.d.ts +18 -0
  54. package/src/lib/server/pay.js +540 -0
  55. package/src/lib/server/pay.js.map +1 -0
  56. package/src/lib/server/platform-org.d.ts +23 -0
  57. package/src/lib/server/platform-org.js +27 -0
  58. package/src/lib/server/platform-org.js.map +1 -0
  59. package/src/lib/server/publish-preconditions.js +4 -1
  60. package/src/lib/server/publish-preconditions.js.map +1 -1
  61. package/src/lib/server/publish-starter.js +5 -2
  62. package/src/lib/server/publish-starter.js.map +1 -1
  63. package/src/lib/server/publisher-profile.d.ts +5 -0
  64. package/src/lib/server/publisher-profile.js +20 -1
  65. package/src/lib/server/publisher-profile.js.map +1 -1
  66. package/src/lib/server/publisher-standing.d.ts +26 -0
  67. package/src/lib/server/publisher-standing.js +66 -0
  68. package/src/lib/server/publisher-standing.js.map +1 -0
  69. package/src/lib/server/sale.d.ts +119 -0
  70. package/src/lib/server/sale.js +304 -0
  71. package/src/lib/server/sale.js.map +1 -0
  72. package/src/lib/server/starter-publish-facts.d.ts +36 -0
  73. package/src/lib/server/starter-publish-facts.js +135 -0
  74. package/src/lib/server/starter-publish-facts.js.map +1 -0
  75. package/src/lib/server.js +8 -0
  76. package/src/lib/server.js.map +1 -1
@@ -14,87 +14,40 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */ 'use client';
17
- import { lockdownRefusalText, parseLockdownRefusal } from "@aglyn/aglyn/app-utils/lockdown";
18
- import { readGaClientId } from "@aglyn/aglyn/app-utils/analytics-events";
19
- import { authorizedFetch } from "@aglyn/shared-util-http/authorized-token";
20
- import { useUser } from "@aglyn/tenant-feature-instance";
21
- import { useCallback, useRef, useState } from "react";
22
- import { STARTER_CHECKOUT_PATH, starterCheckoutBody } from "../model/starter-query.js";
23
- /** Where the browser goes to pay: replaced in a spec. */ export const starterPurchaseNavigation = {
24
- assign: (url)=>window.location.assign(url)
25
- };
17
+ import { buildRoute, Route } from "@aglyn/aglyn/app-utils/console-routes";
18
+ import { useCallback, useState } from "react";
19
+ import { useMarketplacePay } from "./use-marketplace-pay.js";
26
20
  /**
27
- * "Buy and continue" for a priced starter in Create site (AGL-4049): opens
28
- * the marketplace's payment for it, licensed to the workspace the site is
29
- * for, and names Create site as the way back, so the person returns to the
30
- * same pick with the site still to be created. Today's payment page, until
31
- * the marketplace pays in-app.
32
- *
33
- * One attempt per starter: the same key goes with a second click, so a
34
- * double click cannot open a second payment (AGL-1697). A workspace that
35
- * already owns it is told so, not charged again.
36
- */ export function useStarterPurchase(orgId) {
37
- const { data: user } = useUser();
38
- const userRef = useRef(user);
39
- userRef.current = user;
40
- const attempts = useRef(new Map());
41
- const [busy, setBusy] = useState(false);
21
+ * "Buy and continue" for a priced starter in Create site (AGL-4049): pays in
22
+ * the console, licensed to the workspace the site is for, so the person stays
23
+ * on the same pick with the site still to be created. The purchase is on
24
+ * record when it answers, so Create is ready on the next click.
25
+ */ export function useStarterPurchase(orgId, orgSlug) {
26
+ const pay = useMarketplacePay({
27
+ orgId,
28
+ billingHref: orgSlug ? buildRoute(Route.MANAGE_BILLING, {
29
+ orgSlug
30
+ }) : null
31
+ });
42
32
  const [error, setError] = useState(null);
43
- const buy = useCallback(async (listingId)=>{
44
- var _attempts_current_get;
45
- if (!orgId || !listingId) return 'failed';
46
- const key = (_attempts_current_get = attempts.current.get(listingId)) != null ? _attempts_current_get : `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
47
- attempts.current.set(listingId, key);
48
- setBusy(true);
33
+ const buy = useCallback(async (listing)=>{
49
34
  setError(null);
50
- // Busy until the page leaves for the payment, so a second click cannot
51
- // land in between.
52
- let opening = false;
53
- try {
54
- const response = await authorizedFetch(userRef.current, STARTER_CHECKOUT_PATH, {
55
- method: 'POST',
56
- headers: {
57
- 'Content-Type': 'application/json',
58
- 'Idempotency-Key': key
59
- },
60
- body: JSON.stringify(starterCheckoutBody({
61
- listingId,
62
- orgId,
63
- gaClientId: await readGaClientId(process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID)
64
- }))
65
- });
66
- const payload = await response.json().catch(()=>null);
67
- if (response.status === 409 && (payload == null ? void 0 : payload.code) === 'already_purchased') return 'owned';
68
- const locked = parseLockdownRefusal(response.status, payload);
69
- if (locked) {
70
- setError(lockdownRefusalText(locked));
71
- return 'failed';
72
- }
73
- if (response.status === 501) {
74
- setError('Purchases are not set up here yet, so a starter with a price cannot be bought.');
75
- return 'failed';
76
- }
77
- if (!response.ok || typeof (payload == null ? void 0 : payload.url) !== 'string' || !payload.url) {
78
- setError(typeof (payload == null ? void 0 : payload.error) === 'string' && payload.error ? payload.error : 'The payment could not open. Try again.');
79
- return 'failed';
80
- }
81
- opening = true;
82
- starterPurchaseNavigation.assign(payload.url);
83
- return 'opening';
84
- } catch (caught) {
85
- console.error(caught);
86
- setError('The payment could not open. Check your connection and try again.');
87
- return 'failed';
88
- } finally{
89
- if (!opening) setBusy(false);
35
+ const result = await pay.buy(listing);
36
+ if (result.outcome === 'paid' || result.outcome === 'owned') return 'owned';
37
+ if (result.outcome === 'pending') {
38
+ setError('Your payment is going through. You can create this site as soon as it clears.');
39
+ return 'pending';
90
40
  }
41
+ setError(result.error);
42
+ return 'stopped';
91
43
  }, [
92
- orgId
44
+ pay.buy
93
45
  ]);
94
46
  return {
95
47
  buy,
96
- busy,
97
- error
48
+ busy: pay.busy,
49
+ error,
50
+ panel: pay.panel
98
51
  };
99
52
  }
100
53
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/marketplace/src/lib/hooks/use-starter-purchase.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { lockdownRefusalText, parseLockdownRefusal } from '@aglyn/aglyn/app-utils/lockdown'\nimport { readGaClientId } from '@aglyn/aglyn/app-utils/analytics-events'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport { useCallback, useRef, useState } from 'react'\nimport { STARTER_CHECKOUT_PATH, starterCheckoutBody } from '../model/starter-query'\n\n/** How one \"Buy and continue\" ended. */\nexport type StarterPurchaseOutcome =\n /** The payment page is opening: the person comes back to Create site on the same pick. */\n | 'opening'\n /** The workspace owns it already: nothing to pay, the site can be created. */\n | 'owned'\n /** It could not open; {@link StarterPurchase.error} says why. */\n | 'failed'\n\nexport interface StarterPurchase {\n buy: (listingId: string) => Promise<StarterPurchaseOutcome>\n /** A purchase is opening. */\n busy: boolean\n /** Why the last one did not open, or `null`. */\n error: string | null\n}\n\n/** Where the browser goes to pay: replaced in a spec. */\nexport const starterPurchaseNavigation = {\n assign: (url: string) => window.location.assign(url),\n}\n\n/**\n * \"Buy and continue\" for a priced starter in Create site (AGL-4049): opens\n * the marketplace's payment for it, licensed to the workspace the site is\n * for, and names Create site as the way back, so the person returns to the\n * same pick with the site still to be created. Today's payment page, until\n * the marketplace pays in-app.\n *\n * One attempt per starter: the same key goes with a second click, so a\n * double click cannot open a second payment (AGL-1697). A workspace that\n * already owns it is told so, not charged again.\n */\nexport function useStarterPurchase(orgId: string | undefined): StarterPurchase {\n const { data: user } = useUser()\n const userRef = useRef(user)\n userRef.current = user\n const attempts = useRef(new Map<string, string>())\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const buy = useCallback(\n async (listingId: string): Promise<StarterPurchaseOutcome> => {\n if (!orgId || !listingId) return 'failed'\n const key =\n attempts.current.get(listingId) ??\n `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`\n attempts.current.set(listingId, key)\n setBusy(true)\n setError(null)\n // Busy until the page leaves for the payment, so a second click cannot\n // land in between.\n let opening = false\n try {\n const response = await authorizedFetch(userRef.current, STARTER_CHECKOUT_PATH, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'Idempotency-Key': key },\n body: JSON.stringify(\n starterCheckoutBody({\n listingId,\n orgId,\n gaClientId: await readGaClientId(process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID),\n }),\n ),\n })\n const payload = (await response.json().catch((): null => null)) as\n | { url?: unknown; error?: unknown; code?: unknown }\n | null\n if (response.status === 409 && payload?.code === 'already_purchased') return 'owned'\n const locked = parseLockdownRefusal(response.status, payload)\n if (locked) {\n setError(lockdownRefusalText(locked))\n return 'failed'\n }\n if (response.status === 501) {\n setError('Purchases are not set up here yet, so a starter with a price cannot be bought.')\n return 'failed'\n }\n if (!response.ok || typeof payload?.url !== 'string' || !payload.url) {\n setError(typeof payload?.error === 'string' && payload.error ? payload.error : 'The payment could not open. Try again.')\n return 'failed'\n }\n opening = true\n starterPurchaseNavigation.assign(payload.url)\n return 'opening'\n } catch (caught) {\n console.error(caught)\n setError('The payment could not open. Check your connection and try again.')\n return 'failed'\n } finally {\n if (!opening) setBusy(false)\n }\n },\n [orgId],\n )\n\n return { buy, busy, error }\n}\n"],"names":["lockdownRefusalText","parseLockdownRefusal","readGaClientId","authorizedFetch","useUser","useCallback","useRef","useState","STARTER_CHECKOUT_PATH","starterCheckoutBody","starterPurchaseNavigation","assign","url","window","location","useStarterPurchase","orgId","data","user","userRef","current","attempts","Map","busy","setBusy","error","setError","buy","listingId","key","get","Date","now","toString","Math","random","slice","set","opening","response","method","headers","body","JSON","stringify","gaClientId","process","env","NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID","payload","json","catch","status","code","locked","ok","caught","console"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;AAEA,SAASA,mBAAmB,EAAEC,oBAAoB,QAAQ,kCAAiC;AAC3F,SAASC,cAAc,QAAQ,0CAAyC;AACxE,SAASC,eAAe,QAAQ,2CAA0C;AAC1E,SAASC,OAAO,QAAQ,iCAAgC;AACxD,SAASC,WAAW,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAO;AACrD,SAASC,qBAAqB,EAAEC,mBAAmB,QAAQ,4BAAwB;AAmBnF,uDAAuD,GACvD,OAAO,MAAMC,4BAA4B;IACvCC,QAAQ,CAACC,MAAgBC,OAAOC,QAAQ,CAACH,MAAM,CAACC;AAClD,EAAC;AAED;;;;;;;;;;CAUC,GACD,OAAO,SAASG,mBAAmBC,KAAyB;IAC1D,MAAM,EAAEC,MAAMC,IAAI,EAAE,GAAGd;IACvB,MAAMe,UAAUb,OAAOY;IACvBC,QAAQC,OAAO,GAAGF;IAClB,MAAMG,WAAWf,OAAO,IAAIgB;IAC5B,MAAM,CAACC,MAAMC,QAAQ,GAAGjB,SAAS;IACjC,MAAM,CAACkB,OAAOC,SAAS,GAAGnB,SAAwB;IAElD,MAAMoB,MAAMtB,YACV,OAAOuB;YAGHP;QAFF,IAAI,CAACL,SAAS,CAACY,WAAW,OAAO;QACjC,MAAMC,OACJR,wBAAAA,SAASD,OAAO,CAACU,GAAG,CAACF,sBAArBP,wBACA,GAAGU,KAAKC,GAAG,GAAGC,QAAQ,CAAC,IAAI,CAAC,EAAEC,KAAKC,MAAM,GAAGF,QAAQ,CAAC,IAAIG,KAAK,CAAC,GAAG,KAAK;QACzEf,SAASD,OAAO,CAACiB,GAAG,CAACT,WAAWC;QAChCL,QAAQ;QACRE,SAAS;QACT,uEAAuE;QACvE,mBAAmB;QACnB,IAAIY,UAAU;QACd,IAAI;YACF,MAAMC,WAAW,MAAMpC,gBAAgBgB,QAAQC,OAAO,EAAEZ,uBAAuB;gBAC7EgC,QAAQ;gBACRC,SAAS;oBAAE,gBAAgB;oBAAoB,mBAAmBZ;gBAAI;gBACtEa,MAAMC,KAAKC,SAAS,CAClBnC,oBAAoB;oBAClBmB;oBACAZ;oBACA6B,YAAY,MAAM3C,eAAe4C,QAAQC,GAAG,CAACC,mCAAmC;gBAClF;YAEJ;YACA,MAAMC,UAAW,MAAMV,SAASW,IAAI,GAAGC,KAAK,CAAC,IAAY;YAGzD,IAAIZ,SAASa,MAAM,KAAK,OAAOH,CAAAA,2BAAAA,QAASI,IAAI,MAAK,qBAAqB,OAAO;YAC7E,MAAMC,SAASrD,qBAAqBsC,SAASa,MAAM,EAAEH;YACrD,IAAIK,QAAQ;gBACV5B,SAAS1B,oBAAoBsD;gBAC7B,OAAO;YACT;YACA,IAAIf,SAASa,MAAM,KAAK,KAAK;gBAC3B1B,SAAS;gBACT,OAAO;YACT;YACA,IAAI,CAACa,SAASgB,EAAE,IAAI,QAAON,2BAAAA,QAASrC,GAAG,MAAK,YAAY,CAACqC,QAAQrC,GAAG,EAAE;gBACpEc,SAAS,QAAOuB,2BAAAA,QAASxB,KAAK,MAAK,YAAYwB,QAAQxB,KAAK,GAAGwB,QAAQxB,KAAK,GAAG;gBAC/E,OAAO;YACT;YACAa,UAAU;YACV5B,0BAA0BC,MAAM,CAACsC,QAAQrC,GAAG;YAC5C,OAAO;QACT,EAAE,OAAO4C,QAAQ;YACfC,QAAQhC,KAAK,CAAC+B;YACd9B,SAAS;YACT,OAAO;QACT,SAAU;YACR,IAAI,CAACY,SAASd,QAAQ;QACxB;IACF,GACA;QAACR;KAAM;IAGT,OAAO;QAAEW;QAAKJ;QAAME;IAAM;AAC5B"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/marketplace/src/lib/hooks/use-starter-purchase.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { buildRoute, Route } from '@aglyn/aglyn/app-utils/console-routes'\nimport { useCallback, useState, type ReactNode } from 'react'\nimport { useMarketplacePay, type PayListing } from './use-marketplace-pay'\n\n/** How one \"Buy and continue\" ended. */\nexport type StarterPurchaseOutcome =\n /** Paid just now, or owned already: the site can be created. */\n | 'owned'\n /** Paid and still clearing: the site can be created once it has. */\n | 'pending'\n /** Closed, or it could not open; {@link StarterPurchase.error} says why. */\n | 'stopped'\n\nexport interface StarterPurchase {\n buy: (listing: PayListing) => Promise<StarterPurchaseOutcome>\n /** A purchase is opening or paying. */\n busy: boolean\n /** Why the last one did not open, or `null`. */\n error: string | null\n /** The payment, in place under the pick, or `null`. */\n panel: ReactNode\n}\n\n/**\n * \"Buy and continue\" for a priced starter in Create site (AGL-4049): pays in\n * the console, licensed to the workspace the site is for, so the person stays\n * on the same pick with the site still to be created. The purchase is on\n * record when it answers, so Create is ready on the next click.\n */\nexport function useStarterPurchase(orgId: string | undefined, orgSlug: string): StarterPurchase {\n const pay = useMarketplacePay({\n orgId,\n billingHref: orgSlug ? buildRoute(Route.MANAGE_BILLING, { orgSlug }) : null,\n })\n const [error, setError] = useState<string | null>(null)\n\n const buy = useCallback(\n async (listing: PayListing): Promise<StarterPurchaseOutcome> => {\n setError(null)\n const result = await pay.buy(listing)\n if (result.outcome === 'paid' || result.outcome === 'owned') return 'owned'\n if (result.outcome === 'pending') {\n setError('Your payment is going through. You can create this site as soon as it clears.')\n return 'pending'\n }\n setError(result.error)\n return 'stopped'\n },\n [pay.buy],\n )\n\n return { buy, busy: pay.busy, error, panel: pay.panel }\n}\n"],"names":["buildRoute","Route","useCallback","useState","useMarketplacePay","useStarterPurchase","orgId","orgSlug","pay","billingHref","MANAGE_BILLING","error","setError","buy","listing","result","outcome","busy","panel"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;AAEA,SAASA,UAAU,EAAEC,KAAK,QAAQ,wCAAuC;AACzE,SAASC,WAAW,EAAEC,QAAQ,QAAwB,QAAO;AAC7D,SAASC,iBAAiB,QAAyB,2BAAuB;AAqB1E;;;;;CAKC,GACD,OAAO,SAASC,mBAAmBC,KAAyB,EAAEC,OAAe;IAC3E,MAAMC,MAAMJ,kBAAkB;QAC5BE;QACAG,aAAaF,UAAUP,WAAWC,MAAMS,cAAc,EAAE;YAAEH;QAAQ,KAAK;IACzE;IACA,MAAM,CAACI,OAAOC,SAAS,GAAGT,SAAwB;IAElD,MAAMU,MAAMX,YACV,OAAOY;QACLF,SAAS;QACT,MAAMG,SAAS,MAAMP,IAAIK,GAAG,CAACC;QAC7B,IAAIC,OAAOC,OAAO,KAAK,UAAUD,OAAOC,OAAO,KAAK,SAAS,OAAO;QACpE,IAAID,OAAOC,OAAO,KAAK,WAAW;YAChCJ,SAAS;YACT,OAAO;QACT;QACAA,SAASG,OAAOJ,KAAK;QACrB,OAAO;IACT,GACA;QAACH,IAAIK,GAAG;KAAC;IAGX,OAAO;QAAEA;QAAKI,MAAMT,IAAIS,IAAI;QAAEN;QAAOO,OAAOV,IAAIU,KAAK;IAAC;AACxD"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /** The discriminator every Stripe object of a marketplace sale carries. */
18
+ export declare const MARKETPLACE_PURCHASE_TYPE = "marketplace-purchase";
19
+ /** The facts a marketplace sale carries across Stripe, as the webhook reads them. */
20
+ export interface MarketplaceSaleFacts {
21
+ listingId: string;
22
+ buyerUid: string;
23
+ buyerOrgId: string;
24
+ sellerOrgId: string;
25
+ feeCents: number;
26
+ transferCents: number;
27
+ /** The buyer's GA client id, so the server's `purchase` joins their session. */
28
+ gaClientId?: string | null;
29
+ }
30
+ /**
31
+ * A sale's metadata as Stripe form params (AGL-4049): the same fields a
32
+ * hosted checkout session carries, so the purchase record cannot tell the two
33
+ * doors apart, plus the marker that keeps the sale out of the platform's own
34
+ * revenue.
35
+ */
36
+ export declare function marketplaceSaleMetadataParams(facts: MarketplaceSaleFacts): Record<string, string>;
37
+ /** Whether a Stripe invoice is a marketplace sale's. */
38
+ export declare function isMarketplaceInvoice(invoice: unknown): boolean;
39
+ /**
40
+ * The tax on an invoice, in cents.
41
+ *
42
+ * The breakdown first, the scalar only when no array said anything: measured
43
+ * on the live account, a computed invoice can send `tax: 0` or `tax: null`
44
+ * beside a populated `total_taxes[]` (AGL-1811).
45
+ */
46
+ export declare function invoiceTaxCents(invoice: any): number;
47
+ /**
48
+ * The PaymentIntent an invoice settles through, whichever generation of the
49
+ * field it carries: an id or an expanded object at the top level, or under
50
+ * `payments[]` on newer API versions.
51
+ */
52
+ export declare function invoicePaymentIntentId(invoice: any): string;
@@ -0,0 +1,75 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ /**
3
+ * @license
4
+ * Copyright 2026 Aglyn LLC
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */ import { PLUGIN_SALE_METADATA_KEY, PLUGIN_SALE_METADATA_VALUE } from "@aglyn/aglyn/app-utils/plugin-sale";
18
+ /** The discriminator every Stripe object of a marketplace sale carries. */ export const MARKETPLACE_PURCHASE_TYPE = 'marketplace-purchase';
19
+ /**
20
+ * A sale's metadata as Stripe form params (AGL-4049): the same fields a
21
+ * hosted checkout session carries, so the purchase record cannot tell the two
22
+ * doors apart, plus the marker that keeps the sale out of the platform's own
23
+ * revenue.
24
+ */ export function marketplaceSaleMetadataParams(facts) {
25
+ return _extends({
26
+ 'metadata[type]': MARKETPLACE_PURCHASE_TYPE,
27
+ [`metadata[${PLUGIN_SALE_METADATA_KEY}]`]: PLUGIN_SALE_METADATA_VALUE,
28
+ 'metadata[listingId]': facts.listingId,
29
+ 'metadata[buyerUid]': facts.buyerUid,
30
+ 'metadata[buyerOrgId]': facts.buyerOrgId,
31
+ 'metadata[sellerOrgId]': facts.sellerOrgId,
32
+ 'metadata[feeCents]': String(facts.feeCents),
33
+ 'metadata[transferCents]': String(facts.transferCents)
34
+ }, facts.gaClientId && /^\d+\.\d+$/.test(facts.gaClientId) ? {
35
+ 'metadata[ga_client_id]': facts.gaClientId
36
+ } : {});
37
+ }
38
+ /** Whether a Stripe invoice is a marketplace sale's. */ export function isMarketplaceInvoice(invoice) {
39
+ var _invoice_metadata;
40
+ return (invoice == null ? void 0 : (_invoice_metadata = invoice.metadata) == null ? void 0 : _invoice_metadata.type) === MARKETPLACE_PURCHASE_TYPE;
41
+ }
42
+ /**
43
+ * The tax on an invoice, in cents.
44
+ *
45
+ * The breakdown first, the scalar only when no array said anything: measured
46
+ * on the live account, a computed invoice can send `tax: 0` or `tax: null`
47
+ * beside a populated `total_taxes[]` (AGL-1811).
48
+ */ export function invoiceTaxCents(invoice) {
49
+ var _ref;
50
+ const entries = Array.isArray(invoice == null ? void 0 : invoice.total_taxes) ? invoice.total_taxes : Array.isArray(invoice == null ? void 0 : invoice.total_tax_amounts) ? invoice.total_tax_amounts : [];
51
+ if (entries.length > 0) {
52
+ return entries.reduce((sum, entry)=>{
53
+ var _ref;
54
+ const amount = Number((_ref = entry == null ? void 0 : entry.amount) != null ? _ref : 0);
55
+ return sum + (Number.isFinite(amount) ? Math.round(amount) : 0);
56
+ }, 0);
57
+ }
58
+ const scalar = Number((_ref = invoice == null ? void 0 : invoice.tax) != null ? _ref : NaN);
59
+ return Number.isFinite(scalar) && scalar > 0 ? Math.round(scalar) : 0;
60
+ }
61
+ /**
62
+ * The PaymentIntent an invoice settles through, whichever generation of the
63
+ * field it carries: an id or an expanded object at the top level, or under
64
+ * `payments[]` on newer API versions.
65
+ */ export function invoicePaymentIntentId(invoice) {
66
+ var _invoice_payments_data__payment, _invoice_payments_data_, _invoice_payments_data, _invoice_payments;
67
+ const intent = invoice == null ? void 0 : invoice.payment_intent;
68
+ if (typeof intent === 'string' && intent) return intent;
69
+ if (typeof (intent == null ? void 0 : intent.id) === 'string' && intent.id) return intent.id;
70
+ const nested = invoice == null ? void 0 : (_invoice_payments = invoice.payments) == null ? void 0 : (_invoice_payments_data = _invoice_payments.data) == null ? void 0 : (_invoice_payments_data_ = _invoice_payments_data[0]) == null ? void 0 : (_invoice_payments_data__payment = _invoice_payments_data_.payment) == null ? void 0 : _invoice_payments_data__payment.payment_intent;
71
+ if (typeof nested === 'string' && nested) return nested;
72
+ return typeof (nested == null ? void 0 : nested.id) === 'string' ? nested.id : '';
73
+ }
74
+
75
+ //# sourceMappingURL=marketplace-invoice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/marketplace/src/lib/model/marketplace-invoice.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n PLUGIN_SALE_METADATA_KEY,\n PLUGIN_SALE_METADATA_VALUE,\n} from '@aglyn/aglyn/app-utils/plugin-sale'\n\n/** The discriminator every Stripe object of a marketplace sale carries. */\nexport const MARKETPLACE_PURCHASE_TYPE = 'marketplace-purchase'\n\n/** The facts a marketplace sale carries across Stripe, as the webhook reads them. */\nexport interface MarketplaceSaleFacts {\n listingId: string\n buyerUid: string\n buyerOrgId: string\n sellerOrgId: string\n feeCents: number\n transferCents: number\n /** The buyer's GA client id, so the server's `purchase` joins their session. */\n gaClientId?: string | null\n}\n\n/**\n * A sale's metadata as Stripe form params (AGL-4049): the same fields a\n * hosted checkout session carries, so the purchase record cannot tell the two\n * doors apart, plus the marker that keeps the sale out of the platform's own\n * revenue.\n */\nexport function marketplaceSaleMetadataParams(facts: MarketplaceSaleFacts): Record<string, string> {\n return {\n 'metadata[type]': MARKETPLACE_PURCHASE_TYPE,\n [`metadata[${PLUGIN_SALE_METADATA_KEY}]`]: PLUGIN_SALE_METADATA_VALUE,\n 'metadata[listingId]': facts.listingId,\n 'metadata[buyerUid]': facts.buyerUid,\n 'metadata[buyerOrgId]': facts.buyerOrgId,\n 'metadata[sellerOrgId]': facts.sellerOrgId,\n 'metadata[feeCents]': String(facts.feeCents),\n 'metadata[transferCents]': String(facts.transferCents),\n ...(facts.gaClientId && /^\\d+\\.\\d+$/.test(facts.gaClientId)\n ? { 'metadata[ga_client_id]': facts.gaClientId }\n : {}),\n }\n}\n\n/** Whether a Stripe invoice is a marketplace sale's. */\nexport function isMarketplaceInvoice(invoice: unknown): boolean {\n return (invoice as { metadata?: { type?: unknown } } | null | undefined)?.metadata?.type ===\n MARKETPLACE_PURCHASE_TYPE\n}\n\n/**\n * The tax on an invoice, in cents.\n *\n * The breakdown first, the scalar only when no array said anything: measured\n * on the live account, a computed invoice can send `tax: 0` or `tax: null`\n * beside a populated `total_taxes[]` (AGL-1811).\n */\nexport function invoiceTaxCents(invoice: any): number {\n const entries: any[] = Array.isArray(invoice?.total_taxes)\n ? invoice.total_taxes\n : Array.isArray(invoice?.total_tax_amounts)\n ? invoice.total_tax_amounts\n : []\n if (entries.length > 0) {\n return entries.reduce((sum: number, entry: any) => {\n const amount = Number(entry?.amount ?? 0)\n return sum + (Number.isFinite(amount) ? Math.round(amount) : 0)\n }, 0)\n }\n const scalar = Number(invoice?.tax ?? NaN)\n return Number.isFinite(scalar) && scalar > 0 ? Math.round(scalar) : 0\n}\n\n/**\n * The PaymentIntent an invoice settles through, whichever generation of the\n * field it carries: an id or an expanded object at the top level, or under\n * `payments[]` on newer API versions.\n */\nexport function invoicePaymentIntentId(invoice: any): string {\n const intent = invoice?.payment_intent\n if (typeof intent === 'string' && intent) return intent\n if (typeof intent?.id === 'string' && intent.id) return intent.id\n const nested = invoice?.payments?.data?.[0]?.payment?.payment_intent\n if (typeof nested === 'string' && nested) return nested\n return typeof nested?.id === 'string' ? nested.id : ''\n}\n"],"names":["PLUGIN_SALE_METADATA_KEY","PLUGIN_SALE_METADATA_VALUE","MARKETPLACE_PURCHASE_TYPE","marketplaceSaleMetadataParams","facts","listingId","buyerUid","buyerOrgId","sellerOrgId","String","feeCents","transferCents","gaClientId","test","isMarketplaceInvoice","invoice","metadata","type","invoiceTaxCents","entries","Array","isArray","total_taxes","total_tax_amounts","length","reduce","sum","entry","amount","Number","isFinite","Math","round","scalar","tax","NaN","invoicePaymentIntentId","intent","payment_intent","id","nested","payments","data","payment"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,wBAAwB,EACxBC,0BAA0B,QACrB,qCAAoC;AAE3C,yEAAyE,GACzE,OAAO,MAAMC,4BAA4B,uBAAsB;AAc/D;;;;;CAKC,GACD,OAAO,SAASC,8BAA8BC,KAA2B;IACvE,OAAO;QACL,kBAAkBF;QAClB,CAAC,CAAC,SAAS,EAAEF,yBAAyB,CAAC,CAAC,CAAC,EAAEC;QAC3C,uBAAuBG,MAAMC,SAAS;QACtC,sBAAsBD,MAAME,QAAQ;QACpC,wBAAwBF,MAAMG,UAAU;QACxC,yBAAyBH,MAAMI,WAAW;QAC1C,sBAAsBC,OAAOL,MAAMM,QAAQ;QAC3C,2BAA2BD,OAAOL,MAAMO,aAAa;OACjDP,MAAMQ,UAAU,IAAI,aAAaC,IAAI,CAACT,MAAMQ,UAAU,IACtD;QAAE,0BAA0BR,MAAMQ,UAAU;IAAC,IAC7C,CAAC;AAET;AAEA,sDAAsD,GACtD,OAAO,SAASE,qBAAqBC,OAAgB;QAC5C;IAAP,OAAO,CAACA,4BAAD,oBAAA,AAACA,QAAkEC,QAAQ,qBAA3E,kBAA6EC,IAAI,MACtFf;AACJ;AAEA;;;;;;CAMC,GACD,OAAO,SAASgB,gBAAgBH,OAAY;;IAC1C,MAAMI,UAAiBC,MAAMC,OAAO,CAACN,2BAAAA,QAASO,WAAW,IACrDP,QAAQO,WAAW,GACnBF,MAAMC,OAAO,CAACN,2BAAAA,QAASQ,iBAAiB,IACtCR,QAAQQ,iBAAiB,GACzB,EAAE;IACR,IAAIJ,QAAQK,MAAM,GAAG,GAAG;QACtB,OAAOL,QAAQM,MAAM,CAAC,CAACC,KAAaC;;YAClC,MAAMC,SAASC,eAAOF,yBAAAA,MAAOC,MAAM,mBAAI;YACvC,OAAOF,MAAOG,CAAAA,OAAOC,QAAQ,CAACF,UAAUG,KAAKC,KAAK,CAACJ,UAAU,CAAA;QAC/D,GAAG;IACL;IACA,MAAMK,SAASJ,eAAOd,2BAAAA,QAASmB,GAAG,mBAAIC;IACtC,OAAON,OAAOC,QAAQ,CAACG,WAAWA,SAAS,IAAIF,KAAKC,KAAK,CAACC,UAAU;AACtE;AAEA;;;;CAIC,GACD,OAAO,SAASG,uBAAuBrB,OAAY;QAIlCA,iCAAAA,yBAAAA,wBAAAA;IAHf,MAAMsB,SAAStB,2BAAAA,QAASuB,cAAc;IACtC,IAAI,OAAOD,WAAW,YAAYA,QAAQ,OAAOA;IACjD,IAAI,QAAOA,0BAAAA,OAAQE,EAAE,MAAK,YAAYF,OAAOE,EAAE,EAAE,OAAOF,OAAOE,EAAE;IACjE,MAAMC,SAASzB,4BAAAA,oBAAAA,QAAS0B,QAAQ,sBAAjB1B,yBAAAA,kBAAmB2B,IAAI,sBAAvB3B,0BAAAA,sBAAyB,CAAC,EAAE,sBAA5BA,kCAAAA,wBAA8B4B,OAAO,qBAArC5B,gCAAuCuB,cAAc;IACpE,IAAI,OAAOE,WAAW,YAAYA,QAAQ,OAAOA;IACjD,OAAO,QAAOA,0BAAAA,OAAQD,EAAE,MAAK,WAAWC,OAAOD,EAAE,GAAG;AACtD"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /** The card a quote names, as far as this person may see it. */
18
+ export interface PayQuoteCard {
19
+ type?: string | null;
20
+ brand?: string | null;
21
+ last4?: string | null;
22
+ email?: string | null;
23
+ }
24
+ /** What the pay door answers a `quote` with: what will be charged, before it is. */
25
+ export interface PayQuote {
26
+ listingName: string;
27
+ amountCents: number;
28
+ taxCents: number;
29
+ totalCents: number;
30
+ /** `null` for someone who may buy but may not see billing. */
31
+ card: PayQuoteCard | null;
32
+ /** Whether this person holds `billing.manage`, which paying takes. */
33
+ canPay: boolean;
34
+ }
35
+ /** The two things a workspace needs before it can be charged. */
36
+ export type PayPrerequisite = 'card_required' | 'billing_address_required';
37
+ /** Reads the prerequisite a refusal names, or `null` when it names none. */
38
+ export declare function payPrerequisiteOf(status: number, payload: unknown): PayPrerequisite | null;
39
+ /** Dollars and cents, for a line a buyer is about to agree to. */
40
+ export declare function formatPayCents(cents: number): string;
41
+ /** The saved method in words, wallets included: they carry an email, not a number. */
42
+ export declare function payCardLabel(card: PayQuoteCard | null): string;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ /** The card a quote names, as far as this person may see it. */ /** Reads the prerequisite a refusal names, or `null` when it names none. */ export function payPrerequisiteOf(status, payload) {
17
+ const code = payload == null ? void 0 : payload.code;
18
+ return status === 412 && (code === 'card_required' || code === 'billing_address_required') ? code : null;
19
+ }
20
+ /** Dollars and cents, for a line a buyer is about to agree to. */ export function formatPayCents(cents) {
21
+ return new Intl.NumberFormat('en-US', {
22
+ style: 'currency',
23
+ currency: 'USD'
24
+ }).format(cents / 100);
25
+ }
26
+ /** The saved method in words, wallets included: they carry an email, not a number. */ export function payCardLabel(card) {
27
+ var _ref, _card_brand, _card_type;
28
+ if (card == null ? void 0 : card.last4) return `${((_ref = (_card_brand = card.brand) != null ? _card_brand : card.type) != null ? _ref : 'card').toUpperCase()} •••• ${card.last4}`;
29
+ if (card == null ? void 0 : card.email) return `${(_card_type = card.type) != null ? _card_type : 'wallet'} · ${card.email}`;
30
+ return 'the card on file';
31
+ }
32
+
33
+ //# sourceMappingURL=marketplace-pay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/marketplace/src/lib/model/marketplace-pay.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/** The card a quote names, as far as this person may see it. */\nexport interface PayQuoteCard {\n type?: string | null\n brand?: string | null\n last4?: string | null\n email?: string | null\n}\n\n/** What the pay door answers a `quote` with: what will be charged, before it is. */\nexport interface PayQuote {\n listingName: string\n amountCents: number\n taxCents: number\n totalCents: number\n /** `null` for someone who may buy but may not see billing. */\n card: PayQuoteCard | null\n /** Whether this person holds `billing.manage`, which paying takes. */\n canPay: boolean\n}\n\n/** The two things a workspace needs before it can be charged. */\nexport type PayPrerequisite = 'card_required' | 'billing_address_required'\n\n/** Reads the prerequisite a refusal names, or `null` when it names none. */\nexport function payPrerequisiteOf(status: number, payload: unknown): PayPrerequisite | null {\n const code = (payload as { code?: unknown } | null | undefined)?.code\n return status === 412 && (code === 'card_required' || code === 'billing_address_required')\n ? code\n : null\n}\n\n/** Dollars and cents, for a line a buyer is about to agree to. */\nexport function formatPayCents(cents: number): string {\n return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(cents / 100)\n}\n\n/** The saved method in words, wallets included: they carry an email, not a number. */\nexport function payCardLabel(card: PayQuoteCard | null): string {\n if (card?.last4) return `${(card.brand ?? card.type ?? 'card').toUpperCase()} •••• ${card.last4}`\n if (card?.email) return `${card.type ?? 'wallet'} · ${card.email}`\n return 'the card on file'\n}\n"],"names":["payPrerequisiteOf","status","payload","code","formatPayCents","cents","Intl","NumberFormat","style","currency","format","payCardLabel","card","last4","brand","type","toUpperCase","email"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,8DAA8D,GAuB9D,0EAA0E,GAC1E,OAAO,SAASA,kBAAkBC,MAAc,EAAEC,OAAgB;IAChE,MAAMC,OAAQD,2BAAD,AAACA,QAAmDC,IAAI;IACrE,OAAOF,WAAW,OAAQE,CAAAA,SAAS,mBAAmBA,SAAS,0BAAyB,IACpFA,OACA;AACN;AAEA,gEAAgE,GAChE,OAAO,SAASC,eAAeC,KAAa;IAC1C,OAAO,IAAIC,KAAKC,YAAY,CAAC,SAAS;QAAEC,OAAO;QAAYC,UAAU;IAAM,GAAGC,MAAM,CAACL,QAAQ;AAC/F;AAEA,oFAAoF,GACpF,OAAO,SAASM,aAAaC,IAAyB;QACxBA,MAAAA,aACDA;IAD3B,IAAIA,wBAAAA,KAAMC,KAAK,EAAE,OAAO,GAAG,EAACD,QAAAA,cAAAA,KAAKE,KAAK,YAAVF,cAAcA,KAAKG,IAAI,YAAvBH,OAA2B,QAAQI,WAAW,GAAG,MAAM,EAAEJ,KAAKC,KAAK,EAAE;IACjG,IAAID,wBAAAA,KAAMK,KAAK,EAAE,OAAO,IAAGL,aAAAA,KAAKG,IAAI,YAATH,aAAa,SAAS,GAAG,EAAEA,KAAKK,KAAK,EAAE;IAClE,OAAO;AACT"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /**
18
+ * Whether a seller is the platform itself, selling at a waived fee (AGL-4049).
19
+ *
20
+ * The platform's own org sells through the marketplace the same way any
21
+ * publisher does, with one difference that is not a privilege: there is nobody
22
+ * to pay. Its money already lands on the platform's account, so a Connect
23
+ * transfer would be the platform paying itself, and it never onboards Connect.
24
+ *
25
+ * BOTH HALVES, ALWAYS. The waiver is the existing staff override
26
+ * (`marketplaceFeePct: 0`) and the org is a server-side marker
27
+ * (`AGLYN_PLATFORM_ORG_ID`, read in `server/platform-org.ts`). A waiver on any
28
+ * other seller still pays that seller, and the platform's org at a real rate
29
+ * still needs a payout account. No client-writable field decides this.
30
+ *
31
+ * Pure, so the sale, the publish gate and their specs all ask one question.
32
+ */
33
+ export declare function sellsAsPlatform(input: {
34
+ sellerOrgId: string;
35
+ feePercent: number;
36
+ platformOrgId: string | null | undefined;
37
+ }): boolean;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ /**
17
+ * Whether a seller is the platform itself, selling at a waived fee (AGL-4049).
18
+ *
19
+ * The platform's own org sells through the marketplace the same way any
20
+ * publisher does, with one difference that is not a privilege: there is nobody
21
+ * to pay. Its money already lands on the platform's account, so a Connect
22
+ * transfer would be the platform paying itself, and it never onboards Connect.
23
+ *
24
+ * BOTH HALVES, ALWAYS. The waiver is the existing staff override
25
+ * (`marketplaceFeePct: 0`) and the org is a server-side marker
26
+ * (`AGLYN_PLATFORM_ORG_ID`, read in `server/platform-org.ts`). A waiver on any
27
+ * other seller still pays that seller, and the platform's org at a real rate
28
+ * still needs a payout account. No client-writable field decides this.
29
+ *
30
+ * Pure, so the sale, the publish gate and their specs all ask one question.
31
+ */ export function sellsAsPlatform(input) {
32
+ const { sellerOrgId, feePercent, platformOrgId } = input;
33
+ return feePercent === 0 && !!platformOrgId && sellerOrgId === platformOrgId;
34
+ }
35
+
36
+ //# sourceMappingURL=platform-seller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/marketplace/src/lib/model/platform-seller.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Whether a seller is the platform itself, selling at a waived fee (AGL-4049).\n *\n * The platform's own org sells through the marketplace the same way any\n * publisher does, with one difference that is not a privilege: there is nobody\n * to pay. Its money already lands on the platform's account, so a Connect\n * transfer would be the platform paying itself, and it never onboards Connect.\n *\n * BOTH HALVES, ALWAYS. The waiver is the existing staff override\n * (`marketplaceFeePct: 0`) and the org is a server-side marker\n * (`AGLYN_PLATFORM_ORG_ID`, read in `server/platform-org.ts`). A waiver on any\n * other seller still pays that seller, and the platform's org at a real rate\n * still needs a payout account. No client-writable field decides this.\n *\n * Pure, so the sale, the publish gate and their specs all ask one question.\n */\nexport function sellsAsPlatform(input: {\n sellerOrgId: string\n feePercent: number\n platformOrgId: string | null | undefined\n}): boolean {\n const { sellerOrgId, feePercent, platformOrgId } = input\n return feePercent === 0 && !!platformOrgId && sellerOrgId === platformOrgId\n}\n"],"names":["sellsAsPlatform","input","sellerOrgId","feePercent","platformOrgId"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;CAeC,GACD,OAAO,SAASA,gBAAgBC,KAI/B;IACC,MAAM,EAAEC,WAAW,EAAEC,UAAU,EAAEC,aAAa,EAAE,GAAGH;IACnD,OAAOE,eAAe,KAAK,CAAC,CAACC,iBAAiBF,gBAAgBE;AAChE"}
@@ -106,8 +106,20 @@
106
106
  * merchant of record and determines, collects and remits transaction tax since
107
107
  * 2026-08-14. The Terms of Service moved TO them in this pass (new ToS §10.7),
108
108
  * not the other way around.
109
+ *
110
+ * ## 2026-11-02 — `2026-11-02.1`, site starters (AGL-4049)
111
+ *
112
+ * The opening names site starters among the Artifacts, and §1 is now "Site
113
+ * Starters": a site starter is an Artifact and everything in it is warranted
114
+ * under §3. That replaces §1's pre-release paragraph. Its "AS IS" wording stays
115
+ * in §10, and the right to change the Marketplace stays in Terms of Service
116
+ * §5.1. §2 to §14 keep their numbers, because the repo and the native screens
117
+ * cite them.
118
+ *
119
+ * The capture also carries §8.6's "license" spelling, which the page already
120
+ * served after the `2026-08-24.1` pin was taken.
109
121
  */
110
- export declare const PUBLISHER_AGREEMENT_VERSION = "2026-08-24.1";
122
+ export declare const PUBLISHER_AGREEMENT_VERSION = "2026-11-02.1";
111
123
  export declare const PUBLISHER_AGREEMENT_TITLE = "Marketplace Publisher Agreement";
112
124
  /**
113
125
  * The snapshot pin for the version above (AGL-1678).
@@ -144,9 +156,9 @@ export declare const PUBLISHER_AGREEMENT_TITLE = "Marketplace Publisher Agreemen
144
156
  * hand-write a snapshot: it is evidence of what a publisher was shown, and a
145
157
  * snapshot of unpublished text is a false record.
146
158
  */
147
- export declare const PUBLISHER_AGREEMENT_SHA256 = "2df6e940f037b4630e53c8f63bad8604ef4bf370374b89afcd4ea7f9fe8e8d63";
159
+ export declare const PUBLISHER_AGREEMENT_SHA256 = "3a345609a30e915be53dfeaf8e4a2c141e92a250e39cf741f8c8c0c9c764d23c";
148
160
  /** Byte length of the same snapshot — a cheap second check on the content. */
149
- export declare const PUBLISHER_AGREEMENT_BYTES = 13730;
161
+ export declare const PUBLISHER_AGREEMENT_BYTES = 13709;
150
162
  /**
151
163
  * Canonical document, on the operator's legal origin beside the other terms.
152
164
  *
@@ -129,7 +129,19 @@
129
129
  * merchant of record and determines, collects and remits transaction tax since
130
130
  * 2026-08-14. The Terms of Service moved TO them in this pass (new ToS §10.7),
131
131
  * not the other way around.
132
- */ export const PUBLISHER_AGREEMENT_VERSION = '2026-08-24.1';
132
+ *
133
+ * ## 2026-11-02 — `2026-11-02.1`, site starters (AGL-4049)
134
+ *
135
+ * The opening names site starters among the Artifacts, and §1 is now "Site
136
+ * Starters": a site starter is an Artifact and everything in it is warranted
137
+ * under §3. That replaces §1's pre-release paragraph. Its "AS IS" wording stays
138
+ * in §10, and the right to change the Marketplace stays in Terms of Service
139
+ * §5.1. §2 to §14 keep their numbers, because the repo and the native screens
140
+ * cite them.
141
+ *
142
+ * The capture also carries §8.6's "license" spelling, which the page already
143
+ * served after the `2026-08-24.1` pin was taken.
144
+ */ export const PUBLISHER_AGREEMENT_VERSION = '2026-11-02.1';
133
145
  export const PUBLISHER_AGREEMENT_TITLE = 'Marketplace Publisher Agreement';
134
146
  /**
135
147
  * The snapshot pin for the version above (AGL-1678).
@@ -165,8 +177,8 @@ export const PUBLISHER_AGREEMENT_TITLE = 'Marketplace Publisher Agreement';
165
177
  * the version's entry to `PUBLISHER_AGREEMENT_CHANGES` below. Never
166
178
  * hand-write a snapshot: it is evidence of what a publisher was shown, and a
167
179
  * snapshot of unpublished text is a false record.
168
- */ export const PUBLISHER_AGREEMENT_SHA256 = '2df6e940f037b4630e53c8f63bad8604ef4bf370374b89afcd4ea7f9fe8e8d63';
169
- /** Byte length of the same snapshot — a cheap second check on the content. */ export const PUBLISHER_AGREEMENT_BYTES = 13730;
180
+ */ export const PUBLISHER_AGREEMENT_SHA256 = '3a345609a30e915be53dfeaf8e4a2c141e92a250e39cf741f8c8c0c9c764d23c';
181
+ /** Byte length of the same snapshot — a cheap second check on the content. */ export const PUBLISHER_AGREEMENT_BYTES = 13709;
170
182
  /**
171
183
  * Canonical document, on the operator's legal origin beside the other terms.
172
184
  *
@@ -277,6 +289,14 @@ export const PUBLISHER_AGREEMENT_TITLE = 'Marketplace Publisher Agreement';
277
289
  changes: [
278
290
  '§13.3: venue moves to Travis County, Texas, and governing law now cites Terms of Service Section 18.6.'
279
291
  ]
292
+ },
293
+ {
294
+ version: '2026-11-02.1',
295
+ changes: [
296
+ 'Opening paragraph: site starters are among the Artifacts you can publish.',
297
+ '§1, new: a site starter is an Artifact. Its pages, shared layout, theme and, for an AI site starter, its answers are its content, and you warrant them under §3. §1 no longer describes the Marketplace as pre-release.',
298
+ '§8.6: a spelling correction, with no change in meaning.'
299
+ ]
280
300
  }
281
301
  ];
282
302
  /**