@apso/cli 0.15.2 → 0.15.3
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.
|
@@ -732,13 +732,11 @@ class McpServe extends base_command_1.default {
|
|
|
732
732
|
],
|
|
733
733
|
};
|
|
734
734
|
}
|
|
735
|
-
// File the issue
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
timeout: 30000,
|
|
741
|
-
}).trim();
|
|
735
|
+
// File the issue. fileIssue passes the title as a discrete argv
|
|
736
|
+
// element and the body via a temp file (execFile, shell: false), so
|
|
737
|
+
// backticks / $() / quotes in user-supplied content are never
|
|
738
|
+
// shell-evaluated (no command injection).
|
|
739
|
+
const url = (0, runner_1.fileIssue)(title, body);
|
|
742
740
|
return {
|
|
743
741
|
content: [
|
|
744
742
|
{
|
|
@@ -14,6 +14,14 @@ export declare function formatFindings(findings: DiagnosticFinding[]): string;
|
|
|
14
14
|
* Check if the GitHub CLI is installed and authenticated.
|
|
15
15
|
*/
|
|
16
16
|
export declare function isGhAvailable(): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Build the argv array for `gh issue list --search`.
|
|
19
|
+
*
|
|
20
|
+
* Pure function (no side effects) so it can be unit-tested. The search query
|
|
21
|
+
* is returned as its own array element and is NEVER concatenated into a shell
|
|
22
|
+
* string, so backticks / quotes / `$()` in the title are treated literally.
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildIssueSearchArgs(title: string): string[];
|
|
17
25
|
/**
|
|
18
26
|
* Search for existing issues that might duplicate what we're about to file.
|
|
19
27
|
*/
|
|
@@ -22,6 +30,27 @@ export declare function searchExistingIssues(title: string): {
|
|
|
22
30
|
title: string;
|
|
23
31
|
url: string;
|
|
24
32
|
}[];
|
|
33
|
+
/**
|
|
34
|
+
* Build the argv array for `gh issue create`.
|
|
35
|
+
*
|
|
36
|
+
* Pure function (no side effects) so it can be unit-tested. The title is
|
|
37
|
+
* returned as its own array element directly after `--title` and the body is
|
|
38
|
+
* passed via `--body-file <path>`. Nothing is concatenated into a shell string,
|
|
39
|
+
* so backticks / `$()` / quotes / newlines in the title are passed literally
|
|
40
|
+
* (no command substitution, no injection).
|
|
41
|
+
*/
|
|
42
|
+
export declare function buildIssueCreateArgs(title: string, bodyFilePath: string): string[];
|
|
43
|
+
/**
|
|
44
|
+
* File a GitHub issue with an arbitrary title and body.
|
|
45
|
+
*
|
|
46
|
+
* The body is written to a temp file and passed via `--body-file`, and the
|
|
47
|
+
* title is passed as a discrete argv element via execFile (shell: false). The
|
|
48
|
+
* child's stdin is explicitly not inherited from the parent so it cannot
|
|
49
|
+
* consume / blank the body.
|
|
50
|
+
*
|
|
51
|
+
* Returns the URL of the created issue.
|
|
52
|
+
*/
|
|
53
|
+
export declare function fileIssue(title: string, body: string): string;
|
|
25
54
|
/**
|
|
26
55
|
* Build and file a GitHub issue from diagnostic findings.
|
|
27
56
|
* Returns the URL of the created issue.
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fileGitHubIssue = exports.searchExistingIssues = exports.isGhAvailable = exports.formatFindings = exports.runDiagnostics = void 0;
|
|
3
|
+
exports.fileGitHubIssue = exports.fileIssue = exports.buildIssueCreateArgs = exports.searchExistingIssues = exports.buildIssueSearchArgs = exports.isGhAvailable = exports.formatFindings = exports.runDiagnostics = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const child_process_1 = require("child_process");
|
|
6
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
6
7
|
const os = tslib_1.__importStar(require("os"));
|
|
8
|
+
const path = tslib_1.__importStar(require("path"));
|
|
7
9
|
const checks_1 = require("./checks");
|
|
8
10
|
/**
|
|
9
11
|
* Run all diagnostic checks and return aggregated findings.
|
|
@@ -74,7 +76,8 @@ function formatFinding(f) {
|
|
|
74
76
|
*/
|
|
75
77
|
function isGhAvailable() {
|
|
76
78
|
try {
|
|
77
|
-
(
|
|
79
|
+
// execFile (shell: false) — no shell interpretation of arguments.
|
|
80
|
+
(0, child_process_1.execFileSync)("gh", ["auth", "status"], { stdio: "ignore" });
|
|
78
81
|
return true;
|
|
79
82
|
}
|
|
80
83
|
catch {
|
|
@@ -82,14 +85,47 @@ function isGhAvailable() {
|
|
|
82
85
|
}
|
|
83
86
|
}
|
|
84
87
|
exports.isGhAvailable = isGhAvailable;
|
|
88
|
+
/**
|
|
89
|
+
* The GitHub repository issues are filed against.
|
|
90
|
+
*/
|
|
91
|
+
const ISSUE_REPO = "apsoai/cli";
|
|
92
|
+
/**
|
|
93
|
+
* Build the argv array for `gh issue list --search`.
|
|
94
|
+
*
|
|
95
|
+
* Pure function (no side effects) so it can be unit-tested. The search query
|
|
96
|
+
* is returned as its own array element and is NEVER concatenated into a shell
|
|
97
|
+
* string, so backticks / quotes / `$()` in the title are treated literally.
|
|
98
|
+
*/
|
|
99
|
+
function buildIssueSearchArgs(title) {
|
|
100
|
+
// Extract key terms from the title for search (passed as a single argv arg).
|
|
101
|
+
const searchQuery = title.slice(0, 100);
|
|
102
|
+
return [
|
|
103
|
+
"issue",
|
|
104
|
+
"list",
|
|
105
|
+
"--repo",
|
|
106
|
+
ISSUE_REPO,
|
|
107
|
+
"--search",
|
|
108
|
+
searchQuery,
|
|
109
|
+
"--state",
|
|
110
|
+
"open",
|
|
111
|
+
"--json",
|
|
112
|
+
"number,title,url",
|
|
113
|
+
"--limit",
|
|
114
|
+
"5",
|
|
115
|
+
];
|
|
116
|
+
}
|
|
117
|
+
exports.buildIssueSearchArgs = buildIssueSearchArgs;
|
|
85
118
|
/**
|
|
86
119
|
* Search for existing issues that might duplicate what we're about to file.
|
|
87
120
|
*/
|
|
88
121
|
function searchExistingIssues(title) {
|
|
89
122
|
try {
|
|
90
|
-
//
|
|
91
|
-
|
|
92
|
-
const result = (0, child_process_1.
|
|
123
|
+
// execFile with an args array (shell: false). The title is passed as a
|
|
124
|
+
// distinct argv element, so it is never shell-evaluated.
|
|
125
|
+
const result = (0, child_process_1.execFileSync)("gh", buildIssueSearchArgs(title), {
|
|
126
|
+
encoding: "utf-8",
|
|
127
|
+
timeout: 15000,
|
|
128
|
+
});
|
|
93
129
|
return JSON.parse(result);
|
|
94
130
|
}
|
|
95
131
|
catch {
|
|
@@ -97,6 +133,56 @@ function searchExistingIssues(title) {
|
|
|
97
133
|
}
|
|
98
134
|
}
|
|
99
135
|
exports.searchExistingIssues = searchExistingIssues;
|
|
136
|
+
/**
|
|
137
|
+
* Build the argv array for `gh issue create`.
|
|
138
|
+
*
|
|
139
|
+
* Pure function (no side effects) so it can be unit-tested. The title is
|
|
140
|
+
* returned as its own array element directly after `--title` and the body is
|
|
141
|
+
* passed via `--body-file <path>`. Nothing is concatenated into a shell string,
|
|
142
|
+
* so backticks / `$()` / quotes / newlines in the title are passed literally
|
|
143
|
+
* (no command substitution, no injection).
|
|
144
|
+
*/
|
|
145
|
+
function buildIssueCreateArgs(title, bodyFilePath) {
|
|
146
|
+
return [
|
|
147
|
+
"issue",
|
|
148
|
+
"create",
|
|
149
|
+
"--repo",
|
|
150
|
+
ISSUE_REPO,
|
|
151
|
+
"--title",
|
|
152
|
+
title,
|
|
153
|
+
"--body-file",
|
|
154
|
+
bodyFilePath,
|
|
155
|
+
];
|
|
156
|
+
}
|
|
157
|
+
exports.buildIssueCreateArgs = buildIssueCreateArgs;
|
|
158
|
+
/**
|
|
159
|
+
* File a GitHub issue with an arbitrary title and body.
|
|
160
|
+
*
|
|
161
|
+
* The body is written to a temp file and passed via `--body-file`, and the
|
|
162
|
+
* title is passed as a discrete argv element via execFile (shell: false). The
|
|
163
|
+
* child's stdin is explicitly not inherited from the parent so it cannot
|
|
164
|
+
* consume / blank the body.
|
|
165
|
+
*
|
|
166
|
+
* Returns the URL of the created issue.
|
|
167
|
+
*/
|
|
168
|
+
function fileIssue(title, body) {
|
|
169
|
+
const bodyFilePath = path.join(fs.mkdtempSync(path.join(os.tmpdir(), "apso-issue-")), "body.md");
|
|
170
|
+
try {
|
|
171
|
+
fs.writeFileSync(bodyFilePath, body, "utf-8");
|
|
172
|
+
const result = (0, child_process_1.execFileSync)("gh", buildIssueCreateArgs(title, bodyFilePath), {
|
|
173
|
+
encoding: "utf-8",
|
|
174
|
+
timeout: 30000,
|
|
175
|
+
// Do not pipe the parent's stdin into the child (the body is supplied via
|
|
176
|
+
// file). stdout/stderr are captured by execFileSync.
|
|
177
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
178
|
+
});
|
|
179
|
+
return result.trim();
|
|
180
|
+
}
|
|
181
|
+
finally {
|
|
182
|
+
fs.rmSync(path.dirname(bodyFilePath), { recursive: true, force: true });
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
exports.fileIssue = fileIssue;
|
|
100
186
|
/**
|
|
101
187
|
* Build and file a GitHub issue from diagnostic findings.
|
|
102
188
|
* Returns the URL of the created issue.
|
|
@@ -105,12 +191,7 @@ function fileGitHubIssue(findings, ctx) {
|
|
|
105
191
|
const pkg = loadCliVersion();
|
|
106
192
|
const title = buildIssueTitle(findings);
|
|
107
193
|
const body = buildIssueBody(findings, ctx, pkg);
|
|
108
|
-
|
|
109
|
-
input: body,
|
|
110
|
-
encoding: "utf-8",
|
|
111
|
-
timeout: 30000,
|
|
112
|
-
});
|
|
113
|
-
return result.trim();
|
|
194
|
+
return fileIssue(title, body);
|
|
114
195
|
}
|
|
115
196
|
exports.fileGitHubIssue = fileGitHubIssue;
|
|
116
197
|
function loadCliVersion() {
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
@Column({
|
|
4
4
|
type: 'enum',
|
|
5
5
|
nullable: <%= Boolean(field.nullable) %>,
|
|
6
|
-
enum: enums.<%= field.dataType%>,
|
|
7
|
-
default: enums.<%= field.dataType%>.<%= field.default.toLowerCase().replace(/[^a-z0-9]/g, '_').replace(/^(\d)/, '_$1').replace(/_+/g, '_').replace(/_$/, '') %>
|
|
6
|
+
enum: enums.<%= field.dataType%><% if (field.default !== null) { %>,
|
|
7
|
+
default: enums.<%= field.dataType%>.<%= field.default.toLowerCase().replace(/[^a-z0-9]/g, '_').replace(/^(\d)/, '_$1').replace(/_+/g, '_').replace(/_$/, '') %><% } %>
|
|
8
8
|
})
|
|
9
9
|
<% if (field.index ) {%>
|
|
10
10
|
@Index()
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apso/cli",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@apso/cli",
|
|
9
|
-
"version": "0.15.
|
|
9
|
+
"version": "0.15.3",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@electric-sql/pglite": "^0.2.17",
|
package/oclif.manifest.json
CHANGED