@salesforce/ui-bundle-features 1.117.2

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 (68) hide show
  1. package/LICENSE.txt +82 -0
  2. package/README.md +153 -0
  3. package/dist/aggregate-features.d.ts +16 -0
  4. package/dist/aggregate-features.d.ts.map +1 -0
  5. package/dist/aggregate-features.js +43 -0
  6. package/dist/aggregate-features.js.map +1 -0
  7. package/dist/cli.d.ts +8 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +71 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/conflict-detector.d.ts +31 -0
  12. package/dist/conflict-detector.d.ts.map +1 -0
  13. package/dist/conflict-detector.js +153 -0
  14. package/dist/conflict-detector.js.map +1 -0
  15. package/dist/dependency-resolver.d.ts +18 -0
  16. package/dist/dependency-resolver.d.ts.map +1 -0
  17. package/dist/dependency-resolver.js +96 -0
  18. package/dist/dependency-resolver.js.map +1 -0
  19. package/dist/describe-command.d.ts +10 -0
  20. package/dist/describe-command.d.ts.map +1 -0
  21. package/dist/describe-command.js +119 -0
  22. package/dist/describe-command.js.map +1 -0
  23. package/dist/feature-metadata.d.ts +30 -0
  24. package/dist/feature-metadata.d.ts.map +1 -0
  25. package/dist/feature-metadata.js +136 -0
  26. package/dist/feature-metadata.js.map +1 -0
  27. package/dist/feature-search.d.ts +16 -0
  28. package/dist/feature-search.d.ts.map +1 -0
  29. package/dist/feature-search.js +140 -0
  30. package/dist/feature-search.js.map +1 -0
  31. package/dist/features.json +137 -0
  32. package/dist/file-copier.d.ts +15 -0
  33. package/dist/file-copier.d.ts.map +1 -0
  34. package/dist/file-copier.js +105 -0
  35. package/dist/file-copier.js.map +1 -0
  36. package/dist/install-command.d.ts +15 -0
  37. package/dist/install-command.d.ts.map +1 -0
  38. package/dist/install-command.js +314 -0
  39. package/dist/install-command.js.map +1 -0
  40. package/dist/list-command.d.ts +13 -0
  41. package/dist/list-command.d.ts.map +1 -0
  42. package/dist/list-command.js +71 -0
  43. package/dist/list-command.js.map +1 -0
  44. package/dist/logger.d.ts +48 -0
  45. package/dist/logger.d.ts.map +1 -0
  46. package/dist/logger.js +82 -0
  47. package/dist/logger.js.map +1 -0
  48. package/dist/package-manager.d.ts +22 -0
  49. package/dist/package-manager.d.ts.map +1 -0
  50. package/dist/package-manager.js +172 -0
  51. package/dist/package-manager.js.map +1 -0
  52. package/dist/placeholder-resolver.d.ts +25 -0
  53. package/dist/placeholder-resolver.d.ts.map +1 -0
  54. package/dist/placeholder-resolver.js +78 -0
  55. package/dist/placeholder-resolver.js.map +1 -0
  56. package/dist/schema-loader.d.ts +17 -0
  57. package/dist/schema-loader.d.ts.map +1 -0
  58. package/dist/schema-loader.js +82 -0
  59. package/dist/schema-loader.js.map +1 -0
  60. package/dist/types.d.ts +174 -0
  61. package/dist/types.d.ts.map +1 -0
  62. package/dist/types.js +7 -0
  63. package/dist/types.js.map +1 -0
  64. package/dist/utils.d.ts +30 -0
  65. package/dist/utils.d.ts.map +1 -0
  66. package/dist/utils.js +58 -0
  67. package/dist/utils.js.map +1 -0
  68. package/package.json +53 -0
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { getFeatureMetadata } from "./feature-metadata.js";
7
+ import { executeCopyOperations } from "./file-copier.js";
8
+ import { installPackage, installPackageDependencies, isPackageInstalled, } from "./package-manager.js";
9
+ /**
10
+ * Resolve and install feature dependencies recursively
11
+ * Follows the exact workflow: install package -> load schema -> recursively process
12
+ */
13
+ export async function resolveFeatureDependencies(dependencies, context) {
14
+ for (const dependency of dependencies) {
15
+ await installFeatureDependency(dependency, context);
16
+ }
17
+ }
18
+ /**
19
+ * Install a single feature dependency with section-delimited output
20
+ */
21
+ async function installFeatureDependency(featureName, context) {
22
+ const logger = context.logger;
23
+ // Resolve feature name to package name
24
+ // Dependencies are defined statically by feature authors, not user input.
25
+ // If a dependency is not found, it indicates a bug in the CLI or feature definition.
26
+ const feature = getFeatureMetadata(featureName);
27
+ if (!feature) {
28
+ throw new Error(`Internal error: feature dependency "${featureName}" not found in the feature registry. ` +
29
+ `This is a bug in the features CLI — please report it.`);
30
+ }
31
+ const packageName = feature.package;
32
+ const displayName = featureName;
33
+ // Check if already installed
34
+ if (context.installedFeatures.has(packageName)) {
35
+ logger.debug(`Feature dependency already installed: ${packageName}`);
36
+ return;
37
+ }
38
+ // Step 1: Install the package (before opening section, so npm output is suppressed)
39
+ if (!isPackageInstalled(packageName, context.uiBundleDir)) {
40
+ await installPackage(packageName, true, context.uiBundleDir, context.dryRun, context.verbose);
41
+ }
42
+ else {
43
+ logger.debug(`Package already in node_modules: ${packageName}`);
44
+ }
45
+ // Mark as installed to prevent duplicate processing
46
+ context.installedFeatures.add(packageName);
47
+ if (context.dryRun) {
48
+ logger.info(`[DRY RUN] Would process feature dependency schema: ${packageName}`);
49
+ return;
50
+ }
51
+ // Step 2: Build schema from feature metadata
52
+ const schema = {
53
+ featureDependencies: feature.featureDependencies,
54
+ packageDependencies: feature.packageDependencies,
55
+ packageDevDependencies: feature.packageDevDependencies,
56
+ copy: feature.copy,
57
+ };
58
+ logger.debug(`Processing schema for dependency: ${packageName}`);
59
+ // Step 3: Install sub-dependencies first (they get their own sections)
60
+ if (schema.featureDependencies && schema.featureDependencies.length > 0) {
61
+ await resolveFeatureDependencies(schema.featureDependencies, context);
62
+ }
63
+ // Step 4: Open section for THIS dependency
64
+ logger.section(`Installing dependency: ${displayName}`);
65
+ logger.plain(`Installing package: ${packageName}`);
66
+ // Step 5: Install package dependencies (inside section)
67
+ if (schema.packageDependencies || schema.packageDevDependencies) {
68
+ logger.blank();
69
+ await installPackageDependencies(schema, context);
70
+ }
71
+ // Step 6: Execute copy operations (inside section)
72
+ if (schema.copy && schema.copy.length > 0) {
73
+ logger.blank();
74
+ await executeCopyOperations(schema.copy, packageName, context);
75
+ }
76
+ logger.sectionEnd(`Dependency installed: ${displayName}`);
77
+ }
78
+ /**
79
+ * Process the "own" operations for a feature (package deps + copies),
80
+ * excluding recursive feature dependency resolution.
81
+ * Used by cli.ts for the main feature's section.
82
+ */
83
+ export async function processFeatureOwnOperations(schema, packageName, context) {
84
+ const logger = context.logger;
85
+ // Install packageDependencies
86
+ if (schema.packageDependencies || schema.packageDevDependencies) {
87
+ logger.blank();
88
+ await installPackageDependencies(schema, context);
89
+ }
90
+ // Execute copy operations
91
+ if (schema.copy && schema.copy.length > 0) {
92
+ logger.blank();
93
+ await executeCopyOperations(schema.copy, packageName, context);
94
+ }
95
+ }
96
+ //# sourceMappingURL=dependency-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-resolver.js","sourceRoot":"","sources":["../src/dependency-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ /**
7
+ * Describe a specific feature in detail
8
+ */
9
+ export declare function describeFeature(featureName: string): void;
10
+ //# sourceMappingURL=describe-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describe-command.d.ts","sourceRoot":"","sources":["../src/describe-command.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CA4HzD"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { getAllFeatures, getFeatureMetadata, resolveFeatureName, suggestSimilarFeatures, } from "./feature-metadata.js";
7
+ /**
8
+ * Describe a specific feature in detail
9
+ */
10
+ export function describeFeature(featureName) {
11
+ const resolvedName = resolveFeatureName(featureName);
12
+ if (!resolvedName) {
13
+ console.error(`\nFeature not found: ${featureName}\n`);
14
+ const suggestions = suggestSimilarFeatures(featureName);
15
+ if (suggestions.length > 0) {
16
+ console.log("Did you mean?");
17
+ for (const s of suggestions) {
18
+ console.log(` - ${s}`);
19
+ }
20
+ }
21
+ else {
22
+ console.log("Available features:");
23
+ const allFeatures = getAllFeatures();
24
+ for (const [name] of Object.entries(allFeatures)) {
25
+ console.log(` - ${name}`);
26
+ }
27
+ }
28
+ console.log('\nUse "npx @salesforce/ui-bundle-features list" to see all features\n');
29
+ process.exit(1);
30
+ }
31
+ const feature = getFeatureMetadata(resolvedName);
32
+ console.log("\n" + "=".repeat(80));
33
+ console.log(`${feature.name}`);
34
+ console.log("=".repeat(80));
35
+ console.log();
36
+ console.log("Description:");
37
+ console.log(` ${feature.longDescription}`);
38
+ console.log();
39
+ console.log("Package:", feature.package);
40
+ console.log();
41
+ if (feature.keywords && feature.keywords.length > 0) {
42
+ console.log("Keywords:", feature.keywords.join(", "));
43
+ console.log();
44
+ }
45
+ if (feature.featureDependencies && feature.featureDependencies.length > 0) {
46
+ console.log("Feature Dependencies:");
47
+ for (const dep of feature.featureDependencies) {
48
+ const depMeta = getFeatureMetadata(dep);
49
+ console.log(` - ${dep}${depMeta ? ` (${depMeta.package})` : ""}`);
50
+ }
51
+ console.log();
52
+ }
53
+ if (feature.packageDependencies && Object.keys(feature.packageDependencies).length > 0) {
54
+ console.log("Package Dependencies:");
55
+ for (const [pkg, version] of Object.entries(feature.packageDependencies)) {
56
+ console.log(` - ${pkg}@${version}`);
57
+ }
58
+ console.log();
59
+ }
60
+ if (feature.packageDevDependencies && Object.keys(feature.packageDevDependencies).length > 0) {
61
+ console.log("Package Dev Dependencies:");
62
+ for (const [pkg, version] of Object.entries(feature.packageDevDependencies)) {
63
+ console.log(` - ${pkg}@${version}`);
64
+ }
65
+ console.log();
66
+ }
67
+ if (feature.copy && feature.copy.length > 0) {
68
+ const regularCopies = feature.copy.filter((op) => !op.integrationTarget);
69
+ const exampleFiles = feature.copy.filter((op) => op.integrationTarget);
70
+ if (regularCopies.length > 0) {
71
+ console.log("Copy Operations:");
72
+ for (const op of regularCopies) {
73
+ console.log(` - ${op.from} → ${op.to}`);
74
+ if (op.description) {
75
+ console.log(` ${op.description}`);
76
+ }
77
+ }
78
+ console.log();
79
+ }
80
+ if (exampleFiles.length > 0) {
81
+ console.log("Integration Examples:");
82
+ console.log(" These __example__ files show how to integrate the feature:");
83
+ console.log();
84
+ for (const op of exampleFiles) {
85
+ console.log(` - ${op.to.split("/").pop()}`);
86
+ if (op.description) {
87
+ console.log(` ${op.description}`);
88
+ }
89
+ if (op.integrationTarget) {
90
+ console.log(` Review and integrate patterns into: ${op.integrationTarget}`);
91
+ console.log(` Then delete the example file`);
92
+ }
93
+ }
94
+ console.log();
95
+ }
96
+ }
97
+ if (feature.features && feature.features.length > 0) {
98
+ console.log("Features:");
99
+ for (const item of feature.features) {
100
+ console.log(` - ${item}`);
101
+ }
102
+ console.log();
103
+ }
104
+ if (feature.components && feature.components.length > 0) {
105
+ console.log("Components:");
106
+ for (const component of feature.components) {
107
+ console.log(` - ${component}`);
108
+ }
109
+ console.log();
110
+ }
111
+ console.log("Installation:");
112
+ console.log(` npx @salesforce/ui-bundle-features install ${resolvedName} --ui-bundle-dir <path>`);
113
+ console.log();
114
+ console.log("Example:");
115
+ console.log(` npx @salesforce/ui-bundle-features install ${resolvedName} \\`);
116
+ console.log(" --ui-bundle-dir force-app/main/default/uiBundles/my-ui-bundle");
117
+ console.log();
118
+ }
119
+ //# sourceMappingURL=describe-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describe-command.js","sourceRoot":"","sources":["../src/describe-command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import type { FeatureMetadata } from "./types.js";
7
+ /**
8
+ * Get all available features
9
+ */
10
+ export declare function getAllFeatures(): Record<string, FeatureMetadata>;
11
+ /**
12
+ * Resolve a feature name to its canonical (registry) key, matching case-insensitively.
13
+ * Returns the canonical key or null if no match is found.
14
+ */
15
+ export declare function resolveFeatureName(featureName: string): string | null;
16
+ /**
17
+ * Get metadata for a specific feature (case-insensitive).
18
+ */
19
+ export declare function getFeatureMetadata(featureName: string): FeatureMetadata | null;
20
+ /**
21
+ * Suggest similar feature names for a given input.
22
+ * Uses prefix matching and Levenshtein distance.
23
+ * Returns up to `max` suggestions sorted by relevance.
24
+ */
25
+ export declare function suggestSimilarFeatures(input: string, max?: number): string[];
26
+ /**
27
+ * Get feature name from package name
28
+ */
29
+ export declare function getFeatureNameFromPackage(packageName: string): string | null;
30
+ //# sourceMappingURL=feature-metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-metadata.d.ts","sourceRoot":"","sources":["../src/feature-metadata.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAoB,MAAM,YAAY,CAAC;AAsCpE;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAGhE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAcrE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAK9E;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAI,GAAG,MAAM,EAAE,CA0BvE;AAyBD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU5E"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { readFileSync } from "fs";
7
+ import { dirname, join } from "path";
8
+ import { fileURLToPath } from "url";
9
+ // Get the directory name for ES modules
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = dirname(__filename);
12
+ let metadataCache = null;
13
+ /**
14
+ * Load the features metadata from features.json
15
+ */
16
+ function loadMetadata() {
17
+ if (metadataCache) {
18
+ return metadataCache;
19
+ }
20
+ // Check __dirname first (works for both src/ via tsx and dist/ when compiled),
21
+ // then fall back to dist/ (for dev/test when running from src/).
22
+ const candidates = [
23
+ join(__dirname, "features.json"),
24
+ join(__dirname, "..", "dist", "features.json"),
25
+ ];
26
+ for (const metadataPath of candidates) {
27
+ try {
28
+ const content = readFileSync(metadataPath, "utf-8");
29
+ metadataCache = JSON.parse(content);
30
+ return metadataCache;
31
+ }
32
+ catch {
33
+ // Try next candidate
34
+ }
35
+ }
36
+ throw new Error(`Failed to load features.json: not found in ${candidates.join(", ")}. Run "npm run build" first.`);
37
+ }
38
+ /**
39
+ * Get all available features
40
+ */
41
+ export function getAllFeatures() {
42
+ const metadata = loadMetadata();
43
+ return metadata.features;
44
+ }
45
+ /**
46
+ * Resolve a feature name to its canonical (registry) key, matching case-insensitively.
47
+ * Returns the canonical key or null if no match is found.
48
+ */
49
+ export function resolveFeatureName(featureName) {
50
+ const metadata = loadMetadata();
51
+ // Exact match first
52
+ if (metadata.features[featureName]) {
53
+ return featureName;
54
+ }
55
+ // Case-insensitive match
56
+ const lower = featureName.toLowerCase();
57
+ for (const key of Object.keys(metadata.features)) {
58
+ if (key.toLowerCase() === lower) {
59
+ return key;
60
+ }
61
+ }
62
+ return null;
63
+ }
64
+ /**
65
+ * Get metadata for a specific feature (case-insensitive).
66
+ */
67
+ export function getFeatureMetadata(featureName) {
68
+ const resolved = resolveFeatureName(featureName);
69
+ if (!resolved)
70
+ return null;
71
+ const metadata = loadMetadata();
72
+ return metadata.features[resolved] || null;
73
+ }
74
+ /**
75
+ * Suggest similar feature names for a given input.
76
+ * Uses prefix matching and Levenshtein distance.
77
+ * Returns up to `max` suggestions sorted by relevance.
78
+ */
79
+ export function suggestSimilarFeatures(input, max = 3) {
80
+ const allFeatures = getAllFeatures();
81
+ const names = Object.keys(allFeatures);
82
+ const lower = input.toLowerCase();
83
+ const scored = names.map((name) => {
84
+ const nameLower = name.toLowerCase();
85
+ // Prefix match: input is a prefix of the feature name or vice versa
86
+ if (nameLower.startsWith(lower) || lower.startsWith(nameLower)) {
87
+ return { name, distance: 0 };
88
+ }
89
+ // Substring match: input appears within the feature name
90
+ if (nameLower.includes(lower)) {
91
+ return { name, distance: 1 };
92
+ }
93
+ return { name, distance: levenshtein(lower, nameLower) };
94
+ });
95
+ scored.sort((a, b) => a.distance - b.distance);
96
+ // Only suggest features within a reasonable edit distance
97
+ const maxDistance = Math.max(3, Math.floor(input.length / 2));
98
+ return scored
99
+ .filter((s) => s.distance <= maxDistance)
100
+ .slice(0, max)
101
+ .map((s) => s.name);
102
+ }
103
+ /**
104
+ * Simple Levenshtein distance between two strings.
105
+ */
106
+ function levenshtein(a, b) {
107
+ const m = a.length;
108
+ const n = b.length;
109
+ const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
110
+ for (let i = 0; i <= m; i++)
111
+ dp[i][0] = i;
112
+ for (let j = 0; j <= n; j++)
113
+ dp[0][j] = j;
114
+ for (let i = 1; i <= m; i++) {
115
+ for (let j = 1; j <= n; j++) {
116
+ dp[i][j] =
117
+ a[i - 1] === b[j - 1]
118
+ ? dp[i - 1][j - 1]
119
+ : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
120
+ }
121
+ }
122
+ return dp[m][n];
123
+ }
124
+ /**
125
+ * Get feature name from package name
126
+ */
127
+ export function getFeatureNameFromPackage(packageName) {
128
+ const allFeatures = getAllFeatures();
129
+ for (const [featureName, feature] of Object.entries(allFeatures)) {
130
+ if (feature.package === packageName) {
131
+ return featureName;
132
+ }
133
+ }
134
+ return null;
135
+ }
136
+ //# sourceMappingURL=feature-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-metadata.js","sourceRoot":"","sources":["../src/feature-metadata.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import type { FeatureMetadata } from "./types.js";
7
+ /**
8
+ * Search features by keyword with scoring and ranking
9
+ */
10
+ export declare function searchFeatures(query: string): FeatureMetadata[];
11
+ /**
12
+ * Get feature metadata or throw a descriptive error with search suggestions.
13
+ * Use this when a feature MUST exist (e.g., install commands).
14
+ */
15
+ export declare function getFeatureMetadataOrThrow(featureName: string): Readonly<FeatureMetadata>;
16
+ //# sourceMappingURL=feature-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-search.d.ts","sourceRoot":"","sources":["../src/feature-search.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAuGlD;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,EAAE,CA2B/D;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,CAAC,eAAe,CAAC,CAuBxF"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { getAllFeatures, getFeatureMetadata, suggestSimilarFeatures } from "./feature-metadata.js";
7
+ /**
8
+ * Score a feature against search terms
9
+ * @internal
10
+ */
11
+ function scoreFeature(feature, terms, originalQuery) {
12
+ let score = 0;
13
+ const matchedFields = [];
14
+ const matchedTerms = new Set();
15
+ // Prepare searchable text fields (lowercase for case-insensitive matching)
16
+ const nameLower = feature.name.toLowerCase();
17
+ const shortDescLower = feature.shortDescription.toLowerCase();
18
+ const longDescLower = feature.longDescription.toLowerCase();
19
+ const keywordsLower = feature.keywords.map((k) => k.toLowerCase());
20
+ const featuresLower = (feature.features || []).map((f) => f.toLowerCase());
21
+ const componentsLower = (feature.components || []).map((c) => c.toLowerCase());
22
+ // Check for exact feature name match (highest priority)
23
+ if (nameLower === originalQuery) {
24
+ score += 1000;
25
+ matchedFields.push("name (exact)");
26
+ terms.forEach((t) => matchedTerms.add(t));
27
+ }
28
+ // Check each search term
29
+ for (const term of terms) {
30
+ // Name match (partial)
31
+ if (nameLower.includes(term)) {
32
+ score += 500;
33
+ matchedFields.push(`name: "${term}"`);
34
+ matchedTerms.add(term);
35
+ }
36
+ // Exact keyword match
37
+ if (keywordsLower.some((kw) => kw === term)) {
38
+ score += 400;
39
+ matchedFields.push(`keyword: "${term}"`);
40
+ matchedTerms.add(term);
41
+ }
42
+ else if (keywordsLower.some((kw) => kw.includes(term))) {
43
+ // Partial keyword match (less weight)
44
+ score += 300;
45
+ matchedFields.push(`keyword partial: "${term}"`);
46
+ matchedTerms.add(term);
47
+ }
48
+ // Short description match
49
+ if (shortDescLower.includes(term)) {
50
+ score += 300;
51
+ matchedFields.push(`short description: "${term}"`);
52
+ matchedTerms.add(term);
53
+ }
54
+ // Components match
55
+ const matchingComponent = componentsLower.find((c) => c.includes(term));
56
+ if (matchingComponent) {
57
+ score += 250;
58
+ matchedFields.push(`component: "${term}"`);
59
+ matchedTerms.add(term);
60
+ }
61
+ // Features/capabilities match
62
+ const matchingFeature = featuresLower.find((f) => f.includes(term));
63
+ if (matchingFeature) {
64
+ score += 200;
65
+ matchedFields.push(`feature: "${term}"`);
66
+ matchedTerms.add(term);
67
+ }
68
+ // Long description match
69
+ if (longDescLower.includes(term)) {
70
+ score += 100;
71
+ matchedFields.push(`long description: "${term}"`);
72
+ matchedTerms.add(term);
73
+ }
74
+ }
75
+ // Bonus: Term coverage (rewards matching more search terms)
76
+ score += matchedTerms.size * 100;
77
+ // Bonus: Phrase match (all terms appear consecutively as a phrase)
78
+ const allText = [
79
+ nameLower,
80
+ shortDescLower,
81
+ longDescLower,
82
+ ...keywordsLower,
83
+ ...featuresLower,
84
+ ...componentsLower,
85
+ ].join(" ");
86
+ if (allText.includes(originalQuery)) {
87
+ score += 200;
88
+ matchedFields.push("phrase match");
89
+ }
90
+ return { score, matchedFields };
91
+ }
92
+ /**
93
+ * Search features by keyword with scoring and ranking
94
+ */
95
+ export function searchFeatures(query) {
96
+ const allFeatures = getAllFeatures();
97
+ // Parse query into search terms (split on whitespace)
98
+ const terms = query.toLowerCase().trim().split(/\s+/);
99
+ const originalQuery = query.toLowerCase().trim();
100
+ // Score each feature
101
+ const scoredResults = [];
102
+ for (const feature of Object.values(allFeatures)) {
103
+ const result = scoreFeature(feature, terms, originalQuery);
104
+ // Only include features that have at least one match (score > 0)
105
+ if (result.score > 0) {
106
+ scoredResults.push({
107
+ feature,
108
+ score: result.score,
109
+ });
110
+ }
111
+ }
112
+ // Sort by score descending (highest score first)
113
+ scoredResults.sort((a, b) => b.score - a.score);
114
+ // Return just the features (maintains backwards compatibility)
115
+ return scoredResults.map((r) => r.feature);
116
+ }
117
+ /**
118
+ * Get feature metadata or throw a descriptive error with search suggestions.
119
+ * Use this when a feature MUST exist (e.g., install commands).
120
+ */
121
+ export function getFeatureMetadataOrThrow(featureName) {
122
+ const feature = getFeatureMetadata(featureName);
123
+ if (feature) {
124
+ return feature;
125
+ }
126
+ const searchResults = searchFeatures(featureName);
127
+ if (searchResults.length > 0) {
128
+ const suggestions = searchResults
129
+ .slice(0, 5)
130
+ .map((f) => ` - ${f.name}: ${f.shortDescription}`)
131
+ .join("\n");
132
+ throw new Error(`Feature "${featureName}" not found. Did you mean one of these?\n${suggestions}`);
133
+ }
134
+ const similar = suggestSimilarFeatures(featureName);
135
+ if (similar.length > 0) {
136
+ throw new Error(`Feature "${featureName}" not found. Similar features: ${similar.join(", ")}`);
137
+ }
138
+ throw new Error(`Feature "${featureName}" not found. Use "list" to see available features.`);
139
+ }
140
+ //# sourceMappingURL=feature-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-search.js","sourceRoot":"","sources":["../src/feature-search.ts"],"names":[],"mappings":"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"}