framer-code-link 0.2.3 → 0.2.5

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 +52 -9
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -117,6 +117,7 @@ let LogLevel = /* @__PURE__ */ function(LogLevel$1) {
117
117
  let currentLevel = LogLevel.INFO;
118
118
  let lastMessage = "";
119
119
  let lastMessageCount = 0;
120
+ let lastWasFileSync = false;
120
121
  const CLEAR_LINE = "\x1B[2K";
121
122
  const MOVE_CURSOR_UP = "\x1B[1A";
122
123
  function rewriteLastLine(text) {
@@ -144,12 +145,14 @@ function flushDedupe() {
144
145
  /**
145
146
  * Log with deduplication - repeated messages within window get counted
146
147
  */
147
- function logWithDedupe(message, writer) {
148
+ function logWithDedupe(message, writer, isFileSync = false) {
148
149
  if (message === lastMessage) {
149
150
  lastMessageCount++;
150
151
  dedupeMessage(message, lastMessageCount);
151
152
  return;
152
153
  }
154
+ if (isFileSync && !lastWasFileSync) console.log();
155
+ lastWasFileSync = isFileSync;
153
156
  lastMessage = message;
154
157
  lastMessageCount = 1;
155
158
  writer();
@@ -215,19 +218,19 @@ function success(message, ...args) {
215
218
  function fileDown(fileName) {
216
219
  if (currentLevel <= LogLevel.INFO) {
217
220
  const msg = ` ${import_picocolors.default.blue("↓")} ${fileName}`;
218
- logWithDedupe(msg, () => console.log(msg));
221
+ logWithDedupe(msg, () => console.log(msg), true);
219
222
  }
220
223
  }
221
224
  function fileUp(fileName) {
222
225
  if (currentLevel <= LogLevel.INFO) {
223
226
  const msg = ` ${import_picocolors.default.green("↑")} ${fileName}`;
224
- logWithDedupe(msg, () => console.log(msg));
227
+ logWithDedupe(msg, () => console.log(msg), true);
225
228
  }
226
229
  }
227
230
  function fileDelete(fileName) {
228
231
  if (currentLevel <= LogLevel.INFO) {
229
232
  const msg = ` ${import_picocolors.default.red("×")} ${fileName}`;
230
- logWithDedupe(msg, () => console.log(msg));
233
+ logWithDedupe(msg, () => console.log(msg), true);
231
234
  }
232
235
  }
233
236
  /**
@@ -1083,15 +1086,31 @@ const REACT_DOM_TYPES_VERSION = "18.3.1";
1083
1086
  const CORE_LIBRARIES = ["framer-motion", "framer"];
1084
1087
  const JSON_EXTENSION_REGEX = /\.json$/i;
1085
1088
  /**
1089
+ * Packages that are officially supported for type acquisition.
1090
+ * Use --unsupported-npm flag to allow other packages.
1091
+ */
1092
+ const SUPPORTED_PACKAGES = new Set([
1093
+ "framer",
1094
+ "framer-motion",
1095
+ "react",
1096
+ "@types/react",
1097
+ "eventemitter3",
1098
+ "csstype",
1099
+ "motion-dom",
1100
+ "motion-utils"
1101
+ ]);
1102
+ /**
1086
1103
  * Installer class for managing automatic type acquisition.
1087
1104
  */
1088
1105
  var Installer = class {
1089
1106
  projectDir;
1107
+ allowUnsupportedNpm;
1090
1108
  ata;
1091
1109
  processedImports = /* @__PURE__ */ new Set();
1092
1110
  initializationPromise = null;
1093
1111
  constructor(config) {
1094
1112
  this.projectDir = config.projectDir;
1113
+ this.allowUnsupportedNpm = config.allowUnsupportedNpm ?? false;
1095
1114
  const seenPackages = /* @__PURE__ */ new Set();
1096
1115
  this.ata = setupTypeAcquisition({
1097
1116
  projectName: "framer-code-link",
@@ -1174,18 +1193,37 @@ var Installer = class {
1174
1193
  });
1175
1194
  }
1176
1195
  async processImports(fileName, content) {
1177
- const imports = extractImports(content).filter((imp) => imp.type === "npm");
1196
+ const allImports = extractImports(content).filter((imp) => imp.type === "npm");
1197
+ if (allImports.length === 0) return;
1198
+ const imports = this.allowUnsupportedNpm ? allImports : allImports.filter((imp) => this.isSupportedPackage(imp.name));
1199
+ if (allImports.length - imports.length > 0 && !this.allowUnsupportedNpm) debug(`Skipping unsupported packages: ${allImports.filter((imp) => !this.isSupportedPackage(imp.name)).map((imp) => imp.name).join(", ")} (use --unsupported-npm to enable)`);
1178
1200
  if (imports.length === 0) return;
1179
1201
  const hash = imports.map((imp) => imp.name).sort().join(",");
1180
1202
  if (this.processedImports.has(hash)) return;
1181
1203
  this.processedImports.add(hash);
1182
1204
  debug(`Processing imports for ${fileName} (${imports.length} packages)`);
1205
+ const filteredContent = this.allowUnsupportedNpm ? content : this.buildFilteredImports(imports);
1183
1206
  try {
1184
- await this.ata(content);
1207
+ await this.ata(filteredContent);
1185
1208
  } catch (err) {
1186
1209
  warn(`ATA failed for ${fileName}`, err);
1187
1210
  }
1188
1211
  }
1212
+ /**
1213
+ * Check if a package is in the supported list.
1214
+ * Also checks for subpath imports (e.g., "framer/build" -> "framer")
1215
+ */
1216
+ isSupportedPackage(pkgName) {
1217
+ if (SUPPORTED_PACKAGES.has(pkgName)) return true;
1218
+ const basePkg = pkgName.startsWith("@") ? pkgName.split("/").slice(0, 2).join("/") : pkgName.split("/")[0];
1219
+ return SUPPORTED_PACKAGES.has(basePkg);
1220
+ }
1221
+ /**
1222
+ * Build synthetic import statements for ATA from filtered imports
1223
+ */
1224
+ buildFilteredImports(imports) {
1225
+ return imports.map((imp) => `import "${imp.name}";`).join("\n");
1226
+ }
1189
1227
  async writeTypeFile(receivedPath, code) {
1190
1228
  const normalized = receivedPath.replace(/^\//, "");
1191
1229
  const destination = path.join(this.projectDir, normalized);
@@ -2109,7 +2147,8 @@ function transition(state, event) {
2109
2147
  name: conflict.fileName,
2110
2148
  content: conflict.remoteContent,
2111
2149
  modifiedAt: conflict.remoteModifiedAt ?? Date.now()
2112
- }]
2150
+ }],
2151
+ silent: true
2113
2152
  });
2114
2153
  }
2115
2154
  if (remainingConflicts.length > 0) {
@@ -2379,7 +2418,10 @@ async function start(config) {
2379
2418
  }
2380
2419
  });
2381
2420
  if (config.projectDir && !installer) {
2382
- installer = new Installer({ projectDir: config.projectDir });
2421
+ installer = new Installer({
2422
+ projectDir: config.projectDir,
2423
+ allowUnsupportedNpm: config.allowUnsupportedNpm
2424
+ });
2383
2425
  await installer.initialize();
2384
2426
  startWatcher();
2385
2427
  }
@@ -2519,7 +2561,7 @@ program.exitOverride((err) => {
2519
2561
  }
2520
2562
  throw err;
2521
2563
  });
2522
- program.name("framer-code-link").description("Sync Framer code components to your local filesystem").version("0.1.0").argument("[projectHash]", "Framer Project ID Hash (auto-detected from package.json if omitted)").option("-n, --name <name>", "Project name (optional)").option("-d, --dir <directory>", "Explicit project directory").option("-v, --verbose", "Enable verbose logging").option("--log-level <level>", "Set log level (debug, info, warn, error)").option("--dangerously-auto-delete", "Automatically delete remote files without confirmation").action(async (projectHash, options) => {
2564
+ program.name("framer-code-link").description("Sync Framer code components to your local filesystem").version("0.1.0").argument("[projectHash]", "Framer Project ID Hash (auto-detected from package.json if omitted)").option("-n, --name <name>", "Project name (optional)").option("-d, --dir <directory>", "Explicit project directory").option("-v, --verbose", "Enable verbose logging").option("--log-level <level>", "Set log level (debug, info, warn, error)").option("--dangerously-auto-delete", "Automatically delete remote files without confirmation").option("--unsupported-npm", "Allow type acquisition for unsupported npm packages").action(async (projectHash, options) => {
2523
2565
  if (!projectHash) {
2524
2566
  const detected = await getProjectHashFromCwd();
2525
2567
  if (detected) projectHash = detected;
@@ -2547,6 +2589,7 @@ program.name("framer-code-link").description("Sync Framer code components to you
2547
2589
  projectDir: null,
2548
2590
  filesDir: null,
2549
2591
  dangerouslyAutoDelete: options.dangerouslyAutoDelete ?? false,
2592
+ allowUnsupportedNpm: options.unsupportedNpm ?? false,
2550
2593
  explicitDir: options.dir,
2551
2594
  explicitName: options.name
2552
2595
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "framer-code-link",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "CLI tool for syncing Framer code components - controller-centric architecture",
5
5
  "main": "dist/index.mjs",
6
6
  "type": "module",