framer-code-link 0.10.1 → 0.12.0

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 +51 -28
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -1262,7 +1262,8 @@ var Installer = class {
1262
1262
  this.ensurePrettierConfig(),
1263
1263
  this.ensureFramerDeclarations(),
1264
1264
  this.ensurePackageJson(),
1265
- this.ensureSkills()
1265
+ this.ensureSkills(),
1266
+ this.ensureGitignore()
1266
1267
  ]);
1267
1268
  Promise.resolve().then(async () => {
1268
1269
  await this.ensureReact18Types();
@@ -1416,6 +1417,27 @@ declare module "*.json"
1416
1417
  async ensureSkills() {
1417
1418
  await installSkills(this.projectDir);
1418
1419
  }
1420
+ async ensureGitignore() {
1421
+ const gitignorePath = path.join(this.projectDir, ".gitignore");
1422
+ try {
1423
+ await fs.access(gitignorePath);
1424
+ debug(".gitignore already exists");
1425
+ return;
1426
+ } catch {}
1427
+ const content = [
1428
+ "node_modules/",
1429
+ "",
1430
+ "# Framer Code Link",
1431
+ ".framer-sync-state.json",
1432
+ ".skills/",
1433
+ ".agents/skills/",
1434
+ ".claude/skills/",
1435
+ ".cursor/skills/",
1436
+ ""
1437
+ ].join("\n");
1438
+ await fs.writeFile(gitignorePath, content);
1439
+ debug("Created .gitignore");
1440
+ }
1419
1441
  async ensureReact18Types() {
1420
1442
  const reactTypesDir = path.join(this.projectDir, "node_modules/@types/react");
1421
1443
  const reactFiles = [
@@ -1877,8 +1899,8 @@ function hashContent(content) {
1877
1899
  function toPackageName(name) {
1878
1900
  return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/^-+|-+$/g, "").replace(/-+/g, "-");
1879
1901
  }
1880
- function toDirName(name) {
1881
- return name.replace(/[^a-zA-Z0-9- ]/g, "-").replace(/^[-\s]+|[-\s]+$/g, "").replace(/-+/g, "-");
1902
+ function toDirectoryName(name) {
1903
+ return name.replace(/[^a-zA-Z0-9-]/g, "-").replace(/^-+|-+$/g, "").replace(/-+/g, "-");
1882
1904
  }
1883
1905
  async function getProjectHashFromCwd() {
1884
1906
  try {
@@ -1889,27 +1911,27 @@ async function getProjectHashFromCwd() {
1889
1911
  return null;
1890
1912
  }
1891
1913
  }
1892
- async function findOrCreateProjectDir(projectHash, projectName, explicitDir) {
1893
- if (explicitDir) {
1894
- const resolved = path.resolve(explicitDir);
1914
+ async function findOrCreateProjectDirectory(projectHash, projectName, explicitDirectory) {
1915
+ if (explicitDirectory) {
1916
+ const resolved = path.resolve(explicitDirectory);
1895
1917
  await fs.mkdir(path.join(resolved, "files"), { recursive: true });
1896
1918
  return {
1897
- dir: resolved,
1919
+ directory: resolved,
1898
1920
  created: false
1899
1921
  };
1900
1922
  }
1901
1923
  const cwd = process.cwd();
1902
- const existing = await findExistingProjectDir(cwd, projectHash);
1924
+ const existing = await findExistingProjectDirectory(cwd, projectHash);
1903
1925
  if (existing) return {
1904
- dir: existing,
1926
+ directory: existing,
1905
1927
  created: false
1906
1928
  };
1907
1929
  if (!projectName) throw new Error("Failed to get Project name. Pass --name <project name>.");
1908
- const dirName = toDirName(projectName);
1930
+ const directoryName = toDirectoryName(projectName);
1909
1931
  const pkgName = toPackageName(projectName);
1910
1932
  const shortId = shortProjectHash(projectHash);
1911
- const projectDir = path.join(cwd, dirName || shortId);
1912
- await fs.mkdir(path.join(projectDir, "files"), { recursive: true });
1933
+ const projectDirectory = path.join(cwd, directoryName || shortId);
1934
+ await fs.mkdir(path.join(projectDirectory, "files"), { recursive: true });
1913
1935
  const pkg = {
1914
1936
  name: pkgName || shortId,
1915
1937
  version: "1.0.0",
@@ -1917,19 +1939,19 @@ async function findOrCreateProjectDir(projectHash, projectName, explicitDir) {
1917
1939
  shortProjectHash: shortId,
1918
1940
  framerProjectName: projectName
1919
1941
  };
1920
- await fs.writeFile(path.join(projectDir, "package.json"), JSON.stringify(pkg, null, 2));
1942
+ await fs.writeFile(path.join(projectDirectory, "package.json"), JSON.stringify(pkg, null, 2));
1921
1943
  return {
1922
- dir: projectDir,
1944
+ directory: projectDirectory,
1923
1945
  created: true
1924
1946
  };
1925
1947
  }
1926
- async function findExistingProjectDir(baseDir, projectHash) {
1927
- if (await matchesProject(path.join(baseDir, "package.json"), projectHash)) return baseDir;
1928
- const entries = await fs.readdir(baseDir, { withFileTypes: true });
1948
+ async function findExistingProjectDirectory(baseDirectory, projectHash) {
1949
+ if (await matchesProject(path.join(baseDirectory, "package.json"), projectHash)) return baseDirectory;
1950
+ const entries = await fs.readdir(baseDirectory, { withFileTypes: true });
1929
1951
  for (const entry of entries) {
1930
1952
  if (!entry.isDirectory()) continue;
1931
- const dir = path.join(baseDir, entry.name);
1932
- if (await matchesProject(path.join(dir, "package.json"), projectHash)) return dir;
1953
+ const directory = path.join(baseDirectory, entry.name);
1954
+ if (await matchesProject(path.join(directory, "package.json"), projectHash)) return directory;
1933
1955
  }
1934
1956
  return null;
1935
1957
  }
@@ -2351,9 +2373,9 @@ async function executeEffect(effect, context) {
2351
2373
  case "INIT_WORKSPACE":
2352
2374
  if (!config.projectDir) {
2353
2375
  const projectName = config.explicitName ?? effect.projectInfo.projectName;
2354
- const result = await findOrCreateProjectDir(config.projectHash, projectName, config.explicitDir);
2355
- config.projectDir = result.dir;
2356
- config.projectDirCreated = result.created;
2376
+ const directoryInfo = await findOrCreateProjectDirectory(config.projectHash, projectName, config.explicitDirectory);
2377
+ config.projectDir = directoryInfo.directory;
2378
+ config.projectDirCreated = directoryInfo.created;
2357
2379
  config.filesDir = `${config.projectDir}/files`;
2358
2380
  debug(`Files directory: ${config.filesDir}`);
2359
2381
  await fs.mkdir(config.filesDir, { recursive: true });
@@ -2505,11 +2527,12 @@ async function executeEffect(effect, context) {
2505
2527
  resetDisconnectState();
2506
2528
  return [];
2507
2529
  }
2508
- const relativeDir = config.projectDir ? "./" + (path.relative(process.cwd(), config.projectDir) || ".") : null;
2509
- if (effect.totalCount === 0 && relativeDir) if (config.projectDirCreated) success(`Created ${relativeDir} folder`);
2510
- else success(`Syncing to ${relativeDir} folder`);
2511
- else if (relativeDir && config.projectDirCreated) success(`Synced into ${relativeDir} (${effect.updatedCount} files added)`);
2512
- else if (relativeDir) success(`Synced into ${relativeDir} (${effect.updatedCount} files updated, ${effect.unchangedCount} unchanged)`);
2530
+ const relative = config.projectDir ? path.relative(process.cwd(), config.projectDir) : null;
2531
+ const relativeDirectory = relative != null ? relative ? "./" + relative : "." : null;
2532
+ if (effect.totalCount === 0 && relativeDirectory) if (config.projectDirCreated) success(`Created ${relativeDirectory} folder`);
2533
+ else success(`Syncing to ${relativeDirectory} folder`);
2534
+ else if (relativeDirectory && config.projectDirCreated) success(`Synced into ${relativeDirectory} (${effect.updatedCount} files added)`);
2535
+ else if (relativeDirectory) success(`Synced into ${relativeDirectory} (${effect.updatedCount} files updated, ${effect.unchangedCount} unchanged)`);
2513
2536
  else success(`Synced ${effect.totalCount} files (${effect.updatedCount} updated, ${effect.unchangedCount} unchanged)`);
2514
2537
  status("Watching for changes...");
2515
2538
  return [];
@@ -2757,7 +2780,7 @@ program.name("framer-code-link").description("Sync Framer code components to you
2757
2780
  filesDir: null,
2758
2781
  dangerouslyAutoDelete: options.dangerouslyAutoDelete ?? false,
2759
2782
  allowUnsupportedNpm: options.unsupportedNpm ?? false,
2760
- explicitDir: options.dir,
2783
+ explicitDirectory: options.dir,
2761
2784
  explicitName: options.name
2762
2785
  };
2763
2786
  if (config.dangerouslyAutoDelete) warn("Auto-delete mode enabled - files will be deleted without confirmation");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "framer-code-link",
3
- "version": "0.10.1",
3
+ "version": "0.12.0",
4
4
  "description": "CLI tool for syncing Framer code components - controller-centric architecture",
5
5
  "main": "dist/index.mjs",
6
6
  "type": "module",