@knowledgine/cli 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/dist/commands/capture.d.ts +23 -0
  2. package/dist/commands/capture.d.ts.map +1 -0
  3. package/dist/commands/capture.js +237 -0
  4. package/dist/commands/capture.js.map +1 -0
  5. package/dist/commands/demo.d.ts +6 -0
  6. package/dist/commands/demo.d.ts.map +1 -0
  7. package/dist/commands/demo.js +48 -0
  8. package/dist/commands/demo.js.map +1 -0
  9. package/dist/commands/feedback.d.ts +27 -0
  10. package/dist/commands/feedback.d.ts.map +1 -0
  11. package/dist/commands/feedback.js +120 -0
  12. package/dist/commands/feedback.js.map +1 -0
  13. package/dist/commands/ingest.d.ts +9 -0
  14. package/dist/commands/ingest.d.ts.map +1 -0
  15. package/dist/commands/ingest.js +162 -0
  16. package/dist/commands/ingest.js.map +1 -0
  17. package/dist/commands/init.d.ts +2 -0
  18. package/dist/commands/init.d.ts.map +1 -1
  19. package/dist/commands/init.js +327 -42
  20. package/dist/commands/init.js.map +1 -1
  21. package/dist/commands/plugins.d.ts +6 -0
  22. package/dist/commands/plugins.d.ts.map +1 -0
  23. package/dist/commands/plugins.js +41 -0
  24. package/dist/commands/plugins.js.map +1 -0
  25. package/dist/commands/search.d.ts +16 -0
  26. package/dist/commands/search.d.ts.map +1 -0
  27. package/dist/commands/search.js +140 -0
  28. package/dist/commands/search.js.map +1 -0
  29. package/dist/commands/setup.d.ts +57 -0
  30. package/dist/commands/setup.d.ts.map +1 -0
  31. package/dist/commands/setup.js +331 -0
  32. package/dist/commands/setup.js.map +1 -0
  33. package/dist/commands/start.d.ts +1 -0
  34. package/dist/commands/start.d.ts.map +1 -1
  35. package/dist/commands/start.js +98 -24
  36. package/dist/commands/start.js.map +1 -1
  37. package/dist/commands/status.d.ts +5 -0
  38. package/dist/commands/status.d.ts.map +1 -0
  39. package/dist/commands/status.js +149 -0
  40. package/dist/commands/status.js.map +1 -0
  41. package/dist/commands/tool.d.ts +29 -0
  42. package/dist/commands/tool.d.ts.map +1 -0
  43. package/dist/commands/tool.js +247 -0
  44. package/dist/commands/tool.js.map +1 -0
  45. package/dist/commands/upgrade.d.ts +6 -0
  46. package/dist/commands/upgrade.d.ts.map +1 -0
  47. package/dist/commands/upgrade.js +137 -0
  48. package/dist/commands/upgrade.js.map +1 -0
  49. package/dist/index.js +178 -2
  50. package/dist/index.js.map +1 -1
  51. package/dist/lib/demo-manager.d.ts +16 -0
  52. package/dist/lib/demo-manager.d.ts.map +1 -0
  53. package/dist/lib/demo-manager.js +37 -0
  54. package/dist/lib/demo-manager.js.map +1 -0
  55. package/dist/lib/entity-extractor.d.ts +15 -0
  56. package/dist/lib/entity-extractor.d.ts.map +1 -0
  57. package/dist/lib/entity-extractor.js +86 -0
  58. package/dist/lib/entity-extractor.js.map +1 -0
  59. package/dist/lib/formatter.d.ts +7 -0
  60. package/dist/lib/formatter.d.ts.map +1 -0
  61. package/dist/lib/formatter.js +94 -0
  62. package/dist/lib/formatter.js.map +1 -0
  63. package/dist/lib/indexer.d.ts +6 -1
  64. package/dist/lib/indexer.d.ts.map +1 -1
  65. package/dist/lib/indexer.js +4 -1
  66. package/dist/lib/indexer.js.map +1 -1
  67. package/dist/lib/ingest-watcher.d.ts +20 -0
  68. package/dist/lib/ingest-watcher.d.ts.map +1 -0
  69. package/dist/lib/ingest-watcher.js +45 -0
  70. package/dist/lib/ingest-watcher.js.map +1 -0
  71. package/dist/lib/plugin-loader.d.ts +5 -0
  72. package/dist/lib/plugin-loader.d.ts.map +1 -0
  73. package/dist/lib/plugin-loader.js +27 -0
  74. package/dist/lib/plugin-loader.js.map +1 -0
  75. package/dist/lib/progress.d.ts +63 -0
  76. package/dist/lib/progress.d.ts.map +1 -0
  77. package/dist/lib/progress.js +228 -0
  78. package/dist/lib/progress.js.map +1 -0
  79. package/dist/lib/ui/box.d.ts +7 -0
  80. package/dist/lib/ui/box.d.ts.map +1 -0
  81. package/dist/lib/ui/box.js +19 -0
  82. package/dist/lib/ui/box.js.map +1 -0
  83. package/dist/lib/ui/error-formatter.d.ts +8 -0
  84. package/dist/lib/ui/error-formatter.d.ts.map +1 -0
  85. package/dist/lib/ui/error-formatter.js +21 -0
  86. package/dist/lib/ui/error-formatter.js.map +1 -0
  87. package/dist/lib/ui/index.d.ts +7 -0
  88. package/dist/lib/ui/index.d.ts.map +1 -0
  89. package/dist/lib/ui/index.js +7 -0
  90. package/dist/lib/ui/index.js.map +1 -0
  91. package/dist/lib/ui/output.d.ts +2 -0
  92. package/dist/lib/ui/output.d.ts.map +1 -0
  93. package/dist/lib/ui/output.js +4 -0
  94. package/dist/lib/ui/output.js.map +1 -0
  95. package/dist/lib/ui/spinner.d.ts +4 -0
  96. package/dist/lib/ui/spinner.d.ts.map +1 -0
  97. package/dist/lib/ui/spinner.js +5 -0
  98. package/dist/lib/ui/spinner.js.map +1 -0
  99. package/dist/lib/ui/table.d.ts +9 -0
  100. package/dist/lib/ui/table.d.ts.map +1 -0
  101. package/dist/lib/ui/table.js +28 -0
  102. package/dist/lib/ui/table.js.map +1 -0
  103. package/dist/lib/ui/theme.d.ts +21 -0
  104. package/dist/lib/ui/theme.d.ts.map +1 -0
  105. package/dist/lib/ui/theme.js +29 -0
  106. package/dist/lib/ui/theme.js.map +1 -0
  107. package/dist/lib/unknown-command-handler.d.ts +14 -0
  108. package/dist/lib/unknown-command-handler.d.ts.map +1 -0
  109. package/dist/lib/unknown-command-handler.js +25 -0
  110. package/dist/lib/unknown-command-handler.js.map +1 -0
  111. package/dist/lib/url-validator.d.ts +2 -0
  112. package/dist/lib/url-validator.d.ts.map +1 -0
  113. package/dist/lib/url-validator.js +21 -0
  114. package/dist/lib/url-validator.js.map +1 -0
  115. package/fixtures/demo/notes/api-design-decisions.md +84 -0
  116. package/fixtures/demo/notes/auth-debugging.md +60 -0
  117. package/fixtures/demo/notes/ci-cd-pipeline.md +97 -0
  118. package/fixtures/demo/notes/code-review-notes.md +78 -0
  119. package/fixtures/demo/notes/database-optimization.md +81 -0
  120. package/fixtures/demo/notes/docker-troubleshooting.md +80 -0
  121. package/fixtures/demo/notes/react-performance.md +67 -0
  122. package/fixtures/demo/notes/typescript-migration.md +89 -0
  123. package/package.json +13 -4
@@ -0,0 +1,84 @@
1
+ ---
2
+ tags:
3
+ - api
4
+ - rest
5
+ - design
6
+ author: demo-user
7
+ project: backend-api
8
+ ---
9
+
10
+ # REST API Design Decisions
11
+
12
+ ## Issue: Pagination Strategy
13
+
14
+ Needed to decide between offset-based and cursor-based pagination
15
+ for the search results endpoint.
16
+
17
+ ### Decision: Cursor-based pagination
18
+
19
+ Offset pagination breaks when items are inserted/deleted during browsing.
20
+
21
+ ```typescript
22
+ // Cursor-based pagination
23
+ interface PaginatedResponse<T> {
24
+ data: T[];
25
+ cursor: string | null; // null means no more pages
26
+ hasMore: boolean;
27
+ }
28
+
29
+ app.get("/api/notes", (req, res) => {
30
+ const { cursor, limit = 20 } = req.query;
31
+ const decoded = cursor ? decodeCursor(cursor) : null;
32
+
33
+ const notes = db.query(
34
+ `SELECT * FROM notes
35
+ WHERE ($1::text IS NULL OR id < $1)
36
+ ORDER BY id DESC LIMIT $2`,
37
+ [decoded?.id, limit + 1],
38
+ );
39
+
40
+ const hasMore = notes.length > limit;
41
+ const data = notes.slice(0, limit);
42
+
43
+ res.json({
44
+ data,
45
+ cursor: hasMore ? encodeCursor(data.at(-1)) : null,
46
+ hasMore,
47
+ });
48
+ });
49
+ ```
50
+
51
+ ## Issue: Error Response Format
52
+
53
+ Standardized error responses across all endpoints.
54
+
55
+ ### Solution: RFC 7807 Problem Details
56
+
57
+ ```typescript
58
+ interface ProblemDetail {
59
+ type: string;
60
+ title: string;
61
+ status: number;
62
+ detail: string;
63
+ instance?: string;
64
+ }
65
+
66
+ // Error handler middleware
67
+ app.use((err, req, res, _next) => {
68
+ const problem: ProblemDetail = {
69
+ type: `https://api.example.com/errors/${err.code}`,
70
+ title: err.title || "Internal Server Error",
71
+ status: err.status || 500,
72
+ detail: err.message,
73
+ instance: req.originalUrl,
74
+ };
75
+ res.status(problem.status).json(problem);
76
+ });
77
+ ```
78
+
79
+ ## Learnings
80
+
81
+ - Cursor-based pagination is more reliable for real-time data
82
+ - Consistent error formats reduce client-side error handling complexity
83
+ - Always version your API from the start (`/v1/`)
84
+ - Document decisions in ADRs for future team members
@@ -0,0 +1,60 @@
1
+ ---
2
+ tags:
3
+ - authentication
4
+ - jwt
5
+ - debugging
6
+ author: demo-user
7
+ project: backend-api
8
+ ---
9
+
10
+ # Authentication Debugging Session
11
+
12
+ ## Problem
13
+
14
+ JWT token validation was failing intermittently in production.
15
+ Users reported being logged out randomly after 10-15 minutes,
16
+ even though the token expiry was set to 1 hour.
17
+
18
+ ### Error Log
19
+
20
+ ```
21
+ Error: TokenExpiredError: jwt expired
22
+ at /app/middleware/auth.ts:42:11
23
+ at processTicksAndRejections (node:internal/process/task_queues:95:5)
24
+ ```
25
+
26
+ ## Investigation
27
+
28
+ - Checked server clock sync — NTP was configured correctly
29
+ - Compared token `iat` (issued at) timestamps with server time
30
+ - Found a 45-minute clock skew between API server and auth service
31
+
32
+ ## Solution
33
+
34
+ The auth service was running in a container with a drifted system clock.
35
+
36
+ ```typescript
37
+ // Added clock tolerance to JWT verification
38
+ const decoded = jwt.verify(token, SECRET, {
39
+ clockTolerance: 60, // allow 60 seconds of clock skew
40
+ });
41
+ ```
42
+
43
+ Also fixed the root cause by enabling NTP sync in the Docker container:
44
+
45
+ ```dockerfile
46
+ RUN apt-get update && apt-get install -y ntpdate
47
+ CMD ntpdate -s pool.ntp.org && node server.js
48
+ ```
49
+
50
+ ## Learnings
51
+
52
+ - Always configure clock tolerance for distributed JWT validation
53
+ - Container clocks can drift if the host NTP is not propagated
54
+ - Add monitoring for clock skew between services
55
+ - The `clockTolerance` option is safer than extending token expiry
56
+
57
+ ## Time Spent
58
+
59
+ Investigation: 2 hours
60
+ Fix + deployment: 30 minutes
@@ -0,0 +1,97 @@
1
+ ---
2
+ tags:
3
+ - ci-cd
4
+ - github-actions
5
+ - testing
6
+ author: demo-user
7
+ project: infrastructure
8
+ ---
9
+
10
+ # CI/CD Pipeline Setup and Debugging
11
+
12
+ ## Problem
13
+
14
+ The CI pipeline was taking 25 minutes per push, blocking the
15
+ development workflow. Flaky tests caused unnecessary re-runs.
16
+
17
+ ## Investigation
18
+
19
+ Analyzed GitHub Actions run logs:
20
+
21
+ - Dependency install: 4 minutes (no caching)
22
+ - Build: 3 minutes
23
+ - Tests: 15 minutes (sequential, with 3 flaky tests)
24
+ - Deploy: 3 minutes
25
+
26
+ ## Solution: Optimized Pipeline
27
+
28
+ ```yaml
29
+ # .github/workflows/ci.yml
30
+ name: CI
31
+ on: [push, pull_request]
32
+
33
+ jobs:
34
+ build-and-test:
35
+ runs-on: ubuntu-latest
36
+ steps:
37
+ - uses: actions/checkout@v4
38
+
39
+ - uses: pnpm/action-setup@v4
40
+ with:
41
+ version: 9
42
+
43
+ - uses: actions/setup-node@v4
44
+ with:
45
+ node-version: 20
46
+ cache: "pnpm"
47
+
48
+ - run: pnpm install --frozen-lockfile
49
+
50
+ - run: pnpm build
51
+
52
+ - run: pnpm test:run --reporter=verbose
53
+ env:
54
+ CI: true
55
+
56
+ lint:
57
+ runs-on: ubuntu-latest
58
+ steps:
59
+ - uses: actions/checkout@v4
60
+ - uses: pnpm/action-setup@v4
61
+ - run: pnpm install --frozen-lockfile
62
+ - run: pnpm lint
63
+ ```
64
+
65
+ ### Flaky Test Fix
66
+
67
+ ```typescript
68
+ // Before: timing-dependent test
69
+ it("should debounce input", async () => {
70
+ fireEvent.change(input, { target: { value: "test" } });
71
+ await new Promise((r) => setTimeout(r, 300));
72
+ expect(onSearch).toHaveBeenCalledTimes(1);
73
+ });
74
+
75
+ // After: deterministic with fake timers
76
+ it("should debounce input", () => {
77
+ vi.useFakeTimers();
78
+ fireEvent.change(input, { target: { value: "test" } });
79
+ vi.advanceTimersByTime(300);
80
+ expect(onSearch).toHaveBeenCalledTimes(1);
81
+ vi.useRealTimers();
82
+ });
83
+ ```
84
+
85
+ ## Results
86
+
87
+ - Pipeline time: 25 min → 8 min (68% reduction)
88
+ - Flaky test rate: 15% → 0%
89
+ - Developer satisfaction significantly improved
90
+
91
+ ## Learnings
92
+
93
+ - Cache dependencies aggressively in CI
94
+ - Run lint and tests in parallel jobs
95
+ - Flaky tests erode trust — fix them immediately
96
+ - Use `--frozen-lockfile` to catch dependency drift
97
+ - Fake timers eliminate timing-based flakiness
@@ -0,0 +1,78 @@
1
+ ---
2
+ tags:
3
+ - code-review
4
+ - best-practices
5
+ - team
6
+ author: demo-user
7
+ project: team-process
8
+ ---
9
+
10
+ # Code Review Guidelines and Common Issues
11
+
12
+ ## Problem
13
+
14
+ Code reviews were inconsistent. Some PRs got rubber-stamped while
15
+ others received 50+ nitpick comments. Reviews took 2-3 days on average.
16
+
17
+ ## Solution: Review Checklist
18
+
19
+ ### What to Check
20
+
21
+ 1. **Correctness**: Does the code do what the PR description says?
22
+ 2. **Edge cases**: Null handling, empty arrays, boundary conditions
23
+ 3. **Security**: Input validation, SQL injection, XSS
24
+ 4. **Tests**: Are new behaviors covered? Are edge cases tested?
25
+ 5. **Naming**: Do variable/function names convey intent?
26
+
27
+ ### Common Issues Found in Reviews
28
+
29
+ #### Error handling gaps
30
+
31
+ ```typescript
32
+ // Bad: swallows errors silently
33
+ try {
34
+ await saveUser(data);
35
+ } catch {
36
+ // ignore
37
+ }
38
+
39
+ // Good: handle or propagate with context
40
+ try {
41
+ await saveUser(data);
42
+ } catch (error) {
43
+ logger.error("Failed to save user", { userId: data.id, error });
44
+ throw new ServiceError("User save failed", { cause: error });
45
+ }
46
+ ```
47
+
48
+ #### Missing input validation
49
+
50
+ ```typescript
51
+ // Bad: trusts external input
52
+ app.post("/api/users", (req, res) => {
53
+ db.query("INSERT INTO users (name) VALUES ($1)", [req.body.name]);
54
+ });
55
+
56
+ // Good: validate before processing
57
+ app.post("/api/users", (req, res) => {
58
+ const { name } = req.body;
59
+ if (!name || typeof name !== "string" || name.length > 255) {
60
+ return res.status(400).json({ error: "Invalid name" });
61
+ }
62
+ db.query("INSERT INTO users (name) VALUES ($1)", [name]);
63
+ });
64
+ ```
65
+
66
+ ## Process Improvements
67
+
68
+ - Max review turnaround: 4 hours for small PRs, 1 day for large
69
+ - Use "Request changes" only for blocking issues
70
+ - Prefix comments: `nit:`, `question:`, `suggestion:`, `blocking:`
71
+ - Author should self-review before requesting review
72
+
73
+ ## Learnings
74
+
75
+ - Checklists reduce review inconsistency
76
+ - Small PRs (< 300 lines) get better reviews and faster merges
77
+ - Automate what you can (linting, formatting, type checking)
78
+ - Focus reviews on logic and design, not style
@@ -0,0 +1,81 @@
1
+ ---
2
+ tags:
3
+ - database
4
+ - sql
5
+ - performance
6
+ author: demo-user
7
+ project: backend-api
8
+ ---
9
+
10
+ # SQL Query Optimization and Indexing
11
+
12
+ ## Problem
13
+
14
+ The notes search endpoint was timing out with 100k+ rows.
15
+ Average query time was 4.2 seconds, causing user-visible latency.
16
+
17
+ ### Slow Query
18
+
19
+ ```sql
20
+ SELECT n.*, COUNT(p.id) as pattern_count
21
+ FROM notes n
22
+ LEFT JOIN patterns p ON p.note_id = n.id
23
+ WHERE n.content LIKE '%typescript%'
24
+ AND n.created_at > '2024-01-01'
25
+ GROUP BY n.id
26
+ ORDER BY n.created_at DESC
27
+ LIMIT 20;
28
+ ```
29
+
30
+ ## Investigation
31
+
32
+ Used `EXPLAIN ANALYZE` to identify bottlenecks:
33
+
34
+ ```sql
35
+ EXPLAIN ANALYZE SELECT ...;
36
+ -- Seq Scan on notes (cost=0.00..12847.00 rows=100234 width=412)
37
+ -- Filter: (content ~~ '%typescript%')
38
+ -- Rows Removed by Filter: 95102
39
+ ```
40
+
41
+ The sequential scan was reading every row.
42
+
43
+ ## Solution: Indexing Strategy
44
+
45
+ ```sql
46
+ -- 1. B-tree index for date range queries
47
+ CREATE INDEX idx_notes_created_at ON notes (created_at DESC);
48
+
49
+ -- 2. Full-text search index instead of LIKE
50
+ CREATE INDEX idx_notes_content_fts ON notes
51
+ USING GIN (to_tsvector('english', content));
52
+
53
+ -- 3. Covering index for the common query pattern
54
+ CREATE INDEX idx_patterns_note_id ON patterns (note_id);
55
+ ```
56
+
57
+ ### Rewritten Query
58
+
59
+ ```sql
60
+ SELECT n.*, COUNT(p.id) as pattern_count
61
+ FROM notes n
62
+ LEFT JOIN patterns p ON p.note_id = n.id
63
+ WHERE to_tsvector('english', n.content) @@ plainto_tsquery('typescript')
64
+ AND n.created_at > '2024-01-01'
65
+ GROUP BY n.id
66
+ ORDER BY n.created_at DESC
67
+ LIMIT 20;
68
+ ```
69
+
70
+ ## Results
71
+
72
+ - Query time: 4.2s → 18ms (233x improvement)
73
+ - Index storage overhead: ~45MB (acceptable for 100k rows)
74
+
75
+ ## Learnings
76
+
77
+ - `LIKE '%term%'` cannot use indexes — always use full-text search
78
+ - `EXPLAIN ANALYZE` is the first tool to reach for
79
+ - Covering indexes avoid table lookups for frequently joined columns
80
+ - Monitor index bloat in write-heavy tables
81
+ - Partial indexes can save space when queries filter on a condition
@@ -0,0 +1,80 @@
1
+ ---
2
+ tags:
3
+ - docker
4
+ - networking
5
+ - devops
6
+ author: demo-user
7
+ project: microservices
8
+ ---
9
+
10
+ # Docker Container Networking Issues
11
+
12
+ ## Problem
13
+
14
+ Containers in docker-compose could not communicate with each other.
15
+ The API service failed to connect to the database container.
16
+
17
+ ```
18
+ Error: connect ECONNREFUSED 127.0.0.1:5432
19
+ ```
20
+
21
+ ## Investigation
22
+
23
+ - Verified both containers were running: `docker ps` showed healthy status
24
+ - Checked network: `docker network ls` showed custom bridge network
25
+ - The API was using `localhost` instead of the service name
26
+
27
+ ## Solution
28
+
29
+ Docker containers have their own network namespace. Use the service
30
+ name as the hostname, not `localhost`.
31
+
32
+ ```yaml
33
+ # docker-compose.yml
34
+ services:
35
+ api:
36
+ build: ./api
37
+ environment:
38
+ # Wrong: DB_HOST=localhost
39
+ DB_HOST: postgres # Use service name
40
+ DB_PORT: 5432
41
+ depends_on:
42
+ postgres:
43
+ condition: service_healthy
44
+
45
+ postgres:
46
+ image: postgres:16
47
+ healthcheck:
48
+ test: ["CMD-SHELL", "pg_isready -U app"]
49
+ interval: 5s
50
+ timeout: 3s
51
+ retries: 5
52
+ ```
53
+
54
+ ## Additional Fix: DNS Resolution Timing
55
+
56
+ Even with correct hostnames, the API started before DNS was ready.
57
+
58
+ ```typescript
59
+ // Added retry logic for database connection
60
+ async function connectWithRetry(maxRetries = 5): Promise<Pool> {
61
+ for (let i = 0; i < maxRetries; i++) {
62
+ try {
63
+ const pool = new Pool({ host: process.env.DB_HOST });
64
+ await pool.query("SELECT 1");
65
+ return pool;
66
+ } catch (err) {
67
+ console.log(`DB connection attempt ${i + 1} failed, retrying...`);
68
+ await new Promise((r) => setTimeout(r, 2000));
69
+ }
70
+ }
71
+ throw new Error("Could not connect to database");
72
+ }
73
+ ```
74
+
75
+ ## Learnings
76
+
77
+ - Never use `localhost` for inter-container communication
78
+ - Use `depends_on` with health checks, not just service ordering
79
+ - Add connection retry logic for resilience
80
+ - `docker network inspect` is useful for debugging DNS issues
@@ -0,0 +1,67 @@
1
+ ---
2
+ tags:
3
+ - react
4
+ - performance
5
+ - frontend
6
+ author: demo-user
7
+ project: dashboard-app
8
+ ---
9
+
10
+ # React Performance Optimization
11
+
12
+ ## Issue
13
+
14
+ The dashboard page was taking 3+ seconds to render with 500 items.
15
+ React DevTools Profiler showed excessive re-renders on every state change.
16
+
17
+ ## Root Cause Analysis
18
+
19
+ 1. Parent component state changes triggered full list re-render
20
+ 2. Inline arrow functions in JSX created new references each render
21
+ 3. Large bundle size from importing entire icon library
22
+
23
+ ## Fix: Memoization
24
+
25
+ ```tsx
26
+ // Before: re-renders on every parent state change
27
+ const ListItem = ({ item, onClick }) => <div onClick={() => onClick(item.id)}>{item.name}</div>;
28
+
29
+ // After: memoized with stable callback
30
+ const ListItem = React.memo(({ item, onClick }) => <div onClick={onClick}>{item.name}</div>);
31
+
32
+ // Parent: stable callback reference
33
+ const handleClick = useCallback((id: string) => {
34
+ setSelectedId(id);
35
+ }, []);
36
+ ```
37
+
38
+ ## Fix: Code Splitting
39
+
40
+ ```tsx
41
+ // Before: eager import
42
+ import { AnalyticsChart } from "./AnalyticsChart";
43
+
44
+ // After: lazy loaded
45
+ const AnalyticsChart = React.lazy(() => import("./AnalyticsChart"));
46
+
47
+ function Dashboard() {
48
+ return (
49
+ <Suspense fallback={<Skeleton />}>
50
+ <AnalyticsChart data={data} />
51
+ </Suspense>
52
+ );
53
+ }
54
+ ```
55
+
56
+ ## Results
57
+
58
+ - Initial render: 3.2s → 0.8s (75% improvement)
59
+ - Re-render on selection: 450ms → 12ms
60
+ - Bundle size: 1.2MB → 680KB
61
+
62
+ ## Learnings
63
+
64
+ - Profile before optimizing — measure actual bottlenecks
65
+ - React.memo only helps when props are actually stable
66
+ - Lazy loading is most effective for below-the-fold content
67
+ - Tree-shaking icon libraries saves significant bundle size
@@ -0,0 +1,89 @@
1
+ ---
2
+ tags:
3
+ - typescript
4
+ - migration
5
+ - refactoring
6
+ author: demo-user
7
+ project: legacy-app
8
+ ---
9
+
10
+ # JavaScript to TypeScript Migration
11
+
12
+ ## Problem
13
+
14
+ The legacy Express app (50+ files) had no type safety. Runtime errors
15
+ were discovered only in production, and onboarding new developers
16
+ took weeks due to lack of type documentation.
17
+
18
+ ## Migration Strategy
19
+
20
+ Adopted an incremental approach instead of a big-bang rewrite.
21
+
22
+ ### Phase 1: Setup (Day 1)
23
+
24
+ ```jsonc
25
+ // tsconfig.json - permissive start
26
+ {
27
+ "compilerOptions": {
28
+ "allowJs": true,
29
+ "checkJs": false,
30
+ "strict": false,
31
+ "outDir": "dist",
32
+ "rootDir": "src",
33
+ },
34
+ "include": ["src/**/*"],
35
+ }
36
+ ```
37
+
38
+ ### Phase 2: Rename files (Week 1)
39
+
40
+ ```bash
41
+ # Renamed .js → .ts one directory at a time
42
+ # Started with utility files that had no dependencies
43
+ find src/utils -name "*.js" -exec bash -c 'mv "$0" "${0%.js}.ts"' {} \;
44
+ ```
45
+
46
+ ### Phase 3: Add types gradually (Week 2-4)
47
+
48
+ ```typescript
49
+ // Before: implicit any everywhere
50
+ function processUser(user) {
51
+ return { name: user.name, role: user.role || "viewer" };
52
+ }
53
+
54
+ // After: explicit types
55
+ interface User {
56
+ id: string;
57
+ name: string;
58
+ role?: "admin" | "editor" | "viewer";
59
+ }
60
+
61
+ function processUser(user: User): { name: string; role: string } {
62
+ return { name: user.name, role: user.role ?? "viewer" };
63
+ }
64
+ ```
65
+
66
+ ### Phase 4: Enable strict mode (Week 5)
67
+
68
+ ```jsonc
69
+ {
70
+ "compilerOptions": {
71
+ "strict": true,
72
+ "noUncheckedIndexedAccess": true,
73
+ },
74
+ }
75
+ ```
76
+
77
+ ## Results
78
+
79
+ - Runtime type errors: 12/month → 0/month
80
+ - Onboarding time: 3 weeks → 1 week
81
+ - Refactoring confidence: significantly improved with IDE support
82
+
83
+ ## Learnings
84
+
85
+ - Incremental migration is key — never stop shipping features
86
+ - Start with leaf files (utilities), move inward to core logic
87
+ - `@ts-expect-error` is better than `any` for tracking tech debt
88
+ - Enable `strict` as soon as possible to avoid accumulating debt
89
+ - The build time increase was negligible (< 2 seconds)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knowledgine/cli",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -14,13 +14,22 @@
14
14
  }
15
15
  },
16
16
  "dependencies": {
17
+ "@clack/prompts": "^1.1.0",
18
+ "boxen": "^8.0.1",
19
+ "chalk": "^5.6.2",
17
20
  "chokidar": "^5.0.0",
21
+ "cli-table3": "^0.6.5",
18
22
  "commander": "^14.0.3",
19
- "@knowledgine/core": "0.1.0",
20
- "@knowledgine/mcp-server": "0.1.0"
23
+ "log-symbols": "^7.0.1",
24
+ "ora": "^9.3.0",
25
+ "smol-toml": "^1.6.0",
26
+ "@knowledgine/core": "0.2.1",
27
+ "@knowledgine/ingest": "0.2.1",
28
+ "@knowledgine/mcp-server": "0.2.1"
21
29
  },
22
30
  "files": [
23
- "dist"
31
+ "dist",
32
+ "fixtures"
24
33
  ],
25
34
  "description": "CLI for indexing markdown files and serving MCP knowledge tools",
26
35
  "mcpName": "io.github.3062-in-zamud/knowledgine",