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