@mrpatronz/nexusflow 1.3.3 → 1.6.0
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/README.md +50 -0
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +85 -44
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +16 -73
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.d.ts +4 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +58 -318
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/finish.d.ts +17 -0
- package/dist/commands/finish.d.ts.map +1 -0
- package/dist/commands/finish.js +173 -0
- package/dist/commands/finish.js.map +1 -0
- package/dist/commands/handoff.d.ts.map +1 -1
- package/dist/commands/handoff.js +11 -6
- package/dist/commands/handoff.js.map +1 -1
- package/dist/commands/knowledge.d.ts +36 -0
- package/dist/commands/knowledge.d.ts.map +1 -0
- package/dist/commands/knowledge.js +184 -0
- package/dist/commands/knowledge.js.map +1 -0
- package/dist/commands/open.d.ts.map +1 -1
- package/dist/commands/open.js +2 -4
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/refresh.d.ts +2 -1
- package/dist/commands/refresh.d.ts.map +1 -1
- package/dist/commands/refresh.js +35 -2
- package/dist/commands/refresh.js.map +1 -1
- package/dist/commands/strategy.d.ts +37 -0
- package/dist/commands/strategy.d.ts.map +1 -0
- package/dist/commands/strategy.js +198 -0
- package/dist/commands/strategy.js.map +1 -0
- package/dist/core/commit.d.ts +41 -0
- package/dist/core/commit.d.ts.map +1 -0
- package/dist/core/commit.js +53 -0
- package/dist/core/commit.js.map +1 -0
- package/dist/core/config.d.ts +3 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +60 -32
- package/dist/core/config.js.map +1 -1
- package/dist/core/config.test.js +24 -0
- package/dist/core/config.test.js.map +1 -1
- package/dist/core/diff.d.ts +27 -0
- package/dist/core/diff.d.ts.map +1 -0
- package/dist/core/diff.js +50 -0
- package/dist/core/diff.js.map +1 -0
- package/dist/core/doctor.d.ts +34 -0
- package/dist/core/doctor.d.ts.map +1 -0
- package/dist/core/doctor.js +276 -0
- package/dist/core/doctor.js.map +1 -0
- package/dist/core/finish.d.ts +56 -0
- package/dist/core/finish.d.ts.map +1 -0
- package/dist/core/finish.js +121 -0
- package/dist/core/finish.js.map +1 -0
- package/dist/core/finish.test.d.ts +2 -0
- package/dist/core/finish.test.d.ts.map +1 -0
- package/dist/core/finish.test.js +110 -0
- package/dist/core/finish.test.js.map +1 -0
- package/dist/core/knowledge.d.ts +96 -0
- package/dist/core/knowledge.d.ts.map +1 -0
- package/dist/core/knowledge.js +299 -0
- package/dist/core/knowledge.js.map +1 -0
- package/dist/core/knowledge.test.d.ts +2 -0
- package/dist/core/knowledge.test.d.ts.map +1 -0
- package/dist/core/knowledge.test.js +157 -0
- package/dist/core/knowledge.test.js.map +1 -0
- package/dist/core/refresh.test.d.ts +2 -0
- package/dist/core/refresh.test.d.ts.map +1 -0
- package/dist/core/refresh.test.js +67 -0
- package/dist/core/refresh.test.js.map +1 -0
- package/dist/core/status.d.ts +45 -0
- package/dist/core/status.d.ts.map +1 -0
- package/dist/core/status.js +45 -0
- package/dist/core/status.js.map +1 -0
- package/dist/core/sync.test.d.ts +2 -0
- package/dist/core/sync.test.d.ts.map +1 -0
- package/dist/core/sync.test.js +86 -0
- package/dist/core/sync.test.js.map +1 -0
- package/dist/core/workspace.create.test.d.ts +2 -0
- package/dist/core/workspace.create.test.d.ts.map +1 -0
- package/dist/core/workspace.create.test.js +95 -0
- package/dist/core/workspace.create.test.js.map +1 -0
- package/dist/core/workspace.d.ts +9 -3
- package/dist/core/workspace.d.ts.map +1 -1
- package/dist/core/workspace.js +91 -13
- package/dist/core/workspace.js.map +1 -1
- package/dist/core/worktree.d.ts +11 -1
- package/dist/core/worktree.d.ts.map +1 -1
- package/dist/core/worktree.js +2 -0
- package/dist/core/worktree.js.map +1 -1
- package/dist/core/worktree.test.d.ts +2 -0
- package/dist/core/worktree.test.d.ts.map +1 -0
- package/dist/core/worktree.test.js +111 -0
- package/dist/core/worktree.test.js.map +1 -0
- package/dist/generators/base.js +1 -1
- package/dist/generators/index.d.ts +7 -0
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +4 -1
- package/dist/generators/index.js.map +1 -1
- package/dist/index.js +205 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +51 -282
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools.d.ts +45 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +413 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +43 -26
- package/dist/server.js.map +1 -1
- package/dist/utils/debug.d.ts +17 -0
- package/dist/utils/debug.d.ts.map +1 -0
- package/dist/utils/debug.js +25 -0
- package/dist/utils/debug.js.map +1 -0
- package/dist/utils/detect-ai.d.ts +14 -6
- package/dist/utils/detect-ai.d.ts.map +1 -1
- package/dist/utils/detect-ai.js +22 -9
- package/dist/utils/detect-ai.js.map +1 -1
- package/dist/utils/detect-ai.test.js +33 -0
- package/dist/utils/detect-ai.test.js.map +1 -1
- package/dist/utils/git.d.ts +13 -2
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +64 -5
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/git.test.js +46 -8
- package/dist/utils/git.test.js.map +1 -1
- package/dist/utils/multi-git.d.ts +40 -0
- package/dist/utils/multi-git.d.ts.map +1 -1
- package/dist/utils/multi-git.js +80 -0
- package/dist/utils/multi-git.js.map +1 -1
- package/dist/utils/multi-git.test.js +54 -1
- package/dist/utils/multi-git.test.js.map +1 -1
- package/dist/utils/open-editor.d.ts +20 -0
- package/dist/utils/open-editor.d.ts.map +1 -0
- package/dist/utils/open-editor.js +44 -0
- package/dist/utils/open-editor.js.map +1 -0
- package/dist/utils/pr.d.ts +50 -0
- package/dist/utils/pr.d.ts.map +1 -0
- package/dist/utils/pr.js +144 -0
- package/dist/utils/pr.js.map +1 -0
- package/dist/utils/pr.test.d.ts +2 -0
- package/dist/utils/pr.test.d.ts.map +1 -0
- package/dist/utils/pr.test.js +47 -0
- package/dist/utils/pr.test.js.map +1 -0
- package/dist/utils/prompts.d.ts +22 -1
- package/dist/utils/prompts.d.ts.map +1 -1
- package/dist/utils/prompts.js +145 -24
- package/dist/utils/prompts.js.map +1 -1
- package/dist/utils/resolve-workspace.d.ts +30 -0
- package/dist/utils/resolve-workspace.d.ts.map +1 -0
- package/dist/utils/resolve-workspace.js +77 -0
- package/dist/utils/resolve-workspace.js.map +1 -0
- package/dist/utils/workflow-advisor.d.ts +2 -0
- package/dist/utils/workflow-advisor.d.ts.map +1 -1
- package/dist/utils/workflow-advisor.js +27 -4
- package/dist/utils/workflow-advisor.js.map +1 -1
- package/package.json +11 -11
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module commands/strategy
|
|
3
|
+
* CLI subcommands for managing teamwork collaboration strategy templates.
|
|
4
|
+
* Provides list, create, edit, and delete operations for strategy templates
|
|
5
|
+
* stored in ~/.nexusflow/workflows/.
|
|
6
|
+
*/
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import { confirm, input, select, editor } from '@inquirer/prompts';
|
|
9
|
+
import { getWorkflowTemplates, saveWorkflowTemplate, deleteWorkflowTemplate, } from '../utils/workflows.js';
|
|
10
|
+
/**
|
|
11
|
+
* Lists all available strategy templates (built-in and custom).
|
|
12
|
+
*/
|
|
13
|
+
export async function strategyListCommand() {
|
|
14
|
+
console.log(chalk.bold.cyan('\n📋 NexusFlow — Strategy Templates\n'));
|
|
15
|
+
const templates = await getWorkflowTemplates();
|
|
16
|
+
if (templates.length === 0) {
|
|
17
|
+
console.log(chalk.yellow(' No strategy templates found.'));
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const builtIn = templates.filter((t) => !t.custom);
|
|
21
|
+
const custom = templates.filter((t) => t.custom);
|
|
22
|
+
if (builtIn.length > 0) {
|
|
23
|
+
console.log(chalk.bold(' Built-in Strategies:'));
|
|
24
|
+
for (const t of builtIn) {
|
|
25
|
+
console.log(` ${chalk.green('●')} ${chalk.bold(t.name)} ${chalk.dim(`(${t.id})`)}`);
|
|
26
|
+
console.log(` ${chalk.dim(t.description)}`);
|
|
27
|
+
}
|
|
28
|
+
console.log();
|
|
29
|
+
}
|
|
30
|
+
if (custom.length > 0) {
|
|
31
|
+
console.log(chalk.bold(' Custom Strategies:'));
|
|
32
|
+
for (const t of custom) {
|
|
33
|
+
console.log(` ${chalk.blue('●')} ${chalk.bold(t.name)} ${chalk.dim(`(${t.id})`)}`);
|
|
34
|
+
console.log(` ${chalk.dim(t.description)}`);
|
|
35
|
+
}
|
|
36
|
+
console.log();
|
|
37
|
+
}
|
|
38
|
+
console.log(chalk.dim(` Total: ${builtIn.length} built-in, ${custom.length} custom\n`));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates a new custom strategy template.
|
|
42
|
+
*/
|
|
43
|
+
export async function strategyCreateCommand(options) {
|
|
44
|
+
console.log(chalk.bold.cyan('\n✏️ NexusFlow — Create Strategy Template\n'));
|
|
45
|
+
const name = options.name || await input({
|
|
46
|
+
message: 'Strategy Name:',
|
|
47
|
+
validate: (value) => value.trim().length > 0 || 'Name cannot be empty',
|
|
48
|
+
});
|
|
49
|
+
let content;
|
|
50
|
+
if (options.file) {
|
|
51
|
+
const { readFile } = await import('node:fs/promises');
|
|
52
|
+
const { existsSync } = await import('node:fs');
|
|
53
|
+
if (!existsSync(options.file)) {
|
|
54
|
+
console.error(chalk.red(` ✖ File not found: ${options.file}`));
|
|
55
|
+
process.exitCode = 1;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
content = await readFile(options.file, 'utf-8');
|
|
59
|
+
console.log(chalk.dim(` Read strategy from ${options.file}`));
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
content = await editor({
|
|
63
|
+
message: 'Write your strategy content (save and close the editor when done):',
|
|
64
|
+
default: `# ${name.trim()}\n\nDescribe your teamwork cooperation guidelines here.\n\n## Guidelines\n\n- \n`,
|
|
65
|
+
waitForUserInput: false,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
if (!content.trim()) {
|
|
69
|
+
console.log(chalk.yellow(' ⚠ Empty content — aborting.'));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
const template = await saveWorkflowTemplate(name.trim(), content.trim());
|
|
74
|
+
console.log(chalk.green(` ✔ Saved strategy: ${chalk.bold(template.name)} (${template.id})`));
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
console.error(chalk.red(` ✖ Failed to save strategy: ${err}`));
|
|
78
|
+
process.exitCode = 1;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Edits an existing custom strategy template.
|
|
83
|
+
*/
|
|
84
|
+
export async function strategyEditCommand(options) {
|
|
85
|
+
console.log(chalk.bold.cyan('\n✏️ NexusFlow — Edit Strategy Template\n'));
|
|
86
|
+
const templates = await getWorkflowTemplates();
|
|
87
|
+
const customTemplates = templates.filter((t) => t.custom);
|
|
88
|
+
if (customTemplates.length === 0) {
|
|
89
|
+
console.log(chalk.yellow(' No custom strategy templates to edit.'));
|
|
90
|
+
console.log(chalk.dim(' Built-in templates cannot be edited. Use "nexusflow strategy create" to make a custom override.\n'));
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
let templateId = options.id;
|
|
94
|
+
if (!templateId) {
|
|
95
|
+
templateId = await select({
|
|
96
|
+
message: 'Select a custom strategy to edit:',
|
|
97
|
+
choices: customTemplates.map((t) => ({
|
|
98
|
+
name: `${t.name} ${chalk.dim(`(${t.id})`)}`,
|
|
99
|
+
value: t.id,
|
|
100
|
+
})),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
const template = customTemplates.find((t) => t.id === templateId);
|
|
104
|
+
if (!template) {
|
|
105
|
+
console.error(chalk.red(` ✖ Custom template "${templateId}" not found.`));
|
|
106
|
+
process.exitCode = 1;
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const content = await editor({
|
|
110
|
+
message: `Editing "${template.name}" (save and close the editor when done):`,
|
|
111
|
+
default: template.content,
|
|
112
|
+
waitForUserInput: false,
|
|
113
|
+
});
|
|
114
|
+
if (!content.trim()) {
|
|
115
|
+
console.log(chalk.yellow(' ⚠ Empty content — no changes saved.'));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
const updated = await saveWorkflowTemplate(template.name, content.trim(), template.id);
|
|
120
|
+
console.log(chalk.green(` ✔ Updated strategy: ${chalk.bold(updated.name)} (${updated.id})`));
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
console.error(chalk.red(` ✖ Failed to save changes: ${err}`));
|
|
124
|
+
process.exitCode = 1;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Deletes a custom strategy template.
|
|
129
|
+
*/
|
|
130
|
+
export async function strategyDeleteCommand(options) {
|
|
131
|
+
console.log(chalk.bold.cyan('\n🗑️ NexusFlow — Delete Strategy Template\n'));
|
|
132
|
+
const templates = await getWorkflowTemplates();
|
|
133
|
+
const customTemplates = templates.filter((t) => t.custom);
|
|
134
|
+
if (customTemplates.length === 0) {
|
|
135
|
+
console.log(chalk.yellow(' No custom strategy templates to delete.\n'));
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
let templateId = options.id;
|
|
139
|
+
if (!templateId) {
|
|
140
|
+
templateId = await select({
|
|
141
|
+
message: 'Select a custom strategy to delete:',
|
|
142
|
+
choices: customTemplates.map((t) => ({
|
|
143
|
+
name: `${t.name} ${chalk.dim(`(${t.id})`)}`,
|
|
144
|
+
value: t.id,
|
|
145
|
+
})),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
const template = customTemplates.find((t) => t.id === templateId);
|
|
149
|
+
if (!template) {
|
|
150
|
+
console.error(chalk.red(` ✖ Custom template "${templateId}" not found.`));
|
|
151
|
+
process.exitCode = 1;
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (!options.yes) {
|
|
155
|
+
const confirmed = await confirm({
|
|
156
|
+
message: `Are you sure you want to delete "${template.name}"?`,
|
|
157
|
+
default: false,
|
|
158
|
+
});
|
|
159
|
+
if (!confirmed) {
|
|
160
|
+
console.log(chalk.dim(' Cancelled.'));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
await deleteWorkflowTemplate(template.id);
|
|
166
|
+
console.log(chalk.green(` ✔ Deleted strategy: ${chalk.bold(template.name)}`));
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
console.error(chalk.red(` ✖ Failed to delete strategy: ${err}`));
|
|
170
|
+
process.exitCode = 1;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Shows the full content of a strategy template.
|
|
175
|
+
*/
|
|
176
|
+
export async function strategyShowCommand(options) {
|
|
177
|
+
const templates = await getWorkflowTemplates();
|
|
178
|
+
let templateId = options.id;
|
|
179
|
+
if (!templateId) {
|
|
180
|
+
templateId = await select({
|
|
181
|
+
message: 'Select a strategy to view:',
|
|
182
|
+
choices: templates.map((t) => ({
|
|
183
|
+
name: `${t.name}${t.custom ? ' (Custom)' : ''} ${chalk.dim(`(${t.id})`)}`,
|
|
184
|
+
value: t.id,
|
|
185
|
+
})),
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
const template = templates.find((t) => t.id === templateId);
|
|
189
|
+
if (!template) {
|
|
190
|
+
console.error(chalk.red(` ✖ Template "${templateId}" not found.`));
|
|
191
|
+
process.exitCode = 1;
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
console.log(chalk.bold.cyan(`\n📄 ${template.name}${template.custom ? chalk.blue(' (Custom)') : ''}\n`));
|
|
195
|
+
console.log(template.content);
|
|
196
|
+
console.log();
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strategy.js","sourceRoot":"","sources":["../../src/commands/strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/commit
|
|
3
|
+
* Headless cross-repo commit engine shared by the CLI, the dashboard server,
|
|
4
|
+
* the MCP server, and the finish flow. The CLI adds its own interactive
|
|
5
|
+
* rendering and dry-run handling around/instead of this; consumers that just
|
|
6
|
+
* need to commit changed repos call this directly.
|
|
7
|
+
*/
|
|
8
|
+
/** Options for {@link commitWorkspace}. */
|
|
9
|
+
export interface WorkspaceCommitOptions {
|
|
10
|
+
/** Skip the `git push` step. */
|
|
11
|
+
noPush?: boolean;
|
|
12
|
+
/** Restrict the commit to these repos (by directory name). */
|
|
13
|
+
repos?: string[];
|
|
14
|
+
}
|
|
15
|
+
/** Per-repo commit outcome. */
|
|
16
|
+
export interface RepoCommitReport {
|
|
17
|
+
name: string;
|
|
18
|
+
success: boolean;
|
|
19
|
+
commitHash: string;
|
|
20
|
+
filesChanged: number;
|
|
21
|
+
message: string;
|
|
22
|
+
}
|
|
23
|
+
/** Aggregate result of committing across a workspace. */
|
|
24
|
+
export interface WorkspaceCommitReport {
|
|
25
|
+
/** Only repos that had changes and were committed (or attempted). */
|
|
26
|
+
repos: RepoCommitReport[];
|
|
27
|
+
committedCount: number;
|
|
28
|
+
failedCount: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Commits (and optionally pushes) every repo in the workspace that has
|
|
32
|
+
* working-tree changes.
|
|
33
|
+
*
|
|
34
|
+
* @param workspacePath - Absolute path to the workspace directory.
|
|
35
|
+
* @param message - Commit message applied to each repo.
|
|
36
|
+
* @param options - Push/repo-filter options.
|
|
37
|
+
* @returns Per-repo reports plus committed/failed counts.
|
|
38
|
+
* @throws If `options.repos` names a repo not in the workspace.
|
|
39
|
+
*/
|
|
40
|
+
export declare function commitWorkspace(workspacePath: string, message: string, options?: WorkspaceCommitOptions): Promise<WorkspaceCommitReport>;
|
|
41
|
+
//# sourceMappingURL=commit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commit.d.ts","sourceRoot":"","sources":["../../src/core/commit.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,2CAA2C;AAC3C,MAAM,WAAW,sBAAsB;IACrC,gCAAgC;IAChC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,+BAA+B;AAC/B,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,yDAAyD;AACzD,MAAM,WAAW,qBAAqB;IACpC,qEAAqE;IACrE,KAAK,EAAE,gBAAgB,EAAE,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,qBAAqB,CAAC,CAsChC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/commit
|
|
3
|
+
* Headless cross-repo commit engine shared by the CLI, the dashboard server,
|
|
4
|
+
* the MCP server, and the finish flow. The CLI adds its own interactive
|
|
5
|
+
* rendering and dry-run handling around/instead of this; consumers that just
|
|
6
|
+
* need to commit changed repos call this directly.
|
|
7
|
+
*/
|
|
8
|
+
import { getWorkspaceRepos, getRepoStatus, commitAndPush, } from '../utils/multi-git.js';
|
|
9
|
+
/**
|
|
10
|
+
* Commits (and optionally pushes) every repo in the workspace that has
|
|
11
|
+
* working-tree changes.
|
|
12
|
+
*
|
|
13
|
+
* @param workspacePath - Absolute path to the workspace directory.
|
|
14
|
+
* @param message - Commit message applied to each repo.
|
|
15
|
+
* @param options - Push/repo-filter options.
|
|
16
|
+
* @returns Per-repo reports plus committed/failed counts.
|
|
17
|
+
* @throws If `options.repos` names a repo not in the workspace.
|
|
18
|
+
*/
|
|
19
|
+
export async function commitWorkspace(workspacePath, message, options) {
|
|
20
|
+
let repos = await getWorkspaceRepos(workspacePath);
|
|
21
|
+
if (options?.repos && options.repos.length > 0) {
|
|
22
|
+
const filter = options.repos;
|
|
23
|
+
const unknown = filter.filter((name) => !repos.some((r) => r.name === name));
|
|
24
|
+
if (unknown.length > 0) {
|
|
25
|
+
throw new Error(`Repositor${unknown.length === 1 ? 'y' : 'ies'} not in this workspace: ${unknown.join(', ')}. ` +
|
|
26
|
+
`Available: ${repos.map((r) => r.name).join(', ')}`);
|
|
27
|
+
}
|
|
28
|
+
repos = repos.filter((r) => filter.includes(r.name));
|
|
29
|
+
}
|
|
30
|
+
const reports = [];
|
|
31
|
+
for (const repo of repos) {
|
|
32
|
+
const status = await getRepoStatus(repo.path);
|
|
33
|
+
if (!status.hasChanges) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const result = await commitAndPush(repo.path, message, repo.branchName, {
|
|
37
|
+
noPush: options?.noPush,
|
|
38
|
+
});
|
|
39
|
+
reports.push({
|
|
40
|
+
name: repo.name,
|
|
41
|
+
success: result.success,
|
|
42
|
+
commitHash: result.commitHash,
|
|
43
|
+
filesChanged: result.filesChanged,
|
|
44
|
+
message: result.message,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
repos: reports,
|
|
49
|
+
committedCount: reports.filter((r) => r.success).length,
|
|
50
|
+
failedCount: reports.filter((r) => !r.success).length,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=commit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commit.js","sourceRoot":"","sources":["../../src/core/commit.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,aAAa,GACd,MAAM,uBAAuB,CAAC;AA2B/B;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,aAAqB,EACrB,OAAe,EACf,OAAgC;IAEhC,IAAI,KAAK,GAAG,MAAM,iBAAiB,CAAC,aAAa,CAAC,CAAC;IAEnD,IAAI,OAAO,EAAE,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAC7B,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC;QAC7E,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,YAAY,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,2BAA2B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;gBAC7F,cAAc,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACtD,CAAC;QACJ,CAAC;QACD,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,OAAO,GAAuB,EAAE,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YACvB,SAAS;QACX,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE;YACtE,MAAM,EAAE,OAAO,EAAE,MAAM;SACxB,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,YAAY,EAAE,MAAM,CAAC,YAAY;YACjC,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,KAAK,EAAE,OAAO;QACd,cAAc,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM;QACvD,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM;KACtD,CAAC;AACJ,CAAC"}
|
package/dist/core/config.d.ts
CHANGED
|
@@ -21,7 +21,9 @@ export declare function ensureConfigDir(): Promise<void>;
|
|
|
21
21
|
*
|
|
22
22
|
* @returns The loaded or default configuration.
|
|
23
23
|
*/
|
|
24
|
-
export declare function loadConfig(
|
|
24
|
+
export declare function loadConfig(options?: {
|
|
25
|
+
quiet?: boolean;
|
|
26
|
+
}): Promise<NexusFlowConfig>;
|
|
25
27
|
/**
|
|
26
28
|
* Persists the given configuration to ~/.nexusflow/config.json.
|
|
27
29
|
* Creates the config directory if it doesn't exist.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AA0CnD;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,eAAe,CAuClD;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAGrD;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,eAAe,CAAC,CAmC5F;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CASvE"}
|
package/dist/core/config.js
CHANGED
|
@@ -5,7 +5,40 @@
|
|
|
5
5
|
import * as fs from 'node:fs/promises';
|
|
6
6
|
import * as path from 'node:path';
|
|
7
7
|
import * as os from 'node:os';
|
|
8
|
+
import chalk from 'chalk';
|
|
8
9
|
import { getStorageProvider, setActiveStorageProvider } from './adapters/registry.js';
|
|
10
|
+
import { debugLog } from '../utils/debug.js';
|
|
11
|
+
/**
|
|
12
|
+
* Activates the configured storage provider, falling back to local storage on
|
|
13
|
+
* failure. Unless `quiet`, a failure prints a visible warning (a silent
|
|
14
|
+
* fallback from e.g. the Obsidian adapter to local is a nasty surprise). The
|
|
15
|
+
* quiet path exists for bootstrap, where plugin-provided adapters are not yet
|
|
16
|
+
* registered and a warning would be a false alarm.
|
|
17
|
+
*/
|
|
18
|
+
function activateStorageProvider(config, quiet) {
|
|
19
|
+
const providerName = config.storageProvider || 'local';
|
|
20
|
+
try {
|
|
21
|
+
const provider = getStorageProvider(providerName);
|
|
22
|
+
const adapterSettings = config.adapterConfig?.[providerName] ?? {};
|
|
23
|
+
if (provider.configure) {
|
|
24
|
+
provider.configure(adapterSettings);
|
|
25
|
+
}
|
|
26
|
+
setActiveStorageProvider(provider);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (!quiet) {
|
|
30
|
+
console.warn(chalk.yellow(`⚠ Storage adapter "${providerName}" failed to activate — falling back to local storage.`));
|
|
31
|
+
}
|
|
32
|
+
debugLog('storage', `activate "${providerName}"`, error);
|
|
33
|
+
// Deterministic fallback rather than relying on the registry's implicit default.
|
|
34
|
+
try {
|
|
35
|
+
setActiveStorageProvider(getStorageProvider('local'));
|
|
36
|
+
}
|
|
37
|
+
catch (fallbackError) {
|
|
38
|
+
debugLog('storage', 'local fallback failed', fallbackError);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
9
42
|
/** Name of the config directory under the user's home folder. */
|
|
10
43
|
const CONFIG_DIR_NAME = '.nexusflow';
|
|
11
44
|
/** Name of the config file. */
|
|
@@ -72,34 +105,38 @@ export async function ensureConfigDir() {
|
|
|
72
105
|
*
|
|
73
106
|
* @returns The loaded or default configuration.
|
|
74
107
|
*/
|
|
75
|
-
export async function loadConfig() {
|
|
108
|
+
export async function loadConfig(options = {}) {
|
|
76
109
|
const configPath = path.join(getConfigDir(), CONFIG_FILE_NAME);
|
|
77
|
-
|
|
110
|
+
const quiet = options.quiet ?? false;
|
|
111
|
+
let merged = getDefaultConfig();
|
|
112
|
+
let raw = null;
|
|
78
113
|
try {
|
|
79
|
-
|
|
80
|
-
const parsed = JSON.parse(raw);
|
|
81
|
-
// Merge with defaults so newly-added keys are always present.
|
|
82
|
-
merged = { ...getDefaultConfig(), ...parsed };
|
|
83
|
-
if (parsed.localLlm) {
|
|
84
|
-
merged.localLlm = { ...getDefaultConfig().localLlm, ...parsed.localLlm };
|
|
85
|
-
}
|
|
114
|
+
raw = await fs.readFile(configPath, 'utf-8');
|
|
86
115
|
}
|
|
87
116
|
catch {
|
|
88
|
-
// File doesn't exist or is unreadable —
|
|
89
|
-
|
|
117
|
+
// File doesn't exist (first run) or is unreadable — defaults are correct.
|
|
118
|
+
raw = null;
|
|
90
119
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
120
|
+
if (raw !== null) {
|
|
121
|
+
try {
|
|
122
|
+
const parsed = JSON.parse(raw);
|
|
123
|
+
// Merge with defaults so newly-added keys are always present.
|
|
124
|
+
merged = { ...getDefaultConfig(), ...parsed };
|
|
125
|
+
if (parsed.localLlm) {
|
|
126
|
+
merged.localLlm = { ...getDefaultConfig().localLlm, ...parsed.localLlm };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
// A corrupted config is worth surfacing — silently reverting devDir /
|
|
131
|
+
// workspacesDir / storageProvider to defaults is a nasty failure mode.
|
|
132
|
+
if (!quiet) {
|
|
133
|
+
console.warn(chalk.yellow('⚠ ~/.nexusflow/config.json is invalid JSON — using defaults for this run.'));
|
|
134
|
+
}
|
|
135
|
+
debugLog('config', 'parse config.json', error);
|
|
136
|
+
merged = getDefaultConfig();
|
|
99
137
|
}
|
|
100
|
-
setActiveStorageProvider(provider);
|
|
101
138
|
}
|
|
102
|
-
|
|
139
|
+
activateStorageProvider(merged, quiet);
|
|
103
140
|
return merged;
|
|
104
141
|
}
|
|
105
142
|
/**
|
|
@@ -113,16 +150,7 @@ export async function saveConfig(config) {
|
|
|
113
150
|
const configPath = path.join(getConfigDir(), CONFIG_FILE_NAME);
|
|
114
151
|
const data = JSON.stringify(config, null, 2) + '\n';
|
|
115
152
|
await fs.writeFile(configPath, data, 'utf-8');
|
|
116
|
-
//
|
|
117
|
-
|
|
118
|
-
const providerName = config.storageProvider || 'local';
|
|
119
|
-
const provider = getStorageProvider(providerName);
|
|
120
|
-
const adapterSettings = config.adapterConfig?.[providerName] ?? {};
|
|
121
|
-
if (provider.configure) {
|
|
122
|
-
provider.configure(adapterSettings);
|
|
123
|
-
}
|
|
124
|
-
setActiveStorageProvider(provider);
|
|
125
|
-
}
|
|
126
|
-
catch { }
|
|
153
|
+
// Re-activate the storage provider based on the saved configuration.
|
|
154
|
+
activateStorageProvider(config, false);
|
|
127
155
|
}
|
|
128
156
|
//# sourceMappingURL=config.js.map
|
package/dist/core/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
|
package/dist/core/config.test.js
CHANGED
|
@@ -59,6 +59,30 @@ describe('config core module', () => {
|
|
|
59
59
|
expect(config.version).toBe('1.0.0');
|
|
60
60
|
expect(config.localLlm?.enabled).toBe(false);
|
|
61
61
|
});
|
|
62
|
+
it('warns and falls back to local on an unknown storage provider', async () => {
|
|
63
|
+
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify({ storageProvider: 'bogus' }));
|
|
64
|
+
const warn = vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
65
|
+
const config = await loadConfig();
|
|
66
|
+
expect(warn).toHaveBeenCalledWith(expect.stringContaining('bogus'));
|
|
67
|
+
expect(config.storageProvider).toBe('bogus');
|
|
68
|
+
warn.mockRestore();
|
|
69
|
+
});
|
|
70
|
+
it('suppresses the storage-fallback warning when quiet', async () => {
|
|
71
|
+
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify({ storageProvider: 'bogus' }));
|
|
72
|
+
const warn = vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
73
|
+
await loadConfig({ quiet: true });
|
|
74
|
+
expect(warn).not.toHaveBeenCalled();
|
|
75
|
+
warn.mockRestore();
|
|
76
|
+
});
|
|
77
|
+
it('warns and returns defaults on invalid JSON', async () => {
|
|
78
|
+
vi.mocked(fs.readFile).mockResolvedValue('{ this is not valid json ');
|
|
79
|
+
const warn = vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
80
|
+
const config = await loadConfig();
|
|
81
|
+
expect(warn).toHaveBeenCalledWith(expect.stringContaining('invalid JSON'));
|
|
82
|
+
expect(config.version).toBe('1.0.0');
|
|
83
|
+
expect(config.localLlm?.enabled).toBe(false);
|
|
84
|
+
warn.mockRestore();
|
|
85
|
+
});
|
|
62
86
|
});
|
|
63
87
|
describe('saveConfig', () => {
|
|
64
88
|
it('should create directory and save configuration', async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/core/config.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/core/config.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/diff
|
|
3
|
+
* Headless cross-repo diff report shared by the CLI `diff` command, the
|
|
4
|
+
* dashboard server, and the MCP `get_workspace_diff` tool. Returns structured
|
|
5
|
+
* data; rendering is the caller's concern.
|
|
6
|
+
*/
|
|
7
|
+
/** Diff summary for a single repo that has changes or unpushed commits. */
|
|
8
|
+
export interface RepoDiffReport {
|
|
9
|
+
name: string;
|
|
10
|
+
filesChanged: number;
|
|
11
|
+
additions: number;
|
|
12
|
+
deletions: number;
|
|
13
|
+
/** Commits ahead of origin, or `null` when the branch was never pushed. */
|
|
14
|
+
unpushed: number | null;
|
|
15
|
+
summary: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Builds a diff report for every repo in the workspace that has working-tree
|
|
19
|
+
* changes or local commits that have not been pushed.
|
|
20
|
+
*
|
|
21
|
+
* @param workspacePath - Absolute path to the workspace directory.
|
|
22
|
+
* @param repos - Optional repo-name filter.
|
|
23
|
+
* @returns One entry per repo with changes; clean+pushed repos are omitted.
|
|
24
|
+
* @throws If `repos` names a repo not in the workspace.
|
|
25
|
+
*/
|
|
26
|
+
export declare function getWorkspaceDiffReport(workspacePath: string, repos?: string[]): Promise<RepoDiffReport[]>;
|
|
27
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/core/diff.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,2EAA2E;AAC3E,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,aAAa,EAAE,MAAM,EACrB,KAAK,CAAC,EAAE,MAAM,EAAE,GACf,OAAO,CAAC,cAAc,EAAE,CAAC,CAyC3B"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/diff
|
|
3
|
+
* Headless cross-repo diff report shared by the CLI `diff` command, the
|
|
4
|
+
* dashboard server, and the MCP `get_workspace_diff` tool. Returns structured
|
|
5
|
+
* data; rendering is the caller's concern.
|
|
6
|
+
*/
|
|
7
|
+
import { getWorkspaceRepos, getRepoStatus, getDiffSummary, getUnpushedCount, } from '../utils/multi-git.js';
|
|
8
|
+
/**
|
|
9
|
+
* Builds a diff report for every repo in the workspace that has working-tree
|
|
10
|
+
* changes or local commits that have not been pushed.
|
|
11
|
+
*
|
|
12
|
+
* @param workspacePath - Absolute path to the workspace directory.
|
|
13
|
+
* @param repos - Optional repo-name filter.
|
|
14
|
+
* @returns One entry per repo with changes; clean+pushed repos are omitted.
|
|
15
|
+
* @throws If `repos` names a repo not in the workspace.
|
|
16
|
+
*/
|
|
17
|
+
export async function getWorkspaceDiffReport(workspacePath, repos) {
|
|
18
|
+
let workspaceRepos = await getWorkspaceRepos(workspacePath);
|
|
19
|
+
if (repos && repos.length > 0) {
|
|
20
|
+
const unknown = repos.filter((name) => !workspaceRepos.some((r) => r.name === name));
|
|
21
|
+
if (unknown.length > 0) {
|
|
22
|
+
throw new Error(`Repositor${unknown.length === 1 ? 'y' : 'ies'} not in this workspace: ${unknown.join(', ')}. ` +
|
|
23
|
+
`Available: ${workspaceRepos.map((r) => r.name).join(', ')}`);
|
|
24
|
+
}
|
|
25
|
+
workspaceRepos = workspaceRepos.filter((r) => repos.includes(r.name));
|
|
26
|
+
}
|
|
27
|
+
const results = [];
|
|
28
|
+
for (const repo of workspaceRepos) {
|
|
29
|
+
const status = await getRepoStatus(repo.path);
|
|
30
|
+
const unpushed = await getUnpushedCount(repo.path, repo.branchName);
|
|
31
|
+
// A repo with no working-tree changes still matters when it has local
|
|
32
|
+
// commits that were never pushed — otherwise "all clean" hides them.
|
|
33
|
+
if (!status.hasChanges && !(unpushed && unpushed > 0)) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const diff = status.hasChanges
|
|
37
|
+
? await getDiffSummary(repo.path)
|
|
38
|
+
: { summary: 'No working-tree changes', additions: 0, deletions: 0 };
|
|
39
|
+
results.push({
|
|
40
|
+
name: repo.name,
|
|
41
|
+
filesChanged: status.changedFiles.length,
|
|
42
|
+
additions: diff.additions,
|
|
43
|
+
deletions: diff.deletions,
|
|
44
|
+
unpushed,
|
|
45
|
+
summary: diff.summary,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return results;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/core/diff.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAa/B;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,aAAqB,EACrB,KAAgB;IAEhB,IAAI,cAAc,GAAG,MAAM,iBAAiB,CAAC,aAAa,CAAC,CAAC;IAE5D,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC;QACrF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,YAAY,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,2BAA2B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;gBAC7F,cAAc,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC/D,CAAC;QACJ,CAAC;QACD,cAAc,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,OAAO,GAAqB,EAAE,CAAC;IAErC,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAEpE,sEAAsE;QACtE,qEAAqE;QACrE,IAAI,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC,QAAQ,IAAI,QAAQ,GAAG,CAAC,CAAC,EAAE,CAAC;YACtD,SAAS;QACX,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU;YAC5B,CAAC,CAAC,MAAM,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;YACjC,CAAC,CAAC,EAAE,OAAO,EAAE,yBAAyB,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;QAEvE,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC,MAAM;YACxC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,QAAQ;YACR,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|