framer-code-link 0.4.6 → 0.4.8

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 +28 -25
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -156,6 +156,13 @@ function normalizePath$1(filePath) {
156
156
  if (isAbsolute) return `/${normalized}`;
157
157
  return normalized;
158
158
  }
159
+ function normalizeCodeFilePath(filePath) {
160
+ const normalized = normalizePath$1(filePath);
161
+ return normalized.startsWith("/") ? normalized.slice(1) : normalized;
162
+ }
163
+ function canonicalFileName(filePath) {
164
+ return normalizeCodeFilePath(filePath);
165
+ }
159
166
  function sanitizeFilePath(input, capitalizeReactComponent = true) {
160
167
  const trimmed = input.trim();
161
168
  const [inputName, extension] = splitExtension(filename(trimmed));
@@ -174,6 +181,13 @@ function isSupportedExtension$1(filePath) {
174
181
  return /\.(tsx?|jsx?|json)$/i.test(filePath);
175
182
  }
176
183
  /**
184
+ * Returns a normalized, lowercase key for case-insensitive file lookups.
185
+ * Use this for Map keys on operating systems where "File.tsx" and "file.tsx" are the same file.
186
+ */
187
+ function fileKeyForLookup(filePath) {
188
+ return canonicalFileName(filePath).toLowerCase();
189
+ }
190
+ /**
177
191
  * Pluralize a word based on count
178
192
  * @example pluralize(1, "file") => "1 file"
179
193
  * @example pluralize(3, "file") => "3 files"
@@ -712,11 +726,7 @@ const SUPPORTED_EXTENSIONS = [
712
726
  ".json"
713
727
  ];
714
728
  const DEFAULT_EXTENSION = ".tsx";
715
- const DEFAULT_REMOTE_DRIFT_MS = 2500;
716
- /** Normalize file name for case-insensitive comparison (macOS/Windows compat) */
717
- function normalizeForComparison(fileName) {
718
- return fileName.toLowerCase();
719
- }
729
+ const DEFAULT_REMOTE_DRIFT_MS = 2e3;
720
730
  /**
721
731
  * Lists all supported files in the files directory
722
732
  */
@@ -759,17 +769,17 @@ async function detectConflicts(remoteFiles, filesDir, options = {}) {
759
769
  const detect = options.detectConflicts ?? true;
760
770
  const preferRemote = options.preferRemote ?? false;
761
771
  const persistedState = options.persistedState;
762
- const getPersistedState = (fileName) => persistedState?.get(normalizeForComparison(fileName));
772
+ const getPersistedState = (fileName) => persistedState?.get(fileKeyForLookup(fileName));
763
773
  debug(`Detecting conflicts for ${String(remoteFiles.length)} remote files`);
764
774
  const localFiles = await listFiles(filesDir);
765
- const localFileMap = new Map(localFiles.map((f) => [normalizeForComparison(f.name), f]));
775
+ const localFileMap = new Map(localFiles.map((f) => [fileKeyForLookup(f.name), f]));
766
776
  const remoteFileMap = new Map(remoteFiles.map((f) => {
767
- return [normalizeForComparison(resolveRemoteReference(filesDir, f.name).relativePath), f];
777
+ return [fileKeyForLookup(resolveRemoteReference(filesDir, f.name).relativePath), f];
768
778
  }));
769
779
  const processedFiles = /* @__PURE__ */ new Set();
770
780
  for (const remote of remoteFiles) {
771
781
  const normalized = resolveRemoteReference(filesDir, remote.name);
772
- const normalizedKey = normalizeForComparison(normalized.relativePath);
782
+ const normalizedKey = fileKeyForLookup(normalized.relativePath);
773
783
  const local = localFileMap.get(normalizedKey);
774
784
  processedFiles.add(normalizedKey);
775
785
  const persisted = getPersistedState(normalized.relativePath);
@@ -820,7 +830,7 @@ async function detectConflicts(remoteFiles, filesDir, options = {}) {
820
830
  });
821
831
  }
822
832
  for (const local of localFiles) {
823
- const localKey = normalizeForComparison(local.name);
833
+ const localKey = fileKeyForLookup(local.name);
824
834
  if (!processedFiles.has(localKey)) {
825
835
  const persisted = getPersistedState(local.name);
826
836
  if (persisted) {
@@ -841,8 +851,8 @@ async function detectConflicts(remoteFiles, filesDir, options = {}) {
841
851
  });
842
852
  }
843
853
  }
844
- if (persistedState) for (const [fileName] of persistedState) {
845
- const normalizedKey = normalizeForComparison(fileName);
854
+ if (persistedState) for (const fileName of persistedState.keys()) {
855
+ const normalizedKey = fileKeyForLookup(fileName);
846
856
  const inLocal = localFileMap.has(normalizedKey);
847
857
  const inRemote = remoteFileMap.has(normalizedKey);
848
858
  if (!inLocal && !inRemote) debug(`[AUTO-RESOLVE] ${fileName}: deleted on both sides, no conflict`);
@@ -1615,13 +1625,6 @@ function initWatcher(filesDir) {
1615
1625
 
1616
1626
  //#endregion
1617
1627
  //#region src/utils/file-metadata-cache.ts
1618
- /**
1619
- * In-memory cache on top of state-persistence.
1620
- */
1621
- /** Normalize file name for case-insensitive lookup (macOS/Windows compat) */
1622
- function normalizeKey(fileName) {
1623
- return fileName.toLowerCase();
1624
- }
1625
1628
  var FileMetadataCache = class {
1626
1629
  metadata = /* @__PURE__ */ new Map();
1627
1630
  persisted = /* @__PURE__ */ new Map();
@@ -1634,7 +1637,7 @@ var FileMetadataCache = class {
1634
1637
  const loaded = await loadPersistedState(projectDir);
1635
1638
  this.persisted = loaded;
1636
1639
  this.metadata = /* @__PURE__ */ new Map();
1637
- for (const [fileName, state] of loaded.entries()) this.metadata.set(normalizeKey(fileName), {
1640
+ for (const [fileName, state] of loaded.entries()) this.metadata.set(fileKeyForLookup(fileName), {
1638
1641
  localHash: state.contentHash,
1639
1642
  lastSyncedHash: state.contentHash,
1640
1643
  lastRemoteTimestamp: state.timestamp
@@ -1642,10 +1645,10 @@ var FileMetadataCache = class {
1642
1645
  this.initialized = true;
1643
1646
  }
1644
1647
  get(fileName) {
1645
- return this.metadata.get(normalizeKey(fileName));
1648
+ return this.metadata.get(fileKeyForLookup(fileName));
1646
1649
  }
1647
1650
  has(fileName) {
1648
- return this.metadata.has(normalizeKey(fileName));
1651
+ return this.metadata.has(fileKeyForLookup(fileName));
1649
1652
  }
1650
1653
  size() {
1651
1654
  return this.metadata.size;
@@ -1654,7 +1657,7 @@ var FileMetadataCache = class {
1654
1657
  return this.persisted;
1655
1658
  }
1656
1659
  recordRemoteWrite(fileName, content, remoteModifiedAt) {
1657
- const key = normalizeKey(fileName);
1660
+ const key = fileKeyForLookup(fileName);
1658
1661
  const contentHash = hashFileContent(content);
1659
1662
  this.metadata.set(key, {
1660
1663
  localHash: contentHash,
@@ -1668,7 +1671,7 @@ var FileMetadataCache = class {
1668
1671
  this.schedulePersist();
1669
1672
  }
1670
1673
  recordSyncedSnapshot(fileName, contentHash, remoteModifiedAt) {
1671
- const key = normalizeKey(fileName);
1674
+ const key = fileKeyForLookup(fileName);
1672
1675
  this.metadata.set(key, {
1673
1676
  localHash: contentHash,
1674
1677
  lastSyncedHash: contentHash,
@@ -1681,7 +1684,7 @@ var FileMetadataCache = class {
1681
1684
  this.schedulePersist();
1682
1685
  }
1683
1686
  recordDelete(fileName) {
1684
- const key = normalizeKey(fileName);
1687
+ const key = fileKeyForLookup(fileName);
1685
1688
  this.metadata.delete(key);
1686
1689
  this.persisted.delete(key);
1687
1690
  this.schedulePersist();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "framer-code-link",
3
- "version": "0.4.6",
3
+ "version": "0.4.8",
4
4
  "description": "CLI tool for syncing Framer code components - controller-centric architecture",
5
5
  "main": "dist/index.mjs",
6
6
  "type": "module",