mycontext-cli 2.0.28 → 2.0.30

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 (69) hide show
  1. package/README.md +106 -14
  2. package/dist/cli.js +89 -99
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/generate-components.d.ts +10 -0
  5. package/dist/commands/generate-components.d.ts.map +1 -1
  6. package/dist/commands/generate-components.js +300 -3
  7. package/dist/commands/generate-components.js.map +1 -1
  8. package/dist/commands/generate-context-files.d.ts +9 -0
  9. package/dist/commands/generate-context-files.d.ts.map +1 -1
  10. package/dist/commands/generate-context-files.js +57 -0
  11. package/dist/commands/generate-context-files.js.map +1 -1
  12. package/dist/commands/generate.d.ts +5 -0
  13. package/dist/commands/generate.d.ts.map +1 -1
  14. package/dist/commands/generate.js +75 -1
  15. package/dist/commands/generate.js.map +1 -1
  16. package/dist/commands/init.d.ts +9 -0
  17. package/dist/commands/init.d.ts.map +1 -1
  18. package/dist/commands/init.js +223 -68
  19. package/dist/commands/init.js.map +1 -1
  20. package/dist/commands/preview-components.d.ts +12 -0
  21. package/dist/commands/preview-components.d.ts.map +1 -0
  22. package/dist/commands/preview-components.js +122 -0
  23. package/dist/commands/preview-components.js.map +1 -0
  24. package/dist/commands/refine-component.d.ts +43 -0
  25. package/dist/commands/refine-component.d.ts.map +1 -0
  26. package/dist/commands/refine-component.js +313 -0
  27. package/dist/commands/refine-component.js.map +1 -0
  28. package/dist/commands/review-context.d.ts +47 -0
  29. package/dist/commands/review-context.d.ts.map +1 -0
  30. package/dist/commands/review-context.js +335 -0
  31. package/dist/commands/review-context.js.map +1 -0
  32. package/dist/package.json +11 -2
  33. package/dist/services/ContextValidator.d.ts +99 -0
  34. package/dist/services/ContextValidator.d.ts.map +1 -0
  35. package/dist/services/ContextValidator.js +433 -0
  36. package/dist/services/ContextValidator.js.map +1 -0
  37. package/dist/services/MutationLogger.d.ts +54 -0
  38. package/dist/services/MutationLogger.d.ts.map +1 -0
  39. package/dist/services/MutationLogger.js +164 -0
  40. package/dist/services/MutationLogger.js.map +1 -0
  41. package/dist/services/RegressionRunner.d.ts +49 -0
  42. package/dist/services/RegressionRunner.d.ts.map +1 -0
  43. package/dist/services/RegressionRunner.js +285 -0
  44. package/dist/services/RegressionRunner.js.map +1 -0
  45. package/dist/services/TriggerLogger.d.ts +101 -0
  46. package/dist/services/TriggerLogger.d.ts.map +1 -0
  47. package/dist/services/TriggerLogger.js +263 -0
  48. package/dist/services/TriggerLogger.js.map +1 -0
  49. package/dist/templates/instantdb/db.template.ts +14 -0
  50. package/dist/templates/instantdb/home-client.template.tsx +127 -0
  51. package/dist/templates/instantdb/page.template.tsx +5 -0
  52. package/dist/templates/instantdb/perms.template.ts +9 -0
  53. package/dist/templates/instantdb/schema.template.ts +28 -0
  54. package/dist/templates/playbooks/instantdb-integration.md +851 -0
  55. package/dist/templates/playbooks/mpesa-integration.md +652 -0
  56. package/dist/templates/pm-integration-config.json +20 -0
  57. package/dist/templates/ui-spec-examples.md +318 -0
  58. package/dist/templates/ui-spec-templates.json +244 -0
  59. package/dist/utils/envExampleGenerator.d.ts.map +1 -1
  60. package/dist/utils/envExampleGenerator.js +9 -3
  61. package/dist/utils/envExampleGenerator.js.map +1 -1
  62. package/dist/utils/hybridAIClient.d.ts.map +1 -1
  63. package/dist/utils/hybridAIClient.js +21 -0
  64. package/dist/utils/hybridAIClient.js.map +1 -1
  65. package/dist/utils/openRouterClient.d.ts +10 -0
  66. package/dist/utils/openRouterClient.d.ts.map +1 -0
  67. package/dist/utils/openRouterClient.js +61 -0
  68. package/dist/utils/openRouterClient.js.map +1 -0
  69. package/package.json +11 -2
@@ -0,0 +1,263 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TriggerLogger = void 0;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ class TriggerLogger {
9
+ constructor() {
10
+ this.logPath = ".mycontext/trigger-log.json";
11
+ }
12
+ /**
13
+ * Log a trigger event
14
+ */
15
+ async logTrigger(type, description, affectedComponents, userAction, metadata) {
16
+ const event = {
17
+ id: this.generateEventId(),
18
+ type,
19
+ timestamp: new Date().toISOString(),
20
+ description,
21
+ affectedComponents,
22
+ userAction,
23
+ metadata,
24
+ };
25
+ const log = await this.loadLog();
26
+ log.events.push(event);
27
+ log.lastUpdated = new Date().toISOString();
28
+ await this.saveLog(log);
29
+ }
30
+ /**
31
+ * Log context file changes
32
+ */
33
+ async logContextChange(changedFiles, userAction = "Context files updated") {
34
+ const affectedComponents = await this.getAffectedComponentsFromContext(changedFiles);
35
+ await this.logTrigger("context-change", `Context files changed: ${changedFiles.join(", ")}`, affectedComponents, userAction, { changedFiles });
36
+ }
37
+ /**
38
+ * Log schema changes
39
+ */
40
+ async logSchemaChange(userAction = "Schema updated") {
41
+ const affectedComponents = await this.getAffectedComponentsFromSchema();
42
+ await this.logTrigger("schema-change", "InstantDB schema modified", affectedComponents, userAction, { schemaChanged: true });
43
+ }
44
+ /**
45
+ * Log component refinement
46
+ */
47
+ async logComponentRefinement(componentName, refinementType, userAction = "Component refined") {
48
+ await this.logTrigger("component-refinement", `Component ${componentName} refined via ${refinementType}`, [componentName], userAction, { refinementType, componentName });
49
+ }
50
+ /**
51
+ * Log approval changes
52
+ */
53
+ async logApprovalChange(featureId, oldApproval, newApproval, userAction = "Feature approval changed") {
54
+ const affectedComponents = await this.getAffectedComponentsFromFeature(featureId);
55
+ await this.logTrigger("approval-change", `Feature ${featureId} approval changed from ${oldApproval} to ${newApproval}`, affectedComponents, userAction, { featureId, oldApproval, newApproval });
56
+ }
57
+ /**
58
+ * Get recent trigger events
59
+ */
60
+ async getRecentEvents(limit = 10) {
61
+ const log = await this.loadLog();
62
+ return log.events
63
+ .sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())
64
+ .slice(0, limit);
65
+ }
66
+ /**
67
+ * Get events by type
68
+ */
69
+ async getEventsByType(type) {
70
+ const log = await this.loadLog();
71
+ return log.events.filter((event) => event.type === type);
72
+ }
73
+ /**
74
+ * Get events affecting a specific component
75
+ */
76
+ async getEventsForComponent(componentName) {
77
+ const log = await this.loadLog();
78
+ return log.events.filter((event) => event.affectedComponents.includes(componentName));
79
+ }
80
+ /**
81
+ * Check if component needs regeneration based on triggers
82
+ */
83
+ async needsRegeneration(componentName) {
84
+ const events = await this.getEventsForComponent(componentName);
85
+ // Check if there are any recent trigger events
86
+ const recentEvents = events.filter((event) => {
87
+ const eventTime = new Date(event.timestamp).getTime();
88
+ const oneHourAgo = Date.now() - 60 * 60 * 1000;
89
+ return eventTime > oneHourAgo;
90
+ });
91
+ return recentEvents.length > 0;
92
+ }
93
+ /**
94
+ * Get regeneration recommendations
95
+ */
96
+ async getRegenerationRecommendations() {
97
+ const recentEvents = await this.getRecentEvents(5);
98
+ const shouldRegenerate = [];
99
+ let reason = "";
100
+ for (const event of recentEvents) {
101
+ if (event.type === "context-change" || event.type === "schema-change") {
102
+ shouldRegenerate.push(...event.affectedComponents);
103
+ reason = `Recent ${event.type} detected`;
104
+ }
105
+ }
106
+ return {
107
+ shouldRegenerate: [...new Set(shouldRegenerate)], // Remove duplicates
108
+ reason,
109
+ };
110
+ }
111
+ /**
112
+ * Clear old events (keep last 50)
113
+ */
114
+ async cleanupOldEvents() {
115
+ const log = await this.loadLog();
116
+ log.events = log.events
117
+ .sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())
118
+ .slice(0, 50);
119
+ await this.saveLog(log);
120
+ }
121
+ /**
122
+ * Load trigger log from file
123
+ */
124
+ async loadLog() {
125
+ try {
126
+ const fs = require("fs-extra");
127
+ if (await fs.pathExists(this.logPath)) {
128
+ const content = await fs.readFile(this.logPath, "utf8");
129
+ return JSON.parse(content);
130
+ }
131
+ }
132
+ catch (error) {
133
+ // If file doesn't exist or is corrupted, return empty log
134
+ }
135
+ return {
136
+ events: [],
137
+ lastUpdated: new Date().toISOString(),
138
+ version: "1.0",
139
+ };
140
+ }
141
+ /**
142
+ * Save trigger log to file
143
+ */
144
+ async saveLog(log) {
145
+ const fs = require("fs-extra");
146
+ await fs.ensureDir(".mycontext");
147
+ await fs.writeFile(this.logPath, JSON.stringify(log, null, 2));
148
+ }
149
+ /**
150
+ * Generate unique event ID
151
+ */
152
+ generateEventId() {
153
+ return `event_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
154
+ }
155
+ /**
156
+ * Get affected components from context file changes
157
+ */
158
+ async getAffectedComponentsFromContext(changedFiles) {
159
+ // This would analyze which components are affected by context changes
160
+ // For now, return all components if PRD or features files changed
161
+ const criticalFiles = [
162
+ "01a-features.md",
163
+ "01b-user-flows.md",
164
+ "01c-edge-cases.md",
165
+ ];
166
+ const hasCriticalChange = changedFiles.some((file) => criticalFiles.some((critical) => file.includes(critical)));
167
+ if (hasCriticalChange) {
168
+ // Return all components - this is a conservative approach
169
+ return await this.getAllComponentNames();
170
+ }
171
+ return [];
172
+ }
173
+ /**
174
+ * Get affected components from schema changes
175
+ */
176
+ async getAffectedComponentsFromSchema() {
177
+ // Schema changes typically affect all components that use data
178
+ return await this.getAllComponentNames();
179
+ }
180
+ /**
181
+ * Get affected components from feature approval changes
182
+ */
183
+ async getAffectedComponentsFromFeature(featureId) {
184
+ // Map feature ID to component name
185
+ return [
186
+ featureId.replace(/-/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
187
+ ];
188
+ }
189
+ /**
190
+ * Get all component names from component list
191
+ */
192
+ async getAllComponentNames() {
193
+ try {
194
+ const fs = require("fs-extra");
195
+ const componentListPath = ".mycontext/component-list.json";
196
+ if (await fs.pathExists(componentListPath)) {
197
+ const content = await fs.readFile(componentListPath, "utf8");
198
+ const componentList = JSON.parse(content);
199
+ // Extract component names from hierarchical structure
200
+ const names = [];
201
+ const extractNames = (item) => {
202
+ if (item.components) {
203
+ item.components.forEach((comp) => names.push(comp.name));
204
+ }
205
+ if (item.children) {
206
+ item.children.forEach(extractNames);
207
+ }
208
+ };
209
+ extractNames(componentList);
210
+ return names;
211
+ }
212
+ }
213
+ catch (error) {
214
+ // Return empty array if component list not found
215
+ }
216
+ return [];
217
+ }
218
+ /**
219
+ * Display trigger log summary
220
+ */
221
+ async displaySummary() {
222
+ const recentEvents = await this.getRecentEvents(5);
223
+ const recommendations = await this.getRegenerationRecommendations();
224
+ console.log(chalk_1.default.blue("\n📋 Trigger Log Summary"));
225
+ console.log(chalk_1.default.gray("Recent events affecting your components:"));
226
+ if (recentEvents.length === 0) {
227
+ console.log(chalk_1.default.green(" ✅ No recent trigger events"));
228
+ return;
229
+ }
230
+ recentEvents.forEach((event, index) => {
231
+ const timeAgo = this.getTimeAgo(event.timestamp);
232
+ console.log(chalk_1.default.yellow(` ${index + 1}. ${event.description}`));
233
+ console.log(chalk_1.default.gray(` ${timeAgo} - ${event.userAction}`));
234
+ if (event.affectedComponents.length > 0) {
235
+ console.log(chalk_1.default.gray(` Affects: ${event.affectedComponents.join(", ")}`));
236
+ }
237
+ });
238
+ if (recommendations.shouldRegenerate.length > 0) {
239
+ console.log(chalk_1.default.yellow(`\n⚠️ ${recommendations.reason}`));
240
+ console.log(chalk_1.default.blue(` Consider regenerating: ${recommendations.shouldRegenerate.join(", ")}`));
241
+ }
242
+ }
243
+ /**
244
+ * Get human-readable time ago
245
+ */
246
+ getTimeAgo(timestamp) {
247
+ const now = new Date().getTime();
248
+ const eventTime = new Date(timestamp).getTime();
249
+ const diffMs = now - eventTime;
250
+ const diffMins = Math.floor(diffMs / (1000 * 60));
251
+ const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
252
+ const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
253
+ if (diffMins < 1)
254
+ return "just now";
255
+ if (diffMins < 60)
256
+ return `${diffMins}m ago`;
257
+ if (diffHours < 24)
258
+ return `${diffHours}h ago`;
259
+ return `${diffDays}d ago`;
260
+ }
261
+ }
262
+ exports.TriggerLogger = TriggerLogger;
263
+ //# sourceMappingURL=TriggerLogger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TriggerLogger.js","sourceRoot":"","sources":["../../src/services/TriggerLogger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { init } from '@instantdb/react';
2
+ import schema from '../instant.schema';
3
+
4
+ const APP_ID = process.env.NEXT_PUBLIC_INSTANT_APP_ID!;
5
+
6
+ if (!APP_ID) {
7
+ throw new Error(
8
+ 'NEXT_PUBLIC_INSTANT_APP_ID is not set. Run: mycontext init . --framework instantdb'
9
+ );
10
+ }
11
+
12
+ const db = init({ appId: APP_ID, schema });
13
+
14
+ export default db;
@@ -0,0 +1,127 @@
1
+ "use client";
2
+
3
+ import { id } from "@instantdb/react";
4
+ import db from "@/lib/db";
5
+ import { Button } from "@/components/ui/button";
6
+ import { Input } from "@/components/ui/input";
7
+ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
8
+ import { Checkbox } from "@/components/ui/checkbox";
9
+ import { useState } from "react";
10
+
11
+ export default function HomeClient() {
12
+ const [newTodo, setNewTodo] = useState("");
13
+ const { isLoading, error, data } = db.useQuery({ todos: {} });
14
+
15
+ const addTodo = () => {
16
+ if (!newTodo.trim()) return;
17
+
18
+ db.transact(
19
+ db.tx.todos[id()].update({
20
+ text: newTodo,
21
+ done: false,
22
+ createdAt: Date.now(),
23
+ })
24
+ );
25
+ setNewTodo("");
26
+ };
27
+
28
+ const toggleTodo = (todo: any) => {
29
+ db.transact(db.tx.todos[todo.id].update({ done: !todo.done }));
30
+ };
31
+
32
+ const deleteTodo = (todo: any) => {
33
+ db.transact(db.tx.todos[todo.id].delete());
34
+ };
35
+
36
+ if (isLoading) {
37
+ return (
38
+ <div className="max-w-2xl mx-auto p-8">
39
+ <div className="text-center">Loading...</div>
40
+ </div>
41
+ );
42
+ }
43
+
44
+ if (error) {
45
+ return (
46
+ <div className="max-w-2xl mx-auto p-8">
47
+ <Card className="border-red-500">
48
+ <CardHeader>
49
+ <CardTitle className="text-red-500">Error</CardTitle>
50
+ </CardHeader>
51
+ <CardContent>
52
+ <p className="text-sm text-muted-foreground">{error.message}</p>
53
+ <p className="text-xs text-muted-foreground mt-4">
54
+ Make sure NEXT_PUBLIC_INSTANT_APP_ID is set in your .env file
55
+ </p>
56
+ </CardContent>
57
+ </Card>
58
+ </div>
59
+ );
60
+ }
61
+
62
+ const { todos } = data;
63
+
64
+ return (
65
+ <div className="max-w-2xl mx-auto p-8">
66
+ <Card>
67
+ <CardHeader>
68
+ <CardTitle className="text-4xl font-bold">My Todos</CardTitle>
69
+ <p className="text-sm text-muted-foreground">
70
+ Real-time todos powered by InstantDB
71
+ </p>
72
+ </CardHeader>
73
+ <CardContent className="space-y-4">
74
+ <div className="flex gap-2">
75
+ <Input
76
+ value={newTodo}
77
+ onChange={(e) => setNewTodo(e.target.value)}
78
+ placeholder="What needs to be done?"
79
+ onKeyPress={(e) => e.key === "Enter" && addTodo()}
80
+ className="flex-1"
81
+ />
82
+ <Button onClick={addTodo}>Add</Button>
83
+ </div>
84
+
85
+ <div className="space-y-2">
86
+ {todos.length === 0 ? (
87
+ <div className="text-center py-8 text-muted-foreground">
88
+ No todos yet. Add one above!
89
+ </div>
90
+ ) : (
91
+ todos.map((todo: any) => (
92
+ <Card key={todo.id} className="p-4">
93
+ <div className="flex items-center gap-4">
94
+ <Checkbox
95
+ checked={todo.done}
96
+ onCheckedChange={() => toggleTodo(todo)}
97
+ />
98
+ <span
99
+ className={`flex-1 ${
100
+ todo.done ? "line-through text-muted-foreground" : ""
101
+ }`}
102
+ >
103
+ {todo.text}
104
+ </span>
105
+ <Button
106
+ variant="destructive"
107
+ size="sm"
108
+ onClick={() => deleteTodo(todo)}
109
+ >
110
+ Delete
111
+ </Button>
112
+ </div>
113
+ </Card>
114
+ ))
115
+ )}
116
+ </div>
117
+
118
+ <div className="text-xs text-muted-foreground pt-4 border-t">
119
+ <p>
120
+ ✨ Try opening this in multiple tabs - changes sync in real-time!
121
+ </p>
122
+ </div>
123
+ </CardContent>
124
+ </Card>
125
+ </div>
126
+ );
127
+ }
@@ -0,0 +1,5 @@
1
+ import HomeClient from "./home-client";
2
+
3
+ export default function Home() {
4
+ return <HomeClient />;
5
+ }
@@ -0,0 +1,9 @@
1
+ export default {
2
+ todos: {
3
+ allow: {
4
+ create: "auth.id != null",
5
+ update: "auth.id != null",
6
+ delete: "auth.id != null",
7
+ },
8
+ },
9
+ };
@@ -0,0 +1,28 @@
1
+ import { i } from "@instantdb/react";
2
+
3
+ const _schema = i.schema({
4
+ entities: {
5
+ $files: i.entity({
6
+ path: i.string().unique().indexed(),
7
+ url: i.string(),
8
+ }),
9
+ $users: i.entity({
10
+ email: i.string().unique().indexed().optional(),
11
+ type: i.string().optional(),
12
+ }),
13
+ todos: i.entity({
14
+ text: i.string(),
15
+ done: i.boolean(),
16
+ createdAt: i.number(),
17
+ }),
18
+ },
19
+ links: {},
20
+ rooms: {},
21
+ });
22
+
23
+ type _AppSchema = typeof _schema;
24
+ interface AppSchema extends _AppSchema {}
25
+ const schema: AppSchema = _schema;
26
+
27
+ export type { AppSchema };
28
+ export default schema;