vectorvesper 1.0.0 → 1.2.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.js +95 -3
  2. package/package.json +4 -1
package/dist/index.js CHANGED
@@ -879,6 +879,65 @@ Using ${component.title || component.name}:`)));
879
879
  }
880
880
  }
881
881
 
882
+ // src/utils/transpile.ts
883
+ function isTsSource(target) {
884
+ return /\.(tsx|ts|mts|cts)$/i.test(target);
885
+ }
886
+ function toJsTarget(target) {
887
+ return target.replace(/\.tsx$/i, ".jsx").replace(/\.mts$/i, ".mjs").replace(/\.cts$/i, ".cjs").replace(/\.ts$/i, ".js");
888
+ }
889
+ async function stripTypes(content, filename) {
890
+ const babelMod = await import("@babel/core");
891
+ const transformAsync = babelMod.transformAsync ?? babelMod.default?.transformAsync;
892
+ if (typeof transformAsync !== "function") {
893
+ throw new Error("@babel/core is not available");
894
+ }
895
+ const presetMod = await import("@babel/preset-typescript");
896
+ const presetTypescript = presetMod.default ?? presetMod;
897
+ const result = await transformAsync(content, {
898
+ filename,
899
+ // .tsx → parse JSX; .ts → treat `<T>` as a generic
900
+ configFile: false,
901
+ babelrc: false,
902
+ comments: true,
903
+ // Only strip types. No JSX/react preset, so JSX is left untouched.
904
+ presets: [presetTypescript]
905
+ });
906
+ if (!result || typeof result.code !== "string") {
907
+ throw new Error("type-stripping produced no output");
908
+ }
909
+ return result.code;
910
+ }
911
+ async function fileToJs(target, content) {
912
+ if (/\.d\.ts$/i.test(target)) return { target, content };
913
+ if (!isTsSource(target)) return { target, content };
914
+ try {
915
+ const code = await stripTypes(content, target);
916
+ return { target: toJsTarget(target), content: code };
917
+ } catch (err) {
918
+ return { target, content, error: err instanceof Error ? err.message : String(err) };
919
+ }
920
+ }
921
+ async function maybeTranspile(components, tsx) {
922
+ if (tsx) return { components, warnings: [] };
923
+ const warnings = [];
924
+ const transpiled = await Promise.all(
925
+ components.map(async (component) => {
926
+ const files = await Promise.all(
927
+ component.files.map(async (file) => {
928
+ const res = await fileToJs(file.target, file.content ?? "");
929
+ if (res.error) {
930
+ warnings.push(`${file.target} kept as TypeScript (${res.error})`);
931
+ }
932
+ return { ...file, target: res.target, content: res.content };
933
+ })
934
+ );
935
+ return { ...component, files };
936
+ })
937
+ );
938
+ return { components: transpiled, warnings };
939
+ }
940
+
882
941
  // src/commands/add.ts
883
942
  async function handleDependencies(components, projectRoot, projectInfo, options) {
884
943
  const missing = getMissingDependencies(components, projectRoot);
@@ -993,6 +1052,18 @@ async function addCommand(slug, options = {}) {
993
1052
  process.exit(1);
994
1053
  return;
995
1054
  }
1055
+ let transpileWarnings = [];
1056
+ if (config.tsx === false) {
1057
+ spinner.text = "Converting to JavaScript...";
1058
+ const t = await maybeTranspile(resolvedComponents, false);
1059
+ resolvedComponents = t.components;
1060
+ transpileWarnings = t.warnings;
1061
+ } else {
1062
+ resolvedComponents = resolvedComponents.map((c) => ({
1063
+ ...c,
1064
+ files: c.files.filter((f) => f.type !== "types")
1065
+ }));
1066
+ }
996
1067
  spinner.text = "Checking file conflicts...";
997
1068
  let planned;
998
1069
  try {
@@ -1091,6 +1162,11 @@ async function addCommand(slug, options = {}) {
1091
1162
  framework: projectInfo.framework,
1092
1163
  hasTailwind: projectInfo.hasTailwind
1093
1164
  });
1165
+ if (transpileWarnings.length > 0) {
1166
+ console.log(pc6.yellow(`
1167
+ \u26A0\uFE0F Some files were kept as TypeScript:`));
1168
+ for (const w of transpileWarnings) console.log(` ${pc6.dim(w)}`);
1169
+ }
1094
1170
  console.log("");
1095
1171
  console.log(pc6.bold(pc6.green(`\u2714 Added ${pc6.cyan(targetComponent.slug)} to ${installPath}`)));
1096
1172
  console.log("");
@@ -1160,16 +1236,27 @@ async function updateCommand(slug, options = {}) {
1160
1236
  const upToDate = [];
1161
1237
  const failed = [];
1162
1238
  const updatedComponents = [];
1239
+ const transpileWarnings = [];
1163
1240
  for (const target of targets) {
1164
1241
  spinner.text = `Updating ${pc7.cyan(target)}...`;
1165
1242
  try {
1166
- const components = await resolveComponentTree(target);
1243
+ let components = await resolveComponentTree(target);
1167
1244
  const remote = components[components.length - 1];
1168
1245
  const localVersion = manifest.components[target]?.version;
1169
1246
  if (localVersion === remote.version && !options.force) {
1170
1247
  upToDate.push(target);
1171
1248
  continue;
1172
1249
  }
1250
+ if (config.tsx === false) {
1251
+ const t = await maybeTranspile(components, false);
1252
+ components = t.components;
1253
+ transpileWarnings.push(...t.warnings);
1254
+ } else {
1255
+ components = components.map((c) => ({
1256
+ ...c,
1257
+ files: c.files.filter((f) => f.type !== "types")
1258
+ }));
1259
+ }
1173
1260
  const planned = planFiles(components, installDir, projectRoot);
1174
1261
  writeFiles(planned.map((f) => ({ absolutePath: f.absolutePath, content: f.content })));
1175
1262
  recordInstall(components, installDir, projectRoot);
@@ -1197,6 +1284,11 @@ async function updateCommand(slug, options = {}) {
1197
1284
  Failed (${failed.length}):`)));
1198
1285
  for (const f of failed) console.log(` ${pc7.red("\u2716")} ${f.slug}: ${pc7.dim(f.reason)}`);
1199
1286
  }
1287
+ if (transpileWarnings.length > 0) {
1288
+ console.log(pc7.yellow(`
1289
+ \u26A0\uFE0F Some files were kept as TypeScript:`));
1290
+ for (const w of transpileWarnings) console.log(` ${pc7.dim(w)}`);
1291
+ }
1200
1292
  console.log("");
1201
1293
  if (updatedComponents.length > 0) {
1202
1294
  await handleDependencies(updatedComponents, projectRoot, projectInfo, options);
@@ -1305,7 +1397,7 @@ Remove ${slug}
1305
1397
  import fs9 from "fs";
1306
1398
  import path9 from "path";
1307
1399
  import pc9 from "picocolors";
1308
- var CLI_VERSION = true ? "1.0.0" : "0.0.0-dev";
1400
+ var CLI_VERSION = true ? "1.2.0" : "0.0.0-dev";
1309
1401
  async function infoCommand() {
1310
1402
  console.log(pc9.bold(pc9.cyan("\nVector Vesper Diagnostics\n")));
1311
1403
  const projectInfo = detectProject();
@@ -1603,7 +1695,7 @@ async function whoamiCommand() {
1603
1695
  }
1604
1696
 
1605
1697
  // src/index.ts
1606
- var version = true ? "1.0.0" : "0.0.0-dev";
1698
+ var version = true ? "1.2.0" : "0.0.0-dev";
1607
1699
  var program = new Command();
1608
1700
  program.name("vv").description("Vector Vesper CLI \u2014 add visual components to your React project").version(version).option("--verbose", "Show detailed debug output").hook("preAction", (thisCommand) => {
1609
1701
  const opts = thisCommand.opts();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vectorvesper",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Add WebGL, React Three Fiber & advanced motion components to your project via CLI.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -46,6 +46,8 @@
46
46
  "test:watch": "vitest"
47
47
  },
48
48
  "dependencies": {
49
+ "@babel/core": "^7.24.0",
50
+ "@babel/preset-typescript": "^7.24.0",
49
51
  "@clack/prompts": "^0.7.0",
50
52
  "commander": "^12.0.0",
51
53
  "ora": "^8.0.1",
@@ -53,6 +55,7 @@
53
55
  "zod": "^3.22.4"
54
56
  },
55
57
  "devDependencies": {
58
+ "@types/babel__core": "^7.20.5",
56
59
  "@types/node": "^25.9.2",
57
60
  "tsup": "^8.0.2",
58
61
  "typescript": "^6.0.3",