@sylphx/flow 1.0.0 → 1.0.1

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.
@@ -0,0 +1,89 @@
1
+ import {
2
+ fileSystemError
3
+ } from "./chunk-t4fbfa5v.js";
4
+ import {
5
+ tryCatchAsync
6
+ } from "./chunk-nd5fdvaq.js";
7
+ import"./chunk-5j4w74t6.js";
8
+
9
+ // src/composables/functional/useFileSystem.ts
10
+ import fsPromises from "node:fs/promises";
11
+ import path from "node:path";
12
+ var joinPath = (...segments) => path.join(...segments);
13
+ var resolvePath = (...segments) => path.resolve(...segments);
14
+ var dirname = (filePath) => path.dirname(filePath);
15
+ var basename = (filePath, ext) => path.basename(filePath, ext);
16
+ var extname = (filePath) => path.extname(filePath);
17
+ var readFile = async (filePath) => {
18
+ return tryCatchAsync(async () => {
19
+ return await fsPromises.readFile(filePath, "utf-8");
20
+ }, (error) => fileSystemError(`Failed to read file: ${filePath}`, filePath, "read", {
21
+ cause: error instanceof Error ? error : undefined
22
+ }));
23
+ };
24
+ var writeFile = async (filePath, content) => {
25
+ return tryCatchAsync(async () => {
26
+ await fsPromises.writeFile(filePath, content, "utf-8");
27
+ }, (error) => fileSystemError(`Failed to write file: ${filePath}`, filePath, "write", {
28
+ cause: error instanceof Error ? error : undefined
29
+ }));
30
+ };
31
+ var deleteFile = async (filePath) => {
32
+ return tryCatchAsync(async () => {
33
+ await fsPromises.unlink(filePath);
34
+ }, (error) => fileSystemError(`Failed to delete file: ${filePath}`, filePath, "delete", {
35
+ cause: error instanceof Error ? error : undefined
36
+ }));
37
+ };
38
+ var createDirectory = async (dirPath, options) => {
39
+ return tryCatchAsync(async () => {
40
+ await fsPromises.mkdir(dirPath, { recursive: options?.recursive ?? true });
41
+ }, (error) => fileSystemError(`Failed to create directory: ${dirPath}`, dirPath, "create", {
42
+ cause: error instanceof Error ? error : undefined
43
+ }));
44
+ };
45
+ var pathExists = async (filePath) => {
46
+ return tryCatchAsync(async () => {
47
+ try {
48
+ await fsPromises.access(filePath);
49
+ return true;
50
+ } catch {
51
+ return false;
52
+ }
53
+ }, (error) => fileSystemError(`Failed to check if path exists: ${filePath}`, filePath, "stat", {
54
+ cause: error instanceof Error ? error : undefined
55
+ }));
56
+ };
57
+ var readDirectory = async (dirPath) => {
58
+ return tryCatchAsync(async () => {
59
+ return await fsPromises.readdir(dirPath);
60
+ }, (error) => fileSystemError(`Failed to read directory: ${dirPath}`, dirPath, "read", {
61
+ cause: error instanceof Error ? error : undefined
62
+ }));
63
+ };
64
+ var getStats = async (filePath) => {
65
+ return tryCatchAsync(async () => {
66
+ const stats = await fsPromises.stat(filePath);
67
+ return {
68
+ isFile: stats.isFile(),
69
+ isDirectory: stats.isDirectory(),
70
+ size: stats.size
71
+ };
72
+ }, (error) => fileSystemError(`Failed to get stats for: ${filePath}`, filePath, "stat", {
73
+ cause: error instanceof Error ? error : undefined
74
+ }));
75
+ };
76
+ export {
77
+ writeFile,
78
+ resolvePath,
79
+ readFile,
80
+ readDirectory,
81
+ pathExists,
82
+ joinPath,
83
+ getStats,
84
+ extname,
85
+ dirname,
86
+ deleteFile,
87
+ createDirectory,
88
+ basename
89
+ };
@@ -0,0 +1,208 @@
1
+ import {
2
+ getProjectSettingsFile
3
+ } from "./chunk-7eq34c42.js";
4
+ import {
5
+ CLIError
6
+ } from "./chunk-cjd3mk4c.js";
7
+
8
+ // src/core/upgrade-manager.ts
9
+ import fs from "node:fs/promises";
10
+ import path from "node:path";
11
+ import { exec } from "node:child_process";
12
+ import { promisify } from "node:util";
13
+ import ora from "ora";
14
+ var __dirname = "/home/runner/work/flow/flow/packages/flow/src/core";
15
+ var execAsync = promisify(exec);
16
+
17
+ class UpgradeManager {
18
+ projectPath;
19
+ options;
20
+ constructor(projectPath = process.cwd(), options = {}) {
21
+ this.projectPath = projectPath;
22
+ this.options = options;
23
+ }
24
+ async checkUpdates() {
25
+ if (this.options.verbose) {
26
+ console.log("检查更新...");
27
+ }
28
+ const [flowLatest, targetLatest] = await Promise.all([
29
+ this.getLatestFlowVersion(),
30
+ this.getLatestTargetVersion()
31
+ ]);
32
+ let flowVersion = null;
33
+ let targetVersion = null;
34
+ const flowCurrent = await this.getCurrentFlowVersion();
35
+ if (flowLatest && flowCurrent && flowLatest !== flowCurrent) {
36
+ flowVersion = { current: flowCurrent, latest: flowLatest };
37
+ }
38
+ const configPath = path.join(this.projectPath, getProjectSettingsFile());
39
+ try {
40
+ const config = JSON.parse(await fs.readFile(configPath, "utf-8"));
41
+ const target = config.target;
42
+ if (target) {
43
+ const targetCurrent = await this.getCurrentTargetVersion(target);
44
+ if (targetLatest && targetCurrent && targetLatest !== targetCurrent) {
45
+ targetVersion = { current: targetCurrent, latest: targetLatest };
46
+ }
47
+ }
48
+ } catch {}
49
+ return {
50
+ flowUpdate: !!flowVersion,
51
+ targetUpdate: !!targetVersion,
52
+ flowVersion,
53
+ targetVersion
54
+ };
55
+ }
56
+ async upgradeFlow(state) {
57
+ if (!state.outdated || !state.latestVersion) {
58
+ return false;
59
+ }
60
+ const spinner = ora("升级 Sylphx Flow...").start();
61
+ try {
62
+ if (!this.options.skipBackup) {
63
+ await this.backupConfig();
64
+ }
65
+ if (this.options.dryRun) {
66
+ spinner.succeed(`模拟升级: ${state.version} → ${state.latestVersion}`);
67
+ return true;
68
+ }
69
+ const configPath = path.join(this.projectPath, getProjectSettingsFile());
70
+ try {
71
+ const config = JSON.parse(await fs.readFile(configPath, "utf-8"));
72
+ config.version = state.latestVersion;
73
+ config.lastUpdated = new Date().toISOString();
74
+ await fs.writeFile(configPath, JSON.stringify(config, null, 2));
75
+ } catch {}
76
+ spinner.succeed(`已升级到 ${state.latestVersion}`);
77
+ return true;
78
+ } catch (error) {
79
+ spinner.fail("升级失败");
80
+ throw new CLIError(`升级 Sylphx Flow 失败: ${error instanceof Error ? error.message : String(error)}`, "UPGRADE_FAILED");
81
+ }
82
+ }
83
+ async upgradeTarget(state) {
84
+ if (!state.target || !state.targetLatestVersion) {
85
+ return false;
86
+ }
87
+ const spinner = ora(`升级 ${state.target}...`).start();
88
+ try {
89
+ if (state.target === "claude-code") {
90
+ await this.upgradeClaudeCode();
91
+ } else if (state.target === "opencode") {
92
+ await this.upgradeOpenCode();
93
+ }
94
+ spinner.succeed(`${state.target} 已升级到最新版本`);
95
+ return true;
96
+ } catch (error) {
97
+ spinner.fail(`${state.target} 升级失败`);
98
+ throw new CLIError(`升级 ${state.target} 失败: ${error instanceof Error ? error.message : String(error)}`, "TARGET_UPGRADE_FAILED");
99
+ }
100
+ }
101
+ async upgradeClaudeCode() {
102
+ if (this.options.dryRun) {
103
+ console.log("模拟: claude update");
104
+ return;
105
+ }
106
+ const { stdout } = await execAsync("claude update");
107
+ if (this.options.verbose) {
108
+ console.log(stdout);
109
+ }
110
+ }
111
+ async upgradeOpenCode() {
112
+ if (this.options.dryRun) {
113
+ console.log("模拟: opencode upgrade");
114
+ return;
115
+ }
116
+ const { stdout } = await execAsync("opencode upgrade");
117
+ if (this.options.verbose) {
118
+ console.log(stdout);
119
+ }
120
+ }
121
+ async upgradeComponents(components) {
122
+ const upgraded = [];
123
+ for (const component of components) {
124
+ const spinner = ora(`升级 ${component}...`).start();
125
+ try {
126
+ await this.upgradeComponent(component);
127
+ spinner.succeed(`${component} 已升级`);
128
+ upgraded.push(component);
129
+ } catch (error) {
130
+ spinner.fail(`${component} 升级失败`);
131
+ if (this.options.verbose) {
132
+ console.error(error);
133
+ }
134
+ }
135
+ }
136
+ return upgraded;
137
+ }
138
+ async upgradeComponent(component) {
139
+ const componentPath = path.join(this.projectPath, ".claude", component);
140
+ await fs.rm(componentPath, { recursive: true, force: true });
141
+ if (this.options.dryRun) {
142
+ console.log(`模拟: 重新安装 ${component}`);
143
+ }
144
+ }
145
+ async backupConfig() {
146
+ const backupDir = this.options.backupPath || path.join(this.projectPath, ".claude-backup");
147
+ await fs.mkdir(backupDir, { recursive: true });
148
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
149
+ const backupPath = path.join(backupDir, `backup-${timestamp}`);
150
+ const claudePath = path.join(this.projectPath, ".claude");
151
+ try {
152
+ await fs.cp(claudePath, path.join(backupPath, ".claude"), { recursive: true });
153
+ } catch {}
154
+ const configPath = path.join(this.projectPath, getProjectSettingsFile());
155
+ try {
156
+ await fs.cp(configPath, path.join(backupPath, getProjectSettingsFile()));
157
+ } catch {}
158
+ return backupPath;
159
+ }
160
+ async getCurrentFlowVersion() {
161
+ try {
162
+ const configPath = path.join(this.projectPath, getProjectSettingsFile());
163
+ const config = JSON.parse(await fs.readFile(configPath, "utf-8"));
164
+ return config.version || null;
165
+ } catch {
166
+ return null;
167
+ }
168
+ }
169
+ async getLatestFlowVersion() {
170
+ try {
171
+ const packagePath = path.join(__dirname, "..", "..", "package.json");
172
+ const packageJson = JSON.parse(await fs.readFile(packagePath, "utf-8"));
173
+ return packageJson.version || null;
174
+ } catch {
175
+ return null;
176
+ }
177
+ }
178
+ async getCurrentTargetVersion(target) {
179
+ if (target === "claude-code") {
180
+ try {
181
+ const { stdout } = await execAsync("claude --version");
182
+ const match = stdout.match(/v?(\d+\.\d+\.\d+)/);
183
+ return match ? match[1] : null;
184
+ } catch {
185
+ return null;
186
+ }
187
+ }
188
+ return null;
189
+ }
190
+ async getLatestTargetVersion(target) {
191
+ if (target === "claude-code") {
192
+ try {
193
+ const { stdout } = await execAsync("npm view @anthropic-ai/claude-code version");
194
+ return stdout.trim();
195
+ } catch {
196
+ return null;
197
+ }
198
+ }
199
+ return null;
200
+ }
201
+ static async isUpgradeAvailable() {
202
+ const manager = new UpgradeManager;
203
+ const updates = await manager.checkUpdates();
204
+ return updates.flowUpdate || updates.targetUpdate;
205
+ }
206
+ }
207
+
208
+ export { UpgradeManager };