Skip to content

Commit 4c079da

Browse files
committed
Show cli warnings when listing dbcontexts or migrations. Fixes #35
1 parent 6140032 commit 4c079da

11 files changed

+132
-102
lines changed

sample_dotnet/ExampleAPI/Context/BloggingContext.cs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,9 @@ public class BloggingContext : DbContext
1111

1212
public DbSet<Tag> Tags { get; set; }
1313

14-
public string DbPath { get; private set; }
15-
16-
public BloggingContext()
17-
{
18-
DbPath = $"blogging.db";
19-
}
20-
2114
protected override void OnConfiguring(DbContextOptionsBuilder options)
2215
{
23-
options.UseSqlite($"Data Source={DbPath}");
16+
options.UseSqlite($"Data Source=blogging.db");
2417
options.LogTo(Console.WriteLine);
2518
options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
2619
}

sample_dotnet/ExampleAPI/blogging.db

0 Bytes
Binary file not shown.

src/actions/DBContextInfoCommandAction.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as vscode from 'vscode';
22

3-
import { CLI } from '../cli/CLI';
3+
import { EFOutputParser } from '../cli/EFOutputParser';
44
import { getCommandsConfig } from '../config/config';
55
import { TREE_VIEW_ID } from '../constants/constants';
66

@@ -42,14 +42,12 @@ export class DBContextInfoCommandAction extends TerminalAction {
4242
removeDataFromOutput: true,
4343
asJson: true,
4444
});
45-
const output = CLI.getDataFromStdOut(await this.getOutput());
46-
const uri = vscode.Uri.parse(
47-
`${TextDocumentProvider.scheme}:${output}`,
48-
);
45+
const { data } = EFOutputParser.parse(await this.getOutput());
46+
const uri = vscode.Uri.parse(`${TextDocumentProvider.scheme}:${data}`);
4947
const doc = await vscode.workspace.openTextDocument(uri);
5048
await vscode.languages.setTextDocumentLanguage(doc, 'json');
5149
await vscode.window.showTextDocument(doc, { preview: false });
52-
return output;
50+
return data;
5351
},
5452
);
5553
}

src/actions/GenerateERDAction.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import path from 'path';
44
import fs from 'fs';
55
import util from 'util';
66

7-
import { CLI } from '../cli/CLI';
87
import { getCommandsConfig, getERDConfig } from '../config/config';
98
import { TerminalAction } from './TerminalAction';
109
import { DEFAULT_EFCORE_PROVIDERS, TREE_VIEW_ID } from '../constants/constants';
@@ -18,6 +17,7 @@ import type { Logger } from '../util/Logger';
1817

1918
// @ts-ignore
2019
import mermaidTemplate from '../templates/DbContext.Mermaid.t4';
20+
import { EFOutputParser } from '../cli/EFOutputParser';
2121

2222
const copyFile = util.promisify(fs.copyFile);
2323
const rename = util.promisify(fs.rename);
@@ -162,7 +162,7 @@ export class GenerateERDAction extends TerminalAction {
162162
},
163163
);
164164
const output = await this.getOutput();
165-
const data = CLI.getDataFromStdOut(await this.getOutput());
165+
const { data } = EFOutputParser.parse(output);
166166
const result = JSON.parse(data) as ScaffoldResult;
167167

168168
const fileContents = fs.readFileSync(result.contextFile, 'utf-8');

src/actions/GenerateScriptAction.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as vscode from 'vscode';
22

3-
import { CLI } from '../cli/CLI';
3+
import { EFOutputParser } from '../cli/EFOutputParser';
44
import { getCommandsConfig } from '../config/config';
55
import { TREE_VIEW_ID } from '../constants/constants';
66
import type { TerminalProvider } from '../terminal/TerminalProvider';
@@ -40,7 +40,7 @@ export class GenerateScriptAction extends TerminalAction {
4040
removeDataFromOutput: true,
4141
});
4242
const output = await this.getOutput();
43-
const data = CLI.getDataFromStdOut(output);
43+
const { data } = EFOutputParser.parse(output);
4444
const uri = vscode.Uri.parse(`${TextDocumentProvider.scheme}:${data}`);
4545
const doc = await vscode.workspace.openTextDocument(uri);
4646
await vscode.languages.setTextDocumentLanguage(doc, 'sql');

src/actions/ScaffoldAction.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Project } from 'nuget-deps-tree';
22
import * as vscode from 'vscode';
3-
import { CLI } from '../cli/CLI';
3+
import { EFOutputParser } from '../cli/EFOutputParser';
44
import { CommandProvider } from '../commands/CommandProvider';
55
import { RefreshTreeCommand } from '../commands/RefreshTreeCommand';
66
import { getCommandsConfig } from '../config/config';
@@ -136,10 +136,9 @@ export class ScaffoldAction extends TerminalAction {
136136
asJson: true,
137137
},
138138
);
139-
const output = JSON.parse(
140-
CLI.getDataFromStdOut(await this.getOutput()),
141-
) as ScaffoldResult;
142139

140+
const { data } = EFOutputParser.parse(await this.getOutput());
141+
const output = JSON.parse(data) as ScaffoldResult;
143142
const uri = vscode.Uri.file(output.contextFile);
144143
const doc = await vscode.workspace.openTextDocument(uri);
145144
await vscode.window.showTextDocument(doc);

src/cli/CLI.ts

Lines changed: 8 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@ import type { ChildProcess } from 'child_process';
22
import { spawn } from 'child_process';
33

44
import { getEnvConfig } from '../config/config';
5-
import { TerminalColors } from '../terminal/TerminalColors';
65
import type { Logger } from '../util/Logger';
7-
8-
const NEWLINE_SEPARATOR = /\r\n|\r|\n/;
9-
const OUTPUT_PREFIX = /^([a-z]+:([\s]{4}|[\s]{3}))/;
6+
import { EFOutputParser } from './EFOutputParser';
107

118
export type ExecOpts = {
129
cmdArgs: string[];
@@ -29,67 +26,6 @@ export type ExecProcess = {
2926
export class CLI {
3027
constructor(private readonly logger: Logger) {}
3128

32-
public static getDataFromStdOut(output: string): string {
33-
return this.stripPrefixFromStdOut(
34-
output
35-
.split(NEWLINE_SEPARATOR)
36-
.filter(line => line.startsWith('data:'))
37-
.join('\n'),
38-
);
39-
}
40-
41-
public static getErrorsFromStdOut(output: string): string {
42-
return this.stripPrefixFromStdOut(
43-
output
44-
.split(NEWLINE_SEPARATOR)
45-
.filter(line => line.startsWith('error:'))
46-
.join('\n'),
47-
);
48-
}
49-
50-
private static filter(out: string, prefix: string) {
51-
return out
52-
.split(NEWLINE_SEPARATOR)
53-
.filter(line => !line.trim().startsWith(prefix))
54-
.join('\n');
55-
}
56-
57-
public static filterInfoFromOutput(out: string): string {
58-
return this.filter(out, 'info:');
59-
}
60-
61-
public static filterDataFromOutput(out: string): string {
62-
return this.filter(out, 'data:');
63-
}
64-
65-
public static colorizeOutput(output: string): string {
66-
return output
67-
.split(NEWLINE_SEPARATOR)
68-
.map(line => {
69-
if (line.startsWith('warn:')) {
70-
return (
71-
line.replace(OUTPUT_PREFIX, `$1${TerminalColors.yellow}`) +
72-
TerminalColors.reset
73-
);
74-
}
75-
if (line.startsWith('error:')) {
76-
return (
77-
line.replace(OUTPUT_PREFIX, `$1${TerminalColors.red}`) +
78-
TerminalColors.reset
79-
);
80-
}
81-
return line;
82-
})
83-
.join('\n');
84-
}
85-
86-
public static stripPrefixFromStdOut(output: string): string {
87-
return output
88-
.split(NEWLINE_SEPARATOR)
89-
.map(line => line.replace(OUTPUT_PREFIX, ''))
90-
.join('\n');
91-
}
92-
9329
private getInterpolatedArgs(
9430
args: string[],
9531
params: { [key: string]: string },
@@ -117,12 +53,14 @@ export class CLI {
11753

11854
const args = interpolatedArgs.concat(additionalArgs);
11955

56+
const envConfig = getEnvConfig();
57+
12058
const cmd = spawn(args[0], args.slice(1), {
12159
cwd,
12260
shell: true,
12361
env: {
12462
...process.env,
125-
...getEnvConfig(),
63+
...envConfig,
12664
},
12765
});
12866

@@ -149,10 +87,12 @@ export class CLI {
14987
});
15088

15189
cmd?.on('exit', async code => {
152-
const error = stderr || CLI.getErrorsFromStdOut(stdout);
90+
const error = stderr || EFOutputParser.parse(stdout).errors;
15391
if (error || code !== 0) {
15492
handlers?.onStdOut?.(`Exited with code ${code}\n`);
155-
const finalError = CLI.filterInfoFromOutput(error || stdout);
93+
const finalError = EFOutputParser.filterInfoFromOutput(
94+
error || stdout,
95+
);
15696
rej(new Error(finalError));
15797
} else {
15898
res(stdout);

src/cli/EFOutputParser.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { TerminalColors } from '../terminal/TerminalColors';
2+
3+
const NEWLINE_SEPARATOR = /\r\n|\r|\n/;
4+
const OUTPUT_PREFIX = /^([a-z]+:([\s]{1,4}))/;
5+
6+
export class EFOutputParser {
7+
private static filter(out: string, prefix: string) {
8+
return out
9+
.split(NEWLINE_SEPARATOR)
10+
.filter(line => !line.trim().startsWith(prefix))
11+
.join('\n');
12+
}
13+
14+
public static filterInfoFromOutput(out: string): string {
15+
return this.filter(out, 'info:');
16+
}
17+
18+
public static filterDataFromOutput(out: string): string {
19+
return this.filter(out, 'data:');
20+
}
21+
22+
public static stripPrefixFromStdOut(output: string): string {
23+
return output
24+
.split(NEWLINE_SEPARATOR)
25+
.map(line => line.replace(OUTPUT_PREFIX, ''))
26+
.join('\n');
27+
}
28+
29+
public static colorizeOutput(output: string): string {
30+
return output
31+
.split(NEWLINE_SEPARATOR)
32+
.map(line => {
33+
if (line.startsWith('warn:')) {
34+
return (
35+
line.replace(OUTPUT_PREFIX, `$1${TerminalColors.yellow}`) +
36+
TerminalColors.reset
37+
);
38+
}
39+
if (line.startsWith('error:')) {
40+
return (
41+
line.replace(OUTPUT_PREFIX, `$1${TerminalColors.red}`) +
42+
TerminalColors.reset
43+
);
44+
}
45+
return line;
46+
})
47+
.join('\n');
48+
}
49+
50+
public static parse(output: string) {
51+
let warnings = '';
52+
let data = '';
53+
let errors = '';
54+
let matchedWarning = false;
55+
let matchedError = false;
56+
57+
output.split(NEWLINE_SEPARATOR).forEach(line => {
58+
if (matchedWarning && !OUTPUT_PREFIX.test(line)) {
59+
matchedWarning = true;
60+
} else {
61+
matchedWarning = line.startsWith('warn:');
62+
}
63+
64+
if (matchedError && !OUTPUT_PREFIX.test(line)) {
65+
matchedError = true;
66+
} else {
67+
matchedError = line.startsWith('error:');
68+
}
69+
70+
const matchedData = line.startsWith('data:');
71+
72+
const lineWithoutPrefix = line.replace(OUTPUT_PREFIX, '');
73+
74+
if (matchedWarning) {
75+
warnings += lineWithoutPrefix;
76+
} else if (matchedError) {
77+
errors += lineWithoutPrefix;
78+
} else if (matchedData) {
79+
data += lineWithoutPrefix;
80+
}
81+
});
82+
83+
return {
84+
warnings,
85+
errors,
86+
data,
87+
};
88+
}
89+
}

src/terminal/Terminal.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import type { ChildProcess } from 'child_process';
33

44
import { EventWaiter } from '../util/EventWaiter';
55
import type { ExecOpts, ExecProcess } from '../cli/CLI';
6-
import { CLI } from '../cli/CLI';
6+
import type { CLI } from '../cli/CLI';
77
import { TerminalColors } from './TerminalColors';
8+
import { EFOutputParser } from '../cli/EFOutputParser';
89

910
const NL = '\n';
1011
const CR = '\r';
@@ -39,11 +40,11 @@ export class Terminal implements vscode.Pseudoterminal {
3940
} else {
4041
let line = lineBuffer + buffer;
4142
lineBuffer = '';
42-
line = CLI.colorizeOutput(line);
43+
line = EFOutputParser.colorizeOutput(line);
4344
if (removeDataFromOutput) {
44-
line = CLI.filterDataFromOutput(line);
45+
line = EFOutputParser.filterDataFromOutput(line);
4546
}
46-
this.write(CLI.stripPrefixFromStdOut(line));
47+
this.write(EFOutputParser.stripPrefixFromStdOut(line));
4748
}
4849
};
4950
}

src/treeView/DbContextTreeItem.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import type { Migration } from '../types/Migration';
33
import { getIconPath } from './iconProvider';
44
import { MigrationTreeItem } from './MigrationTreeItem';
55
import { TreeItem } from './TreeItem';
6-
import { CLI } from '../cli/CLI';
6+
import type { CLI } from '../cli/CLI';
77
import { TreeItemCache } from './TreeItemCache';
88
import { ContextValues } from './ContextValues';
99
import type { ProjectFile } from '../types/ProjectFile';
1010
import { getCommandsConfig } from '../config/config';
1111
import type { Logger } from '../util/Logger';
12+
import { EFOutputParser } from '../cli/EFOutputParser';
1213

1314
export const dbContextsCache = new TreeItemCache<MigrationTreeItem[]>();
1415

@@ -58,10 +59,14 @@ export class DbContextTreeItem extends TreeItem {
5859
project: this.projectFile.name,
5960
},
6061
});
62+
const stdOut = await output;
63+
const { data, warnings } = EFOutputParser.parse(stdOut);
6164

62-
const migrations = JSON.parse(
63-
CLI.getDataFromStdOut(await output),
64-
) as Migration[];
65+
if (warnings) {
66+
void vscode.window.showWarningMessage(warnings);
67+
}
68+
69+
const migrations = JSON.parse(data) as Migration[];
6570

6671
const children = migrations.map(
6772
migration =>

0 commit comments

Comments
 (0)