@devilsdev/rag-pipeline-utils 2.3.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/README.md +293 -369
  2. package/contracts/loader-contract.json +11 -6
  3. package/contracts/reranker-contract.json +18 -26
  4. package/dist/index.cjs +21190 -47
  5. package/dist/index.d.ts +298 -68
  6. package/dist/index.mjs +9 -76
  7. package/package.json +20 -8
  8. package/src/agentic/agentic-pipeline.js +235 -0
  9. package/src/agentic/iterative-retriever.js +213 -0
  10. package/src/agentic/query-planner.js +208 -0
  11. package/src/agentic/self-critique.js +102 -0
  12. package/src/ai/adaptive-retrieval.js +0 -3
  13. package/src/ai/federated-learning.js +0 -3
  14. package/src/ai/federation.js +1 -6
  15. package/src/ai/index.js +9 -20
  16. package/src/ai/model-training.js +0 -3
  17. package/src/ai/multimodal-processing.js +0 -3
  18. package/src/ai/multimodal.js +1 -6
  19. package/src/ai/orchestrator.js +1 -6
  20. package/src/ai/retrieval-engine.js +1 -6
  21. package/src/chunking/chunking-engine.js +142 -0
  22. package/src/chunking/strategies/fixed-size.js +54 -0
  23. package/src/chunking/strategies/recursive.js +127 -0
  24. package/src/chunking/strategies/semantic.js +128 -0
  25. package/src/chunking/strategies/sentence.js +32 -0
  26. package/src/chunking/strategies/structure-aware.js +138 -0
  27. package/src/citation/citation-tracker.js +161 -0
  28. package/src/citation/hallucination-detector.js +74 -0
  29. package/src/citation/source-mapper.js +95 -0
  30. package/src/cli/commands/ai-ml/adaptive-commands.js +178 -0
  31. package/src/cli/commands/ai-ml/federated-commands.js +207 -0
  32. package/src/cli/commands/ai-ml/index.js +17 -0
  33. package/src/cli/commands/ai-ml/multimodal-commands.js +187 -0
  34. package/src/cli/commands/ai-ml/shared.js +51 -0
  35. package/src/cli/commands/ai-ml/training-commands.js +228 -0
  36. package/src/cli/commands/ai-ml.js +176 -757
  37. package/src/cli/commands/plugin-hub/certification-commands.js +221 -0
  38. package/src/cli/commands/plugin-hub/event-handlers.js +64 -0
  39. package/src/cli/commands/plugin-hub/hub-commands.js +290 -0
  40. package/src/cli/commands/plugin-hub/review-commands.js +78 -0
  41. package/src/cli/commands/plugin-hub.js +106 -782
  42. package/src/cli/diagnostics/config-checker.js +81 -0
  43. package/src/cli/diagnostics/dependency-checker.js +69 -0
  44. package/src/cli/diagnostics/environment-checker.js +45 -0
  45. package/src/cli/diagnostics/performance-checker.js +51 -0
  46. package/src/cli/diagnostics/plugin-checker.js +106 -0
  47. package/src/cli/diagnostics/security-checker.js +61 -0
  48. package/src/cli/doctor-command.js +70 -369
  49. package/src/cli/enhanced-cli-commands.js +162 -706
  50. package/src/cli/handlers/config-handler.js +126 -0
  51. package/src/cli/handlers/diagnostics-handler.js +113 -0
  52. package/src/cli/handlers/ingest-handler.js +42 -0
  53. package/src/cli/handlers/init-handler.js +51 -0
  54. package/src/cli/handlers/query-handler.js +45 -0
  55. package/src/cli/handlers/run-handler.js +181 -0
  56. package/src/cli/interactive-wizard.js +99 -723
  57. package/src/cli/shared/cli-utils.js +89 -0
  58. package/src/cli/wizard/configuration.js +148 -0
  59. package/src/cli/wizard/observability.js +79 -0
  60. package/src/cli/wizard/performance.js +76 -0
  61. package/src/cli/wizard/plugin-selection.js +297 -0
  62. package/src/cli/wizard/preview-save.js +172 -0
  63. package/src/cli/wizard/project-setup.js +66 -0
  64. package/src/config/memory-optimization.js +3 -3
  65. package/src/connectors/anthropic-connector.js +179 -0
  66. package/src/connectors/base-connector.js +94 -0
  67. package/src/connectors/cohere-connector.js +143 -0
  68. package/src/connectors/local-embedder.js +171 -0
  69. package/src/connectors/memory-retriever.js +150 -0
  70. package/src/connectors/ollama-connector.js +205 -0
  71. package/src/connectors/openai-connector.js +173 -0
  72. package/src/core/create-pipeline.js +21 -1
  73. package/src/core/observability/tracing.js +2 -1
  74. package/src/core/pipeline-factory.js +0 -1
  75. package/src/core/plugin-registry.js +14 -14
  76. package/src/cost/cost-calculator.js +146 -0
  77. package/src/cost/cost-tracker.js +260 -0
  78. package/src/cost/token-budget.js +245 -0
  79. package/src/dag/core/execution-scheduler.js +2 -1
  80. package/src/dag/core/topology-validation.js +0 -3
  81. package/src/dag/dag-engine.js +3 -5
  82. package/src/dag/dag-node.js +0 -1
  83. package/src/dag/enhanced-dag-engine.js +171 -99
  84. package/src/dashboard/dashboard-generator.js +642 -0
  85. package/src/dashboard/metrics-aggregator.js +409 -0
  86. package/src/debug/execution-tracer.js +210 -0
  87. package/src/debug/trace-inspector.js +281 -0
  88. package/src/dev/dev-server.js +5 -5
  89. package/src/dev/hot-reload.js +3 -2
  90. package/src/dx/integration-templates.js +0 -3
  91. package/src/ecosystem/plugin-analytics-dashboard.js +2 -2
  92. package/src/ecosystem/plugin-hub.js +2 -2
  93. package/src/enterprise/audit-logging.js +2 -2
  94. package/src/enterprise/sso-integration.js +52 -32
  95. package/src/evaluate/context-metrics.js +127 -0
  96. package/src/evaluate/evaluator.js +4 -2
  97. package/src/evaluate/faithfulness.js +117 -0
  98. package/src/evaluate/groundedness.js +60 -0
  99. package/src/evaluate/pipeline-evaluator.js +156 -0
  100. package/src/evaluate/relevance.js +129 -0
  101. package/src/evaluate/scoring.js +27 -0
  102. package/src/graph/entity-extractor.js +183 -0
  103. package/src/graph/graph-index.js +113 -0
  104. package/src/graph/graph-retriever.js +244 -0
  105. package/src/graph/knowledge-graph.js +256 -0
  106. package/src/guardrails/guardrails-pipeline.js +136 -0
  107. package/src/guardrails/post-generation-guard.js +170 -0
  108. package/src/guardrails/pre-retrieval-guard.js +161 -0
  109. package/src/guardrails/retrieval-guard.js +126 -0
  110. package/src/index.js +255 -9
  111. package/src/loader/html-loader.js +4 -15
  112. package/src/loader/markdown-loader.js +4 -15
  113. package/src/mcp/mcp-server.js +199 -0
  114. package/src/mcp/mcp-tool-builder.js +121 -0
  115. package/src/observability/audit-logger.js +0 -2
  116. package/src/observability/event-logger.js +2 -1
  117. package/src/observability/security-monitor.js +0 -2
  118. package/src/observability/telemetry.js +0 -2
  119. package/src/reranker/cascade-reranker.js +79 -0
  120. package/src/reranker/embedding-reranker.js +124 -0
  121. package/src/reranker/llm-reranker.js +6 -3
  122. package/src/reranker/scoring-reranker.js +123 -0
  123. package/src/retrieval/bm25-search.js +157 -0
  124. package/src/retrieval/hybrid-retriever.js +111 -0
  125. package/src/retrieval/rank-fusion.js +62 -0
  126. package/src/security/jwt-config.js +4 -3
  127. package/src/security/jwt-validator.js +2 -1
  128. package/src/security/plugin-sandbox.js +0 -3
  129. package/src/security/plugin-signature-verifier.js +4 -6
  130. package/src/security/validator.js +0 -2
  131. package/src/streaming/embedding-stream.js +197 -0
  132. package/src/streaming/sse-adapter.js +168 -0
  133. package/src/streaming/stream-router.js +210 -0
  134. package/src/streaming/streaming-embedder.js +231 -0
  135. package/src/streaming/websocket-adapter.js +171 -0
  136. package/src/templates/scaffold.js +147 -0
  137. package/src/templates/template-registry.js +272 -0
  138. package/src/utils/contract-validator.js +2 -1
  139. package/src/utils/input-sanitizer.js +80 -99
  140. package/src/utils/performance-monitor.js +0 -3
  141. package/src/utils/plugin-scaffolder.js +9 -16
  142. package/src/utils/rate-limiter.js +0 -1
  143. package/src/utils/retry-policy.js +0 -3
  144. package/src/utils/safe-expression-evaluator.js +0 -3
  145. package/src/utils/secure-logger-config.js +2 -4
  146. package/src/utils/secure-logging.js +0 -3
  147. package/src/utils/structured-logger.js +0 -3
  148. package/src/ai/index-fixed.js +0 -509
  149. package/src/ai/module-template.js +0 -37
  150. package/src/ci/workflow-analyzer.js +0 -71
  151. package/src/cli/plugin-marketplace-commands.js +0 -869
  152. package/src/dev/README.md +0 -126
  153. package/src/dev/examples/hot-reload-usage.js +0 -355
  154. package/src/mocks/openai-embedder.js +0 -119
  155. package/src/mocks/openai-llm.js +0 -77
  156. package/src/mocks/pdf-loader.js +0 -21
  157. package/src/mocks/pinecone-retriever.js +0 -106
  158. package/src/scripts/script-utilities.js +0 -36
  159. package/src/utils/ci/diagnostic-reporter.js +0 -57
  160. package/src/utils/examples/error-formatter-usage.js +0 -351
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Certification Commands
3
+ * Plugin certification and publisher verification operations
4
+ */
5
+
6
+ const chalk = require("chalk");
7
+ const ora = require("ora");
8
+ const inquirer = require("inquirer");
9
+ const Table = require("cli-table3");
10
+
11
+ async function submitForCertification(certification, plugin, options) {
12
+ try {
13
+ const result = await certification.submitForCertification(
14
+ plugin,
15
+ options.level,
16
+ );
17
+
18
+ console.log(chalk.green("\nšŸ† Certification submitted successfully!")); // eslint-disable-line no-console
19
+ console.log(chalk.blue(`Certification ID: ${result.id}`)); // eslint-disable-line no-console
20
+ console.log(chalk.blue(`Level: ${result.level}`)); // eslint-disable-line no-console
21
+ console.log(chalk.blue(`Score: ${result.score}/100`)); // eslint-disable-line no-console
22
+ console.log(chalk.blue(`Status: ${result.status || "Pending"}`)); // eslint-disable-line no-console
23
+
24
+ if (result.estimatedCompletion) {
25
+ console.log(
26
+ chalk.blue(`Estimated completion: ${result.estimatedCompletion}`),
27
+ ); // eslint-disable-line no-console
28
+ }
29
+ } catch (error) {
30
+ console.error(
31
+ chalk.red(`Certification submission failed: ${error.message}`),
32
+ ); // eslint-disable-line no-console
33
+ process.exit(1);
34
+ }
35
+ }
36
+
37
+ async function verifyCertification(certification, plugin, certificationId) {
38
+ const spinner = ora("Verifying certification...").start();
39
+
40
+ try {
41
+ const verification = await certification.verifyCertification(
42
+ plugin,
43
+ certificationId,
44
+ );
45
+ spinner.stop();
46
+
47
+ if (verification.valid) {
48
+ console.log(chalk.green("āœ… Certification is valid!")); // eslint-disable-line no-console
49
+ console.log(chalk.blue(`Plugin: ${plugin}`)); // eslint-disable-line no-console
50
+ console.log(chalk.blue(`Level: ${verification.certification.level}`)); // eslint-disable-line no-console
51
+ console.log(
52
+ chalk.blue(
53
+ `Expires: ${new Date(verification.expiresAt).toLocaleDateString()}`,
54
+ ),
55
+ ); // eslint-disable-line no-console
56
+ } else {
57
+ console.log(chalk.red("āŒ Certification is invalid or expired")); // eslint-disable-line no-console
58
+ }
59
+ } catch (error) {
60
+ spinner.stop();
61
+ console.error(chalk.red(`Verification failed: ${error.message}`)); // eslint-disable-line no-console
62
+ process.exit(1);
63
+ }
64
+ }
65
+
66
+ async function showCertificationRequirements(certification, level) {
67
+ const levels = level ? [level] : ["BASIC", "VERIFIED", "ENTERPRISE"];
68
+
69
+ for (const certLevel of levels) {
70
+ const requirements = certification.getCertificationRequirements(certLevel);
71
+
72
+ if (!requirements) {
73
+ console.log(chalk.red(`Unknown certification level: ${certLevel}`)); // eslint-disable-line no-console
74
+ continue;
75
+ }
76
+
77
+ console.log(
78
+ chalk.blue.bold(`\n${certLevel} Certification Requirements:\n`),
79
+ ); // eslint-disable-line no-console
80
+
81
+ console.log(chalk.green("Automated Checks:")); // eslint-disable-line no-console
82
+ requirements.automated.forEach((check) => {
83
+ console.log(chalk.gray(` • ${check}`)); // eslint-disable-line no-console
84
+ });
85
+
86
+ if (requirements.manual.length > 0) {
87
+ console.log(chalk.yellow("\nManual Review:")); // eslint-disable-line no-console
88
+ requirements.manual.forEach((review) => {
89
+ console.log(chalk.gray(` • ${review}`)); // eslint-disable-line no-console
90
+ });
91
+ }
92
+
93
+ if (requirements.audit.length > 0) {
94
+ console.log(chalk.red("\nSecurity Audit:")); // eslint-disable-line no-console
95
+ requirements.audit.forEach((audit) => {
96
+ console.log(chalk.gray(` • ${audit}`)); // eslint-disable-line no-console
97
+ });
98
+ }
99
+
100
+ console.log(chalk.blue(`\nMinimum Score: ${requirements.minScore}/100`)); // eslint-disable-line no-console
101
+ console.log(chalk.blue(`Validity Period: ${requirements.validityPeriod}`)); // eslint-disable-line no-console
102
+ }
103
+ }
104
+
105
+ async function getPublisherStatus(certification, publisherId) {
106
+ const spinner = ora("Checking publisher status...").start();
107
+
108
+ try {
109
+ const status = await certification.getPublisherStatus(publisherId || "me");
110
+ spinner.stop();
111
+
112
+ console.log(chalk.blue.bold("\nPublisher Status:\n")); // eslint-disable-line no-console
113
+
114
+ const table = new Table({
115
+ chars: {
116
+ top: "",
117
+ "top-mid": "",
118
+ "top-left": "",
119
+ "top-right": "",
120
+ bottom: "",
121
+ "bottom-mid": "",
122
+ "bottom-left": "",
123
+ "bottom-right": "",
124
+ left: "",
125
+ "left-mid": "",
126
+ mid: "",
127
+ "mid-mid": "",
128
+ right: "",
129
+ "right-mid": "",
130
+ middle: " ",
131
+ },
132
+ style: { "padding-left": 0, "padding-right": 0 },
133
+ });
134
+
135
+ table.push(
136
+ ["Verified:", status.verified ? chalk.green("Yes āœ“") : chalk.gray("No")],
137
+ ["Level:", status.level || chalk.gray("None")],
138
+ ["Certified Plugins:", status.certifiedPlugins.toString()],
139
+ ["Reputation:", status.reputation.toString()],
140
+ ["Member Since:", new Date(status.joinedAt).toLocaleDateString()],
141
+ ["Last Activity:", new Date(status.lastActivity).toLocaleDateString()],
142
+ );
143
+
144
+ console.log(table.toString()); // eslint-disable-line no-console
145
+
146
+ if (status.badges && status.badges.length > 0) {
147
+ console.log(chalk.blue("\nBadges:"), status.badges.join(", ")); // eslint-disable-line no-console
148
+ }
149
+ } catch (error) {
150
+ spinner.stop();
151
+ console.error(
152
+ chalk.red(`Failed to get publisher status: ${error.message}`),
153
+ ); // eslint-disable-line no-console
154
+ process.exit(1);
155
+ }
156
+ }
157
+
158
+ async function applyForPublisherVerification(certification) {
159
+ console.log(chalk.blue("šŸ“ Publisher Verification Application\n")); // eslint-disable-line no-console
160
+
161
+ const answers = await inquirer.prompt([
162
+ {
163
+ _type: "input",
164
+ name: "name",
165
+ message: "Full name:",
166
+ validate: (input) => input.length > 0,
167
+ },
168
+ {
169
+ _type: "input",
170
+ name: "email",
171
+ message: "Email address:",
172
+ validate: (input) => /\S+@\S+\.\S+/.test(input),
173
+ },
174
+ {
175
+ _type: "input",
176
+ name: "organization",
177
+ message: "Organization (optional):",
178
+ },
179
+ {
180
+ _type: "input",
181
+ name: "website",
182
+ message: "Website/Portfolio:",
183
+ },
184
+ {
185
+ _type: "input",
186
+ name: "github",
187
+ message: "GitHub profile:",
188
+ },
189
+ {
190
+ _type: "editor",
191
+ name: "motivation",
192
+ message: "Why do you want to become a verified publisher?",
193
+ },
194
+ ]);
195
+
196
+ const spinner = ora("Submitting application...").start();
197
+
198
+ try {
199
+ const result = await certification.applyForPublisherVerification(answers);
200
+ spinner.stop();
201
+
202
+ console.log(chalk.green("\nāœ… Application submitted successfully!")); // eslint-disable-line no-console
203
+ console.log(chalk.blue(`Application ID: ${result.applicationId}`)); // eslint-disable-line no-console
204
+ console.log(chalk.blue(`Status: ${result.status}`)); // eslint-disable-line no-console
205
+ console.log(
206
+ chalk.blue(`Estimated review time: ${result.estimatedReviewTime}`),
207
+ ); // eslint-disable-line no-console
208
+ } catch (error) {
209
+ spinner.stop();
210
+ console.error(chalk.red(`Application failed: ${error.message}`)); // eslint-disable-line no-console
211
+ process.exit(1);
212
+ }
213
+ }
214
+
215
+ module.exports = {
216
+ submitForCertification,
217
+ verifyCertification,
218
+ showCertificationRequirements,
219
+ getPublisherStatus,
220
+ applyForPublisherVerification,
221
+ };
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Event Handlers
3
+ * Event listener setup for hub and certification instances
4
+ */
5
+
6
+ const chalk = require("chalk");
7
+
8
+ function setupEventListeners(hub, certification) {
9
+ // Hub events
10
+ hub.on("install_start", (data) => {
11
+ console.log(
12
+ chalk.blue(
13
+ `šŸš€ Starting installation of ${data.pluginId}@${data.version}`,
14
+ ),
15
+ ); // eslint-disable-line no-console
16
+ });
17
+
18
+ hub.on("install_progress", (data) => {
19
+ const stages = {
20
+ security_scan: "šŸ” Running security scan...",
21
+ downloading: "ā¬‡ļø Downloading plugin...",
22
+ verifying: "āœ… Verifying integrity...",
23
+ sandbox_install: "šŸ—ļø Installing in sandbox...",
24
+ installing: "šŸ“¦ Installing to system...",
25
+ };
26
+ console.log(
27
+ chalk.yellow(stages[data.stage] || `Processing ${data.stage}...`),
28
+ ); // eslint-disable-line no-console
29
+ });
30
+
31
+ hub.on("install_complete", (data) => {
32
+ console.log(
33
+ chalk.green(`āœ… Successfully installed ${data.pluginId}@${data.version}`),
34
+ ); // eslint-disable-line no-console
35
+ });
36
+
37
+ hub.on("install_error", (data) => {
38
+ console.error(chalk.red(`āŒ Installation failed: ${data.error.message}`)); // eslint-disable-line no-console
39
+ });
40
+
41
+ // Certification events
42
+ certification.on("certification_start", (data) => {
43
+ console.log(
44
+ chalk.blue(
45
+ `šŸ† Starting ${data.level} certification for ${data.pluginId}`,
46
+ ),
47
+ ); // eslint-disable-line no-console
48
+ });
49
+
50
+ certification.on("certification_progress", (data) => {
51
+ const stages = {
52
+ automated_checks: "šŸ¤– Running automated checks...",
53
+ manual_review: "šŸ‘„ Submitting for manual review...",
54
+ security_audit: "šŸ”’ Performing security audit...",
55
+ };
56
+ console.log(
57
+ chalk.yellow(stages[data.stage] || `Processing ${data.stage}...`),
58
+ ); // eslint-disable-line no-console
59
+ });
60
+ }
61
+
62
+ module.exports = {
63
+ setupEventListeners,
64
+ };
@@ -0,0 +1,290 @@
1
+ /**
2
+ * Hub Commands
3
+ * Core plugin hub operations: search, install, info, list, publish, trending
4
+ */
5
+
6
+ const chalk = require("chalk");
7
+ const ora = require("ora");
8
+ const Table = require("cli-table3");
9
+
10
+ async function searchPlugins(hub, query, _options) {
11
+ const spinner = ora("Searching plugins...").start();
12
+
13
+ try {
14
+ const searchOptions = {
15
+ category: _options.category,
16
+ tags: _options.tags ? _options.tags.split(",") : undefined,
17
+ author: _options.author,
18
+ minRating: _options.minRating,
19
+ verified: _options.verified,
20
+ limit: _options.limit,
21
+ sortBy: _options.sort,
22
+ };
23
+
24
+ const results = await hub.searchPlugins(query, searchOptions);
25
+ spinner.stop();
26
+
27
+ if (results.results.length === 0) {
28
+ console.log(chalk.yellow("No plugins found matching your criteria.")); // eslint-disable-line no-console
29
+ return;
30
+ }
31
+
32
+ console.log(chalk.green(`Found ${results.total} plugins:\n`)); // eslint-disable-line no-console
33
+
34
+ const table = new Table({
35
+ head: ["Name", "Version", "Author", "Rating", "Downloads", "Description"],
36
+ colWidths: [20, 10, 15, 8, 10, 40],
37
+ });
38
+
39
+ for (const plugin of results.results) {
40
+ const rating =
41
+ "ā˜…".repeat(Math.floor(plugin.rating)) +
42
+ "ā˜†".repeat(5 - Math.floor(plugin.rating));
43
+ const certified = plugin.certified ? chalk.green("āœ“") : "";
44
+
45
+ table.push([
46
+ `${plugin.name} ${certified}`,
47
+ plugin.version,
48
+ plugin.author,
49
+ `${rating} (${plugin.reviewCount})`,
50
+ plugin.downloadCount.toLocaleString(),
51
+ plugin.description.substring(0, 35) +
52
+ (plugin.description.length > 35 ? "..." : ""),
53
+ ]);
54
+ }
55
+
56
+ console.log(table.toString()); // eslint-disable-line no-console
57
+
58
+ if (results.hasMore) {
59
+ console.log(
60
+ chalk.blue(
61
+ `\nShowing ${results.results.length} of ${results.total} results. Use --limit to see more.`,
62
+ ),
63
+ ); // eslint-disable-line no-console
64
+ }
65
+ } catch (error) {
66
+ spinner.stop();
67
+ console.error(chalk.red(`Search failed: ${error.message}`)); // eslint-disable-line no-console
68
+ process.exit(1);
69
+ }
70
+ }
71
+
72
+ async function installPlugin(hub, plugin, _options) {
73
+ try {
74
+ const installOptions = {
75
+ securityScan: _options.securityScan,
76
+ requireCertified: _options.requireCertified,
77
+ sandboxTimeout: _options.sandboxTimeout,
78
+ };
79
+
80
+ const result = await hub.installPlugin(
81
+ plugin,
82
+ _options.version,
83
+ installOptions,
84
+ );
85
+
86
+ console.log(chalk.green("\nāœ… Installation completed successfully!")); // eslint-disable-line no-console
87
+ console.log(chalk.blue(`Plugin: ${result.pluginInfo.name}`)); // eslint-disable-line no-console
88
+ console.log(chalk.blue(`Version: ${result.version}`)); // eslint-disable-line no-console
89
+ console.log(chalk.blue(`Install Path: ${result.installPath}`)); // eslint-disable-line no-console
90
+
91
+ if (result.pluginInfo.certified) {
92
+ console.log(chalk.green("šŸ† This plugin is certified!")); // eslint-disable-line no-console
93
+ }
94
+ } catch (error) {
95
+ console.error(chalk.red(`Installation failed: ${error.message}`)); // eslint-disable-line no-console
96
+ process.exit(1);
97
+ }
98
+ }
99
+
100
+ async function getPluginInfo(hub, plugin) {
101
+ const spinner = ora("Fetching plugin information...").start();
102
+
103
+ try {
104
+ const info = await hub.getPluginInfo(plugin);
105
+ spinner.stop();
106
+
107
+ console.log(chalk.blue.bold(`\n${info.name} v${info.version}\n`)); // eslint-disable-line no-console
108
+ console.log(chalk.gray(info.description)); // eslint-disable-line no-console
109
+ console.log(); // eslint-disable-line no-console
110
+
111
+ const details = new Table({
112
+ chars: {
113
+ top: "",
114
+ "top-mid": "",
115
+ "top-left": "",
116
+ "top-right": "",
117
+ bottom: "",
118
+ "bottom-mid": "",
119
+ "bottom-left": "",
120
+ "bottom-right": "",
121
+ left: "",
122
+ "left-mid": "",
123
+ mid: "",
124
+ "mid-mid": "",
125
+ right: "",
126
+ "right-mid": "",
127
+ middle: " ",
128
+ },
129
+ style: { "padding-left": 0, "padding-right": 0 },
130
+ });
131
+
132
+ const rating =
133
+ "ā˜…".repeat(Math.floor(info.rating)) +
134
+ "ā˜†".repeat(5 - Math.floor(info.rating));
135
+
136
+ details.push(
137
+ ["Author:", info.author],
138
+ ["Category:", info.category],
139
+ ["Rating:", `${rating} (${info.reviewCount} reviews)`],
140
+ ["Downloads:", info.downloadCount.toLocaleString()],
141
+ ["License:", info.license],
142
+ ["Last Updated:", new Date(info.lastUpdated).toLocaleDateString()],
143
+ ["Certified:", info.certified ? chalk.green("Yes āœ“") : chalk.gray("No")],
144
+ [
145
+ "Verified Publisher:",
146
+ info.verifiedPublisher ? chalk.green("Yes āœ“") : chalk.gray("No"),
147
+ ],
148
+ );
149
+
150
+ console.log(details.toString()); // eslint-disable-line no-console
151
+
152
+ if (info.tags && info.tags.length > 0) {
153
+ console.log(
154
+ chalk.blue("\nTags:"),
155
+ info.tags.map((tag) => chalk.cyan(`#${tag}`)).join(" "),
156
+ ); // eslint-disable-line no-console
157
+ }
158
+
159
+ if (info.homepage) {
160
+ console.log(chalk.blue("\nHomepage:"), chalk.underline(info.homepage)); // eslint-disable-line no-console
161
+ }
162
+
163
+ if (info.repository) {
164
+ console.log(chalk.blue("Repository:"), chalk.underline(info.repository)); // eslint-disable-line no-console
165
+ }
166
+ } catch (error) {
167
+ spinner.stop();
168
+ console.error(chalk.red(`Failed to get plugin info: ${error.message}`)); // eslint-disable-line no-console
169
+ process.exit(1);
170
+ }
171
+ }
172
+
173
+ async function listInstalledPlugins(hub, _options) {
174
+ const spinner = ora("Loading installed plugins...").start();
175
+
176
+ try {
177
+ const installed = await hub.getInstalledPlugins();
178
+ spinner.stop();
179
+
180
+ if (installed.length === 0) {
181
+ console.log(chalk.yellow("No plugins installed.")); // eslint-disable-line no-console
182
+ return;
183
+ }
184
+
185
+ if (_options.format === "json") {
186
+ console.log(JSON.stringify(installed, null, 2)); // eslint-disable-line no-console
187
+ return;
188
+ }
189
+
190
+ console.log(chalk.green(`${installed.length} plugins installed:\n`)); // eslint-disable-line no-console
191
+
192
+ const table = new Table({
193
+ head: ["Name", "Version", "Type", "Last Used", "Status"],
194
+ colWidths: [25, 12, 15, 15, 10],
195
+ });
196
+
197
+ for (const plugin of installed) {
198
+ const lastUsed = plugin.lastUsed
199
+ ? new Date(plugin.lastUsed).toLocaleDateString()
200
+ : chalk.gray("Never");
201
+
202
+ const status = plugin.certified
203
+ ? chalk.green("Certified")
204
+ : chalk.gray("Standard");
205
+
206
+ table.push([plugin.name, plugin.version, plugin._type, lastUsed, status]);
207
+ }
208
+
209
+ console.log(table.toString()); // eslint-disable-line no-console
210
+ } catch (error) {
211
+ spinner.stop();
212
+ console.error(chalk.red(`Failed to list plugins: ${error.message}`)); // eslint-disable-line no-console
213
+ process.exit(1);
214
+ }
215
+ }
216
+
217
+ async function publishPlugin(hub, pluginPath, _options) {
218
+ if (_options.dryRun) {
219
+ console.log(
220
+ chalk.blue("šŸ” Dry run mode - validating plugin without publishing\n"),
221
+ ); // eslint-disable-line no-console
222
+ }
223
+
224
+ try {
225
+ if (!_options.dryRun) {
226
+ const result = await hub.publishPlugin(pluginPath, _options);
227
+
228
+ console.log(chalk.green("\nšŸŽ‰ Plugin published successfully!")); // eslint-disable-line no-console
229
+ console.log(chalk.blue(`Plugin ID: ${result.pluginId}`)); // eslint-disable-line no-console
230
+ console.log(chalk.blue(`Version: ${result.version}`)); // eslint-disable-line no-console
231
+ console.log(chalk.blue(`URL: ${result.url}`)); // eslint-disable-line no-console
232
+ } else {
233
+ console.log(
234
+ chalk.green("āœ… Plugin validation passed - ready for publishing!"),
235
+ ); // eslint-disable-line no-console
236
+ }
237
+ } catch (error) {
238
+ console.error(chalk.red(`Publishing failed: ${error.message}`)); // eslint-disable-line no-console
239
+ process.exit(1);
240
+ }
241
+ }
242
+
243
+ async function getTrendingPlugins(hub, _options) {
244
+ const spinner = ora("Loading trending plugins...").start();
245
+
246
+ try {
247
+ const trending = await hub.getTrendingPlugins(_options);
248
+ spinner.stop();
249
+
250
+ console.log(chalk.green(`šŸ”„ Trending plugins (${_options.period}):\n`)); // eslint-disable-line no-console
251
+
252
+ const table = new Table({
253
+ head: ["Rank", "Name", "Author", "Category", "Growth", "Rating"],
254
+ colWidths: [6, 20, 15, 15, 10, 10],
255
+ });
256
+
257
+ trending.forEach((plugin, index) => {
258
+ const rating =
259
+ "ā˜…".repeat(Math.floor(plugin.rating)) +
260
+ "ā˜†".repeat(5 - Math.floor(plugin.rating));
261
+ const certified = plugin.certified ? chalk.green("āœ“") : "";
262
+
263
+ table.push([
264
+ `#${index + 1}`,
265
+ `${plugin.name} ${certified}`,
266
+ plugin.author,
267
+ plugin.category,
268
+ chalk.green(`+${plugin.growth || 0}%`),
269
+ rating,
270
+ ]);
271
+ });
272
+
273
+ console.log(table.toString()); // eslint-disable-line no-console
274
+ } catch (error) {
275
+ spinner.stop();
276
+ console.error(
277
+ chalk.red(`Failed to load trending plugins: ${error.message}`),
278
+ ); // eslint-disable-line no-console
279
+ process.exit(1);
280
+ }
281
+ }
282
+
283
+ module.exports = {
284
+ searchPlugins,
285
+ installPlugin,
286
+ getPluginInfo,
287
+ listInstalledPlugins,
288
+ publishPlugin,
289
+ getTrendingPlugins,
290
+ };
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Review Commands
3
+ * Plugin rating and review operations
4
+ */
5
+
6
+ const chalk = require("chalk");
7
+ const ora = require("ora");
8
+
9
+ async function ratePlugin(hub, plugin, rating, _options) {
10
+ if (rating < 1 || rating > 5) {
11
+ console.error(chalk.red("Rating must be between 1 and 5")); // eslint-disable-line no-console
12
+ process.exit(1);
13
+ }
14
+
15
+ try {
16
+ await hub.ratePlugin(plugin, rating, _options.review);
17
+
18
+ const stars = "ā˜…".repeat(rating) + "ā˜†".repeat(5 - rating);
19
+ console.log(chalk.green(`āœ… Rated ${plugin}: ${stars}`)); // eslint-disable-line no-console
20
+
21
+ if (_options.review) {
22
+ console.log(chalk.blue("Review submitted successfully!")); // eslint-disable-line no-console
23
+ }
24
+ } catch (error) {
25
+ console.error(chalk.red(`Rating failed: ${error.message}`)); // eslint-disable-line no-console
26
+ process.exit(1);
27
+ }
28
+ }
29
+
30
+ async function getPluginReviews(hub, plugin, _options) {
31
+ const spinner = ora("Loading reviews...").start();
32
+
33
+ try {
34
+ const reviews = await hub.getPluginReviews(plugin, _options);
35
+ spinner.stop();
36
+
37
+ if (reviews.reviews.length === 0) {
38
+ console.log(chalk.yellow("No reviews found for this plugin.")); // eslint-disable-line no-console
39
+ return;
40
+ }
41
+
42
+ console.log(chalk.green(`Reviews for ${plugin}:\n`)); // eslint-disable-line no-console
43
+
44
+ for (const review of reviews.reviews) {
45
+ const stars = "ā˜…".repeat(review.rating) + "ā˜†".repeat(5 - review.rating);
46
+ const date = new Date(review.createdAt).toLocaleDateString();
47
+
48
+ console.log(chalk.blue(`${stars} by ${review.author} on ${date}`)); // eslint-disable-line no-console
49
+
50
+ if (review.review) {
51
+ console.log(chalk.gray(`"${review.review}"`)); // eslint-disable-line no-console
52
+ }
53
+
54
+ if (review.helpful > 0) {
55
+ console.log(chalk.green(`šŸ‘ ${review.helpful} found this helpful`)); // eslint-disable-line no-console
56
+ }
57
+
58
+ console.log(); // eslint-disable-line no-console
59
+ }
60
+
61
+ if (reviews.hasMore) {
62
+ console.log(
63
+ chalk.blue(
64
+ `Showing ${reviews.reviews.length} of ${reviews.total} reviews.`,
65
+ ),
66
+ ); // eslint-disable-line no-console
67
+ }
68
+ } catch (error) {
69
+ spinner.stop();
70
+ console.error(chalk.red(`Failed to load reviews: ${error.message}`)); // eslint-disable-line no-console
71
+ process.exit(1);
72
+ }
73
+ }
74
+
75
+ module.exports = {
76
+ ratePlugin,
77
+ getPluginReviews,
78
+ };