@kb-labs/shared 1.1.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.
- package/.cursorrules +32 -0
- package/.github/workflows/ci.yml +13 -0
- package/.github/workflows/deploy.yml +28 -0
- package/.github/workflows/docker-build.yml +25 -0
- package/.github/workflows/drift-check.yml +10 -0
- package/.github/workflows/profiles-validate.yml +16 -0
- package/.github/workflows/release.yml +8 -0
- package/.kb/devkit/agents/devkit-maintainer/context.globs +15 -0
- package/.kb/devkit/agents/devkit-maintainer/permissions.yml +17 -0
- package/.kb/devkit/agents/devkit-maintainer/prompt.md +28 -0
- package/.kb/devkit/agents/devkit-maintainer/runbook.md +31 -0
- package/.kb/devkit/agents/docs-crafter/prompt.md +24 -0
- package/.kb/devkit/agents/docs-crafter/runbook.md +18 -0
- package/.kb/devkit/agents/release-manager/context.globs +7 -0
- package/.kb/devkit/agents/release-manager/prompt.md +27 -0
- package/.kb/devkit/agents/release-manager/runbook.md +17 -0
- package/.kb/devkit/agents/test-generator/context.globs +7 -0
- package/.kb/devkit/agents/test-generator/prompt.md +27 -0
- package/.kb/devkit/agents/test-generator/runbook.md +18 -0
- package/.vscode/settings.json +23 -0
- package/CHANGELOG.md +33 -0
- package/CONTRIBUTING.md +117 -0
- package/LICENSE +21 -0
- package/README.md +306 -0
- package/docs/DECLARATIVE-FLAGS-AND-ENV.md +622 -0
- package/docs/DOCUMENTATION.md +70 -0
- package/docs/adr/0000-template.md +52 -0
- package/docs/adr/0001-architecture-and-repository-layout.md +31 -0
- package/docs/adr/0002-plugins-and-extensibility.md +44 -0
- package/docs/adr/0003-package-and-module-boundaries.md +35 -0
- package/docs/adr/0004-versioning-and-release-policy.md +36 -0
- package/docs/adr/0005-reactive-loader-pattern.md +179 -0
- package/docs/adr/0006-declarative-flags-and-env-systems.md +376 -0
- package/eslint.config.js +27 -0
- package/kb-labs.config.json +5 -0
- package/package.json +88 -0
- package/package.json.bin +25 -0
- package/package.json.lib +30 -0
- package/packages/shared-cli-ui/CHANGELOG.md +20 -0
- package/packages/shared-cli-ui/README.md +342 -0
- package/packages/shared-cli-ui/docs/ARCHITECTURE.md +105 -0
- package/packages/shared-cli-ui/eslint.config.js +27 -0
- package/packages/shared-cli-ui/package.json +72 -0
- package/packages/shared-cli-ui/src/__tests__/artifacts-display.spec.ts +89 -0
- package/packages/shared-cli-ui/src/__tests__/format.spec.ts +44 -0
- package/packages/shared-cli-ui/src/__tests__/loader-json-mode.test.ts +119 -0
- package/packages/shared-cli-ui/src/artifacts-display.ts +266 -0
- package/packages/shared-cli-ui/src/cli-auto-discovery.ts +120 -0
- package/packages/shared-cli-ui/src/colors.ts +142 -0
- package/packages/shared-cli-ui/src/command-discovery.ts +72 -0
- package/packages/shared-cli-ui/src/command-output.ts +153 -0
- package/packages/shared-cli-ui/src/command-result.ts +267 -0
- package/packages/shared-cli-ui/src/command-runner.ts +310 -0
- package/packages/shared-cli-ui/src/command-suggestions.ts +204 -0
- package/packages/shared-cli-ui/src/debug/components/output.ts +141 -0
- package/packages/shared-cli-ui/src/debug/components/trace.ts +101 -0
- package/packages/shared-cli-ui/src/debug/components/tree.ts +88 -0
- package/packages/shared-cli-ui/src/debug/formatters/ai.ts +17 -0
- package/packages/shared-cli-ui/src/debug/formatters/human.ts +98 -0
- package/packages/shared-cli-ui/src/debug/formatters/timeline.ts +94 -0
- package/packages/shared-cli-ui/src/debug/index.ts +56 -0
- package/packages/shared-cli-ui/src/debug/types.ts +57 -0
- package/packages/shared-cli-ui/src/debug/utilities.ts +203 -0
- package/packages/shared-cli-ui/src/dynamic-command-discovery.ts +131 -0
- package/packages/shared-cli-ui/src/format.ts +412 -0
- package/packages/shared-cli-ui/src/index.ts +34 -0
- package/packages/shared-cli-ui/src/loader.ts +196 -0
- package/packages/shared-cli-ui/src/manifest-parser.ts +151 -0
- package/packages/shared-cli-ui/src/modern-format.ts +271 -0
- package/packages/shared-cli-ui/src/multi-cli-suggestions.ts +159 -0
- package/packages/shared-cli-ui/src/table.ts +134 -0
- package/packages/shared-cli-ui/src/timing-tracker.ts +68 -0
- package/packages/shared-cli-ui/src/utils/context.ts +12 -0
- package/packages/shared-cli-ui/src/utils/env.ts +164 -0
- package/packages/shared-cli-ui/src/utils/flags.ts +269 -0
- package/packages/shared-cli-ui/src/utils/path.ts +8 -0
- package/packages/shared-cli-ui/tsconfig.build.json +15 -0
- package/packages/shared-cli-ui/tsconfig.json +9 -0
- package/packages/shared-cli-ui/tsup.config.ts +11 -0
- package/packages/shared-cli-ui/vitest.config.ts +15 -0
- package/packages/shared-command-kit/CHANGELOG.md +20 -0
- package/packages/shared-command-kit/LICENSE +22 -0
- package/packages/shared-command-kit/README.md +1030 -0
- package/packages/shared-command-kit/docs/HIGH-LEVEL-API.md +89 -0
- package/packages/shared-command-kit/docs/LOW-LEVEL-API.md +105 -0
- package/packages/shared-command-kit/docs/MIGRATION-GUIDE.md +135 -0
- package/packages/shared-command-kit/eslint.config.js +27 -0
- package/packages/shared-command-kit/eslint.config.ts +14 -0
- package/packages/shared-command-kit/package.json +76 -0
- package/packages/shared-command-kit/prettierrc.json +5 -0
- package/packages/shared-command-kit/src/__tests__/define-command.spec.ts +294 -0
- package/packages/shared-command-kit/src/__tests__/define-route.test.ts +285 -0
- package/packages/shared-command-kit/src/__tests__/define-system-command.spec.ts +508 -0
- package/packages/shared-command-kit/src/__tests__/define-webhook.test.ts +156 -0
- package/packages/shared-command-kit/src/__tests__/define-websocket.test.ts +316 -0
- package/packages/shared-command-kit/src/__tests__/errors.spec.ts +45 -0
- package/packages/shared-command-kit/src/__tests__/flags.spec.ts +353 -0
- package/packages/shared-command-kit/src/__tests__/platform-api.test.ts +135 -0
- package/packages/shared-command-kit/src/__tests__/plugin-context-v3.snapshot.spec.ts +240 -0
- package/packages/shared-command-kit/src/__tests__/ws-types.test.ts +359 -0
- package/packages/shared-command-kit/src/analytics/index.ts +6 -0
- package/packages/shared-command-kit/src/analytics/with-analytics.ts +195 -0
- package/packages/shared-command-kit/src/define-action.ts +100 -0
- package/packages/shared-command-kit/src/define-command.ts +113 -0
- package/packages/shared-command-kit/src/define-route.ts +113 -0
- package/packages/shared-command-kit/src/define-system-command.ts +362 -0
- package/packages/shared-command-kit/src/define-webhook.ts +115 -0
- package/packages/shared-command-kit/src/define-websocket.ts +308 -0
- package/packages/shared-command-kit/src/errors/factory.ts +282 -0
- package/packages/shared-command-kit/src/errors/format-validation.ts +144 -0
- package/packages/shared-command-kit/src/errors/format.ts +92 -0
- package/packages/shared-command-kit/src/errors/index.ts +9 -0
- package/packages/shared-command-kit/src/errors/types.ts +32 -0
- package/packages/shared-command-kit/src/flags/define.ts +92 -0
- package/packages/shared-command-kit/src/flags/index.ts +9 -0
- package/packages/shared-command-kit/src/flags/types.ts +153 -0
- package/packages/shared-command-kit/src/flags/validate.ts +358 -0
- package/packages/shared-command-kit/src/helpers/context.ts +8 -0
- package/packages/shared-command-kit/src/helpers/flags.ts +84 -0
- package/packages/shared-command-kit/src/helpers/index.ts +42 -0
- package/packages/shared-command-kit/src/helpers/patterns.ts +464 -0
- package/packages/shared-command-kit/src/helpers/platform.ts +335 -0
- package/packages/shared-command-kit/src/helpers/use-analytics.ts +95 -0
- package/packages/shared-command-kit/src/helpers/use-cache.ts +97 -0
- package/packages/shared-command-kit/src/helpers/use-config.ts +99 -0
- package/packages/shared-command-kit/src/helpers/use-embeddings.ts +49 -0
- package/packages/shared-command-kit/src/helpers/use-llm.ts +316 -0
- package/packages/shared-command-kit/src/helpers/use-logger.ts +77 -0
- package/packages/shared-command-kit/src/helpers/use-platform.ts +111 -0
- package/packages/shared-command-kit/src/helpers/use-resource-broker.ts +106 -0
- package/packages/shared-command-kit/src/helpers/use-storage.ts +71 -0
- package/packages/shared-command-kit/src/helpers/use-vector-store.ts +49 -0
- package/packages/shared-command-kit/src/helpers/validation.ts +398 -0
- package/packages/shared-command-kit/src/index.ts +410 -0
- package/packages/shared-command-kit/src/jobs.ts +132 -0
- package/packages/shared-command-kit/src/lifecycle/define-handlers.ts +366 -0
- package/packages/shared-command-kit/src/lifecycle/index.ts +6 -0
- package/packages/shared-command-kit/src/manifest.ts +127 -0
- package/packages/shared-command-kit/src/rest/define-handler.ts +187 -0
- package/packages/shared-command-kit/src/rest/index.ts +11 -0
- package/packages/shared-command-kit/src/studio/index.ts +12 -0
- package/packages/shared-command-kit/src/validation/index.ts +6 -0
- package/packages/shared-command-kit/src/validation/schema-builders.ts +409 -0
- package/packages/shared-command-kit/src/ws-types.ts +106 -0
- package/packages/shared-command-kit/tsconfig.build.json +15 -0
- package/packages/shared-command-kit/tsconfig.json +9 -0
- package/packages/shared-command-kit/tsup.config.ts +30 -0
- package/packages/shared-command-kit/vitest.config.ts +4 -0
- package/packages/shared-http/package.json +67 -0
- package/packages/shared-http/src/__tests__/log-correlation.test.ts +81 -0
- package/packages/shared-http/src/__tests__/operation-metrics-tracker.test.ts +55 -0
- package/packages/shared-http/src/http-observability-collector.ts +363 -0
- package/packages/shared-http/src/index.ts +36 -0
- package/packages/shared-http/src/log-correlation.ts +89 -0
- package/packages/shared-http/src/operation-metrics-tracker.ts +107 -0
- package/packages/shared-http/src/register-openapi.ts +108 -0
- package/packages/shared-http/src/resolve-schema-ref.ts +75 -0
- package/packages/shared-http/src/schemas.ts +29 -0
- package/packages/shared-http/src/service-observability.ts +63 -0
- package/packages/shared-http/tsconfig.build.json +15 -0
- package/packages/shared-http/tsconfig.json +9 -0
- package/packages/shared-http/tsup.config.ts +23 -0
- package/packages/shared-http/vitest.config.ts +13 -0
- package/packages/shared-perm-presets/CHANGELOG.md +20 -0
- package/packages/shared-perm-presets/README.md +78 -0
- package/packages/shared-perm-presets/eslint.config.js +27 -0
- package/packages/shared-perm-presets/package.json +45 -0
- package/packages/shared-perm-presets/src/__tests__/combine.test.ts +403 -0
- package/packages/shared-perm-presets/src/__tests__/presets.test.ts +205 -0
- package/packages/shared-perm-presets/src/combine.ts +278 -0
- package/packages/shared-perm-presets/src/index.ts +18 -0
- package/packages/shared-perm-presets/src/presets/ci-environment.ts +34 -0
- package/packages/shared-perm-presets/src/presets/full-env.ts +16 -0
- package/packages/shared-perm-presets/src/presets/git-workflow.ts +40 -0
- package/packages/shared-perm-presets/src/presets/index.ts +8 -0
- package/packages/shared-perm-presets/src/presets/kb-platform.ts +30 -0
- package/packages/shared-perm-presets/src/presets/llm-access.ts +29 -0
- package/packages/shared-perm-presets/src/presets/minimal.ts +21 -0
- package/packages/shared-perm-presets/src/presets/npm-publish.ts +48 -0
- package/packages/shared-perm-presets/src/presets/vector-store.ts +40 -0
- package/packages/shared-perm-presets/src/types.ts +192 -0
- package/packages/shared-perm-presets/tsconfig.build.json +15 -0
- package/packages/shared-perm-presets/tsconfig.json +9 -0
- package/packages/shared-perm-presets/tsup.config.ts +8 -0
- package/packages/shared-perm-presets/vitest.config.ts +9 -0
- package/packages/shared-testing/CHANGELOG.md +20 -0
- package/packages/shared-testing/README.md +430 -0
- package/packages/shared-testing/package.json +51 -0
- package/packages/shared-testing/src/__tests__/create-test-context.test.ts +199 -0
- package/packages/shared-testing/src/__tests__/mock-cache.test.ts +174 -0
- package/packages/shared-testing/src/__tests__/mock-llm.test.ts +212 -0
- package/packages/shared-testing/src/__tests__/setup-platform.test.ts +90 -0
- package/packages/shared-testing/src/__tests__/test-command.test.ts +557 -0
- package/packages/shared-testing/src/create-test-context.ts +550 -0
- package/packages/shared-testing/src/index.ts +77 -0
- package/packages/shared-testing/src/mock-cache.ts +179 -0
- package/packages/shared-testing/src/mock-llm.ts +319 -0
- package/packages/shared-testing/src/mock-logger.ts +97 -0
- package/packages/shared-testing/src/mock-storage.ts +108 -0
- package/packages/shared-testing/src/setup-platform.ts +101 -0
- package/packages/shared-testing/src/test-command.ts +288 -0
- package/packages/shared-testing/tsconfig.build.json +15 -0
- package/packages/shared-testing/tsconfig.json +9 -0
- package/packages/shared-testing/tsup.config.ts +20 -0
- package/packages/shared-testing/vitest.config.ts +3 -0
- package/packages/shared-tool-kit/CHANGELOG.md +20 -0
- package/packages/shared-tool-kit/package.json +47 -0
- package/packages/shared-tool-kit/src/__tests__/factory.test.ts +103 -0
- package/packages/shared-tool-kit/src/__tests__/mock-tool.test.ts +95 -0
- package/packages/shared-tool-kit/src/factory.ts +126 -0
- package/packages/shared-tool-kit/src/index.ts +32 -0
- package/packages/shared-tool-kit/src/testing/index.ts +84 -0
- package/packages/shared-tool-kit/tsconfig.build.json +15 -0
- package/packages/shared-tool-kit/tsconfig.json +9 -0
- package/packages/shared-tool-kit/tsup.config.ts +21 -0
- package/pnpm-workspace.yaml +11070 -0
- package/prettierrc.json +1 -0
- package/scripts/devkit-sync.mjs +37 -0
- package/scripts/hooks/post-push +9 -0
- package/scripts/hooks/pre-commit +9 -0
- package/scripts/hooks/pre-push +9 -0
- package/tsconfig.base.json +9 -0
- package/tsconfig.build.json +15 -0
- package/tsconfig.json +9 -0
- package/tsconfig.paths.json +50 -0
- package/tsconfig.tools.json +18 -0
- package/tsup.config.bin.ts +34 -0
- package/tsup.config.cli.ts +41 -0
- package/tsup.config.dual.ts +46 -0
- package/tsup.config.ts +36 -0
- package/tsup.external.json +104 -0
- package/vitest.config.ts +48 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/shared-command-kit/errors/format-validation
|
|
3
|
+
* User-friendly formatting for flag validation errors
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { FlagValidationError, StringFlagSchema } from '../flags/types';
|
|
7
|
+
import type { FlagSchemaDefinition } from '../flags/types';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Format a validation error into a user-friendly message
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```
|
|
14
|
+
* ❌ Missing required flag: --text
|
|
15
|
+
*
|
|
16
|
+
* Usage: kb mind rag-query --text <query>
|
|
17
|
+
* Hint: Try kb mind rag-query --help
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export function formatValidationError(
|
|
21
|
+
error: FlagValidationError,
|
|
22
|
+
options: {
|
|
23
|
+
commandName?: string;
|
|
24
|
+
schema?: FlagSchemaDefinition;
|
|
25
|
+
} = {}
|
|
26
|
+
): string {
|
|
27
|
+
const { commandName, schema } = options;
|
|
28
|
+
const lines: string[] = [];
|
|
29
|
+
|
|
30
|
+
// Main error message with emoji
|
|
31
|
+
const errorMsg = error.message;
|
|
32
|
+
|
|
33
|
+
// Determine error type and format accordingly
|
|
34
|
+
if (errorMsg.includes('is required')) {
|
|
35
|
+
lines.push(`❌ Missing required flag: --${error.flag}`);
|
|
36
|
+
} else if (errorMsg.includes('must be one of')) {
|
|
37
|
+
// Extract the invalid value if available
|
|
38
|
+
const valueStr = error.value !== undefined ? ` ${error.value}` : '';
|
|
39
|
+
lines.push(`❌ Invalid value for --${error.flag}:${valueStr}`);
|
|
40
|
+
} else if (errorMsg.includes('must be a')) {
|
|
41
|
+
lines.push(`❌ Invalid type for --${error.flag}`);
|
|
42
|
+
} else if (errorMsg.includes('conflicts with')) {
|
|
43
|
+
lines.push(`❌ Flag conflict: --${error.flag}`);
|
|
44
|
+
} else if (errorMsg.includes('depends on')) {
|
|
45
|
+
lines.push(`❌ Missing dependency for --${error.flag}`);
|
|
46
|
+
} else {
|
|
47
|
+
// Fallback: use the original message
|
|
48
|
+
lines.push(`❌ ${errorMsg}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
lines.push(''); // Empty line for spacing
|
|
52
|
+
|
|
53
|
+
// Generate usage hint if we have schema and command name
|
|
54
|
+
if (commandName && schema) {
|
|
55
|
+
const usageLine = generateUsageLine(commandName, schema, error.flag);
|
|
56
|
+
if (usageLine) {
|
|
57
|
+
lines.push(`Usage: ${usageLine}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Add help hint
|
|
62
|
+
if (commandName) {
|
|
63
|
+
lines.push(`Hint: Try ${commandName} --help`);
|
|
64
|
+
} else {
|
|
65
|
+
lines.push('Hint: Try --help for more information');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return lines.join('\n');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Generate a usage line from command name and schema
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* generateUsageLine('kb mind rag-query', schema, 'text')
|
|
76
|
+
* // Returns: 'kb mind rag-query --text <query> [options]'
|
|
77
|
+
*/
|
|
78
|
+
function generateUsageLine(
|
|
79
|
+
commandName: string,
|
|
80
|
+
schema: FlagSchemaDefinition,
|
|
81
|
+
errorFlag: string
|
|
82
|
+
): string {
|
|
83
|
+
const parts: string[] = [commandName];
|
|
84
|
+
|
|
85
|
+
// Add the flag that caused the error first
|
|
86
|
+
const errorFlagSchema = schema[errorFlag];
|
|
87
|
+
if (errorFlagSchema) {
|
|
88
|
+
const flagStr = formatFlagForUsage(errorFlag, errorFlagSchema);
|
|
89
|
+
parts.push(flagStr);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Check if there are other required flags
|
|
93
|
+
const otherRequiredFlags = Object.entries(schema)
|
|
94
|
+
.filter(([name, flagSchema]) =>
|
|
95
|
+
name !== errorFlag && flagSchema.required
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
if (otherRequiredFlags.length > 0) {
|
|
99
|
+
// Add other required flags
|
|
100
|
+
for (const [name, flagSchema] of otherRequiredFlags) {
|
|
101
|
+
parts.push(formatFlagForUsage(name, flagSchema));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Add [options] if there are optional flags
|
|
106
|
+
const hasOptionalFlags = Object.values(schema).some(s => !s.required);
|
|
107
|
+
if (hasOptionalFlags) {
|
|
108
|
+
parts.push('[options]');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return parts.join(' ');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Format a single flag for usage display
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* formatFlagForUsage('text', { type: 'string', required: true })
|
|
119
|
+
* // Returns: '--text <text>'
|
|
120
|
+
*
|
|
121
|
+
* formatFlagForUsage('mode', { type: 'string', choices: ['local', 'auto'] })
|
|
122
|
+
* // Returns: '[--mode <local|auto>]'
|
|
123
|
+
*/
|
|
124
|
+
function formatFlagForUsage(
|
|
125
|
+
name: string,
|
|
126
|
+
schema: FlagSchemaDefinition[string]
|
|
127
|
+
): string {
|
|
128
|
+
let valueHint: string;
|
|
129
|
+
|
|
130
|
+
if ('choices' in schema && (schema as StringFlagSchema).choices && (schema as StringFlagSchema).choices!.length > 0) {
|
|
131
|
+
// Show choices: <local|auto>
|
|
132
|
+
valueHint = `<${(schema as StringFlagSchema).choices!.join('|')}>`;
|
|
133
|
+
} else if (schema.type === 'boolean') {
|
|
134
|
+
// Boolean flags don't need a value hint
|
|
135
|
+
return schema.required ? `--${name}` : `[--${name}]`;
|
|
136
|
+
} else {
|
|
137
|
+
// Generic type hint: <text>, <number>, etc.
|
|
138
|
+
valueHint = `<${name}>`;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const flagPart = `--${name} ${valueHint}`;
|
|
142
|
+
|
|
143
|
+
return schema.required ? flagPart : `[${flagPart}]`;
|
|
144
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/shared-command-kit/errors/format
|
|
3
|
+
* Error formatting utilities
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { FormattedError, FormatErrorOptions } from './types';
|
|
7
|
+
import { FlagValidationError } from '../flags/types';
|
|
8
|
+
import { formatValidationError } from './format-validation';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Format error for display
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const formatted = formatError(error, {
|
|
16
|
+
* jsonMode: Boolean(flags.json),
|
|
17
|
+
* showStack: Boolean(flags.debug),
|
|
18
|
+
* timingMs: tracker.total(),
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* if (flags.json) {
|
|
22
|
+
* ctx.output?.json(formatted.json);
|
|
23
|
+
* } else {
|
|
24
|
+
* ctx.output?.error(formatted.message);
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function formatError(
|
|
29
|
+
error: unknown,
|
|
30
|
+
options: FormatErrorOptions = {}
|
|
31
|
+
): FormattedError {
|
|
32
|
+
const { showStack = false, timingMs } = options;
|
|
33
|
+
|
|
34
|
+
// Special handling for FlagValidationError
|
|
35
|
+
if (error instanceof FlagValidationError) {
|
|
36
|
+
const friendlyMessage = formatValidationError(error, {
|
|
37
|
+
commandName: error.commandName,
|
|
38
|
+
schema: error.schema,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const json: FormattedError['json'] = {
|
|
42
|
+
ok: false,
|
|
43
|
+
error: error.message,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
if (timingMs !== undefined) {
|
|
47
|
+
json.timingMs = timingMs;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (showStack && error.stack) {
|
|
51
|
+
json.stack = error.stack;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let message = friendlyMessage;
|
|
55
|
+
if (showStack && error.stack) {
|
|
56
|
+
message = `${friendlyMessage}\n\nStack trace:\n${error.stack}`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
message,
|
|
61
|
+
json,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Standard error formatting for other errors
|
|
66
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
67
|
+
const errorStack = error instanceof Error ? error.stack : undefined;
|
|
68
|
+
|
|
69
|
+
const json: FormattedError['json'] = {
|
|
70
|
+
ok: false,
|
|
71
|
+
error: errorMessage,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
if (timingMs !== undefined) {
|
|
75
|
+
json.timingMs = timingMs;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (showStack && errorStack) {
|
|
79
|
+
json.stack = errorStack;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let message = errorMessage;
|
|
83
|
+
if (showStack && errorStack) {
|
|
84
|
+
message = `${errorMessage}\n\n${errorStack}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
message,
|
|
89
|
+
json,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/shared-command-kit/errors/types
|
|
3
|
+
* Types for error formatting
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Formatted error result
|
|
8
|
+
*/
|
|
9
|
+
export interface FormattedError {
|
|
10
|
+
/** Human-readable error message */
|
|
11
|
+
message: string;
|
|
12
|
+
/** JSON representation */
|
|
13
|
+
json: {
|
|
14
|
+
ok: false;
|
|
15
|
+
error: string;
|
|
16
|
+
timingMs?: number;
|
|
17
|
+
stack?: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Error formatting options
|
|
23
|
+
*/
|
|
24
|
+
export interface FormatErrorOptions {
|
|
25
|
+
/** Output in JSON format */
|
|
26
|
+
jsonMode?: boolean;
|
|
27
|
+
/** Include stack trace */
|
|
28
|
+
showStack?: boolean;
|
|
29
|
+
/** Timing information */
|
|
30
|
+
timingMs?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/shared-command-kit/flags/define
|
|
3
|
+
* Define flag schemas with automatic type inference
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
FlagSchemaDefinition,
|
|
8
|
+
BooleanFlagSchema,
|
|
9
|
+
StringFlagSchema,
|
|
10
|
+
NumberFlagSchema,
|
|
11
|
+
ArrayFlagSchema,
|
|
12
|
+
} from './types';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Flag schema with type inference
|
|
16
|
+
*/
|
|
17
|
+
export interface FlagSchemaWithInfer<T extends FlagSchemaDefinition> {
|
|
18
|
+
/** Original schema definition */
|
|
19
|
+
readonly schema: T;
|
|
20
|
+
/** Infer TypeScript type from schema */
|
|
21
|
+
infer: InferFlags<T>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Infer TypeScript type from flag schema definition
|
|
26
|
+
*/
|
|
27
|
+
export type InferFlags<T extends FlagSchemaDefinition> = {
|
|
28
|
+
[K in keyof T]: T[K] extends BooleanFlagSchema
|
|
29
|
+
? T[K]['default'] extends boolean
|
|
30
|
+
? boolean
|
|
31
|
+
: T[K]['required'] extends true
|
|
32
|
+
? boolean
|
|
33
|
+
: boolean | undefined
|
|
34
|
+
: T[K] extends StringFlagSchema
|
|
35
|
+
? T[K]['choices'] extends readonly string[]
|
|
36
|
+
? T[K]['required'] extends true
|
|
37
|
+
? T[K]['choices'][number]
|
|
38
|
+
: T[K]['default'] extends string
|
|
39
|
+
? T[K]['choices'][number]
|
|
40
|
+
: T[K]['choices'][number] | undefined
|
|
41
|
+
: T[K]['required'] extends true
|
|
42
|
+
? string
|
|
43
|
+
: T[K]['default'] extends string
|
|
44
|
+
? string
|
|
45
|
+
: string | undefined
|
|
46
|
+
: T[K] extends NumberFlagSchema
|
|
47
|
+
? T[K]['required'] extends true
|
|
48
|
+
? number
|
|
49
|
+
: T[K]['default'] extends number
|
|
50
|
+
? number
|
|
51
|
+
: number | undefined
|
|
52
|
+
: T[K] extends ArrayFlagSchema
|
|
53
|
+
? T[K]['items'] extends 'string'
|
|
54
|
+
? string[]
|
|
55
|
+
: T[K]['items'] extends 'number'
|
|
56
|
+
? number[]
|
|
57
|
+
: T[K]['items'] extends 'boolean'
|
|
58
|
+
? boolean[]
|
|
59
|
+
: unknown[]
|
|
60
|
+
: unknown;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Define a flag schema with automatic type inference
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* const schema = defineFlags({
|
|
69
|
+
* scope: {
|
|
70
|
+
* type: 'string',
|
|
71
|
+
* required: true,
|
|
72
|
+
* pattern: /^[@a-z0-9-/]+$/i,
|
|
73
|
+
* },
|
|
74
|
+
* 'dry-run': {
|
|
75
|
+
* type: 'boolean',
|
|
76
|
+
* default: false,
|
|
77
|
+
* },
|
|
78
|
+
* });
|
|
79
|
+
*
|
|
80
|
+
* type Flags = typeof schema.infer;
|
|
81
|
+
* // Flags = { scope: string; 'dry-run': boolean }
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export function defineFlags<T extends FlagSchemaDefinition>(
|
|
85
|
+
definition: T
|
|
86
|
+
): FlagSchemaWithInfer<T> {
|
|
87
|
+
return {
|
|
88
|
+
schema: definition,
|
|
89
|
+
infer: {} as InferFlags<T>,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @kb-labs/shared-command-kit/flags/types
|
|
3
|
+
* Types for flag validation and schema definition
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Flag type definition
|
|
8
|
+
*/
|
|
9
|
+
export type FlagType = 'boolean' | 'string' | 'number' | 'array';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Base flag schema definition
|
|
13
|
+
*/
|
|
14
|
+
export interface BaseFlagSchema<T extends FlagType = FlagType> {
|
|
15
|
+
/** Flag name */
|
|
16
|
+
name?: string;
|
|
17
|
+
/** Flag type */
|
|
18
|
+
type: T;
|
|
19
|
+
/** Short alias (e.g., 'n' for 'dry-run') */
|
|
20
|
+
alias?: string;
|
|
21
|
+
/** Description for help text */
|
|
22
|
+
description?: string;
|
|
23
|
+
/** Default value if flag is not provided */
|
|
24
|
+
default?: unknown;
|
|
25
|
+
/** Whether flag is required */
|
|
26
|
+
required?: boolean;
|
|
27
|
+
/** Flags that conflict with this flag */
|
|
28
|
+
conflicts?: string[];
|
|
29
|
+
/** Flags that this flag depends on */
|
|
30
|
+
dependsOn?: string[];
|
|
31
|
+
/** Flags that are implied when this flag is set */
|
|
32
|
+
implies?: string[] | [string, unknown][];
|
|
33
|
+
// Note: transform is defined in child interfaces with specific types
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Boolean flag schema
|
|
38
|
+
*/
|
|
39
|
+
export interface BooleanFlagSchema extends BaseFlagSchema<'boolean'> {
|
|
40
|
+
type: 'boolean';
|
|
41
|
+
default?: boolean;
|
|
42
|
+
/** Transform function to apply to the value */
|
|
43
|
+
transform?: (value: boolean) => boolean | Promise<boolean>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* String flag schema
|
|
48
|
+
*/
|
|
49
|
+
export interface StringFlagSchema extends BaseFlagSchema<'string'> {
|
|
50
|
+
type: 'string';
|
|
51
|
+
default?: string;
|
|
52
|
+
/** Allowed values (enum) */
|
|
53
|
+
choices?: readonly string[];
|
|
54
|
+
/** Regex pattern for validation */
|
|
55
|
+
pattern?: RegExp;
|
|
56
|
+
/** Minimum string length */
|
|
57
|
+
minLength?: number;
|
|
58
|
+
/** Maximum string length */
|
|
59
|
+
maxLength?: number;
|
|
60
|
+
/** Custom validation function */
|
|
61
|
+
validate?: (value: string) => true | string | Promise<true | string>;
|
|
62
|
+
/** Transform function to apply to the value */
|
|
63
|
+
transform?: (value: string) => string | Promise<string>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Number flag schema
|
|
68
|
+
*/
|
|
69
|
+
export interface NumberFlagSchema extends BaseFlagSchema<'number'> {
|
|
70
|
+
type: 'number';
|
|
71
|
+
default?: number;
|
|
72
|
+
/** Minimum value */
|
|
73
|
+
min?: number;
|
|
74
|
+
/** Maximum value */
|
|
75
|
+
max?: number;
|
|
76
|
+
/** Custom validation function */
|
|
77
|
+
validate?: (value: number) => true | string | Promise<true | string>;
|
|
78
|
+
/** Transform function to apply to the value */
|
|
79
|
+
transform?: (value: number) => number | Promise<number>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Array flag schema
|
|
84
|
+
*/
|
|
85
|
+
export interface ArrayFlagSchema extends BaseFlagSchema<'array'> {
|
|
86
|
+
type: 'array';
|
|
87
|
+
default?: unknown[];
|
|
88
|
+
/** Type of array items */
|
|
89
|
+
items?: 'string' | 'number' | 'boolean';
|
|
90
|
+
/** Minimum array length */
|
|
91
|
+
minLength?: number;
|
|
92
|
+
/** Maximum array length */
|
|
93
|
+
maxLength?: number;
|
|
94
|
+
/** Transform function to apply to the value */
|
|
95
|
+
transform?: (value: unknown[]) => unknown[] | Promise<unknown[]>;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Union of all flag schema types
|
|
100
|
+
*/
|
|
101
|
+
export type FlagSchema =
|
|
102
|
+
| BooleanFlagSchema
|
|
103
|
+
| StringFlagSchema
|
|
104
|
+
| NumberFlagSchema
|
|
105
|
+
| ArrayFlagSchema;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Flag schema definition object (for defineFlags)
|
|
109
|
+
*/
|
|
110
|
+
export type FlagSchemaDefinition = Record<string, Omit<FlagSchema, 'name'>>;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Validation error
|
|
114
|
+
*/
|
|
115
|
+
export class FlagValidationError extends Error {
|
|
116
|
+
constructor(
|
|
117
|
+
public readonly flag: string,
|
|
118
|
+
message: string,
|
|
119
|
+
public readonly value?: unknown,
|
|
120
|
+
public readonly schema?: FlagSchemaDefinition,
|
|
121
|
+
public readonly commandName?: string
|
|
122
|
+
) {
|
|
123
|
+
super(message);
|
|
124
|
+
this.name = 'FlagValidationError';
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Validation result
|
|
130
|
+
*/
|
|
131
|
+
export interface ValidationResult<T = Record<string, unknown>> {
|
|
132
|
+
success: boolean;
|
|
133
|
+
data?: T;
|
|
134
|
+
errors?: Array<{
|
|
135
|
+
flag: string;
|
|
136
|
+
message: string;
|
|
137
|
+
value?: unknown;
|
|
138
|
+
}>;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Safe validation result (doesn't throw)
|
|
143
|
+
*/
|
|
144
|
+
export interface SafeValidationResult<T = Record<string, unknown>> {
|
|
145
|
+
success: boolean;
|
|
146
|
+
data?: T;
|
|
147
|
+
errors: Array<{
|
|
148
|
+
flag: string;
|
|
149
|
+
message: string;
|
|
150
|
+
value?: unknown;
|
|
151
|
+
}>;
|
|
152
|
+
}
|
|
153
|
+
|