framer-code-link 0.4.0 → 0.4.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 (2) hide show
  1. package/dist/index.mjs +155 -115
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -178,7 +178,9 @@ function debug(message, ...args) {
178
178
  function info(message, ...args) {
179
179
  if (currentLevel <= LogLevel.INFO) {
180
180
  const formatted = args.length > 0 ? `${message} ${args.join(" ")}` : message;
181
- logWithDedupe(formatted, () => console.log(formatted));
181
+ logWithDedupe(formatted, () => {
182
+ console.log(formatted);
183
+ });
182
184
  }
183
185
  }
184
186
  /**
@@ -217,19 +219,25 @@ function success(message, ...args) {
217
219
  function fileDown(fileName) {
218
220
  if (currentLevel <= LogLevel.INFO) {
219
221
  const msg = ` ${import_picocolors.default.blue("↓")} ${fileName}`;
220
- logWithDedupe(msg, () => console.log(msg));
222
+ logWithDedupe(msg, () => {
223
+ console.log(msg);
224
+ });
221
225
  }
222
226
  }
223
227
  function fileUp(fileName) {
224
228
  if (currentLevel <= LogLevel.INFO) {
225
229
  const msg = ` ${import_picocolors.default.green("↑")} ${fileName}`;
226
- logWithDedupe(msg, () => console.log(msg));
230
+ logWithDedupe(msg, () => {
231
+ console.log(msg);
232
+ });
227
233
  }
228
234
  }
229
235
  function fileDelete(fileName) {
230
236
  if (currentLevel <= LogLevel.INFO) {
231
237
  const msg = ` ${import_picocolors.default.red("×")} ${fileName}`;
232
- logWithDedupe(msg, () => console.log(msg));
238
+ logWithDedupe(msg, () => {
239
+ console.log(msg);
240
+ });
233
241
  }
234
242
  }
235
243
  /**
@@ -341,7 +349,7 @@ function initConnection(port) {
341
349
  }
342
350
  });
343
351
  ws.on("close", (code, reason) => {
344
- debug(`Client disconnected (code: ${code}, reason: ${reason?.toString() || "none"})`);
352
+ debug(`Client disconnected (code: ${code}, reason: ${reason.toString()})`);
345
353
  handlers.onDisconnect?.();
346
354
  });
347
355
  ws.on("error", (err) => {
@@ -350,10 +358,20 @@ function initConnection(port) {
350
358
  });
351
359
  resolve({
352
360
  on(event, handler) {
353
- if (event === "handshake") handlers.onHandshake = handler;
354
- else if (event === "message") handlers.onMessage = handler;
355
- else if (event === "disconnect") handlers.onDisconnect = handler;
356
- else if (event === "error") handlers.onError = handler;
361
+ switch (event) {
362
+ case "handshake":
363
+ handlers.onHandshake = handler;
364
+ break;
365
+ case "message":
366
+ handlers.onMessage = handler;
367
+ break;
368
+ case "disconnect":
369
+ handlers.onDisconnect = handler;
370
+ break;
371
+ case "error":
372
+ handlers.onError = handler;
373
+ break;
374
+ }
357
375
  },
358
376
  close() {
359
377
  wss.close();
@@ -449,7 +467,7 @@ function normalizePath$1(filePath) {
449
467
  function initWatcher(filesDir) {
450
468
  const handlers = [];
451
469
  const watcher = chokidar.watch(filesDir, {
452
- ignored: /(^|[\/\\])\../,
470
+ ignored: /(^|[/\\])\.\./,
453
471
  persistent: true,
454
472
  ignoreInitial: false
455
473
  });
@@ -485,12 +503,18 @@ function initWatcher(filesDir) {
485
503
  debug(`Watcher event: ${kind} ${relativePath}`);
486
504
  for (const handler of handlers) handler(event);
487
505
  };
488
- watcher.on("add", (filePath) => emitEvent("add", filePath));
489
- watcher.on("change", (filePath) => emitEvent("change", filePath));
490
- watcher.on("unlink", (filePath) => emitEvent("delete", filePath));
506
+ watcher.on("add", (filePath) => {
507
+ emitEvent("add", filePath);
508
+ });
509
+ watcher.on("change", (filePath) => {
510
+ emitEvent("change", filePath);
511
+ });
512
+ watcher.on("unlink", (filePath) => {
513
+ emitEvent("delete", filePath);
514
+ });
491
515
  return {
492
- on(event, handler) {
493
- if (event === "change") handlers.push(handler);
516
+ on(_event, handler) {
517
+ handlers.push(handler);
494
518
  },
495
519
  async close() {
496
520
  await watcher.close();
@@ -643,7 +667,7 @@ async function detectConflicts(remoteFiles, filesDir, options = {}) {
643
667
  const preferRemote = options.preferRemote ?? false;
644
668
  const persistedState = options.persistedState;
645
669
  const getPersistedState = (fileName) => persistedState?.get(normalizeForComparison(fileName)) ?? persistedState?.get(fileName);
646
- debug(`Detecting conflicts for ${remoteFiles.length} remote files`);
670
+ debug(`Detecting conflicts for ${String(remoteFiles.length)} remote files`);
647
671
  const localFiles = await listFiles(filesDir);
648
672
  const localFileMap = new Map(localFiles.map((f) => [normalizeForComparison(f.name), f]));
649
673
  const remoteFileMap = new Map(remoteFiles.map((f) => {
@@ -666,7 +690,7 @@ async function detectConflicts(remoteFiles, filesDir, options = {}) {
666
690
  localContent: null,
667
691
  remoteContent: remote.content,
668
692
  remoteModifiedAt: remote.modifiedAt,
669
- lastSyncedAt: persisted?.timestamp
693
+ lastSyncedAt: persisted.timestamp
670
694
  });
671
695
  } else writes.push({
672
696
  name: normalized.relativePath,
@@ -708,13 +732,13 @@ async function detectConflicts(remoteFiles, filesDir, options = {}) {
708
732
  const persisted = getPersistedState(local.name);
709
733
  if (persisted) {
710
734
  const localClean = hashFileContent(local.content) === persisted.contentHash;
711
- debug(`Conflict: ${local.name} deleted in Framer (localClean=${localClean})`);
735
+ debug(`Conflict: ${local.name} deleted in Framer (localClean=${String(localClean)})`);
712
736
  conflicts.push({
713
737
  fileName: local.name,
714
738
  localContent: local.content,
715
739
  remoteContent: null,
716
740
  localModifiedAt: local.modifiedAt,
717
- lastSyncedAt: persisted?.timestamp,
741
+ lastSyncedAt: persisted.timestamp,
718
742
  localClean
719
743
  });
720
744
  } else localOnly.push({
@@ -818,7 +842,7 @@ async function deleteLocalFile(fileName, filesDir, hashTracker) {
818
842
  hashTracker.forget(normalized.relativePath);
819
843
  debug(`Deleted file: ${normalized.relativePath}`);
820
844
  } catch (err) {
821
- if (err?.code === "ENOENT") {
845
+ if (err.code === "ENOENT") {
822
846
  hashTracker.forget(normalized.relativePath);
823
847
  debug(`File already deleted: ${normalized.relativePath}`);
824
848
  return;
@@ -844,7 +868,6 @@ async function readFileSafe(fileName, filesDir) {
844
868
  */
845
869
  function filterEchoedFiles(files, hashTracker) {
846
870
  return files.filter((file) => {
847
- if (file.content === void 0) return true;
848
871
  return !hashTracker.shouldSkip(file.name, file.content);
849
872
  });
850
873
  }
@@ -878,7 +901,7 @@ function isSupportedExtension$1(fileName) {
878
901
  function extractImports(code) {
879
902
  const imports = [];
880
903
  const seen = /* @__PURE__ */ new Set();
881
- const npmRegex = /import\s+(?:(?:\*\s+as\s+\w+)|(?:\w+)|(?:\{[^}]*\}))\s+from\s+['"]([^.\/][^'"]+)['"]/g;
904
+ const npmRegex = /import\s+(?:(?:\*\s+as\s+\w+)|(?:\w+)|(?:\{[^}]*\}))\s+from\s+['"]([^./][^'"]+)['"]/g;
882
905
  const urlRegex = /import\s+(?:(?:\*\s+as\s+\w+)|(?:\w+)|(?:\{[^}]*\}))\s+from\s+['"]https?:\/\/[^'"]+['"]/g;
883
906
  let match;
884
907
  while ((match = npmRegex.exec(code)) !== null) {
@@ -910,7 +933,7 @@ function extractImports(code) {
910
933
  * Attempt to derive an npm-style package specifier from a URL import.
911
934
  */
912
935
  function extractPackageFromUrl(url) {
913
- return url.match(/\/(@?[^@\/]+(?:\/[^@\/]+)?)/)?.[1] ?? null;
936
+ return /\/(@?[^@/]+(?:\/[^@/]+)?)/.exec(url)?.[1] ?? null;
914
937
  }
915
938
 
916
939
  //#endregion
@@ -963,29 +986,31 @@ var Installer = class {
963
986
  },
964
987
  progress: () => {},
965
988
  finished: (files) => {
966
- if (files && files.size > 0) debug("ATA: type acquisition complete");
989
+ if (files.size > 0) debug("ATA: type acquisition complete");
967
990
  },
968
991
  errorMessage: (message, error$1) => {
969
992
  warn(`ATA warning: ${message}`, error$1);
970
993
  },
971
- receivedFile: async (code, receivedPath) => {
972
- const normalized = receivedPath.replace(/^\//, "");
973
- const destination = path.join(this.projectDir, normalized);
974
- const pkgMatch = receivedPath.match(/\/node_modules\/(@?[^\/]+(?:\/[^\/]+)?)\//);
975
- try {
976
- if (await fs.readFile(destination, "utf-8") === code) {
977
- if (pkgMatch && !seenPackages.has(pkgMatch[1])) {
978
- seenPackages.add(pkgMatch[1]);
979
- debug(`📦 Types: ${pkgMatch[1]} (from disk cache)`);
994
+ receivedFile: (code, receivedPath) => {
995
+ (async () => {
996
+ const normalized = receivedPath.replace(/^\//, "");
997
+ const destination = path.join(this.projectDir, normalized);
998
+ const pkgMatch = /\/node_modules\/(@?[^/]+(?:\/[^/]+)?)\//.exec(receivedPath);
999
+ try {
1000
+ if (await fs.readFile(destination, "utf-8") === code) {
1001
+ if (pkgMatch && !seenPackages.has(pkgMatch[1])) {
1002
+ seenPackages.add(pkgMatch[1]);
1003
+ debug(`📦 Types: ${pkgMatch[1]} (from disk cache)`);
1004
+ }
1005
+ return;
980
1006
  }
981
- return;
1007
+ } catch {}
1008
+ if (pkgMatch && !seenPackages.has(pkgMatch[1])) {
1009
+ seenPackages.add(pkgMatch[1]);
1010
+ debug(`📦 Types: ${pkgMatch[1]}`);
982
1011
  }
983
- } catch {}
984
- if (pkgMatch && !seenPackages.has(pkgMatch[1])) {
985
- seenPackages.add(pkgMatch[1]);
986
- debug(`📦 Types: ${pkgMatch[1]}`);
987
- }
988
- await this.writeTypeFile(receivedPath, code);
1012
+ await this.writeTypeFile(receivedPath, code);
1013
+ })();
989
1014
  }
990
1015
  }
991
1016
  });
@@ -1073,11 +1098,11 @@ var Installer = class {
1073
1098
  warn(`Failed to write type file ${destination}`, err);
1074
1099
  return;
1075
1100
  }
1076
- if (normalized.match(/node_modules\/@types\/[^\/]+\/index\.d\.ts$/)) await this.ensureTypesPackageJson(normalized);
1101
+ if (/node_modules\/@types\/[^/]+\/index\.d\.ts$/.exec(normalized)) await this.ensureTypesPackageJson(normalized);
1077
1102
  if (normalized.includes("node_modules/@types/react/index.d.ts")) await this.patchReactTypes(destination);
1078
1103
  }
1079
1104
  async ensureTypesPackageJson(normalizedPath) {
1080
- const pkgMatch = normalizedPath.match(/node_modules\/(@types\/[^\/]+)\//);
1105
+ const pkgMatch = /node_modules\/(@types\/[^/]+)\//.exec(normalizedPath);
1081
1106
  if (!pkgMatch) return;
1082
1107
  const pkgName = pkgMatch[1];
1083
1108
  const pkgDir = path.join(this.projectDir, "node_modules", pkgName);
@@ -1089,16 +1114,7 @@ var Installer = class {
1089
1114
  const version$1 = npmData["dist-tags"]?.latest;
1090
1115
  if (!version$1 || !npmData.versions?.[version$1]) return;
1091
1116
  const pkg = npmData.versions[version$1];
1092
- if (pkg.exports && typeof pkg.exports === "object") {
1093
- const fixExport = (value) => {
1094
- if (typeof value === "string") return { types: value.replace(/\.js$/, ".d.ts").replace(/\.cjs$/, ".d.cts") };
1095
- if (value && typeof value === "object") {
1096
- if ((value.import || value.require) && !value.types) value.types = (value.import || value.require).replace(/\.js$/, ".d.ts").replace(/\.cjs$/, ".d.cts");
1097
- }
1098
- return value;
1099
- };
1100
- for (const key of Object.keys(pkg.exports)) pkg.exports[key] = fixExport(pkg.exports[key]);
1101
- }
1117
+ if (pkg.exports) for (const key of Object.keys(pkg.exports)) pkg.exports[key] = fixExportTypes(pkg.exports[key]);
1102
1118
  await fs.mkdir(pkgDir, { recursive: true });
1103
1119
  await fs.writeFile(pkgJsonPath, JSON.stringify(pkg, null, 2));
1104
1120
  } catch {}
@@ -1108,7 +1124,7 @@ var Installer = class {
1108
1124
  let content = await fs.readFile(destination, "utf-8");
1109
1125
  if (content.includes("function useRef<T = undefined>()")) return;
1110
1126
  const overloadPattern = /function useRef<T>\(initialValue: T \| undefined\): RefObject<T \| undefined>;/;
1111
- if (!overloadPattern.test(content)) return;
1127
+ if (!content.includes("function useRef<T>(initialValue: T | undefined)")) return;
1112
1128
  content = content.replace(overloadPattern, `function useRef<T>(initialValue: T | undefined): RefObject<T | undefined>;
1113
1129
  function useRef<T = undefined>(): MutableRefObject<T | undefined>;`);
1114
1130
  await fs.writeFile(destination, content, "utf-8");
@@ -1248,11 +1264,24 @@ declare module "*.json"
1248
1264
  }));
1249
1265
  }
1250
1266
  };
1267
+ /**
1268
+ * Transform package.json exports to include .d.ts type paths
1269
+ */
1270
+ function fixExportTypes(value) {
1271
+ if (typeof value === "string") return { types: value.replace(/\.js$/, ".d.ts").replace(/\.cjs$/, ".d.cts") };
1272
+ if ((value.import ?? value.require) && !value.types) value.types = (value.import ?? value.require)?.replace(/\.js$/, ".d.ts").replace(/\.cjs$/, ".d.cts");
1273
+ return value;
1274
+ }
1251
1275
  async function fetchWithRetry(url, init, retries = MAX_FETCH_RETRIES) {
1252
- const urlString = typeof url === "string" ? url : url.toString();
1276
+ let urlString;
1277
+ if (typeof url === "string") urlString = url;
1278
+ else if (url instanceof URL) urlString = url.href;
1279
+ else urlString = url.url;
1253
1280
  for (let attempt = 1; attempt <= retries; attempt++) {
1254
1281
  const controller = new AbortController();
1255
- const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
1282
+ const timeout = setTimeout(() => {
1283
+ controller.abort();
1284
+ }, FETCH_TIMEOUT_MS);
1256
1285
  try {
1257
1286
  const response = await fetch(url, {
1258
1287
  ...init,
@@ -1260,12 +1289,13 @@ async function fetchWithRetry(url, init, retries = MAX_FETCH_RETRIES) {
1260
1289
  });
1261
1290
  clearTimeout(timeout);
1262
1291
  return response;
1263
- } catch (error$1) {
1292
+ } catch (err) {
1264
1293
  clearTimeout(timeout);
1265
- const isRetryable = error$1?.cause?.code === "ECONNRESET" || error$1?.cause?.code === "ETIMEDOUT" || error$1?.cause?.code === "UND_ERR_CONNECT_TIMEOUT" || error$1?.message?.includes("timeout");
1294
+ const error$1 = err;
1295
+ const isRetryable = error$1.cause?.code === "ECONNRESET" || error$1.cause?.code === "ETIMEDOUT" || error$1.cause?.code === "UND_ERR_CONNECT_TIMEOUT" || error$1.message.includes("timeout");
1266
1296
  if (attempt < retries && isRetryable) {
1267
1297
  const delay = attempt * 1e3;
1268
- warn(`Fetch failed (${error$1?.cause?.code || error$1?.message}) for ${urlString}, retrying in ${delay}ms...`);
1298
+ warn(`Fetch failed (${error$1.cause?.code ?? error$1.message}) for ${urlString}, retrying in ${delay}ms...`);
1269
1299
  await new Promise((resolve) => setTimeout(resolve, delay));
1270
1300
  continue;
1271
1301
  }
@@ -1397,11 +1427,12 @@ var FileMetadataCache = class {
1397
1427
  if (this.pendingPersist) await this.pendingPersist;
1398
1428
  }
1399
1429
  schedulePersist() {
1400
- if (!this.projectDir) return;
1401
- if (!this.pendingPersist) this.pendingPersist = (async () => {
1430
+ const projectDir = this.projectDir;
1431
+ if (!projectDir) return;
1432
+ this.pendingPersist ??= (async () => {
1402
1433
  try {
1403
1434
  await Promise.resolve();
1404
- await savePersistedState(this.projectDir, this.persisted);
1435
+ await savePersistedState(projectDir, this.persisted);
1405
1436
  } finally {
1406
1437
  this.pendingPersist = null;
1407
1438
  }
@@ -1420,12 +1451,24 @@ var PluginDisconnectedError = class extends Error {
1420
1451
  var UserActionCoordinator = class {
1421
1452
  pendingActions = /* @__PURE__ */ new Map();
1422
1453
  /**
1454
+ * Register a pending action and return a typed promise
1455
+ */
1456
+ awaitAction(actionId, description) {
1457
+ return new Promise((resolve, reject) => {
1458
+ this.pendingActions.set(actionId, {
1459
+ resolve,
1460
+ reject
1461
+ });
1462
+ debug(`Awaiting ${description}: ${actionId}`);
1463
+ });
1464
+ }
1465
+ /**
1423
1466
  * Sends the delete request to the plugin and awaits the user's decision
1424
1467
  */
1425
1468
  async requestDeleteDecision(socket, { fileName, requireConfirmation }) {
1426
1469
  if (!socket) throw new Error("Cannot request delete decision: plugin not connected");
1427
1470
  if (requireConfirmation) {
1428
- const confirmationPromise = this.awaitConfirmation(`delete:${fileName}`, "delete confirmation");
1471
+ const confirmationPromise = this.awaitAction(`delete:${fileName}`, "delete confirmation");
1429
1472
  await sendMessage(socket, {
1430
1473
  type: "file-delete",
1431
1474
  fileNames: [fileName],
@@ -1456,7 +1499,7 @@ var UserActionCoordinator = class {
1456
1499
  if (conflicts.length === 0) return /* @__PURE__ */ new Map();
1457
1500
  const pending = conflicts.map((conflict) => ({
1458
1501
  fileName: conflict.fileName,
1459
- promise: this.awaitConfirmation(`conflict:${conflict.fileName}`, "conflict resolution")
1502
+ promise: this.awaitAction(`conflict:${conflict.fileName}`, "conflict resolution")
1460
1503
  }));
1461
1504
  await sendMessage(socket, {
1462
1505
  type: "conflicts-detected",
@@ -1474,18 +1517,6 @@ var UserActionCoordinator = class {
1474
1517
  }
1475
1518
  }
1476
1519
  /**
1477
- * Generic confirmation awaiter
1478
- */
1479
- awaitConfirmation(actionId, description) {
1480
- return new Promise((resolve, reject) => {
1481
- this.pendingActions.set(actionId, {
1482
- resolve,
1483
- reject
1484
- });
1485
- debug(`Awaiting ${description}: ${actionId}`);
1486
- });
1487
- }
1488
- /**
1489
1520
  * Handle incoming confirmation response
1490
1521
  */
1491
1522
  handleConfirmation(actionId, value) {
@@ -2189,14 +2220,16 @@ async function executeEffect(effect, context) {
2189
2220
  status("Watching for changes...");
2190
2221
  return [];
2191
2222
  }
2192
- case "LOG":
2193
- ({
2223
+ case "LOG": {
2224
+ const logFn = {
2194
2225
  info,
2195
2226
  warn,
2196
2227
  success,
2197
2228
  debug
2198
- }[effect.level] ?? debug)(effect.message);
2229
+ }[effect.level];
2230
+ logFn(effect.message);
2199
2231
  return [];
2232
+ }
2200
2233
  }
2201
2234
  }
2202
2235
  /**
@@ -2236,7 +2269,7 @@ async function start(config) {
2236
2269
  }
2237
2270
  }
2238
2271
  const connection = await initConnection(config.port);
2239
- connection.on("handshake", async (client, message) => {
2272
+ connection.on("handshake", (client, message) => {
2240
2273
  debug(`Received handshake: ${message.projectName} (${message.projectId})`);
2241
2274
  const expectedShort = shortProjectHash(config.projectHash);
2242
2275
  const receivedShort = shortProjectHash(message.projectId);
@@ -2245,24 +2278,26 @@ async function start(config) {
2245
2278
  client.close();
2246
2279
  return;
2247
2280
  }
2248
- await processEvent({
2249
- type: "HANDSHAKE",
2250
- socket: client,
2251
- projectInfo: {
2252
- projectId: message.projectId,
2253
- projectName: message.projectName
2254
- }
2255
- });
2256
- if (config.projectDir && !installer) {
2257
- installer = new Installer({
2258
- projectDir: config.projectDir,
2259
- allowUnsupportedNpm: config.allowUnsupportedNpm
2281
+ (async () => {
2282
+ await processEvent({
2283
+ type: "HANDSHAKE",
2284
+ socket: client,
2285
+ projectInfo: {
2286
+ projectId: message.projectId,
2287
+ projectName: message.projectName
2288
+ }
2260
2289
  });
2261
- await installer.initialize();
2262
- startWatcher();
2263
- }
2264
- cancelDisconnectMessage();
2265
- if (!wasRecentlyDisconnected() && !didShowDisconnect()) success(`Connected to ${message.projectName}`);
2290
+ if (config.projectDir && !installer) {
2291
+ installer = new Installer({
2292
+ projectDir: config.projectDir,
2293
+ allowUnsupportedNpm: config.allowUnsupportedNpm
2294
+ });
2295
+ await installer.initialize();
2296
+ startWatcher();
2297
+ }
2298
+ cancelDisconnectMessage();
2299
+ if (!wasRecentlyDisconnected() && !didShowDisconnect()) success(`Connected to ${message.projectName}`);
2300
+ })();
2266
2301
  });
2267
2302
  async function handleMessage(message) {
2268
2303
  if (!config.projectDir || !installer) {
@@ -2340,21 +2375,25 @@ async function start(config) {
2340
2375
  warn(`Unhandled message type: ${message.type}`);
2341
2376
  return;
2342
2377
  }
2343
- if (event) await processEvent(event);
2378
+ await processEvent(event);
2344
2379
  }
2345
- connection.on("message", async (message) => {
2346
- try {
2347
- await handleMessage(message);
2348
- } catch (err) {
2349
- error("Error handling message:", err);
2350
- }
2380
+ connection.on("message", (message) => {
2381
+ (async () => {
2382
+ try {
2383
+ await handleMessage(message);
2384
+ } catch (err) {
2385
+ error("Error handling message:", err);
2386
+ }
2387
+ })();
2351
2388
  });
2352
- connection.on("disconnect", async () => {
2389
+ connection.on("disconnect", () => {
2353
2390
  scheduleDisconnectMessage(() => {
2354
2391
  status("Disconnected, waiting to reconnect...");
2355
2392
  });
2356
- await processEvent({ type: "DISCONNECT" });
2357
- userActions.cleanup();
2393
+ (async () => {
2394
+ await processEvent({ type: "DISCONNECT" });
2395
+ userActions.cleanup();
2396
+ })();
2358
2397
  });
2359
2398
  connection.on("error", (err) => {
2360
2399
  error("Error on WebSocket connection:", err);
@@ -2363,19 +2402,21 @@ async function start(config) {
2363
2402
  const startWatcher = () => {
2364
2403
  if (!config.filesDir || watcher) return;
2365
2404
  watcher = initWatcher(config.filesDir);
2366
- watcher.on("change", async (event) => {
2367
- await processEvent({
2405
+ watcher.on("change", (event) => {
2406
+ processEvent({
2368
2407
  type: "WATCHER_EVENT",
2369
2408
  event
2370
2409
  });
2371
2410
  });
2372
2411
  };
2373
- process.on("SIGINT", async () => {
2412
+ process.on("SIGINT", () => {
2374
2413
  console.log();
2375
2414
  status("Shutting down...");
2376
- if (watcher) await watcher.close();
2377
- connection.close();
2378
- process.exit(0);
2415
+ (async () => {
2416
+ if (watcher) await watcher.close();
2417
+ connection.close();
2418
+ process.exit(0);
2419
+ })();
2379
2420
  });
2380
2421
  }
2381
2422
 
@@ -2392,7 +2433,7 @@ const program = new Command();
2392
2433
  program.exitOverride((err) => {
2393
2434
  if (err.code === "commander.missingArgument") {
2394
2435
  console.error("Missing Project ID. Copy command via Code Link Plugin.");
2395
- process.exit(err.exitCode ?? 1);
2436
+ process.exit(err.exitCode);
2396
2437
  }
2397
2438
  throw err;
2398
2439
  });
@@ -2406,7 +2447,6 @@ program.name("framer-code-link").description("Sync Framer code components to you
2406
2447
  process.exit(1);
2407
2448
  }
2408
2449
  }
2409
- const isDev = process.env.NODE_ENV === "development";
2410
2450
  if (options.logLevel) {
2411
2451
  const level = {
2412
2452
  debug: LogLevel.DEBUG,
@@ -2415,7 +2455,7 @@ program.name("framer-code-link").description("Sync Framer code components to you
2415
2455
  error: LogLevel.ERROR
2416
2456
  }[options.logLevel.toLowerCase()];
2417
2457
  if (level !== void 0) setLogLevel(level);
2418
- } else if (options.verbose || isDev) setLogLevel(LogLevel.DEBUG);
2458
+ } else if (options.verbose) setLogLevel(LogLevel.DEBUG);
2419
2459
  const port = getPortFromHash(projectHash);
2420
2460
  banner(version, port);
2421
2461
  const config = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "framer-code-link",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "CLI tool for syncing Framer code components - controller-centric architecture",
5
5
  "main": "dist/index.mjs",
6
6
  "type": "module",