mycontext-cli 3.0.2 → 3.0.3

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.
@@ -78,62 +78,165 @@ class InitCommand {
78
78
  ? workingDir
79
79
  : path.resolve(workingDir, finalProjectName);
80
80
  spinner.start();
81
- // 1. pnpm dlx shadcn@latest init
82
- spinner.updateText("Running shadcn init...");
83
- (0, child_process_1.execSync)("pnpm dlx shadcn@latest init", {
84
- cwd: workingDir,
85
- stdio: "inherit",
86
- });
87
- // 2. npx instant-cli init
81
+ // Determine framework (default to instantdb for backward compatibility)
82
+ const framework = options.framework || "instantdb";
83
+ if (framework === "instantdb") {
84
+ // InstantDB workflow
85
+ await this.initInstantDBProject(spinner, workingDir, projectPath, finalProjectName, options, useCurrentDir);
86
+ }
87
+ else if (framework === "nextjs" || framework === "next") {
88
+ // Next.js workflow (shadcn + MyContext only)
89
+ await this.initNextJSProject(spinner, workingDir, projectPath, finalProjectName, options, useCurrentDir);
90
+ }
91
+ else {
92
+ // Default: MyContext only
93
+ await this.initBasicProject(spinner, projectPath, finalProjectName, options, useCurrentDir);
94
+ }
95
+ }
96
+ catch (error) {
97
+ spinner.error({ text: "Failed to initialize project" });
98
+ console.error(chalk_1.default.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
99
+ throw error;
100
+ }
101
+ }
102
+ /**
103
+ * Initialize an InstantDB project with full setup
104
+ */
105
+ async initInstantDBProject(spinner, workingDir, projectPath, projectName, options, useCurrentDir) {
106
+ // 1. Run shadcn init
107
+ spinner.updateText("Running shadcn init...");
108
+ (0, child_process_1.execSync)("pnpm dlx shadcn@latest init", {
109
+ cwd: workingDir,
110
+ stdio: "inherit",
111
+ });
112
+ // 2. Prompt user for instant-cli init
113
+ spinner.stop();
114
+ const { runInstantInit } = await (0, prompts_1.default)({
115
+ type: "confirm",
116
+ name: "runInstantInit",
117
+ message: "Run 'npx instant-cli init' to initialize InstantDB?",
118
+ initial: true,
119
+ });
120
+ if (runInstantInit) {
121
+ spinner.start();
88
122
  spinner.updateText("Running instant-cli init...");
89
123
  (0, child_process_1.execSync)("npx instant-cli init", {
90
124
  cwd: projectPath,
91
125
  stdio: "inherit",
92
126
  });
93
- // 3. pnpm add @instantdb/react
94
- spinner.updateText("Installing @instantdb/react...");
95
- (0, child_process_1.execSync)("pnpm add @instantdb/react", {
96
- cwd: projectPath,
97
- stdio: "inherit",
98
- });
99
- // Initialize MyContext directory structure and context
100
- spinner.updateText("Initializing MyContext project files...");
101
- const config = await this.fs.initializeProject(finalProjectName, options.description || `${finalProjectName} - AI-powered app`, workingDir, useCurrentDir);
102
- spinner.success({
103
- text: `Project "${finalProjectName}" initialized successfully!`,
127
+ // Prompt user to push schemas
128
+ spinner.stop();
129
+ const { pushSchemas } = await (0, prompts_1.default)({
130
+ type: "confirm",
131
+ name: "pushSchemas",
132
+ message: "Push schemas to InstantDB dashboard? (Make sure you've configured your app)",
133
+ initial: false,
104
134
  });
105
- // Show next steps
106
- this.showNextSteps(config, "instantdb", useCurrentDir);
107
- }
108
- catch (error) {
109
- spinner.error({ text: "Failed to initialize project" });
110
- console.error(chalk_1.default.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
135
+ if (pushSchemas) {
136
+ spinner.start();
137
+ spinner.updateText("Pushing schemas to InstantDB...");
138
+ (0, child_process_1.execSync)("npx instant-cli push", {
139
+ cwd: projectPath,
140
+ stdio: "inherit",
141
+ });
142
+ }
111
143
  }
144
+ // 3. Install @instantdb/react and @instantdb/admin
145
+ spinner.start();
146
+ spinner.updateText("Installing InstantDB packages...");
147
+ (0, child_process_1.execSync)("pnpm add @instantdb/react @instantdb/admin", {
148
+ cwd: projectPath,
149
+ stdio: "inherit",
150
+ });
151
+ // Install bcrypt for auth utilities
152
+ spinner.updateText("Installing auth dependencies...");
153
+ (0, child_process_1.execSync)("pnpm add bcryptjs nanoid && pnpm add -D @types/bcryptjs", {
154
+ cwd: projectPath,
155
+ stdio: "inherit",
156
+ });
157
+ // 4. Copy InstantDB templates to lib folder
158
+ spinner.updateText("Copying InstantDB template files...");
159
+ await this.fs.copyInstantDBTemplates(projectPath);
160
+ // 5. Initialize MyContext directory structure and context
161
+ spinner.updateText("Initializing MyContext project files...");
162
+ const config = await this.fs.initializeProject(projectName, options.description || `${projectName} - AI-powered app`, workingDir, useCurrentDir);
163
+ spinner.success({
164
+ text: `Project "${projectName}" initialized successfully with InstantDB!`,
165
+ });
166
+ // Show next steps
167
+ this.showNextSteps(config, "instantdb", useCurrentDir);
168
+ }
169
+ /**
170
+ * Initialize a Next.js project (shadcn + MyContext only)
171
+ */
172
+ async initNextJSProject(spinner, workingDir, projectPath, projectName, options, useCurrentDir) {
173
+ // 1. Run shadcn init
174
+ spinner.updateText("Running shadcn init...");
175
+ (0, child_process_1.execSync)("pnpm dlx shadcn@latest init", {
176
+ cwd: workingDir,
177
+ stdio: "inherit",
178
+ });
179
+ // 2. Initialize MyContext directory structure and context
180
+ spinner.updateText("Initializing MyContext project files...");
181
+ const config = await this.fs.initializeProject(projectName, options.description || `${projectName} - Next.js app`, workingDir, useCurrentDir);
182
+ spinner.success({
183
+ text: `Project "${projectName}" initialized successfully with Next.js!`,
184
+ });
185
+ // Show next steps
186
+ this.showNextSteps(config, "nextjs", useCurrentDir);
187
+ }
188
+ /**
189
+ * Initialize a basic MyContext project (no framework)
190
+ */
191
+ async initBasicProject(spinner, projectPath, projectName, options, useCurrentDir) {
192
+ spinner.updateText("Initializing MyContext project files...");
193
+ const config = await this.fs.initializeProject(projectName, options.description || `${projectName} - AI-powered app`, process.cwd(), useCurrentDir);
194
+ spinner.success({
195
+ text: `Project "${projectName}" initialized successfully!`,
196
+ });
197
+ // Show next steps
198
+ this.showNextSteps(config, undefined, useCurrentDir);
112
199
  }
113
200
  isValidProjectName(name) {
114
201
  // Allow alphanumeric, hyphens, and underscores
115
202
  return /^[a-zA-Z0-9._-]+$/.test(name);
116
203
  }
117
204
  showNextSteps(config, framework, useCurrentDir) {
118
- const projectPath = useCurrentDir ? process.cwd() : config.name;
205
+ const projectPath = useCurrentDir ? "." : config.name;
119
206
  console.log(chalk_1.default.blue("\n🎯 Quick Start:\n"));
120
- console.log(chalk_1.default.yellow("1. Navigate to your project:"));
121
- console.log(chalk_1.default.gray(` cd ${projectPath}\n`));
122
- console.log(chalk_1.default.yellow("2. ️ Analyze a screenshot (Gemini 2.0 Flash):"));
207
+ if (!useCurrentDir) {
208
+ console.log(chalk_1.default.yellow("1. Navigate to your project:"));
209
+ console.log(chalk_1.default.gray(` cd ${projectPath}\n`));
210
+ }
211
+ if (framework === "instantdb") {
212
+ console.log(chalk_1.default.yellow("2. Configure InstantDB:"));
213
+ console.log(chalk_1.default.gray(" • Add your InstantDB App ID to .env.local:"));
214
+ console.log(chalk_1.default.cyan(" NEXT_PUBLIC_INSTANT_APP_ID=your-app-id"));
215
+ console.log(chalk_1.default.gray(" • Template files copied to lib/ (or src/lib/):"));
216
+ console.log(chalk_1.default.gray(" - instant-client.ts (Client SDK)"));
217
+ console.log(chalk_1.default.gray(" - instant-admin.ts (Admin SDK)"));
218
+ console.log(chalk_1.default.gray(" - auth.ts (Auth helpers)"));
219
+ console.log(chalk_1.default.gray(" - instantdb-storage.ts (File storage)\n"));
220
+ }
221
+ console.log(chalk_1.default.yellow("3. ️ Analyze a screenshot (Gemini 2.0 Flash):"));
123
222
  console.log(chalk_1.default.cyan(" mycontext analyze /path/to/screenshot.png"));
124
223
  console.log(chalk_1.default.gray(" # Reverse-engineer any UI into a comprehensive spec!\n"));
125
- console.log(chalk_1.default.yellow("3. Configure AI provider:"));
126
- console.log(chalk_1.default.gray(" Gemini (Free - Recommended for screenshots):"));
224
+ console.log(chalk_1.default.yellow("4. Configure AI provider:"));
225
+ console.log(chalk_1.default.gray(" 🔥 Gemini (Free - Recommended for screenshots):"));
127
226
  console.log(chalk_1.default.gray(" Get API key: https://aistudio.google.com/apikey"));
128
227
  console.log(chalk_1.default.cyan(" echo 'GEMINI_API_KEY=your-key' >> .mycontext/.env\n"));
129
228
  console.log(chalk_1.default.gray(" 📌 Claude (Best for text generation):"));
130
229
  console.log(chalk_1.default.gray(" https://console.anthropic.com/\n"));
131
- console.log(chalk_1.default.yellow("4. Generate full context:"));
230
+ console.log(chalk_1.default.yellow("5. Generate full context:"));
132
231
  console.log(chalk_1.default.gray(" mycontext generate context --full\n"));
133
- console.log(chalk_1.default.yellow("5. Start development:"));
232
+ console.log(chalk_1.default.yellow("6. Start development:"));
134
233
  console.log(chalk_1.default.gray(" pnpm dev\n"));
135
234
  console.log(chalk_1.default.green("✨ Tips:"));
136
235
  console.log(chalk_1.default.gray("• Check .mycontext/ for all generated files"));
236
+ if (framework === "instantdb") {
237
+ console.log(chalk_1.default.gray("• InstantDB templates are ready to use in your lib/ folder"));
238
+ console.log(chalk_1.default.gray("• Update instant.schema.ts with your data model"));
239
+ }
137
240
  console.log(chalk_1.default.gray("• Use --yes flag to skip prompts"));
138
241
  console.log(chalk_1.default.gray("• Run 'mycontext status' to check project progress\n"));
139
242
  // Exit the process gracefully after displaying all information
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mycontext-cli",
3
- "version": "3.0.2",
3
+ "version": "3.0.3",
4
4
  "description": "Spec-Driven Development for the AI Era - Generate comprehensive context + visual screens, then code with Claude/Cursor",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {
@@ -0,0 +1,89 @@
1
+ import bcrypt from "bcryptjs";
2
+ import { nanoid } from "nanoid";
3
+
4
+ export interface CreateUserInput {
5
+ email?: string;
6
+ phone?: string;
7
+ name: string;
8
+ password?: string;
9
+ }
10
+
11
+ export interface MagicCodeData {
12
+ code: string;
13
+ identifier: string; // email or phone
14
+ type: "email" | "phone";
15
+ expiresAt: number;
16
+ userId?: string; // For existing users
17
+ }
18
+
19
+ /**
20
+ * Hash a password using bcrypt
21
+ */
22
+ export async function hashPassword(password: string): Promise<string> {
23
+ const salt = await bcrypt.genSalt(10);
24
+ return bcrypt.hash(password, salt);
25
+ }
26
+
27
+ /**
28
+ * Verify a password against a hash
29
+ */
30
+ export async function verifyPassword(
31
+ password: string,
32
+ hash: string
33
+ ): Promise<boolean> {
34
+ return bcrypt.compare(password, hash);
35
+ }
36
+
37
+ /**
38
+ * Generate a 6-digit magic code
39
+ */
40
+ export function generateMagicCode(): string {
41
+ return Math.floor(100000 + Math.random() * 900000).toString();
42
+ }
43
+
44
+ /**
45
+ * Generate a unique subdomain from business name
46
+ */
47
+ export function generateSubdomain(businessName: string): string {
48
+ const base = businessName
49
+ .toLowerCase()
50
+ .replace(/[^a-z0-9]/g, "-")
51
+ .replace(/-+/g, "-")
52
+ .replace(/^-|-$/g, "");
53
+
54
+ // Add random suffix to ensure uniqueness
55
+ const suffix = nanoid(6).toLowerCase();
56
+ return `${base}-${suffix}`;
57
+ }
58
+
59
+ /**
60
+ * Validate subdomain format
61
+ */
62
+ export function isValidSubdomain(subdomain: string): boolean {
63
+ const regex = /^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/;
64
+ return regex.test(subdomain);
65
+ }
66
+
67
+ /**
68
+ * Create a magic code with expiry (10 minutes)
69
+ */
70
+ export function createMagicCodeData(
71
+ identifier: string,
72
+ type: "email" | "phone",
73
+ userId?: string
74
+ ): MagicCodeData {
75
+ return {
76
+ code: generateMagicCode(),
77
+ identifier,
78
+ type,
79
+ expiresAt: Date.now() + 10 * 60 * 1000, // 10 minutes
80
+ userId,
81
+ };
82
+ }
83
+
84
+ /**
85
+ * Verify if magic code is still valid
86
+ */
87
+ export function isMagicCodeValid(magicCodeData: MagicCodeData): boolean {
88
+ return Date.now() < magicCodeData.expiresAt;
89
+ }
@@ -0,0 +1,9 @@
1
+ import { init, id } from "@instantdb/admin";
2
+ import schema, { AppSchema } from "@/instant.schema";
3
+
4
+ export const adminDb = init({
5
+ appId: process.env.NEXT_PUBLIC_INSTANT_APP_ID!,
6
+ adminToken: process.env.INSTANT_APP_ADMIN_TOKEN!,
7
+ schema,
8
+ });
9
+ export { id };
@@ -0,0 +1,36 @@
1
+ import { init, id } from "@instantdb/react";
2
+ import schema from "@/instant.schema";
3
+
4
+ // ID for app: jibu-delivery
5
+ const APP_ID = process.env.NEXT_PUBLIC_INSTANT_APP_ID!;
6
+
7
+ /**
8
+ * InstantDB client initialization
9
+ *
10
+ * Note: InstantDB uses localStorage and IndexedDB for caching query results.
11
+ * If you encounter JSON parse errors, use the storage utilities from @/lib/storage-utils
12
+ * to clear corrupted storage.
13
+ *
14
+ * The useStorageInit hook in app layout handles automatic error recovery.
15
+ */
16
+ // Mock for E2E testing
17
+ const isE2E = process.env.NEXT_PUBLIC_IS_E2E === "true";
18
+
19
+ const db = isE2E
20
+ ? {
21
+ useAuth: () => ({
22
+ isLoading: false,
23
+ user: { id: "mock-user-id", email: "[EMAIL_ADDRESS]", isGuest: false },
24
+ error: null,
25
+ }),
26
+ useQuery: () => ({ isLoading: false, error: null, data: {} }),
27
+ auth: {
28
+ signOut: async () => {},
29
+ signInAsGuest: async () => {},
30
+ sendMagicCode: async () => {},
31
+ signInWithMagicCode: async () => {},
32
+ },
33
+ } as any
34
+ : init({ appId: APP_ID, schema });
35
+
36
+ export { db, id };
@@ -0,0 +1,236 @@
1
+ /**
2
+ * InstantDB Storage Helper
3
+ *
4
+ * Utilities for uploading and managing files using InstantDB's storage feature.
5
+ * https://www.instantdb.com/docs/storage
6
+ */
7
+
8
+ import { db } from "./instant-client";
9
+
10
+ export interface UploadResult {
11
+ success: boolean;
12
+ url?: string;
13
+ path?: string;
14
+ id?: string;
15
+ error?: string;
16
+ }
17
+
18
+ export interface UploadOptions {
19
+ contentType?: string;
20
+ }
21
+
22
+ /**
23
+ * Upload a file to InstantDB storage
24
+ *
25
+ * @param file - The file to upload
26
+ * @param path - Optional custom path (defaults to auto-generated)
27
+ * @param options - Optional upload options (contentType)
28
+ * @returns Upload result with URL
29
+ */
30
+ export async function uploadFile(
31
+ file: File,
32
+ path?: string,
33
+ options?: UploadOptions
34
+ ): Promise<UploadResult> {
35
+ try {
36
+ // Generate path if not provided
37
+ const fileName = path || `uploads/${Date.now()}-${file.name}`;
38
+
39
+ console.log("📤 Uploading file:", fileName);
40
+
41
+ // Upload to InstantDB storage with correct API
42
+ const opts = {
43
+ contentType: options?.contentType || file.type,
44
+ };
45
+
46
+ const { data } = await db.storage.uploadFile(fileName, file, opts);
47
+
48
+ console.log("✅ File uploaded successfully, ID:", data.id);
49
+
50
+ // Return the path data
51
+ // Note: To get a displayable URL, the client must query $files or use a Signed URL
52
+ return {
53
+ success: true,
54
+ path: fileName,
55
+ id: data.id,
56
+ url: fileName, // Returning path as 'url' for compatibility, consumer should resolve it
57
+ };
58
+ } catch (error) {
59
+ console.error("❌ Error uploading file:", error);
60
+ return {
61
+ success: false,
62
+ error: error instanceof Error ? error.message : "Upload failed",
63
+ };
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Upload an image for inventory item
69
+ *
70
+ * @param file - The image file to upload
71
+ * @param itemId - The inventory item ID
72
+ * @returns Upload result with URL
73
+ */
74
+ export async function uploadInventoryImage(
75
+ file: File,
76
+ itemId: string
77
+ ): Promise<UploadResult> {
78
+ try {
79
+ // Validate file is an image
80
+ if (!file.type.startsWith("image/")) {
81
+ return {
82
+ success: false,
83
+ error: "File must be an image",
84
+ };
85
+ }
86
+
87
+ // Validate file size (max 5MB)
88
+ const maxSize = 5 * 1024 * 1024; // 5MB
89
+ if (file.size > maxSize) {
90
+ return {
91
+ success: false,
92
+ error: "Image must be less than 5MB",
93
+ };
94
+ }
95
+
96
+ // Generate unique path
97
+ const ext = file.name.split(".").pop() || "jpg";
98
+ const fileName = `inventory/${itemId}-${Date.now()}.${ext}`;
99
+
100
+ return await uploadFile(file, fileName, {
101
+ contentType: file.type,
102
+ });
103
+ } catch (error) {
104
+ console.error("❌ Error uploading inventory image:", error);
105
+ return {
106
+ success: false,
107
+ error: error instanceof Error ? error.message : "Upload failed",
108
+ };
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Delete a file from InstantDB storage
114
+ *
115
+ * @param url - The file URL to delete
116
+ * @returns Success status
117
+ */
118
+ export async function deleteFile(url: string): Promise<boolean> {
119
+ try {
120
+ console.log("🗑️ Deleting file:", url);
121
+
122
+ await db.storage.delete(url);
123
+
124
+ console.log("✅ File deleted successfully");
125
+ return true;
126
+ } catch (error) {
127
+ console.error("❌ Error deleting file:", error);
128
+ return false;
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Get a file URL from InstantDB storage
134
+ *
135
+ * @param path - The file path
136
+ * @returns The file URL
137
+ */
138
+ export function getFileUrl(path: string): string {
139
+ return db.storage.getDownloadUrl(path) as any;
140
+ }
141
+
142
+ /**
143
+ * Validate image file
144
+ *
145
+ * @param file - The file to validate
146
+ * @returns Validation result
147
+ */
148
+ export function validateImageFile(file: File): {
149
+ valid: boolean;
150
+ error?: string;
151
+ } {
152
+ // Check file type
153
+ if (!file.type.startsWith("image/")) {
154
+ return {
155
+ valid: false,
156
+ error: "File must be an image (PNG, JPG, GIF, WEBP)",
157
+ };
158
+ }
159
+
160
+ // Check file size (max 5MB)
161
+ const maxSize = 5 * 1024 * 1024; // 5MB
162
+ if (file.size > maxSize) {
163
+ return {
164
+ valid: false,
165
+ error: "Image must be less than 5MB",
166
+ };
167
+ }
168
+
169
+ // Check image dimensions (optional)
170
+ const validTypes = [
171
+ "image/png",
172
+ "image/jpeg",
173
+ "image/jpg",
174
+ "image/gif",
175
+ "image/webp",
176
+ ];
177
+ if (!validTypes.includes(file.type)) {
178
+ return {
179
+ valid: false,
180
+ error: "Supported formats: PNG, JPG, GIF, WEBP",
181
+ };
182
+ }
183
+
184
+ return { valid: true };
185
+ }
186
+
187
+ /**
188
+ * Validate any file based on accept string
189
+ *
190
+ * @param file - The file to validate
191
+ * @param accept - The accept string (e.g. "image/*,application/pdf")
192
+ * @returns Validation result
193
+ */
194
+ export function validateFile(file: File, accept?: string): {
195
+ valid: boolean;
196
+ error?: string;
197
+ } {
198
+ // If no accept string, allow everything
199
+ if (!accept || accept === "*") {
200
+ return { valid: true };
201
+ }
202
+
203
+ const acceptedTypes = accept.split(",").map(t => t.trim());
204
+ const fileType = file.type;
205
+
206
+ // Check if file type matches any accepted type
207
+ const isTypeValid = acceptedTypes.some(type => {
208
+ // Handle wildcards like image/*
209
+ if (type.endsWith("/*")) {
210
+ const mainType = type.split("/")[0];
211
+ return fileType.startsWith(`${mainType}/`);
212
+ }
213
+ // Handle explicit extensions like .pdf (mapped to MIME types usually, but here we check MIME)
214
+ // Note: This is a simple check. For robust file input behavior, usually relying on the input itself is best,
215
+ // but here we validate post-select.
216
+ return type === fileType;
217
+ });
218
+
219
+ if (!isTypeValid) {
220
+ return {
221
+ valid: false,
222
+ error: `File type ${fileType} is not supported. Allowed: ${accept}`,
223
+ };
224
+ }
225
+
226
+ // Generic size limit (10MB for documents, 5MB for images usually, but let's stick to 10MB global for now or parameterize)
227
+ const maxSize = 10 * 1024 * 1024; // 10MB
228
+ if (file.size > maxSize) {
229
+ return {
230
+ valid: false,
231
+ error: "File must be less than 10MB",
232
+ };
233
+ }
234
+
235
+ return { valid: true };
236
+ }
@@ -54,5 +54,14 @@ export declare class FileSystemManager {
54
54
  * Restore a file from backup
55
55
  */
56
56
  restoreFile(backupPath: string, targetPath: string): Promise<void>;
57
+ /**
58
+ * Detect the lib directory in the project
59
+ * Returns src/lib/ if src directory exists, otherwise lib/
60
+ */
61
+ detectLibDirectory(projectPath: string): Promise<string>;
62
+ /**
63
+ * Copy InstantDB template files to the project's lib directory
64
+ */
65
+ copyInstantDBTemplates(projectPath: string): Promise<void>;
57
66
  }
58
67
  //# sourceMappingURL=fileSystem.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fileSystem.d.ts","sourceRoot":"","sources":["../../src/utils/fileSystem.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAgB,MAAM,UAAU,CAAC;AAEvD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgB;IAC7C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAE3C;;OAEG;IACG,iBAAiB,CACrB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,aAAa,CAAC,EAAE,OAAO,GACtB,OAAO,CAAC,aAAa,CAAC;IAsCzB;;OAEG;IACG,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIjD;;OAEG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQjE;;OAEG;IACG,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIhD;;OAEG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C;;OAEG;IACG,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUvD;;OAEG;IACG,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAa1E;;OAEG;IACG,mBAAmB,CACvB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAC9B,OAAO,CAAC,IAAI,CAAC;IAiBhB;;OAEG;IACG,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAa9D;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAgCzB;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBnE;;OAEG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAMnD;;OAEG;IACG,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGzE"}
1
+ {"version":3,"file":"fileSystem.d.ts","sourceRoot":"","sources":["../../src/utils/fileSystem.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAgB,MAAM,UAAU,CAAC;AAEvD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgB;IAC7C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAE3C;;OAEG;IACG,iBAAiB,CACrB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,aAAa,CAAC,EAAE,OAAO,GACtB,OAAO,CAAC,aAAa,CAAC;IAsCzB;;OAEG;IACG,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIjD;;OAEG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQjE;;OAEG;IACG,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIhD;;OAEG;IACG,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C;;OAEG;IACG,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUvD;;OAEG;IACG,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAa1E;;OAEG;IACG,mBAAmB,CACvB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAC9B,OAAO,CAAC,IAAI,CAAC;IAiBhB;;OAEG;IACG,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAa9D;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAgCzB;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBnE;;OAEG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAMnD;;OAEG;IACG,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxE;;;OAGG;IACG,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAW9D;;OAEG;IACG,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAyBjE"}