@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.
Files changed (232) hide show
  1. package/.cursorrules +32 -0
  2. package/.github/workflows/ci.yml +13 -0
  3. package/.github/workflows/deploy.yml +28 -0
  4. package/.github/workflows/docker-build.yml +25 -0
  5. package/.github/workflows/drift-check.yml +10 -0
  6. package/.github/workflows/profiles-validate.yml +16 -0
  7. package/.github/workflows/release.yml +8 -0
  8. package/.kb/devkit/agents/devkit-maintainer/context.globs +15 -0
  9. package/.kb/devkit/agents/devkit-maintainer/permissions.yml +17 -0
  10. package/.kb/devkit/agents/devkit-maintainer/prompt.md +28 -0
  11. package/.kb/devkit/agents/devkit-maintainer/runbook.md +31 -0
  12. package/.kb/devkit/agents/docs-crafter/prompt.md +24 -0
  13. package/.kb/devkit/agents/docs-crafter/runbook.md +18 -0
  14. package/.kb/devkit/agents/release-manager/context.globs +7 -0
  15. package/.kb/devkit/agents/release-manager/prompt.md +27 -0
  16. package/.kb/devkit/agents/release-manager/runbook.md +17 -0
  17. package/.kb/devkit/agents/test-generator/context.globs +7 -0
  18. package/.kb/devkit/agents/test-generator/prompt.md +27 -0
  19. package/.kb/devkit/agents/test-generator/runbook.md +18 -0
  20. package/.vscode/settings.json +23 -0
  21. package/CHANGELOG.md +33 -0
  22. package/CONTRIBUTING.md +117 -0
  23. package/LICENSE +21 -0
  24. package/README.md +306 -0
  25. package/docs/DECLARATIVE-FLAGS-AND-ENV.md +622 -0
  26. package/docs/DOCUMENTATION.md +70 -0
  27. package/docs/adr/0000-template.md +52 -0
  28. package/docs/adr/0001-architecture-and-repository-layout.md +31 -0
  29. package/docs/adr/0002-plugins-and-extensibility.md +44 -0
  30. package/docs/adr/0003-package-and-module-boundaries.md +35 -0
  31. package/docs/adr/0004-versioning-and-release-policy.md +36 -0
  32. package/docs/adr/0005-reactive-loader-pattern.md +179 -0
  33. package/docs/adr/0006-declarative-flags-and-env-systems.md +376 -0
  34. package/eslint.config.js +27 -0
  35. package/kb-labs.config.json +5 -0
  36. package/package.json +88 -0
  37. package/package.json.bin +25 -0
  38. package/package.json.lib +30 -0
  39. package/packages/shared-cli-ui/CHANGELOG.md +20 -0
  40. package/packages/shared-cli-ui/README.md +342 -0
  41. package/packages/shared-cli-ui/docs/ARCHITECTURE.md +105 -0
  42. package/packages/shared-cli-ui/eslint.config.js +27 -0
  43. package/packages/shared-cli-ui/package.json +72 -0
  44. package/packages/shared-cli-ui/src/__tests__/artifacts-display.spec.ts +89 -0
  45. package/packages/shared-cli-ui/src/__tests__/format.spec.ts +44 -0
  46. package/packages/shared-cli-ui/src/__tests__/loader-json-mode.test.ts +119 -0
  47. package/packages/shared-cli-ui/src/artifacts-display.ts +266 -0
  48. package/packages/shared-cli-ui/src/cli-auto-discovery.ts +120 -0
  49. package/packages/shared-cli-ui/src/colors.ts +142 -0
  50. package/packages/shared-cli-ui/src/command-discovery.ts +72 -0
  51. package/packages/shared-cli-ui/src/command-output.ts +153 -0
  52. package/packages/shared-cli-ui/src/command-result.ts +267 -0
  53. package/packages/shared-cli-ui/src/command-runner.ts +310 -0
  54. package/packages/shared-cli-ui/src/command-suggestions.ts +204 -0
  55. package/packages/shared-cli-ui/src/debug/components/output.ts +141 -0
  56. package/packages/shared-cli-ui/src/debug/components/trace.ts +101 -0
  57. package/packages/shared-cli-ui/src/debug/components/tree.ts +88 -0
  58. package/packages/shared-cli-ui/src/debug/formatters/ai.ts +17 -0
  59. package/packages/shared-cli-ui/src/debug/formatters/human.ts +98 -0
  60. package/packages/shared-cli-ui/src/debug/formatters/timeline.ts +94 -0
  61. package/packages/shared-cli-ui/src/debug/index.ts +56 -0
  62. package/packages/shared-cli-ui/src/debug/types.ts +57 -0
  63. package/packages/shared-cli-ui/src/debug/utilities.ts +203 -0
  64. package/packages/shared-cli-ui/src/dynamic-command-discovery.ts +131 -0
  65. package/packages/shared-cli-ui/src/format.ts +412 -0
  66. package/packages/shared-cli-ui/src/index.ts +34 -0
  67. package/packages/shared-cli-ui/src/loader.ts +196 -0
  68. package/packages/shared-cli-ui/src/manifest-parser.ts +151 -0
  69. package/packages/shared-cli-ui/src/modern-format.ts +271 -0
  70. package/packages/shared-cli-ui/src/multi-cli-suggestions.ts +159 -0
  71. package/packages/shared-cli-ui/src/table.ts +134 -0
  72. package/packages/shared-cli-ui/src/timing-tracker.ts +68 -0
  73. package/packages/shared-cli-ui/src/utils/context.ts +12 -0
  74. package/packages/shared-cli-ui/src/utils/env.ts +164 -0
  75. package/packages/shared-cli-ui/src/utils/flags.ts +269 -0
  76. package/packages/shared-cli-ui/src/utils/path.ts +8 -0
  77. package/packages/shared-cli-ui/tsconfig.build.json +15 -0
  78. package/packages/shared-cli-ui/tsconfig.json +9 -0
  79. package/packages/shared-cli-ui/tsup.config.ts +11 -0
  80. package/packages/shared-cli-ui/vitest.config.ts +15 -0
  81. package/packages/shared-command-kit/CHANGELOG.md +20 -0
  82. package/packages/shared-command-kit/LICENSE +22 -0
  83. package/packages/shared-command-kit/README.md +1030 -0
  84. package/packages/shared-command-kit/docs/HIGH-LEVEL-API.md +89 -0
  85. package/packages/shared-command-kit/docs/LOW-LEVEL-API.md +105 -0
  86. package/packages/shared-command-kit/docs/MIGRATION-GUIDE.md +135 -0
  87. package/packages/shared-command-kit/eslint.config.js +27 -0
  88. package/packages/shared-command-kit/eslint.config.ts +14 -0
  89. package/packages/shared-command-kit/package.json +76 -0
  90. package/packages/shared-command-kit/prettierrc.json +5 -0
  91. package/packages/shared-command-kit/src/__tests__/define-command.spec.ts +294 -0
  92. package/packages/shared-command-kit/src/__tests__/define-route.test.ts +285 -0
  93. package/packages/shared-command-kit/src/__tests__/define-system-command.spec.ts +508 -0
  94. package/packages/shared-command-kit/src/__tests__/define-webhook.test.ts +156 -0
  95. package/packages/shared-command-kit/src/__tests__/define-websocket.test.ts +316 -0
  96. package/packages/shared-command-kit/src/__tests__/errors.spec.ts +45 -0
  97. package/packages/shared-command-kit/src/__tests__/flags.spec.ts +353 -0
  98. package/packages/shared-command-kit/src/__tests__/platform-api.test.ts +135 -0
  99. package/packages/shared-command-kit/src/__tests__/plugin-context-v3.snapshot.spec.ts +240 -0
  100. package/packages/shared-command-kit/src/__tests__/ws-types.test.ts +359 -0
  101. package/packages/shared-command-kit/src/analytics/index.ts +6 -0
  102. package/packages/shared-command-kit/src/analytics/with-analytics.ts +195 -0
  103. package/packages/shared-command-kit/src/define-action.ts +100 -0
  104. package/packages/shared-command-kit/src/define-command.ts +113 -0
  105. package/packages/shared-command-kit/src/define-route.ts +113 -0
  106. package/packages/shared-command-kit/src/define-system-command.ts +362 -0
  107. package/packages/shared-command-kit/src/define-webhook.ts +115 -0
  108. package/packages/shared-command-kit/src/define-websocket.ts +308 -0
  109. package/packages/shared-command-kit/src/errors/factory.ts +282 -0
  110. package/packages/shared-command-kit/src/errors/format-validation.ts +144 -0
  111. package/packages/shared-command-kit/src/errors/format.ts +92 -0
  112. package/packages/shared-command-kit/src/errors/index.ts +9 -0
  113. package/packages/shared-command-kit/src/errors/types.ts +32 -0
  114. package/packages/shared-command-kit/src/flags/define.ts +92 -0
  115. package/packages/shared-command-kit/src/flags/index.ts +9 -0
  116. package/packages/shared-command-kit/src/flags/types.ts +153 -0
  117. package/packages/shared-command-kit/src/flags/validate.ts +358 -0
  118. package/packages/shared-command-kit/src/helpers/context.ts +8 -0
  119. package/packages/shared-command-kit/src/helpers/flags.ts +84 -0
  120. package/packages/shared-command-kit/src/helpers/index.ts +42 -0
  121. package/packages/shared-command-kit/src/helpers/patterns.ts +464 -0
  122. package/packages/shared-command-kit/src/helpers/platform.ts +335 -0
  123. package/packages/shared-command-kit/src/helpers/use-analytics.ts +95 -0
  124. package/packages/shared-command-kit/src/helpers/use-cache.ts +97 -0
  125. package/packages/shared-command-kit/src/helpers/use-config.ts +99 -0
  126. package/packages/shared-command-kit/src/helpers/use-embeddings.ts +49 -0
  127. package/packages/shared-command-kit/src/helpers/use-llm.ts +316 -0
  128. package/packages/shared-command-kit/src/helpers/use-logger.ts +77 -0
  129. package/packages/shared-command-kit/src/helpers/use-platform.ts +111 -0
  130. package/packages/shared-command-kit/src/helpers/use-resource-broker.ts +106 -0
  131. package/packages/shared-command-kit/src/helpers/use-storage.ts +71 -0
  132. package/packages/shared-command-kit/src/helpers/use-vector-store.ts +49 -0
  133. package/packages/shared-command-kit/src/helpers/validation.ts +398 -0
  134. package/packages/shared-command-kit/src/index.ts +410 -0
  135. package/packages/shared-command-kit/src/jobs.ts +132 -0
  136. package/packages/shared-command-kit/src/lifecycle/define-handlers.ts +366 -0
  137. package/packages/shared-command-kit/src/lifecycle/index.ts +6 -0
  138. package/packages/shared-command-kit/src/manifest.ts +127 -0
  139. package/packages/shared-command-kit/src/rest/define-handler.ts +187 -0
  140. package/packages/shared-command-kit/src/rest/index.ts +11 -0
  141. package/packages/shared-command-kit/src/studio/index.ts +12 -0
  142. package/packages/shared-command-kit/src/validation/index.ts +6 -0
  143. package/packages/shared-command-kit/src/validation/schema-builders.ts +409 -0
  144. package/packages/shared-command-kit/src/ws-types.ts +106 -0
  145. package/packages/shared-command-kit/tsconfig.build.json +15 -0
  146. package/packages/shared-command-kit/tsconfig.json +9 -0
  147. package/packages/shared-command-kit/tsup.config.ts +30 -0
  148. package/packages/shared-command-kit/vitest.config.ts +4 -0
  149. package/packages/shared-http/package.json +67 -0
  150. package/packages/shared-http/src/__tests__/log-correlation.test.ts +81 -0
  151. package/packages/shared-http/src/__tests__/operation-metrics-tracker.test.ts +55 -0
  152. package/packages/shared-http/src/http-observability-collector.ts +363 -0
  153. package/packages/shared-http/src/index.ts +36 -0
  154. package/packages/shared-http/src/log-correlation.ts +89 -0
  155. package/packages/shared-http/src/operation-metrics-tracker.ts +107 -0
  156. package/packages/shared-http/src/register-openapi.ts +108 -0
  157. package/packages/shared-http/src/resolve-schema-ref.ts +75 -0
  158. package/packages/shared-http/src/schemas.ts +29 -0
  159. package/packages/shared-http/src/service-observability.ts +63 -0
  160. package/packages/shared-http/tsconfig.build.json +15 -0
  161. package/packages/shared-http/tsconfig.json +9 -0
  162. package/packages/shared-http/tsup.config.ts +23 -0
  163. package/packages/shared-http/vitest.config.ts +13 -0
  164. package/packages/shared-perm-presets/CHANGELOG.md +20 -0
  165. package/packages/shared-perm-presets/README.md +78 -0
  166. package/packages/shared-perm-presets/eslint.config.js +27 -0
  167. package/packages/shared-perm-presets/package.json +45 -0
  168. package/packages/shared-perm-presets/src/__tests__/combine.test.ts +403 -0
  169. package/packages/shared-perm-presets/src/__tests__/presets.test.ts +205 -0
  170. package/packages/shared-perm-presets/src/combine.ts +278 -0
  171. package/packages/shared-perm-presets/src/index.ts +18 -0
  172. package/packages/shared-perm-presets/src/presets/ci-environment.ts +34 -0
  173. package/packages/shared-perm-presets/src/presets/full-env.ts +16 -0
  174. package/packages/shared-perm-presets/src/presets/git-workflow.ts +40 -0
  175. package/packages/shared-perm-presets/src/presets/index.ts +8 -0
  176. package/packages/shared-perm-presets/src/presets/kb-platform.ts +30 -0
  177. package/packages/shared-perm-presets/src/presets/llm-access.ts +29 -0
  178. package/packages/shared-perm-presets/src/presets/minimal.ts +21 -0
  179. package/packages/shared-perm-presets/src/presets/npm-publish.ts +48 -0
  180. package/packages/shared-perm-presets/src/presets/vector-store.ts +40 -0
  181. package/packages/shared-perm-presets/src/types.ts +192 -0
  182. package/packages/shared-perm-presets/tsconfig.build.json +15 -0
  183. package/packages/shared-perm-presets/tsconfig.json +9 -0
  184. package/packages/shared-perm-presets/tsup.config.ts +8 -0
  185. package/packages/shared-perm-presets/vitest.config.ts +9 -0
  186. package/packages/shared-testing/CHANGELOG.md +20 -0
  187. package/packages/shared-testing/README.md +430 -0
  188. package/packages/shared-testing/package.json +51 -0
  189. package/packages/shared-testing/src/__tests__/create-test-context.test.ts +199 -0
  190. package/packages/shared-testing/src/__tests__/mock-cache.test.ts +174 -0
  191. package/packages/shared-testing/src/__tests__/mock-llm.test.ts +212 -0
  192. package/packages/shared-testing/src/__tests__/setup-platform.test.ts +90 -0
  193. package/packages/shared-testing/src/__tests__/test-command.test.ts +557 -0
  194. package/packages/shared-testing/src/create-test-context.ts +550 -0
  195. package/packages/shared-testing/src/index.ts +77 -0
  196. package/packages/shared-testing/src/mock-cache.ts +179 -0
  197. package/packages/shared-testing/src/mock-llm.ts +319 -0
  198. package/packages/shared-testing/src/mock-logger.ts +97 -0
  199. package/packages/shared-testing/src/mock-storage.ts +108 -0
  200. package/packages/shared-testing/src/setup-platform.ts +101 -0
  201. package/packages/shared-testing/src/test-command.ts +288 -0
  202. package/packages/shared-testing/tsconfig.build.json +15 -0
  203. package/packages/shared-testing/tsconfig.json +9 -0
  204. package/packages/shared-testing/tsup.config.ts +20 -0
  205. package/packages/shared-testing/vitest.config.ts +3 -0
  206. package/packages/shared-tool-kit/CHANGELOG.md +20 -0
  207. package/packages/shared-tool-kit/package.json +47 -0
  208. package/packages/shared-tool-kit/src/__tests__/factory.test.ts +103 -0
  209. package/packages/shared-tool-kit/src/__tests__/mock-tool.test.ts +95 -0
  210. package/packages/shared-tool-kit/src/factory.ts +126 -0
  211. package/packages/shared-tool-kit/src/index.ts +32 -0
  212. package/packages/shared-tool-kit/src/testing/index.ts +84 -0
  213. package/packages/shared-tool-kit/tsconfig.build.json +15 -0
  214. package/packages/shared-tool-kit/tsconfig.json +9 -0
  215. package/packages/shared-tool-kit/tsup.config.ts +21 -0
  216. package/pnpm-workspace.yaml +11070 -0
  217. package/prettierrc.json +1 -0
  218. package/scripts/devkit-sync.mjs +37 -0
  219. package/scripts/hooks/post-push +9 -0
  220. package/scripts/hooks/pre-commit +9 -0
  221. package/scripts/hooks/pre-push +9 -0
  222. package/tsconfig.base.json +9 -0
  223. package/tsconfig.build.json +15 -0
  224. package/tsconfig.json +9 -0
  225. package/tsconfig.paths.json +50 -0
  226. package/tsconfig.tools.json +18 -0
  227. package/tsup.config.bin.ts +34 -0
  228. package/tsup.config.cli.ts +41 -0
  229. package/tsup.config.dual.ts +46 -0
  230. package/tsup.config.ts +36 -0
  231. package/tsup.external.json +104 -0
  232. package/vitest.config.ts +48 -0
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @module @kb-labs/shared-command-kit/helpers/use-vector-store
3
+ * Global VectorStore access helper
4
+ */
5
+
6
+ import { usePlatform } from './use-platform';
7
+ import type { IVectorStore } from '@kb-labs/core-platform';
8
+
9
+ /**
10
+ * Access global VectorStore adapter
11
+ *
12
+ * Returns the platform vector store adapter (Qdrant, local, etc.).
13
+ * Returns undefined if vectorStore is not configured (graceful degradation).
14
+ *
15
+ * @returns VectorStore adapter or undefined if not configured
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const vectorStore = useVectorStore();
20
+ *
21
+ * if (vectorStore) {
22
+ * await vectorStore.upsert([{ id: '1', vector: [0.1, 0.2], metadata: {} }]);
23
+ * const results = await vectorStore.search([0.1, 0.2], 10);
24
+ * }
25
+ * ```
26
+ */
27
+ export function useVectorStore(): IVectorStore | undefined {
28
+ const platform = usePlatform();
29
+ return platform.vectorStore;
30
+ }
31
+
32
+ /**
33
+ * Check if VectorStore is available
34
+ *
35
+ * @returns true if vectorStore is configured and ready
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * if (isVectorStoreAvailable()) {
40
+ * await vectorStore.upsert(records);
41
+ * } else {
42
+ * // Use local fallback
43
+ * }
44
+ * ```
45
+ */
46
+ export function isVectorStoreAvailable(): boolean {
47
+ const vectorStore = useVectorStore();
48
+ return !!vectorStore;
49
+ }
@@ -0,0 +1,398 @@
1
+ /**
2
+ * @module @kb-labs/shared-command-kit/helpers/validation
3
+ * Validation helpers with common schemas and Zod integration.
4
+ *
5
+ * Provides ready-to-use validation schemas and helpers for common use cases.
6
+ */
7
+
8
+ import { z } from 'zod';
9
+
10
+ /**
11
+ * Validation error with formatted message.
12
+ */
13
+ export class ValidationError extends Error {
14
+ constructor(
15
+ message: string,
16
+ public readonly issues?: Array<{ path: string; message: string }>
17
+ ) {
18
+ super(message);
19
+ this.name = 'ValidationError';
20
+ }
21
+ }
22
+
23
+ // ═══════════════════════════════════════════════════════════════════════════
24
+ // COMMON SCHEMAS
25
+ // ═══════════════════════════════════════════════════════════════════════════
26
+
27
+ /**
28
+ * Common validation schemas for reuse across plugins.
29
+ */
30
+ export const schemas = {
31
+ /**
32
+ * NPM package name (scoped or unscoped).
33
+ * @example "@kb-labs/plugin-template", "lodash"
34
+ */
35
+ packageName: z.string().regex(/^(@[\w-]+\/)?[\w-]+$/, 'Invalid package name'),
36
+
37
+ /**
38
+ * Scoped NPM package name (must start with @).
39
+ * @example "@kb-labs/plugin-template"
40
+ */
41
+ scopedPackageName: z.string().regex(/^@[\w-]+\/[\w-]+$/, 'Invalid scoped package name'),
42
+
43
+ /**
44
+ * Semantic version (semver).
45
+ * @example "1.0.0", "2.1.3-beta.1"
46
+ */
47
+ semver: z.string().regex(/^\d+\.\d+\.\d+(-[\w.]+)?$/, 'Invalid semver'),
48
+
49
+ /**
50
+ * Email address.
51
+ */
52
+ email: z.string().email('Invalid email address'),
53
+
54
+ /**
55
+ * HTTP/HTTPS URL.
56
+ */
57
+ url: z.string().url('Invalid URL'),
58
+
59
+ /**
60
+ * GitHub repository URL.
61
+ * @example "https://github.com/owner/repo"
62
+ */
63
+ githubUrl: z
64
+ .string()
65
+ .regex(/^https:\/\/github\.com\/[\w-]+\/[\w-]+$/, 'Invalid GitHub URL'),
66
+
67
+ /**
68
+ * File path (Unix-style).
69
+ * @example "src/index.ts", "path/to/file.json"
70
+ */
71
+ filePath: z.string().regex(/^[\w\-./]+$/, 'Invalid file path'),
72
+
73
+ /**
74
+ * Non-empty string (trimmed).
75
+ */
76
+ nonEmptyString: z.string().trim().min(1, 'String cannot be empty'),
77
+
78
+ /**
79
+ * Positive integer.
80
+ */
81
+ positiveInt: z.number().int().positive('Must be positive integer'),
82
+
83
+ /**
84
+ * Non-negative integer (including 0).
85
+ */
86
+ nonNegativeInt: z.number().int().min(0, 'Must be non-negative integer'),
87
+
88
+ /**
89
+ * Port number (1-65535).
90
+ */
91
+ port: z.number().int().min(1).max(65535, 'Invalid port number'),
92
+
93
+ /**
94
+ * UUID v4.
95
+ */
96
+ uuid: z.string().uuid('Invalid UUID'),
97
+
98
+ /**
99
+ * ISO 8601 date string.
100
+ * @example "2025-12-05T12:00:00Z"
101
+ */
102
+ isoDate: z.string().datetime('Invalid ISO 8601 date'),
103
+
104
+ /**
105
+ * JSON string (can be parsed).
106
+ */
107
+ jsonString: z.string().refine(
108
+ (val) => {
109
+ try {
110
+ JSON.parse(val);
111
+ return true;
112
+ } catch {
113
+ return false;
114
+ }
115
+ },
116
+ { message: 'Invalid JSON string' }
117
+ ),
118
+
119
+ /**
120
+ * Hexadecimal color code.
121
+ * @example "#FF5733", "#FFF"
122
+ */
123
+ hexColor: z.string().regex(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/, 'Invalid hex color'),
124
+
125
+ /**
126
+ * Tenant ID (alphanumeric, dash, underscore).
127
+ * @example "default", "acme-corp", "tenant_123"
128
+ */
129
+ tenantId: z.string().regex(/^[\w-]+$/, 'Invalid tenant ID'),
130
+
131
+ /**
132
+ * Plugin ID (scoped package name).
133
+ * @example "@kb-labs/plugin-template"
134
+ */
135
+ pluginId: z.string().regex(/^@[\w-]+\/[\w-]+$/, 'Invalid plugin ID'),
136
+ };
137
+
138
+ // ═══════════════════════════════════════════════════════════════════════════
139
+ // VALIDATION FUNCTIONS
140
+ // ═══════════════════════════════════════════════════════════════════════════
141
+
142
+ /**
143
+ * Format Zod error into readable message.
144
+ */
145
+ function formatZodError(error: z.ZodError): string {
146
+ const issues = error.issues
147
+ .map((issue) => {
148
+ const path = issue.path.join('.');
149
+ return path ? `${path}: ${issue.message}` : issue.message;
150
+ })
151
+ .join('\n ');
152
+
153
+ return `Validation failed:\n ${issues}`;
154
+ }
155
+
156
+ /**
157
+ * Validate data against a Zod schema.
158
+ * Throws ValidationError with formatted message on failure.
159
+ *
160
+ * @param schema - Zod schema
161
+ * @param data - Data to validate
162
+ * @returns Validated data (typed)
163
+ * @throws {ValidationError} If validation fails
164
+ *
165
+ * @example
166
+ * ```typescript
167
+ * const userSchema = z.object({
168
+ * name: z.string(),
169
+ * email: schemas.email,
170
+ * });
171
+ *
172
+ * const user = validateInput(userSchema, rawInput);
173
+ * // user is typed as { name: string; email: string }
174
+ * ```
175
+ */
176
+ export function validateInput<T>(schema: z.Schema<T>, data: unknown): T {
177
+ try {
178
+ return schema.parse(data);
179
+ } catch (error) {
180
+ if (error instanceof z.ZodError) {
181
+ const issues = error.issues.map((issue) => ({
182
+ path: issue.path.join('.'),
183
+ message: issue.message,
184
+ }));
185
+ throw new ValidationError(formatZodError(error), issues);
186
+ }
187
+ throw error;
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Safely validate data against a schema.
193
+ * Returns success/failure result instead of throwing.
194
+ *
195
+ * @param schema - Zod schema
196
+ * @param data - Data to validate
197
+ * @returns Validation result
198
+ *
199
+ * @example
200
+ * ```typescript
201
+ * const result = safeValidate(schemas.email, input);
202
+ *
203
+ * if (result.success) {
204
+ * console.log('Valid email:', result.data);
205
+ * } else {
206
+ * console.error('Invalid:', result.error);
207
+ * }
208
+ * ```
209
+ */
210
+ export function safeValidate<T>(
211
+ schema: z.Schema<T>,
212
+ data: unknown
213
+ ): { success: true; data: T } | { success: false; error: string; issues: Array<{ path: string; message: string }> } {
214
+ const result = schema.safeParse(data);
215
+
216
+ if (result.success) {
217
+ return { success: true, data: result.data };
218
+ }
219
+
220
+ const issues = result.error.issues.map((issue) => ({
221
+ path: issue.path.join('.'),
222
+ message: issue.message,
223
+ }));
224
+
225
+ return {
226
+ success: false,
227
+ error: formatZodError(result.error),
228
+ issues,
229
+ };
230
+ }
231
+
232
+ /**
233
+ * Validate schema against data (general purpose).
234
+ * Use this for any data validation, not just flags.
235
+ *
236
+ * @param schema - Zod schema
237
+ * @param data - Data to validate
238
+ * @returns Validated data (typed)
239
+ * @throws {ValidationError} If validation fails
240
+ *
241
+ * @example
242
+ * ```typescript
243
+ * const configSchema = z.object({
244
+ * output: z.string().optional(),
245
+ * force: z.boolean().default(false),
246
+ * });
247
+ *
248
+ * const validConfig = validateSchema(configSchema, rawConfig);
249
+ * ```
250
+ */
251
+ export function validateSchema<T>(schema: z.Schema<T>, data: unknown): T {
252
+ try {
253
+ return validateInput(schema, data);
254
+ } catch (error) {
255
+ if (error instanceof ValidationError) {
256
+ throw new ValidationError(`Validation failed: ${error.message}`, error.issues);
257
+ }
258
+ throw error;
259
+ }
260
+ }
261
+
262
+ /**
263
+ * Validate array of items against schema.
264
+ * Returns validated items and any errors.
265
+ *
266
+ * @param schema - Zod schema for single item
267
+ * @param items - Array of items
268
+ * @returns Validated items and errors
269
+ *
270
+ * @example
271
+ * ```typescript
272
+ * const { valid, invalid } = validateArray(schemas.email, emails);
273
+ *
274
+ * console.log(`${valid.length} valid, ${invalid.length} invalid`);
275
+ * for (const { index, error } of invalid) {
276
+ * console.error(`Item ${index}: ${error}`);
277
+ * }
278
+ * ```
279
+ */
280
+ export function validateArray<T>(
281
+ schema: z.Schema<T>,
282
+ items: unknown[]
283
+ ): {
284
+ valid: T[];
285
+ invalid: Array<{ index: number; item: unknown; error: string }>;
286
+ } {
287
+ const valid: T[] = [];
288
+ const invalid: Array<{ index: number; item: unknown; error: string }> = [];
289
+
290
+ for (let i = 0; i < items.length; i++) {
291
+ const result = safeValidate(schema, items[i]);
292
+ if (result.success) {
293
+ valid.push(result.data);
294
+ } else {
295
+ invalid.push({ index: i, item: items[i], error: result.error });
296
+ }
297
+ }
298
+
299
+ return { valid, invalid };
300
+ }
301
+
302
+ // ═══════════════════════════════════════════════════════════════════════════
303
+ // CUSTOM VALIDATORS
304
+ // ═══════════════════════════════════════════════════════════════════════════
305
+
306
+ /**
307
+ * Check if value is a valid package name.
308
+ */
309
+ export function isPackageName(value: unknown): value is string {
310
+ return schemas.packageName.safeParse(value).success;
311
+ }
312
+
313
+ /**
314
+ * Check if value is a valid semver.
315
+ */
316
+ export function isSemver(value: unknown): value is string {
317
+ return schemas.semver.safeParse(value).success;
318
+ }
319
+
320
+ /**
321
+ * Check if value is a valid email.
322
+ */
323
+ export function isEmail(value: unknown): value is string {
324
+ return schemas.email.safeParse(value).success;
325
+ }
326
+
327
+ /**
328
+ * Check if value is a valid URL.
329
+ */
330
+ export function isUrl(value: unknown): value is string {
331
+ return schemas.url.safeParse(value).success;
332
+ }
333
+
334
+ /**
335
+ * Check if value is a valid UUID.
336
+ */
337
+ export function isUUID(value: unknown): value is string {
338
+ return schemas.uuid.safeParse(value).success;
339
+ }
340
+
341
+ // ═══════════════════════════════════════════════════════════════════════════
342
+ // COMMON PATTERNS
343
+ // ═══════════════════════════════════════════════════════════════════════════
344
+
345
+ /**
346
+ * Create optional string field with default.
347
+ *
348
+ * @example
349
+ * ```typescript
350
+ * const schema = z.object({
351
+ * format: optionalString('json'), // defaults to 'json' if not provided
352
+ * });
353
+ * ```
354
+ */
355
+ export function optionalString(defaultValue: string) {
356
+ return z.string().default(defaultValue);
357
+ }
358
+
359
+ /**
360
+ * Create optional boolean field with default.
361
+ *
362
+ * @example
363
+ * ```typescript
364
+ * const schema = z.object({
365
+ * force: optionalBoolean(false), // defaults to false if not provided
366
+ * });
367
+ * ```
368
+ */
369
+ export function optionalBoolean(defaultValue: boolean) {
370
+ return z.boolean().default(defaultValue);
371
+ }
372
+
373
+ /**
374
+ * Create optional number field with default.
375
+ *
376
+ * @example
377
+ * ```typescript
378
+ * const schema = z.object({
379
+ * timeout: optionalNumber(5000), // defaults to 5000 if not provided
380
+ * });
381
+ * ```
382
+ */
383
+ export function optionalNumber(defaultValue: number) {
384
+ return z.number().default(defaultValue);
385
+ }
386
+
387
+ /**
388
+ * Create enum schema from array of values.
389
+ *
390
+ * @example
391
+ * ```typescript
392
+ * const formatSchema = enumFromArray(['json', 'yaml', 'toml'] as const);
393
+ * // Type: 'json' | 'yaml' | 'toml'
394
+ * ```
395
+ */
396
+ export function enumFromArray<T extends readonly [string, ...string[]]>(values: T) {
397
+ return z.enum(values);
398
+ }