@ncukondo/search-hub 0.22.0 → 0.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -7
- package/dist/cli/commands/config.d.ts +53 -0
- package/dist/cli/commands/config.d.ts.map +1 -1
- package/dist/cli/commands/config.js +62 -0
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/fulltext/index.js +1 -0
- package/dist/cli/commands/fulltext/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +12 -17
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +116 -76
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/query/init.d.ts +0 -1
- package/dist/cli/commands/query/init.d.ts.map +1 -1
- package/dist/cli/commands/query/init.js +2 -3
- package/dist/cli/commands/query/init.js.map +1 -1
- package/dist/cli/commands/query/resolve.d.ts.map +1 -1
- package/dist/cli/commands/query/resolve.js +5 -2
- package/dist/cli/commands/query/resolve.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +183 -23
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/suggestions/rules.js +1 -1
- package/dist/cli/suggestions/rules.js.map +1 -1
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/loader.d.ts +4 -2
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +7 -6
- package/dist/config/loader.js.map +1 -1
- package/dist/config/paths.d.ts +21 -0
- package/dist/config/paths.d.ts.map +1 -1
- package/dist/config/paths.js +28 -5
- package/dist/config/paths.js.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/package.json.js +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -4,11 +4,12 @@ import { Command, Option } from "commander";
|
|
|
4
4
|
import { VERSION } from "../version.js";
|
|
5
5
|
import { init } from "./commands/init.js";
|
|
6
6
|
import { EXIT_CODES } from "./exit-codes.js";
|
|
7
|
-
import { loadConfig, saveConfig } from "../config/loader.js";
|
|
7
|
+
import { loadConfig, loadTomlFile, saveConfig } from "../config/loader.js";
|
|
8
8
|
import "../config/schema.js";
|
|
9
9
|
import { getDefaultConfig } from "../config/defaults.js";
|
|
10
|
-
import { getDefaultConfigPath } from "../config/paths.js";
|
|
11
|
-
import { viewConfig, viewConfigKey, setConfigKey } from "./commands/config.js";
|
|
10
|
+
import { isInsideProject, getDefaultConfigPath, getLocalConfigPath } from "../config/paths.js";
|
|
11
|
+
import { formatEnvVars, viewConfigAllOrigins, viewConfigFiltered, viewConfig, formatShowOrigin, getNestedValue, viewConfigKey, resolveWriteScope, checkSecretKeyWarning, setConfigKey, parseValue, setNestedValue } from "./commands/config.js";
|
|
12
|
+
import { ENV_VAR_MAP } from "../config/env.js";
|
|
12
13
|
import { detectSchemaLink, validateQueryCommand, formatValidateResult, formatVocabValidationOutput, hasVocabErrors } from "./commands/query/validate.js";
|
|
13
14
|
import { MeSHLookupClient } from "../query/mesh-lookup.js";
|
|
14
15
|
import { RateLimiter } from "../providers/base/rate-limiter.js";
|
|
@@ -82,16 +83,23 @@ Quick Start:
|
|
|
82
83
|
$ search-hub search my-search --count-only # Check hit counts
|
|
83
84
|
$ search-hub search my-search # Execute search
|
|
84
85
|
$ search-hub results <session> # Review titles`);
|
|
85
|
-
program.command("init").description("Initialize
|
|
86
|
+
program.command("init").description("Initialize search-hub project (local) or global config").option("-f, --force", "overwrite existing configuration", false).option("-g, --global", "initialize global config instead of local project", false).addHelpText("after", `
|
|
86
87
|
Examples:
|
|
87
|
-
$ search-hub init #
|
|
88
|
+
$ search-hub init # Create .search-hub/ in current directory
|
|
89
|
+
$ search-hub init --global # Create global config (~/.config/search-hub/)
|
|
88
90
|
$ search-hub init --force # Overwrite existing configuration`).action(async (options) => {
|
|
89
91
|
const globalOpts = program.opts();
|
|
90
92
|
try {
|
|
91
|
-
const result = await init({ force: options.force });
|
|
93
|
+
const result = await init({ force: options.force, global: options.global });
|
|
92
94
|
if (!globalOpts.quiet) {
|
|
93
95
|
if (result.success) {
|
|
94
96
|
console.log(result.message);
|
|
97
|
+
if (result.hints) {
|
|
98
|
+
console.log("");
|
|
99
|
+
for (const hint of result.hints) {
|
|
100
|
+
console.log(` ${hint}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
95
103
|
} else {
|
|
96
104
|
console.error(result.message);
|
|
97
105
|
}
|
|
@@ -107,13 +115,91 @@ Examples:
|
|
|
107
115
|
process.exitCode = EXIT_CODES.GENERAL_ERROR;
|
|
108
116
|
}
|
|
109
117
|
});
|
|
110
|
-
program.command("config").description("View and edit configuration").argument("[key]", "configuration key to view or set").argument("[value]", "value to set for the key").addHelpText("after", `
|
|
118
|
+
program.command("config").description("View and edit configuration").argument("[key]", "configuration key to view or set").argument("[value]", "value to set for the key").option("--global", "Use global config scope").option("--local", "Use local project config scope").option("--show-origin", "Show where each config value comes from").option("--list", "List all config values (default when no key given)").option("--env-vars", "Show environment variable mappings").option("--force", "Force write even for secret keys in local scope").addHelpText("after", `
|
|
111
119
|
Examples:
|
|
112
|
-
$ search-hub config
|
|
113
|
-
$ search-hub config providers.pubmed
|
|
114
|
-
$ search-hub config providers.pubmed.api_key KEY # Set API key
|
|
120
|
+
$ search-hub config # Show all config
|
|
121
|
+
$ search-hub config providers.pubmed # Show PubMed config
|
|
122
|
+
$ search-hub config --global providers.pubmed.api_key KEY # Set API key globally
|
|
123
|
+
$ search-hub config --local output.color false # Set in project config
|
|
124
|
+
$ search-hub config --show-origin providers.pubmed.api_key # Show value origin
|
|
125
|
+
$ search-hub config --list --global # Show only global values
|
|
126
|
+
$ search-hub config --env-vars # Show env var mappings`).action(async (key, value, cmdOpts) => {
|
|
115
127
|
const globalOpts = program.opts();
|
|
116
128
|
try {
|
|
129
|
+
if (cmdOpts.envVars) {
|
|
130
|
+
if (!globalOpts.quiet) {
|
|
131
|
+
console.log(formatEnvVars());
|
|
132
|
+
}
|
|
133
|
+
process.exitCode = EXIT_CODES.SUCCESS;
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const inProject = await isInsideProject();
|
|
137
|
+
if (cmdOpts.list || !key && !value) {
|
|
138
|
+
if (cmdOpts.global && cmdOpts.local) {
|
|
139
|
+
if (!globalOpts.quiet) {
|
|
140
|
+
console.error("Error: --global and --local are mutually exclusive");
|
|
141
|
+
}
|
|
142
|
+
process.exitCode = EXIT_CODES.CONFIG_ERROR;
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (cmdOpts.showOrigin && !cmdOpts.global && !cmdOpts.local) {
|
|
146
|
+
let config22;
|
|
147
|
+
try {
|
|
148
|
+
config22 = await loadConfig(
|
|
149
|
+
globalOpts.config ? { explicitConfigPath: globalOpts.config } : {}
|
|
150
|
+
);
|
|
151
|
+
} catch {
|
|
152
|
+
config22 = getDefaultConfig();
|
|
153
|
+
}
|
|
154
|
+
const globalPath = expandPath(getDefaultConfigPath());
|
|
155
|
+
const globalCfg = await loadTomlFile(globalPath);
|
|
156
|
+
const localPath = inProject ? getLocalConfigPath() : "";
|
|
157
|
+
const localCfg = inProject ? await loadTomlFile(localPath) : {};
|
|
158
|
+
if (!globalOpts.quiet) {
|
|
159
|
+
console.log(viewConfigAllOrigins(
|
|
160
|
+
config22,
|
|
161
|
+
ENV_VAR_MAP,
|
|
162
|
+
localCfg,
|
|
163
|
+
localPath,
|
|
164
|
+
globalCfg,
|
|
165
|
+
globalPath
|
|
166
|
+
));
|
|
167
|
+
}
|
|
168
|
+
} else if (cmdOpts.global) {
|
|
169
|
+
const globalConfig = await loadTomlFile(expandPath(getDefaultConfigPath()));
|
|
170
|
+
if (!globalOpts.quiet) {
|
|
171
|
+
const output = viewConfigFiltered(globalConfig);
|
|
172
|
+
console.log(output || "(no global config values set)");
|
|
173
|
+
}
|
|
174
|
+
} else if (cmdOpts.local) {
|
|
175
|
+
if (!inProject) {
|
|
176
|
+
if (!globalOpts.quiet) {
|
|
177
|
+
console.error('Error: --local requires a project directory (.search-hub/). Run "search-hub init" first.');
|
|
178
|
+
}
|
|
179
|
+
process.exitCode = EXIT_CODES.CONFIG_ERROR;
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const localConfig = await loadTomlFile(getLocalConfigPath());
|
|
183
|
+
if (!globalOpts.quiet) {
|
|
184
|
+
const output = viewConfigFiltered(localConfig);
|
|
185
|
+
console.log(output || "(no local config values set)");
|
|
186
|
+
}
|
|
187
|
+
} else {
|
|
188
|
+
let config22;
|
|
189
|
+
try {
|
|
190
|
+
config22 = await loadConfig(
|
|
191
|
+
globalOpts.config ? { explicitConfigPath: globalOpts.config } : {}
|
|
192
|
+
);
|
|
193
|
+
} catch {
|
|
194
|
+
config22 = getDefaultConfig();
|
|
195
|
+
}
|
|
196
|
+
if (!globalOpts.quiet) {
|
|
197
|
+
console.log(viewConfig(config22));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
process.exitCode = EXIT_CODES.SUCCESS;
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
117
203
|
let config2;
|
|
118
204
|
try {
|
|
119
205
|
config2 = await loadConfig(
|
|
@@ -122,29 +208,103 @@ Examples:
|
|
|
122
208
|
} catch {
|
|
123
209
|
config2 = getDefaultConfig();
|
|
124
210
|
}
|
|
125
|
-
if (!
|
|
126
|
-
if (
|
|
127
|
-
|
|
211
|
+
if (key && !value) {
|
|
212
|
+
if (cmdOpts.showOrigin) {
|
|
213
|
+
const envEntry = Object.entries(ENV_VAR_MAP).find(([, path]) => path === key);
|
|
214
|
+
if (envEntry && process.env[envEntry[0]] !== void 0) {
|
|
215
|
+
if (!globalOpts.quiet) {
|
|
216
|
+
console.log(formatShowOrigin(key, process.env[envEntry[0]], "env", envEntry[0]));
|
|
217
|
+
}
|
|
218
|
+
process.exitCode = EXIT_CODES.SUCCESS;
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (inProject) {
|
|
222
|
+
const localConfig = await loadTomlFile(getLocalConfigPath());
|
|
223
|
+
const localVal = getNestedValue(localConfig, key);
|
|
224
|
+
if (localVal !== void 0) {
|
|
225
|
+
if (!globalOpts.quiet) {
|
|
226
|
+
console.log(formatShowOrigin(key, String(localVal), "local", getLocalConfigPath()));
|
|
227
|
+
}
|
|
228
|
+
process.exitCode = EXIT_CODES.SUCCESS;
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
const globalConfigPath = expandPath(getDefaultConfigPath());
|
|
233
|
+
const globalConfig = await loadTomlFile(globalConfigPath);
|
|
234
|
+
const globalVal = getNestedValue(globalConfig, key);
|
|
235
|
+
if (globalVal !== void 0) {
|
|
236
|
+
if (!globalOpts.quiet) {
|
|
237
|
+
console.log(formatShowOrigin(key, String(globalVal), "global", globalConfigPath));
|
|
238
|
+
}
|
|
239
|
+
process.exitCode = EXIT_CODES.SUCCESS;
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
const mergedVal = getNestedValue(config2, key);
|
|
243
|
+
if (mergedVal !== void 0) {
|
|
244
|
+
if (!globalOpts.quiet) {
|
|
245
|
+
console.log(formatShowOrigin(key, String(mergedVal), "default", ""));
|
|
246
|
+
}
|
|
247
|
+
} else {
|
|
248
|
+
if (!globalOpts.quiet) {
|
|
249
|
+
console.error(`Error: Key "${key}" not found in configuration`);
|
|
250
|
+
}
|
|
251
|
+
process.exitCode = EXIT_CODES.CONFIG_ERROR;
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
} else {
|
|
255
|
+
const result = viewConfigKey(config2, key);
|
|
256
|
+
if (result.success) {
|
|
257
|
+
if (!globalOpts.quiet) {
|
|
258
|
+
console.log(result.value);
|
|
259
|
+
}
|
|
260
|
+
} else {
|
|
261
|
+
if (!globalOpts.quiet) {
|
|
262
|
+
console.error(`Error: ${result.error}`);
|
|
263
|
+
}
|
|
264
|
+
process.exitCode = EXIT_CODES.CONFIG_ERROR;
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
128
267
|
}
|
|
129
|
-
} else if (
|
|
130
|
-
const
|
|
131
|
-
|
|
268
|
+
} else if (key && value) {
|
|
269
|
+
const scopeResult = resolveWriteScope({
|
|
270
|
+
global: !!cmdOpts.global,
|
|
271
|
+
local: !!cmdOpts.local,
|
|
272
|
+
insideProject: inProject
|
|
273
|
+
});
|
|
274
|
+
if (scopeResult.scope === "error") {
|
|
132
275
|
if (!globalOpts.quiet) {
|
|
133
|
-
console.
|
|
276
|
+
console.error(`Error: ${scopeResult.error}`);
|
|
134
277
|
}
|
|
135
|
-
|
|
278
|
+
process.exitCode = EXIT_CODES.CONFIG_ERROR;
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
const warning = checkSecretKeyWarning(key, scopeResult.scope);
|
|
282
|
+
if (warning && !cmdOpts.force) {
|
|
136
283
|
if (!globalOpts.quiet) {
|
|
137
|
-
console.error(`Error: ${
|
|
284
|
+
console.error(`Error: ${warning} Use --force to override.`);
|
|
138
285
|
}
|
|
139
286
|
process.exitCode = EXIT_CODES.CONFIG_ERROR;
|
|
140
287
|
return;
|
|
141
288
|
}
|
|
142
|
-
} else {
|
|
143
289
|
const result = setConfigKey(config2, key, value);
|
|
144
290
|
if (result.success) {
|
|
145
|
-
|
|
291
|
+
let configPath;
|
|
292
|
+
if (globalOpts.config) {
|
|
293
|
+
configPath = expandPath(globalOpts.config);
|
|
294
|
+
} else if (scopeResult.scope === "local") {
|
|
295
|
+
configPath = expandPath(getLocalConfigPath());
|
|
296
|
+
} else {
|
|
297
|
+
configPath = expandPath(getDefaultConfigPath());
|
|
298
|
+
}
|
|
146
299
|
try {
|
|
147
|
-
|
|
300
|
+
const existing = await loadTomlFile(configPath);
|
|
301
|
+
const existingValue = getNestedValue(
|
|
302
|
+
config2,
|
|
303
|
+
key
|
|
304
|
+
);
|
|
305
|
+
const parsedValue = parseValue(value, existingValue);
|
|
306
|
+
setNestedValue(existing, key, parsedValue);
|
|
307
|
+
await saveConfig(existing, { path: configPath });
|
|
148
308
|
if (!globalOpts.quiet) {
|
|
149
309
|
console.log(`Set ${key} = ${result.value}`);
|
|
150
310
|
console.log(`Saved to ${configPath}`);
|
|
@@ -334,7 +494,7 @@ Examples:
|
|
|
334
494
|
});
|
|
335
495
|
queryCommand.command("init").description("Generate a template query YAML file").argument("<title>", "query title (used for name field and filename)").option("-o, --output <path>", "write to specific file path").option("--stdout", "output to stdout instead of file").option("--force", "overwrite existing file", false).addHelpText("after", `
|
|
336
496
|
Examples:
|
|
337
|
-
$ search-hub query init "WBA pain mechanisms" # → queries/wba-pain-mechanisms.yaml
|
|
497
|
+
$ search-hub query init "WBA pain mechanisms" # → .search-hub/queries/wba-pain-mechanisms.yaml
|
|
338
498
|
$ search-hub query init "WBA pain" -o ./custom-path.yaml # Custom output path
|
|
339
499
|
$ search-hub query init "WBA pain" --stdout # Print to stdout`).action(async (title, options) => {
|
|
340
500
|
const globalOpts = program.opts();
|