@shepai/cli 1.2.0 → 1.3.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 (208) hide show
  1. package/README.md +29 -12
  2. package/dist/eslint.config.d.mts +3 -0
  3. package/dist/eslint.config.d.mts.map +1 -0
  4. package/dist/eslint.config.mjs +188 -0
  5. package/dist/src/application/ports/output/index.d.ts +8 -0
  6. package/dist/src/application/ports/output/index.d.ts.map +1 -0
  7. package/dist/src/application/ports/output/index.js +7 -0
  8. package/dist/src/application/ports/output/settings.repository.interface.d.ts +43 -0
  9. package/dist/src/application/ports/output/settings.repository.interface.d.ts.map +1 -0
  10. package/dist/src/application/ports/output/settings.repository.interface.js +11 -0
  11. package/dist/src/application/use-cases/settings/index.d.ts +9 -0
  12. package/dist/src/application/use-cases/settings/index.d.ts.map +1 -0
  13. package/dist/src/application/use-cases/settings/index.js +8 -0
  14. package/dist/src/application/use-cases/settings/initialize-settings.use-case.d.ts +33 -0
  15. package/dist/src/application/use-cases/settings/initialize-settings.use-case.d.ts.map +1 -0
  16. package/dist/src/application/use-cases/settings/initialize-settings.use-case.js +63 -0
  17. package/dist/src/application/use-cases/settings/load-settings.use-case.d.ts +33 -0
  18. package/dist/src/application/use-cases/settings/load-settings.use-case.d.ts.map +1 -0
  19. package/dist/src/application/use-cases/settings/load-settings.use-case.js +57 -0
  20. package/dist/src/application/use-cases/settings/update-settings.use-case.d.ts +33 -0
  21. package/dist/src/application/use-cases/settings/update-settings.use-case.d.ts.map +1 -0
  22. package/dist/src/application/use-cases/settings/update-settings.use-case.js +56 -0
  23. package/dist/src/domain/factories/index.d.ts +7 -0
  24. package/dist/src/domain/factories/index.d.ts.map +1 -0
  25. package/dist/src/domain/factories/index.js +6 -0
  26. package/dist/src/domain/factories/settings-defaults.factory.d.ts +36 -0
  27. package/dist/src/domain/factories/settings-defaults.factory.d.ts.map +1 -0
  28. package/dist/src/domain/factories/settings-defaults.factory.js +81 -0
  29. package/dist/src/domain/generated/output.d.ts +717 -0
  30. package/dist/src/domain/generated/output.d.ts.map +1 -0
  31. package/dist/src/domain/generated/output.js +93 -0
  32. package/dist/src/index.d.ts.map +1 -0
  33. package/dist/src/infrastructure/di/container.d.ts +27 -0
  34. package/dist/src/infrastructure/di/container.d.ts.map +1 -0
  35. package/dist/src/infrastructure/di/container.js +53 -0
  36. package/dist/src/infrastructure/persistence/sqlite/connection.d.ts +39 -0
  37. package/dist/src/infrastructure/persistence/sqlite/connection.d.ts.map +1 -0
  38. package/dist/src/infrastructure/persistence/sqlite/connection.js +76 -0
  39. package/dist/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts +50 -0
  40. package/dist/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts.map +1 -0
  41. package/dist/src/infrastructure/persistence/sqlite/mappers/settings.mapper.js +80 -0
  42. package/dist/src/infrastructure/persistence/sqlite/migrations.d.ts +31 -0
  43. package/dist/src/infrastructure/persistence/sqlite/migrations.d.ts.map +1 -0
  44. package/dist/src/infrastructure/persistence/sqlite/migrations.js +66 -0
  45. package/dist/src/infrastructure/repositories/sqlite-settings.repository.d.ts +40 -0
  46. package/dist/src/infrastructure/repositories/sqlite-settings.repository.d.ts.map +1 -0
  47. package/dist/src/infrastructure/repositories/sqlite-settings.repository.js +123 -0
  48. package/dist/src/infrastructure/services/filesystem/shep-directory.service.d.ts +41 -0
  49. package/dist/src/infrastructure/services/filesystem/shep-directory.service.d.ts.map +1 -0
  50. package/dist/src/infrastructure/services/filesystem/shep-directory.service.js +64 -0
  51. package/dist/src/infrastructure/services/settings.service.d.ts +50 -0
  52. package/dist/src/infrastructure/services/settings.service.d.ts.map +1 -0
  53. package/dist/src/infrastructure/services/settings.service.js +67 -0
  54. package/dist/src/infrastructure/services/version.service.d.ts.map +1 -0
  55. package/dist/src/presentation/cli/commands/version.command.d.ts.map +1 -0
  56. package/dist/{presentation → src/presentation}/cli/index.d.ts +1 -1
  57. package/dist/src/presentation/cli/index.d.ts.map +1 -0
  58. package/dist/src/presentation/cli/index.js +86 -0
  59. package/dist/src/presentation/cli/ui/colors.d.ts.map +1 -0
  60. package/dist/src/presentation/cli/ui/formatters.d.ts.map +1 -0
  61. package/dist/src/presentation/cli/ui/index.d.ts.map +1 -0
  62. package/dist/src/presentation/cli/ui/messages.d.ts.map +1 -0
  63. package/dist/src/presentation/cli/ui/symbols.d.ts.map +1 -0
  64. package/dist/src/presentation/web/app/layout.d.ts +7 -0
  65. package/dist/src/presentation/web/app/layout.d.ts.map +1 -0
  66. package/dist/src/presentation/web/app/layout.js +21 -0
  67. package/dist/src/presentation/web/app/not-found.d.ts +2 -0
  68. package/dist/src/presentation/web/app/not-found.d.ts.map +1 -0
  69. package/dist/src/presentation/web/app/not-found.js +4 -0
  70. package/dist/src/presentation/web/app/page.d.ts +2 -0
  71. package/dist/src/presentation/web/app/page.d.ts.map +1 -0
  72. package/dist/src/presentation/web/app/page.js +6 -0
  73. package/dist/src/presentation/web/app/version/page.d.ts +2 -0
  74. package/dist/src/presentation/web/app/version/page.d.ts.map +1 -0
  75. package/dist/src/presentation/web/app/version/page.js +16 -0
  76. package/dist/src/presentation/web/components/features/index.d.ts +2 -0
  77. package/dist/src/presentation/web/components/features/index.d.ts.map +1 -0
  78. package/dist/src/presentation/web/components/features/index.js +2 -0
  79. package/dist/src/presentation/web/components/features/theme-toggle/index.d.ts +2 -0
  80. package/dist/src/presentation/web/components/features/theme-toggle/index.d.ts.map +1 -0
  81. package/dist/src/presentation/web/components/features/theme-toggle/index.js +1 -0
  82. package/dist/src/presentation/web/components/features/theme-toggle/theme-toggle.d.ts +2 -0
  83. package/dist/src/presentation/web/components/features/theme-toggle/theme-toggle.d.ts.map +1 -0
  84. package/dist/src/presentation/web/components/features/theme-toggle/theme-toggle.js +19 -0
  85. package/dist/src/presentation/web/components/features/theme-toggle/theme-toggle.stories.d.ts +8 -0
  86. package/dist/src/presentation/web/components/features/theme-toggle/theme-toggle.stories.d.ts.map +1 -0
  87. package/dist/src/presentation/web/components/features/theme-toggle/theme-toggle.stories.js +17 -0
  88. package/dist/src/presentation/web/components/ui/accordion.d.ts +8 -0
  89. package/dist/src/presentation/web/components/ui/accordion.d.ts.map +1 -0
  90. package/dist/src/presentation/web/components/ui/accordion.js +14 -0
  91. package/dist/src/presentation/web/components/ui/accordion.stories.d.ts +29 -0
  92. package/dist/src/presentation/web/components/ui/accordion.stories.d.ts.map +1 -0
  93. package/dist/src/presentation/web/components/ui/accordion.stories.js +35 -0
  94. package/dist/src/presentation/web/components/ui/alert.d.ts +9 -0
  95. package/dist/src/presentation/web/components/ui/alert.d.ts.map +1 -0
  96. package/dist/src/presentation/web/components/ui/alert.js +22 -0
  97. package/dist/src/presentation/web/components/ui/alert.stories.d.ts +10 -0
  98. package/dist/src/presentation/web/components/ui/alert.stories.d.ts.map +1 -0
  99. package/dist/src/presentation/web/components/ui/alert.stories.js +30 -0
  100. package/dist/src/presentation/web/components/ui/badge.d.ts +10 -0
  101. package/dist/src/presentation/web/components/ui/badge.d.ts.map +1 -0
  102. package/dist/src/presentation/web/components/ui/badge.js +20 -0
  103. package/dist/src/presentation/web/components/ui/badge.stories.d.ts +11 -0
  104. package/dist/src/presentation/web/components/ui/badge.stories.d.ts.map +1 -0
  105. package/dist/src/presentation/web/components/ui/badge.stories.js +44 -0
  106. package/dist/src/presentation/web/components/ui/button.d.ts +12 -0
  107. package/dist/src/presentation/web/components/ui/button.d.ts.map +1 -0
  108. package/dist/src/presentation/web/components/ui/button.js +33 -0
  109. package/dist/src/presentation/web/components/ui/button.stories.d.ts +17 -0
  110. package/dist/src/presentation/web/components/ui/button.stories.d.ts.map +1 -0
  111. package/dist/src/presentation/web/components/ui/button.stories.js +84 -0
  112. package/dist/src/presentation/web/components/ui/card.d.ts +9 -0
  113. package/dist/src/presentation/web/components/ui/card.d.ts.map +1 -0
  114. package/dist/src/presentation/web/components/ui/card.js +16 -0
  115. package/dist/src/presentation/web/components/ui/card.stories.d.ts +10 -0
  116. package/dist/src/presentation/web/components/ui/card.stories.d.ts.map +1 -0
  117. package/dist/src/presentation/web/components/ui/card.stories.js +24 -0
  118. package/dist/src/presentation/web/components/ui/dialog.d.ts +20 -0
  119. package/dist/src/presentation/web/components/ui/dialog.d.ts.map +1 -0
  120. package/dist/src/presentation/web/components/ui/dialog.js +23 -0
  121. package/dist/src/presentation/web/components/ui/dialog.stories.d.ts +9 -0
  122. package/dist/src/presentation/web/components/ui/dialog.stories.d.ts.map +1 -0
  123. package/dist/src/presentation/web/components/ui/dialog.stories.js +23 -0
  124. package/dist/src/presentation/web/components/ui/index.d.ts +13 -0
  125. package/dist/src/presentation/web/components/ui/index.d.ts.map +1 -0
  126. package/dist/src/presentation/web/components/ui/index.js +14 -0
  127. package/dist/src/presentation/web/components/ui/input.d.ts +4 -0
  128. package/dist/src/presentation/web/components/ui/input.d.ts.map +1 -0
  129. package/dist/src/presentation/web/components/ui/input.js +8 -0
  130. package/dist/src/presentation/web/components/ui/input.stories.d.ts +13 -0
  131. package/dist/src/presentation/web/components/ui/input.stories.d.ts.map +1 -0
  132. package/dist/src/presentation/web/components/ui/input.stories.js +55 -0
  133. package/dist/src/presentation/web/components/ui/label.d.ts +6 -0
  134. package/dist/src/presentation/web/components/ui/label.d.ts.map +1 -0
  135. package/dist/src/presentation/web/components/ui/label.js +10 -0
  136. package/dist/src/presentation/web/components/ui/label.stories.d.ts +9 -0
  137. package/dist/src/presentation/web/components/ui/label.stories.d.ts.map +1 -0
  138. package/dist/src/presentation/web/components/ui/label.stories.js +23 -0
  139. package/dist/src/presentation/web/components/ui/popover.d.ts +8 -0
  140. package/dist/src/presentation/web/components/ui/popover.d.ts.map +1 -0
  141. package/dist/src/presentation/web/components/ui/popover.js +11 -0
  142. package/dist/src/presentation/web/components/ui/popover.stories.d.ts +10 -0
  143. package/dist/src/presentation/web/components/ui/popover.stories.d.ts.map +1 -0
  144. package/dist/src/presentation/web/components/ui/popover.stories.js +26 -0
  145. package/dist/src/presentation/web/components/ui/select.d.ts +14 -0
  146. package/dist/src/presentation/web/components/ui/select.d.ts.map +1 -0
  147. package/dist/src/presentation/web/components/ui/select.js +26 -0
  148. package/dist/src/presentation/web/components/ui/select.stories.d.ts +10 -0
  149. package/dist/src/presentation/web/components/ui/select.stories.d.ts.map +1 -0
  150. package/dist/src/presentation/web/components/ui/select.stories.js +23 -0
  151. package/dist/src/presentation/web/components/ui/sonner.d.ts +5 -0
  152. package/dist/src/presentation/web/components/ui/sonner.d.ts.map +1 -0
  153. package/dist/src/presentation/web/components/ui/sonner.js +14 -0
  154. package/dist/src/presentation/web/components/ui/sonner.stories.d.ts +13 -0
  155. package/dist/src/presentation/web/components/ui/sonner.stories.d.ts.map +1 -0
  156. package/dist/src/presentation/web/components/ui/sonner.stories.js +51 -0
  157. package/dist/src/presentation/web/components/ui/tabs.d.ts +8 -0
  158. package/dist/src/presentation/web/components/ui/tabs.d.ts.map +1 -0
  159. package/dist/src/presentation/web/components/ui/tabs.js +13 -0
  160. package/dist/src/presentation/web/components/ui/tabs.stories.d.ts +9 -0
  161. package/dist/src/presentation/web/components/ui/tabs.stories.d.ts.map +1 -0
  162. package/dist/src/presentation/web/components/ui/tabs.stories.js +23 -0
  163. package/dist/src/presentation/web/eslint.config.d.mts +3 -0
  164. package/dist/src/presentation/web/eslint.config.d.mts.map +1 -0
  165. package/dist/src/presentation/web/eslint.config.mjs +15 -0
  166. package/dist/src/presentation/web/hooks/useTheme.d.ts +12 -0
  167. package/dist/src/presentation/web/hooks/useTheme.d.ts.map +1 -0
  168. package/dist/src/presentation/web/hooks/useTheme.js +73 -0
  169. package/dist/src/presentation/web/lib/utils.d.ts +11 -0
  170. package/dist/src/presentation/web/lib/utils.d.ts.map +1 -0
  171. package/dist/src/presentation/web/lib/utils.js +13 -0
  172. package/dist/src/presentation/web/next.config.d.ts +4 -0
  173. package/dist/src/presentation/web/next.config.d.ts.map +1 -0
  174. package/dist/src/presentation/web/next.config.js +9 -0
  175. package/dist/src/presentation/web/postcss.config.d.mts +4 -0
  176. package/dist/src/presentation/web/postcss.config.d.mts.map +1 -0
  177. package/dist/src/presentation/web/postcss.config.mjs +8 -0
  178. package/dist/src/presentation/web/types/theme.d.ts +12 -0
  179. package/dist/src/presentation/web/types/theme.d.ts.map +1 -0
  180. package/dist/src/presentation/web/types/theme.js +5 -0
  181. package/dist/tsconfig.build.tsbuildinfo +1 -0
  182. package/package.json +60 -12
  183. package/dist/index.d.ts.map +0 -1
  184. package/dist/infrastructure/services/version.service.d.ts.map +0 -1
  185. package/dist/presentation/cli/commands/version.command.d.ts.map +0 -1
  186. package/dist/presentation/cli/index.d.ts.map +0 -1
  187. package/dist/presentation/cli/index.js +0 -48
  188. package/dist/presentation/cli/ui/colors.d.ts.map +0 -1
  189. package/dist/presentation/cli/ui/formatters.d.ts.map +0 -1
  190. package/dist/presentation/cli/ui/index.d.ts.map +0 -1
  191. package/dist/presentation/cli/ui/messages.d.ts.map +0 -1
  192. package/dist/presentation/cli/ui/symbols.d.ts.map +0 -1
  193. /package/dist/{index.d.ts → src/index.d.ts} +0 -0
  194. /package/dist/{index.js → src/index.js} +0 -0
  195. /package/dist/{infrastructure → src/infrastructure}/services/version.service.d.ts +0 -0
  196. /package/dist/{infrastructure → src/infrastructure}/services/version.service.js +0 -0
  197. /package/dist/{presentation → src/presentation}/cli/commands/version.command.d.ts +0 -0
  198. /package/dist/{presentation → src/presentation}/cli/commands/version.command.js +0 -0
  199. /package/dist/{presentation → src/presentation}/cli/ui/colors.d.ts +0 -0
  200. /package/dist/{presentation → src/presentation}/cli/ui/colors.js +0 -0
  201. /package/dist/{presentation → src/presentation}/cli/ui/formatters.d.ts +0 -0
  202. /package/dist/{presentation → src/presentation}/cli/ui/formatters.js +0 -0
  203. /package/dist/{presentation → src/presentation}/cli/ui/index.d.ts +0 -0
  204. /package/dist/{presentation → src/presentation}/cli/ui/index.js +0 -0
  205. /package/dist/{presentation → src/presentation}/cli/ui/messages.d.ts +0 -0
  206. /package/dist/{presentation → src/presentation}/cli/ui/messages.js +0 -0
  207. /package/dist/{presentation → src/presentation}/cli/ui/symbols.d.ts +0 -0
  208. /package/dist/{presentation → src/presentation}/cli/ui/symbols.js +0 -0
package/README.md CHANGED
@@ -57,7 +57,7 @@ This launches a TUI wizard to:
57
57
 
58
58
  1. Configure Claude Code authentication (setup token or use existing session)
59
59
  2. Start repository analysis
60
- 3. Open the web UI at `http://localhost:3030/`
60
+ 3. Open the web UI at `http://localhost:3000/`
61
61
 
62
62
  ## How It Works
63
63
 
@@ -148,7 +148,7 @@ Uses **Repository Pattern** with SQLite:
148
148
  | Package Manager | pnpm |
149
149
  | CLI Framework | Commander |
150
150
  | TUI Framework | [OpenTUI](https://opentui.com/) |
151
- | Web UI | Next.js + shadcn/ui |
151
+ | Web UI | Next.js 16 + React 19 + shadcn/ui ([@shepai/web](./src/presentation/web/)) |
152
152
  | Design System | Storybook |
153
153
  | Build Tool | Vite |
154
154
  | Database | SQLite |
@@ -157,19 +157,36 @@ Uses **Repository Pattern** with SQLite:
157
157
  | Embeddings | [Transformers.js](https://huggingface.co/docs/transformers.js) (local, multiple models) |
158
158
  | Testing | Vitest (unit/integration) + Playwright (e2e) |
159
159
  | Methodology | TDD (Red-Green-Refactor) |
160
+ | Security | Trivy, Gitleaks, Semgrep, Hadolint (CI gates) |
161
+
162
+ ## Security
163
+
164
+ Automated security scanning runs on every push and PR:
165
+
166
+ | Scanner | Purpose |
167
+ | ------------ | ------------------------------------------ |
168
+ | **Trivy** | Dependency & container vulnerability scans |
169
+ | **Gitleaks** | Secret detection in git history |
170
+ | **Semgrep** | SAST for TypeScript/JavaScript |
171
+ | **Hadolint** | Dockerfile best practices |
172
+
173
+ Security gates **block releases** on main—all scanners must pass before npm publish and Docker push.
174
+
175
+ See [CI/CD Documentation](./docs/development/cicd.md) for details.
160
176
 
161
177
  ## Documentation
162
178
 
163
- | Document | Description |
164
- | -------------------------------------------------- | ---------------------------------- |
165
- | [CLAUDE.md](./CLAUDE.md) | Guidance for Claude Code instances |
166
- | [AGENTS.md](./AGENTS.md) | Agent system architecture |
167
- | [CONTRIBUTING-AGENTS.md](./CONTRIBUTING-AGENTS.md) | AI agent contribution guidelines |
168
- | [Architecture](./docs/architecture/) | System design and patterns |
169
- | [Concepts](./docs/concepts/) | Core domain concepts |
170
- | [Guides](./docs/guides/) | User guides and tutorials |
171
- | [Development](./docs/development/) | Contributing and development setup |
172
- | [API Reference](./docs/api/) | Interface and model documentation |
179
+ | Document | Description |
180
+ | -------------------------------------------------- | ------------------------------------- |
181
+ | [CLAUDE.md](./CLAUDE.md) | Guidance for Claude Code instances |
182
+ | [AGENTS.md](./AGENTS.md) | Agent system architecture |
183
+ | [CONTRIBUTING-AGENTS.md](./CONTRIBUTING-AGENTS.md) | AI agent contribution guidelines |
184
+ | [Architecture](./docs/architecture/) | System design and patterns |
185
+ | [Concepts](./docs/concepts/) | Core domain concepts |
186
+ | [UI](./docs/ui/) | Web UI architecture and design system |
187
+ | [Guides](./docs/guides/) | User guides and tutorials |
188
+ | [Development](./docs/development/) | Contributing and development setup |
189
+ | [API Reference](./docs/api/) | Interface and model documentation |
173
190
 
174
191
  ## Contributing
175
192
 
@@ -0,0 +1,3 @@
1
+ declare const _default: import("typescript-eslint").FlatConfig.ConfigArray;
2
+ export default _default;
3
+ //# sourceMappingURL=eslint.config.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eslint.config.d.mts","sourceRoot":"","sources":["../eslint.config.mjs"],"names":[],"mappings":""}
@@ -0,0 +1,188 @@
1
+ // @ts-check
2
+ /**
3
+ * ESLint Flat Config for Shep AI CLI
4
+ *
5
+ * This configuration uses ESLint 9+ flat config format with TypeScript support.
6
+ * It's designed to be scalable and maintainable for a large open source project.
7
+ *
8
+ * @see https://eslint.org/docs/latest/use/configure/configuration-files
9
+ * @see https://typescript-eslint.io/getting-started/
10
+ */
11
+ import eslint from '@eslint/js';
12
+ import tseslint from 'typescript-eslint';
13
+ import prettierConfig from 'eslint-config-prettier';
14
+ import reactPlugin from 'eslint-plugin-react';
15
+ import reactHooksPlugin from 'eslint-plugin-react-hooks';
16
+ import nextPlugin from '@next/eslint-plugin-next';
17
+ export default tseslint.config(
18
+ // =============================================================================
19
+ // Global ignores (replaces .eslintignore)
20
+ // =============================================================================
21
+ {
22
+ ignores: [
23
+ // Build outputs
24
+ 'dist/**',
25
+ 'build/**',
26
+ '**/.next/**',
27
+ 'out/**',
28
+ '**/storybook-static/**',
29
+ // Dependencies
30
+ 'node_modules/**',
31
+ // Generated files
32
+ 'apis/**',
33
+ '*.generated.*',
34
+ 'coverage/**',
35
+ 'next-env.d.ts',
36
+ 'src/domain/generated/**', // TypeSpec-generated domain models
37
+ // TypeSpec (handled by tsp linter)
38
+ 'tsp/**',
39
+ // Test outputs
40
+ 'test-results/**',
41
+ 'playwright-report/**',
42
+ // Config files that don't need linting
43
+ '*.config.js',
44
+ '*.config.mjs',
45
+ '*.config.cjs',
46
+ ],
47
+ },
48
+ // =============================================================================
49
+ // Base ESLint recommended rules
50
+ // =============================================================================
51
+ eslint.configs.recommended,
52
+ // =============================================================================
53
+ // TypeScript recommended rules
54
+ // =============================================================================
55
+ ...tseslint.configs.recommended, ...tseslint.configs.stylistic,
56
+ // =============================================================================
57
+ // Project-specific TypeScript rules
58
+ // =============================================================================
59
+ {
60
+ files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'],
61
+ languageOptions: {
62
+ parserOptions: {
63
+ projectService: true,
64
+ tsconfigRootDir: import.meta.dirname,
65
+ },
66
+ },
67
+ rules: {
68
+ // -------------------------------------------------------------------------
69
+ // TypeScript-specific rules
70
+ // -------------------------------------------------------------------------
71
+ // Prefer type-only imports for types (tree-shaking friendly)
72
+ '@typescript-eslint/consistent-type-imports': [
73
+ 'warn',
74
+ {
75
+ prefer: 'type-imports',
76
+ fixStyle: 'inline-type-imports',
77
+ },
78
+ ],
79
+ // Require explicit return types on public methods
80
+ '@typescript-eslint/explicit-function-return-type': 'off',
81
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
82
+ // Allow unused vars with underscore prefix
83
+ '@typescript-eslint/no-unused-vars': [
84
+ 'warn',
85
+ {
86
+ argsIgnorePattern: '^_',
87
+ varsIgnorePattern: '^_',
88
+ caughtErrorsIgnorePattern: '^_',
89
+ },
90
+ ],
91
+ // Prefer nullish coalescing
92
+ '@typescript-eslint/prefer-nullish-coalescing': 'warn',
93
+ // Prefer optional chaining
94
+ '@typescript-eslint/prefer-optional-chain': 'warn',
95
+ // No floating promises (must handle or void)
96
+ '@typescript-eslint/no-floating-promises': 'off', // Enable when typed linting is set up
97
+ // No misused promises
98
+ '@typescript-eslint/no-misused-promises': 'off', // Enable when typed linting is set up
99
+ // -------------------------------------------------------------------------
100
+ // General code quality rules
101
+ // -------------------------------------------------------------------------
102
+ // Enforce consistent brace style
103
+ curly: ['warn', 'all'],
104
+ // Require === and !==
105
+ eqeqeq: ['error', 'always', { null: 'ignore' }],
106
+ // No console in production code (warn for now)
107
+ 'no-console': 'warn',
108
+ // No debugger statements
109
+ 'no-debugger': 'error',
110
+ // Prefer const over let when variable is not reassigned
111
+ 'prefer-const': 'warn',
112
+ // Prefer template literals over string concatenation
113
+ 'prefer-template': 'warn',
114
+ // No var, use let or const
115
+ 'no-var': 'error',
116
+ },
117
+ },
118
+ // =============================================================================
119
+ // JavaScript files (no TypeScript rules)
120
+ // =============================================================================
121
+ {
122
+ files: ['**/*.js', '**/*.mjs', '**/*.cjs'],
123
+ ...tseslint.configs.disableTypeChecked,
124
+ },
125
+ // =============================================================================
126
+ // CLI presentation layer - allow console statements (intentional user output)
127
+ // =============================================================================
128
+ {
129
+ files: ['src/presentation/cli/**/*.ts'],
130
+ rules: {
131
+ 'no-console': 'off',
132
+ },
133
+ },
134
+ // =============================================================================
135
+ // Test files - relaxed rules
136
+ // =============================================================================
137
+ {
138
+ files: ['**/*.test.ts', '**/*.spec.ts', '**/tests/**/*.ts'],
139
+ rules: {
140
+ '@typescript-eslint/no-explicit-any': 'off',
141
+ '@typescript-eslint/no-non-null-assertion': 'off',
142
+ 'no-console': 'off',
143
+ },
144
+ },
145
+ // =============================================================================
146
+ // React/Next.js configuration for web presentation layer
147
+ // =============================================================================
148
+ {
149
+ files: ['src/presentation/web/**/*.tsx', 'src/presentation/web/**/*.ts'],
150
+ plugins: {
151
+ react: reactPlugin,
152
+ 'react-hooks': reactHooksPlugin,
153
+ '@next/next': nextPlugin,
154
+ },
155
+ languageOptions: {
156
+ parserOptions: {
157
+ ecmaFeatures: {
158
+ jsx: true,
159
+ },
160
+ },
161
+ },
162
+ settings: {
163
+ react: {
164
+ version: 'detect',
165
+ },
166
+ },
167
+ rules: {
168
+ // React rules
169
+ 'react/jsx-uses-react': 'off', // Not needed with React 19 JSX transform
170
+ 'react/react-in-jsx-scope': 'off', // Not needed with React 19 JSX transform
171
+ 'react/prop-types': 'off', // Using TypeScript for prop types
172
+ 'react/jsx-no-target-blank': 'error',
173
+ 'react/jsx-key': 'error',
174
+ 'react/no-array-index-key': 'warn',
175
+ 'react/self-closing-comp': 'warn',
176
+ // React Hooks rules
177
+ 'react-hooks/rules-of-hooks': 'error',
178
+ 'react-hooks/exhaustive-deps': 'warn',
179
+ // Next.js rules
180
+ '@next/next/no-html-link-for-pages': 'error',
181
+ '@next/next/no-img-element': 'warn',
182
+ '@next/next/no-sync-scripts': 'error',
183
+ },
184
+ },
185
+ // =============================================================================
186
+ // Prettier compatibility (must be last)
187
+ // =============================================================================
188
+ prettierConfig);
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Application Output Ports Module
3
+ *
4
+ * Exports repository interfaces (output ports) for the Application layer.
5
+ * Infrastructure layer provides concrete implementations.
6
+ */
7
+ export type { ISettingsRepository } from './settings.repository.interface.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/application/ports/output/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Application Output Ports Module
3
+ *
4
+ * Exports repository interfaces (output ports) for the Application layer.
5
+ * Infrastructure layer provides concrete implementations.
6
+ */
7
+ export {};
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Settings Repository Interface
3
+ *
4
+ * Output port for Settings persistence operations.
5
+ * Implementations handle database-specific logic (SQLite, etc.).
6
+ *
7
+ * Following Clean Architecture:
8
+ * - Domain and Application layers depend on this interface
9
+ * - Infrastructure layer provides concrete implementations
10
+ */
11
+ import type { Settings } from '../../../domain/generated/output.js';
12
+ /**
13
+ * Repository interface for Settings entity persistence.
14
+ *
15
+ * Implementations must:
16
+ * - Enforce singleton pattern (only one Settings record allowed)
17
+ * - Handle database connection management
18
+ * - Provide thread-safe operations
19
+ */
20
+ export interface ISettingsRepository {
21
+ /**
22
+ * Initialize settings for the first time.
23
+ * Creates a new Settings record in the database.
24
+ *
25
+ * @param settings - The settings to initialize with
26
+ * @throws Error if settings already exist (singleton constraint)
27
+ */
28
+ initialize(settings: Settings): Promise<void>;
29
+ /**
30
+ * Load existing settings from the database.
31
+ *
32
+ * @returns The existing Settings or null if not initialized
33
+ */
34
+ load(): Promise<Settings | null>;
35
+ /**
36
+ * Update existing settings in the database.
37
+ *
38
+ * @param settings - The updated settings to persist
39
+ * @throws Error if settings don't exist (must initialize first)
40
+ */
41
+ update(settings: Settings): Promise<void>;
42
+ }
43
+ //# sourceMappingURL=settings.repository.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.repository.interface.d.ts","sourceRoot":"","sources":["../../../../../src/application/ports/output/settings.repository.interface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AAEpE;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;OAMG;IACH,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9C;;;;OAIG;IACH,IAAI,IAAI,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IAEjC;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Settings Repository Interface
3
+ *
4
+ * Output port for Settings persistence operations.
5
+ * Implementations handle database-specific logic (SQLite, etc.).
6
+ *
7
+ * Following Clean Architecture:
8
+ * - Domain and Application layers depend on this interface
9
+ * - Infrastructure layer provides concrete implementations
10
+ */
11
+ export {};
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Settings Use Cases Module
3
+ *
4
+ * Exports use cases for Settings entity operations.
5
+ */
6
+ export { InitializeSettingsUseCase } from './initialize-settings.use-case.js';
7
+ export { LoadSettingsUseCase } from './load-settings.use-case.js';
8
+ export { UpdateSettingsUseCase } from './update-settings.use-case.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/application/use-cases/settings/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Settings Use Cases Module
3
+ *
4
+ * Exports use cases for Settings entity operations.
5
+ */
6
+ export { InitializeSettingsUseCase } from './initialize-settings.use-case.js';
7
+ export { LoadSettingsUseCase } from './load-settings.use-case.js';
8
+ export { UpdateSettingsUseCase } from './update-settings.use-case.js';
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Initialize Settings Use Case
3
+ *
4
+ * Handles first-time settings initialization.
5
+ * Creates default settings if none exist, or returns existing settings.
6
+ *
7
+ * Business Rules:
8
+ * - Only one Settings record allowed (singleton pattern)
9
+ * - Uses factory defaults for initial values
10
+ * - Idempotent: safe to call multiple times
11
+ */
12
+ import type { Settings } from '../../../domain/generated/output.js';
13
+ import type { ISettingsRepository } from '../../ports/output/settings.repository.interface.js';
14
+ /**
15
+ * Use case for initializing global settings.
16
+ *
17
+ * Algorithm:
18
+ * 1. Check if settings already exist (load from repository)
19
+ * 2. If exists, return existing settings
20
+ * 3. If not exists, create defaults and initialize in repository
21
+ * 4. Return newly created settings
22
+ */
23
+ export declare class InitializeSettingsUseCase {
24
+ private readonly settingsRepository;
25
+ constructor(settingsRepository: ISettingsRepository);
26
+ /**
27
+ * Execute the initialize settings use case.
28
+ *
29
+ * @returns Existing or newly created Settings
30
+ */
31
+ execute(): Promise<Settings>;
32
+ }
33
+ //# sourceMappingURL=initialize-settings.use-case.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initialize-settings.use-case.d.ts","sourceRoot":"","sources":["../../../../../src/application/use-cases/settings/initialize-settings.use-case.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qDAAqD,CAAC;AAG/F;;;;;;;;GAQG;AACH,qBACa,yBAAyB;IAGlC,OAAO,CAAC,QAAQ,CAAC,kBAAkB;gBAAlB,kBAAkB,EAAE,mBAAmB;IAG1D;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC;CAgBnC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Initialize Settings Use Case
3
+ *
4
+ * Handles first-time settings initialization.
5
+ * Creates default settings if none exist, or returns existing settings.
6
+ *
7
+ * Business Rules:
8
+ * - Only one Settings record allowed (singleton pattern)
9
+ * - Uses factory defaults for initial values
10
+ * - Idempotent: safe to call multiple times
11
+ */
12
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
13
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
14
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
15
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
16
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
17
+ };
18
+ var __metadata = (this && this.__metadata) || function (k, v) {
19
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
20
+ };
21
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
22
+ return function (target, key) { decorator(target, key, paramIndex); }
23
+ };
24
+ import { injectable, inject } from 'tsyringe';
25
+ import { createDefaultSettings } from '../../../domain/factories/settings-defaults.factory.js';
26
+ /**
27
+ * Use case for initializing global settings.
28
+ *
29
+ * Algorithm:
30
+ * 1. Check if settings already exist (load from repository)
31
+ * 2. If exists, return existing settings
32
+ * 3. If not exists, create defaults and initialize in repository
33
+ * 4. Return newly created settings
34
+ */
35
+ let InitializeSettingsUseCase = class InitializeSettingsUseCase {
36
+ settingsRepository;
37
+ constructor(settingsRepository) {
38
+ this.settingsRepository = settingsRepository;
39
+ }
40
+ /**
41
+ * Execute the initialize settings use case.
42
+ *
43
+ * @returns Existing or newly created Settings
44
+ */
45
+ async execute() {
46
+ // Check if settings already exist
47
+ const existingSettings = await this.settingsRepository.load();
48
+ if (existingSettings) {
49
+ return existingSettings;
50
+ }
51
+ // Create new settings with defaults
52
+ const newSettings = createDefaultSettings();
53
+ // Persist to database
54
+ await this.settingsRepository.initialize(newSettings);
55
+ return newSettings;
56
+ }
57
+ };
58
+ InitializeSettingsUseCase = __decorate([
59
+ injectable(),
60
+ __param(0, inject('ISettingsRepository')),
61
+ __metadata("design:paramtypes", [Object])
62
+ ], InitializeSettingsUseCase);
63
+ export { InitializeSettingsUseCase };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Load Settings Use Case
3
+ *
4
+ * Retrieves existing settings from the database.
5
+ * Throws error if settings don't exist (must initialize first).
6
+ *
7
+ * Business Rules:
8
+ * - Settings must be initialized before loading
9
+ * - Returns complete Settings object
10
+ * - Read-only operation (no mutations)
11
+ */
12
+ import type { Settings } from '../../../domain/generated/output.js';
13
+ import type { ISettingsRepository } from '../../ports/output/settings.repository.interface.js';
14
+ /**
15
+ * Use case for loading existing settings.
16
+ *
17
+ * Algorithm:
18
+ * 1. Load settings from repository
19
+ * 2. If not found, throw error with helpful message
20
+ * 3. Return settings
21
+ */
22
+ export declare class LoadSettingsUseCase {
23
+ private readonly settingsRepository;
24
+ constructor(settingsRepository: ISettingsRepository);
25
+ /**
26
+ * Execute the load settings use case.
27
+ *
28
+ * @returns Existing Settings
29
+ * @throws Error if settings don't exist
30
+ */
31
+ execute(): Promise<Settings>;
32
+ }
33
+ //# sourceMappingURL=load-settings.use-case.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-settings.use-case.d.ts","sourceRoot":"","sources":["../../../../../src/application/use-cases/settings/load-settings.use-case.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qDAAqD,CAAC;AAE/F;;;;;;;GAOG;AACH,qBACa,mBAAmB;IAG5B,OAAO,CAAC,QAAQ,CAAC,kBAAkB;gBAAlB,kBAAkB,EAAE,mBAAmB;IAG1D;;;;;OAKG;IACG,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC;CASnC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Load Settings Use Case
3
+ *
4
+ * Retrieves existing settings from the database.
5
+ * Throws error if settings don't exist (must initialize first).
6
+ *
7
+ * Business Rules:
8
+ * - Settings must be initialized before loading
9
+ * - Returns complete Settings object
10
+ * - Read-only operation (no mutations)
11
+ */
12
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
13
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
14
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
15
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
16
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
17
+ };
18
+ var __metadata = (this && this.__metadata) || function (k, v) {
19
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
20
+ };
21
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
22
+ return function (target, key) { decorator(target, key, paramIndex); }
23
+ };
24
+ import { injectable, inject } from 'tsyringe';
25
+ /**
26
+ * Use case for loading existing settings.
27
+ *
28
+ * Algorithm:
29
+ * 1. Load settings from repository
30
+ * 2. If not found, throw error with helpful message
31
+ * 3. Return settings
32
+ */
33
+ let LoadSettingsUseCase = class LoadSettingsUseCase {
34
+ settingsRepository;
35
+ constructor(settingsRepository) {
36
+ this.settingsRepository = settingsRepository;
37
+ }
38
+ /**
39
+ * Execute the load settings use case.
40
+ *
41
+ * @returns Existing Settings
42
+ * @throws Error if settings don't exist
43
+ */
44
+ async execute() {
45
+ const settings = await this.settingsRepository.load();
46
+ if (!settings) {
47
+ throw new Error('Settings not found. Please run initialization first.');
48
+ }
49
+ return settings;
50
+ }
51
+ };
52
+ LoadSettingsUseCase = __decorate([
53
+ injectable(),
54
+ __param(0, inject('ISettingsRepository')),
55
+ __metadata("design:paramtypes", [Object])
56
+ ], LoadSettingsUseCase);
57
+ export { LoadSettingsUseCase };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Update Settings Use Case
3
+ *
4
+ * Updates existing settings in the database.
5
+ * Validates input and persists changes.
6
+ *
7
+ * Business Rules:
8
+ * - Settings must exist before updating
9
+ * - All fields are updatable
10
+ * - Returns updated settings after persistence
11
+ */
12
+ import type { Settings } from '../../../domain/generated/output.js';
13
+ import type { ISettingsRepository } from '../../ports/output/settings.repository.interface.js';
14
+ /**
15
+ * Use case for updating existing settings.
16
+ *
17
+ * Algorithm:
18
+ * 1. Receive updated settings
19
+ * 2. Persist to repository
20
+ * 3. Return updated settings
21
+ */
22
+ export declare class UpdateSettingsUseCase {
23
+ private readonly settingsRepository;
24
+ constructor(settingsRepository: ISettingsRepository);
25
+ /**
26
+ * Execute the update settings use case.
27
+ *
28
+ * @param settings - The updated settings to persist
29
+ * @returns The updated Settings
30
+ */
31
+ execute(settings: Settings): Promise<Settings>;
32
+ }
33
+ //# sourceMappingURL=update-settings.use-case.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-settings.use-case.d.ts","sourceRoot":"","sources":["../../../../../src/application/use-cases/settings/update-settings.use-case.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qDAAqD,CAAC;AAE/F;;;;;;;GAOG;AACH,qBACa,qBAAqB;IAG9B,OAAO,CAAC,QAAQ,CAAC,kBAAkB;gBAAlB,kBAAkB,EAAE,mBAAmB;IAG1D;;;;;OAKG;IACG,OAAO,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;CAOrD"}