@flowgram.ai/cli 0.1.8 → 0.4.11

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.js CHANGED
@@ -10,16 +10,20 @@ import { Command } from "commander";
10
10
 
11
11
  // src/materials/index.ts
12
12
  import inquirer from "inquirer";
13
- import chalk2 from "chalk";
13
+ import chalk3 from "chalk";
14
14
 
15
15
  // src/materials/materials.ts
16
- import { fileURLToPath as fileURLToPath2 } from "url";
16
+ import path4 from "path";
17
+ import fs3 from "fs";
18
+
19
+ // src/utils/ts-file.ts
17
20
  import path3 from "path";
18
21
  import fs2 from "fs";
19
22
 
20
- // src/utils/traverse-file.ts
23
+ // src/utils/file.ts
21
24
  import path2 from "path";
22
25
  import fs from "fs";
26
+ import ignore from "ignore";
23
27
  var File = class {
24
28
  constructor(filePath, root = "/") {
25
29
  this.root = root;
@@ -45,18 +49,120 @@ var File = class {
45
49
  this.content = updater(this.content);
46
50
  fs.writeFileSync(this.path, this.content, "utf-8");
47
51
  }
52
+ write(nextContent) {
53
+ this.content = nextContent;
54
+ fs.writeFileSync(this.path, this.content, "utf-8");
55
+ }
48
56
  };
49
- function* traverseRecursiveFiles(folder) {
57
+ function* traverseRecursiveFilePaths(folder, ig = ignore().add(".git"), root = folder) {
50
58
  const files = fs.readdirSync(folder);
59
+ if (fs.existsSync(path2.join(folder, ".gitignore"))) {
60
+ ig.add(fs.readFileSync(path2.join(folder, ".gitignore"), "utf-8"));
61
+ }
51
62
  for (const file of files) {
52
63
  const filePath = path2.join(folder, file);
64
+ if (ig.ignores(path2.relative(root, filePath))) {
65
+ continue;
66
+ }
53
67
  if (fs.statSync(filePath).isDirectory()) {
54
- yield* traverseRecursiveFiles(filePath);
68
+ yield* traverseRecursiveFilePaths(filePath, ig, root);
55
69
  } else {
56
- yield new File(filePath);
70
+ yield filePath;
57
71
  }
58
72
  }
59
73
  }
74
+ function* traverseRecursiveFiles(folder) {
75
+ for (const filePath of traverseRecursiveFilePaths(folder)) {
76
+ yield new File(filePath);
77
+ }
78
+ }
79
+
80
+ // src/utils/export.ts
81
+ function extractNamedExports(content) {
82
+ const valueExports = [];
83
+ const typeExports = [];
84
+ const typeDefinitions = /* @__PURE__ */ new Set();
85
+ const typePatterns = [
86
+ /\b(?:type|interface)\s+(\w+)/g,
87
+ /\bexport\s+(?:type|interface)\s+(\w+)/g
88
+ ];
89
+ let match;
90
+ for (const pattern of typePatterns) {
91
+ while ((match = pattern.exec(content)) !== null) {
92
+ typeDefinitions.add(match[1]);
93
+ }
94
+ }
95
+ const exportPatterns = [
96
+ // export const/var/let/function/class/type/interface
97
+ /\bexport\s+(const|var|let|function|class|type|interface)\s+(\w+)/g,
98
+ // export { name1, name2 }
99
+ /\bexport\s*\{([^}]+)\}/g,
100
+ // export { name as alias }
101
+ /\bexport\s*\{[^}]*\b(\w+)\s+as\s+(\w+)[^}]*\}/g,
102
+ // export default function name()
103
+ /\bexport\s+default\s+(?:function|class)\s+(\w+)/g,
104
+ // export type { Type1, Type2 }
105
+ /\bexport\s+type\s*\{([^}]+)\}/g,
106
+ // export type { Original as Alias }
107
+ /\bexport\s+type\s*\{[^}]*\b(\w+)\s+as\s+(\w+)[^}]*\}/g
108
+ ];
109
+ exportPatterns[0].lastIndex = 0;
110
+ while ((match = exportPatterns[0].exec(content)) !== null) {
111
+ const [, kind, name] = match;
112
+ if (kind === "type" || kind === "interface" || typeDefinitions.has(name)) {
113
+ typeExports.push(name);
114
+ } else {
115
+ valueExports.push(name);
116
+ }
117
+ }
118
+ exportPatterns[1].lastIndex = 0;
119
+ while ((match = exportPatterns[1].exec(content)) !== null) {
120
+ const exportsList = match[1].split(",").map((item) => item.trim()).filter((item) => item && !item.includes(" as "));
121
+ for (const name of exportsList) {
122
+ if (name.startsWith("type ")) {
123
+ typeExports.push(name.replace("type ", "").trim());
124
+ } else if (typeDefinitions.has(name)) {
125
+ typeExports.push(name);
126
+ } else {
127
+ valueExports.push(name);
128
+ }
129
+ }
130
+ }
131
+ exportPatterns[2].lastIndex = 0;
132
+ while ((match = exportPatterns[2].exec(content)) !== null) {
133
+ const [, original, alias] = match;
134
+ if (typeDefinitions.has(original)) {
135
+ typeExports.push(alias);
136
+ } else {
137
+ valueExports.push(alias);
138
+ }
139
+ }
140
+ exportPatterns[3].lastIndex = 0;
141
+ while ((match = exportPatterns[3].exec(content)) !== null) {
142
+ const name = match[1];
143
+ if (typeDefinitions.has(name)) {
144
+ typeExports.push(name);
145
+ } else {
146
+ valueExports.push(name);
147
+ }
148
+ }
149
+ exportPatterns[4].lastIndex = 0;
150
+ while ((match = exportPatterns[4].exec(content)) !== null) {
151
+ const exportsList = match[1].split(",").map((item) => item.trim()).filter((item) => item && !item.includes(" as "));
152
+ for (const name of exportsList) {
153
+ typeExports.push(name);
154
+ }
155
+ }
156
+ exportPatterns[5].lastIndex = 0;
157
+ while ((match = exportPatterns[5].exec(content)) !== null) {
158
+ const [, original, alias] = match;
159
+ typeExports.push(alias);
160
+ }
161
+ return {
162
+ values: [...new Set(valueExports)].sort(),
163
+ types: [...new Set(typeExports)].sort()
164
+ };
165
+ }
60
166
 
61
167
  // src/utils/import.ts
62
168
  function assembleImport(declaration) {
@@ -75,14 +181,10 @@ function assembleImport(declaration) {
75
181
  if (namespaceImport) {
76
182
  importClauses.push(`* as ${namespaceImport}`);
77
183
  }
78
- return `import ${importClauses.join(", ")} from '${source}'`;
79
- }
80
- function replaceImport(fileContent, origin, replaceTo) {
81
- const replaceImportStatements = replaceTo.map(assembleImport);
82
- return fileContent.replace(origin.statement, replaceImportStatements.join("\n"));
184
+ return `import ${importClauses.join(", ")} from '${source}';`;
83
185
  }
84
186
  function* traverseFileImports(fileContent) {
85
- 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;
187
+ 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;
86
188
  let match;
87
189
  while ((match = importRegex.exec(fileContent)) !== null) {
88
190
  const [fullMatch, defaultPart, namespacePart, namedPart, defaultPart2, source] = match;
@@ -127,9 +229,107 @@ function* traverseFileImports(fileContent) {
127
229
  }
128
230
  }
129
231
 
232
+ // src/utils/ts-file.ts
233
+ var TsFile = class extends File {
234
+ constructor(filePath) {
235
+ super(filePath);
236
+ this.exports = {
237
+ values: [],
238
+ types: []
239
+ };
240
+ this.imports = [];
241
+ this.exports = extractNamedExports(fs2.readFileSync(filePath, "utf-8"));
242
+ this.imports = Array.from(
243
+ traverseFileImports(fs2.readFileSync(filePath, "utf-8"))
244
+ );
245
+ }
246
+ get allExportNames() {
247
+ return [...this.exports.values, ...this.exports.types];
248
+ }
249
+ addImport(importDeclarations) {
250
+ importDeclarations.forEach((importDeclaration) => {
251
+ importDeclaration.statement = assembleImport(importDeclaration);
252
+ });
253
+ this.replace((content) => {
254
+ const lastImportStatement = this.imports[this.imports.length - 1];
255
+ return content.replace(
256
+ lastImportStatement.statement,
257
+ `${lastImportStatement?.statement}
258
+ ${importDeclarations.map(
259
+ (item) => item.statement
260
+ )}
261
+ `
262
+ );
263
+ });
264
+ this.imports.push(...importDeclarations);
265
+ }
266
+ removeImport(importDeclarations) {
267
+ this.replace(
268
+ (content) => importDeclarations.reduce(
269
+ (prev, cur) => prev.replace(cur.statement, ""),
270
+ content
271
+ )
272
+ );
273
+ this.imports = this.imports.filter(
274
+ (item) => !importDeclarations.includes(item)
275
+ );
276
+ }
277
+ replaceImport(oldImports, newImports) {
278
+ newImports.forEach((importDeclaration) => {
279
+ importDeclaration.statement = assembleImport(importDeclaration);
280
+ });
281
+ this.replace((content) => {
282
+ oldImports.forEach((oldImport, idx) => {
283
+ const replaceTo = newImports[idx];
284
+ if (replaceTo) {
285
+ content = content.replace(oldImport.statement, replaceTo.statement);
286
+ this.imports.map((_import) => {
287
+ if (_import.statement === oldImport.statement) {
288
+ _import = replaceTo;
289
+ }
290
+ });
291
+ } else {
292
+ content = content.replace(oldImport.statement, "");
293
+ this.imports = this.imports.filter(
294
+ (_import) => _import.statement !== oldImport.statement
295
+ );
296
+ }
297
+ });
298
+ const restNewImports = newImports.slice(oldImports.length);
299
+ if (restNewImports.length > 0) {
300
+ const lastImportStatement = newImports[oldImports.length - 1].statement;
301
+ content = content.replace(
302
+ lastImportStatement,
303
+ `${lastImportStatement}
304
+ ${restNewImports.map(
305
+ (item) => item.statement
306
+ )}
307
+ `
308
+ );
309
+ }
310
+ this.imports.push(...restNewImports);
311
+ return content;
312
+ });
313
+ }
314
+ };
315
+ function* traverseRecursiveTsFiles(folder) {
316
+ for (const filePath of traverseRecursiveFilePaths(folder)) {
317
+ if (filePath.endsWith(".ts") || filePath.endsWith(".tsx")) {
318
+ yield new TsFile(filePath);
319
+ }
320
+ }
321
+ }
322
+ function getIndexTsFile(folder) {
323
+ const files = fs2.readdirSync(folder);
324
+ for (const file of files) {
325
+ if (file === "index.ts" || file === "index.tsx") {
326
+ return new TsFile(path3.join(folder, file));
327
+ }
328
+ }
329
+ return void 0;
330
+ }
331
+
130
332
  // src/materials/materials.ts
131
- var __filename2 = fileURLToPath2(import.meta.url);
132
- var __dirname2 = path3.dirname(__filename2);
133
333
  var _types = [
134
334
  "components",
135
335
  "effects",
@@ -143,9 +343,9 @@ var _types = [
143
343
  function listAllMaterials(formMaterialSrc) {
144
344
  const _materials = [];
145
345
  for (const _type of _types) {
146
- const materialsPath = path3.join(formMaterialSrc, _type);
346
+ const materialsPath = path4.join(formMaterialSrc, _type);
147
347
  _materials.push(
148
- ...fs2.readdirSync(materialsPath).map((_path) => {
348
+ ...fs3.readdirSync(materialsPath).map((_path) => {
149
349
  if (_path === "index.ts") {
150
350
  return null;
151
351
  }
@@ -153,7 +353,7 @@ function listAllMaterials(formMaterialSrc) {
153
353
  name: _path,
154
354
  // Assuming the folder name is the material name
155
355
  type: _type,
156
- path: path3.join(materialsPath, _path)
356
+ path: path4.join(materialsPath, _path)
157
357
  };
158
358
  }).filter((material) => material !== null)
159
359
  );
@@ -161,50 +361,47 @@ function listAllMaterials(formMaterialSrc) {
161
361
  return _materials;
162
362
  }
163
363
  var getFormMaterialDependencies = (formMaterialPath) => {
164
- const packageJsonPath = path3.join(formMaterialPath, "package.json");
165
- const packageJson = JSON.parse(fs2.readFileSync(packageJsonPath, "utf8"));
364
+ const packageJsonPath = path4.join(formMaterialPath, "package.json");
365
+ const packageJson = JSON.parse(fs3.readFileSync(packageJsonPath, "utf8"));
166
366
  return packageJson.dependencies;
167
367
  };
168
368
  var copyMaterial = (material, project, formMaterialPath) => {
169
369
  const formMaterialDependencies = getFormMaterialDependencies(formMaterialPath);
170
370
  const sourceDir = material.path;
171
- const materialRoot = path3.join(
371
+ const materialRoot = path4.join(
172
372
  project.projectPath,
173
373
  "src",
174
374
  "form-materials",
175
375
  `${material.type}`
176
376
  );
177
- const targetDir = path3.join(materialRoot, material.name);
377
+ const targetDir = path4.join(materialRoot, material.name);
178
378
  const packagesToInstall = /* @__PURE__ */ new Set();
179
- fs2.cpSync(sourceDir, targetDir, { recursive: true });
180
- for (const file of traverseRecursiveFiles(targetDir)) {
181
- if ([".ts", ".tsx"].includes(file.suffix)) {
182
- for (const importDeclaration of traverseFileImports(file.content)) {
183
- const { source } = importDeclaration;
184
- if (source.startsWith("@/")) {
185
- console.log(
186
- `Replace Import from ${source} to @flowgram.ai/form-materials`
187
- );
188
- file.replace(
189
- (content) => replaceImport(content, importDeclaration, [
190
- { ...importDeclaration, source: "@flowgram.ai/form-materials" }
191
- ])
192
- );
193
- packagesToInstall.add(
194
- `@flowgram.ai/form-materials@${project.flowgramVersion}`
195
- );
196
- } else if (!source.startsWith(".") && !source.startsWith("react")) {
197
- const [dep, version] = Object.entries(formMaterialDependencies).find(
198
- ([_key]) => source.startsWith(_key)
199
- ) || [];
200
- if (!dep) {
201
- continue;
202
- }
203
- if (dep.startsWith("@flowgram.ai/")) {
204
- packagesToInstall.add(`${dep}@${project.flowgramVersion}`);
205
- } else {
206
- packagesToInstall.add(`${dep}@${version}`);
207
- }
379
+ fs3.cpSync(sourceDir, targetDir, { recursive: true });
380
+ for (const file of traverseRecursiveTsFiles(targetDir)) {
381
+ for (const importDeclaration of file.imports) {
382
+ const { source } = importDeclaration;
383
+ if (source.startsWith("@/")) {
384
+ console.log(
385
+ `Replace Import from ${source} to @flowgram.ai/form-materials`
386
+ );
387
+ file.replaceImport(
388
+ [importDeclaration],
389
+ [{ ...importDeclaration, source: "@flowgram.ai/form-materials" }]
390
+ );
391
+ packagesToInstall.add(
392
+ `@flowgram.ai/form-materials@${project.flowgramVersion}`
393
+ );
394
+ } else if (!source.startsWith(".") && !source.startsWith("react")) {
395
+ const [dep, version] = Object.entries(formMaterialDependencies).find(
396
+ ([_key]) => source.startsWith(_key)
397
+ ) || [];
398
+ if (!dep) {
399
+ continue;
400
+ }
401
+ if (dep.startsWith("@flowgram.ai/")) {
402
+ packagesToInstall.add(`${dep}@${project.flowgramVersion}`);
403
+ } else {
404
+ packagesToInstall.add(`${dep}@${version}`);
208
405
  }
209
406
  }
210
407
  }
@@ -217,14 +414,14 @@ var copyMaterial = (material, project, formMaterialPath) => {
217
414
  // src/utils/npm.ts
218
415
  import { execSync } from "child_process";
219
416
  import { existsSync } from "fs";
220
- import path4 from "path";
417
+ import path5 from "path";
221
418
  import download from "download";
222
419
  async function getLatestVersion(packageName) {
223
420
  return execSync(`npm view ${packageName} version --tag=latest`).toString().trim();
224
421
  }
225
422
  async function loadNpm(packageName) {
226
423
  const packageLatestVersion = await getLatestVersion(packageName);
227
- const packagePath = path4.join(
424
+ const packagePath = path5.join(
228
425
  __dirname,
229
426
  `./.download/${packageName}-${packageLatestVersion}`
230
427
  );
@@ -244,25 +441,26 @@ async function loadNpm(packageName) {
244
441
  }
245
442
 
246
443
  // src/materials/index.ts
247
- import path6 from "path";
444
+ import path7 from "path";
248
445
 
249
446
  // src/utils/project.ts
250
447
  import { existsSync as existsSync2, readFileSync, writeFileSync } from "fs";
251
- import path5 from "path";
448
+ import path6 from "path";
252
449
  import chalk from "chalk";
253
450
  var Project = class _Project {
254
451
  constructor() {
255
452
  }
256
453
  async init() {
257
454
  let projectPath = process.cwd();
258
- while (projectPath !== "/" && !existsSync2(path5.join(projectPath, "package.json"))) {
259
- projectPath = path5.join(projectPath, "..");
455
+ while (projectPath !== "/" && !existsSync2(path6.join(projectPath, "package.json"))) {
456
+ projectPath = path6.join(projectPath, "..");
260
457
  }
261
458
  if (projectPath === "/") {
262
459
  throw new Error("Please run this command in a valid project");
263
460
  }
264
461
  this.projectPath = projectPath;
265
- this.packageJsonPath = path5.join(projectPath, "package.json");
462
+ this.srcPath = path6.join(projectPath, "src");
463
+ this.packageJsonPath = path6.join(projectPath, "package.json");
266
464
  this.packageJson = JSON.parse(readFileSync(this.packageJsonPath, "utf8"));
267
465
  this.flowgramVersion = this.packageJson.dependencies["@flowgram.ai/fixed-layout-editor"] || this.packageJson.dependencies["@flowgram.ai/free-layout-editor"] || this.packageJson.dependencies["@flowgram.ai/editor"];
268
466
  }
@@ -291,6 +489,12 @@ var Project = class _Project {
291
489
  await this.addDependency(dependency);
292
490
  }
293
491
  }
492
+ writeToPackageJsonFile() {
493
+ writeFileSync(
494
+ this.packageJsonPath,
495
+ JSON.stringify(this.packageJson, null, 2)
496
+ );
497
+ }
294
498
  printInfo() {
295
499
  console.log(chalk.bold("Project Info:"));
296
500
  console.log(chalk.black(` - Flowgram Version: ${this.flowgramVersion}`));
@@ -303,18 +507,70 @@ var Project = class _Project {
303
507
  }
304
508
  };
305
509
 
510
+ // src/materials/refresh-project-import.ts
511
+ import chalk2 from "chalk";
512
+ function executeRefreshProjectImport(project, material) {
513
+ const materialFile = getIndexTsFile(material.path);
514
+ if (!materialFile) {
515
+ console.warn(`Material ${material.name} not found`);
516
+ return;
517
+ }
518
+ const targetDir = `@/form-materials/${material.type}/${material.name}`;
519
+ const exportNames = materialFile.allExportNames;
520
+ console.log(`\u{1F440} The exports of ${material.name} is ${exportNames.join(",")}`);
521
+ for (const tsFile of traverseRecursiveTsFiles(project.srcPath)) {
522
+ for (const importDeclaration of tsFile.imports) {
523
+ if (importDeclaration.source === "@flowgram.ai/form-materials") {
524
+ const currentMaterialImports = importDeclaration.namedImports?.filter(
525
+ (item) => exportNames.includes(item.imported)
526
+ );
527
+ if (!currentMaterialImports?.length) {
528
+ continue;
529
+ }
530
+ const nextImports = [
531
+ {
532
+ ...importDeclaration,
533
+ namedImports: currentMaterialImports,
534
+ source: targetDir
535
+ }
536
+ ];
537
+ const keepImportNames = importDeclaration.namedImports?.filter(
538
+ (item) => !exportNames.includes(item.imported)
539
+ );
540
+ if (keepImportNames?.length) {
541
+ nextImports.unshift({
542
+ ...importDeclaration,
543
+ namedImports: keepImportNames
544
+ });
545
+ }
546
+ tsFile.replaceImport([importDeclaration], nextImports);
547
+ console.log(chalk2.green(`\u{1F504} Refresh Imports In: ${tsFile.path}`));
548
+ console.log(
549
+ `From:
550
+ ${importDeclaration.statement}
551
+ To:
552
+ ${nextImports.map((item) => item.statement).join("\n")}`
553
+ );
554
+ }
555
+ }
556
+ }
557
+ }
558
+
306
559
  // src/materials/index.ts
307
- async function syncMaterial(materialName) {
308
- console.log(chalk2.bgGreenBright("Welcome to @flowgram.ai form-materials!"));
560
+ async function syncMaterial(opts) {
561
+ const { materialName, refreshProjectImports } = opts;
562
+ console.log(chalk3.bold("\u{1F680} Welcome to @flowgram.ai form-materials!"));
309
563
  const project = await Project.getSingleton();
310
564
  project.printInfo();
311
565
  if (!project.flowgramVersion) {
312
566
  throw new Error(
313
- "Please install @flowgram.ai/fixed-layout-editor or @flowgram.ai/free-layout-editor"
567
+ chalk3.red(
568
+ "\u274C Please install @flowgram.ai/fixed-layout-editor or @flowgram.ai/free-layout-editor"
569
+ )
314
570
  );
315
571
  }
316
572
  const formMaterialPath = await loadNpm("@flowgram.ai/form-materials");
317
- const formMaterialSrc = path6.join(formMaterialPath, "src");
573
+ const formMaterialSrc = path7.join(formMaterialPath, "src");
318
574
  const materials = listAllMaterials(formMaterialSrc);
319
575
  let material;
320
576
  if (materialName) {
@@ -323,10 +579,10 @@ async function syncMaterial(materialName) {
323
579
  );
324
580
  if (selectedMaterial) {
325
581
  material = selectedMaterial;
326
- console.log(chalk2.green(`Using material: ${materialName}`));
582
+ console.log(chalk3.green(`Using material: ${materialName}`));
327
583
  } else {
328
584
  console.log(
329
- chalk2.yellow(
585
+ chalk3.yellow(
330
586
  `Material "${materialName}" not found. Please select from the list:`
331
587
  )
332
588
  );
@@ -349,30 +605,34 @@ async function syncMaterial(materialName) {
349
605
  material = result.material;
350
606
  }
351
607
  if (!material) {
352
- console.error(chalk2.red("No material selected. Exiting."));
608
+ console.error(chalk3.red("No material selected. Exiting."));
353
609
  process.exit(1);
354
610
  }
611
+ if (refreshProjectImports) {
612
+ console.log(chalk3.bold("\u{1F680} Refresh imports in your project"));
613
+ executeRefreshProjectImport(project, material);
614
+ }
355
615
  console.log(
356
- chalk2.bold("The following materials will be added to your project")
616
+ chalk3.bold("\u{1F680} The following materials will be added to your project")
357
617
  );
358
618
  console.log(material);
359
619
  let { packagesToInstall } = copyMaterial(material, project, formMaterialPath);
360
620
  await project.addDependencies(packagesToInstall);
361
621
  console.log(
362
- chalk2.bold("These npm dependencies is added to your package.json")
622
+ chalk3.bold("\u2705 These npm dependencies is added to your package.json")
363
623
  );
364
624
  packagesToInstall.forEach((_package) => {
365
625
  console.log(`- ${_package}`);
366
626
  });
367
- console.log(chalk2.bold("\nPlease run npm install to install dependencies"));
627
+ console.log(chalk3.bold("\n\u27A1\uFE0F Please run npm install to install dependencies\n"));
368
628
  }
369
629
 
370
630
  // src/create-app/index.ts
371
- import path7 from "path";
631
+ import path8 from "path";
372
632
  import { execSync as execSync2 } from "child_process";
373
633
  import inquirer2 from "inquirer";
374
- import fs3 from "fs-extra";
375
- import chalk3 from "chalk";
634
+ import fs4 from "fs-extra";
635
+ import chalk4 from "chalk";
376
636
  import download2 from "download";
377
637
  import * as tar from "tar";
378
638
  var args = process.argv.slice(2);
@@ -384,7 +644,7 @@ var updateFlowGramVersions = (dependencies, latestVersion) => {
384
644
  }
385
645
  };
386
646
  var createApp = async (projectName) => {
387
- console.log(chalk3.green("Welcome to @flowgram.ai/create-app CLI!"));
647
+ console.log(chalk4.green("Welcome to @flowgram.ai/create-app CLI!"));
388
648
  const latest = execSync2("npm view @flowgram.ai/demo-fixed-layout version --tag=latest latest").toString().trim();
389
649
  let folderName = "";
390
650
  if (!projectName) {
@@ -414,19 +674,19 @@ var createApp = async (projectName) => {
414
674
  }
415
675
  }
416
676
  try {
417
- const targetDir = path7.join(process.cwd());
677
+ const targetDir = path8.join(process.cwd());
418
678
  const downloadPackage = async () => {
419
679
  try {
420
680
  const tarballBuffer = await download2(`https://registry.npmjs.org/@flowgram.ai/${folderName}/-/${folderName}-${latest}.tgz`);
421
- fs3.ensureDirSync(targetDir);
422
- const tempTarballPath = path7.join(process.cwd(), `${folderName}.tgz`);
423
- fs3.writeFileSync(tempTarballPath, tarballBuffer);
681
+ fs4.ensureDirSync(targetDir);
682
+ const tempTarballPath = path8.join(process.cwd(), `${folderName}.tgz`);
683
+ fs4.writeFileSync(tempTarballPath, tarballBuffer);
424
684
  await tar.x({
425
685
  file: tempTarballPath,
426
686
  C: targetDir
427
687
  });
428
- fs3.renameSync(path7.join(targetDir, "package"), path7.join(targetDir, folderName));
429
- fs3.unlinkSync(tempTarballPath);
688
+ fs4.renameSync(path8.join(targetDir, "package"), path8.join(targetDir, folderName));
689
+ fs4.unlinkSync(tempTarballPath);
430
690
  return true;
431
691
  } catch (error) {
432
692
  console.error(`Error downloading or extracting package: ${error}`);
@@ -434,8 +694,8 @@ var createApp = async (projectName) => {
434
694
  }
435
695
  };
436
696
  const res = await downloadPackage();
437
- const pkgJsonPath = path7.join(targetDir, folderName, "package.json");
438
- const data = fs3.readFileSync(pkgJsonPath, "utf-8");
697
+ const pkgJsonPath = path8.join(targetDir, folderName, "package.json");
698
+ const data = fs4.readFileSync(pkgJsonPath, "utf-8");
439
699
  const packageLatestVersion = execSync2("npm view @flowgram.ai/core version --tag=latest latest").toString().trim();
440
700
  const jsonData = JSON.parse(data);
441
701
  if (jsonData.dependencies) {
@@ -444,15 +704,15 @@ var createApp = async (projectName) => {
444
704
  if (jsonData.devDependencies) {
445
705
  updateFlowGramVersions(jsonData.devDependencies, packageLatestVersion);
446
706
  }
447
- fs3.writeFileSync(pkgJsonPath, JSON.stringify(jsonData, null, 2), "utf-8");
707
+ fs4.writeFileSync(pkgJsonPath, JSON.stringify(jsonData, null, 2), "utf-8");
448
708
  if (res) {
449
- console.log(chalk3.green(`${folderName} Demo project created successfully!`));
450
- console.log(chalk3.yellow("Run the following commands to start:"));
451
- console.log(chalk3.cyan(` cd ${folderName}`));
452
- console.log(chalk3.cyan(" npm install"));
453
- console.log(chalk3.cyan(" npm start"));
709
+ console.log(chalk4.green(`${folderName} Demo project created successfully!`));
710
+ console.log(chalk4.yellow("Run the following commands to start:"));
711
+ console.log(chalk4.cyan(` cd ${folderName}`));
712
+ console.log(chalk4.cyan(" npm install"));
713
+ console.log(chalk4.cyan(" npm start"));
454
714
  } else {
455
- console.log(chalk3.red("Download failed"));
715
+ console.log(chalk4.red("Download failed"));
456
716
  }
457
717
  } catch (error) {
458
718
  console.error("Error downloading repo:", error);
@@ -460,13 +720,63 @@ var createApp = async (projectName) => {
460
720
  }
461
721
  };
462
722
 
723
+ // src/update-version/index.ts
724
+ import chalk5 from "chalk";
725
+ async function updateFlowgramVersion(inputVersion) {
726
+ console.log(chalk5.bold("\u{1F680} Welcome to @flowgram.ai update-version helper"));
727
+ const latestVersion = await getLatestVersion("@flowgram.ai/editor");
728
+ const currentPath = process.cwd();
729
+ console.log("- Latest flowgram version: ", latestVersion);
730
+ console.log("- Current Path: ", currentPath);
731
+ const flowgramVersion = inputVersion || latestVersion;
732
+ for (const file of traverseRecursiveFiles(currentPath)) {
733
+ if (file.path.endsWith("package.json")) {
734
+ console.log("\u{1F440} Find package.json: ", file.path);
735
+ let updated = false;
736
+ const json = JSON.parse(file.content);
737
+ if (json.dependencies) {
738
+ for (const key in json.dependencies) {
739
+ if (key.startsWith("@flowgram.ai/")) {
740
+ updated = true;
741
+ json.dependencies[key] = flowgramVersion;
742
+ console.log(`- Update ${key} to ${flowgramVersion}`);
743
+ }
744
+ }
745
+ }
746
+ if (json.devDependencies) {
747
+ for (const key in json.devDependencies) {
748
+ if (key.startsWith("@flowgram.ai/")) {
749
+ updated = true;
750
+ json.devDependencies[key] = flowgramVersion;
751
+ console.log(`- Update ${key} to ${flowgramVersion}`);
752
+ }
753
+ }
754
+ }
755
+ if (updated) {
756
+ file.write(JSON.stringify(json, null, 2));
757
+ console.log(`\u2705 ${file.path} Updated`);
758
+ }
759
+ }
760
+ }
761
+ }
762
+
463
763
  // src/index.ts
464
764
  var program = new Command();
465
765
  program.name("flowgram-cli").version("1.0.0").description("Flowgram CLI");
466
766
  program.command("create-app").description("Create a new flowgram project").argument("[string]", "Project name").action(async (projectName) => {
467
767
  await createApp(projectName);
468
768
  });
469
- program.command("materials").description("Sync materials to the project").argument("[string]", "Material name").action(async (materialName) => {
470
- await syncMaterial(materialName);
769
+ program.command("materials").description("Sync materials to the project").argument("[string]", "Material name").option(
770
+ "--refresh-project-imports",
771
+ "Refresh project imports to copied materials",
772
+ false
773
+ ).action(async (materialName, options) => {
774
+ await syncMaterial({
775
+ materialName,
776
+ refreshProjectImports: options.refreshProjectImports
777
+ });
778
+ });
779
+ program.command("update-version").description("Update flowgram version in the project").argument("[string]", "Flowgram version").action(async (version) => {
780
+ await updateFlowgramVersion(version);
471
781
  });
472
782
  program.parse(process.argv);