@aglyn/plugins-marketplace 1.0.0-beta.143

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 (165) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +7 -0
  3. package/package.json +51 -0
  4. package/src/index.d.ts +19 -0
  5. package/src/index.js +20 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/components/artifact-update-dialog.component.d.ts +27 -0
  8. package/src/lib/components/artifact-update-dialog.component.js +244 -0
  9. package/src/lib/components/artifact-update-dialog.component.js.map +1 -0
  10. package/src/lib/components/host-plugins-card.component.d.ts +23 -0
  11. package/src/lib/components/host-plugins-card.component.js +566 -0
  12. package/src/lib/components/host-plugins-card.component.js.map +1 -0
  13. package/src/lib/components/listing-content.component.d.ts +57 -0
  14. package/src/lib/components/listing-content.component.js +1880 -0
  15. package/src/lib/components/listing-content.component.js.map +1 -0
  16. package/src/lib/components/listing-image.component.d.ts +46 -0
  17. package/src/lib/components/listing-image.component.js +38 -0
  18. package/src/lib/components/listing-image.component.js.map +1 -0
  19. package/src/lib/components/listing-reviews.component.d.ts +22 -0
  20. package/src/lib/components/listing-reviews.component.js +419 -0
  21. package/src/lib/components/listing-reviews.component.js.map +1 -0
  22. package/src/lib/components/marketplace-browse.component.d.ts +38 -0
  23. package/src/lib/components/marketplace-browse.component.js +802 -0
  24. package/src/lib/components/marketplace-browse.component.js.map +1 -0
  25. package/src/lib/components/plugin-site-set-panel.component.d.ts +24 -0
  26. package/src/lib/components/plugin-site-set-panel.component.js +137 -0
  27. package/src/lib/components/plugin-site-set-panel.component.js.map +1 -0
  28. package/src/lib/components/plugin-site-set.component.d.ts +43 -0
  29. package/src/lib/components/plugin-site-set.component.js +425 -0
  30. package/src/lib/components/plugin-site-set.component.js.map +1 -0
  31. package/src/lib/components/rating-input.component.d.ts +3 -0
  32. package/src/lib/components/rating-input.component.js +47 -0
  33. package/src/lib/components/rating-input.component.js.map +1 -0
  34. package/src/lib/components/report-target.component.d.ts +36 -0
  35. package/src/lib/components/report-target.component.js +181 -0
  36. package/src/lib/components/report-target.component.js.map +1 -0
  37. package/src/lib/components/uninstall-impact-dialog.component.d.ts +40 -0
  38. package/src/lib/components/uninstall-impact-dialog.component.js +244 -0
  39. package/src/lib/components/uninstall-impact-dialog.component.js.map +1 -0
  40. package/src/lib/constants/bundle-common.d.ts +8 -0
  41. package/src/lib/constants/bundle-common.js +9 -0
  42. package/src/lib/constants/bundle-common.js.map +1 -0
  43. package/src/lib/hooks/use-artifact-update.d.ts +41 -0
  44. package/src/lib/hooks/use-artifact-update.js +169 -0
  45. package/src/lib/hooks/use-artifact-update.js.map +1 -0
  46. package/src/lib/hooks/use-marketplace-actions.d.ts +37 -0
  47. package/src/lib/hooks/use-marketplace-actions.js +523 -0
  48. package/src/lib/hooks/use-marketplace-actions.js.map +1 -0
  49. package/src/lib/model/artifact-merge.d.ts +154 -0
  50. package/src/lib/model/artifact-merge.js +228 -0
  51. package/src/lib/model/artifact-merge.js.map +1 -0
  52. package/src/lib/model/index.d.ts +43 -0
  53. package/src/lib/model/index.js +41 -0
  54. package/src/lib/model/index.js.map +1 -0
  55. package/src/lib/model/marketplace-props.d.ts +57 -0
  56. package/src/lib/model/marketplace-props.js +441 -0
  57. package/src/lib/model/marketplace-props.js.map +1 -0
  58. package/src/lib/model/marketplace.d.ts +833 -0
  59. package/src/lib/model/marketplace.js +929 -0
  60. package/src/lib/model/marketplace.js.map +1 -0
  61. package/src/lib/model/rating-field.d.ts +24 -0
  62. package/src/lib/model/rating-field.js +33 -0
  63. package/src/lib/model/rating-field.js.map +1 -0
  64. package/src/lib/plugin.d.ts +33 -0
  65. package/src/lib/plugin.js +86 -0
  66. package/src/lib/plugin.js.map +1 -0
  67. package/src/lib/server/billing-webhook.d.ts +25 -0
  68. package/src/lib/server/billing-webhook.js +1062 -0
  69. package/src/lib/server/billing-webhook.js.map +1 -0
  70. package/src/lib/server/checkout.d.ts +76 -0
  71. package/src/lib/server/checkout.js +477 -0
  72. package/src/lib/server/checkout.js.map +1 -0
  73. package/src/lib/server/connect.d.ts +24 -0
  74. package/src/lib/server/connect.js +205 -0
  75. package/src/lib/server/connect.js.map +1 -0
  76. package/src/lib/server/install-dataset-schema.d.ts +32 -0
  77. package/src/lib/server/install-dataset-schema.js +255 -0
  78. package/src/lib/server/install-dataset-schema.js.map +1 -0
  79. package/src/lib/server/install-email-starter.d.ts +65 -0
  80. package/src/lib/server/install-email-starter.js +279 -0
  81. package/src/lib/server/install-email-starter.js.map +1 -0
  82. package/src/lib/server/install-email-template.d.ts +34 -0
  83. package/src/lib/server/install-email-template.js +252 -0
  84. package/src/lib/server/install-email-template.js.map +1 -0
  85. package/src/lib/server/install-layout.d.ts +29 -0
  86. package/src/lib/server/install-layout.js +323 -0
  87. package/src/lib/server/install-layout.js.map +1 -0
  88. package/src/lib/server/install-pin-counts.d.ts +173 -0
  89. package/src/lib/server/install-pin-counts.js +248 -0
  90. package/src/lib/server/install-pin-counts.js.map +1 -0
  91. package/src/lib/server/install-plugin.d.ts +18 -0
  92. package/src/lib/server/install-plugin.js +405 -0
  93. package/src/lib/server/install-plugin.js.map +1 -0
  94. package/src/lib/server/install-template.d.ts +37 -0
  95. package/src/lib/server/install-template.js +348 -0
  96. package/src/lib/server/install-template.js.map +1 -0
  97. package/src/lib/server/install-theme.d.ts +42 -0
  98. package/src/lib/server/install-theme.js +313 -0
  99. package/src/lib/server/install-theme.js.map +1 -0
  100. package/src/lib/server/install.d.ts +27 -0
  101. package/src/lib/server/install.js +276 -0
  102. package/src/lib/server/install.js.map +1 -0
  103. package/src/lib/server/listing-versions.d.ts +26 -0
  104. package/src/lib/server/listing-versions.js +378 -0
  105. package/src/lib/server/listing-versions.js.map +1 -0
  106. package/src/lib/server/preview-image.d.ts +37 -0
  107. package/src/lib/server/preview-image.js +216 -0
  108. package/src/lib/server/preview-image.js.map +1 -0
  109. package/src/lib/server/provenance.d.ts +100 -0
  110. package/src/lib/server/provenance.js +118 -0
  111. package/src/lib/server/provenance.js.map +1 -0
  112. package/src/lib/server/publish-dataset-schema.d.ts +31 -0
  113. package/src/lib/server/publish-dataset-schema.js +202 -0
  114. package/src/lib/server/publish-dataset-schema.js.map +1 -0
  115. package/src/lib/server/publish-email-starter.d.ts +44 -0
  116. package/src/lib/server/publish-email-starter.js +231 -0
  117. package/src/lib/server/publish-email-starter.js.map +1 -0
  118. package/src/lib/server/publish-email-template.d.ts +33 -0
  119. package/src/lib/server/publish-email-template.js +211 -0
  120. package/src/lib/server/publish-email-template.js.map +1 -0
  121. package/src/lib/server/publish-layout.d.ts +33 -0
  122. package/src/lib/server/publish-layout.js +243 -0
  123. package/src/lib/server/publish-layout.js.map +1 -0
  124. package/src/lib/server/publish-plugin.d.ts +18 -0
  125. package/src/lib/server/publish-plugin.js +485 -0
  126. package/src/lib/server/publish-plugin.js.map +1 -0
  127. package/src/lib/server/publish-preconditions.d.ts +86 -0
  128. package/src/lib/server/publish-preconditions.js +160 -0
  129. package/src/lib/server/publish-preconditions.js.map +1 -0
  130. package/src/lib/server/publish-template.d.ts +27 -0
  131. package/src/lib/server/publish-template.js +215 -0
  132. package/src/lib/server/publish-template.js.map +1 -0
  133. package/src/lib/server/publish-theme.d.ts +38 -0
  134. package/src/lib/server/publish-theme.js +186 -0
  135. package/src/lib/server/publish-theme.js.map +1 -0
  136. package/src/lib/server/publish.d.ts +26 -0
  137. package/src/lib/server/publish.js +204 -0
  138. package/src/lib/server/publish.js.map +1 -0
  139. package/src/lib/server/publisher-profile-save.d.ts +30 -0
  140. package/src/lib/server/publisher-profile-save.js +226 -0
  141. package/src/lib/server/publisher-profile-save.js.map +1 -0
  142. package/src/lib/server/publisher-profile.d.ts +86 -0
  143. package/src/lib/server/publisher-profile.js +116 -0
  144. package/src/lib/server/publisher-profile.js.map +1 -0
  145. package/src/lib/server/purchase-entitlement.d.ts +83 -0
  146. package/src/lib/server/purchase-entitlement.js +118 -0
  147. package/src/lib/server/purchase-entitlement.js.map +1 -0
  148. package/src/lib/server/report.d.ts +32 -0
  149. package/src/lib/server/report.js +101 -0
  150. package/src/lib/server/report.js.map +1 -0
  151. package/src/lib/server/reviews.d.ts +41 -0
  152. package/src/lib/server/reviews.js +240 -0
  153. package/src/lib/server/reviews.js.map +1 -0
  154. package/src/lib/server/update-artifact.d.ts +19 -0
  155. package/src/lib/server/update-artifact.js +569 -0
  156. package/src/lib/server/update-artifact.js.map +1 -0
  157. package/src/lib/server/verification-request.d.ts +31 -0
  158. package/src/lib/server/verification-request.js +173 -0
  159. package/src/lib/server/verification-request.js.map +1 -0
  160. package/src/lib/server/version-stats.d.ts +202 -0
  161. package/src/lib/server/version-stats.js +305 -0
  162. package/src/lib/server/version-stats.js.map +1 -0
  163. package/src/lib/server.d.ts +30 -0
  164. package/src/lib/server.js +95 -0
  165. package/src/lib/server.js.map +1 -0
@@ -0,0 +1,441 @@
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
+ */ /**
18
+ * The properties a published component or layout declares (AGL-2933), held to
19
+ * the marketplace sanitizer before they reach another org's site.
20
+ *
21
+ * A declaration is publisher-written data that renders inside the installer's
22
+ * console and, through `{{prop.*}}`, on their live pages: a Link default
23
+ * becomes an `href`, an Image default a `src`, a Formatted document default a
24
+ * body, and labels and help text are drawn in the Attributes panel. Each is
25
+ * checked by the rule the published tree's own values meet.
26
+ *
27
+ * **A refused default becomes no default; the property is kept.** Its field
28
+ * still shows on every instance and its `{{prop.*}}` still resolves, empty.
29
+ * Dropping the property instead would leave every binding to it rendering as
30
+ * a raw token and every page value stored under its name orphaned — a bad
31
+ * default is not a reason to break the component around it. The same goes
32
+ * for a refused label, help text or option label: the text is cleared and
33
+ * the property, or the option, stays.
34
+ *
35
+ * Not re-exported from the model barrel: this reaches the author-HTML
36
+ * sanitizer, which no browser bundle that imports the listing model needs.
37
+ * Publish, install and update import it by path.
38
+ */ import { sanitizeAuthorHtml } from "@aglyn/aglyn/app-utils/author-html";
39
+ import { COMPONENT_PROP_NAME_PATTERN } from "@aglyn/aglyn/app-utils/reusable-component-keys";
40
+ import { reusablePropPatternProblem } from "@aglyn/aglyn/app-utils/reusable-prop-values";
41
+ import { FieldComponentType } from "@aglyn/aglyn/foundation/definitions/components.types";
42
+ import { isReusablePropType, reusablePropKind, reusablePropTakesSeveral } from "@aglyn/aglyn/foundation/definitions/property-kinds";
43
+ import { MARKETPLACE_DEFINITION_MAX_BYTES, MARKETPLACE_SAFE_HREF, MARKETPLACE_SAFE_SRC } from "./marketplace.js";
44
+ /** The most properties one published component or layout may declare. */ export const MARKETPLACE_PROPS_MAX_COUNT = 200;
45
+ const LABEL_MAX_LENGTH = 200;
46
+ const DESCRIPTION_MAX_LENGTH = 1000;
47
+ const TEXT_DEFAULT_MAX_LENGTH = 10000;
48
+ const DOCUMENT_DEFAULT_MAX_LENGTH = 50000;
49
+ const SETTING_STRING_MAX_LENGTH = 200;
50
+ const CONDITION_MAX_DEPTH = 8;
51
+ /** An icon id as the catalog names one: `mdiRocket`. */ const ICON_ID = /^[A-Za-z][A-Za-z0-9_-]{0,99}$/;
52
+ /** SVG path data and nothing else — the only thing an icon path is drawn as. */ const SVG_PATH_DATA = /^[MmZzLlHhVvCcSsQqTtAa0-9eE.,+\-\s]{1,20000}$/;
53
+ /**
54
+ * Markup in text that is only ever drawn as text. Refused rather than escaped:
55
+ * a label is not somewhere markup belongs, so its presence says the value was
56
+ * written for some other reader.
57
+ */ const MARKUP = /<[A-Za-z!/?]/;
58
+ /**
59
+ * A scheme a browser will execute, spelled the way a browser reads it — with
60
+ * the C0 controls and spaces it strips while resolving one removed first, so
61
+ * `java\tscript:` is caught.
62
+ */ function startsWithScriptScheme(value) {
63
+ // eslint-disable-next-line no-control-regex
64
+ const stripped = value.replace(/[\u0000-\u0020\u007f]/g, '').toLowerCase();
65
+ return /^(javascript|vbscript|livescript):/.test(stripped) || /^data:(text\/html|application\/xhtml|image\/svg)/.test(stripped);
66
+ }
67
+ /**
68
+ * CSS a Style property's value could smuggle into a declaration: a fetched
69
+ * resource, a script-bearing legacy expression, an import, or the punctuation
70
+ * that ends one declaration and starts another.
71
+ */ const UNSAFE_STYLE_VALUE = /url\s*\(|expression\s*\(|@import|[;{}<>]|\\/i;
72
+ /** Markdown link and image targets: inline `](…)` and reference `[id]: …`. */ const MARKDOWN_INLINE_TARGET = /\]\(\s*<?([^)\s>]*)/g;
73
+ const MARKDOWN_REFERENCE_TARGET = /^\s{0,3}\[[^\]]+\]:\s*<?(\S*?)>?(?:\s|$)/gm;
74
+ /** A text field's value if it is plain text within `max`, else nothing. */ function plainText(value, max) {
75
+ if (typeof value !== 'string') return undefined;
76
+ if (value.length > max || MARKUP.test(value)) return undefined;
77
+ return value;
78
+ }
79
+ /**
80
+ * Whether a Long text or Formatted document default is one the installer can
81
+ * be handed: no markup the author-HTML sanitizer would strip, and no link or
82
+ * image target with a scheme a browser would execute.
83
+ *
84
+ * A test, not a transform: a default the sanitizer would have to rewrite is
85
+ * not what the publisher wrote, so it is refused whole rather than stored as
86
+ * someone's guess at what was meant.
87
+ */ function isSafeDocument(value) {
88
+ if (value.length > DOCUMENT_DEFAULT_MAX_LENGTH) return false;
89
+ if (value.includes('<')) {
90
+ const removals = [];
91
+ sanitizeAuthorHtml(value, removals);
92
+ if (removals.length) return false;
93
+ }
94
+ for (const match of value.matchAll(MARKDOWN_INLINE_TARGET)){
95
+ if (match[1] && startsWithScriptScheme(match[1])) return false;
96
+ }
97
+ for (const match of value.matchAll(MARKDOWN_REFERENCE_TARGET)){
98
+ if (match[1] && startsWithScriptScheme(match[1])) return false;
99
+ }
100
+ return !startsWithScriptScheme(value);
101
+ }
102
+ /**
103
+ * A stored property value of a kind with no rule of its own: text, a number,
104
+ * a Yes / no, or a list of texts and numbers — the shapes
105
+ * `ReusableComponentPropValue` admits besides an icon — each text passing
106
+ * `stringOk`. `undefined` when it is anything else.
107
+ */ function plainValue(value, stringOk) {
108
+ const isText = (entry)=>typeof entry === 'string' && entry.length <= TEXT_DEFAULT_MAX_LENGTH && stringOk(entry);
109
+ const isNumber = (entry)=>typeof entry === 'number' && Number.isFinite(entry);
110
+ if (isText(value) || isNumber(value) || typeof value === 'boolean') {
111
+ return value;
112
+ }
113
+ if (Array.isArray(value) && value.every((entry)=>isText(entry) || isNumber(entry))) {
114
+ return [
115
+ ...value
116
+ ];
117
+ }
118
+ return undefined;
119
+ }
120
+ /** One answer or a list of answers, as the property's kind takes them. */ function answers(value, several) {
121
+ const isAnswer = (entry)=>typeof entry === 'string' && entry.length <= TEXT_DEFAULT_MAX_LENGTH && !startsWithScriptScheme(entry) || typeof entry === 'number' && Number.isFinite(entry);
122
+ if (Array.isArray(value)) {
123
+ return several && value.every(isAnswer) ? [
124
+ ...value
125
+ ] : undefined;
126
+ }
127
+ return isAnswer(value) ? value : undefined;
128
+ }
129
+ /**
130
+ * A declaration's default held to its kind's rule: the value to store, or
131
+ * `undefined` when the default is refused. `iconPath` rides along for an Icon.
132
+ */ function sanitizeDefault(prop, value, iconPath) {
133
+ var _prop_type;
134
+ const kind = reusablePropKind(prop.type);
135
+ switch((_prop_type = prop.type) != null ? _prop_type : 'text'){
136
+ case 'href':
137
+ {
138
+ if (typeof value !== 'string') return undefined;
139
+ const trimmed = value.trim();
140
+ return MARKETPLACE_SAFE_HREF.test(trimmed) ? {
141
+ value: trimmed
142
+ } : undefined;
143
+ }
144
+ case 'image':
145
+ {
146
+ if (typeof value !== 'string') return undefined;
147
+ const trimmed = value.trim();
148
+ return MARKETPLACE_SAFE_SRC.test(trimmed) ? {
149
+ value: trimmed
150
+ } : undefined;
151
+ }
152
+ case 'richText':
153
+ case FieldComponentType.MARKDOWN:
154
+ return typeof value === 'string' && isSafeDocument(value) ? {
155
+ value
156
+ } : undefined;
157
+ case 'icon':
158
+ {
159
+ if (typeof value !== 'string' || !ICON_ID.test(value)) return undefined;
160
+ if (iconPath === undefined || iconPath === null || iconPath === '') {
161
+ return {
162
+ value
163
+ };
164
+ }
165
+ return typeof iconPath === 'string' && SVG_PATH_DATA.test(iconPath) ? {
166
+ value,
167
+ iconPath
168
+ } : undefined;
169
+ }
170
+ case 'text':
171
+ {
172
+ if (typeof value === 'number' || typeof value === 'boolean') {
173
+ return {
174
+ value
175
+ };
176
+ }
177
+ return typeof value === 'string' && value.length <= TEXT_DEFAULT_MAX_LENGTH && !startsWithScriptScheme(value) ? {
178
+ value
179
+ } : undefined;
180
+ }
181
+ }
182
+ switch(kind.value){
183
+ case 'number':
184
+ {
185
+ if (typeof value === 'number') {
186
+ return Number.isFinite(value) ? {
187
+ value
188
+ } : undefined;
189
+ }
190
+ return typeof value === 'string' && value.trim() !== '' && Number.isFinite(Number(value)) ? {
191
+ value
192
+ } : undefined;
193
+ }
194
+ case 'boolean':
195
+ {
196
+ if (reusablePropTakesSeveral(prop)) {
197
+ const list = answers(value, true);
198
+ return list === undefined ? undefined : {
199
+ value: list
200
+ };
201
+ }
202
+ return typeof value === 'boolean' || typeof value === 'string' && value.length <= 10 || typeof value === 'number' && Number.isFinite(value) ? {
203
+ value
204
+ } : undefined;
205
+ }
206
+ }
207
+ if (kind.options) {
208
+ const list = answers(value, reusablePropTakesSeveral(prop));
209
+ return list === undefined ? undefined : {
210
+ value: list
211
+ };
212
+ }
213
+ const stringOk = kind.group === 'Style' ? (text)=>!UNSAFE_STYLE_VALUE.test(text) && !startsWithScriptScheme(text) : (text)=>!startsWithScriptScheme(text);
214
+ const safe = plainValue(value, stringOk);
215
+ return safe === undefined ? undefined : {
216
+ value: safe
217
+ };
218
+ }
219
+ /** The answers a property offers, each with a value; a refused label is cleared. */ function sanitizeOptions(raw) {
220
+ if (!Array.isArray(raw)) return undefined;
221
+ const options = [];
222
+ for (const entry of raw){
223
+ if (!entry || typeof entry !== 'object') continue;
224
+ const rawValue = entry.value;
225
+ const value = typeof rawValue === 'number' && Number.isFinite(rawValue) ? String(rawValue) : rawValue;
226
+ if (typeof value !== 'string' || value.length > SETTING_STRING_MAX_LENGTH) {
227
+ continue;
228
+ }
229
+ const label = plainText(entry.label, LABEL_MAX_LENGTH);
230
+ options.push(label === undefined ? {
231
+ value
232
+ } : {
233
+ value,
234
+ label
235
+ });
236
+ }
237
+ return options;
238
+ }
239
+ /** A kind's settings: flat, primitive, and short. */ function sanitizeSettings(raw) {
240
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return undefined;
241
+ const settings = {};
242
+ for (const [key, value] of Object.entries(raw)){
243
+ if (key.startsWith('__') || key.length > 64) continue;
244
+ if (typeof value === 'boolean') settings[key] = value;
245
+ else if (typeof value === 'number' && Number.isFinite(value)) settings[key] = value;
246
+ else if (typeof value === 'string') {
247
+ const text = plainText(value, SETTING_STRING_MAX_LENGTH);
248
+ if (text !== undefined) settings[key] = text;
249
+ }
250
+ }
251
+ return settings;
252
+ }
253
+ const RULE_PRIMITIVE_KEYS = [
254
+ 'notMatch',
255
+ 'isEmpty',
256
+ 'isNotEmpty'
257
+ ];
258
+ const RULE_NUMBER_KEYS = [
259
+ 'greaterThan',
260
+ 'greaterThanOrEqualTo',
261
+ 'lessThan',
262
+ 'lessThanOrEqualTo'
263
+ ];
264
+ /** A condition's serializable shape, rebuilt key by key. */ function sanitizeCondition(raw, depth = 0) {
265
+ if (depth > CONDITION_MAX_DEPTH || !raw || typeof raw !== 'object') {
266
+ return undefined;
267
+ }
268
+ if (Array.isArray(raw)) {
269
+ const list = raw.map((entry)=>sanitizeCondition(entry, depth + 1)).filter((entry)=>Boolean(entry) && !Array.isArray(entry));
270
+ return list.length ? list : undefined;
271
+ }
272
+ const value = raw;
273
+ for (const key of [
274
+ 'and',
275
+ 'or'
276
+ ]){
277
+ if (key in value) {
278
+ const list = sanitizeCondition(value[key], depth + 1);
279
+ if (!list) return undefined;
280
+ return {
281
+ [key]: Array.isArray(list) ? list : [
282
+ list
283
+ ]
284
+ };
285
+ }
286
+ }
287
+ if ('not' in value) {
288
+ const inner = sanitizeCondition(value['not'], depth + 1);
289
+ return inner ? {
290
+ not: inner
291
+ } : undefined;
292
+ }
293
+ if (typeof value['when'] !== 'string' || !COMPONENT_PROP_NAME_PATTERN.test(value['when'])) {
294
+ return undefined;
295
+ }
296
+ const rule = {
297
+ when: value['when']
298
+ };
299
+ const is = value['is'];
300
+ if (typeof is === 'string' || typeof is === 'boolean' || typeof is === 'number' && Number.isFinite(is)) {
301
+ rule.is = is;
302
+ } else if (Array.isArray(is) && is.every((entry)=>[
303
+ 'string',
304
+ 'number',
305
+ 'boolean'
306
+ ].includes(typeof entry))) {
307
+ rule.is = [
308
+ ...is
309
+ ];
310
+ }
311
+ for (const key of RULE_PRIMITIVE_KEYS){
312
+ if (typeof value[key] === 'boolean') rule[key] = value[key];
313
+ }
314
+ for (const key of RULE_NUMBER_KEYS){
315
+ const entry = value[key];
316
+ if (typeof entry === 'number' && Number.isFinite(entry)) rule[key] = entry;
317
+ }
318
+ // A pattern every page can match, with its flags, or no rule at all: the
319
+ // rest of a pattern rule means nothing without it, and a pattern no page can
320
+ // match holds nothing wherever it is evaluated (AGL-2893).
321
+ if (value['pattern']) {
322
+ if (reusablePropPatternProblem(value['pattern'], value['flags'])) {
323
+ return undefined;
324
+ }
325
+ rule.pattern = value['pattern'];
326
+ if (value['flags']) rule.flags = value['flags'];
327
+ }
328
+ return rule;
329
+ }
330
+ /**
331
+ * Holds a published component's or layout's declared properties to the
332
+ * marketplace sanitizer.
333
+ *
334
+ * Every property with a usable name is kept, in order, with only the keys a
335
+ * declaration has. What each default, label, help text and option label must
336
+ * satisfy is the rule the published tree's own values meet — see the module
337
+ * comment — and whatever fails it is cleared rather than taken as grounds to
338
+ * lose the property. An entry with no usable name is skipped: nothing can
339
+ * bind to it, so it is not a property. A second entry with a name already
340
+ * taken is skipped for the same reason — bindings resolve to the first.
341
+ *
342
+ * Refuses outright only a declaration list too large to publish, which is
343
+ * the same answer the tree gets.
344
+ *
345
+ * Idempotent, so install and update run it again over what publish stored.
346
+ */ export function sanitizeMarketplaceProps(raw) {
347
+ if (!Array.isArray(raw)) return {
348
+ ok: true,
349
+ props: [],
350
+ clearedDefaults: []
351
+ };
352
+ if (raw.length > MARKETPLACE_PROPS_MAX_COUNT) {
353
+ return {
354
+ ok: false,
355
+ error: `This declares ${raw.length} properties — a listing may declare at ` + `most ${MARKETPLACE_PROPS_MAX_COUNT}.`
356
+ };
357
+ }
358
+ const props = [];
359
+ const clearedDefaults = [];
360
+ const seen = new Set();
361
+ for (const entry of raw){
362
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) continue;
363
+ const source = entry;
364
+ const name = source['name'];
365
+ if (typeof name !== 'string' || !COMPONENT_PROP_NAME_PATTERN.test(name)) {
366
+ continue;
367
+ }
368
+ if (seen.has(name)) continue;
369
+ seen.add(name);
370
+ const prop = {
371
+ name
372
+ };
373
+ // An unknown kind reads as Text everywhere, so it is kept as written and
374
+ // its default held to Text's rule by `reusablePropKind`.
375
+ if (typeof source['type'] === 'string' && source['type'].length <= 64) {
376
+ prop.type = source['type'];
377
+ }
378
+ const label = plainText(source['label'], LABEL_MAX_LENGTH);
379
+ if (label !== undefined) prop.label = label;
380
+ const description = plainText(source['description'], DESCRIPTION_MAX_LENGTH);
381
+ if (description !== undefined) prop.description = description;
382
+ const options = sanitizeOptions(source['options']);
383
+ if (options) prop.options = options;
384
+ const settings = sanitizeSettings(source['settings']);
385
+ if (settings) prop.settings = settings;
386
+ const condition = sanitizeCondition(source['condition']);
387
+ if (condition) prop.condition = condition;
388
+ const rawDefault = source['defaultValue'];
389
+ if (rawDefault !== undefined && rawDefault !== null) {
390
+ const kindProp = isReusablePropType(prop.type) ? prop : _extends({}, prop, {
391
+ type: 'text'
392
+ });
393
+ const safe = sanitizeDefault(kindProp, rawDefault, source['defaultIconPath']);
394
+ if (safe === undefined) {
395
+ clearedDefaults.push(name);
396
+ } else {
397
+ prop.defaultValue = safe.value;
398
+ if (safe.iconPath) prop.defaultIconPath = safe.iconPath;
399
+ }
400
+ }
401
+ props.push(prop);
402
+ }
403
+ let serialized;
404
+ try {
405
+ serialized = JSON.stringify(props);
406
+ } catch (unused) {
407
+ return {
408
+ ok: false,
409
+ error: 'Properties are not serializable'
410
+ };
411
+ }
412
+ if (serialized.length > MARKETPLACE_DEFINITION_MAX_BYTES) {
413
+ return {
414
+ ok: false,
415
+ error: 'Properties are too large to publish'
416
+ };
417
+ }
418
+ return {
419
+ ok: true,
420
+ props,
421
+ clearedDefaults
422
+ };
423
+ }
424
+ /**
425
+ * The properties a stored listing version carries, re-held to the sanitizer,
426
+ * or `undefined` for a version published before properties were carried.
427
+ *
428
+ * The distinction is what install and update act on: a version with a list —
429
+ * even an empty one — says what the component declares, so it replaces what
430
+ * the installed copy has; a version with none says nothing, so the installed
431
+ * copy keeps its own.
432
+ */ export function readPublishedProps(raw) {
433
+ if (!Array.isArray(raw)) return undefined;
434
+ const sanitized = sanitizeMarketplaceProps(raw);
435
+ // Publish refused anything too large, so a stored list that is must have
436
+ // been written some other way; it says nothing trustworthy about what the
437
+ // component declares, and is treated as saying nothing.
438
+ return sanitized.ok ? sanitized.props : undefined;
439
+ }
440
+
441
+ //# sourceMappingURL=marketplace-props.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/marketplace/src/lib/model/marketplace-props.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 * The properties a published component or layout declares (AGL-2933), held to\n * the marketplace sanitizer before they reach another org's site.\n *\n * A declaration is publisher-written data that renders inside the installer's\n * console and, through `{{prop.*}}`, on their live pages: a Link default\n * becomes an `href`, an Image default a `src`, a Formatted document default a\n * body, and labels and help text are drawn in the Attributes panel. Each is\n * checked by the rule the published tree's own values meet.\n *\n * **A refused default becomes no default; the property is kept.** Its field\n * still shows on every instance and its `{{prop.*}}` still resolves, empty.\n * Dropping the property instead would leave every binding to it rendering as\n * a raw token and every page value stored under its name orphaned — a bad\n * default is not a reason to break the component around it. The same goes\n * for a refused label, help text or option label: the text is cleared and\n * the property, or the option, stays.\n *\n * Not re-exported from the model barrel: this reaches the author-HTML\n * sanitizer, which no browser bundle that imports the listing model needs.\n * Publish, install and update import it by path.\n */\n\nimport {\n sanitizeAuthorHtml,\n type AuthorHtmlRemoval,\n} from '@aglyn/aglyn/app-utils/author-html'\nimport { COMPONENT_PROP_NAME_PATTERN } from '@aglyn/aglyn/app-utils/reusable-component-keys'\nimport { reusablePropPatternProblem } from '@aglyn/aglyn/app-utils/reusable-prop-values'\nimport { FieldComponentType } from '@aglyn/aglyn/foundation/definitions/components.types'\nimport {\n isReusablePropType,\n reusablePropKind,\n reusablePropTakesSeveral,\n} from '@aglyn/aglyn/foundation/definitions/property-kinds'\nimport type {\n ReusableComponentProp,\n ReusableComponentPropCondition,\n ReusableComponentPropOption,\n ReusableComponentPropRule,\n} from '@aglyn/aglyn/foundation/definitions/platform.types'\nimport {\n MARKETPLACE_DEFINITION_MAX_BYTES,\n MARKETPLACE_SAFE_HREF,\n MARKETPLACE_SAFE_SRC,\n} from './marketplace'\n\n/** The most properties one published component or layout may declare. */\nexport const MARKETPLACE_PROPS_MAX_COUNT = 200\n\nconst LABEL_MAX_LENGTH = 200\nconst DESCRIPTION_MAX_LENGTH = 1000\nconst TEXT_DEFAULT_MAX_LENGTH = 10_000\nconst DOCUMENT_DEFAULT_MAX_LENGTH = 50_000\nconst SETTING_STRING_MAX_LENGTH = 200\nconst CONDITION_MAX_DEPTH = 8\n\n/** An icon id as the catalog names one: `mdiRocket`. */\nconst ICON_ID = /^[A-Za-z][A-Za-z0-9_-]{0,99}$/\n\n/** SVG path data and nothing else — the only thing an icon path is drawn as. */\nconst SVG_PATH_DATA = /^[MmZzLlHhVvCcSsQqTtAa0-9eE.,+\\-\\s]{1,20000}$/\n\n/**\n * Markup in text that is only ever drawn as text. Refused rather than escaped:\n * a label is not somewhere markup belongs, so its presence says the value was\n * written for some other reader.\n */\nconst MARKUP = /<[A-Za-z!/?]/\n\n/**\n * A scheme a browser will execute, spelled the way a browser reads it — with\n * the C0 controls and spaces it strips while resolving one removed first, so\n * `java\\tscript:` is caught.\n */\nfunction startsWithScriptScheme(value: string): boolean {\n // eslint-disable-next-line no-control-regex\n const stripped = value.replace(/[\\u0000-\\u0020\\u007f]/g, '').toLowerCase()\n return (\n /^(javascript|vbscript|livescript):/.test(stripped) ||\n /^data:(text\\/html|application\\/xhtml|image\\/svg)/.test(stripped)\n )\n}\n\n/**\n * CSS a Style property's value could smuggle into a declaration: a fetched\n * resource, a script-bearing legacy expression, an import, or the punctuation\n * that ends one declaration and starts another.\n */\nconst UNSAFE_STYLE_VALUE = /url\\s*\\(|expression\\s*\\(|@import|[;{}<>]|\\\\/i\n\n/** Markdown link and image targets: inline `](…)` and reference `[id]: …`. */\nconst MARKDOWN_INLINE_TARGET = /\\]\\(\\s*<?([^)\\s>]*)/g\nconst MARKDOWN_REFERENCE_TARGET = /^\\s{0,3}\\[[^\\]]+\\]:\\s*<?(\\S*?)>?(?:\\s|$)/gm\n\n/** The sanitized declarations, or why the list was refused outright. */\nexport type MarketplacePropsResult =\n | {\n ok: true\n props: ReusableComponentProp[]\n /** Names of the properties whose default was refused and cleared. */\n clearedDefaults: string[]\n }\n | { ok: false; error: string }\n\n/** A text field's value if it is plain text within `max`, else nothing. */\nfunction plainText(value: unknown, max: number): string | undefined {\n if (typeof value !== 'string') return undefined\n if (value.length > max || MARKUP.test(value)) return undefined\n return value\n}\n\n/**\n * Whether a Long text or Formatted document default is one the installer can\n * be handed: no markup the author-HTML sanitizer would strip, and no link or\n * image target with a scheme a browser would execute.\n *\n * A test, not a transform: a default the sanitizer would have to rewrite is\n * not what the publisher wrote, so it is refused whole rather than stored as\n * someone's guess at what was meant.\n */\nfunction isSafeDocument(value: string): boolean {\n if (value.length > DOCUMENT_DEFAULT_MAX_LENGTH) return false\n if (value.includes('<')) {\n const removals: AuthorHtmlRemoval[] = []\n sanitizeAuthorHtml(value, removals)\n if (removals.length) return false\n }\n for (const match of value.matchAll(MARKDOWN_INLINE_TARGET)) {\n if (match[1] && startsWithScriptScheme(match[1])) return false\n }\n for (const match of value.matchAll(MARKDOWN_REFERENCE_TARGET)) {\n if (match[1] && startsWithScriptScheme(match[1])) return false\n }\n return !startsWithScriptScheme(value)\n}\n\n/**\n * A stored property value of a kind with no rule of its own: text, a number,\n * a Yes / no, or a list of texts and numbers — the shapes\n * `ReusableComponentPropValue` admits besides an icon — each text passing\n * `stringOk`. `undefined` when it is anything else.\n */\nfunction plainValue(\n value: unknown,\n stringOk: (text: string) => boolean,\n): unknown {\n const isText = (entry: unknown): entry is string =>\n typeof entry === 'string' &&\n entry.length <= TEXT_DEFAULT_MAX_LENGTH &&\n stringOk(entry)\n const isNumber = (entry: unknown): entry is number =>\n typeof entry === 'number' && Number.isFinite(entry)\n if (isText(value) || isNumber(value) || typeof value === 'boolean') {\n return value\n }\n if (Array.isArray(value) && value.every((entry) => isText(entry) || isNumber(entry))) {\n return [...value]\n }\n return undefined\n}\n\n/** One answer or a list of answers, as the property's kind takes them. */\nfunction answers(\n value: unknown,\n several: boolean,\n): unknown {\n const isAnswer = (entry: unknown) =>\n (typeof entry === 'string' &&\n entry.length <= TEXT_DEFAULT_MAX_LENGTH &&\n !startsWithScriptScheme(entry)) ||\n (typeof entry === 'number' && Number.isFinite(entry))\n if (Array.isArray(value)) {\n return several && value.every(isAnswer) ? [...value] : undefined\n }\n return isAnswer(value) ? value : undefined\n}\n\n/**\n * A declaration's default held to its kind's rule: the value to store, or\n * `undefined` when the default is refused. `iconPath` rides along for an Icon.\n */\nfunction sanitizeDefault(\n prop: Pick<ReusableComponentProp, 'type' | 'options' | 'settings'>,\n value: unknown,\n iconPath: unknown,\n): { value: unknown; iconPath?: string } | undefined {\n const kind = reusablePropKind(prop.type)\n switch (prop.type ?? 'text') {\n case 'href': {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n return MARKETPLACE_SAFE_HREF.test(trimmed) ? { value: trimmed } : undefined\n }\n case 'image': {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n return MARKETPLACE_SAFE_SRC.test(trimmed) ? { value: trimmed } : undefined\n }\n case 'richText':\n case FieldComponentType.MARKDOWN:\n return typeof value === 'string' && isSafeDocument(value)\n ? { value }\n : undefined\n case 'icon': {\n if (typeof value !== 'string' || !ICON_ID.test(value)) return undefined\n if (iconPath === undefined || iconPath === null || iconPath === '') {\n return { value }\n }\n return typeof iconPath === 'string' && SVG_PATH_DATA.test(iconPath)\n ? { value, iconPath }\n : undefined\n }\n case 'text': {\n if (typeof value === 'number' || typeof value === 'boolean') {\n return { value }\n }\n return typeof value === 'string' &&\n value.length <= TEXT_DEFAULT_MAX_LENGTH &&\n !startsWithScriptScheme(value)\n ? { value }\n : undefined\n }\n }\n switch (kind.value) {\n case 'number': {\n if (typeof value === 'number') {\n return Number.isFinite(value) ? { value } : undefined\n }\n return typeof value === 'string' &&\n value.trim() !== '' &&\n Number.isFinite(Number(value))\n ? { value }\n : undefined\n }\n case 'boolean': {\n if (reusablePropTakesSeveral(prop)) {\n const list = answers(value, true)\n return list === undefined ? undefined : { value: list }\n }\n return typeof value === 'boolean' ||\n (typeof value === 'string' && value.length <= 10) ||\n (typeof value === 'number' && Number.isFinite(value))\n ? { value }\n : undefined\n }\n }\n if (kind.options) {\n const list = answers(value, reusablePropTakesSeveral(prop))\n return list === undefined ? undefined : { value: list }\n }\n const stringOk =\n kind.group === 'Style'\n ? (text: string) => !UNSAFE_STYLE_VALUE.test(text) && !startsWithScriptScheme(text)\n : (text: string) => !startsWithScriptScheme(text)\n const safe = plainValue(value, stringOk)\n return safe === undefined ? undefined : { value: safe }\n}\n\n/** The answers a property offers, each with a value; a refused label is cleared. */\nfunction sanitizeOptions(raw: unknown): ReusableComponentPropOption[] | undefined {\n if (!Array.isArray(raw)) return undefined\n const options: ReusableComponentPropOption[] = []\n for (const entry of raw) {\n if (!entry || typeof entry !== 'object') continue\n const rawValue = (entry as { value?: unknown }).value\n const value =\n typeof rawValue === 'number' && Number.isFinite(rawValue)\n ? String(rawValue)\n : rawValue\n if (typeof value !== 'string' || value.length > SETTING_STRING_MAX_LENGTH) {\n continue\n }\n const label = plainText((entry as { label?: unknown }).label, LABEL_MAX_LENGTH)\n options.push(label === undefined ? { value } : { value, label })\n }\n return options\n}\n\n/** A kind's settings: flat, primitive, and short. */\nfunction sanitizeSettings(\n raw: unknown,\n): Record<string, string | number | boolean> | undefined {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return undefined\n const settings: Record<string, string | number | boolean> = {}\n for (const [key, value] of Object.entries(raw)) {\n if (key.startsWith('__') || key.length > 64) continue\n if (typeof value === 'boolean') settings[key] = value\n else if (typeof value === 'number' && Number.isFinite(value)) settings[key] = value\n else if (typeof value === 'string') {\n const text = plainText(value, SETTING_STRING_MAX_LENGTH)\n if (text !== undefined) settings[key] = text\n }\n }\n return settings\n}\n\nconst RULE_PRIMITIVE_KEYS = ['notMatch', 'isEmpty', 'isNotEmpty'] as const\nconst RULE_NUMBER_KEYS = [\n 'greaterThan',\n 'greaterThanOrEqualTo',\n 'lessThan',\n 'lessThanOrEqualTo',\n] as const\n\n/** A condition's serializable shape, rebuilt key by key. */\nfunction sanitizeCondition(\n raw: unknown,\n depth = 0,\n): ReusableComponentPropCondition | ReusableComponentPropCondition[] | undefined {\n if (depth > CONDITION_MAX_DEPTH || !raw || typeof raw !== 'object') {\n return undefined\n }\n if (Array.isArray(raw)) {\n const list = raw\n .map((entry) => sanitizeCondition(entry, depth + 1))\n .filter((entry): entry is ReusableComponentPropCondition =>\n Boolean(entry) && !Array.isArray(entry),\n )\n return list.length ? list : undefined\n }\n const value = raw as Record<string, unknown>\n for (const key of ['and', 'or'] as const) {\n if (key in value) {\n const list = sanitizeCondition(value[key], depth + 1)\n if (!list) return undefined\n return { [key]: Array.isArray(list) ? list : [list] } as ReusableComponentPropCondition\n }\n }\n if ('not' in value) {\n const inner = sanitizeCondition(value['not'], depth + 1)\n return inner ? { not: inner } : undefined\n }\n if (typeof value['when'] !== 'string' || !COMPONENT_PROP_NAME_PATTERN.test(value['when'])) {\n return undefined\n }\n const rule: ReusableComponentPropRule = { when: value['when'] }\n const is = value['is']\n if (\n typeof is === 'string' ||\n typeof is === 'boolean' ||\n (typeof is === 'number' && Number.isFinite(is))\n ) {\n rule.is = is\n } else if (\n Array.isArray(is) &&\n is.every((entry) => ['string', 'number', 'boolean'].includes(typeof entry))\n ) {\n rule.is = [...is]\n }\n for (const key of RULE_PRIMITIVE_KEYS) {\n if (typeof value[key] === 'boolean') rule[key] = value[key] as boolean\n }\n for (const key of RULE_NUMBER_KEYS) {\n const entry = value[key]\n if (typeof entry === 'number' && Number.isFinite(entry)) rule[key] = entry\n }\n // A pattern every page can match, with its flags, or no rule at all: the\n // rest of a pattern rule means nothing without it, and a pattern no page can\n // match holds nothing wherever it is evaluated (AGL-2893).\n if (value['pattern']) {\n if (reusablePropPatternProblem(value['pattern'], value['flags'])) {\n return undefined\n }\n rule.pattern = value['pattern'] as string\n if (value['flags']) rule.flags = value['flags'] as string\n }\n return rule\n}\n\n/**\n * Holds a published component's or layout's declared properties to the\n * marketplace sanitizer.\n *\n * Every property with a usable name is kept, in order, with only the keys a\n * declaration has. What each default, label, help text and option label must\n * satisfy is the rule the published tree's own values meet — see the module\n * comment — and whatever fails it is cleared rather than taken as grounds to\n * lose the property. An entry with no usable name is skipped: nothing can\n * bind to it, so it is not a property. A second entry with a name already\n * taken is skipped for the same reason — bindings resolve to the first.\n *\n * Refuses outright only a declaration list too large to publish, which is\n * the same answer the tree gets.\n *\n * Idempotent, so install and update run it again over what publish stored.\n */\nexport function sanitizeMarketplaceProps(raw: unknown): MarketplacePropsResult {\n if (!Array.isArray(raw)) return { ok: true, props: [], clearedDefaults: [] }\n if (raw.length > MARKETPLACE_PROPS_MAX_COUNT) {\n return {\n ok: false,\n error:\n `This declares ${raw.length} properties — a listing may declare at ` +\n `most ${MARKETPLACE_PROPS_MAX_COUNT}.`,\n }\n }\n const props: ReusableComponentProp[] = []\n const clearedDefaults: string[] = []\n const seen = new Set<string>()\n for (const entry of raw) {\n if (!entry || typeof entry !== 'object' || Array.isArray(entry)) continue\n const source = entry as Record<string, unknown>\n const name = source['name']\n if (typeof name !== 'string' || !COMPONENT_PROP_NAME_PATTERN.test(name)) {\n continue\n }\n if (seen.has(name)) continue\n seen.add(name)\n\n const prop: ReusableComponentProp = { name }\n // An unknown kind reads as Text everywhere, so it is kept as written and\n // its default held to Text's rule by `reusablePropKind`.\n if (typeof source['type'] === 'string' && source['type'].length <= 64) {\n prop.type = source['type'] as ReusableComponentProp['type']\n }\n const label = plainText(source['label'], LABEL_MAX_LENGTH)\n if (label !== undefined) prop.label = label\n const description = plainText(source['description'], DESCRIPTION_MAX_LENGTH)\n if (description !== undefined) prop.description = description\n const options = sanitizeOptions(source['options'])\n if (options) prop.options = options\n const settings = sanitizeSettings(source['settings'])\n if (settings) prop.settings = settings\n const condition = sanitizeCondition(source['condition'])\n if (condition) prop.condition = condition\n\n const rawDefault = source['defaultValue']\n if (rawDefault !== undefined && rawDefault !== null) {\n const kindProp = isReusablePropType(prop.type) ? prop : { ...prop, type: 'text' as const }\n const safe = sanitizeDefault(kindProp, rawDefault, source['defaultIconPath'])\n if (safe === undefined) {\n clearedDefaults.push(name)\n } else {\n prop.defaultValue = safe.value as ReusableComponentProp['defaultValue']\n if (safe.iconPath) prop.defaultIconPath = safe.iconPath\n }\n }\n props.push(prop)\n }\n let serialized: string\n try {\n serialized = JSON.stringify(props)\n } catch {\n return { ok: false, error: 'Properties are not serializable' }\n }\n if (serialized.length > MARKETPLACE_DEFINITION_MAX_BYTES) {\n return { ok: false, error: 'Properties are too large to publish' }\n }\n return { ok: true, props, clearedDefaults }\n}\n\n/**\n * The properties a stored listing version carries, re-held to the sanitizer,\n * or `undefined` for a version published before properties were carried.\n *\n * The distinction is what install and update act on: a version with a list —\n * even an empty one — says what the component declares, so it replaces what\n * the installed copy has; a version with none says nothing, so the installed\n * copy keeps its own.\n */\nexport function readPublishedProps(\n raw: unknown,\n): ReusableComponentProp[] | undefined {\n if (!Array.isArray(raw)) return undefined\n const sanitized = sanitizeMarketplaceProps(raw)\n // Publish refused anything too large, so a stored list that is must have\n // been written some other way; it says nothing trustworthy about what the\n // component declares, and is treated as saying nothing.\n return sanitized.ok ? sanitized.props : undefined\n}\n"],"names":["sanitizeAuthorHtml","COMPONENT_PROP_NAME_PATTERN","reusablePropPatternProblem","FieldComponentType","isReusablePropType","reusablePropKind","reusablePropTakesSeveral","MARKETPLACE_DEFINITION_MAX_BYTES","MARKETPLACE_SAFE_HREF","MARKETPLACE_SAFE_SRC","MARKETPLACE_PROPS_MAX_COUNT","LABEL_MAX_LENGTH","DESCRIPTION_MAX_LENGTH","TEXT_DEFAULT_MAX_LENGTH","DOCUMENT_DEFAULT_MAX_LENGTH","SETTING_STRING_MAX_LENGTH","CONDITION_MAX_DEPTH","ICON_ID","SVG_PATH_DATA","MARKUP","startsWithScriptScheme","value","stripped","replace","toLowerCase","test","UNSAFE_STYLE_VALUE","MARKDOWN_INLINE_TARGET","MARKDOWN_REFERENCE_TARGET","plainText","max","undefined","length","isSafeDocument","includes","removals","match","matchAll","plainValue","stringOk","isText","entry","isNumber","Number","isFinite","Array","isArray","every","answers","several","isAnswer","sanitizeDefault","prop","iconPath","kind","type","trimmed","trim","MARKDOWN","list","options","group","text","safe","sanitizeOptions","raw","rawValue","String","label","push","sanitizeSettings","settings","key","Object","entries","startsWith","RULE_PRIMITIVE_KEYS","RULE_NUMBER_KEYS","sanitizeCondition","depth","map","filter","Boolean","inner","not","rule","when","is","pattern","flags","sanitizeMarketplaceProps","ok","props","clearedDefaults","error","seen","Set","source","name","has","add","description","condition","rawDefault","kindProp","defaultValue","defaultIconPath","serialized","JSON","stringify","readPublishedProps","sanitized"],"mappings":"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"}