@adea-ai/plugins 1.0.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 (79) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +74 -0
  3. package/dist/agent-plugins-catalog.d.ts +26 -0
  4. package/dist/agent-plugins-catalog.js +699 -0
  5. package/dist/agent-plugins-catalog.js.map +1 -0
  6. package/dist/agent-plugins-harness.d.ts +54 -0
  7. package/dist/agent-plugins-harness.js +212 -0
  8. package/dist/agent-plugins-harness.js.map +1 -0
  9. package/dist/agent-plugins-schema.d.ts +402 -0
  10. package/dist/agent-plugins-schema.js +200 -0
  11. package/dist/agent-plugins-schema.js.map +1 -0
  12. package/dist/consumer-index.d.ts +217 -0
  13. package/dist/consumer-index.js +358 -0
  14. package/dist/consumer-index.js.map +1 -0
  15. package/dist/display-name.d.ts +8 -0
  16. package/dist/display-name.js +160 -0
  17. package/dist/display-name.js.map +1 -0
  18. package/dist/harness.d.ts +13 -0
  19. package/dist/harness.js +169 -0
  20. package/dist/harness.js.map +1 -0
  21. package/dist/icon-mirror.d.ts +69 -0
  22. package/dist/icon-mirror.js +147 -0
  23. package/dist/icon-mirror.js.map +1 -0
  24. package/dist/icons.d.ts +65 -0
  25. package/dist/icons.js +268 -0
  26. package/dist/icons.js.map +1 -0
  27. package/dist/index.d.ts +304 -0
  28. package/dist/index.js +1877 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/portable-catalog.d.ts +9 -0
  31. package/dist/portable-catalog.js +175 -0
  32. package/dist/portable-catalog.js.map +1 -0
  33. package/dist/publication.d.ts +98 -0
  34. package/dist/publication.js +121 -0
  35. package/dist/publication.js.map +1 -0
  36. package/dist/schema.d.ts +705 -0
  37. package/dist/schema.js +267 -0
  38. package/dist/schema.js.map +1 -0
  39. package/dist/site-icons.d.ts +55 -0
  40. package/dist/site-icons.js +155 -0
  41. package/dist/site-icons.js.map +1 -0
  42. package/dist/sources.d.ts +54 -0
  43. package/dist/sources.js +306 -0
  44. package/dist/sources.js.map +1 -0
  45. package/package.json +102 -0
  46. package/schemas/agent-package.v1.json +387 -0
  47. package/schemas/catalog.v1.schema.json +407 -0
  48. package/schemas/compatibility.v1.schema.json +23 -0
  49. package/schemas/harness-profile.v1.json +75 -0
  50. package/schemas/installation-plan.v2.json +695 -0
  51. package/schemas/sources-lock.v1.schema.json +61 -0
  52. package/src/agent-plugins-catalog.test.ts +402 -0
  53. package/src/agent-plugins-catalog.ts +800 -0
  54. package/src/agent-plugins-harness.test.ts +272 -0
  55. package/src/agent-plugins-harness.ts +281 -0
  56. package/src/agent-plugins-schema.test.ts +27 -0
  57. package/src/agent-plugins-schema.ts +219 -0
  58. package/src/artifacts.test.ts +545 -0
  59. package/src/catalog-installation.test.ts +42 -0
  60. package/src/consumer-index.test.ts +465 -0
  61. package/src/consumer-index.ts +592 -0
  62. package/src/display-name.test.ts +56 -0
  63. package/src/display-name.ts +157 -0
  64. package/src/harness.ts +202 -0
  65. package/src/icon-mirror.ts +196 -0
  66. package/src/icons.test.ts +185 -0
  67. package/src/icons.ts +297 -0
  68. package/src/index.test.ts +888 -0
  69. package/src/index.ts +2538 -0
  70. package/src/portable-catalog.test.ts +186 -0
  71. package/src/portable-catalog.ts +203 -0
  72. package/src/publication.test.ts +117 -0
  73. package/src/publication.ts +171 -0
  74. package/src/schema.ts +309 -0
  75. package/src/site-icon-fallback.test.ts +267 -0
  76. package/src/site-icons.test.ts +171 -0
  77. package/src/site-icons.ts +161 -0
  78. package/src/sources.ts +360 -0
  79. package/src/upstream-headers.test.ts +148 -0
@@ -0,0 +1,217 @@
1
+ import type { Catalog } from './schema.js';
2
+ import { type IconContentType } from './icons.js';
3
+ /**
4
+ * Placement policy that decides which source variant represents a product.
5
+ * Trusted compiler configuration; never derived from upstream plugin content.
6
+ */
7
+ export interface ProductPreference {
8
+ readonly schemaVersion: 1;
9
+ readonly sourcePreference: readonly string[];
10
+ readonly canonicalOverrides?: Readonly<Record<string, string>>;
11
+ }
12
+ /**
13
+ * Source order used when no variant is published by the product's own vendor.
14
+ * The Claude Code marketplace leads because it carries the largest catalog;
15
+ * the knowledge-work marketplace re-publishes many of the same products.
16
+ */
17
+ export declare const DEFAULT_SOURCE_PREFERENCE: readonly string[];
18
+ export declare const DEFAULT_TOP_COUNT = 6;
19
+ export declare function parseProductPreference(input: unknown): ProductPreference;
20
+ /**
21
+ * A brand mark resolved at compile time and mirrored into the catalog release,
22
+ * so a client renders it without a second lookup or an upstream fetch.
23
+ */
24
+ export interface ProductIcon {
25
+ /** `content` is the vendor's own plugin file; `favicon` is the product site's. */
26
+ readonly kind: 'content' | 'favicon';
27
+ /** Release asset name; fetch it from the release for this `catalogId`. */
28
+ readonly asset: string;
29
+ /**
30
+ * Absolute, immutable URL for the asset, present when the build knows where
31
+ * the catalog will be published. A client renders this and never composes a
32
+ * URL; a deployment that hosts assets elsewhere substitutes its base here.
33
+ */
34
+ readonly assetUrl?: string;
35
+ readonly digest: string;
36
+ readonly contentType: IconContentType;
37
+ readonly bytes: number;
38
+ /** Plugin-relative path the mark came from, for `content`. */
39
+ readonly path: string | null;
40
+ /** Site icon URL, for `favicon`. */
41
+ readonly url: string | null;
42
+ readonly homepage: string | null;
43
+ }
44
+ /**
45
+ * Deterministic rendering hint for a product without a brand mark: initials and
46
+ * a stable hue. Clients draw it locally, which keeps it crisp, themable and
47
+ * free of a network request.
48
+ */
49
+ export interface ProductMonogram {
50
+ readonly text: string;
51
+ readonly hue: number;
52
+ }
53
+ /**
54
+ * The install-relevant facts of the release a product installs.
55
+ *
56
+ * A browsing client shows a plugin, then plans an install from it: the digest it
57
+ * must pin, the connectors and credentials setup will ask for, and the
58
+ * capabilities the harness has to negotiate. Carrying them here means the grid
59
+ * needs no second artifact.
60
+ */
61
+ export interface ConsumerRelease {
62
+ readonly releaseId: string;
63
+ readonly canonicalContentDigest: string;
64
+ readonly contentResolution: string;
65
+ readonly capabilities: readonly {
66
+ readonly type: string;
67
+ readonly name: string;
68
+ }[];
69
+ readonly requiredConnectors: readonly string[];
70
+ readonly requiredCredentials: readonly string[];
71
+ /** Commit the release was resolved from, for audit and update state. */
72
+ readonly sourceRevision: string;
73
+ readonly upstreamVersion?: string;
74
+ /** Canonical package status, when the release carries one. */
75
+ readonly packageStatus?: string;
76
+ readonly packageDigest?: string;
77
+ }
78
+ /** One installable product, resolved from every source variant that publishes it. */ /**
79
+ * The install-relevant facts of the release a product installs.
80
+ *
81
+ * A browsing client shows a plugin, then plans an install from it: the digest it
82
+ * must pin, the connectors and credentials setup will ask for, and the
83
+ * capabilities the harness has to negotiate. Carrying them here means the grid
84
+ * needs no second artifact.
85
+ */
86
+ export interface ConsumerRelease {
87
+ readonly releaseId: string;
88
+ readonly canonicalContentDigest: string;
89
+ readonly contentResolution: string;
90
+ readonly capabilities: readonly {
91
+ readonly type: string;
92
+ readonly name: string;
93
+ }[];
94
+ readonly requiredConnectors: readonly string[];
95
+ readonly requiredCredentials: readonly string[];
96
+ /** Commit the release was resolved from, for audit and update state. */
97
+ readonly sourceRevision: string;
98
+ readonly upstreamVersion?: string;
99
+ /** Canonical package status, when the release carries one. */
100
+ readonly packageStatus?: string;
101
+ readonly packageDigest?: string;
102
+ }
103
+ /** One installable product, resolved from every source variant that publishes it. */
104
+ export interface ConsumerProduct {
105
+ readonly productKey: string;
106
+ readonly pluginId: string;
107
+ readonly variantPluginIds: readonly string[];
108
+ readonly variantsIdentical: boolean;
109
+ readonly displayName: string;
110
+ readonly upstreamName: string;
111
+ readonly description: string;
112
+ readonly sourceId: string;
113
+ /**
114
+ * Who publishes the product, from the canonical variant. A card renders the
115
+ * first author as the publisher, so it travels with the product.
116
+ */
117
+ readonly authors: readonly string[];
118
+ /** Where the canonical release came from, for source links and audit. */
119
+ readonly provenance: {
120
+ readonly repositoryUrl: string;
121
+ readonly resolvedCommitSha: string;
122
+ readonly manifestPath: string;
123
+ readonly pluginSubdirectory: string;
124
+ };
125
+ readonly categories: readonly string[];
126
+ readonly primaryCategory: string;
127
+ readonly license: string;
128
+ readonly homepage?: string;
129
+ readonly capabilitySummary: Readonly<Record<string, number>>;
130
+ readonly compatibility: Readonly<Record<string, string>>;
131
+ readonly releaseId: string;
132
+ /** The release `pluginId` pins, with the facts an install needs. */
133
+ readonly release: ConsumerRelease;
134
+ readonly keywords: readonly string[];
135
+ /** Security classification of the canonical variant, for a detail panel. */
136
+ readonly securityClassification: {
137
+ readonly level: string;
138
+ readonly reasons: readonly string[];
139
+ readonly permissionSensitiveChanges: readonly string[];
140
+ readonly contentResolution: string;
141
+ };
142
+ readonly icon: ProductIcon | null;
143
+ readonly monogram: ProductMonogram;
144
+ }
145
+ export interface ConsumerCategory {
146
+ readonly category: string;
147
+ readonly productCount: number;
148
+ readonly pluginCount: number;
149
+ readonly pluginIds: readonly string[];
150
+ readonly productKeys: readonly string[];
151
+ readonly topProductKeys: readonly string[];
152
+ /** Artifact that carries full records for `topProductKeys`. */
153
+ readonly shelfArtifact: string;
154
+ /** Artifact that carries full records for every product in the category. */
155
+ readonly listArtifact: string;
156
+ }
157
+ /** A curated name that no longer resolves to a product in its category. */
158
+ export interface LeadingDiagnostic {
159
+ readonly category: string;
160
+ readonly name: string;
161
+ readonly reason: 'UNKNOWN_CATEGORY' | 'PRODUCT_NOT_FOUND' | 'PRODUCT_NOT_IN_CATEGORY';
162
+ }
163
+ /** Brand-mark coverage, so an incomplete set is visible rather than implied. */
164
+ export interface IconCoverage {
165
+ readonly total: number;
166
+ readonly content: number;
167
+ readonly favicon: number;
168
+ readonly monogramOnly: number;
169
+ /** Products still rendering a monogram, in display order: the curation list. */
170
+ readonly monogramProductKeys: readonly string[];
171
+ }
172
+ export declare function iconCoverage(index: Pick<ConsumerIndex, 'products'>): IconCoverage;
173
+ export interface ConsumerIndex {
174
+ readonly topCount: number;
175
+ readonly sourcePreference: readonly string[];
176
+ readonly counts: {
177
+ readonly plugins: number;
178
+ readonly products: number;
179
+ readonly redundantPlugins: number;
180
+ };
181
+ readonly products: Readonly<Record<string, ConsumerProduct>>;
182
+ readonly categories: readonly ConsumerCategory[];
183
+ readonly diagnostics: readonly LeadingDiagnostic[];
184
+ /** Present on the navigation artifact; summarised from `products`. */
185
+ readonly iconCoverage?: IconCoverage;
186
+ }
187
+ export declare const SHELF_ARTIFACT_PREFIX = "shelf-";
188
+ export declare const CATEGORY_ARTIFACT_PREFIX = "category-";
189
+ export declare const CATALOG_INDEX_ARTIFACT = "catalog-index.v1.json";
190
+ /** Shard artifact names are derived from the category so they stay stable. */
191
+ export declare function shardArtifactNames(category: string): {
192
+ shelf: string;
193
+ list: string;
194
+ };
195
+ /**
196
+ * Initials and a hue derived from the product key, so a product without a mark
197
+ * still renders a stable tile instead of a blank one.
198
+ */
199
+ export declare function monogramFor(displayName: string, productKey: string): ProductMonogram;
200
+ /**
201
+ * Builds the deduplicated, pre-sorted consumer view of a catalog.
202
+ *
203
+ * Each product appears once, represented by its canonical variant, and each
204
+ * category carries a display order plus the curated shelf of top products.
205
+ * Nothing here is random: every order is either configured or derived from
206
+ * stable identifiers.
207
+ */
208
+ export declare function buildConsumerIndex(input: {
209
+ readonly catalog: Pick<Catalog, 'plugins' | 'sources'>;
210
+ readonly leading?: Readonly<Record<string, readonly string[]>>;
211
+ readonly topCount?: number;
212
+ readonly preference?: ProductPreference;
213
+ /** Where the catalog will be published, so records can carry absolute URLs. */
214
+ readonly publicationRepositoryUrl?: string;
215
+ /** Committed asset base a browser can fetch directly; preferred when set. */
216
+ readonly publicationAssetsBaseUrl?: string;
217
+ }): ConsumerIndex;
@@ -0,0 +1,358 @@
1
+ import { iconAssetName } from './icons.js';
2
+ import { immutableAssetUrl } from './publication.js';
3
+ /**
4
+ * Source order used when no variant is published by the product's own vendor.
5
+ * The Claude Code marketplace leads because it carries the largest catalog;
6
+ * the knowledge-work marketplace re-publishes many of the same products.
7
+ */
8
+ export const DEFAULT_SOURCE_PREFERENCE = [
9
+ 'claude-official',
10
+ 'cursor-official',
11
+ 'openai-official',
12
+ 'knowledge-work-official',
13
+ ];
14
+ export const DEFAULT_TOP_COUNT = 6;
15
+ export function parseProductPreference(input) {
16
+ if (typeof input !== 'object' || input === null)
17
+ throw new Error('PRODUCT_PREFERENCE_INVALID');
18
+ const raw = input;
19
+ if (raw.schemaVersion !== 1)
20
+ throw new Error('PRODUCT_PREFERENCE_INVALID');
21
+ if (!Array.isArray(raw.sourcePreference) ||
22
+ raw.sourcePreference.length === 0 ||
23
+ raw.sourcePreference.some((value) => typeof value !== 'string' || value.length === 0))
24
+ throw new Error('PRODUCT_PREFERENCE_INVALID');
25
+ if (new Set(raw.sourcePreference).size !== raw.sourcePreference.length)
26
+ throw new Error('PRODUCT_PREFERENCE_DUPLICATE_SOURCE');
27
+ const overrides = raw.canonicalOverrides;
28
+ if (overrides !== undefined) {
29
+ if (typeof overrides !== 'object' || overrides === null)
30
+ throw new Error('PRODUCT_PREFERENCE_INVALID');
31
+ for (const [productKey, pluginId] of Object.entries(overrides))
32
+ if (typeof pluginId !== 'string' || !pluginId.startsWith('plugin:'))
33
+ throw new Error(`PRODUCT_PREFERENCE_OVERRIDE_INVALID: ${productKey}`);
34
+ }
35
+ return {
36
+ schemaVersion: 1,
37
+ sourcePreference: [...raw.sourcePreference],
38
+ ...(overrides ? { canonicalOverrides: { ...overrides } } : {}),
39
+ };
40
+ }
41
+ export function iconCoverage(index) {
42
+ const products = Object.values(index.products);
43
+ const monogramOnly = products
44
+ .filter((product) => !product.icon)
45
+ .map((product) => product.productKey)
46
+ .toSorted();
47
+ return {
48
+ total: products.length,
49
+ content: products.filter((product) => product.icon?.kind === 'content').length,
50
+ favicon: products.filter((product) => product.icon?.kind === 'favicon').length,
51
+ monogramOnly: monogramOnly.length,
52
+ monogramProductKeys: monogramOnly,
53
+ };
54
+ }
55
+ function isHumanFormatted(value) {
56
+ return /[A-Z]/.test(value) || /\s/.test(value);
57
+ }
58
+ /**
59
+ * Prefers content published by the product's own vendor over a marketplace's
60
+ * own wrapper package, then applies the configured source order.
61
+ */
62
+ function selectCanonical(variants, sourceRepository, preference) {
63
+ const override = preference.canonicalOverrides?.[variants[0]?.productGroupingKey ?? ''];
64
+ const overridden = override ? variants.find((plugin) => plugin.pluginId === override) : undefined;
65
+ if (overridden)
66
+ return overridden;
67
+ const rank = (plugin) => {
68
+ const index = preference.sourcePreference.indexOf(plugin.sourceId);
69
+ return index === -1 ? preference.sourcePreference.length : index;
70
+ };
71
+ // A variant with no resolved release repository proves nothing about its
72
+ // origin, so it is treated as marketplace-shipped rather than vendor-published.
73
+ const vendorPublished = (plugin) => {
74
+ const repository = plugin.availableReleases[0]?.resolvedRepositoryUrl;
75
+ return repository !== undefined && repository !== sourceRepository.get(plugin.sourceId);
76
+ };
77
+ return [...variants].toSorted((left, right) => Number(vendorPublished(right)) - Number(vendorPublished(left)) ||
78
+ rank(left) - rank(right) ||
79
+ Number(isHumanFormatted(right.displayName)) - Number(isHumanFormatted(left.displayName)) ||
80
+ left.pluginId.localeCompare(right.pluginId))[0];
81
+ }
82
+ /** Picks the most presentable label among a product's variants. */
83
+ function selectDisplayName(variants, canonical) {
84
+ const formatted = variants
85
+ .map((plugin) => plugin.displayName)
86
+ .filter((value) => isHumanFormatted(value) && value !== '')
87
+ .toSorted();
88
+ return formatted[0] ?? canonical.displayName;
89
+ }
90
+ export const SHELF_ARTIFACT_PREFIX = 'shelf-';
91
+ export const CATEGORY_ARTIFACT_PREFIX = 'category-';
92
+ export const CATALOG_INDEX_ARTIFACT = 'catalog-index.v1.json';
93
+ /** Shard artifact names are derived from the category so they stay stable. */
94
+ export function shardArtifactNames(category) {
95
+ if (!/^[a-z0-9][a-z0-9-]{1,63}$/.test(category))
96
+ throw new Error(`CATEGORY_SLUG_INVALID: ${category}`);
97
+ return {
98
+ shelf: `${SHELF_ARTIFACT_PREFIX}${category}.v1.json`,
99
+ list: `${CATEGORY_ARTIFACT_PREFIX}${category}.v1.json`,
100
+ };
101
+ }
102
+ /** The release a product's install target pins, when it is still resolvable. */
103
+ function currentRelease(plugin) {
104
+ return (plugin.availableReleases.find((release) => release.releaseId === plugin.currentReleaseId) ??
105
+ plugin.availableReleases[0]);
106
+ }
107
+ /** Reads a nested string out of untrusted release metadata. */
108
+ function nestedString(value, key) {
109
+ if (typeof value !== 'object' || value === null)
110
+ return undefined;
111
+ const nested = value[key];
112
+ return typeof nested === 'string' && nested.length > 0 ? nested : undefined;
113
+ }
114
+ function describeRelease(plugin) {
115
+ const release = currentRelease(plugin);
116
+ const packages = (release.releaseMetadata ?? {}).agentPlugins;
117
+ return {
118
+ releaseId: release.releaseId,
119
+ canonicalContentDigest: release.canonicalContentDigest,
120
+ contentResolution: release.contentResolution,
121
+ capabilities: release.capabilities.map((capability) => ({
122
+ type: capability.type,
123
+ name: capability.name,
124
+ })),
125
+ requiredConnectors: [...release.requiredConnectors],
126
+ requiredCredentials: [...release.requiredCredentials],
127
+ sourceRevision: release.resolvedCommitSha,
128
+ ...(release.upstreamVersion ? { upstreamVersion: release.upstreamVersion } : {}),
129
+ ...(nestedString(packages, 'status')
130
+ ? { packageStatus: nestedString(packages, 'status') }
131
+ : {}),
132
+ ...(nestedString(packages, 'packageDigest')
133
+ ? { packageDigest: nestedString(packages, 'packageDigest') }
134
+ : {}),
135
+ };
136
+ }
137
+ /** Prefers the canonical variant's mark, then any variant that has one. */
138
+ function selectProductIcon(variants, canonical, catalogId, publicationRepositoryUrl, publicationAssetsBaseUrl) {
139
+ const ordered = [canonical, ...variants.filter((plugin) => plugin !== canonical)];
140
+ for (const plugin of ordered) {
141
+ const icon = currentRelease(plugin)?.icon;
142
+ if (!icon)
143
+ continue;
144
+ const asset = iconAssetName(icon.digest, icon.contentType);
145
+ return {
146
+ kind: icon.kind,
147
+ asset,
148
+ ...(publicationAssetsBaseUrl
149
+ ? { assetUrl: `${publicationAssetsBaseUrl}/${asset}` }
150
+ : publicationRepositoryUrl
151
+ ? { assetUrl: immutableAssetUrl(publicationRepositoryUrl, catalogId, asset) }
152
+ : {}),
153
+ digest: icon.digest,
154
+ contentType: icon.contentType,
155
+ bytes: icon.bytes,
156
+ path: icon.kind === 'content' ? icon.path : null,
157
+ url: icon.kind === 'favicon' ? icon.url : null,
158
+ homepage: icon.kind === 'favicon' ? icon.homepage : null,
159
+ };
160
+ }
161
+ return null;
162
+ }
163
+ const MONOGRAM_HUE_OFFSETS = [0, 137, 274];
164
+ /**
165
+ * Initials and a hue derived from the product key, so a product without a mark
166
+ * still renders a stable tile instead of a blank one.
167
+ */
168
+ export function monogramFor(displayName, productKey) {
169
+ const words = displayName.split(/[^\p{L}\p{N}]+/u).filter(Boolean);
170
+ const first = words[0] ?? productKey;
171
+ const second = words[1];
172
+ const text = (words.length > 1 && second ? (first[0] ?? '') + (second[0] ?? '') : first.slice(0, 2)).toUpperCase();
173
+ let hash = 0;
174
+ for (const character of productKey)
175
+ hash = (hash * 31 + character.codePointAt(0)) % 360;
176
+ // Keep adjacent hues off each other so side-by-side tiles stay distinct.
177
+ return { text: text || '?', hue: (hash + MONOGRAM_HUE_OFFSETS[hash % 3]) % 360 };
178
+ }
179
+ function compactCompatibility(plugin) {
180
+ return Object.fromEntries(Object.entries(plugin.harnessCompatibility).map(([harness, value]) => [harness, value.status]));
181
+ }
182
+ /**
183
+ * Builds the deduplicated, pre-sorted consumer view of a catalog.
184
+ *
185
+ * Each product appears once, represented by its canonical variant, and each
186
+ * category carries a display order plus the curated shelf of top products.
187
+ * Nothing here is random: every order is either configured or derived from
188
+ * stable identifiers.
189
+ */
190
+ export function buildConsumerIndex(input) {
191
+ const preference = input.preference ?? {
192
+ schemaVersion: 1,
193
+ sourcePreference: [...DEFAULT_SOURCE_PREFERENCE],
194
+ };
195
+ const leading = input.leading ?? {};
196
+ const topCount = input.topCount ?? DEFAULT_TOP_COUNT;
197
+ const sourceRepository = new Map(input.catalog.sources.map((source) => [source.sourceId, source.repositoryUrl]));
198
+ const variantsByProduct = new Map();
199
+ for (const plugin of input.catalog.plugins) {
200
+ const list = variantsByProduct.get(plugin.productGroupingKey);
201
+ if (list)
202
+ list.push(plugin);
203
+ else
204
+ variantsByProduct.set(plugin.productGroupingKey, [plugin]);
205
+ }
206
+ const catalogId = input.catalog.catalogId ?? '';
207
+ const products = {};
208
+ for (const [productKey, variants] of [...variantsByProduct].toSorted((left, right) => left[0].localeCompare(right[0]))) {
209
+ const canonical = selectCanonical(variants, sourceRepository, preference);
210
+ const variantPluginIds = variants
211
+ .map((plugin) => plugin.pluginId)
212
+ .toSorted((left, right) => left === canonical.pluginId
213
+ ? -1
214
+ : right === canonical.pluginId
215
+ ? 1
216
+ : left.localeCompare(right));
217
+ const releaseIds = new Set(variants.map((plugin) => plugin.currentReleaseId));
218
+ const productCategories = [
219
+ ...new Set(variants.flatMap((plugin) => plugin.categories)),
220
+ ].toSorted();
221
+ products[productKey] = {
222
+ productKey,
223
+ pluginId: canonical.pluginId,
224
+ variantPluginIds,
225
+ variantsIdentical: releaseIds.size === 1 && variants.length > 1,
226
+ displayName: selectDisplayName(variants, canonical),
227
+ upstreamName: canonical.upstreamPluginName,
228
+ description: canonical.description || (variants.find((v) => v.description)?.description ?? ''),
229
+ sourceId: canonical.sourceId,
230
+ authors: [...canonical.authors],
231
+ provenance: {
232
+ repositoryUrl: canonical.provenance.repositoryUrl,
233
+ resolvedCommitSha: currentRelease(canonical).resolvedCommitSha,
234
+ manifestPath: canonical.provenance.manifestPath,
235
+ pluginSubdirectory: canonical.provenance.pluginSubdirectory,
236
+ },
237
+ // A product's categories are the union across its variants: sources
238
+ // disagree (one marketplace files Slack under productivity, another under
239
+ // communication), and a product belongs wherever any variant is filed.
240
+ categories: productCategories,
241
+ primaryCategory: productCategories[0] ?? 'other',
242
+ license: canonical.license.name,
243
+ ...(canonical.homepage ? { homepage: canonical.homepage } : {}),
244
+ capabilitySummary: { ...canonical.capabilitySummary },
245
+ compatibility: compactCompatibility(canonical),
246
+ releaseId: canonical.currentReleaseId,
247
+ release: describeRelease(canonical),
248
+ keywords: [...canonical.keywords],
249
+ securityClassification: {
250
+ level: canonical.securityClassification.level,
251
+ reasons: [...canonical.securityClassification.reasons],
252
+ permissionSensitiveChanges: [
253
+ ...canonical.securityClassification.permissionSensitiveChanges,
254
+ ],
255
+ contentResolution: canonical.securityClassification.contentResolution,
256
+ },
257
+ icon: selectProductIcon(variants, canonical, catalogId, input.publicationRepositoryUrl, input.publicationAssetsBaseUrl),
258
+ monogram: monogramFor(selectDisplayName(variants, canonical), productKey),
259
+ };
260
+ }
261
+ const categoryNames = [
262
+ ...new Set(input.catalog.plugins.flatMap((plugin) => plugin.categories)),
263
+ ].toSorted();
264
+ const diagnostics = [];
265
+ // Resolve every curated name first, so a category's shelf can never lose a
266
+ // curated product to another category that merely reached it by fill order.
267
+ const curatedByCategory = new Map();
268
+ for (const category of categoryNames) {
269
+ const members = input.catalog.plugins.filter((plugin) => plugin.categories.includes(category));
270
+ const curated = [];
271
+ for (const name of leading[category] ?? []) {
272
+ const matches = members.filter((plugin) => plugin.upstreamPluginName === name);
273
+ if (matches.length === 0) {
274
+ diagnostics.push({
275
+ category,
276
+ name,
277
+ reason: variantsByProduct.has(name) ? 'PRODUCT_NOT_IN_CATEGORY' : 'PRODUCT_NOT_FOUND',
278
+ });
279
+ continue;
280
+ }
281
+ const key = matches[0].productGroupingKey;
282
+ if (!curated.includes(key))
283
+ curated.push(key);
284
+ }
285
+ curatedByCategory.set(category, curated);
286
+ }
287
+ // A shelf product headlined once, assigned to the first category that curates
288
+ // it. Every curated product is reserved up front, so a later category's fill
289
+ // can never take it before its owner is processed.
290
+ const curatedOwner = new Map();
291
+ for (const category of categoryNames)
292
+ for (const productKey of curatedByCategory.get(category))
293
+ if (!curatedOwner.has(productKey))
294
+ curatedOwner.set(productKey, category);
295
+ const filled = new Set();
296
+ const categories = categoryNames.map((category) => {
297
+ const members = input.catalog.plugins.filter((plugin) => plugin.categories.includes(category));
298
+ const curated = curatedByCategory.get(category);
299
+ const curatedRank = new Map(curated.map((key, index) => [key, index]));
300
+ const productKeys = [...new Set(members.map((plugin) => plugin.productGroupingKey))].toSorted((left, right) => (curatedRank.get(left) ?? Number.POSITIVE_INFINITY) -
301
+ (curatedRank.get(right) ?? Number.POSITIVE_INFINITY) || left.localeCompare(right));
302
+ const memberIds = new Set(members.map((plugin) => plugin.pluginId));
303
+ // Curated first in configured order, canonical variant ahead of its own
304
+ // variants, then alphabetical for a predictable browsing tail.
305
+ const orderedIds = [];
306
+ for (const productKey of productKeys) {
307
+ const product = products[productKey];
308
+ for (const pluginId of product.variantPluginIds)
309
+ if (memberIds.has(pluginId))
310
+ orderedIds.push(pluginId);
311
+ }
312
+ // Curated products this category owns, then deterministic fill so a shelf
313
+ // stays full without repeating a product another category already shows.
314
+ const topProductKeys = [];
315
+ for (const productKey of productKeys) {
316
+ if (topProductKeys.length === topCount)
317
+ break;
318
+ if (curatedOwner.get(productKey) !== category)
319
+ continue;
320
+ topProductKeys.push(productKey);
321
+ }
322
+ for (const productKey of productKeys) {
323
+ if (topProductKeys.length === topCount)
324
+ break;
325
+ if (curatedOwner.has(productKey) || filled.has(productKey))
326
+ continue;
327
+ topProductKeys.push(productKey);
328
+ filled.add(productKey);
329
+ }
330
+ return {
331
+ category,
332
+ productCount: productKeys.length,
333
+ pluginCount: members.length,
334
+ pluginIds: orderedIds,
335
+ productKeys,
336
+ topProductKeys,
337
+ shelfArtifact: shardArtifactNames(category).shelf,
338
+ listArtifact: shardArtifactNames(category).list,
339
+ };
340
+ });
341
+ for (const category of Object.keys(leading))
342
+ if (!categoryNames.includes(category))
343
+ for (const name of leading[category])
344
+ diagnostics.push({ category, name, reason: 'UNKNOWN_CATEGORY' });
345
+ return {
346
+ topCount,
347
+ sourcePreference: [...preference.sourcePreference],
348
+ counts: {
349
+ plugins: input.catalog.plugins.length,
350
+ products: Object.keys(products).length,
351
+ redundantPlugins: input.catalog.plugins.length - Object.keys(products).length,
352
+ },
353
+ products,
354
+ categories,
355
+ diagnostics: diagnostics.toSorted((left, right) => left.category.localeCompare(right.category) || left.name.localeCompare(right.name)),
356
+ };
357
+ }
358
+ //# sourceMappingURL=consumer-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consumer-index.js","sourceRoot":"","sources":["../src/consumer-index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAwB,MAAM,YAAY,CAAA;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAYpD;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAsB;IAC1D,iBAAiB;IACjB,iBAAiB;IACjB,iBAAiB;IACjB,yBAAyB;CAC1B,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAA;AAElC,MAAM,UAAU,sBAAsB,CAAC,KAAc;IACnD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAA;IAC9F,MAAM,GAAG,GAAG,KAAmC,CAAA;IAC/C,IAAI,GAAG,CAAC,aAAa,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAA;IAC1E,IACE,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;QACpC,GAAG,CAAC,gBAAgB,CAAC,MAAM,KAAK,CAAC;QACjC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;QAErF,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAA;IAC/C,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,gBAAgB,CAAC,MAAM;QACpE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;IACxD,MAAM,SAAS,GAAG,GAAG,CAAC,kBAAkB,CAAA;IACxC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,IAAI;YACrD,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAA;QAC/C,KAAK,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;YAC5D,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC;gBACjE,MAAM,IAAI,KAAK,CAAC,wCAAwC,UAAU,EAAE,CAAC,CAAA;IAC3E,CAAC;IACD,OAAO;QACL,aAAa,EAAE,CAAC;QAChB,gBAAgB,EAAE,CAAC,GAAG,GAAG,CAAC,gBAAgB,CAAC;QAC3C,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,EAAE,GAAG,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/D,CAAA;AACH,CAAC;AA4JD,MAAM,UAAU,YAAY,CAAC,KAAsC;IACjE,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;IAC9C,MAAM,YAAY,GAAG,QAAQ;SAC1B,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;SAClC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;SACpC,QAAQ,EAAE,CAAA;IACb,OAAO;QACL,KAAK,EAAE,QAAQ,CAAC,MAAM;QACtB,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,MAAM;QAC9E,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,MAAM;QAC9E,YAAY,EAAE,YAAY,CAAC,MAAM;QACjC,mBAAmB,EAAE,YAAY;KAClC,CAAA;AACH,CAAC;AAiBD,SAAS,gBAAgB,CAAC,KAAa;IACrC,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AAChD,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CACtB,QAA2B,EAC3B,gBAA6C,EAC7C,UAA6B;IAE7B,MAAM,QAAQ,GAAG,UAAU,CAAC,kBAAkB,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,kBAAkB,IAAI,EAAE,CAAC,CAAA;IACvF,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACjG,IAAI,UAAU;QAAE,OAAO,UAAU,CAAA;IACjC,MAAM,IAAI,GAAG,CAAC,MAAc,EAAU,EAAE;QACtC,MAAM,KAAK,GAAG,UAAU,CAAC,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAClE,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAA;IAClE,CAAC,CAAA;IACD,yEAAyE;IACzE,gFAAgF;IAChF,MAAM,eAAe,GAAG,CAAC,MAAc,EAAW,EAAE;QAClD,MAAM,UAAU,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,qBAAqB,CAAA;QACrE,OAAO,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IACzF,CAAC,CAAA;IACD,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,QAAQ,CAC3B,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACd,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC9D,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,GAAG,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxF,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,CAC9C,CAAC,CAAC,CAAE,CAAA;AACP,CAAC;AAED,mEAAmE;AACnE,SAAS,iBAAiB,CAAC,QAA2B,EAAE,SAAiB;IACvE,MAAM,SAAS,GAAG,QAAQ;SACvB,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC;SACnC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;SAC1D,QAAQ,EAAE,CAAA;IACb,OAAO,SAAS,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,WAAW,CAAA;AAC9C,CAAC;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAG,QAAQ,CAAA;AAC7C,MAAM,CAAC,MAAM,wBAAwB,GAAG,WAAW,CAAA;AACnD,MAAM,CAAC,MAAM,sBAAsB,GAAG,uBAAuB,CAAA;AAE7D,8EAA8E;AAC9E,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IAIjD,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAA;IACvD,OAAO;QACL,KAAK,EAAE,GAAG,qBAAqB,GAAG,QAAQ,UAAU;QACpD,IAAI,EAAE,GAAG,wBAAwB,GAAG,QAAQ,UAAU;KACvD,CAAA;AACH,CAAC;AAED,gFAAgF;AAChF,SAAS,cAAc,CAAC,MAAc;IACpC,OAAO,CACL,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,KAAK,MAAM,CAAC,gBAAgB,CAAC;QACzF,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAC5B,CAAA;AACH,CAAC;AAED,+DAA+D;AAC/D,SAAS,YAAY,CAAC,KAAc,EAAE,GAAW;IAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAA;IACjE,MAAM,MAAM,GAAI,KAAiC,CAAC,GAAG,CAAC,CAAA;IACtD,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;AAC7E,CAAC;AAED,SAAS,eAAe,CAAC,MAAc;IACrC,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAE,CAAA;IACvC,MAAM,QAAQ,GAAI,CAAC,OAAO,CAAC,eAAe,IAAI,EAAE,CAA6B,CAAC,YAAY,CAAA;IAC1F,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,sBAAsB,EAAE,OAAO,CAAC,sBAAsB;QACtD,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;QAC5C,YAAY,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YACtD,IAAI,EAAE,UAAU,CAAC,IAAI;YACrB,IAAI,EAAE,UAAU,CAAC,IAAI;SACtB,CAAC,CAAC;QACH,kBAAkB,EAAE,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC;QACnD,mBAAmB,EAAE,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC;QACrD,cAAc,EAAE,OAAO,CAAC,iBAAiB;QACzC,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChF,GAAG,CAAC,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC;YAClC,CAAC,CAAC,EAAE,aAAa,EAAE,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAE,EAAE;YACtD,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,YAAY,CAAC,QAAQ,EAAE,eAAe,CAAC;YACzC,CAAC,CAAC,EAAE,aAAa,EAAE,YAAY,CAAC,QAAQ,EAAE,eAAe,CAAE,EAAE;YAC7D,CAAC,CAAC,EAAE,CAAC;KACR,CAAA;AACH,CAAC;AAED,2EAA2E;AAC3E,SAAS,iBAAiB,CACxB,QAA2B,EAC3B,SAAiB,EACjB,SAAiB,EACjB,wBAA4C,EAC5C,wBAA4C;IAE5C,MAAM,OAAO,GAAG,CAAC,SAAS,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAA;IACjF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,EAAE,IAAI,CAAA;QACzC,IAAI,CAAC,IAAI;YAAE,SAAQ;QACnB,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;QAC1D,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK;YACL,GAAG,CAAC,wBAAwB;gBAC1B,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,wBAAwB,IAAI,KAAK,EAAE,EAAE;gBACtD,CAAC,CAAC,wBAAwB;oBACxB,CAAC,CAAC,EAAE,QAAQ,EAAE,iBAAiB,CAAC,wBAAwB,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE;oBAC7E,CAAC,CAAC,EAAE,CAAC;YACT,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;YAChD,GAAG,EAAE,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI;YAC9C,QAAQ,EAAE,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI;SACzD,CAAA;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,MAAM,oBAAoB,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAU,CAAA;AAEnD;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,WAAmB,EAAE,UAAkB;IACjE,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAClE,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,UAAU,CAAA;IACpC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;IACvB,MAAM,IAAI,GAAG,CACX,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CACtF,CAAC,WAAW,EAAE,CAAA;IACf,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,KAAK,MAAM,SAAS,IAAI,UAAU;QAAE,IAAI,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC,CAAE,CAAC,GAAG,GAAG,CAAA;IACxF,yEAAyE;IACzE,OAAO,EAAE,IAAI,EAAE,IAAI,IAAI,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,oBAAoB,CAAC,IAAI,GAAG,CAAC,CAAE,CAAC,GAAG,GAAG,EAAE,CAAA;AACnF,CAAC;AAED,SAAS,oBAAoB,CAAC,MAAc;IAC1C,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAC/F,CAAA;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,KASlC;IACC,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,IAAI;QACrC,aAAa,EAAE,CAAU;QACzB,gBAAgB,EAAE,CAAC,GAAG,yBAAyB,CAAC;KACjD,CAAA;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,EAAE,CAAA;IACnC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,iBAAiB,CAAA;IACpD,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAC9B,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC,CAC/E,CAAA;IACD,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAoB,CAAA;IACrD,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3C,MAAM,IAAI,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAA;QAC7D,IAAI,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;;YACtB,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IACjE,CAAC;IACD,MAAM,SAAS,GAAI,KAAK,CAAC,OAAkC,CAAC,SAAS,IAAI,EAAE,CAAA;IAC3E,MAAM,QAAQ,GAAoC,EAAE,CAAA;IACpD,KAAK,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACnF,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAChC,EAAE,CAAC;QACF,MAAM,SAAS,GAAG,eAAe,CAAC,QAAQ,EAAE,gBAAgB,EAAE,UAAU,CAAC,CAAA;QACzE,MAAM,gBAAgB,GAAG,QAAQ;aAC9B,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;aAChC,QAAQ,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACxB,IAAI,KAAK,SAAS,CAAC,QAAQ;YACzB,CAAC,CAAC,CAAC,CAAC;YACJ,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,QAAQ;gBAC5B,CAAC,CAAC,CAAC;gBACH,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAChC,CAAA;QACH,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAA;QAC7E,MAAM,iBAAiB,GAAG;YACxB,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;SAC5D,CAAC,QAAQ,EAAE,CAAA;QACZ,QAAQ,CAAC,UAAU,CAAC,GAAG;YACrB,UAAU;YACV,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,gBAAgB;YAChB,iBAAiB,EAAE,UAAU,CAAC,IAAI,KAAK,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;YAC/D,WAAW,EAAE,iBAAiB,CAAC,QAAQ,EAAE,SAAS,CAAC;YACnD,YAAY,EAAE,SAAS,CAAC,kBAAkB;YAC1C,WAAW,EACT,SAAS,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,WAAW,IAAI,EAAE,CAAC;YACnF,QAAQ,EAAE,SAAS,CAAC,QAAQ;YAC5B,OAAO,EAAE,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC;YAC/B,UAAU,EAAE;gBACV,aAAa,EAAE,SAAS,CAAC,UAAU,CAAC,aAAa;gBACjD,iBAAiB,EAAE,cAAc,CAAC,SAAS,CAAE,CAAC,iBAAiB;gBAC/D,YAAY,EAAE,SAAS,CAAC,UAAU,CAAC,YAAY;gBAC/C,kBAAkB,EAAE,SAAS,CAAC,UAAU,CAAC,kBAAkB;aAC5D;YACD,oEAAoE;YACpE,0EAA0E;YAC1E,uEAAuE;YACvE,UAAU,EAAE,iBAAiB;YAC7B,eAAe,EAAE,iBAAiB,CAAC,CAAC,CAAC,IAAI,OAAO;YAChD,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,IAAI;YAC/B,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/D,iBAAiB,EAAE,EAAE,GAAG,SAAS,CAAC,iBAAiB,EAAE;YACrD,aAAa,EAAE,oBAAoB,CAAC,SAAS,CAAC;YAC9C,SAAS,EAAE,SAAS,CAAC,gBAAgB;YACrC,OAAO,EAAE,eAAe,CAAC,SAAS,CAAC;YACnC,QAAQ,EAAE,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC;YACjC,sBAAsB,EAAE;gBACtB,KAAK,EAAE,SAAS,CAAC,sBAAsB,CAAC,KAAK;gBAC7C,OAAO,EAAE,CAAC,GAAG,SAAS,CAAC,sBAAsB,CAAC,OAAO,CAAC;gBACtD,0BAA0B,EAAE;oBAC1B,GAAG,SAAS,CAAC,sBAAsB,CAAC,0BAA0B;iBAC/D;gBACD,iBAAiB,EAAE,SAAS,CAAC,sBAAsB,CAAC,iBAAiB;aACtE;YACD,IAAI,EAAE,iBAAiB,CACrB,QAAQ,EACR,SAAS,EACT,SAAS,EACT,KAAK,CAAC,wBAAwB,EAC9B,KAAK,CAAC,wBAAwB,CAC/B;YACD,QAAQ,EAAE,WAAW,CAAC,iBAAiB,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,UAAU,CAAC;SAC1E,CAAA;IACH,CAAC;IAED,MAAM,aAAa,GAAG;QACpB,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;KACzE,CAAC,QAAQ,EAAE,CAAA;IACZ,MAAM,WAAW,GAAwB,EAAE,CAAA;IAC3C,2EAA2E;IAC3E,4EAA4E;IAC5E,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAoB,CAAA;IACrD,KAAK,MAAM,QAAQ,IAAI,aAAa,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAA;QAC9F,MAAM,OAAO,GAAa,EAAE,CAAA;QAC5B,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;YAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,kBAAkB,KAAK,IAAI,CAAC,CAAA;YAC9E,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,WAAW,CAAC,IAAI,CAAC;oBACf,QAAQ;oBACR,IAAI;oBACJ,MAAM,EAAE,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,mBAAmB;iBACtF,CAAC,CAAA;gBACF,SAAQ;YACV,CAAC;YACD,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC,kBAAkB,CAAA;YAC1C,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC/C,CAAC;QACD,iBAAiB,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC1C,CAAC;IACD,8EAA8E;IAC9E,6EAA6E;IAC7E,mDAAmD;IACnD,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAA;IAC9C,KAAK,MAAM,QAAQ,IAAI,aAAa;QAClC,KAAK,MAAM,UAAU,IAAI,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAE;YACvD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC;gBAAE,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;IAC7E,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAA;IAChC,MAAM,UAAU,GAAuB,aAAa,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QACpE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAA;QAC9F,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAA;QAChD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;QACtE,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAC3F,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACd,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,iBAAiB,CAAC;YACjD,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,iBAAiB,CAAC,IAAI,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CACtF,CAAA;QACD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAA;QACnE,wEAAwE;QACxE,+DAA+D;QAC/D,MAAM,UAAU,GAAa,EAAE,CAAA;QAC/B,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAE,CAAA;YACrC,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,gBAAgB;gBAC7C,IAAI,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;oBAAE,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC1D,CAAC;QACD,0EAA0E;QAC1E,yEAAyE;QACzE,MAAM,cAAc,GAAa,EAAE,CAAA;QACnC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,IAAI,cAAc,CAAC,MAAM,KAAK,QAAQ;gBAAE,MAAK;YAC7C,IAAI,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,QAAQ;gBAAE,SAAQ;YACvD,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACjC,CAAC;QACD,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,IAAI,cAAc,CAAC,MAAM,KAAK,QAAQ;gBAAE,MAAK;YAC7C,IAAI,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC;gBAAE,SAAQ;YACpE,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;YAC/B,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QACxB,CAAC;QACD,OAAO;YACL,QAAQ;YACR,YAAY,EAAE,WAAW,CAAC,MAAM;YAChC,WAAW,EAAE,OAAO,CAAC,MAAM;YAC3B,SAAS,EAAE,UAAU;YACrB,WAAW;YACX,cAAc;YACd,aAAa,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC,KAAK;YACjD,YAAY,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC,IAAI;SAChD,CAAA;IACH,CAAC,CAAC,CAAA;IACF,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;QACzC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC;YACnC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAE;gBACnC,WAAW,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAA;IACtE,OAAO;QACL,QAAQ;QACR,gBAAgB,EAAE,CAAC,GAAG,UAAU,CAAC,gBAAgB,CAAC;QAClD,MAAM,EAAE;YACN,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM;YACrC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM;YACtC,gBAAgB,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM;SAC9E;QACD,QAAQ;QACR,UAAU;QACV,WAAW,EAAE,WAAW,CAAC,QAAQ,CAC/B,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACd,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CACrF;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Title-cases a slug-shaped name and leaves a properly cased one alone.
3
+ *
4
+ * Separators become spaces (`adobe-for-creativity` → `Adobe for Creativity`),
5
+ * but a dot does not, so domain-style names keep their shape
6
+ * (`monday.com` → `Monday.com`).
7
+ */
8
+ export declare function normalizeDisplayName(value: string): string;