@flowgram.ai/form-materials 0.2.4 → 0.2.6

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.
@@ -1,30 +1,31 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env -S npx tsx@latest
2
2
 
3
- import chalk from 'chalk';
4
- import { Command } from 'commander';
5
3
  import inquirer from 'inquirer';
4
+ import { Command } from 'commander';
5
+ import chalk from 'chalk';
6
6
 
7
- import { bfsMaterials, copyMaterial, listAllMaterials } from './materials.js';
8
- import { getProjectInfo, installDependencies } from './project.js';
7
+ import { getProjectInfo, installDependencies, ProjectInfo } from './project.js';
8
+ import { bfsMaterials, copyMaterial, listAllMaterials, Material } from './materials.js';
9
9
 
10
10
  const program = new Command();
11
11
 
12
12
  program
13
- .version('1.0.0')
13
+ .version('1.0.1')
14
14
  .description('Add official materials to your project')
15
15
  .argument('[materialName]', 'Optional material name to skip selection (format: type/name)')
16
- .action(async (materialName) => {
16
+ .action(async (materialName?: string) => {
17
+ // materialName can be undefined
17
18
  console.log(chalk.bgGreenBright('Welcome to @flowgram.ai/form-materials CLI!'));
18
19
 
19
- const projectInfo = getProjectInfo();
20
+ const projectInfo: ProjectInfo = getProjectInfo();
20
21
 
21
22
  console.log(chalk.bold('Project Info:'));
22
23
  console.log(chalk.black(` - Flowgram Version: ${projectInfo.flowgramVersion}`));
23
24
  console.log(chalk.black(` - Project Path: ${projectInfo.projectPath}`));
24
25
 
25
- const materials = listAllMaterials();
26
+ const materials: Material[] = listAllMaterials();
26
27
 
27
- let material;
28
+ let material: Material | undefined; // material can be undefined
28
29
 
29
30
  // Check if materialName is provided and exists in materials
30
31
  if (materialName) {
@@ -42,7 +43,9 @@ program
42
43
  // If material not found or materialName not provided, prompt user to select
43
44
  if (!material) {
44
45
  // User select one component
45
- const result = await inquirer.prompt([
46
+ const result = await inquirer.prompt<{
47
+ material: Material; // Specify type for prompt result
48
+ }>([
46
49
  {
47
50
  type: 'list',
48
51
  name: 'material',
@@ -57,18 +60,23 @@ program
57
60
  ]);
58
61
  material = result.material;
59
62
  }
63
+ // Ensure material is defined before proceeding
64
+ if (!material) {
65
+ console.error(chalk.red('No material selected. Exiting.'));
66
+ process.exit(1);
67
+ }
60
68
 
61
69
  console.log(material);
62
70
 
63
71
  // 3. Get the component dependencies by BFS (include depMaterials and depPackages)
64
- const { allMaterials, allPackages } = bfsMaterials(material, materials);
72
+ const { allMaterials, allPackages } = bfsMaterials(material!, materials);
65
73
 
66
74
  // 4. Install the dependencies
67
75
  let flowgramPackage = `@flowgram.ai/editor`;
68
76
  if (projectInfo.flowgramVersion !== 'workspace:*') {
69
77
  flowgramPackage = `@flowgram.ai/editor@${projectInfo.flowgramVersion}`;
70
78
  }
71
- const packagesToInstall = [flowgramPackage, ...allPackages];
79
+ const packagesToInstall: string[] = [flowgramPackage, ...allPackages];
72
80
 
73
81
  console.log(chalk.bold('These npm dependencies will be added to your project'));
74
82
  console.log(packagesToInstall);
@@ -77,8 +85,9 @@ program
77
85
  // 5. Copy the materials to the project
78
86
  console.log(chalk.bold('These Materials will be added to your project'));
79
87
  console.log(allMaterials);
80
- allMaterials.forEach((material) => {
81
- copyMaterial(material, projectInfo);
88
+ allMaterials.forEach((mat: Material) => {
89
+ // Add type for mat
90
+ copyMaterial(mat, projectInfo);
82
91
  });
83
92
  });
84
93
 
@@ -0,0 +1,137 @@
1
+ import { fileURLToPath } from 'url';
2
+ import path from 'path';
3
+ import fs from 'fs';
4
+
5
+ import { ProjectInfo } from './project'; // Import ProjectInfo
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+
10
+ // Added type definitions
11
+ export interface Material {
12
+ name: string;
13
+ type: string;
14
+ path: string;
15
+ depPackages?: string[];
16
+ depMaterials?: string[];
17
+ [key: string]: any; // For other properties from config.json
18
+ }
19
+
20
+ const _types: string[] = ['components', 'effects', 'utils', 'typings'];
21
+
22
+ export function listAllMaterials(): Material[] {
23
+ const _materials: Material[] = [];
24
+
25
+ for (const _type of _types) {
26
+ // 在 Node.js 中,import.meta.dirname 不可用,可使用 import.meta.url 结合 url 模块来获取目录路径
27
+
28
+ const materialsPath: string = path.join(__dirname, '..', 'src', _type);
29
+ _materials.push(
30
+ ...fs
31
+ .readdirSync(materialsPath)
32
+ .map((_path: string) => {
33
+ if (_path === 'index.ts') {
34
+ return null;
35
+ }
36
+
37
+ const configPath = path.join(materialsPath, _path, 'config.json');
38
+ // Check if config.json exists before reading
39
+ if (!fs.existsSync(configPath)) {
40
+ console.warn(
41
+ `Warning: config.json not found for material at ${path.join(materialsPath, _path)}`
42
+ );
43
+ return null;
44
+ }
45
+ const configContent = fs.readFileSync(configPath, 'utf8');
46
+ const config = JSON.parse(configContent);
47
+
48
+ return {
49
+ ...config,
50
+ name: _path, // Assuming the folder name is the material name
51
+ type: _type,
52
+ path: path.join(materialsPath, _path),
53
+ } as Material;
54
+ })
55
+ .filter((material): material is Material => material !== null)
56
+ );
57
+ }
58
+
59
+ return _materials;
60
+ }
61
+
62
+ interface BfsResult {
63
+ allMaterials: Material[];
64
+ allPackages: string[];
65
+ }
66
+
67
+ export function bfsMaterials(material: Material, _materials: Material[] = []): BfsResult {
68
+ function findConfigByName(name: string): Material | undefined {
69
+ return _materials.find(
70
+ (_config) => _config.name === name || `${_config.type}/${_config.name}` === name
71
+ );
72
+ }
73
+
74
+ const queue: (Material | undefined)[] = [material]; // Queue can hold undefined if findConfigByName returns undefined
75
+ const allMaterials = new Set<Material>();
76
+ const allPackages = new Set<string>();
77
+
78
+ while (queue.length > 0) {
79
+ const _material = queue.shift();
80
+ if (!_material || allMaterials.has(_material)) {
81
+ // Check if _material is defined
82
+ continue;
83
+ }
84
+ allMaterials.add(_material);
85
+
86
+ if (_material.depPackages) {
87
+ for (const _package of _material.depPackages) {
88
+ allPackages.add(_package);
89
+ }
90
+ }
91
+
92
+ if (_material.depMaterials) {
93
+ for (const _materialName of _material.depMaterials) {
94
+ const depMaterial = findConfigByName(_materialName);
95
+ if (depMaterial) {
96
+ // Ensure dependent material is found before adding to queue
97
+ queue.push(depMaterial);
98
+ } else {
99
+ console.warn(
100
+ `Warning: Dependent material "${_materialName}" not found for material "${_material.name}".`
101
+ );
102
+ }
103
+ }
104
+ }
105
+ }
106
+
107
+ return {
108
+ allMaterials: Array.from(allMaterials),
109
+ allPackages: Array.from(allPackages),
110
+ };
111
+ }
112
+
113
+ export const copyMaterial = (material: Material, projectInfo: ProjectInfo): void => {
114
+ const sourceDir: string = material.path;
115
+ const materialRoot: string = path.join(
116
+ projectInfo.projectPath,
117
+ 'src',
118
+ 'form-materials',
119
+ `${material.type}`
120
+ );
121
+ const targetDir = path.join(materialRoot, material.name);
122
+ fs.cpSync(sourceDir, targetDir, { recursive: true });
123
+
124
+ let materialRootIndexTs: string = '';
125
+ const indexTsPath = path.join(materialRoot, 'index.ts');
126
+ if (fs.existsSync(indexTsPath)) {
127
+ materialRootIndexTs = fs.readFileSync(indexTsPath, 'utf8');
128
+ }
129
+ if (!materialRootIndexTs.includes(material.name)) {
130
+ fs.writeFileSync(
131
+ indexTsPath,
132
+ `${materialRootIndexTs}${materialRootIndexTs.endsWith('\n') ? '' : '\n'}export * from './${
133
+ material.name
134
+ }';\n`
135
+ );
136
+ }
137
+ };
@@ -1,10 +1,25 @@
1
- import { execSync } from 'child_process';
2
- import fs from 'fs';
3
1
  import path from 'path';
2
+ import fs from 'fs';
3
+ import { execSync } from 'child_process';
4
4
 
5
- export function getProjectInfo() {
5
+ // Added type definitions
6
+ interface PackageJson {
7
+ dependencies: { [key: string]: string };
8
+ devDependencies?: { [key: string]: string };
9
+ peerDependencies?: { [key: string]: string };
10
+ [key: string]: any;
11
+ }
12
+
13
+ export interface ProjectInfo {
14
+ projectPath: string;
15
+ packageJsonPath: string;
16
+ packageJson: PackageJson;
17
+ flowgramVersion: string;
18
+ }
19
+
20
+ export function getProjectInfo(): ProjectInfo {
6
21
  // get nearest package.json
7
- let projectPath = process.cwd();
22
+ let projectPath: string = process.cwd();
8
23
 
9
24
  while (projectPath !== '/' && !fs.existsSync(path.join(projectPath, 'package.json'))) {
10
25
  projectPath = path.join(projectPath, '..');
@@ -14,12 +29,11 @@ export function getProjectInfo() {
14
29
  throw new Error('Please run this command in a valid project');
15
30
  }
16
31
 
17
- const packageJsonPath = path.join(projectPath, 'package.json');
18
-
19
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
32
+ const packageJsonPath: string = path.join(projectPath, 'package.json');
33
+ const packageJson: PackageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
20
34
 
21
35
  // fixed layout or free layout
22
- const flowgramVersion =
36
+ const flowgramVersion: string | undefined =
23
37
  packageJson.dependencies['@flowgram.ai/fixed-layout-editor'] ||
24
38
  packageJson.dependencies['@flowgram.ai/free-layout-editor'] ||
25
39
  packageJson.dependencies['@flowgram.ai/editor'];
@@ -34,12 +48,12 @@ export function getProjectInfo() {
34
48
  projectPath,
35
49
  packageJsonPath,
36
50
  packageJson,
37
- flowgramVersion,
51
+ flowgramVersion, // TypeScript will ensure this is string due to the check above
38
52
  };
39
53
  }
40
54
 
41
- export function findRushJson(startPath) {
42
- let currentPath = startPath;
55
+ export function findRushJson(startPath: string): string | null {
56
+ let currentPath: string = startPath;
43
57
  while (currentPath !== '/' && !fs.existsSync(path.join(currentPath, 'rush.json'))) {
44
58
  currentPath = path.join(currentPath, '..');
45
59
  }
@@ -49,7 +63,7 @@ export function findRushJson(startPath) {
49
63
  return null;
50
64
  }
51
65
 
52
- export function installDependencies(packages, projectInfo) {
66
+ export function installDependencies(packages: string[], projectInfo: ProjectInfo): void {
53
67
  if (fs.existsSync(path.join(projectInfo.projectPath, 'yarn.lock'))) {
54
68
  execSync(`yarn add ${packages.join(' ')}`, { stdio: 'inherit' });
55
69
  return;