@flowgram.ai/cli 0.4.11 → 0.4.13

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.
package/dist/index.cjs CHANGED
@@ -23,35 +23,108 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  ));
24
24
 
25
25
  // src/index.ts
26
+ var import_path10 = __toESM(require("path"), 1);
26
27
  var import_commander = require("commander");
27
28
 
28
- // src/materials/index.ts
29
- var import_inquirer = __toESM(require("inquirer"), 1);
30
- var import_chalk3 = __toESM(require("chalk"), 1);
29
+ // src/update-version/index.ts
30
+ var import_chalk = __toESM(require("chalk"), 1);
31
31
 
32
- // src/materials/materials.ts
33
- var import_path3 = __toESM(require("path"), 1);
34
- var import_fs3 = __toESM(require("fs"), 1);
32
+ // src/utils/npm.ts
33
+ var import_path = __toESM(require("path"), 1);
34
+ var import_https = __toESM(require("https"), 1);
35
+ var import_fs = require("fs");
36
+ var import_child_process = require("child_process");
37
+ var tar = __toESM(require("tar"), 1);
38
+ var import_fs_extra = __toESM(require("fs-extra"), 1);
39
+ var LoadedNpmPkg = class {
40
+ constructor(name, version, path11) {
41
+ this.name = name;
42
+ this.version = version;
43
+ this.path = path11;
44
+ }
45
+ get srcPath() {
46
+ return import_path.default.join(this.path, "src");
47
+ }
48
+ get distPath() {
49
+ return import_path.default.join(this.path, "dist");
50
+ }
51
+ get packageJson() {
52
+ if (!this._packageJson) {
53
+ this._packageJson = JSON.parse((0, import_fs.readFileSync)(import_path.default.join(this.path, "package.json"), "utf8"));
54
+ }
55
+ return this._packageJson;
56
+ }
57
+ get dependencies() {
58
+ return this.packageJson.dependencies;
59
+ }
60
+ };
61
+ function downloadFile(url, dest) {
62
+ return new Promise((resolve, reject) => {
63
+ const file = import_fs_extra.default.createWriteStream(dest);
64
+ import_https.default.get(url, (response) => {
65
+ if (response.statusCode !== 200) {
66
+ reject(new Error(`Download failed: ${response.statusCode}`));
67
+ return;
68
+ }
69
+ response.pipe(file);
70
+ file.on("finish", () => {
71
+ file.close();
72
+ resolve();
73
+ });
74
+ }).on("error", (err) => {
75
+ import_fs_extra.default.unlink(dest, () => reject(err));
76
+ });
77
+ file.on("error", (err) => {
78
+ import_fs_extra.default.unlink(dest, () => reject(err));
79
+ });
80
+ });
81
+ }
82
+ async function getLatestVersion(packageName) {
83
+ return (0, import_child_process.execSync)(`npm view ${packageName} version --tag=latest`).toString().trim();
84
+ }
85
+ async function loadNpm(packageName) {
86
+ const packageLatestVersion = await getLatestVersion(packageName);
87
+ const packagePath = import_path.default.join(__dirname, `./.download/${packageName}-${packageLatestVersion}`);
88
+ if ((0, import_fs.existsSync)(packagePath)) {
89
+ return new LoadedNpmPkg(packageName, packageLatestVersion, packagePath);
90
+ }
91
+ try {
92
+ const tarballUrl = (0, import_child_process.execSync)(`npm view ${packageName}@${packageLatestVersion} dist.tarball`).toString().trim();
93
+ const tempTarballPath = import_path.default.join(
94
+ __dirname,
95
+ `./.download/${packageName}-${packageLatestVersion}.tgz`
96
+ );
97
+ import_fs_extra.default.ensureDirSync(import_path.default.dirname(tempTarballPath));
98
+ await downloadFile(tarballUrl, tempTarballPath);
99
+ import_fs_extra.default.ensureDirSync(packagePath);
100
+ await tar.x({
101
+ file: tempTarballPath,
102
+ cwd: packagePath,
103
+ strip: 1
104
+ });
105
+ import_fs_extra.default.unlinkSync(tempTarballPath);
106
+ return new LoadedNpmPkg(packageName, packageLatestVersion, packagePath);
107
+ } catch (error) {
108
+ console.error(`Error downloading or extracting package: ${error}`);
109
+ throw error;
110
+ }
111
+ }
35
112
 
36
- // src/utils/ts-file.ts
113
+ // src/utils/file.ts
37
114
  var import_path2 = __toESM(require("path"), 1);
38
115
  var import_fs2 = __toESM(require("fs"), 1);
39
-
40
- // src/utils/file.ts
41
- var import_path = __toESM(require("path"), 1);
42
- var import_fs = __toESM(require("fs"), 1);
43
116
  var import_ignore = __toESM(require("ignore"), 1);
44
117
  var File = class {
45
118
  constructor(filePath, root = "/") {
46
119
  this.root = root;
47
120
  this.path = filePath;
48
- this.relativePath = import_path.default.relative(this.root, this.path);
49
- this.suffix = import_path.default.extname(this.path);
50
- if (!import_fs.default.existsSync(this.path)) {
51
- throw Error(`File ${import_path.default} Not Exists`);
121
+ this.relativePath = import_path2.default.relative(this.root, this.path);
122
+ this.suffix = import_path2.default.extname(this.path);
123
+ if (!import_fs2.default.existsSync(this.path)) {
124
+ throw Error(`File ${import_path2.default} Not Exists`);
52
125
  }
53
126
  try {
54
- this.content = import_fs.default.readFileSync(this.path, "utf-8");
127
+ this.content = import_fs2.default.readFileSync(this.path, "utf-8");
55
128
  this.isUtf8 = true;
56
129
  } catch (e) {
57
130
  this.isUtf8 = false;
@@ -64,24 +137,24 @@ var File = class {
64
137
  return;
65
138
  }
66
139
  this.content = updater(this.content);
67
- import_fs.default.writeFileSync(this.path, this.content, "utf-8");
140
+ import_fs2.default.writeFileSync(this.path, this.content, "utf-8");
68
141
  }
69
142
  write(nextContent) {
70
143
  this.content = nextContent;
71
- import_fs.default.writeFileSync(this.path, this.content, "utf-8");
144
+ import_fs2.default.writeFileSync(this.path, this.content, "utf-8");
72
145
  }
73
146
  };
74
147
  function* traverseRecursiveFilePaths(folder, ig = (0, import_ignore.default)().add(".git"), root = folder) {
75
- const files = import_fs.default.readdirSync(folder);
76
- if (import_fs.default.existsSync(import_path.default.join(folder, ".gitignore"))) {
77
- ig.add(import_fs.default.readFileSync(import_path.default.join(folder, ".gitignore"), "utf-8"));
148
+ const files = import_fs2.default.readdirSync(folder);
149
+ if (import_fs2.default.existsSync(import_path2.default.join(folder, ".gitignore"))) {
150
+ ig.add(import_fs2.default.readFileSync(import_path2.default.join(folder, ".gitignore"), "utf-8"));
78
151
  }
79
152
  for (const file of files) {
80
- const filePath = import_path.default.join(folder, file);
81
- if (ig.ignores(import_path.default.relative(root, filePath))) {
153
+ const filePath = import_path2.default.join(folder, file);
154
+ if (ig.ignores(import_path2.default.relative(root, filePath))) {
82
155
  continue;
83
156
  }
84
- if (import_fs.default.statSync(filePath).isDirectory()) {
157
+ if (import_fs2.default.statSync(filePath).isDirectory()) {
85
158
  yield* traverseRecursiveFilePaths(filePath, ig, root);
86
159
  } else {
87
160
  yield filePath;
@@ -90,7 +163,185 @@ function* traverseRecursiveFilePaths(folder, ig = (0, import_ignore.default)().a
90
163
  }
91
164
  function* traverseRecursiveFiles(folder) {
92
165
  for (const filePath of traverseRecursiveFilePaths(folder)) {
93
- yield new File(filePath);
166
+ yield new File(filePath, folder);
167
+ }
168
+ }
169
+
170
+ // src/update-version/index.ts
171
+ async function updateFlowgramVersion(inputVersion) {
172
+ console.log(import_chalk.default.bold("\u{1F680} Welcome to @flowgram.ai update-version helper"));
173
+ const latestVersion = await getLatestVersion("@flowgram.ai/editor");
174
+ const currentPath = process.cwd();
175
+ console.log("- Latest flowgram version: ", latestVersion);
176
+ console.log("- Current Path: ", currentPath);
177
+ const flowgramVersion = inputVersion || latestVersion;
178
+ for (const file of traverseRecursiveFiles(currentPath)) {
179
+ if (file.path.endsWith("package.json")) {
180
+ console.log("\u{1F440} Find package.json: ", file.path);
181
+ let updated = false;
182
+ const json = JSON.parse(file.content);
183
+ if (json.dependencies) {
184
+ for (const key in json.dependencies) {
185
+ if (key.startsWith("@flowgram.ai/")) {
186
+ updated = true;
187
+ json.dependencies[key] = flowgramVersion;
188
+ console.log(`- Update ${key} to ${flowgramVersion}`);
189
+ }
190
+ }
191
+ }
192
+ if (json.devDependencies) {
193
+ for (const key in json.devDependencies) {
194
+ if (key.startsWith("@flowgram.ai/")) {
195
+ updated = true;
196
+ json.devDependencies[key] = flowgramVersion;
197
+ console.log(`- Update ${key} to ${flowgramVersion}`);
198
+ }
199
+ }
200
+ }
201
+ if (updated) {
202
+ file.write(JSON.stringify(json, null, 2));
203
+ console.log(`\u2705 ${file.path} Updated`);
204
+ }
205
+ }
206
+ }
207
+ }
208
+
209
+ // src/materials/index.ts
210
+ var import_path8 = __toESM(require("path"), 1);
211
+ var import_chalk5 = __toESM(require("chalk"), 1);
212
+
213
+ // src/utils/project.ts
214
+ var import_path3 = __toESM(require("path"), 1);
215
+ var import_fs3 = require("fs");
216
+ var import_chalk2 = __toESM(require("chalk"), 1);
217
+ var Project = class _Project {
218
+ constructor() {
219
+ }
220
+ async init() {
221
+ let projectPath = process.cwd();
222
+ while (projectPath !== "/" && !(0, import_fs3.existsSync)(import_path3.default.join(projectPath, "package.json"))) {
223
+ projectPath = import_path3.default.join(projectPath, "..");
224
+ }
225
+ if (projectPath === "/") {
226
+ throw new Error("Please run this command in a valid project");
227
+ }
228
+ this.projectPath = projectPath;
229
+ this.srcPath = import_path3.default.join(projectPath, "src");
230
+ this.packageJsonPath = import_path3.default.join(projectPath, "package.json");
231
+ this.packageJson = JSON.parse((0, import_fs3.readFileSync)(this.packageJsonPath, "utf8"));
232
+ this.flowgramVersion = this.packageJson.dependencies["@flowgram.ai/fixed-layout-editor"] || this.packageJson.dependencies["@flowgram.ai/free-layout-editor"] || this.packageJson.dependencies["@flowgram.ai/editor"];
233
+ }
234
+ async addDependency(dependency) {
235
+ let name;
236
+ let version;
237
+ const lastAtIndex = dependency.lastIndexOf("@");
238
+ if (lastAtIndex <= 0) {
239
+ name = dependency;
240
+ version = await getLatestVersion(name);
241
+ } else {
242
+ name = dependency.substring(0, lastAtIndex);
243
+ version = dependency.substring(lastAtIndex + 1);
244
+ if (!version.trim()) {
245
+ version = await getLatestVersion(name);
246
+ }
247
+ }
248
+ this.packageJson.dependencies[name] = version;
249
+ (0, import_fs3.writeFileSync)(this.packageJsonPath, JSON.stringify(this.packageJson, null, 2));
250
+ }
251
+ async addDependencies(dependencies) {
252
+ for (const dependency of dependencies) {
253
+ await this.addDependency(dependency);
254
+ }
255
+ }
256
+ writeToPackageJsonFile() {
257
+ (0, import_fs3.writeFileSync)(this.packageJsonPath, JSON.stringify(this.packageJson, null, 2));
258
+ }
259
+ printInfo() {
260
+ console.log(import_chalk2.default.bold("Project Info:"));
261
+ console.log(import_chalk2.default.black(` - Flowgram Version: ${this.flowgramVersion}`));
262
+ console.log(import_chalk2.default.black(` - Project Path: ${this.projectPath}`));
263
+ }
264
+ static async getSingleton() {
265
+ const info = new _Project();
266
+ await info.init();
267
+ return info;
268
+ }
269
+ };
270
+
271
+ // src/materials/select.ts
272
+ var import_inquirer = __toESM(require("inquirer"), 1);
273
+ var import_chalk3 = __toESM(require("chalk"), 1);
274
+
275
+ // src/materials/material.ts
276
+ var import_path5 = __toESM(require("path"), 1);
277
+ var import_fs5 = require("fs");
278
+
279
+ // src/utils/ts-file.ts
280
+ var import_path4 = __toESM(require("path"), 1);
281
+ var import_fs4 = __toESM(require("fs"), 1);
282
+
283
+ // src/utils/import.ts
284
+ function assembleImport(declaration) {
285
+ const { namedImports, defaultImport, namespaceImport, source } = declaration;
286
+ const importClauses = [];
287
+ if (namedImports) {
288
+ importClauses.push(
289
+ `{ ${namedImports.map(
290
+ ({ local, imported, typeOnly }) => `${typeOnly ? "type " : ""}${imported}${local ? ` as ${local}` : ""}`
291
+ ).join(", ")} }`
292
+ );
293
+ }
294
+ if (defaultImport) {
295
+ importClauses.push(defaultImport);
296
+ }
297
+ if (namespaceImport) {
298
+ importClauses.push(`* as ${namespaceImport}`);
299
+ }
300
+ return `import ${importClauses.join(", ")} from '${source}';`;
301
+ }
302
+ function* traverseFileImports(fileContent) {
303
+ const importRegex = /import\s+([^{}*,]*?)?(?:\s*\*\s*as\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*,?)?(?:\s*\{([^}]*)\}\s*,?)?(?:\s*([a-zA-Z_$][a-zA-Z0-9_$]*)\s*,?)?\s*from\s*['"`]([^'"`]+)['"`]\;?/g;
304
+ let match;
305
+ while ((match = importRegex.exec(fileContent)) !== null) {
306
+ const [fullMatch, defaultPart, namespacePart, namedPart, defaultPart2, source] = match;
307
+ const declaration = {
308
+ statement: fullMatch,
309
+ source
310
+ };
311
+ const defaultImport = defaultPart?.trim() || defaultPart2?.trim();
312
+ if (defaultImport && !namespacePart && !namedPart) {
313
+ declaration.defaultImport = defaultImport;
314
+ } else if (defaultImport && (namespacePart || namedPart)) {
315
+ declaration.defaultImport = defaultImport;
316
+ }
317
+ if (namespacePart) {
318
+ declaration.namespaceImport = namespacePart.trim();
319
+ }
320
+ if (namedPart) {
321
+ const namedImports = [];
322
+ const namedItems = namedPart.split(",").map((item) => item.trim()).filter(Boolean);
323
+ for (const item of namedItems) {
324
+ const typeOnly = item.startsWith("type ");
325
+ const cleanItem = typeOnly ? item.slice(5).trim() : item;
326
+ if (cleanItem.includes(" as ")) {
327
+ const [imported, local] = cleanItem.split(" as ").map((s) => s.trim());
328
+ namedImports.push({
329
+ imported,
330
+ local,
331
+ typeOnly
332
+ });
333
+ } else {
334
+ namedImports.push({
335
+ imported: cleanItem,
336
+ typeOnly
337
+ });
338
+ }
339
+ }
340
+ if (namedImports.length > 0) {
341
+ declaration.namedImports = namedImports;
342
+ }
343
+ }
344
+ yield declaration;
94
345
  }
95
346
  }
96
347
 
@@ -99,10 +350,7 @@ function extractNamedExports(content) {
99
350
  const valueExports = [];
100
351
  const typeExports = [];
101
352
  const typeDefinitions = /* @__PURE__ */ new Set();
102
- const typePatterns = [
103
- /\b(?:type|interface)\s+(\w+)/g,
104
- /\bexport\s+(?:type|interface)\s+(\w+)/g
105
- ];
353
+ const typePatterns = [/\b(?:type|interface)\s+(\w+)/g, /\bexport\s+(?:type|interface)\s+(\w+)/g];
106
354
  let match;
107
355
  for (const pattern of typePatterns) {
108
356
  while ((match = pattern.exec(content)) !== null) {
@@ -181,84 +429,17 @@ function extractNamedExports(content) {
181
429
  };
182
430
  }
183
431
 
184
- // src/utils/import.ts
185
- function assembleImport(declaration) {
186
- const { namedImports, defaultImport, namespaceImport, source } = declaration;
187
- const importClauses = [];
188
- if (namedImports) {
189
- importClauses.push(
190
- `{ ${namedImports.map(
191
- ({ local, imported, typeOnly }) => `${typeOnly ? "type " : ""}${imported}${local ? ` as ${local}` : ""}`
192
- ).join(", ")} }`
193
- );
194
- }
195
- if (defaultImport) {
196
- importClauses.push(defaultImport);
197
- }
198
- if (namespaceImport) {
199
- importClauses.push(`* as ${namespaceImport}`);
200
- }
201
- return `import ${importClauses.join(", ")} from '${source}';`;
202
- }
203
- function* traverseFileImports(fileContent) {
204
- const importRegex = /import\s+([^{}*,]*?)?(?:\s*\*\s*as\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\s*,?)?(?:\s*\{([^}]*)\}\s*,?)?(?:\s*([a-zA-Z_$][a-zA-Z0-9_$]*)\s*,?)?\s*from\s*['"`]([^'"`]+)['"`]\;?/g;
205
- let match;
206
- while ((match = importRegex.exec(fileContent)) !== null) {
207
- const [fullMatch, defaultPart, namespacePart, namedPart, defaultPart2, source] = match;
208
- const declaration = {
209
- statement: fullMatch,
210
- source
211
- };
212
- const defaultImport = defaultPart?.trim() || defaultPart2?.trim();
213
- if (defaultImport && !namespacePart && !namedPart) {
214
- declaration.defaultImport = defaultImport;
215
- } else if (defaultImport && (namespacePart || namedPart)) {
216
- declaration.defaultImport = defaultImport;
217
- }
218
- if (namespacePart) {
219
- declaration.namespaceImport = namespacePart.trim();
220
- }
221
- if (namedPart) {
222
- const namedImports = [];
223
- const namedItems = namedPart.split(",").map((item) => item.trim()).filter(Boolean);
224
- for (const item of namedItems) {
225
- const typeOnly = item.startsWith("type ");
226
- const cleanItem = typeOnly ? item.slice(5).trim() : item;
227
- if (cleanItem.includes(" as ")) {
228
- const [imported, local] = cleanItem.split(" as ").map((s) => s.trim());
229
- namedImports.push({
230
- imported,
231
- local,
232
- typeOnly
233
- });
234
- } else {
235
- namedImports.push({
236
- imported: cleanItem,
237
- typeOnly
238
- });
239
- }
240
- }
241
- if (namedImports.length > 0) {
242
- declaration.namedImports = namedImports;
243
- }
244
- }
245
- yield declaration;
246
- }
247
- }
248
-
249
432
  // src/utils/ts-file.ts
250
433
  var TsFile = class extends File {
251
- constructor(filePath) {
252
- super(filePath);
434
+ constructor(filePath, root) {
435
+ super(filePath, root);
253
436
  this.exports = {
254
437
  values: [],
255
438
  types: []
256
439
  };
257
440
  this.imports = [];
258
- this.exports = extractNamedExports(import_fs2.default.readFileSync(filePath, "utf-8"));
259
- this.imports = Array.from(
260
- traverseFileImports(import_fs2.default.readFileSync(filePath, "utf-8"))
261
- );
441
+ this.exports = extractNamedExports(import_fs4.default.readFileSync(filePath, "utf-8"));
442
+ this.imports = Array.from(traverseFileImports(import_fs4.default.readFileSync(filePath, "utf-8")));
262
443
  }
263
444
  get allExportNames() {
264
445
  return [...this.exports.values, ...this.exports.types];
@@ -272,9 +453,7 @@ var TsFile = class extends File {
272
453
  return content.replace(
273
454
  lastImportStatement.statement,
274
455
  `${lastImportStatement?.statement}
275
- ${importDeclarations.map(
276
- (item) => item.statement
277
- )}
456
+ ${importDeclarations.map((item) => item.statement)}
278
457
  `
279
458
  );
280
459
  });
@@ -282,14 +461,9 @@ ${importDeclarations.map(
282
461
  }
283
462
  removeImport(importDeclarations) {
284
463
  this.replace(
285
- (content) => importDeclarations.reduce(
286
- (prev, cur) => prev.replace(cur.statement, ""),
287
- content
288
- )
289
- );
290
- this.imports = this.imports.filter(
291
- (item) => !importDeclarations.includes(item)
464
+ (content) => importDeclarations.reduce((prev, cur) => prev.replace(cur.statement, ""), content)
292
465
  );
466
+ this.imports = this.imports.filter((item) => !importDeclarations.includes(item));
293
467
  }
294
468
  replaceImport(oldImports, newImports) {
295
469
  newImports.forEach((importDeclaration) => {
@@ -318,9 +492,7 @@ ${importDeclarations.map(
318
492
  content = content.replace(
319
493
  lastImportStatement,
320
494
  `${lastImportStatement}
321
- ${restNewImports.map(
322
- (item) => item.statement
323
- )}
495
+ ${restNewImports.map((item) => item.statement).join("\n")}
324
496
  `
325
497
  );
326
498
  }
@@ -332,236 +504,158 @@ ${restNewImports.map(
332
504
  function* traverseRecursiveTsFiles(folder) {
333
505
  for (const filePath of traverseRecursiveFilePaths(folder)) {
334
506
  if (filePath.endsWith(".ts") || filePath.endsWith(".tsx")) {
335
- yield new TsFile(filePath);
507
+ yield new TsFile(filePath, folder);
336
508
  }
337
509
  }
338
510
  }
339
511
  function getIndexTsFile(folder) {
340
- const files = import_fs2.default.readdirSync(folder);
512
+ const files = import_fs4.default.readdirSync(folder);
341
513
  for (const file of files) {
342
514
  if (file === "index.ts" || file === "index.tsx") {
343
- return new TsFile(import_path2.default.join(folder, file));
515
+ return new TsFile(import_path4.default.join(folder, file), folder);
344
516
  }
345
517
  }
346
518
  return void 0;
347
519
  }
348
520
 
349
- // src/materials/materials.ts
350
- var _types = [
521
+ // src/materials/material.ts
522
+ var _Material = class _Material {
523
+ constructor(type, name, formMaterialPkg) {
524
+ this.type = type;
525
+ this.name = name;
526
+ this.formMaterialPkg = formMaterialPkg;
527
+ }
528
+ get fullName() {
529
+ return `${this.type}/${this.name}`;
530
+ }
531
+ get sourceDir() {
532
+ return import_path5.default.join(this.formMaterialPkg.srcPath, this.type, this.name);
533
+ }
534
+ get indexFile() {
535
+ return getIndexTsFile(this.sourceDir);
536
+ }
537
+ get allExportNames() {
538
+ return this.indexFile?.allExportNames || [];
539
+ }
540
+ static listAll(formMaterialPkg) {
541
+ if (!this._all_materials_cache.length) {
542
+ this._all_materials_cache = _Material.ALL_TYPES.map((type) => {
543
+ const materialsPath = import_path5.default.join(formMaterialPkg.srcPath, type);
544
+ return (0, import_fs5.readdirSync)(materialsPath).map((_path) => {
545
+ if (_path === "index.ts") {
546
+ return null;
547
+ }
548
+ return new _Material(type, _path, formMaterialPkg);
549
+ }).filter((material) => material !== null);
550
+ }).flat();
551
+ }
552
+ return this._all_materials_cache;
553
+ }
554
+ };
555
+ _Material._all_materials_cache = [];
556
+ _Material.ALL_TYPES = [
351
557
  "components",
352
558
  "effects",
353
559
  "plugins",
354
560
  "shared",
355
- "typings",
356
561
  "validate",
357
562
  "form-plugins",
358
563
  "hooks"
359
564
  ];
360
- function listAllMaterials(formMaterialSrc) {
361
- const _materials = [];
362
- for (const _type of _types) {
363
- const materialsPath = import_path3.default.join(formMaterialSrc, _type);
364
- _materials.push(
365
- ...import_fs3.default.readdirSync(materialsPath).map((_path) => {
366
- if (_path === "index.ts") {
367
- return null;
368
- }
369
- return {
370
- name: _path,
371
- // Assuming the folder name is the material name
372
- type: _type,
373
- path: import_path3.default.join(materialsPath, _path)
374
- };
375
- }).filter((material) => material !== null)
376
- );
377
- }
378
- return _materials;
379
- }
380
- var getFormMaterialDependencies = (formMaterialPath) => {
381
- const packageJsonPath = import_path3.default.join(formMaterialPath, "package.json");
382
- const packageJson = JSON.parse(import_fs3.default.readFileSync(packageJsonPath, "utf8"));
383
- return packageJson.dependencies;
384
- };
385
- var copyMaterial = (material, project, formMaterialPath) => {
386
- const formMaterialDependencies = getFormMaterialDependencies(formMaterialPath);
387
- const sourceDir = material.path;
388
- const materialRoot = import_path3.default.join(
389
- project.projectPath,
390
- "src",
391
- "form-materials",
392
- `${material.type}`
393
- );
394
- const targetDir = import_path3.default.join(materialRoot, material.name);
395
- const packagesToInstall = /* @__PURE__ */ new Set();
396
- import_fs3.default.cpSync(sourceDir, targetDir, { recursive: true });
397
- for (const file of traverseRecursiveTsFiles(targetDir)) {
398
- for (const importDeclaration of file.imports) {
399
- const { source } = importDeclaration;
400
- if (source.startsWith("@/")) {
401
- console.log(
402
- `Replace Import from ${source} to @flowgram.ai/form-materials`
403
- );
404
- file.replaceImport(
405
- [importDeclaration],
406
- [{ ...importDeclaration, source: "@flowgram.ai/form-materials" }]
407
- );
408
- packagesToInstall.add(
409
- `@flowgram.ai/form-materials@${project.flowgramVersion}`
410
- );
411
- } else if (!source.startsWith(".") && !source.startsWith("react")) {
412
- const [dep, version] = Object.entries(formMaterialDependencies).find(
413
- ([_key]) => source.startsWith(_key)
414
- ) || [];
415
- if (!dep) {
416
- continue;
565
+ var Material = _Material;
566
+
567
+ // src/materials/select.ts
568
+ var getSelectedMaterials = async (cliOpts, formMaterialPkg) => {
569
+ const { materialName, selectMultiple } = cliOpts;
570
+ const materials = Material.listAll(formMaterialPkg);
571
+ let selectedMaterials = [];
572
+ if (materialName) {
573
+ selectedMaterials = materialName.split(",").map((_name) => materials.find((_m) => _m.fullName === _name.trim())).filter(Boolean);
574
+ }
575
+ if (!selectedMaterials.length) {
576
+ console.log(import_chalk3.default.yellow(`Material "${materialName}" not found. Please select from the list:`));
577
+ const choices = materials.map((_material) => ({
578
+ name: _material.fullName,
579
+ value: _material
580
+ }));
581
+ if (selectMultiple) {
582
+ const result = await import_inquirer.default.prompt([
583
+ {
584
+ type: "checkbox",
585
+ name: "material",
586
+ message: "Select multiple materials to add:",
587
+ choices
417
588
  }
418
- if (dep.startsWith("@flowgram.ai/")) {
419
- packagesToInstall.add(`${dep}@${project.flowgramVersion}`);
420
- } else {
421
- packagesToInstall.add(`${dep}@${version}`);
589
+ ]);
590
+ selectedMaterials = result.material;
591
+ } else {
592
+ const result = await import_inquirer.default.prompt([
593
+ {
594
+ type: "list",
595
+ name: "material",
596
+ message: "Select one material to add:",
597
+ choices
422
598
  }
423
- }
599
+ ]);
600
+ selectedMaterials = [result.material];
424
601
  }
425
602
  }
426
- return {
427
- packagesToInstall: [...packagesToInstall]
428
- };
603
+ return selectedMaterials;
429
604
  };
430
605
 
431
- // src/utils/npm.ts
432
- var import_child_process = require("child_process");
433
- var import_fs4 = require("fs");
434
- var import_path4 = __toESM(require("path"), 1);
435
- var import_download = __toESM(require("download"), 1);
436
- async function getLatestVersion(packageName) {
437
- return (0, import_child_process.execSync)(`npm view ${packageName} version --tag=latest`).toString().trim();
438
- }
439
- async function loadNpm(packageName) {
440
- const packageLatestVersion = await getLatestVersion(packageName);
441
- const packagePath = import_path4.default.join(
442
- __dirname,
443
- `./.download/${packageName}-${packageLatestVersion}`
444
- );
445
- if ((0, import_fs4.existsSync)(packagePath)) {
446
- return packagePath;
447
- }
448
- try {
449
- const tarballUrl = (0, import_child_process.execSync)(
450
- `npm view ${packageName}@${packageLatestVersion} dist.tarball`
451
- ).toString().trim();
452
- await (0, import_download.default)(tarballUrl, packagePath, { extract: true, strip: 1 });
453
- return packagePath;
454
- } catch (error) {
455
- console.error(`Error downloading or extracting package: ${error}`);
456
- throw error;
457
- }
458
- }
459
-
460
- // src/materials/index.ts
606
+ // src/materials/refresh-project-import.ts
461
607
  var import_path6 = __toESM(require("path"), 1);
462
-
463
- // src/utils/project.ts
464
- var import_fs5 = require("fs");
465
- var import_path5 = __toESM(require("path"), 1);
466
- var import_chalk = __toESM(require("chalk"), 1);
467
- var Project = class _Project {
468
- constructor() {
469
- }
470
- async init() {
471
- let projectPath = process.cwd();
472
- while (projectPath !== "/" && !(0, import_fs5.existsSync)(import_path5.default.join(projectPath, "package.json"))) {
473
- projectPath = import_path5.default.join(projectPath, "..");
474
- }
475
- if (projectPath === "/") {
476
- throw new Error("Please run this command in a valid project");
477
- }
478
- this.projectPath = projectPath;
479
- this.srcPath = import_path5.default.join(projectPath, "src");
480
- this.packageJsonPath = import_path5.default.join(projectPath, "package.json");
481
- this.packageJson = JSON.parse((0, import_fs5.readFileSync)(this.packageJsonPath, "utf8"));
482
- this.flowgramVersion = this.packageJson.dependencies["@flowgram.ai/fixed-layout-editor"] || this.packageJson.dependencies["@flowgram.ai/free-layout-editor"] || this.packageJson.dependencies["@flowgram.ai/editor"];
483
- }
484
- async addDependency(dependency) {
485
- let name;
486
- let version;
487
- const lastAtIndex = dependency.lastIndexOf("@");
488
- if (lastAtIndex <= 0) {
489
- name = dependency;
490
- version = await getLatestVersion(name);
491
- } else {
492
- name = dependency.substring(0, lastAtIndex);
493
- version = dependency.substring(lastAtIndex + 1);
494
- if (!version.trim()) {
495
- version = await getLatestVersion(name);
496
- }
497
- }
498
- this.packageJson.dependencies[name] = version;
499
- (0, import_fs5.writeFileSync)(
500
- this.packageJsonPath,
501
- JSON.stringify(this.packageJson, null, 2)
502
- );
503
- }
504
- async addDependencies(dependencies) {
505
- for (const dependency of dependencies) {
506
- await this.addDependency(dependency);
608
+ var import_chalk4 = __toESM(require("chalk"), 1);
609
+ function executeRefreshProjectImport(context) {
610
+ const { selectedMaterials, project, targetFormMaterialRoot } = context;
611
+ const exportName2Material = /* @__PURE__ */ new Map();
612
+ const targetModule = `@/${import_path6.default.relative(project.srcPath, targetFormMaterialRoot)}`;
613
+ for (const material of selectedMaterials) {
614
+ if (!material.indexFile) {
615
+ console.warn(`Material ${material.name} not found`);
616
+ return;
507
617
  }
618
+ console.log(`\u{1F440} The exports of ${material.name} is ${material.allExportNames.join(",")}`);
619
+ material.allExportNames.forEach((exportName) => {
620
+ exportName2Material.set(exportName, material);
621
+ });
508
622
  }
509
- writeToPackageJsonFile() {
510
- (0, import_fs5.writeFileSync)(
511
- this.packageJsonPath,
512
- JSON.stringify(this.packageJson, null, 2)
513
- );
514
- }
515
- printInfo() {
516
- console.log(import_chalk.default.bold("Project Info:"));
517
- console.log(import_chalk.default.black(` - Flowgram Version: ${this.flowgramVersion}`));
518
- console.log(import_chalk.default.black(` - Project Path: ${this.projectPath}`));
519
- }
520
- static async getSingleton() {
521
- const info = new _Project();
522
- await info.init();
523
- return info;
524
- }
525
- };
526
-
527
- // src/materials/refresh-project-import.ts
528
- var import_chalk2 = __toESM(require("chalk"), 1);
529
- function executeRefreshProjectImport(project, material) {
530
- const materialFile = getIndexTsFile(material.path);
531
- if (!materialFile) {
532
- console.warn(`Material ${material.name} not found`);
533
- return;
534
- }
535
- const targetDir = `@/form-materials/${material.type}/${material.name}`;
536
- const exportNames = materialFile.allExportNames;
537
- console.log(`\u{1F440} The exports of ${material.name} is ${exportNames.join(",")}`);
538
623
  for (const tsFile of traverseRecursiveTsFiles(project.srcPath)) {
539
624
  for (const importDeclaration of tsFile.imports) {
540
- if (importDeclaration.source === "@flowgram.ai/form-materials") {
541
- const currentMaterialImports = importDeclaration.namedImports?.filter(
542
- (item) => exportNames.includes(item.imported)
543
- );
544
- if (!currentMaterialImports?.length) {
625
+ if (importDeclaration.source.startsWith("@flowgram.ai/form-materials")) {
626
+ const restImports = [];
627
+ const importMap = {};
628
+ if (!importDeclaration.namedImports) {
545
629
  continue;
546
630
  }
547
- const nextImports = [
548
- {
549
- ...importDeclaration,
550
- namedImports: currentMaterialImports,
551
- source: targetDir
631
+ for (const nameImport of importDeclaration.namedImports) {
632
+ const material = exportName2Material.get(nameImport.imported);
633
+ if (material) {
634
+ const importModule = `${targetModule}/${material.fullName}`;
635
+ importMap[importModule] = importMap[importModule] || [];
636
+ importMap[importModule].push(nameImport);
637
+ } else {
638
+ restImports.push(nameImport);
552
639
  }
553
- ];
554
- const keepImportNames = importDeclaration.namedImports?.filter(
555
- (item) => !exportNames.includes(item.imported)
640
+ }
641
+ if (Object.keys(importMap).length === 0) {
642
+ continue;
643
+ }
644
+ const nextImports = Object.entries(importMap).map(
645
+ ([importModule, namedImports]) => ({
646
+ ...importDeclaration,
647
+ namedImports,
648
+ source: importModule
649
+ })
556
650
  );
557
- if (keepImportNames?.length) {
651
+ if (restImports?.length) {
558
652
  nextImports.unshift({
559
653
  ...importDeclaration,
560
- namedImports: keepImportNames
654
+ namedImports: restImports
561
655
  });
562
656
  }
563
657
  tsFile.replaceImport([importDeclaration], nextImports);
564
- console.log(import_chalk2.default.green(`\u{1F504} Refresh Imports In: ${tsFile.path}`));
658
+ console.log(import_chalk4.default.green(`\u{1F504} Refresh Imports In: ${tsFile.path}`));
565
659
  console.log(
566
660
  `From:
567
661
  ${importDeclaration.statement}
@@ -573,86 +667,147 @@ ${nextImports.map((item) => item.statement).join("\n")}`
573
667
  }
574
668
  }
575
669
 
670
+ // src/materials/copy.ts
671
+ var import_path7 = __toESM(require("path"), 1);
672
+ var import_fs6 = __toESM(require("fs"), 1);
673
+ var copyMaterials = (ctx) => {
674
+ const { selectedMaterials, project, formMaterialPkg, targetFormMaterialRoot } = ctx;
675
+ const formMaterialDependencies = formMaterialPkg.dependencies;
676
+ const packagesToInstall = /* @__PURE__ */ new Set();
677
+ for (const material of selectedMaterials) {
678
+ const sourceDir = material.sourceDir;
679
+ const targetDir = import_path7.default.join(targetFormMaterialRoot, material.type, material.name);
680
+ import_fs6.default.cpSync(sourceDir, targetDir, { recursive: true });
681
+ for (const file of traverseRecursiveTsFiles(targetDir)) {
682
+ for (const importDeclaration of file.imports) {
683
+ const { source } = importDeclaration;
684
+ if (source.startsWith("@/")) {
685
+ console.log(`Replace Import from ${source} to @flowgram.ai/form-materials`);
686
+ file.replaceImport(
687
+ [importDeclaration],
688
+ [{ ...importDeclaration, source: "@flowgram.ai/form-materials" }]
689
+ );
690
+ packagesToInstall.add(`@flowgram.ai/form-materials@${project.flowgramVersion}`);
691
+ } else if (!source.startsWith(".") && !source.startsWith("react")) {
692
+ const [dep, version] = Object.entries(formMaterialDependencies).find(([_key]) => source.startsWith(_key)) || [];
693
+ if (!dep) {
694
+ continue;
695
+ }
696
+ if (dep.startsWith("@flowgram.ai/")) {
697
+ packagesToInstall.add(`${dep}@${project.flowgramVersion}`);
698
+ } else {
699
+ packagesToInstall.add(`${dep}@${version}`);
700
+ }
701
+ }
702
+ }
703
+ }
704
+ }
705
+ return {
706
+ packagesToInstall: [...packagesToInstall]
707
+ };
708
+ };
709
+
576
710
  // src/materials/index.ts
577
- async function syncMaterial(opts) {
578
- const { materialName, refreshProjectImports } = opts;
579
- console.log(import_chalk3.default.bold("\u{1F680} Welcome to @flowgram.ai form-materials!"));
711
+ async function syncMaterial(cliOpts) {
712
+ const { refreshProjectImports, targetMaterialRootDir } = cliOpts;
713
+ console.log(import_chalk5.default.bold("\u{1F680} Welcome to @flowgram.ai form-materials CLI!"));
580
714
  const project = await Project.getSingleton();
581
715
  project.printInfo();
716
+ const targetFormMaterialRoot = targetMaterialRootDir || import_path8.default.join(project.projectPath, "src", "form-materials");
717
+ console.log(import_chalk5.default.black(` - Target material root: ${targetFormMaterialRoot}`));
582
718
  if (!project.flowgramVersion) {
583
719
  throw new Error(
584
- import_chalk3.default.red(
720
+ import_chalk5.default.red(
585
721
  "\u274C Please install @flowgram.ai/fixed-layout-editor or @flowgram.ai/free-layout-editor"
586
722
  )
587
723
  );
588
724
  }
589
- const formMaterialPath = await loadNpm("@flowgram.ai/form-materials");
590
- const formMaterialSrc = import_path6.default.join(formMaterialPath, "src");
591
- const materials = listAllMaterials(formMaterialSrc);
592
- let material;
593
- if (materialName) {
594
- const selectedMaterial = materials.find(
595
- (m) => `${m.type}/${m.name}` === materialName
596
- );
597
- if (selectedMaterial) {
598
- material = selectedMaterial;
599
- console.log(import_chalk3.default.green(`Using material: ${materialName}`));
600
- } else {
601
- console.log(
602
- import_chalk3.default.yellow(
603
- `Material "${materialName}" not found. Please select from the list:`
604
- )
605
- );
606
- }
607
- }
608
- if (!material) {
609
- const result = await import_inquirer.default.prompt([
610
- {
611
- type: "list",
612
- name: "material",
613
- message: "Select one material to add:",
614
- choices: [
615
- ...materials.map((_material) => ({
616
- name: `${_material.type}/${_material.name}`,
617
- value: _material
618
- }))
619
- ]
620
- }
621
- ]);
622
- material = result.material;
623
- }
624
- if (!material) {
625
- console.error(import_chalk3.default.red("No material selected. Exiting."));
725
+ const formMaterialPkg = await loadNpm("@flowgram.ai/form-materials");
726
+ let selectedMaterials = await getSelectedMaterials(cliOpts, formMaterialPkg);
727
+ if (!selectedMaterials.length) {
728
+ console.error(import_chalk5.default.red("No material selected. Exiting."));
626
729
  process.exit(1);
627
730
  }
731
+ const context = {
732
+ selectedMaterials,
733
+ project,
734
+ formMaterialPkg,
735
+ cliOpts,
736
+ targetFormMaterialRoot
737
+ };
738
+ console.log(import_chalk5.default.bold("\u{1F680} The following materials will be added to your project"));
739
+ console.log(selectedMaterials.map((material) => `\u{1F4E6} ${material.fullName}`).join("\n"));
740
+ console.log("\n");
741
+ let { packagesToInstall } = copyMaterials(context);
628
742
  if (refreshProjectImports) {
629
- console.log(import_chalk3.default.bold("\u{1F680} Refresh imports in your project"));
630
- executeRefreshProjectImport(project, material);
631
- }
632
- console.log(
633
- import_chalk3.default.bold("\u{1F680} The following materials will be added to your project")
634
- );
635
- console.log(material);
636
- let { packagesToInstall } = copyMaterial(material, project, formMaterialPath);
743
+ console.log(import_chalk5.default.bold("\u{1F680} Refresh imports in your project"));
744
+ executeRefreshProjectImport(context);
745
+ }
637
746
  await project.addDependencies(packagesToInstall);
638
- console.log(
639
- import_chalk3.default.bold("\u2705 These npm dependencies is added to your package.json")
640
- );
747
+ console.log(import_chalk5.default.bold("\n\u2705 These npm dependencies is added to your package.json"));
641
748
  packagesToInstall.forEach((_package) => {
642
749
  console.log(`- ${_package}`);
643
750
  });
644
- console.log(import_chalk3.default.bold("\n\u27A1\uFE0F Please run npm install to install dependencies\n"));
751
+ console.log(import_chalk5.default.bold(import_chalk5.default.bold("\n\u27A1\uFE0F Please run npm install to install dependencies\n")));
752
+ }
753
+
754
+ // src/find-materials/index.ts
755
+ var import_chalk6 = __toESM(require("chalk"), 1);
756
+ async function findUsedMaterials() {
757
+ console.log(import_chalk6.default.bold("\u{1F680} Welcome to @flowgram.ai form-materials CLI!"));
758
+ const project = await Project.getSingleton();
759
+ project.printInfo();
760
+ const formMaterialPkg = await loadNpm("@flowgram.ai/form-materials");
761
+ const materials = Material.listAll(formMaterialPkg);
762
+ const allUsedMaterials = /* @__PURE__ */ new Set();
763
+ const exportName2Material = /* @__PURE__ */ new Map();
764
+ for (const material of materials) {
765
+ if (!material.indexFile) {
766
+ console.warn(`Material ${material.name} not found`);
767
+ return;
768
+ }
769
+ console.log(`\u{1F440} The exports of ${material.name} is ${material.allExportNames.join(",")}`);
770
+ material.allExportNames.forEach((exportName) => {
771
+ exportName2Material.set(exportName, material);
772
+ });
773
+ }
774
+ for (const tsFile of traverseRecursiveTsFiles(project.srcPath)) {
775
+ const fileMaterials = /* @__PURE__ */ new Set();
776
+ let fileImportPrinted = false;
777
+ for (const importDeclaration of tsFile.imports) {
778
+ if (!importDeclaration.source.startsWith("@flowgram.ai/form-materials") || !importDeclaration.namedImports?.length) {
779
+ continue;
780
+ }
781
+ if (!fileImportPrinted) {
782
+ fileImportPrinted = true;
783
+ console.log(import_chalk6.default.bold(`
784
+ \u{1F440} Searching ${tsFile.path}`));
785
+ }
786
+ console.log(`\u{1F50D} ${importDeclaration.statement}`);
787
+ if (importDeclaration.namedImports) {
788
+ importDeclaration.namedImports.forEach((namedImport) => {
789
+ const material = exportName2Material.get(namedImport.imported);
790
+ if (material) {
791
+ fileMaterials.add(material);
792
+ allUsedMaterials.add(material);
793
+ console.log(`import ${import_chalk6.default.bold(material.fullName)} by ${namedImport.imported}`);
794
+ }
795
+ });
796
+ }
797
+ }
798
+ }
799
+ console.log(import_chalk6.default.bold("\n\u{1F4E6} All used materials:"));
800
+ console.log([...allUsedMaterials].map((_material) => _material.fullName).join(","));
645
801
  }
646
802
 
647
803
  // src/create-app/index.ts
648
- var import_path7 = __toESM(require("path"), 1);
804
+ var import_path9 = __toESM(require("path"), 1);
805
+ var import_https2 = __toESM(require("https"), 1);
649
806
  var import_child_process2 = require("child_process");
807
+ var tar2 = __toESM(require("tar"), 1);
650
808
  var import_inquirer2 = __toESM(require("inquirer"), 1);
651
- var import_fs_extra = __toESM(require("fs-extra"), 1);
652
- var import_chalk4 = __toESM(require("chalk"), 1);
653
- var import_download2 = __toESM(require("download"), 1);
654
- var tar = __toESM(require("tar"), 1);
655
- var args = process.argv.slice(2);
809
+ var import_fs_extra2 = __toESM(require("fs-extra"), 1);
810
+ var import_chalk7 = __toESM(require("chalk"), 1);
656
811
  var updateFlowGramVersions = (dependencies, latestVersion) => {
657
812
  for (const packageName in dependencies) {
658
813
  if (packageName.startsWith("@flowgram.ai")) {
@@ -660,8 +815,29 @@ var updateFlowGramVersions = (dependencies, latestVersion) => {
660
815
  }
661
816
  }
662
817
  };
818
+ function downloadFile2(url, dest) {
819
+ return new Promise((resolve, reject) => {
820
+ const file = import_fs_extra2.default.createWriteStream(dest);
821
+ import_https2.default.get(url, (response) => {
822
+ if (response.statusCode !== 200) {
823
+ reject(new Error(`Download failed: ${response.statusCode}`));
824
+ return;
825
+ }
826
+ response.pipe(file);
827
+ file.on("finish", () => {
828
+ file.close();
829
+ resolve();
830
+ });
831
+ }).on("error", (err) => {
832
+ import_fs_extra2.default.unlink(dest, () => reject(err));
833
+ });
834
+ file.on("error", (err) => {
835
+ import_fs_extra2.default.unlink(dest, () => reject(err));
836
+ });
837
+ });
838
+ }
663
839
  var createApp = async (projectName) => {
664
- console.log(import_chalk4.default.green("Welcome to @flowgram.ai/create-app CLI!"));
840
+ console.log(import_chalk7.default.green("Welcome to @flowgram.ai/create-app CLI!"));
665
841
  const latest = (0, import_child_process2.execSync)("npm view @flowgram.ai/demo-fixed-layout version --tag=latest latest").toString().trim();
666
842
  let folderName = "";
667
843
  if (!projectName) {
@@ -683,7 +859,14 @@ var createApp = async (projectName) => {
683
859
  ]);
684
860
  folderName = repo;
685
861
  } else {
686
- if (["fixed-layout", "free-layout", "fixed-layout-simple", "free-layout-simple", "playground", "nextjs"].includes(projectName)) {
862
+ if ([
863
+ "fixed-layout",
864
+ "free-layout",
865
+ "fixed-layout-simple",
866
+ "free-layout-simple",
867
+ "playground",
868
+ "nextjs"
869
+ ].includes(projectName)) {
687
870
  folderName = `demo-${projectName}`;
688
871
  } else {
689
872
  console.error('Invalid projectName. Please run "npx create-app" to choose demo.');
@@ -691,19 +874,20 @@ var createApp = async (projectName) => {
691
874
  }
692
875
  }
693
876
  try {
694
- const targetDir = import_path7.default.join(process.cwd());
877
+ const targetDir = import_path9.default.join(process.cwd());
695
878
  const downloadPackage = async () => {
696
879
  try {
697
- const tarballBuffer = await (0, import_download2.default)(`https://registry.npmjs.org/@flowgram.ai/${folderName}/-/${folderName}-${latest}.tgz`);
698
- import_fs_extra.default.ensureDirSync(targetDir);
699
- const tempTarballPath = import_path7.default.join(process.cwd(), `${folderName}.tgz`);
700
- import_fs_extra.default.writeFileSync(tempTarballPath, tarballBuffer);
701
- await tar.x({
880
+ const url = `https://registry.npmjs.org/@flowgram.ai/${folderName}/-/${folderName}-${latest}.tgz`;
881
+ const tempTarballPath = import_path9.default.join(process.cwd(), `${folderName}.tgz`);
882
+ console.log(import_chalk7.default.blue(`Downloading ${url} ...`));
883
+ await downloadFile2(url, tempTarballPath);
884
+ import_fs_extra2.default.ensureDirSync(targetDir);
885
+ await tar2.x({
702
886
  file: tempTarballPath,
703
887
  C: targetDir
704
888
  });
705
- import_fs_extra.default.renameSync(import_path7.default.join(targetDir, "package"), import_path7.default.join(targetDir, folderName));
706
- import_fs_extra.default.unlinkSync(tempTarballPath);
889
+ import_fs_extra2.default.renameSync(import_path9.default.join(targetDir, "package"), import_path9.default.join(targetDir, folderName));
890
+ import_fs_extra2.default.unlinkSync(tempTarballPath);
707
891
  return true;
708
892
  } catch (error) {
709
893
  console.error(`Error downloading or extracting package: ${error}`);
@@ -711,8 +895,8 @@ var createApp = async (projectName) => {
711
895
  }
712
896
  };
713
897
  const res = await downloadPackage();
714
- const pkgJsonPath = import_path7.default.join(targetDir, folderName, "package.json");
715
- const data = import_fs_extra.default.readFileSync(pkgJsonPath, "utf-8");
898
+ const pkgJsonPath = import_path9.default.join(targetDir, folderName, "package.json");
899
+ const data = import_fs_extra2.default.readFileSync(pkgJsonPath, "utf-8");
716
900
  const packageLatestVersion = (0, import_child_process2.execSync)("npm view @flowgram.ai/core version --tag=latest latest").toString().trim();
717
901
  const jsonData = JSON.parse(data);
718
902
  if (jsonData.dependencies) {
@@ -721,15 +905,15 @@ var createApp = async (projectName) => {
721
905
  if (jsonData.devDependencies) {
722
906
  updateFlowGramVersions(jsonData.devDependencies, packageLatestVersion);
723
907
  }
724
- import_fs_extra.default.writeFileSync(pkgJsonPath, JSON.stringify(jsonData, null, 2), "utf-8");
908
+ import_fs_extra2.default.writeFileSync(pkgJsonPath, JSON.stringify(jsonData, null, 2), "utf-8");
725
909
  if (res) {
726
- console.log(import_chalk4.default.green(`${folderName} Demo project created successfully!`));
727
- console.log(import_chalk4.default.yellow("Run the following commands to start:"));
728
- console.log(import_chalk4.default.cyan(` cd ${folderName}`));
729
- console.log(import_chalk4.default.cyan(" npm install"));
730
- console.log(import_chalk4.default.cyan(" npm start"));
910
+ console.log(import_chalk7.default.green(`${folderName} Demo project created successfully!`));
911
+ console.log(import_chalk7.default.yellow("Run the following commands to start:"));
912
+ console.log(import_chalk7.default.cyan(` cd ${folderName}`));
913
+ console.log(import_chalk7.default.cyan(" npm install"));
914
+ console.log(import_chalk7.default.cyan(" npm start"));
731
915
  } else {
732
- console.log(import_chalk4.default.red("Download failed"));
916
+ console.log(import_chalk7.default.red("Download failed"));
733
917
  }
734
918
  } catch (error) {
735
919
  console.error("Error downloading repo:", error);
@@ -737,62 +921,26 @@ var createApp = async (projectName) => {
737
921
  }
738
922
  };
739
923
 
740
- // src/update-version/index.ts
741
- var import_chalk5 = __toESM(require("chalk"), 1);
742
- async function updateFlowgramVersion(inputVersion) {
743
- console.log(import_chalk5.default.bold("\u{1F680} Welcome to @flowgram.ai update-version helper"));
744
- const latestVersion = await getLatestVersion("@flowgram.ai/editor");
745
- const currentPath = process.cwd();
746
- console.log("- Latest flowgram version: ", latestVersion);
747
- console.log("- Current Path: ", currentPath);
748
- const flowgramVersion = inputVersion || latestVersion;
749
- for (const file of traverseRecursiveFiles(currentPath)) {
750
- if (file.path.endsWith("package.json")) {
751
- console.log("\u{1F440} Find package.json: ", file.path);
752
- let updated = false;
753
- const json = JSON.parse(file.content);
754
- if (json.dependencies) {
755
- for (const key in json.dependencies) {
756
- if (key.startsWith("@flowgram.ai/")) {
757
- updated = true;
758
- json.dependencies[key] = flowgramVersion;
759
- console.log(`- Update ${key} to ${flowgramVersion}`);
760
- }
761
- }
762
- }
763
- if (json.devDependencies) {
764
- for (const key in json.devDependencies) {
765
- if (key.startsWith("@flowgram.ai/")) {
766
- updated = true;
767
- json.devDependencies[key] = flowgramVersion;
768
- console.log(`- Update ${key} to ${flowgramVersion}`);
769
- }
770
- }
771
- }
772
- if (updated) {
773
- file.write(JSON.stringify(json, null, 2));
774
- console.log(`\u2705 ${file.path} Updated`);
775
- }
776
- }
777
- }
778
- }
779
-
780
924
  // src/index.ts
781
925
  var program = new import_commander.Command();
782
926
  program.name("flowgram-cli").version("1.0.0").description("Flowgram CLI");
783
927
  program.command("create-app").description("Create a new flowgram project").argument("[string]", "Project name").action(async (projectName) => {
784
928
  await createApp(projectName);
785
929
  });
786
- program.command("materials").description("Sync materials to the project").argument("[string]", "Material name").option(
787
- "--refresh-project-imports",
788
- "Refresh project imports to copied materials",
789
- false
790
- ).action(async (materialName, options) => {
930
+ program.command("materials").description("Sync materials to the project").argument(
931
+ "[string]",
932
+ "Material name or names\nExample 1: components/variable-selector \nExample2: components/variable-selector,effect/provideJsonSchemaOutputs"
933
+ ).option("--refresh-project-imports", "Refresh project imports to copied materials", false).option("--target-material-root-dir <string>", "Target directory to copy materials").option("--select-multiple", "Select multiple materials", false).action(async (materialName, options) => {
791
934
  await syncMaterial({
792
935
  materialName,
793
- refreshProjectImports: options.refreshProjectImports
936
+ refreshProjectImports: options.refreshProjectImports,
937
+ targetMaterialRootDir: options.targetMaterialRootDir ? import_path10.default.join(process.cwd(), options.targetMaterialRootDir) : void 0,
938
+ selectMultiple: options.selectMultiple
794
939
  });
795
940
  });
941
+ program.command("find-used-materials").description("Find used materials in the project").action(async () => {
942
+ await findUsedMaterials();
943
+ });
796
944
  program.command("update-version").description("Update flowgram version in the project").argument("[string]", "Flowgram version").action(async (version) => {
797
945
  await updateFlowgramVersion(version);
798
946
  });