@aglyn/plugins-marketplace 1.0.0-beta.146 → 1.0.0-beta.149

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aglyn/plugins-marketplace",
3
- "version": "1.0.0-beta.146",
3
+ "version": "1.0.0-beta.149",
4
4
  "license": "Apache-2.0",
5
5
  "homepage": "https://aglyn.com",
6
6
  "repository": {
@@ -25,16 +25,16 @@
25
25
  "./package.json": "./package.json"
26
26
  },
27
27
  "dependencies": {
28
- "@aglyn/aglyn": "1.0.0-beta.146",
29
- "@aglyn/shared-data-mdi": "1.0.0-beta.146",
30
- "@aglyn/shared-ui-jsx": "1.0.0-beta.146",
31
- "@aglyn/shared-ui-next": "1.0.0-beta.146",
32
- "@aglyn/shared-ui-snackstack": "1.0.0-beta.146",
33
- "@aglyn/shared-util-email": "1.0.0-beta.146",
34
- "@aglyn/shared-util-http": "1.0.0-beta.146",
35
- "@aglyn/tenant-data-admin": "1.0.0-beta.146",
36
- "@aglyn/tenant-feature-instance": "1.0.0-beta.146",
37
- "@aglyn/tenant-runtime": "1.0.0-beta.146",
28
+ "@aglyn/aglyn": "1.0.0-beta.149",
29
+ "@aglyn/shared-data-mdi": "1.0.0-beta.149",
30
+ "@aglyn/shared-ui-jsx": "1.0.0-beta.149",
31
+ "@aglyn/shared-ui-next": "1.0.0-beta.149",
32
+ "@aglyn/shared-ui-snackstack": "1.0.0-beta.149",
33
+ "@aglyn/shared-util-email": "1.0.0-beta.149",
34
+ "@aglyn/shared-util-http": "1.0.0-beta.149",
35
+ "@aglyn/tenant-data-admin": "1.0.0-beta.149",
36
+ "@aglyn/tenant-feature-instance": "1.0.0-beta.149",
37
+ "@aglyn/tenant-runtime": "1.0.0-beta.149",
38
38
  "@swc/helpers": "0.5.23"
39
39
  },
40
40
  "peerDependencies": {
@@ -0,0 +1,21 @@
1
+ import type { ConsoleArtifactPublishZoneProps } from '@aglyn/aglyn';
2
+ /**
3
+ * Publish an artifact to the marketplace (AGL-672, moved out of the console
4
+ * app by AGL-3080).
5
+ *
6
+ * The publish form is identical across artifact types — name, description,
7
+ * category, price — and only the endpoint and identifying fields differ, so
8
+ * this takes both rather than being copied per type. Every gate that
9
+ * matters (plan, publisher profile, payouts, host role) lives on the server;
10
+ * this surfaces the server's message rather than trying to predict it.
11
+ *
12
+ * Drawn through the `hostArtifactPublish` zone, so the page that offers the
13
+ * publish keeps the control that opens it and never imports this. A page
14
+ * with no widget on that zone leaves the offer out entirely, which is why
15
+ * this may safely draw nothing for a kind it does not sell.
16
+ */
17
+ export declare function PublishArtifactDialog({ artifact, onClose, }: ConsoleArtifactPublishZoneProps): import("react").JSX.Element;
18
+ export declare namespace PublishArtifactDialog {
19
+ var displayName: string;
20
+ }
21
+ export default PublishArtifactDialog;
@@ -0,0 +1,327 @@
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
+ */ 'use client';
17
+ import { _ as _extends } from "@swc/helpers/_/_extends";
18
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
+ import { isBelowMarketplacePriceFloor, marketplacePriceCostNote, marketplacePriceFloorHint } from "@aglyn/aglyn";
20
+ import { useSnackbar } from "@aglyn/shared-ui-snackstack";
21
+ import { useUser } from "@aglyn/tenant-feature-instance";
22
+ import { authorizedFetch } from "@aglyn/shared-util-http/authorized-token";
23
+ import { Button, Dialog, DialogActions, DialogContent, DialogTitle, Stack, TextField, Typography } from "@mui/material";
24
+ import { useCallback, useEffect, useMemo, useState } from "react";
25
+ /**
26
+ * WHERE EACH KIND GOES, which is the knowledge that used to sit in the app
27
+ * (AGL-3080).
28
+ *
29
+ * A console page hands over what it has — a kind, the scope holding it, the
30
+ * document — and this is the only place that turns it into a request. The
31
+ * pages that offer publishing named the endpoint, the payload key and the
32
+ * noun themselves, which made them files that could not compile without a
33
+ * marketplace and could not be right without being kept in step with one.
34
+ *
35
+ * ⚠️ A KIND THIS DOES NOT KNOW IS SAID OUT LOUD, not drawn as nothing. It
36
+ * means a console offering to publish something this marketplace does not
37
+ * sell — the two lists have gone out of step — and the person has already
38
+ * clicked. Drawing nothing would make the control look broken with no way to
39
+ * tell what happened, and guessing an endpoint from the kind would post to a
40
+ * route that does not exist and report the 404 to the publisher.
41
+ *
42
+ * The control itself is a separate matter: a page only offers the publish
43
+ * when this zone has a widget at all, so a workspace with no marketplace
44
+ * never gets here.
45
+ */ function publishRequestFor(artifact) {
46
+ var _artifact_hostId, _artifact_orgId, _artifact_artifactId;
47
+ const hostId = (_artifact_hostId = artifact.hostId) != null ? _artifact_hostId : '';
48
+ const orgId = (_artifact_orgId = artifact.orgId) != null ? _artifact_orgId : '';
49
+ const artifactId = (_artifact_artifactId = artifact.artifactId) != null ? _artifact_artifactId : '';
50
+ switch(artifact.kind){
51
+ case 'layout':
52
+ return {
53
+ endpoint: 'marketplace/publish-layout',
54
+ payload: {
55
+ hostId,
56
+ layoutId: artifactId
57
+ },
58
+ noun: 'layout',
59
+ categoryPlaceholder: 'e.g. Marketing, Docs, Storefront'
60
+ };
61
+ case 'component':
62
+ return {
63
+ endpoint: 'marketplace/publish',
64
+ payload: {
65
+ hostId,
66
+ componentId: artifactId
67
+ },
68
+ noun: 'component'
69
+ };
70
+ case 'site':
71
+ return {
72
+ endpoint: 'marketplace/publish-template',
73
+ payload: {
74
+ hostId
75
+ },
76
+ noun: 'site template'
77
+ };
78
+ case 'theme':
79
+ return {
80
+ endpoint: 'marketplace/publish-theme',
81
+ payload: {
82
+ hostId
83
+ },
84
+ noun: 'theme'
85
+ };
86
+ // Datasets are org-scoped, so this route takes orgId rather than hostId.
87
+ case 'datasetSchema':
88
+ return {
89
+ endpoint: 'marketplace/publish-dataset-schema',
90
+ payload: {
91
+ orgId,
92
+ datasetId: artifactId
93
+ },
94
+ noun: 'dataset schema'
95
+ };
96
+ case 'emailTemplate':
97
+ return {
98
+ endpoint: 'marketplace/publish-email-template',
99
+ payload: {
100
+ hostId,
101
+ templateKey: artifactId
102
+ },
103
+ noun: 'email template'
104
+ };
105
+ case 'emailStarter':
106
+ return {
107
+ endpoint: 'marketplace/publish-email-starter',
108
+ payload: {
109
+ hostId,
110
+ screenId: artifactId
111
+ },
112
+ noun: 'email starter'
113
+ };
114
+ default:
115
+ return null;
116
+ }
117
+ }
118
+ /**
119
+ * Publish an artifact to the marketplace (AGL-672, moved out of the console
120
+ * app by AGL-3080).
121
+ *
122
+ * The publish form is identical across artifact types — name, description,
123
+ * category, price — and only the endpoint and identifying fields differ, so
124
+ * this takes both rather than being copied per type. Every gate that
125
+ * matters (plan, publisher profile, payouts, host role) lives on the server;
126
+ * this surfaces the server's message rather than trying to predict it.
127
+ *
128
+ * Drawn through the `hostArtifactPublish` zone, so the page that offers the
129
+ * publish keeps the control that opens it and never imports this. A page
130
+ * with no widget on that zone leaves the offer out entirely, which is why
131
+ * this may safely draw nothing for a kind it does not sell.
132
+ */ export function PublishArtifactDialog({ artifact, onClose }) {
133
+ var _ref, _ref1, _ref2, _marketplacePriceCostNote;
134
+ // Memoized because it is a dependency of the publish callback: rebuilt
135
+ // every render, it would rebuild that callback every render too.
136
+ const target = useMemo(()=>artifact ? publishRequestFor(artifact) : null, [
137
+ artifact
138
+ ]);
139
+ const { data: user } = useUser();
140
+ const { enqueueSnackbar } = useSnackbar();
141
+ const [name, setName] = useState('');
142
+ const [description, setDescription] = useState('');
143
+ const [category, setCategory] = useState('');
144
+ const [price, setPrice] = useState('');
145
+ const [busy, setBusy] = useState(false);
146
+ useEffect(()=>{
147
+ var _artifact_displayName, _artifact_description;
148
+ if (!artifact) return;
149
+ setName((_artifact_displayName = artifact.displayName) != null ? _artifact_displayName : '');
150
+ setDescription((_artifact_description = artifact.description) != null ? _artifact_description : '');
151
+ setCategory('');
152
+ setPrice('');
153
+ }, [
154
+ artifact
155
+ ]);
156
+ const handlePublish = useCallback(async ()=>{
157
+ if (!target || !name.trim() || busy) return;
158
+ setBusy(true);
159
+ try {
160
+ const response = await authorizedFetch(user, `/api/${target.endpoint}`, {
161
+ method: 'POST',
162
+ headers: {
163
+ 'Content-Type': 'application/json'
164
+ },
165
+ body: JSON.stringify(_extends({}, target.payload, {
166
+ displayName: name.trim(),
167
+ description: description.trim(),
168
+ category: category.trim(),
169
+ priceUsd: Number(price) || 0
170
+ }))
171
+ });
172
+ const payload = await response.json().catch(()=>({}));
173
+ if (!response.ok) {
174
+ var _ref;
175
+ // 412 means a setup step is missing (publisher profile, payouts) —
176
+ // actionable, so it reads as a warning rather than an error.
177
+ return void enqueueSnackbar((_ref = payload == null ? void 0 : payload.error) != null ? _ref : 'Publish failed', {
178
+ variant: response.status === 412 ? 'warning' : 'error',
179
+ allowDuplicate: true
180
+ });
181
+ }
182
+ enqueueSnackbar(`Published v${payload.version} to the marketplace`, {
183
+ variant: 'success',
184
+ persist: false
185
+ });
186
+ onClose();
187
+ } catch (error) {
188
+ console.error(error);
189
+ enqueueSnackbar('An error has occurred', {
190
+ variant: 'error',
191
+ allowDuplicate: true
192
+ });
193
+ } finally{
194
+ setBusy(false);
195
+ }
196
+ }, [
197
+ target,
198
+ name,
199
+ description,
200
+ category,
201
+ price,
202
+ busy,
203
+ user,
204
+ enqueueSnackbar,
205
+ onClose
206
+ ]);
207
+ if (artifact && !target) {
208
+ return /*#__PURE__*/ _jsxs(Dialog, {
209
+ open: true,
210
+ onClose: onClose,
211
+ maxWidth: "xs",
212
+ fullWidth: true,
213
+ children: [
214
+ /*#__PURE__*/ _jsx(DialogTitle, {
215
+ children: 'Nothing publishes this'
216
+ }),
217
+ /*#__PURE__*/ _jsx(DialogContent, {
218
+ children: /*#__PURE__*/ _jsx(Typography, {
219
+ variant: "body2",
220
+ color: "text.secondary",
221
+ children: `This marketplace does not publish a ${artifact.kind}, so there ` + 'is nowhere to send it. Nothing was changed.'
222
+ })
223
+ }),
224
+ /*#__PURE__*/ _jsx(DialogActions, {
225
+ children: /*#__PURE__*/ _jsx(Button, {
226
+ size: "small",
227
+ onClick: onClose,
228
+ children: 'Close'
229
+ })
230
+ })
231
+ ]
232
+ });
233
+ }
234
+ return /*#__PURE__*/ _jsxs(Dialog, {
235
+ open: !!target,
236
+ onClose: busy ? undefined : onClose,
237
+ maxWidth: "xs",
238
+ fullWidth: true,
239
+ children: [
240
+ /*#__PURE__*/ _jsx(DialogTitle, {
241
+ children: `Publish ${(_ref = target == null ? void 0 : target.noun) != null ? _ref : 'artifact'}`
242
+ }),
243
+ /*#__PURE__*/ _jsx(DialogContent, {
244
+ children: /*#__PURE__*/ _jsxs(Stack, {
245
+ spacing: 2,
246
+ sx: {
247
+ pt: 1
248
+ },
249
+ children: [
250
+ /*#__PURE__*/ _jsx(Typography, {
251
+ variant: "body2",
252
+ color: "text.secondary",
253
+ children: `Publishes the current published version of this ` + `${(_ref1 = target == null ? void 0 : target.noun) != null ? _ref1 : 'artifact'} so other organizations can ` + 'install it. Your site is unaffected.'
254
+ }),
255
+ /*#__PURE__*/ _jsx(TextField, {
256
+ autoFocus: true,
257
+ size: "small",
258
+ label: "Listing name",
259
+ value: name,
260
+ onChange: (event)=>setName(event.target.value),
261
+ disabled: busy,
262
+ fullWidth: true
263
+ }),
264
+ /*#__PURE__*/ _jsx(TextField, {
265
+ size: "small",
266
+ label: "Description",
267
+ value: description,
268
+ onChange: (event)=>setDescription(event.target.value),
269
+ disabled: busy,
270
+ multiline: true,
271
+ minRows: 2,
272
+ fullWidth: true
273
+ }),
274
+ /*#__PURE__*/ _jsx(TextField, {
275
+ size: "small",
276
+ label: "Category",
277
+ placeholder: (_ref2 = target == null ? void 0 : target.categoryPlaceholder) != null ? _ref2 : 'e.g. Marketing, Docs',
278
+ value: category,
279
+ onChange: (event)=>setCategory(event.target.value),
280
+ disabled: busy,
281
+ fullWidth: true
282
+ }),
283
+ /*#__PURE__*/ _jsx(TextField, {
284
+ size: "small",
285
+ label: "Price (USD)",
286
+ placeholder: "0 = free",
287
+ // The minimum price (AGL-2343). Marketplace checkout is a
288
+ // destination charge, so Stripe's fee comes out of the PLATFORM's
289
+ // balance while the seller is transferred a fixed share — at $1 the
290
+ // fee is larger than the whole platform cut. The publish route
291
+ // refuses anything under the floor, so the field says so before the
292
+ // publisher gets there and the button holds.
293
+ error: isBelowMarketplacePriceFloor(price),
294
+ helperText: (_marketplacePriceCostNote = marketplacePriceCostNote(price)) != null ? _marketplacePriceCostNote : marketplacePriceFloorHint('Paid listings need payouts set up on your marketplace profile.'),
295
+ value: price,
296
+ onChange: (event)=>setPrice(event.target.value.replace(/[^0-9]/g, '')),
297
+ disabled: busy,
298
+ fullWidth: true
299
+ })
300
+ ]
301
+ })
302
+ }),
303
+ /*#__PURE__*/ _jsxs(DialogActions, {
304
+ children: [
305
+ /*#__PURE__*/ _jsx(Button, {
306
+ size: "small",
307
+ onClick: onClose,
308
+ disabled: busy,
309
+ children: 'Cancel'
310
+ }),
311
+ /*#__PURE__*/ _jsx(Button, {
312
+ size: "small",
313
+ variant: "contained",
314
+ color: "primary",
315
+ disabled: busy || !name.trim() || isBelowMarketplacePriceFloor(price),
316
+ onClick: ()=>void handlePublish(),
317
+ children: busy ? 'Publishing…' : 'Publish'
318
+ })
319
+ ]
320
+ })
321
+ ]
322
+ });
323
+ }
324
+ PublishArtifactDialog.displayName = 'PublishArtifactDialog';
325
+ export default PublishArtifactDialog;
326
+
327
+ //# sourceMappingURL=publish-artifact-dialog.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/marketplace/src/lib/components/publish-artifact-dialog.component.tsx"],"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 {\n isBelowMarketplacePriceFloor,\n marketplacePriceCostNote,\n marketplacePriceFloorHint,\n} from '@aglyn/aglyn'\nimport type {\n ConsoleArtifactPublishZoneProps,\n ConsolePublishableArtifact,\n} from '@aglyn/aglyn'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useUser } from '@aglyn/tenant-feature-instance'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport {\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\n\n/** One kind's publish route, and the words a person reads about it. */\ninterface PublishRequest {\n /** Plugin API path, e.g. `marketplace/publish-layout`. */\n endpoint: string\n /** Extra body fields identifying what is being published. */\n payload: Record<string, unknown>\n /** Noun used in copy: \"layout\", \"component\", … */\n noun: string\n categoryPlaceholder?: string\n}\n\n/**\n * WHERE EACH KIND GOES, which is the knowledge that used to sit in the app\n * (AGL-3080).\n *\n * A console page hands over what it has — a kind, the scope holding it, the\n * document — and this is the only place that turns it into a request. The\n * pages that offer publishing named the endpoint, the payload key and the\n * noun themselves, which made them files that could not compile without a\n * marketplace and could not be right without being kept in step with one.\n *\n * ⚠️ A KIND THIS DOES NOT KNOW IS SAID OUT LOUD, not drawn as nothing. It\n * means a console offering to publish something this marketplace does not\n * sell — the two lists have gone out of step — and the person has already\n * clicked. Drawing nothing would make the control look broken with no way to\n * tell what happened, and guessing an endpoint from the kind would post to a\n * route that does not exist and report the 404 to the publisher.\n *\n * The control itself is a separate matter: a page only offers the publish\n * when this zone has a widget at all, so a workspace with no marketplace\n * never gets here.\n */\nfunction publishRequestFor(\n artifact: ConsolePublishableArtifact,\n): PublishRequest | null {\n const hostId = artifact.hostId ?? ''\n const orgId = artifact.orgId ?? ''\n const artifactId = artifact.artifactId ?? ''\n switch (artifact.kind) {\n case 'layout':\n return {\n endpoint: 'marketplace/publish-layout',\n payload: { hostId, layoutId: artifactId },\n noun: 'layout',\n categoryPlaceholder: 'e.g. Marketing, Docs, Storefront',\n }\n case 'component':\n return {\n endpoint: 'marketplace/publish',\n payload: { hostId, componentId: artifactId },\n noun: 'component',\n }\n case 'site':\n return {\n endpoint: 'marketplace/publish-template',\n payload: { hostId },\n noun: 'site template',\n }\n case 'theme':\n return {\n endpoint: 'marketplace/publish-theme',\n payload: { hostId },\n noun: 'theme',\n }\n // Datasets are org-scoped, so this route takes orgId rather than hostId.\n case 'datasetSchema':\n return {\n endpoint: 'marketplace/publish-dataset-schema',\n payload: { orgId, datasetId: artifactId },\n noun: 'dataset schema',\n }\n case 'emailTemplate':\n return {\n endpoint: 'marketplace/publish-email-template',\n payload: { hostId, templateKey: artifactId },\n noun: 'email template',\n }\n case 'emailStarter':\n return {\n endpoint: 'marketplace/publish-email-starter',\n payload: { hostId, screenId: artifactId },\n noun: 'email starter',\n }\n default:\n return null\n }\n}\n\n/**\n * Publish an artifact to the marketplace (AGL-672, moved out of the console\n * app by AGL-3080).\n *\n * The publish form is identical across artifact types — name, description,\n * category, price — and only the endpoint and identifying fields differ, so\n * this takes both rather than being copied per type. Every gate that\n * matters (plan, publisher profile, payouts, host role) lives on the server;\n * this surfaces the server's message rather than trying to predict it.\n *\n * Drawn through the `hostArtifactPublish` zone, so the page that offers the\n * publish keeps the control that opens it and never imports this. A page\n * with no widget on that zone leaves the offer out entirely, which is why\n * this may safely draw nothing for a kind it does not sell.\n */\nexport function PublishArtifactDialog({\n artifact,\n onClose,\n}: ConsoleArtifactPublishZoneProps) {\n // Memoized because it is a dependency of the publish callback: rebuilt\n // every render, it would rebuild that callback every render too.\n const target = useMemo(\n () => (artifact ? publishRequestFor(artifact) : null),\n [artifact],\n )\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n const [name, setName] = useState('')\n const [description, setDescription] = useState('')\n const [category, setCategory] = useState('')\n const [price, setPrice] = useState('')\n const [busy, setBusy] = useState(false)\n\n useEffect(() => {\n if (!artifact) return\n setName(artifact.displayName ?? '')\n setDescription(artifact.description ?? '')\n setCategory('')\n setPrice('')\n }, [artifact])\n\n const handlePublish = useCallback(async () => {\n if (!target || !name.trim() || busy) return\n setBusy(true)\n try {\n const response = await authorizedFetch(user, `/api/${target.endpoint}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...target.payload,\n displayName: name.trim(),\n description: description.trim(),\n category: category.trim(),\n priceUsd: Number(price) || 0,\n }),\n })\n const payload = await response.json().catch(() => ({}))\n if (!response.ok) {\n // 412 means a setup step is missing (publisher profile, payouts) —\n // actionable, so it reads as a warning rather than an error.\n return void enqueueSnackbar(payload?.error ?? 'Publish failed', {\n variant: response.status === 412 ? 'warning' : 'error',\n allowDuplicate: true,\n })\n }\n enqueueSnackbar(`Published v${payload.version} to the marketplace`, {\n variant: 'success',\n persist: false,\n })\n onClose()\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setBusy(false)\n }\n }, [\n target,\n name,\n description,\n category,\n price,\n busy,\n user,\n enqueueSnackbar,\n onClose,\n ])\n\n if (artifact && !target) {\n return (\n <Dialog open onClose={onClose} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{'Nothing publishes this'}</DialogTitle>\n <DialogContent>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`This marketplace does not publish a ${artifact.kind}, so there ` +\n 'is nowhere to send it. Nothing was changed.'}\n </Typography>\n </DialogContent>\n <DialogActions>\n <Button size=\"small\" onClick={onClose}>\n {'Close'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n }\n\n return (\n <Dialog\n open={!!target}\n onClose={busy ? undefined : onClose}\n maxWidth=\"xs\"\n fullWidth\n >\n <DialogTitle>{`Publish ${target?.noun ?? 'artifact'}`}</DialogTitle>\n <DialogContent>\n <Stack spacing={2} sx={{ pt: 1 }}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`Publishes the current published version of this ` +\n `${target?.noun ?? 'artifact'} so other organizations can ` +\n 'install it. Your site is unaffected.'}\n </Typography>\n <TextField\n autoFocus\n size=\"small\"\n label=\"Listing name\"\n value={name}\n onChange={(event) => setName(event.target.value)}\n disabled={busy}\n fullWidth\n />\n <TextField\n size=\"small\"\n label=\"Description\"\n value={description}\n onChange={(event) => setDescription(event.target.value)}\n disabled={busy}\n multiline\n minRows={2}\n fullWidth\n />\n <TextField\n size=\"small\"\n label=\"Category\"\n placeholder={target?.categoryPlaceholder ?? 'e.g. Marketing, Docs'}\n value={category}\n onChange={(event) => setCategory(event.target.value)}\n disabled={busy}\n fullWidth\n />\n <TextField\n size=\"small\"\n label=\"Price (USD)\"\n placeholder=\"0 = free\"\n // The minimum price (AGL-2343). Marketplace checkout is a\n // destination charge, so Stripe's fee comes out of the PLATFORM's\n // balance while the seller is transferred a fixed share — at $1 the\n // fee is larger than the whole platform cut. The publish route\n // refuses anything under the floor, so the field says so before the\n // publisher gets there and the button holds.\n error={isBelowMarketplacePriceFloor(price)}\n helperText={\n marketplacePriceCostNote(price) ??\n marketplacePriceFloorHint(\n 'Paid listings need payouts set up on your marketplace profile.',\n )\n }\n value={price}\n onChange={(event) =>\n setPrice(event.target.value.replace(/[^0-9]/g, ''))\n }\n disabled={busy}\n fullWidth\n />\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button size=\"small\" onClick={onClose} disabled={busy}>\n {'Cancel'}\n </Button>\n <Button\n size=\"small\"\n variant=\"contained\"\n color=\"primary\"\n disabled={busy || !name.trim() || isBelowMarketplacePriceFloor(price)}\n onClick={() => void handlePublish()}\n >\n {busy ? 'Publishing…' : 'Publish'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\n\nPublishArtifactDialog.displayName = 'PublishArtifactDialog'\n\nexport default PublishArtifactDialog\n"],"names":["isBelowMarketplacePriceFloor","marketplacePriceCostNote","marketplacePriceFloorHint","useSnackbar","useUser","authorizedFetch","Button","Dialog","DialogActions","DialogContent","DialogTitle","Stack","TextField","Typography","useCallback","useEffect","useMemo","useState","publishRequestFor","artifact","hostId","orgId","artifactId","kind","endpoint","payload","layoutId","noun","categoryPlaceholder","componentId","datasetId","templateKey","screenId","PublishArtifactDialog","onClose","target","data","user","enqueueSnackbar","name","setName","description","setDescription","category","setCategory","price","setPrice","busy","setBusy","displayName","handlePublish","trim","response","method","headers","body","JSON","stringify","priceUsd","Number","json","catch","ok","error","variant","status","allowDuplicate","version","persist","console","open","maxWidth","fullWidth","color","size","onClick","undefined","spacing","sx","pt","autoFocus","label","value","onChange","event","disabled","multiline","minRows","placeholder","helperText","replace"],"mappings":"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"}
package/src/lib/plugin.js CHANGED
@@ -19,6 +19,7 @@ import MarketplaceBrowse from "./components/marketplace-browse.component.js";
19
19
  import MarketplacePaymentsNotice from "./components/marketplace-payments-notice.component.js";
20
20
  import HostPluginsCard from "./components/host-plugins-card.component.js";
21
21
  import PluginSiteSetPanel from "./components/plugin-site-set-panel.component.js";
22
+ import PublishArtifactDialog from "./components/publish-artifact-dialog.component.js";
22
23
  import { MarketplaceListingContent } from "./components/listing-content.component.js";
23
24
  import { BUNDLE_ID } from "./constants/bundle-common.js";
24
25
  import { RATING_FIELD } from "./model/rating-field.js";
@@ -83,6 +84,16 @@ import RatingInput from "./components/rating-input.component.js";
83
84
  slot: 'pluginSiteSet',
84
85
  widgetId: 'marketplace-plugin-site-set',
85
86
  Component: PluginSiteSetPanel
87
+ },
88
+ // Publishing something the console holds (AGL-3080). The page that
89
+ // offers it keeps the control that opens it — a menu item is one entry
90
+ // of a list the page builds, not a widget — and hands over what it has
91
+ // in its own vocabulary. Where a layout or a theme GOES, what a listing
92
+ // of it is called and what it may cost at the least are this plugin's.
93
+ {
94
+ slot: 'hostArtifactPublish',
95
+ widgetId: 'marketplace-publish-artifact',
96
+ Component: PublishArtifactDialog
86
97
  }
87
98
  ],
88
99
  pluginId: BUNDLE_ID,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../libs/plugins/marketplace/src/lib/plugin.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 * as Aglyn from '@aglyn/aglyn'\nimport MarketplaceBrowse from './components/marketplace-browse.component'\nimport MarketplacePaymentsNotice from './components/marketplace-payments-notice.component'\nimport HostPluginsCard from './components/host-plugins-card.component'\nimport PluginSiteSetPanel from './components/plugin-site-set-panel.component'\nimport { MarketplaceListingContent } from './components/listing-content.component'\nimport { BUNDLE_ID } from './constants/bundle-common'\nimport { RATING_FIELD } from './model/rating-field'\nimport RatingInput from './components/rating-input.component'\n\n/**\n * Marketplace feature plugin (AGL-395). Console-only — marketplace components\n * install into a host's own components collection and render through the\n * normal compose pipeline, so there is no separate canvas bundle.\n *\n * The marketplace moved to org scope (AGL-772/774): browse + install live at\n * `/[orgSlug]/marketplace`, so this plugin no longer contributes a per-site\n * `Marketplace` nav tab (AGL-775). It exposes its UI purely through widget\n * slots — `orgMarketplace` (browse), `marketplaceListing` (detail) and\n * `orgAddons` (installed) — which the app renders without importing the\n * plugin.\n */\nexport function registerMarketplaceConsole(): void {\n // Custom field type (AGL-434): rating rides int32 with a starred input.\n Aglyn.registerCustomFieldType({ ...RATING_FIELD, Input: RatingInput })\n Aglyn.registerConsoleExtension({\n // Listing detail content (AGL-419): the app route keeps the chrome\n // and renders this through the 'marketplaceListing' slot.\n widgets: [\n {\n slot: 'marketplaceListing',\n widgetId: 'marketplace-listing-content',\n Component: MarketplaceListingContent,\n },\n // What this deployment cannot do, said BEFORE the click (AGL-2019,\n // moved here by AGL-3080). The sentence names what still works\n // without a Stripe platform — browsing and free installs — which is\n // this plugin's knowledge; the app supplies only the fact, through\n // the deployment-capability context its org layout provides. The\n // widget draws nothing at all on a configured deployment.\n {\n slot: 'marketplaceCapability',\n widgetId: 'marketplace-payments-notice',\n Component: MarketplacePaymentsNotice,\n },\n // Org marketplace browse (AGL-772): the org-scope `/marketplace`\n // page renders this with an acting hostId + orgScoped, so listing\n // links resolve to the org route. The single place to browse/install,\n // replacing the per-site marketplace tab.\n {\n slot: 'orgMarketplace',\n widgetId: 'marketplace-org-marketplace',\n Component: MarketplaceBrowse,\n },\n // Installed add-ons management (AGL-423): the org \"Plugins &\n // add-ons\" hub renders this with an acting hostId — the card lists\n // host + org install pins with upgrade/uninstall/share-with-org.\n {\n slot: 'orgAddons',\n widgetId: 'marketplace-installed-addons',\n Component: HostPluginsCard,\n },\n // The site set for one installation (AGL-1007): the same control the\n // listing page uses, exposed so the installation detail page can show\n // it without the app importing this plugin.\n {\n slot: 'pluginSiteSet',\n widgetId: 'marketplace-plugin-site-set',\n Component: PluginSiteSetPanel,\n },\n ],\n pluginId: BUNDLE_ID,\n displayName: 'Marketplace',\n })\n}\n\n// Shared with the listing/publisher detail app-routes.\nexport { default as useMarketplaceActions } from './hooks/use-marketplace-actions'\nexport { default as MarketplaceBrowse } from './components/marketplace-browse.component'\nexport { default as HostPluginsCard } from './components/host-plugins-card.component'\nexport { default as PluginSiteSetPanel } from './components/plugin-site-set-panel.component'\n"],"names":["Aglyn","MarketplaceBrowse","MarketplacePaymentsNotice","HostPluginsCard","PluginSiteSetPanel","MarketplaceListingContent","BUNDLE_ID","RATING_FIELD","RatingInput","registerMarketplaceConsole","registerCustomFieldType","Input","registerConsoleExtension","widgets","slot","widgetId","Component","pluginId","displayName","default","useMarketplaceActions"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,OAAOC,uBAAuB,+CAA2C;AACzE,OAAOC,+BAA+B,wDAAoD;AAC1F,OAAOC,qBAAqB,8CAA0C;AACtE,OAAOC,wBAAwB,kDAA8C;AAC7E,SAASC,yBAAyB,QAAQ,4CAAwC;AAClF,SAASC,SAAS,QAAQ,+BAA2B;AACrD,SAASC,YAAY,QAAQ,0BAAsB;AACnD,OAAOC,iBAAiB,yCAAqC;AAE7D;;;;;;;;;;;CAWC,GACD,OAAO,SAASC;IACd,wEAAwE;IACxET,MAAMU,uBAAuB,CAAC,aAAKH;QAAcI,OAAOH;;IACxDR,MAAMY,wBAAwB,CAAC;QAC7B,mEAAmE;QACnE,0DAA0D;QAC1DC,SAAS;YACP;gBACEC,MAAM;gBACNC,UAAU;gBACVC,WAAWX;YACb;YACA,mEAAmE;YACnE,+DAA+D;YAC/D,oEAAoE;YACpE,mEAAmE;YACnE,iEAAiE;YACjE,0DAA0D;YAC1D;gBACES,MAAM;gBACNC,UAAU;gBACVC,WAAWd;YACb;YACA,iEAAiE;YACjE,kEAAkE;YAClE,sEAAsE;YACtE,0CAA0C;YAC1C;gBACEY,MAAM;gBACNC,UAAU;gBACVC,WAAWf;YACb;YACA,6DAA6D;YAC7D,mEAAmE;YACnE,iEAAiE;YACjE;gBACEa,MAAM;gBACNC,UAAU;gBACVC,WAAWb;YACb;YACA,qEAAqE;YACrE,sEAAsE;YACtE,4CAA4C;YAC5C;gBACEW,MAAM;gBACNC,UAAU;gBACVC,WAAWZ;YACb;SACD;QACDa,UAAUX;QACVY,aAAa;IACf;AACF;AAEA,uDAAuD;AACvD,SAASC,WAAWC,qBAAqB,QAAQ,qCAAiC;AAClF,SAASD,WAAWlB,iBAAiB,QAAQ,+CAA2C;AACxF,SAASkB,WAAWhB,eAAe,QAAQ,8CAA0C;AACrF,SAASgB,WAAWf,kBAAkB,QAAQ,kDAA8C"}
1
+ {"version":3,"sources":["../../../../../../libs/plugins/marketplace/src/lib/plugin.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 * as Aglyn from '@aglyn/aglyn'\nimport MarketplaceBrowse from './components/marketplace-browse.component'\nimport MarketplacePaymentsNotice from './components/marketplace-payments-notice.component'\nimport HostPluginsCard from './components/host-plugins-card.component'\nimport PluginSiteSetPanel from './components/plugin-site-set-panel.component'\nimport PublishArtifactDialog from './components/publish-artifact-dialog.component'\nimport { MarketplaceListingContent } from './components/listing-content.component'\nimport { BUNDLE_ID } from './constants/bundle-common'\nimport { RATING_FIELD } from './model/rating-field'\nimport RatingInput from './components/rating-input.component'\n\n/**\n * Marketplace feature plugin (AGL-395). Console-only — marketplace components\n * install into a host's own components collection and render through the\n * normal compose pipeline, so there is no separate canvas bundle.\n *\n * The marketplace moved to org scope (AGL-772/774): browse + install live at\n * `/[orgSlug]/marketplace`, so this plugin no longer contributes a per-site\n * `Marketplace` nav tab (AGL-775). It exposes its UI purely through widget\n * slots — `orgMarketplace` (browse), `marketplaceListing` (detail) and\n * `orgAddons` (installed) — which the app renders without importing the\n * plugin.\n */\nexport function registerMarketplaceConsole(): void {\n // Custom field type (AGL-434): rating rides int32 with a starred input.\n Aglyn.registerCustomFieldType({ ...RATING_FIELD, Input: RatingInput })\n Aglyn.registerConsoleExtension({\n // Listing detail content (AGL-419): the app route keeps the chrome\n // and renders this through the 'marketplaceListing' slot.\n widgets: [\n {\n slot: 'marketplaceListing',\n widgetId: 'marketplace-listing-content',\n Component: MarketplaceListingContent,\n },\n // What this deployment cannot do, said BEFORE the click (AGL-2019,\n // moved here by AGL-3080). The sentence names what still works\n // without a Stripe platform — browsing and free installs — which is\n // this plugin's knowledge; the app supplies only the fact, through\n // the deployment-capability context its org layout provides. The\n // widget draws nothing at all on a configured deployment.\n {\n slot: 'marketplaceCapability',\n widgetId: 'marketplace-payments-notice',\n Component: MarketplacePaymentsNotice,\n },\n // Org marketplace browse (AGL-772): the org-scope `/marketplace`\n // page renders this with an acting hostId + orgScoped, so listing\n // links resolve to the org route. The single place to browse/install,\n // replacing the per-site marketplace tab.\n {\n slot: 'orgMarketplace',\n widgetId: 'marketplace-org-marketplace',\n Component: MarketplaceBrowse,\n },\n // Installed add-ons management (AGL-423): the org \"Plugins &\n // add-ons\" hub renders this with an acting hostId — the card lists\n // host + org install pins with upgrade/uninstall/share-with-org.\n {\n slot: 'orgAddons',\n widgetId: 'marketplace-installed-addons',\n Component: HostPluginsCard,\n },\n // The site set for one installation (AGL-1007): the same control the\n // listing page uses, exposed so the installation detail page can show\n // it without the app importing this plugin.\n {\n slot: 'pluginSiteSet',\n widgetId: 'marketplace-plugin-site-set',\n Component: PluginSiteSetPanel,\n },\n // Publishing something the console holds (AGL-3080). The page that\n // offers it keeps the control that opens it — a menu item is one entry\n // of a list the page builds, not a widget — and hands over what it has\n // in its own vocabulary. Where a layout or a theme GOES, what a listing\n // of it is called and what it may cost at the least are this plugin's.\n {\n slot: 'hostArtifactPublish',\n widgetId: 'marketplace-publish-artifact',\n Component: PublishArtifactDialog,\n },\n ],\n pluginId: BUNDLE_ID,\n displayName: 'Marketplace',\n })\n}\n\n// Shared with the listing/publisher detail app-routes.\nexport { default as useMarketplaceActions } from './hooks/use-marketplace-actions'\nexport { default as MarketplaceBrowse } from './components/marketplace-browse.component'\nexport { default as HostPluginsCard } from './components/host-plugins-card.component'\nexport { default as PluginSiteSetPanel } from './components/plugin-site-set-panel.component'\n"],"names":["Aglyn","MarketplaceBrowse","MarketplacePaymentsNotice","HostPluginsCard","PluginSiteSetPanel","PublishArtifactDialog","MarketplaceListingContent","BUNDLE_ID","RATING_FIELD","RatingInput","registerMarketplaceConsole","registerCustomFieldType","Input","registerConsoleExtension","widgets","slot","widgetId","Component","pluginId","displayName","default","useMarketplaceActions"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,OAAOC,uBAAuB,+CAA2C;AACzE,OAAOC,+BAA+B,wDAAoD;AAC1F,OAAOC,qBAAqB,8CAA0C;AACtE,OAAOC,wBAAwB,kDAA8C;AAC7E,OAAOC,2BAA2B,oDAAgD;AAClF,SAASC,yBAAyB,QAAQ,4CAAwC;AAClF,SAASC,SAAS,QAAQ,+BAA2B;AACrD,SAASC,YAAY,QAAQ,0BAAsB;AACnD,OAAOC,iBAAiB,yCAAqC;AAE7D;;;;;;;;;;;CAWC,GACD,OAAO,SAASC;IACd,wEAAwE;IACxEV,MAAMW,uBAAuB,CAAC,aAAKH;QAAcI,OAAOH;;IACxDT,MAAMa,wBAAwB,CAAC;QAC7B,mEAAmE;QACnE,0DAA0D;QAC1DC,SAAS;YACP;gBACEC,MAAM;gBACNC,UAAU;gBACVC,WAAWX;YACb;YACA,mEAAmE;YACnE,+DAA+D;YAC/D,oEAAoE;YACpE,mEAAmE;YACnE,iEAAiE;YACjE,0DAA0D;YAC1D;gBACES,MAAM;gBACNC,UAAU;gBACVC,WAAWf;YACb;YACA,iEAAiE;YACjE,kEAAkE;YAClE,sEAAsE;YACtE,0CAA0C;YAC1C;gBACEa,MAAM;gBACNC,UAAU;gBACVC,WAAWhB;YACb;YACA,6DAA6D;YAC7D,mEAAmE;YACnE,iEAAiE;YACjE;gBACEc,MAAM;gBACNC,UAAU;gBACVC,WAAWd;YACb;YACA,qEAAqE;YACrE,sEAAsE;YACtE,4CAA4C;YAC5C;gBACEY,MAAM;gBACNC,UAAU;gBACVC,WAAWb;YACb;YACA,mEAAmE;YACnE,uEAAuE;YACvE,uEAAuE;YACvE,wEAAwE;YACxE,uEAAuE;YACvE;gBACEW,MAAM;gBACNC,UAAU;gBACVC,WAAWZ;YACb;SACD;QACDa,UAAUX;QACVY,aAAa;IACf;AACF;AAEA,uDAAuD;AACvD,SAASC,WAAWC,qBAAqB,QAAQ,qCAAiC;AAClF,SAASD,WAAWnB,iBAAiB,QAAQ,+CAA2C;AACxF,SAASmB,WAAWjB,eAAe,QAAQ,8CAA0C;AACrF,SAASiB,WAAWhB,kBAAkB,QAAQ,kDAA8C"}