create-mcp-use-app 0.14.17 → 2.0.0-beta.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.
- package/README.md +2 -8
- package/dist/ansi.d.ts +9 -0
- package/dist/ansi.d.ts.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1768 -629
- package/dist/prompts.d.ts +16 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/templates/blank/index.ts +4 -92
- package/dist/templates/blank/package.json +5 -13
- package/dist/templates/blank/tsconfig.json +1 -5
- package/dist/templates/mcp-apps/index.ts +29 -123
- package/dist/templates/mcp-apps/package.json +7 -14
- package/dist/templates/mcp-apps/resources/product-search-result/view.tsx +25 -0
- package/dist/templates/mcp-apps/tools.d.ts +8 -0
- package/dist/templates/mcp-apps/tsconfig.json +8 -14
- package/dist/templates/starter/index.ts +43 -80
- package/dist/templates/starter/package.json +7 -19
- package/dist/templates/starter/tsconfig.json +1 -5
- package/package.json +4 -12
- package/dist/templates/mcp-apps/pnpm-workspace.yaml +0 -2
- package/dist/templates/mcp-apps/resources/product-search-result/components/Accordion.tsx +0 -35
- package/dist/templates/mcp-apps/resources/product-search-result/components/AccordionItem.tsx +0 -32
- package/dist/templates/mcp-apps/resources/product-search-result/components/Carousel.tsx +0 -51
- package/dist/templates/mcp-apps/resources/product-search-result/components/CarouselItem.tsx +0 -54
- package/dist/templates/mcp-apps/resources/product-search-result/components/CarouselSkeleton.tsx +0 -20
- package/dist/templates/mcp-apps/resources/product-search-result/hooks/useCarouselAnimation.ts +0 -78
- package/dist/templates/mcp-apps/resources/product-search-result/types.ts +0 -20
- package/dist/templates/mcp-apps/resources/product-search-result/widget.tsx +0 -288
- package/dist/templates/mcp-apps/resources/styles.css +0 -117
package/dist/index.js
CHANGED
|
@@ -1,35 +1,1269 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
|
|
28
|
+
// ../../node_modules/.pnpm/sisteransi@1.0.5/node_modules/sisteransi/src/index.js
|
|
29
|
+
var require_src = __commonJS({
|
|
30
|
+
"../../node_modules/.pnpm/sisteransi@1.0.5/node_modules/sisteransi/src/index.js"(exports, module) {
|
|
31
|
+
"use strict";
|
|
32
|
+
var ESC2 = "\x1B";
|
|
33
|
+
var CSI2 = `${ESC2}[`;
|
|
34
|
+
var beep = "\x07";
|
|
35
|
+
var cursor3 = {
|
|
36
|
+
to(x, y) {
|
|
37
|
+
if (!y) return `${CSI2}${x + 1}G`;
|
|
38
|
+
return `${CSI2}${y + 1};${x + 1}H`;
|
|
39
|
+
},
|
|
40
|
+
move(x, y) {
|
|
41
|
+
let ret = "";
|
|
42
|
+
if (x < 0) ret += `${CSI2}${-x}D`;
|
|
43
|
+
else if (x > 0) ret += `${CSI2}${x}C`;
|
|
44
|
+
if (y < 0) ret += `${CSI2}${-y}A`;
|
|
45
|
+
else if (y > 0) ret += `${CSI2}${y}B`;
|
|
46
|
+
return ret;
|
|
47
|
+
},
|
|
48
|
+
up: (count = 1) => `${CSI2}${count}A`,
|
|
49
|
+
down: (count = 1) => `${CSI2}${count}B`,
|
|
50
|
+
forward: (count = 1) => `${CSI2}${count}C`,
|
|
51
|
+
backward: (count = 1) => `${CSI2}${count}D`,
|
|
52
|
+
nextLine: (count = 1) => `${CSI2}E`.repeat(count),
|
|
53
|
+
prevLine: (count = 1) => `${CSI2}F`.repeat(count),
|
|
54
|
+
left: `${CSI2}G`,
|
|
55
|
+
hide: `${CSI2}?25l`,
|
|
56
|
+
show: `${CSI2}?25h`,
|
|
57
|
+
save: `${ESC2}7`,
|
|
58
|
+
restore: `${ESC2}8`
|
|
59
|
+
};
|
|
60
|
+
var scroll = {
|
|
61
|
+
up: (count = 1) => `${CSI2}S`.repeat(count),
|
|
62
|
+
down: (count = 1) => `${CSI2}T`.repeat(count)
|
|
63
|
+
};
|
|
64
|
+
var erase3 = {
|
|
65
|
+
screen: `${CSI2}2J`,
|
|
66
|
+
up: (count = 1) => `${CSI2}1J`.repeat(count),
|
|
67
|
+
down: (count = 1) => `${CSI2}J`.repeat(count),
|
|
68
|
+
line: `${CSI2}2K`,
|
|
69
|
+
lineEnd: `${CSI2}K`,
|
|
70
|
+
lineStart: `${CSI2}1K`,
|
|
71
|
+
lines(count) {
|
|
72
|
+
let clear = "";
|
|
73
|
+
for (let i2 = 0; i2 < count; i2++)
|
|
74
|
+
clear += this.line + (i2 < count - 1 ? cursor3.up() : "");
|
|
75
|
+
if (count)
|
|
76
|
+
clear += cursor3.left;
|
|
77
|
+
return clear;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
module.exports = { cursor: cursor3, scroll, erase: erase3, beep };
|
|
81
|
+
}
|
|
82
|
+
});
|
|
2
83
|
|
|
3
|
-
// src/index.
|
|
4
|
-
import chalk from "chalk";
|
|
5
|
-
import { Command } from "commander";
|
|
6
|
-
import { Box, render, Text } from "ink";
|
|
7
|
-
import SelectInput from "ink-select-input";
|
|
8
|
-
import TextInput from "ink-text-input";
|
|
84
|
+
// src/index.ts
|
|
9
85
|
import { spawn, spawnSync } from "child_process";
|
|
10
86
|
import {
|
|
11
87
|
copyFileSync,
|
|
12
88
|
cpSync,
|
|
13
|
-
existsSync as
|
|
89
|
+
existsSync as existsSync3,
|
|
14
90
|
mkdirSync,
|
|
15
91
|
mkdtempSync,
|
|
16
|
-
readdirSync as
|
|
92
|
+
readdirSync as readdirSync3,
|
|
17
93
|
readFileSync as readFileSync2,
|
|
18
94
|
rmSync,
|
|
19
95
|
writeFileSync as writeFileSync2
|
|
20
96
|
} from "fs";
|
|
21
97
|
import { tmpdir } from "os";
|
|
22
|
-
import { dirname, join as
|
|
23
|
-
import {
|
|
24
|
-
import { pipeline } from "stream/promises";
|
|
98
|
+
import { dirname as dirname2, join as join3 } from "path";
|
|
99
|
+
import { parseArgs } from "util";
|
|
25
100
|
import { fileURLToPath } from "url";
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
101
|
+
|
|
102
|
+
// src/ansi.ts
|
|
103
|
+
var wrap = (code) => (text2) => `\x1B[${code}m${text2}\x1B[0m`;
|
|
104
|
+
var bold = wrap("1");
|
|
105
|
+
var red = wrap("31");
|
|
106
|
+
var green = wrap("32");
|
|
107
|
+
var yellow = wrap("33");
|
|
108
|
+
var cyan = wrap("36");
|
|
109
|
+
var gray = wrap("90");
|
|
110
|
+
var white = wrap("37");
|
|
111
|
+
var whiteBold = (text2) => `\x1B[1;37m${text2}\x1B[0m`;
|
|
112
|
+
|
|
113
|
+
// ../../node_modules/.pnpm/@clack+core@1.4.3/node_modules/@clack/core/dist/index.mjs
|
|
114
|
+
import { styleText } from "util";
|
|
115
|
+
import { stdout, stdin } from "process";
|
|
116
|
+
import * as l from "readline";
|
|
117
|
+
import l__default from "readline";
|
|
118
|
+
|
|
119
|
+
// ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
|
|
120
|
+
var getCodePointsLength = /* @__PURE__ */ (() => {
|
|
121
|
+
const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
|
|
122
|
+
return (input) => {
|
|
123
|
+
let surrogatePairsNr = 0;
|
|
124
|
+
SURROGATE_PAIR_RE.lastIndex = 0;
|
|
125
|
+
while (SURROGATE_PAIR_RE.test(input)) {
|
|
126
|
+
surrogatePairsNr += 1;
|
|
127
|
+
}
|
|
128
|
+
return input.length - surrogatePairsNr;
|
|
129
|
+
};
|
|
130
|
+
})();
|
|
131
|
+
var isFullWidth = (x) => {
|
|
132
|
+
return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
|
|
133
|
+
};
|
|
134
|
+
var isWideNotCJKTNotEmoji = (x) => {
|
|
135
|
+
return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
|
|
139
|
+
var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
|
|
140
|
+
var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
|
|
141
|
+
var CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu;
|
|
142
|
+
var TAB_RE = /\t{1,1000}/y;
|
|
143
|
+
var EMOJI_RE = /[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/yu;
|
|
144
|
+
var LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
|
|
145
|
+
var MODIFIER_RE = /\p{M}+/gu;
|
|
146
|
+
var NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
|
|
147
|
+
var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
|
|
148
|
+
const LIMIT = truncationOptions.limit ?? Infinity;
|
|
149
|
+
const ELLIPSIS = truncationOptions.ellipsis ?? "";
|
|
150
|
+
const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
|
|
151
|
+
const ANSI_WIDTH = 0;
|
|
152
|
+
const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
|
|
153
|
+
const TAB_WIDTH = widthOptions.tabWidth ?? 8;
|
|
154
|
+
const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
|
|
155
|
+
const FULL_WIDTH_WIDTH = 2;
|
|
156
|
+
const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
|
|
157
|
+
const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
|
|
158
|
+
const PARSE_BLOCKS = [
|
|
159
|
+
[LATIN_RE, REGULAR_WIDTH],
|
|
160
|
+
[ANSI_RE, ANSI_WIDTH],
|
|
161
|
+
[CONTROL_RE, CONTROL_WIDTH],
|
|
162
|
+
[TAB_RE, TAB_WIDTH],
|
|
163
|
+
[EMOJI_RE, EMOJI_WIDTH],
|
|
164
|
+
[CJKT_WIDE_RE, WIDE_WIDTH]
|
|
165
|
+
];
|
|
166
|
+
let indexPrev = 0;
|
|
167
|
+
let index = 0;
|
|
168
|
+
let length = input.length;
|
|
169
|
+
let lengthExtra = 0;
|
|
170
|
+
let truncationEnabled = false;
|
|
171
|
+
let truncationIndex = length;
|
|
172
|
+
let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
|
|
173
|
+
let unmatchedStart = 0;
|
|
174
|
+
let unmatchedEnd = 0;
|
|
175
|
+
let width = 0;
|
|
176
|
+
let widthExtra = 0;
|
|
177
|
+
outer: while (true) {
|
|
178
|
+
if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
|
|
179
|
+
const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
|
|
180
|
+
lengthExtra = 0;
|
|
181
|
+
for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
|
|
182
|
+
const codePoint = char.codePointAt(0) || 0;
|
|
183
|
+
if (isFullWidth(codePoint)) {
|
|
184
|
+
widthExtra = FULL_WIDTH_WIDTH;
|
|
185
|
+
} else if (isWideNotCJKTNotEmoji(codePoint)) {
|
|
186
|
+
widthExtra = WIDE_WIDTH;
|
|
187
|
+
} else {
|
|
188
|
+
widthExtra = REGULAR_WIDTH;
|
|
189
|
+
}
|
|
190
|
+
if (width + widthExtra > truncationLimit) {
|
|
191
|
+
truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
|
|
192
|
+
}
|
|
193
|
+
if (width + widthExtra > LIMIT) {
|
|
194
|
+
truncationEnabled = true;
|
|
195
|
+
break outer;
|
|
196
|
+
}
|
|
197
|
+
lengthExtra += char.length;
|
|
198
|
+
width += widthExtra;
|
|
199
|
+
}
|
|
200
|
+
unmatchedStart = unmatchedEnd = 0;
|
|
201
|
+
}
|
|
202
|
+
if (index >= length) {
|
|
203
|
+
break outer;
|
|
204
|
+
}
|
|
205
|
+
for (let i2 = 0, l2 = PARSE_BLOCKS.length; i2 < l2; i2++) {
|
|
206
|
+
const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i2];
|
|
207
|
+
BLOCK_RE.lastIndex = index;
|
|
208
|
+
if (BLOCK_RE.test(input)) {
|
|
209
|
+
lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
|
|
210
|
+
widthExtra = lengthExtra * BLOCK_WIDTH;
|
|
211
|
+
if (width + widthExtra > truncationLimit) {
|
|
212
|
+
truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
|
|
213
|
+
}
|
|
214
|
+
if (width + widthExtra > LIMIT) {
|
|
215
|
+
truncationEnabled = true;
|
|
216
|
+
break outer;
|
|
217
|
+
}
|
|
218
|
+
width += widthExtra;
|
|
219
|
+
unmatchedStart = indexPrev;
|
|
220
|
+
unmatchedEnd = index;
|
|
221
|
+
index = indexPrev = BLOCK_RE.lastIndex;
|
|
222
|
+
continue outer;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
index += 1;
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
width: truncationEnabled ? truncationLimit : width,
|
|
229
|
+
index: truncationEnabled ? truncationIndex : length,
|
|
230
|
+
truncated: truncationEnabled,
|
|
231
|
+
ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
|
|
232
|
+
};
|
|
233
|
+
};
|
|
234
|
+
var dist_default = getStringTruncatedWidth;
|
|
235
|
+
|
|
236
|
+
// ../../node_modules/.pnpm/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
|
|
237
|
+
var NO_TRUNCATION2 = {
|
|
238
|
+
limit: Infinity,
|
|
239
|
+
ellipsis: "",
|
|
240
|
+
ellipsisWidth: 0
|
|
241
|
+
};
|
|
242
|
+
var fastStringWidth = (input, options = {}) => {
|
|
243
|
+
return dist_default(input, NO_TRUNCATION2, options).width;
|
|
244
|
+
};
|
|
245
|
+
var dist_default2 = fastStringWidth;
|
|
246
|
+
|
|
247
|
+
// ../../node_modules/.pnpm/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
|
|
248
|
+
var ESC = "\x1B";
|
|
249
|
+
var CSI = "\x9B";
|
|
250
|
+
var END_CODE = 39;
|
|
251
|
+
var ANSI_ESCAPE_BELL = "\x07";
|
|
252
|
+
var ANSI_CSI = "[";
|
|
253
|
+
var ANSI_OSC = "]";
|
|
254
|
+
var ANSI_SGR_TERMINATOR = "m";
|
|
255
|
+
var ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
|
|
256
|
+
var GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
|
|
257
|
+
var getClosingCode = (openingCode) => {
|
|
258
|
+
if (openingCode >= 30 && openingCode <= 37)
|
|
259
|
+
return 39;
|
|
260
|
+
if (openingCode >= 90 && openingCode <= 97)
|
|
261
|
+
return 39;
|
|
262
|
+
if (openingCode >= 40 && openingCode <= 47)
|
|
263
|
+
return 49;
|
|
264
|
+
if (openingCode >= 100 && openingCode <= 107)
|
|
265
|
+
return 49;
|
|
266
|
+
if (openingCode === 1 || openingCode === 2)
|
|
267
|
+
return 22;
|
|
268
|
+
if (openingCode === 3)
|
|
269
|
+
return 23;
|
|
270
|
+
if (openingCode === 4)
|
|
271
|
+
return 24;
|
|
272
|
+
if (openingCode === 7)
|
|
273
|
+
return 27;
|
|
274
|
+
if (openingCode === 8)
|
|
275
|
+
return 28;
|
|
276
|
+
if (openingCode === 9)
|
|
277
|
+
return 29;
|
|
278
|
+
if (openingCode === 0)
|
|
279
|
+
return 0;
|
|
280
|
+
return void 0;
|
|
281
|
+
};
|
|
282
|
+
var wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
|
|
283
|
+
var wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
|
|
284
|
+
var wrapWord = (rows, word, columns) => {
|
|
285
|
+
const characters = word[Symbol.iterator]();
|
|
286
|
+
let isInsideEscape = false;
|
|
287
|
+
let isInsideLinkEscape = false;
|
|
288
|
+
let lastRow = rows.at(-1);
|
|
289
|
+
let visible = lastRow === void 0 ? 0 : dist_default2(lastRow);
|
|
290
|
+
let currentCharacter = characters.next();
|
|
291
|
+
let nextCharacter = characters.next();
|
|
292
|
+
let rawCharacterIndex = 0;
|
|
293
|
+
while (!currentCharacter.done) {
|
|
294
|
+
const character = currentCharacter.value;
|
|
295
|
+
const characterLength = dist_default2(character);
|
|
296
|
+
if (visible + characterLength <= columns) {
|
|
297
|
+
rows[rows.length - 1] += character;
|
|
298
|
+
} else {
|
|
299
|
+
rows.push(character);
|
|
300
|
+
visible = 0;
|
|
301
|
+
}
|
|
302
|
+
if (character === ESC || character === CSI) {
|
|
303
|
+
isInsideEscape = true;
|
|
304
|
+
isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
|
|
305
|
+
}
|
|
306
|
+
if (isInsideEscape) {
|
|
307
|
+
if (isInsideLinkEscape) {
|
|
308
|
+
if (character === ANSI_ESCAPE_BELL) {
|
|
309
|
+
isInsideEscape = false;
|
|
310
|
+
isInsideLinkEscape = false;
|
|
311
|
+
}
|
|
312
|
+
} else if (character === ANSI_SGR_TERMINATOR) {
|
|
313
|
+
isInsideEscape = false;
|
|
314
|
+
}
|
|
315
|
+
} else {
|
|
316
|
+
visible += characterLength;
|
|
317
|
+
if (visible === columns && !nextCharacter.done) {
|
|
318
|
+
rows.push("");
|
|
319
|
+
visible = 0;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
currentCharacter = nextCharacter;
|
|
323
|
+
nextCharacter = characters.next();
|
|
324
|
+
rawCharacterIndex += character.length;
|
|
325
|
+
}
|
|
326
|
+
lastRow = rows.at(-1);
|
|
327
|
+
if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) {
|
|
328
|
+
rows[rows.length - 2] += rows.pop();
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
var stringVisibleTrimSpacesRight = (string) => {
|
|
332
|
+
const words = string.split(" ");
|
|
333
|
+
let last = words.length;
|
|
334
|
+
while (last) {
|
|
335
|
+
if (dist_default2(words[last - 1])) {
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
last--;
|
|
339
|
+
}
|
|
340
|
+
if (last === words.length) {
|
|
341
|
+
return string;
|
|
342
|
+
}
|
|
343
|
+
return words.slice(0, last).join(" ") + words.slice(last).join("");
|
|
344
|
+
};
|
|
345
|
+
var exec = (string, columns, options = {}) => {
|
|
346
|
+
if (options.trim !== false && string.trim() === "") {
|
|
347
|
+
return "";
|
|
348
|
+
}
|
|
349
|
+
let returnValue = "";
|
|
350
|
+
let escapeCode;
|
|
351
|
+
let escapeUrl;
|
|
352
|
+
const words = string.split(" ");
|
|
353
|
+
let rows = [""];
|
|
354
|
+
let rowLength = 0;
|
|
355
|
+
for (let index = 0; index < words.length; index++) {
|
|
356
|
+
const word = words[index];
|
|
357
|
+
if (options.trim !== false) {
|
|
358
|
+
const row = rows.at(-1) ?? "";
|
|
359
|
+
const trimmed = row.trimStart();
|
|
360
|
+
if (row.length !== trimmed.length) {
|
|
361
|
+
rows[rows.length - 1] = trimmed;
|
|
362
|
+
rowLength = dist_default2(trimmed);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (index !== 0) {
|
|
366
|
+
if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
|
|
367
|
+
rows.push("");
|
|
368
|
+
rowLength = 0;
|
|
369
|
+
}
|
|
370
|
+
if (rowLength || options.trim === false) {
|
|
371
|
+
rows[rows.length - 1] += " ";
|
|
372
|
+
rowLength++;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
const wordLength = dist_default2(word);
|
|
376
|
+
if (options.hard && wordLength > columns) {
|
|
377
|
+
const remainingColumns = columns - rowLength;
|
|
378
|
+
const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
|
|
379
|
+
const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
|
|
380
|
+
if (breaksStartingNextLine < breaksStartingThisLine) {
|
|
381
|
+
rows.push("");
|
|
382
|
+
}
|
|
383
|
+
wrapWord(rows, word, columns);
|
|
384
|
+
rowLength = dist_default2(rows.at(-1) ?? "");
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
if (rowLength + wordLength > columns && rowLength && wordLength) {
|
|
388
|
+
if (options.wordWrap === false && rowLength < columns) {
|
|
389
|
+
wrapWord(rows, word, columns);
|
|
390
|
+
rowLength = dist_default2(rows.at(-1) ?? "");
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
rows.push("");
|
|
394
|
+
rowLength = 0;
|
|
395
|
+
}
|
|
396
|
+
if (rowLength + wordLength > columns && options.wordWrap === false) {
|
|
397
|
+
wrapWord(rows, word, columns);
|
|
398
|
+
rowLength = dist_default2(rows.at(-1) ?? "");
|
|
399
|
+
continue;
|
|
400
|
+
}
|
|
401
|
+
rows[rows.length - 1] += word;
|
|
402
|
+
rowLength += wordLength;
|
|
403
|
+
}
|
|
404
|
+
if (options.trim !== false) {
|
|
405
|
+
rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
|
|
406
|
+
}
|
|
407
|
+
const preString = rows.join("\n");
|
|
408
|
+
let inSurrogate = false;
|
|
409
|
+
for (let i2 = 0; i2 < preString.length; i2++) {
|
|
410
|
+
const character = preString[i2];
|
|
411
|
+
returnValue += character;
|
|
412
|
+
if (!inSurrogate) {
|
|
413
|
+
inSurrogate = character >= "\uD800" && character <= "\uDBFF";
|
|
414
|
+
if (inSurrogate) {
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
} else {
|
|
418
|
+
inSurrogate = false;
|
|
419
|
+
}
|
|
420
|
+
if (character === ESC || character === CSI) {
|
|
421
|
+
GROUP_REGEX.lastIndex = i2 + 1;
|
|
422
|
+
const groupsResult = GROUP_REGEX.exec(preString);
|
|
423
|
+
const groups = groupsResult?.groups;
|
|
424
|
+
if (groups?.code !== void 0) {
|
|
425
|
+
const code = Number.parseFloat(groups.code);
|
|
426
|
+
escapeCode = code === END_CODE ? void 0 : code;
|
|
427
|
+
} else if (groups?.uri !== void 0) {
|
|
428
|
+
escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
if (preString[i2 + 1] === "\n") {
|
|
432
|
+
if (escapeUrl) {
|
|
433
|
+
returnValue += wrapAnsiHyperlink("");
|
|
434
|
+
}
|
|
435
|
+
const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
|
|
436
|
+
if (escapeCode && closingCode) {
|
|
437
|
+
returnValue += wrapAnsiCode(closingCode);
|
|
438
|
+
}
|
|
439
|
+
} else if (character === "\n") {
|
|
440
|
+
if (escapeCode && getClosingCode(escapeCode)) {
|
|
441
|
+
returnValue += wrapAnsiCode(escapeCode);
|
|
442
|
+
}
|
|
443
|
+
if (escapeUrl) {
|
|
444
|
+
returnValue += wrapAnsiHyperlink(escapeUrl);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
return returnValue;
|
|
449
|
+
};
|
|
450
|
+
var CRLF_OR_LF = /\r?\n/;
|
|
451
|
+
function wrapAnsi(string, columns, options) {
|
|
452
|
+
return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// ../../node_modules/.pnpm/@clack+core@1.4.3/node_modules/@clack/core/dist/index.mjs
|
|
456
|
+
var import_sisteransi = __toESM(require_src(), 1);
|
|
457
|
+
import { ReadStream } from "tty";
|
|
458
|
+
function findCursor(s, o, l2) {
|
|
459
|
+
if (!l2.some((r2) => !r2.disabled))
|
|
460
|
+
return s;
|
|
461
|
+
const t2 = s + o, n3 = Math.max(l2.length - 1, 0), e = t2 < 0 ? n3 : t2 > n3 ? 0 : t2;
|
|
462
|
+
return l2[e]?.disabled ? findCursor(e, o < 0 ? -1 : 1, l2) : e;
|
|
463
|
+
}
|
|
464
|
+
var a$1 = ["up", "down", "left", "right", "space", "enter", "cancel"];
|
|
465
|
+
var t = [
|
|
466
|
+
"January",
|
|
467
|
+
"February",
|
|
468
|
+
"March",
|
|
469
|
+
"April",
|
|
470
|
+
"May",
|
|
471
|
+
"June",
|
|
472
|
+
"July",
|
|
473
|
+
"August",
|
|
474
|
+
"September",
|
|
475
|
+
"October",
|
|
476
|
+
"November",
|
|
477
|
+
"December"
|
|
478
|
+
];
|
|
479
|
+
var settings = {
|
|
480
|
+
actions: new Set(a$1),
|
|
481
|
+
aliases: /* @__PURE__ */ new Map([
|
|
482
|
+
// vim support
|
|
483
|
+
["k", "up"],
|
|
484
|
+
["j", "down"],
|
|
485
|
+
["h", "left"],
|
|
486
|
+
["l", "right"],
|
|
487
|
+
["", "cancel"],
|
|
488
|
+
// opinionated defaults!
|
|
489
|
+
["escape", "cancel"]
|
|
490
|
+
]),
|
|
491
|
+
messages: {
|
|
492
|
+
cancel: "Canceled",
|
|
493
|
+
error: "Something went wrong"
|
|
494
|
+
},
|
|
495
|
+
withGuide: true,
|
|
496
|
+
date: {
|
|
497
|
+
monthNames: [...t],
|
|
498
|
+
messages: {
|
|
499
|
+
required: "Please enter a valid date",
|
|
500
|
+
invalidMonth: "There are only 12 months in a year",
|
|
501
|
+
invalidDay: (n3, e) => `There are only ${n3} days in ${e}`,
|
|
502
|
+
afterMin: (n3) => `Date must be on or after ${n3.toISOString().slice(0, 10)}`,
|
|
503
|
+
beforeMax: (n3) => `Date must be on or before ${n3.toISOString().slice(0, 10)}`
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
function isActionKey(n3, e) {
|
|
508
|
+
if (typeof n3 == "string")
|
|
509
|
+
return settings.aliases.get(n3) === e;
|
|
510
|
+
for (const s of n3)
|
|
511
|
+
if (s !== void 0 && isActionKey(s, e))
|
|
512
|
+
return true;
|
|
513
|
+
return false;
|
|
514
|
+
}
|
|
515
|
+
function diffLines(i2, s) {
|
|
516
|
+
if (i2 === s) return;
|
|
517
|
+
const e = i2.split(`
|
|
518
|
+
`), t2 = s.split(`
|
|
519
|
+
`), r2 = Math.max(e.length, t2.length), f = [];
|
|
520
|
+
for (let n3 = 0; n3 < r2; n3++)
|
|
521
|
+
e[n3] !== t2[n3] && f.push(n3);
|
|
522
|
+
return {
|
|
523
|
+
lines: f,
|
|
524
|
+
numLinesBefore: e.length,
|
|
525
|
+
numLinesAfter: t2.length,
|
|
526
|
+
numLines: r2
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
var R = globalThis.process.platform.startsWith("win");
|
|
530
|
+
var CANCEL_SYMBOL = /* @__PURE__ */ Symbol("clack:cancel");
|
|
531
|
+
function isCancel(e) {
|
|
532
|
+
return e === CANCEL_SYMBOL;
|
|
533
|
+
}
|
|
534
|
+
function setRawMode(e, r2) {
|
|
535
|
+
const o = e;
|
|
536
|
+
o.isTTY && o.setRawMode(r2);
|
|
537
|
+
}
|
|
538
|
+
function block({
|
|
539
|
+
input: e = stdin,
|
|
540
|
+
output: r2 = stdout,
|
|
541
|
+
overwrite: o = true,
|
|
542
|
+
hideCursor: t2 = true
|
|
543
|
+
} = {}) {
|
|
544
|
+
const s = l.createInterface({
|
|
545
|
+
input: e,
|
|
546
|
+
output: r2,
|
|
547
|
+
prompt: "",
|
|
548
|
+
tabSize: 1
|
|
549
|
+
});
|
|
550
|
+
l.emitKeypressEvents(e, s), e instanceof ReadStream && e.isTTY && e.setRawMode(true);
|
|
551
|
+
const n3 = (f, { name: a2, sequence: p }) => {
|
|
552
|
+
const c2 = String(f);
|
|
553
|
+
if (isActionKey([c2, a2, p], "cancel")) {
|
|
554
|
+
t2 && r2.write(import_sisteransi.cursor.show), process.exit(0);
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
if (!o) return;
|
|
558
|
+
const i2 = a2 === "return" ? 0 : -1, m = a2 === "return" ? -1 : 0;
|
|
559
|
+
l.moveCursor(r2, i2, m, () => {
|
|
560
|
+
l.clearLine(r2, 1, () => {
|
|
561
|
+
e.once("keypress", n3);
|
|
562
|
+
});
|
|
563
|
+
});
|
|
564
|
+
};
|
|
565
|
+
return t2 && r2.write(import_sisteransi.cursor.hide), e.once("keypress", n3), () => {
|
|
566
|
+
e.off("keypress", n3), t2 && r2.write(import_sisteransi.cursor.show), e instanceof ReadStream && e.isTTY && !R && e.setRawMode(false), s.terminal = false, s.close();
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
var getColumns = (e) => "columns" in e && typeof e.columns == "number" ? e.columns : 80;
|
|
570
|
+
var getRows = (e) => "rows" in e && typeof e.rows == "number" ? e.rows : 20;
|
|
571
|
+
function wrapTextWithPrefix(e, r2, o, t2 = o, s = o, n3) {
|
|
572
|
+
const f = getColumns(e ?? stdout);
|
|
573
|
+
return wrapAnsi(r2, f - o.length, {
|
|
574
|
+
hard: true,
|
|
575
|
+
trim: false
|
|
576
|
+
}).split(`
|
|
577
|
+
`).map((c2, i2, m) => {
|
|
578
|
+
const d = n3 ? n3(c2, i2) : c2;
|
|
579
|
+
return i2 === 0 ? `${t2}${d}` : i2 === m.length - 1 ? `${s}${d}` : `${o}${d}`;
|
|
580
|
+
}).join(`
|
|
581
|
+
`);
|
|
582
|
+
}
|
|
583
|
+
function runValidation(e, n3) {
|
|
584
|
+
if ("~standard" in e) {
|
|
585
|
+
const a2 = e["~standard"].validate(n3);
|
|
586
|
+
if (a2 instanceof Promise)
|
|
587
|
+
throw new TypeError(
|
|
588
|
+
"Schema validation must be synchronous. Update `validate()` and remove any asynchronous logic."
|
|
589
|
+
);
|
|
590
|
+
return a2.issues?.at(0)?.message;
|
|
591
|
+
}
|
|
592
|
+
return e(n3);
|
|
593
|
+
}
|
|
594
|
+
var V = class {
|
|
595
|
+
input;
|
|
596
|
+
output;
|
|
597
|
+
_abortSignal;
|
|
598
|
+
rl;
|
|
599
|
+
opts;
|
|
600
|
+
_render;
|
|
601
|
+
_track = false;
|
|
602
|
+
_prevFrame = "";
|
|
603
|
+
_subscribers = /* @__PURE__ */ new Map();
|
|
604
|
+
_cursor = 0;
|
|
605
|
+
state = "initial";
|
|
606
|
+
error = "";
|
|
607
|
+
value;
|
|
608
|
+
userInput = "";
|
|
609
|
+
constructor(t2, e = true) {
|
|
610
|
+
const { input: i2 = stdin, output: n3 = stdout, render: s, signal: r2, ...o } = t2;
|
|
611
|
+
this.opts = o, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = s.bind(this), this._track = e, this._abortSignal = r2, this.input = i2, this.output = n3;
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Unsubscribe all listeners
|
|
615
|
+
*/
|
|
616
|
+
unsubscribe() {
|
|
617
|
+
this._subscribers.clear();
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Set a subscriber with opts
|
|
621
|
+
* @param event - The event name
|
|
622
|
+
*/
|
|
623
|
+
setSubscriber(t2, e) {
|
|
624
|
+
const i2 = this._subscribers.get(t2) ?? [];
|
|
625
|
+
i2.push(e), this._subscribers.set(t2, i2);
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Subscribe to an event
|
|
629
|
+
* @param event - The event name
|
|
630
|
+
* @param cb - The callback
|
|
631
|
+
*/
|
|
632
|
+
on(t2, e) {
|
|
633
|
+
this.setSubscriber(t2, { cb: e });
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Subscribe to an event once
|
|
637
|
+
* @param event - The event name
|
|
638
|
+
* @param cb - The callback
|
|
639
|
+
*/
|
|
640
|
+
once(t2, e) {
|
|
641
|
+
this.setSubscriber(t2, { cb: e, once: true });
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Emit an event with data
|
|
645
|
+
* @param event - The event name
|
|
646
|
+
* @param data - The data to pass to the callback
|
|
647
|
+
*/
|
|
648
|
+
emit(t2, ...e) {
|
|
649
|
+
const i2 = this._subscribers.get(t2) ?? [], n3 = [];
|
|
650
|
+
for (const s of i2)
|
|
651
|
+
s.cb(...e), s.once && n3.push(() => i2.splice(i2.indexOf(s), 1));
|
|
652
|
+
for (const s of n3)
|
|
653
|
+
s();
|
|
654
|
+
}
|
|
655
|
+
prompt() {
|
|
656
|
+
return new Promise((t2) => {
|
|
657
|
+
if (this._abortSignal) {
|
|
658
|
+
if (this._abortSignal.aborted)
|
|
659
|
+
return this.state = "cancel", this.close(), t2(CANCEL_SYMBOL);
|
|
660
|
+
this._abortSignal.addEventListener(
|
|
661
|
+
"abort",
|
|
662
|
+
() => {
|
|
663
|
+
this.state = "cancel", this.close();
|
|
664
|
+
},
|
|
665
|
+
{ once: true }
|
|
666
|
+
);
|
|
667
|
+
}
|
|
668
|
+
this.rl = l__default.createInterface({
|
|
669
|
+
input: this.input,
|
|
670
|
+
tabSize: 2,
|
|
671
|
+
prompt: "",
|
|
672
|
+
escapeCodeTimeout: 50,
|
|
673
|
+
terminal: true
|
|
674
|
+
}), this.rl.prompt(), this.opts.initialUserInput !== void 0 && this._setUserInput(this.opts.initialUserInput, true), this.input.on("keypress", this.onKeypress), setRawMode(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
|
|
675
|
+
this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t2(this.value);
|
|
676
|
+
}), this.once("cancel", () => {
|
|
677
|
+
this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t2(CANCEL_SYMBOL);
|
|
678
|
+
});
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
_isActionKey(t2, e) {
|
|
682
|
+
return t2 === " ";
|
|
683
|
+
}
|
|
684
|
+
_shouldSubmit(t2, e) {
|
|
685
|
+
return true;
|
|
686
|
+
}
|
|
687
|
+
_setValue(t2) {
|
|
688
|
+
this.value = t2, this.emit("value", this.value);
|
|
689
|
+
}
|
|
690
|
+
_setUserInput(t2, e) {
|
|
691
|
+
this.userInput = t2 ?? "", this.emit("userInput", this.userInput), e && this._track && this.rl && (this.rl.write(this.userInput), this._cursor = this.rl.cursor);
|
|
692
|
+
}
|
|
693
|
+
_clearUserInput() {
|
|
694
|
+
this.rl?.write(null, { ctrl: true, name: "u" }), this._setUserInput("");
|
|
695
|
+
}
|
|
696
|
+
onKeypress(t2, e) {
|
|
697
|
+
if (this._track && e.name !== "return" && (e.name && this._isActionKey(t2, e) && this.rl?.write(null, { ctrl: true, name: "h" }), this._cursor = this.rl?.cursor ?? 0, this._setUserInput(this.rl?.line)), this.state === "error" && (this.state = "active"), e?.name && (!this._track && settings.aliases.has(e.name) && this.emit("cursor", settings.aliases.get(e.name)), settings.actions.has(e.name) && this.emit("cursor", e.name)), t2 && (t2.toLowerCase() === "y" || t2.toLowerCase() === "n") && this.emit("confirm", t2.toLowerCase() === "y"), this.emit("key", t2, e), e?.name === "return" && this._shouldSubmit(t2, e)) {
|
|
698
|
+
if (this.opts.validate) {
|
|
699
|
+
const i2 = runValidation(this.opts.validate, this.value);
|
|
700
|
+
i2 && (this.error = i2 instanceof Error ? i2.message : i2, this.state = "error", this.rl?.write(this.userInput));
|
|
701
|
+
}
|
|
702
|
+
this.state !== "error" && (this.state = "submit");
|
|
703
|
+
}
|
|
704
|
+
isActionKey([t2, e?.name, e?.sequence], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
|
|
705
|
+
}
|
|
706
|
+
close() {
|
|
707
|
+
this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
|
|
708
|
+
`), setRawMode(this.input, false), this.rl?.close(), this.rl = void 0, this.emit(`${this.state}`, this.value), this.unsubscribe();
|
|
709
|
+
}
|
|
710
|
+
restoreCursor() {
|
|
711
|
+
const t2 = wrapAnsi(this._prevFrame, process.stdout.columns, { hard: true, trim: false }).split(`
|
|
712
|
+
`).length - 1;
|
|
713
|
+
this.output.write(import_sisteransi.cursor.move(-999, t2 * -1));
|
|
714
|
+
}
|
|
715
|
+
render() {
|
|
716
|
+
const t2 = wrapAnsi(this._render(this) ?? "", process.stdout.columns, {
|
|
717
|
+
hard: true,
|
|
718
|
+
trim: false
|
|
719
|
+
});
|
|
720
|
+
if (t2 !== this._prevFrame) {
|
|
721
|
+
if (this.state === "initial")
|
|
722
|
+
this.output.write(import_sisteransi.cursor.hide);
|
|
723
|
+
else {
|
|
724
|
+
const e = diffLines(this._prevFrame, t2), i2 = getRows(this.output);
|
|
725
|
+
if (this.restoreCursor(), e) {
|
|
726
|
+
const n3 = Math.max(0, e.numLinesAfter - i2), s = Math.max(0, e.numLinesBefore - i2);
|
|
727
|
+
let r2 = e.lines.find((o) => o >= n3);
|
|
728
|
+
if (r2 === void 0) {
|
|
729
|
+
this._prevFrame = t2;
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
if (e.lines.length === 1) {
|
|
733
|
+
this.output.write(import_sisteransi.cursor.move(0, r2 - s)), this.output.write(import_sisteransi.erase.lines(1));
|
|
734
|
+
const o = t2.split(`
|
|
735
|
+
`);
|
|
736
|
+
this.output.write(o[r2]), this._prevFrame = t2, this.output.write(import_sisteransi.cursor.move(0, o.length - r2 - 1));
|
|
737
|
+
return;
|
|
738
|
+
} else if (e.lines.length > 1) {
|
|
739
|
+
if (n3 < s)
|
|
740
|
+
r2 = n3;
|
|
741
|
+
else {
|
|
742
|
+
const h2 = r2 - s;
|
|
743
|
+
h2 > 0 && this.output.write(import_sisteransi.cursor.move(0, h2));
|
|
744
|
+
}
|
|
745
|
+
this.output.write(import_sisteransi.erase.down());
|
|
746
|
+
const f = t2.split(`
|
|
747
|
+
`).slice(r2);
|
|
748
|
+
this.output.write(f.join(`
|
|
749
|
+
`)), this._prevFrame = t2;
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
this.output.write(import_sisteransi.erase.down());
|
|
754
|
+
}
|
|
755
|
+
this.output.write(t2), this.state === "initial" && (this.state = "active"), this._prevFrame = t2;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
};
|
|
759
|
+
var r = class extends V {
|
|
760
|
+
get cursor() {
|
|
761
|
+
return this.value ? 0 : 1;
|
|
762
|
+
}
|
|
763
|
+
get _value() {
|
|
764
|
+
return this.cursor === 0;
|
|
765
|
+
}
|
|
766
|
+
constructor(t2) {
|
|
767
|
+
super(t2, false), this.value = !!t2.initialValue, this.on("userInput", () => {
|
|
768
|
+
this.value = this._value;
|
|
769
|
+
}), this.on("confirm", (i2) => {
|
|
770
|
+
this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = i2, this.state = "submit", this.close();
|
|
771
|
+
}), this.on("cursor", () => {
|
|
772
|
+
this.value = !this.value;
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
};
|
|
776
|
+
var n$1 = class n extends V {
|
|
777
|
+
options;
|
|
778
|
+
cursor = 0;
|
|
779
|
+
get _selectedValue() {
|
|
780
|
+
return this.options[this.cursor];
|
|
781
|
+
}
|
|
782
|
+
changeValue() {
|
|
783
|
+
const e = this._selectedValue;
|
|
784
|
+
this.value = e === void 0 ? void 0 : e.value;
|
|
785
|
+
}
|
|
786
|
+
constructor(e) {
|
|
787
|
+
super(e, false), this.options = e.options;
|
|
788
|
+
const o = this.options.findIndex(({ value: s }) => s === e.initialValue), t2 = o === -1 ? 0 : o;
|
|
789
|
+
this.cursor = this.options[t2]?.disabled ? findCursor(t2, 1, this.options) : t2, this.changeValue(), this.on("cursor", (s) => {
|
|
790
|
+
switch (s) {
|
|
791
|
+
case "left":
|
|
792
|
+
case "up":
|
|
793
|
+
this.cursor = findCursor(this.cursor, -1, this.options);
|
|
794
|
+
break;
|
|
795
|
+
case "down":
|
|
796
|
+
case "right":
|
|
797
|
+
this.cursor = findCursor(this.cursor, 1, this.options);
|
|
798
|
+
break;
|
|
799
|
+
}
|
|
800
|
+
this.changeValue();
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
};
|
|
804
|
+
var n2 = class extends V {
|
|
805
|
+
get userInputWithCursor() {
|
|
806
|
+
if (this.state === "submit")
|
|
807
|
+
return this.userInput;
|
|
808
|
+
const t2 = this.userInput;
|
|
809
|
+
if (this.cursor >= t2.length)
|
|
810
|
+
return `${this.userInput}\u2588`;
|
|
811
|
+
const r2 = t2.slice(0, this.cursor), s = t2.slice(this.cursor, this.cursor + 1), e = t2.slice(this.cursor + 1);
|
|
812
|
+
return `${r2}${styleText("inverse", s)}${e}`;
|
|
813
|
+
}
|
|
814
|
+
get cursor() {
|
|
815
|
+
return this._cursor;
|
|
816
|
+
}
|
|
817
|
+
constructor(t2) {
|
|
818
|
+
super({
|
|
819
|
+
...t2,
|
|
820
|
+
initialUserInput: t2.initialUserInput ?? t2.initialValue
|
|
821
|
+
}), this.on("userInput", (r2) => {
|
|
822
|
+
this._setValue(r2);
|
|
823
|
+
}), this.on("finalize", () => {
|
|
824
|
+
this.value || (this.value = t2.defaultValue), this.value === void 0 && (this.value = "");
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
};
|
|
828
|
+
|
|
829
|
+
// ../../node_modules/.pnpm/@clack+prompts@1.7.0/node_modules/@clack/prompts/dist/index.mjs
|
|
830
|
+
import { styleText as styleText2, stripVTControlCharacters } from "util";
|
|
831
|
+
import process$1 from "process";
|
|
832
|
+
var import_sisteransi2 = __toESM(require_src(), 1);
|
|
833
|
+
import { existsSync, lstatSync, readdirSync } from "fs";
|
|
834
|
+
import { dirname, join } from "path";
|
|
835
|
+
function isUnicodeSupported() {
|
|
836
|
+
if (process$1.platform !== "win32") {
|
|
837
|
+
return process$1.env.TERM !== "linux";
|
|
838
|
+
}
|
|
839
|
+
return Boolean(process$1.env.CI) || Boolean(process$1.env.WT_SESSION) || Boolean(process$1.env.TERMINUS_SUBLIME) || process$1.env.ConEmuTask === "{cmd::Cmder}" || process$1.env.TERM_PROGRAM === "Terminus-Sublime" || process$1.env.TERM_PROGRAM === "vscode" || process$1.env.TERM === "xterm-256color" || process$1.env.TERM === "alacritty" || process$1.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
840
|
+
}
|
|
841
|
+
var unicode = isUnicodeSupported();
|
|
842
|
+
var isCI = () => process.env.CI === "true";
|
|
843
|
+
var unicodeOr = (o, e) => unicode ? o : e;
|
|
844
|
+
var S_STEP_ACTIVE = unicodeOr("\u25C6", "*");
|
|
845
|
+
var S_STEP_CANCEL = unicodeOr("\u25A0", "x");
|
|
846
|
+
var S_STEP_ERROR = unicodeOr("\u25B2", "x");
|
|
847
|
+
var S_STEP_SUBMIT = unicodeOr("\u25C7", "o");
|
|
848
|
+
var S_BAR_START = unicodeOr("\u250C", "T");
|
|
849
|
+
var S_BAR = unicodeOr("\u2502", "|");
|
|
850
|
+
var S_BAR_END = unicodeOr("\u2514", "\u2014");
|
|
851
|
+
var S_BAR_START_RIGHT = unicodeOr("\u2510", "T");
|
|
852
|
+
var S_BAR_END_RIGHT = unicodeOr("\u2518", "\u2014");
|
|
853
|
+
var S_RADIO_ACTIVE = unicodeOr("\u25CF", ">");
|
|
854
|
+
var S_RADIO_INACTIVE = unicodeOr("\u25CB", " ");
|
|
855
|
+
var S_CHECKBOX_ACTIVE = unicodeOr("\u25FB", "[\u2022]");
|
|
856
|
+
var S_CHECKBOX_SELECTED = unicodeOr("\u25FC", "[+]");
|
|
857
|
+
var S_CHECKBOX_INACTIVE = unicodeOr("\u25FB", "[ ]");
|
|
858
|
+
var S_PASSWORD_MASK = unicodeOr("\u25AA", "\u2022");
|
|
859
|
+
var S_BAR_H = unicodeOr("\u2500", "-");
|
|
860
|
+
var S_CORNER_TOP_RIGHT = unicodeOr("\u256E", "+");
|
|
861
|
+
var S_CONNECT_LEFT = unicodeOr("\u251C", "+");
|
|
862
|
+
var S_CORNER_BOTTOM_RIGHT = unicodeOr("\u256F", "+");
|
|
863
|
+
var S_CORNER_BOTTOM_LEFT = unicodeOr("\u2570", "+");
|
|
864
|
+
var S_CORNER_TOP_LEFT = unicodeOr("\u256D", "+");
|
|
865
|
+
var S_INFO = unicodeOr("\u25CF", "\u2022");
|
|
866
|
+
var S_SUCCESS = unicodeOr("\u25C6", "*");
|
|
867
|
+
var S_WARN = unicodeOr("\u25B2", "!");
|
|
868
|
+
var S_ERROR = unicodeOr("\u25A0", "x");
|
|
869
|
+
var symbol = (o) => {
|
|
870
|
+
switch (o) {
|
|
871
|
+
case "initial":
|
|
872
|
+
case "active":
|
|
873
|
+
return styleText2("cyan", S_STEP_ACTIVE);
|
|
874
|
+
case "cancel":
|
|
875
|
+
return styleText2("red", S_STEP_CANCEL);
|
|
876
|
+
case "error":
|
|
877
|
+
return styleText2("yellow", S_STEP_ERROR);
|
|
878
|
+
case "submit":
|
|
879
|
+
return styleText2("green", S_STEP_SUBMIT);
|
|
880
|
+
}
|
|
881
|
+
};
|
|
882
|
+
var symbolBar = (o) => {
|
|
883
|
+
switch (o) {
|
|
884
|
+
case "initial":
|
|
885
|
+
case "active":
|
|
886
|
+
return styleText2("cyan", S_BAR);
|
|
887
|
+
case "cancel":
|
|
888
|
+
return styleText2("red", S_BAR);
|
|
889
|
+
case "error":
|
|
890
|
+
return styleText2("yellow", S_BAR);
|
|
891
|
+
case "submit":
|
|
892
|
+
return styleText2("green", S_BAR);
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
function formatInstructionFooter(o, e) {
|
|
896
|
+
const r2 = [`${e ? `${styleText2("cyan", S_BAR)} ` : ""}${o.join(" \u2022 ")}`];
|
|
897
|
+
return e && r2.push(styleText2("cyan", S_BAR_END)), r2;
|
|
898
|
+
}
|
|
899
|
+
var I = (l2, e, w, p, b, C = false) => {
|
|
900
|
+
let r2 = e, O = 0;
|
|
901
|
+
if (C)
|
|
902
|
+
for (let i2 = p - 1; i2 >= w; i2--) {
|
|
903
|
+
const m = l2[i2];
|
|
904
|
+
if (m && (r2 -= m.length), O++, r2 <= b) break;
|
|
905
|
+
}
|
|
906
|
+
else
|
|
907
|
+
for (let i2 = w; i2 < p; i2++) {
|
|
908
|
+
const m = l2[i2];
|
|
909
|
+
if (m && (r2 -= m.length), O++, r2 <= b) break;
|
|
910
|
+
}
|
|
911
|
+
return { lineCount: r2, removals: O };
|
|
912
|
+
};
|
|
913
|
+
var limitOptions = ({
|
|
914
|
+
cursor: l2,
|
|
915
|
+
options: e,
|
|
916
|
+
style: w,
|
|
917
|
+
output: p = process.stdout,
|
|
918
|
+
maxItems: b = Number.POSITIVE_INFINITY,
|
|
919
|
+
columnPadding: C = 0,
|
|
920
|
+
rowPadding: r2 = 4
|
|
921
|
+
}) => {
|
|
922
|
+
const i2 = getColumns(p) - C, m = getRows(p), M = styleText2("dim", "..."), v = Math.max(m - r2, 0), a2 = Math.max(Math.min(b, v), 5);
|
|
923
|
+
let f = 0;
|
|
924
|
+
l2 >= a2 - 3 && (f = Math.max(
|
|
925
|
+
Math.min(l2 - a2 + 3, e.length - a2),
|
|
926
|
+
0
|
|
927
|
+
));
|
|
928
|
+
let d = a2 < e.length && f > 0, c2 = a2 < e.length && f + a2 < e.length;
|
|
929
|
+
const W2 = Math.min(
|
|
930
|
+
f + a2,
|
|
931
|
+
e.length
|
|
932
|
+
), s = [];
|
|
933
|
+
let g = 0;
|
|
934
|
+
d && g++, c2 && g++;
|
|
935
|
+
const T = f + (d ? 1 : 0), y = W2 - (c2 ? 1 : 0);
|
|
936
|
+
for (let t2 = T; t2 < y; t2++) {
|
|
937
|
+
const n3 = e[t2], o = n3 ? w(n3, t2 === l2) : "", h2 = wrapAnsi(o, i2, {
|
|
938
|
+
hard: true,
|
|
939
|
+
trim: false
|
|
940
|
+
}).split(`
|
|
941
|
+
`);
|
|
942
|
+
s.push(h2), g += h2.length;
|
|
943
|
+
}
|
|
944
|
+
if (g > v) {
|
|
945
|
+
let t2 = 0, n3 = 0, o = g;
|
|
946
|
+
const h2 = l2 - T;
|
|
947
|
+
let u3 = v;
|
|
948
|
+
const L = () => I(s, o, 0, h2, u3), E = () => I(
|
|
949
|
+
s,
|
|
950
|
+
o,
|
|
951
|
+
h2 + 1,
|
|
952
|
+
s.length,
|
|
953
|
+
u3,
|
|
954
|
+
true
|
|
955
|
+
);
|
|
956
|
+
d ? ({ lineCount: o, removals: t2 } = L(), o > u3 && (c2 || (u3 -= 1), { lineCount: o, removals: n3 } = E())) : (c2 || (u3 -= 1), { lineCount: o, removals: n3 } = E(), o > u3 && (u3 -= 1, { lineCount: o, removals: t2 } = L())), t2 > 0 && (d = true, s.splice(0, t2)), n3 > 0 && (c2 = true, s.splice(s.length - n3, n3));
|
|
957
|
+
}
|
|
958
|
+
const x = [];
|
|
959
|
+
d && x.push(M);
|
|
960
|
+
for (const t2 of s)
|
|
961
|
+
for (const n3 of t2)
|
|
962
|
+
x.push(n3);
|
|
963
|
+
return c2 && x.push(M), x;
|
|
964
|
+
};
|
|
965
|
+
var confirm = (i2) => {
|
|
966
|
+
const a2 = i2.active ?? "Yes", s = i2.inactive ?? "No";
|
|
967
|
+
return new r({
|
|
968
|
+
active: a2,
|
|
969
|
+
inactive: s,
|
|
970
|
+
signal: i2.signal,
|
|
971
|
+
input: i2.input,
|
|
972
|
+
output: i2.output,
|
|
973
|
+
initialValue: i2.initialValue ?? true,
|
|
974
|
+
render() {
|
|
975
|
+
const e = i2.withGuide ?? settings.withGuide, u3 = `${symbol(this.state)} `, l2 = e ? `${styleText2("gray", S_BAR)} ` : "", f = wrapTextWithPrefix(
|
|
976
|
+
i2.output,
|
|
977
|
+
i2.message,
|
|
978
|
+
l2,
|
|
979
|
+
u3
|
|
980
|
+
), o = `${e ? `${styleText2("gray", S_BAR)}
|
|
981
|
+
` : ""}${f}
|
|
982
|
+
`, c2 = this.value ? a2 : s;
|
|
983
|
+
switch (this.state) {
|
|
984
|
+
case "submit": {
|
|
985
|
+
const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
|
|
986
|
+
return `${o}${r2}${styleText2("dim", c2)}`;
|
|
987
|
+
}
|
|
988
|
+
case "cancel": {
|
|
989
|
+
const r2 = e ? `${styleText2("gray", S_BAR)} ` : "";
|
|
990
|
+
return `${o}${r2}${styleText2(["strikethrough", "dim"], c2)}${e ? `
|
|
991
|
+
${styleText2("gray", S_BAR)}` : ""}`;
|
|
992
|
+
}
|
|
993
|
+
default: {
|
|
994
|
+
const r2 = e ? `${styleText2("cyan", S_BAR)} ` : "", g = e ? styleText2("cyan", S_BAR_END) : "";
|
|
995
|
+
return `${o}${r2}${this.value ? `${styleText2("green", S_RADIO_ACTIVE)} ${a2}` : `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", a2)}`}${i2.vertical ? e ? `
|
|
996
|
+
${styleText2("cyan", S_BAR)} ` : `
|
|
997
|
+
` : ` ${styleText2("dim", "/")} `}${this.value ? `${styleText2("dim", S_RADIO_INACTIVE)} ${styleText2("dim", s)}` : `${styleText2("green", S_RADIO_ACTIVE)} ${s}`}
|
|
998
|
+
${g}
|
|
999
|
+
`;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
}).prompt();
|
|
1004
|
+
};
|
|
1005
|
+
var MULTISELECT_INSTRUCTIONS = [
|
|
1006
|
+
`${styleText2("dim", "\u2191/\u2193")} to navigate`,
|
|
1007
|
+
`${styleText2("dim", "Space:")} select`,
|
|
1008
|
+
`${styleText2("dim", "Enter:")} confirm`
|
|
1009
|
+
];
|
|
1010
|
+
var cancel = (o = "", t2) => {
|
|
1011
|
+
const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_END)} ` : "";
|
|
1012
|
+
i2.write(`${e}${styleText2("red", o)}
|
|
1013
|
+
|
|
1014
|
+
`);
|
|
1015
|
+
};
|
|
1016
|
+
var W = (l2) => styleText2("magenta", l2);
|
|
1017
|
+
var spinner = ({
|
|
1018
|
+
indicator: l2 = "dots",
|
|
1019
|
+
onCancel: h2,
|
|
1020
|
+
output: n3 = process.stdout,
|
|
1021
|
+
cancelMessage: G,
|
|
1022
|
+
errorMessage: O,
|
|
1023
|
+
frames: E = unicode ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"],
|
|
1024
|
+
delay: F = unicode ? 80 : 120,
|
|
1025
|
+
signal: m,
|
|
1026
|
+
...I2
|
|
1027
|
+
} = {}) => {
|
|
1028
|
+
const u3 = isCI();
|
|
1029
|
+
let M, T, d = false, S = false, s = "", p, w = performance.now();
|
|
1030
|
+
const x = getColumns(n3), k = I2?.styleFrame ?? W, g = (e) => {
|
|
1031
|
+
const r2 = e > 1 ? O ?? settings.messages.error : G ?? settings.messages.cancel;
|
|
1032
|
+
S = e === 1, d && (a2(r2, e), S && typeof h2 == "function" && h2());
|
|
1033
|
+
}, f = () => g(2), i2 = () => g(1), A = () => {
|
|
1034
|
+
process.on("uncaughtExceptionMonitor", f), process.on("unhandledRejection", f), process.on("SIGINT", i2), process.on("SIGTERM", i2), process.on("exit", g), m && m.addEventListener("abort", i2);
|
|
1035
|
+
}, H = () => {
|
|
1036
|
+
process.removeListener("uncaughtExceptionMonitor", f), process.removeListener("unhandledRejection", f), process.removeListener("SIGINT", i2), process.removeListener("SIGTERM", i2), process.removeListener("exit", g), m && m.removeEventListener("abort", i2);
|
|
1037
|
+
}, y = () => {
|
|
1038
|
+
if (p === void 0) return;
|
|
1039
|
+
u3 && n3.write(`
|
|
1040
|
+
`);
|
|
1041
|
+
const r2 = wrapAnsi(p, x, {
|
|
1042
|
+
hard: true,
|
|
1043
|
+
trim: false
|
|
1044
|
+
}).split(`
|
|
1045
|
+
`);
|
|
1046
|
+
r2.length > 1 && n3.write(import_sisteransi2.cursor.up(r2.length - 1)), n3.write(import_sisteransi2.cursor.to(0)), n3.write(import_sisteransi2.erase.down());
|
|
1047
|
+
}, C = (e) => e.replace(/\.+$/, ""), _ = (e) => {
|
|
1048
|
+
const r2 = (performance.now() - e) / 1e3, t2 = Math.floor(r2 / 60), o = Math.floor(r2 % 60);
|
|
1049
|
+
return t2 > 0 ? `[${t2}m ${o}s]` : `[${o}s]`;
|
|
1050
|
+
}, N = I2.withGuide ?? settings.withGuide, P = (e = "") => {
|
|
1051
|
+
d = true, M = block({ output: n3 }), s = C(e), w = performance.now(), N && n3.write(`${styleText2("gray", S_BAR)}
|
|
1052
|
+
`);
|
|
1053
|
+
let r2 = 0, t2 = 0;
|
|
1054
|
+
A(), T = setInterval(() => {
|
|
1055
|
+
if (u3 && s === p)
|
|
1056
|
+
return;
|
|
1057
|
+
y(), p = s;
|
|
1058
|
+
const o = k(E[r2]);
|
|
1059
|
+
let v;
|
|
1060
|
+
if (u3)
|
|
1061
|
+
v = `${o} ${s}...`;
|
|
1062
|
+
else if (l2 === "timer")
|
|
1063
|
+
v = `${o} ${s} ${_(w)}`;
|
|
1064
|
+
else {
|
|
1065
|
+
const B = ".".repeat(Math.floor(t2)).slice(0, 3);
|
|
1066
|
+
v = `${o} ${s}${B}`;
|
|
1067
|
+
}
|
|
1068
|
+
const j = wrapAnsi(v, x, {
|
|
1069
|
+
hard: true,
|
|
1070
|
+
trim: false
|
|
1071
|
+
});
|
|
1072
|
+
n3.write(j), r2 = r2 + 1 < E.length ? r2 + 1 : 0, t2 = t2 < 4 ? t2 + 0.125 : 0;
|
|
1073
|
+
}, F);
|
|
1074
|
+
}, a2 = (e = "", r2 = 0, t2 = false) => {
|
|
1075
|
+
if (!d) return;
|
|
1076
|
+
d = false, clearInterval(T), y();
|
|
1077
|
+
const o = r2 === 0 ? styleText2("green", S_STEP_SUBMIT) : r2 === 1 ? styleText2("red", S_STEP_CANCEL) : styleText2("red", S_STEP_ERROR);
|
|
1078
|
+
s = e ?? s, t2 || (l2 === "timer" ? n3.write(`${o} ${s} ${_(w)}
|
|
1079
|
+
`) : n3.write(`${o} ${s}
|
|
1080
|
+
`)), H(), M();
|
|
1081
|
+
};
|
|
1082
|
+
return {
|
|
1083
|
+
start: P,
|
|
1084
|
+
stop: (e = "") => a2(e, 0),
|
|
1085
|
+
message: (e = "") => {
|
|
1086
|
+
s = C(e ?? s);
|
|
1087
|
+
},
|
|
1088
|
+
cancel: (e = "") => a2(e, 1),
|
|
1089
|
+
error: (e = "") => a2(e, 2),
|
|
1090
|
+
clear: () => a2("", 0, true),
|
|
1091
|
+
get isCancelled() {
|
|
1092
|
+
return S;
|
|
1093
|
+
}
|
|
1094
|
+
};
|
|
1095
|
+
};
|
|
1096
|
+
var u2 = {
|
|
1097
|
+
light: unicodeOr("\u2500", "-"),
|
|
1098
|
+
heavy: unicodeOr("\u2501", "="),
|
|
1099
|
+
block: unicodeOr("\u2588", "#")
|
|
1100
|
+
};
|
|
1101
|
+
var SELECT_INSTRUCTIONS = [
|
|
1102
|
+
`${styleText2("dim", "\u2191/\u2193")} to navigate`,
|
|
1103
|
+
`${styleText2("dim", "Enter:")} confirm`
|
|
1104
|
+
];
|
|
1105
|
+
var c = (t2, o) => t2.includes(`
|
|
1106
|
+
`) ? t2.split(`
|
|
1107
|
+
`).map((d) => o(d)).join(`
|
|
1108
|
+
`) : o(t2);
|
|
1109
|
+
var select = (t2) => {
|
|
1110
|
+
const o = (n3, m) => {
|
|
1111
|
+
if (n3 === void 0)
|
|
1112
|
+
return "";
|
|
1113
|
+
const s = n3.label ?? String(n3.value);
|
|
1114
|
+
switch (m) {
|
|
1115
|
+
case "disabled":
|
|
1116
|
+
return `${styleText2("gray", S_RADIO_INACTIVE)} ${c(s, (i2) => styleText2("gray", i2))}${n3.hint ? ` ${styleText2("dim", `(${n3.hint ?? "disabled"})`)}` : ""}`;
|
|
1117
|
+
case "selected":
|
|
1118
|
+
return `${c(s, (i2) => styleText2("dim", i2))}`;
|
|
1119
|
+
case "active":
|
|
1120
|
+
return `${styleText2("green", S_RADIO_ACTIVE)} ${s}${n3.hint ? ` ${styleText2("dim", `(${n3.hint})`)}` : ""}`;
|
|
1121
|
+
case "cancelled":
|
|
1122
|
+
return `${c(s, (i2) => styleText2(["strikethrough", "dim"], i2))}`;
|
|
1123
|
+
default:
|
|
1124
|
+
return `${styleText2("dim", S_RADIO_INACTIVE)} ${c(s, (i2) => styleText2("dim", i2))}`;
|
|
1125
|
+
}
|
|
1126
|
+
}, d = t2.showInstructions ?? true;
|
|
1127
|
+
return new n$1({
|
|
1128
|
+
options: t2.options,
|
|
1129
|
+
signal: t2.signal,
|
|
1130
|
+
input: t2.input,
|
|
1131
|
+
output: t2.output,
|
|
1132
|
+
initialValue: t2.initialValue,
|
|
1133
|
+
render() {
|
|
1134
|
+
const n3 = t2.withGuide ?? settings.withGuide, m = `${symbol(this.state)} `, s = `${symbolBar(this.state)} `, i2 = wrapTextWithPrefix(
|
|
1135
|
+
t2.output,
|
|
1136
|
+
t2.message,
|
|
1137
|
+
s,
|
|
1138
|
+
m
|
|
1139
|
+
), u3 = `${n3 ? `${styleText2("gray", S_BAR)}
|
|
1140
|
+
` : ""}${i2}
|
|
1141
|
+
`;
|
|
1142
|
+
switch (this.state) {
|
|
1143
|
+
case "submit": {
|
|
1144
|
+
const r2 = n3 ? `${styleText2("gray", S_BAR)} ` : "", a2 = wrapTextWithPrefix(
|
|
1145
|
+
t2.output,
|
|
1146
|
+
o(this.options[this.cursor], "selected"),
|
|
1147
|
+
r2
|
|
1148
|
+
);
|
|
1149
|
+
return `${u3}${a2}`;
|
|
1150
|
+
}
|
|
1151
|
+
case "cancel": {
|
|
1152
|
+
const r2 = n3 ? `${styleText2("gray", S_BAR)} ` : "", a2 = wrapTextWithPrefix(
|
|
1153
|
+
t2.output,
|
|
1154
|
+
o(this.options[this.cursor], "cancelled"),
|
|
1155
|
+
r2
|
|
1156
|
+
);
|
|
1157
|
+
return `${u3}${a2}${n3 ? `
|
|
1158
|
+
${styleText2("gray", S_BAR)}` : ""}`;
|
|
1159
|
+
}
|
|
1160
|
+
default: {
|
|
1161
|
+
const r2 = n3 ? `${styleText2("cyan", S_BAR)} ` : "", a2 = u3.split(`
|
|
1162
|
+
`).length, p = d ? formatInstructionFooter(SELECT_INSTRUCTIONS, n3) : n3 ? [styleText2("cyan", S_BAR_END)] : [], b = p.join(`
|
|
1163
|
+
`), f = p.length + 1;
|
|
1164
|
+
return `${u3}${r2}${limitOptions({
|
|
1165
|
+
output: t2.output,
|
|
1166
|
+
cursor: this.cursor,
|
|
1167
|
+
options: this.options,
|
|
1168
|
+
maxItems: t2.maxItems,
|
|
1169
|
+
columnPadding: r2.length,
|
|
1170
|
+
rowPadding: a2 + f,
|
|
1171
|
+
style: (g, x) => o(g, g.disabled ? "disabled" : x ? "active" : "inactive")
|
|
1172
|
+
}).join(`
|
|
1173
|
+
${r2}`)}
|
|
1174
|
+
${b}
|
|
1175
|
+
`;
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}).prompt();
|
|
1180
|
+
};
|
|
1181
|
+
var i = `${styleText2("gray", S_BAR)} `;
|
|
1182
|
+
var text = (e) => new n2({
|
|
1183
|
+
validate: e.validate,
|
|
1184
|
+
placeholder: e.placeholder,
|
|
1185
|
+
defaultValue: e.defaultValue,
|
|
1186
|
+
initialValue: e.initialValue,
|
|
1187
|
+
output: e.output,
|
|
1188
|
+
signal: e.signal,
|
|
1189
|
+
input: e.input,
|
|
1190
|
+
render() {
|
|
1191
|
+
const i2 = e?.withGuide ?? settings.withGuide, s = `${`${i2 ? `${styleText2("gray", S_BAR)}
|
|
1192
|
+
` : ""}${symbol(this.state)} `}${e.message}
|
|
1193
|
+
`, c2 = e.placeholder && e.placeholder.length > 0 ? (
|
|
1194
|
+
// biome-ignore lint/style/noNonNullAssertion: guarded by placeholder.length > 0
|
|
1195
|
+
styleText2("inverse", e.placeholder[0]) + styleText2("dim", e.placeholder.slice(1))
|
|
1196
|
+
) : styleText2(["inverse", "hidden"], "_"), o = this.userInput ? this.userInputWithCursor : c2, l2 = this.value ?? "";
|
|
1197
|
+
switch (this.state) {
|
|
1198
|
+
case "error": {
|
|
1199
|
+
const n3 = this.error ? ` ${styleText2("yellow", this.error)}` : "", r2 = i2 ? `${styleText2("yellow", S_BAR)} ` : "", d = i2 ? styleText2("yellow", S_BAR_END) : "";
|
|
1200
|
+
return `${s.trim()}
|
|
1201
|
+
${r2}${o}
|
|
1202
|
+
${d}${n3}
|
|
1203
|
+
`;
|
|
1204
|
+
}
|
|
1205
|
+
case "submit": {
|
|
1206
|
+
const n3 = l2 ? ` ${styleText2("dim", l2)}` : "", r2 = i2 ? styleText2("gray", S_BAR) : "";
|
|
1207
|
+
return `${s}${r2}${n3}`;
|
|
1208
|
+
}
|
|
1209
|
+
case "cancel": {
|
|
1210
|
+
const n3 = l2 ? ` ${styleText2(["strikethrough", "dim"], l2)}` : "", r2 = i2 ? styleText2("gray", S_BAR) : "";
|
|
1211
|
+
return `${s}${r2}${n3}${l2.trim() ? `
|
|
1212
|
+
${r2}` : ""}`;
|
|
1213
|
+
}
|
|
1214
|
+
default: {
|
|
1215
|
+
const n3 = i2 ? `${styleText2("cyan", S_BAR)} ` : "", r2 = i2 ? styleText2("cyan", S_BAR_END) : "";
|
|
1216
|
+
return `${s}${n3}${o}
|
|
1217
|
+
${r2}
|
|
1218
|
+
`;
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
}).prompt();
|
|
1223
|
+
|
|
1224
|
+
// src/prompts.ts
|
|
1225
|
+
function isInteractive() {
|
|
1226
|
+
return process.stdin.isTTY === true;
|
|
1227
|
+
}
|
|
1228
|
+
function handleCancel(value) {
|
|
1229
|
+
if (isCancel(value)) {
|
|
1230
|
+
cancel("Operation cancelled");
|
|
1231
|
+
process.exit(0);
|
|
1232
|
+
}
|
|
1233
|
+
return value;
|
|
1234
|
+
}
|
|
1235
|
+
async function promptText(message, options = {}) {
|
|
1236
|
+
const result = await text({
|
|
1237
|
+
message,
|
|
1238
|
+
defaultValue: options.defaultValue,
|
|
1239
|
+
placeholder: options.defaultValue,
|
|
1240
|
+
validate: options.validate ? (value) => options.validate(value ?? "") : void 0
|
|
1241
|
+
});
|
|
1242
|
+
return handleCancel(result);
|
|
1243
|
+
}
|
|
1244
|
+
async function promptConfirm(message, initialValue = true) {
|
|
1245
|
+
const result = await confirm({ message, initialValue });
|
|
1246
|
+
return handleCancel(result);
|
|
1247
|
+
}
|
|
1248
|
+
async function promptSelect(message, items, defaultIndex = 0) {
|
|
1249
|
+
if (items.length === 0) {
|
|
1250
|
+
throw new Error("No items to select");
|
|
1251
|
+
}
|
|
1252
|
+
const result = await select({
|
|
1253
|
+
message,
|
|
1254
|
+
options: items.map((item) => ({
|
|
1255
|
+
value: item.value,
|
|
1256
|
+
label: item.label
|
|
1257
|
+
})),
|
|
1258
|
+
initialValue: items[defaultIndex]?.value
|
|
1259
|
+
});
|
|
1260
|
+
return handleCancel(result);
|
|
1261
|
+
}
|
|
1262
|
+
var spinner2 = spinner;
|
|
29
1263
|
|
|
30
1264
|
// src/utils.ts
|
|
31
|
-
import { existsSync, readdirSync, readFileSync, writeFileSync } from "fs";
|
|
32
|
-
import { basename, join, resolve } from "path";
|
|
1265
|
+
import { existsSync as existsSync2, readdirSync as readdirSync2, readFileSync, writeFileSync } from "fs";
|
|
1266
|
+
import { basename, join as join2, resolve } from "path";
|
|
33
1267
|
var SAFE_DIR_ENTRIES = /* @__PURE__ */ new Set([
|
|
34
1268
|
".claude",
|
|
35
1269
|
".cursor",
|
|
@@ -60,7 +1294,7 @@ function isSafeEntry(name) {
|
|
|
60
1294
|
return SAFE_DIR_ENTRIES.has(name);
|
|
61
1295
|
}
|
|
62
1296
|
function findUnsafeEntries(dir) {
|
|
63
|
-
return
|
|
1297
|
+
return readdirSync2(dir).filter((entry) => !isSafeEntry(entry)).sort();
|
|
64
1298
|
}
|
|
65
1299
|
function sanitizePackageName(raw) {
|
|
66
1300
|
return raw.toLowerCase().replace(/[^a-z0-9_.-]/g, "-").replace(/^[.-]+/, "").replace(/[.-]+$/, "") || "my-app";
|
|
@@ -84,15 +1318,15 @@ function deriveProjectInfo(rawName, cwd) {
|
|
|
84
1318
|
};
|
|
85
1319
|
}
|
|
86
1320
|
function updatePackageJson(projectPath, projectName) {
|
|
87
|
-
const packageJsonPath =
|
|
1321
|
+
const packageJsonPath = join2(projectPath, "package.json");
|
|
88
1322
|
const packageJsonContent = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
89
1323
|
packageJsonContent.name = projectName;
|
|
90
1324
|
packageJsonContent.description = `MCP server: ${projectName}`;
|
|
91
1325
|
writeFileSync(packageJsonPath, JSON.stringify(packageJsonContent, null, 2));
|
|
92
1326
|
}
|
|
93
1327
|
function updateIndexTs(projectPath, projectName) {
|
|
94
|
-
const indexPath =
|
|
95
|
-
if (!
|
|
1328
|
+
const indexPath = join2(projectPath, "index.ts");
|
|
1329
|
+
if (!existsSync2(indexPath)) {
|
|
96
1330
|
return;
|
|
97
1331
|
}
|
|
98
1332
|
let content = readFileSync(indexPath, "utf-8");
|
|
@@ -100,9 +1334,45 @@ function updateIndexTs(projectPath, projectName) {
|
|
|
100
1334
|
writeFileSync(indexPath, content);
|
|
101
1335
|
}
|
|
102
1336
|
|
|
103
|
-
// src/index.
|
|
1337
|
+
// src/index.ts
|
|
104
1338
|
var __filename = fileURLToPath(import.meta.url);
|
|
105
|
-
var __dirname =
|
|
1339
|
+
var __dirname = dirname2(__filename);
|
|
1340
|
+
function parseCli(argv) {
|
|
1341
|
+
const { values, positionals } = parseArgs({
|
|
1342
|
+
args: argv,
|
|
1343
|
+
options: {
|
|
1344
|
+
template: { type: "string", short: "t" },
|
|
1345
|
+
"list-templates": { type: "boolean" },
|
|
1346
|
+
install: { type: "boolean" },
|
|
1347
|
+
skills: { type: "boolean" },
|
|
1348
|
+
dev: { type: "boolean" },
|
|
1349
|
+
canary: { type: "boolean" },
|
|
1350
|
+
yarn: { type: "boolean" },
|
|
1351
|
+
npm: { type: "boolean" },
|
|
1352
|
+
pnpm: { type: "boolean" },
|
|
1353
|
+
help: { type: "boolean", short: "h" },
|
|
1354
|
+
version: { type: "boolean", short: "V" }
|
|
1355
|
+
},
|
|
1356
|
+
allowPositionals: true,
|
|
1357
|
+
strict: false
|
|
1358
|
+
});
|
|
1359
|
+
const install = argv.includes("--install") ? true : argv.includes("--no-install") ? false : values.install;
|
|
1360
|
+
const skills = argv.includes("--skills") ? true : argv.includes("--no-skills") ? false : values.skills;
|
|
1361
|
+
return {
|
|
1362
|
+
projectName: positionals[0],
|
|
1363
|
+
options: {
|
|
1364
|
+
template: values.template,
|
|
1365
|
+
listTemplates: values["list-templates"],
|
|
1366
|
+
install,
|
|
1367
|
+
skills,
|
|
1368
|
+
dev: values.dev,
|
|
1369
|
+
canary: values.canary,
|
|
1370
|
+
yarn: values.yarn,
|
|
1371
|
+
npm: values.npm,
|
|
1372
|
+
pnpm: values.pnpm
|
|
1373
|
+
}
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
106
1376
|
function runPackageManager(packageManager, args, cwd) {
|
|
107
1377
|
return new Promise((resolve2, reject) => {
|
|
108
1378
|
const child = spawn(packageManager, args, {
|
|
@@ -131,9 +1401,11 @@ function detectPackageManager() {
|
|
|
131
1401
|
const userAgent = process.env.npm_config_user_agent || "";
|
|
132
1402
|
if (userAgent.includes("yarn")) {
|
|
133
1403
|
return "yarn";
|
|
134
|
-
}
|
|
1404
|
+
}
|
|
1405
|
+
if (userAgent.includes("pnpm")) {
|
|
135
1406
|
return "pnpm";
|
|
136
|
-
}
|
|
1407
|
+
}
|
|
1408
|
+
if (userAgent.includes("npm")) {
|
|
137
1409
|
return "npm";
|
|
138
1410
|
}
|
|
139
1411
|
return null;
|
|
@@ -144,7 +1416,6 @@ function getDevCommand(packageManager) {
|
|
|
144
1416
|
return "yarn dev";
|
|
145
1417
|
case "pnpm":
|
|
146
1418
|
return "pnpm dev";
|
|
147
|
-
case "npm":
|
|
148
1419
|
default:
|
|
149
1420
|
return "npm run dev";
|
|
150
1421
|
}
|
|
@@ -155,7 +1426,6 @@ function getInstallCommand(packageManager) {
|
|
|
155
1426
|
return "yarn";
|
|
156
1427
|
case "pnpm":
|
|
157
1428
|
return "pnpm install";
|
|
158
|
-
case "npm":
|
|
159
1429
|
default:
|
|
160
1430
|
return "npm install";
|
|
161
1431
|
}
|
|
@@ -166,7 +1436,6 @@ function getInstallArgs(packageManager) {
|
|
|
166
1436
|
return ["install"];
|
|
167
1437
|
case "pnpm":
|
|
168
1438
|
return ["install"];
|
|
169
|
-
case "npm":
|
|
170
1439
|
default:
|
|
171
1440
|
return ["install"];
|
|
172
1441
|
}
|
|
@@ -193,112 +1462,92 @@ function sendInstallTelemetryEvent(agents, skills) {
|
|
|
193
1462
|
} catch {
|
|
194
1463
|
}
|
|
195
1464
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
const
|
|
1465
|
+
var SKILLS_REPO = "https://github.com/mcp-use/mcp-use.git";
|
|
1466
|
+
var SKILLS_SPARSE_PATH = "skills/mcp-apps-builder";
|
|
1467
|
+
var SKILLS_AGENT_DIRS = [".cursor", ".claude", ".agent"];
|
|
1468
|
+
var SKILLS_MANUAL_INSTALL_CMD = "npx --yes skills add mcp-use/mcp-use --yes --skill mcp-apps-builder -a cursor -a claude-code -a codex";
|
|
1469
|
+
function isGitAvailable() {
|
|
1470
|
+
const result = spawnSync("git", ["--version"], {
|
|
1471
|
+
stdio: "ignore",
|
|
1472
|
+
shell: false
|
|
1473
|
+
});
|
|
1474
|
+
return result.status === 0 && !result.error;
|
|
1475
|
+
}
|
|
1476
|
+
function warnSkillsInstallFailed(missingGit) {
|
|
1477
|
+
const reason = missingGit ? "Failed to install skills: git is not installed or not in PATH." : "Failed to install skills.";
|
|
1478
|
+
console.log(yellow(`\u26A0\uFE0F ${reason}`));
|
|
1479
|
+
console.log(yellow(` Run manually: ${SKILLS_MANUAL_INSTALL_CMD}`));
|
|
1480
|
+
}
|
|
1481
|
+
async function installSkills(projectPath) {
|
|
1482
|
+
const tempDir = mkdtempSync(join3(tmpdir(), "mcp-use-skills-"));
|
|
1483
|
+
const repoDir = join3(tempDir, "repo");
|
|
202
1484
|
try {
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
1485
|
+
const clone = spawnSync(
|
|
1486
|
+
"git",
|
|
1487
|
+
[
|
|
1488
|
+
"clone",
|
|
1489
|
+
"--depth",
|
|
1490
|
+
"1",
|
|
1491
|
+
"--filter=blob:none",
|
|
1492
|
+
"--sparse",
|
|
1493
|
+
"--single-branch",
|
|
1494
|
+
SKILLS_REPO,
|
|
1495
|
+
repoDir
|
|
1496
|
+
],
|
|
1497
|
+
{ stdio: "ignore", shell: false }
|
|
1498
|
+
);
|
|
1499
|
+
if (clone.status !== 0 || clone.error) {
|
|
1500
|
+
throw new Error("git clone failed");
|
|
206
1501
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
filter: (path) => path.includes("/skills/mcp-apps-builder/"),
|
|
212
|
-
strip: 1
|
|
213
|
-
// Removes 'mcp-use-{commit}/' prefix
|
|
214
|
-
})
|
|
1502
|
+
const checkout = spawnSync(
|
|
1503
|
+
"git",
|
|
1504
|
+
["sparse-checkout", "set", SKILLS_SPARSE_PATH],
|
|
1505
|
+
{ cwd: repoDir, stdio: "ignore", shell: false }
|
|
215
1506
|
);
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
throw new Error("Skills folder not found in tarball");
|
|
1507
|
+
if (checkout.status !== 0 || checkout.error) {
|
|
1508
|
+
throw new Error("git sparse-checkout failed");
|
|
219
1509
|
}
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
"claude-code": ".claude",
|
|
224
|
-
codex: ".agent"
|
|
225
|
-
};
|
|
226
|
-
for (const preset of presets) {
|
|
227
|
-
const folderName = presetFolders[preset];
|
|
228
|
-
const outputPath = join2(projectPath, folderName, "skills");
|
|
229
|
-
cpSync(skillsPath, outputPath, { recursive: true });
|
|
1510
|
+
const skillSrc = join3(repoDir, SKILLS_SPARSE_PATH);
|
|
1511
|
+
if (!existsSync3(skillSrc)) {
|
|
1512
|
+
throw new Error("mcp-apps-builder skill not found in repository");
|
|
230
1513
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
)
|
|
238
|
-
);
|
|
239
|
-
console.log(
|
|
240
|
-
chalk.yellow(
|
|
241
|
-
` Error: ${error instanceof Error ? error.message : String(error)}`
|
|
242
|
-
)
|
|
243
|
-
);
|
|
244
|
-
return;
|
|
1514
|
+
for (const agentDir of SKILLS_AGENT_DIRS) {
|
|
1515
|
+
const dest = join3(projectPath, agentDir, "skills", "mcp-apps-builder");
|
|
1516
|
+
mkdirSync(dirname2(dest), { recursive: true });
|
|
1517
|
+
cpSync(skillSrc, dest, { recursive: true });
|
|
1518
|
+
}
|
|
1519
|
+
sendInstallTelemetryEvent("cursor,claude-code,codex", "mcp-apps-builder");
|
|
245
1520
|
} finally {
|
|
246
1521
|
rmSync(tempDir, { recursive: true, force: true });
|
|
247
1522
|
}
|
|
248
1523
|
}
|
|
249
|
-
var program = new Command();
|
|
250
1524
|
function renderLogo() {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
chalk.white.bold(
|
|
263
|
-
" \u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2501\u2501\u2501\u2501 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 "
|
|
264
|
-
)
|
|
265
|
-
);
|
|
266
|
-
console.log(
|
|
267
|
-
chalk.white.bold(
|
|
268
|
-
" \u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2501\u2501\u2501\u2501 \u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u255D "
|
|
269
|
-
)
|
|
270
|
-
);
|
|
271
|
-
console.log(
|
|
272
|
-
chalk.white.bold(
|
|
273
|
-
" \u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557"
|
|
274
|
-
)
|
|
275
|
-
);
|
|
276
|
-
console.log(
|
|
277
|
-
chalk.white.bold(
|
|
278
|
-
" \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"
|
|
279
|
-
)
|
|
280
|
-
);
|
|
1525
|
+
const lines = [
|
|
1526
|
+
" \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557",
|
|
1527
|
+
" \u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D",
|
|
1528
|
+
" \u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2501\u2501\u2501\u2501 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 ",
|
|
1529
|
+
" \u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u255D \u2501\u2501\u2501\u2501 \u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u255D ",
|
|
1530
|
+
" \u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557",
|
|
1531
|
+
" \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"
|
|
1532
|
+
];
|
|
1533
|
+
for (const line of lines) {
|
|
1534
|
+
console.log(whiteBold(line));
|
|
1535
|
+
}
|
|
281
1536
|
console.log("");
|
|
282
|
-
console.log(
|
|
1537
|
+
console.log(gray(bold(" by Manufact")));
|
|
283
1538
|
}
|
|
284
1539
|
var packageJson = JSON.parse(
|
|
285
|
-
readFileSync2(
|
|
1540
|
+
readFileSync2(join3(__dirname, "../package.json"), "utf-8")
|
|
286
1541
|
);
|
|
287
1542
|
function getCurrentPackageVersions(isDevelopment = false, useCanary = false) {
|
|
288
1543
|
const versions = {};
|
|
289
1544
|
try {
|
|
290
1545
|
if (isDevelopment) {
|
|
291
1546
|
versions["mcp-use"] = "workspace:*";
|
|
292
|
-
versions["@mcp-use/cli"] = "workspace:*";
|
|
293
|
-
versions["@mcp-use/inspector"] = "workspace:*";
|
|
294
1547
|
} else if (useCanary) {
|
|
295
1548
|
versions["mcp-use"] = "canary";
|
|
296
|
-
versions["@mcp-use/cli"] = "canary";
|
|
297
|
-
versions["@mcp-use/inspector"] = "canary";
|
|
298
1549
|
} else {
|
|
299
1550
|
versions["mcp-use"] = "latest";
|
|
300
|
-
versions["@mcp-use/cli"] = "latest";
|
|
301
|
-
versions["@mcp-use/inspector"] = "latest";
|
|
302
1551
|
}
|
|
303
1552
|
} catch (error) {
|
|
304
1553
|
if (process.env.NODE_ENV === "development") {
|
|
@@ -330,14 +1579,6 @@ function processTemplateFile(filePath, versions, isDevelopment = false, useCanar
|
|
|
330
1579
|
/"mcp-use": "\^[^"]+"/,
|
|
331
1580
|
'"mcp-use": "workspace:*"'
|
|
332
1581
|
);
|
|
333
|
-
processedContent = processedContent.replace(
|
|
334
|
-
/"@mcp-use\/cli": "\^[^"]+"/,
|
|
335
|
-
'"@mcp-use/cli": "workspace:*"'
|
|
336
|
-
);
|
|
337
|
-
processedContent = processedContent.replace(
|
|
338
|
-
/"@mcp-use\/inspector": "\^[^"]+"/,
|
|
339
|
-
'"@mcp-use/inspector": "workspace:*"'
|
|
340
|
-
);
|
|
341
1582
|
} else if (useCanary) {
|
|
342
1583
|
processedContent = processedContent.replace(
|
|
343
1584
|
/"mcp-use": "workspace:\*"/,
|
|
@@ -347,362 +1588,55 @@ function processTemplateFile(filePath, versions, isDevelopment = false, useCanar
|
|
|
347
1588
|
/"mcp-use": "\^[^"]+"/,
|
|
348
1589
|
`"mcp-use": "canary"`
|
|
349
1590
|
);
|
|
350
|
-
processedContent = processedContent.replace(
|
|
351
|
-
/"@mcp-use\/cli": "workspace:\*"/,
|
|
352
|
-
`"@mcp-use/cli": "canary"`
|
|
353
|
-
);
|
|
354
|
-
processedContent = processedContent.replace(
|
|
355
|
-
/"@mcp-use\/cli": "\^[^"]+"/,
|
|
356
|
-
`"@mcp-use/cli": "canary"`
|
|
357
|
-
);
|
|
358
|
-
processedContent = processedContent.replace(
|
|
359
|
-
/"@mcp-use\/inspector": "workspace:\*"/,
|
|
360
|
-
`"@mcp-use/inspector": "canary"`
|
|
361
|
-
);
|
|
362
|
-
processedContent = processedContent.replace(
|
|
363
|
-
/"@mcp-use\/inspector": "\^[^"]+"/,
|
|
364
|
-
`"@mcp-use/inspector": "canary"`
|
|
365
|
-
);
|
|
366
1591
|
} else {
|
|
367
1592
|
processedContent = processedContent.replace(
|
|
368
1593
|
/"mcp-use": "workspace:\*"/,
|
|
369
1594
|
`"mcp-use": "${versions["mcp-use"] || "latest"}"`
|
|
370
1595
|
);
|
|
371
|
-
processedContent = processedContent.replace(
|
|
372
|
-
/"@mcp-use\/cli": "workspace:\*"/,
|
|
373
|
-
`"@mcp-use/cli": "${versions["@mcp-use/cli"] || "latest"}"`
|
|
374
|
-
);
|
|
375
|
-
processedContent = processedContent.replace(
|
|
376
|
-
/"@mcp-use\/inspector": "workspace:\*"/,
|
|
377
|
-
`"@mcp-use/inspector": "${versions["@mcp-use/inspector"] || "latest"}"`
|
|
378
|
-
);
|
|
379
1596
|
}
|
|
380
1597
|
return processedContent;
|
|
381
1598
|
}
|
|
382
1599
|
function getAvailableTemplates() {
|
|
383
|
-
const templatesDir =
|
|
384
|
-
if (!
|
|
1600
|
+
const templatesDir = join3(__dirname, "templates");
|
|
1601
|
+
if (!existsSync3(templatesDir)) {
|
|
385
1602
|
return [];
|
|
386
1603
|
}
|
|
387
|
-
return
|
|
1604
|
+
return readdirSync3(templatesDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name).sort();
|
|
388
1605
|
}
|
|
389
1606
|
function listTemplates() {
|
|
390
1607
|
console.log("");
|
|
391
1608
|
renderLogo();
|
|
392
1609
|
console.log("");
|
|
393
|
-
console.log(
|
|
1610
|
+
console.log(bold("Available Templates:"));
|
|
394
1611
|
console.log("");
|
|
395
|
-
const templatesDir =
|
|
1612
|
+
const templatesDir = join3(__dirname, "templates");
|
|
396
1613
|
const availableTemplates = getAvailableTemplates();
|
|
397
1614
|
if (availableTemplates.length === 0) {
|
|
398
|
-
console.log(
|
|
1615
|
+
console.log(red("\u274C No templates found!"));
|
|
399
1616
|
return;
|
|
400
1617
|
}
|
|
401
1618
|
for (const template of availableTemplates) {
|
|
402
|
-
const packageJsonPath =
|
|
1619
|
+
const packageJsonPath = join3(templatesDir, template, "package.json");
|
|
403
1620
|
let description = "MCP server template";
|
|
404
|
-
if (
|
|
1621
|
+
if (existsSync3(packageJsonPath)) {
|
|
405
1622
|
try {
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
|
|
1623
|
+
const templatePackageJson = JSON.parse(
|
|
1624
|
+
readFileSync2(packageJsonPath, "utf-8")
|
|
1625
|
+
);
|
|
1626
|
+
description = templatePackageJson.description || description;
|
|
1627
|
+
} catch {
|
|
409
1628
|
}
|
|
410
1629
|
}
|
|
411
|
-
console.log(
|
|
412
|
-
chalk.cyan(` ${template.padEnd(15)}`),
|
|
413
|
-
chalk.gray(description)
|
|
414
|
-
);
|
|
1630
|
+
console.log(cyan(` ${template.padEnd(15)}`), gray(description));
|
|
415
1631
|
}
|
|
416
1632
|
console.log("");
|
|
417
1633
|
console.log(
|
|
418
|
-
|
|
1634
|
+
gray(
|
|
419
1635
|
"\u{1F4A1} Use with: npx create-mcp-use-app my-project --template <template>"
|
|
420
1636
|
)
|
|
421
1637
|
);
|
|
422
1638
|
console.log("");
|
|
423
1639
|
}
|
|
424
|
-
program.name("create-mcp-use-app").description("Create a new MCP server project").version(packageJson.version).argument("[project-name]", "Name of the MCP server project").option(
|
|
425
|
-
"-t, --template <template>",
|
|
426
|
-
"Template to use (starter, mcp-ui, mcp-apps, blank) or GitHub repo URL (owner/repo or https://github.com/owner/repo)"
|
|
427
|
-
).option("--list-templates", "List all available templates").option("--install", "Install dependencies after creating project").option("--no-install", "Skip installing dependencies").option("--skills", "Install skills for all agents").option("--no-skills", "Skip installing skills").option("--no-git", "Skip initializing a git repository").option("--dev", "Use workspace dependencies for development").option("--canary", "Use canary versions of packages").option("--yarn", "Use yarn as package manager").option("--npm", "Use npm as package manager").option("--pnpm", "Use pnpm as package manager").action(
|
|
428
|
-
async (projectName, options) => {
|
|
429
|
-
try {
|
|
430
|
-
if (options.listTemplates) {
|
|
431
|
-
listTemplates();
|
|
432
|
-
process.exit(0);
|
|
433
|
-
}
|
|
434
|
-
if (options.dev && options.canary) {
|
|
435
|
-
console.error(chalk.red("\u274C Cannot use --dev and --canary together"));
|
|
436
|
-
console.error(
|
|
437
|
-
chalk.yellow(" Please choose only one dependency mode")
|
|
438
|
-
);
|
|
439
|
-
process.exit(1);
|
|
440
|
-
}
|
|
441
|
-
let selectedTemplate = options.template;
|
|
442
|
-
console.log("");
|
|
443
|
-
renderLogo();
|
|
444
|
-
console.log("");
|
|
445
|
-
if (!projectName) {
|
|
446
|
-
projectName = await promptForProjectName();
|
|
447
|
-
console.log("");
|
|
448
|
-
}
|
|
449
|
-
if (!options.template && !selectedTemplate) {
|
|
450
|
-
selectedTemplate = await promptForTemplate();
|
|
451
|
-
}
|
|
452
|
-
if (!selectedTemplate) {
|
|
453
|
-
selectedTemplate = "starter";
|
|
454
|
-
}
|
|
455
|
-
const trimmedProjectName = projectName.trim();
|
|
456
|
-
if (!trimmedProjectName) {
|
|
457
|
-
console.error(chalk.red("\u274C Project name cannot be empty"));
|
|
458
|
-
process.exit(1);
|
|
459
|
-
}
|
|
460
|
-
const { useCurrentDir, projectPath, displayName, packageName } = deriveProjectInfo(trimmedProjectName, process.cwd());
|
|
461
|
-
if (useCurrentDir) {
|
|
462
|
-
const unsafeEntries = findUnsafeEntries(projectPath);
|
|
463
|
-
if (unsafeEntries.length > 0) {
|
|
464
|
-
console.error(
|
|
465
|
-
chalk.red(
|
|
466
|
-
"\u274C Cannot initialize here \u2014 these entries would clash with the template:"
|
|
467
|
-
)
|
|
468
|
-
);
|
|
469
|
-
for (const entry of unsafeEntries) {
|
|
470
|
-
console.error(chalk.red(` \u2022 ${entry}`));
|
|
471
|
-
}
|
|
472
|
-
console.error("");
|
|
473
|
-
console.error(
|
|
474
|
-
chalk.yellow(
|
|
475
|
-
" Remove these files, or pass a project name to scaffold into a new subdirectory instead."
|
|
476
|
-
)
|
|
477
|
-
);
|
|
478
|
-
process.exit(1);
|
|
479
|
-
}
|
|
480
|
-
} else {
|
|
481
|
-
if (trimmedProjectName.includes("..") || trimmedProjectName.includes("/") || trimmedProjectName.includes("\\")) {
|
|
482
|
-
console.error(
|
|
483
|
-
chalk.red(
|
|
484
|
-
'\u274C Project name cannot contain path separators or ".."'
|
|
485
|
-
)
|
|
486
|
-
);
|
|
487
|
-
console.error(
|
|
488
|
-
chalk.yellow(' Use simple names like "my-mcp-server"')
|
|
489
|
-
);
|
|
490
|
-
process.exit(1);
|
|
491
|
-
}
|
|
492
|
-
const protectedNames = [
|
|
493
|
-
"node_modules",
|
|
494
|
-
".git",
|
|
495
|
-
".env",
|
|
496
|
-
"package.json",
|
|
497
|
-
"src",
|
|
498
|
-
"dist"
|
|
499
|
-
];
|
|
500
|
-
if (protectedNames.includes(trimmedProjectName.toLowerCase())) {
|
|
501
|
-
console.error(
|
|
502
|
-
chalk.red(`\u274C Cannot use protected name "${trimmedProjectName}"`)
|
|
503
|
-
);
|
|
504
|
-
console.error(
|
|
505
|
-
chalk.yellow(" Please choose a different project name")
|
|
506
|
-
);
|
|
507
|
-
process.exit(1);
|
|
508
|
-
}
|
|
509
|
-
if (existsSync2(projectPath)) {
|
|
510
|
-
console.error(
|
|
511
|
-
chalk.red(`\u274C Directory "${trimmedProjectName}" already exists!`)
|
|
512
|
-
);
|
|
513
|
-
console.error(
|
|
514
|
-
chalk.yellow(
|
|
515
|
-
" Please choose a different name or remove the existing directory"
|
|
516
|
-
)
|
|
517
|
-
);
|
|
518
|
-
process.exit(1);
|
|
519
|
-
}
|
|
520
|
-
mkdirSync(projectPath, { recursive: true });
|
|
521
|
-
}
|
|
522
|
-
console.log(chalk.cyan(`\u{1F680} Creating MCP server "${displayName}"...`));
|
|
523
|
-
const validatedTemplate = validateTemplateName(selectedTemplate);
|
|
524
|
-
const versions = getCurrentPackageVersions(options.dev, options.canary);
|
|
525
|
-
await copyTemplate(
|
|
526
|
-
projectPath,
|
|
527
|
-
validatedTemplate,
|
|
528
|
-
versions,
|
|
529
|
-
options.dev,
|
|
530
|
-
options.canary
|
|
531
|
-
);
|
|
532
|
-
updatePackageJson(projectPath, packageName);
|
|
533
|
-
updateIndexTs(projectPath, packageName);
|
|
534
|
-
if (options.template !== void 0) {
|
|
535
|
-
if (options.install === void 0) {
|
|
536
|
-
options.install = false;
|
|
537
|
-
}
|
|
538
|
-
if (options.skills === void 0) {
|
|
539
|
-
options.skills = true;
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
console.log("");
|
|
543
|
-
const shouldInstallSkills = options.skills !== void 0 ? options.skills : await promptForSkillsPresets();
|
|
544
|
-
let skillsInstalled = false;
|
|
545
|
-
if (shouldInstallSkills) {
|
|
546
|
-
console.log("");
|
|
547
|
-
console.log(chalk.cyan("\u{1F4DA} Installing skills..."));
|
|
548
|
-
try {
|
|
549
|
-
await addSkillsToProject(projectPath);
|
|
550
|
-
skillsInstalled = true;
|
|
551
|
-
console.log(chalk.green("\u2705 Skills installed successfully!"));
|
|
552
|
-
} catch (err) {
|
|
553
|
-
console.log(
|
|
554
|
-
chalk.yellow(
|
|
555
|
-
"\u26A0\uFE0F Skills install failed. Run `npx skills add mcp-use/mcp-use` manually in root directory."
|
|
556
|
-
)
|
|
557
|
-
);
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
let usedPackageManager = "npm";
|
|
561
|
-
if (options.yarn) {
|
|
562
|
-
usedPackageManager = "yarn";
|
|
563
|
-
} else if (options.npm) {
|
|
564
|
-
usedPackageManager = "npm";
|
|
565
|
-
} else if (options.pnpm) {
|
|
566
|
-
usedPackageManager = "pnpm";
|
|
567
|
-
} else {
|
|
568
|
-
const detected = detectPackageManager();
|
|
569
|
-
if (detected) {
|
|
570
|
-
usedPackageManager = detected;
|
|
571
|
-
} else {
|
|
572
|
-
const defaultOrder = ["npm", "pnpm", "yarn"];
|
|
573
|
-
usedPackageManager = defaultOrder[0];
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
console.log("");
|
|
577
|
-
const shouldInstall = options.install !== void 0 ? options.install : await promptForInstall(usedPackageManager);
|
|
578
|
-
if (shouldInstall) {
|
|
579
|
-
console.log("");
|
|
580
|
-
console.log(chalk.cyan("\u{1F4E6} Installing dependencies..."));
|
|
581
|
-
console.log("");
|
|
582
|
-
const isKnownManager = options.yarn || options.npm || options.pnpm || detectPackageManager();
|
|
583
|
-
const managersToTry = isKnownManager ? [usedPackageManager] : ["npm", "pnpm", "yarn"];
|
|
584
|
-
let installed = false;
|
|
585
|
-
for (const pm of managersToTry) {
|
|
586
|
-
const spinner = ora(`Installing packages with ${pm}...`).start();
|
|
587
|
-
try {
|
|
588
|
-
await runPackageManager(pm, getInstallArgs(pm), projectPath);
|
|
589
|
-
usedPackageManager = pm;
|
|
590
|
-
spinner.succeed(`Packages installed successfully with ${pm}`);
|
|
591
|
-
installed = true;
|
|
592
|
-
break;
|
|
593
|
-
} catch (err) {
|
|
594
|
-
const remaining = managersToTry.slice(
|
|
595
|
-
managersToTry.indexOf(pm) + 1
|
|
596
|
-
);
|
|
597
|
-
if (remaining.length > 0) {
|
|
598
|
-
spinner.warn(`${pm} not available, trying ${remaining[0]}...`);
|
|
599
|
-
} else {
|
|
600
|
-
spinner.fail("Package installation failed");
|
|
601
|
-
if (err instanceof Error) {
|
|
602
|
-
console.error(chalk.red(err.message));
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
if (!installed) {
|
|
608
|
-
console.log(
|
|
609
|
-
'\u26A0\uFE0F Please run "npm install", "yarn install", or "pnpm install" manually'
|
|
610
|
-
);
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
console.log("");
|
|
614
|
-
console.log(chalk.green("\u2705 MCP server created successfully!"));
|
|
615
|
-
if (options.dev) {
|
|
616
|
-
console.log(
|
|
617
|
-
chalk.yellow("\u{1F527} Development mode: Using workspace dependencies")
|
|
618
|
-
);
|
|
619
|
-
} else if (options.canary) {
|
|
620
|
-
console.log(
|
|
621
|
-
chalk.cyan("\u{1F680} Canary mode: Using canary versions of packages")
|
|
622
|
-
);
|
|
623
|
-
}
|
|
624
|
-
console.log("");
|
|
625
|
-
console.log(chalk.bold("\u{1F4C1} Project structure:"));
|
|
626
|
-
console.log(` ${useCurrentDir ? "." : displayName}/`);
|
|
627
|
-
if (skillsInstalled) {
|
|
628
|
-
console.log(" \u251C\u2500\u2500 .agent/skills/");
|
|
629
|
-
console.log(" \u251C\u2500\u2500 .claude/skills/");
|
|
630
|
-
console.log(" \u251C\u2500\u2500 .cursor/skills/");
|
|
631
|
-
}
|
|
632
|
-
if (validatedTemplate === "blank") {
|
|
633
|
-
console.log(" \u251C\u2500\u2500 public/");
|
|
634
|
-
console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
|
|
635
|
-
console.log(" \u251C\u2500\u2500 package.json");
|
|
636
|
-
console.log(" \u251C\u2500\u2500 tsconfig.json");
|
|
637
|
-
console.log(" \u2514\u2500\u2500 README.md");
|
|
638
|
-
} else if (validatedTemplate === "mcp-apps") {
|
|
639
|
-
console.log(" \u251C\u2500\u2500 public/");
|
|
640
|
-
console.log(" \u251C\u2500\u2500 resources/");
|
|
641
|
-
console.log(" \u2502 \u2514\u2500\u2500 product-search-result/");
|
|
642
|
-
console.log(" \u2502 \u2514\u2500\u2500 widget.tsx");
|
|
643
|
-
console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
|
|
644
|
-
console.log(" \u251C\u2500\u2500 package.json");
|
|
645
|
-
console.log(" \u251C\u2500\u2500 tsconfig.json");
|
|
646
|
-
console.log(" \u2514\u2500\u2500 README.md");
|
|
647
|
-
} else if (validatedTemplate === "starter") {
|
|
648
|
-
console.log(" \u251C\u2500\u2500 public/");
|
|
649
|
-
console.log(" \u251C\u2500\u2500 resources/");
|
|
650
|
-
console.log(" \u2502 \u2514\u2500\u2500 display-weather.tsx");
|
|
651
|
-
console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
|
|
652
|
-
console.log(" \u251C\u2500\u2500 package.json");
|
|
653
|
-
console.log(" \u251C\u2500\u2500 tsconfig.json");
|
|
654
|
-
console.log(" \u2514\u2500\u2500 README.md");
|
|
655
|
-
} else {
|
|
656
|
-
console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
|
|
657
|
-
console.log(" \u251C\u2500\u2500 package.json");
|
|
658
|
-
console.log(" \u251C\u2500\u2500 tsconfig.json");
|
|
659
|
-
console.log(" \u2514\u2500\u2500 README.md");
|
|
660
|
-
}
|
|
661
|
-
console.log("");
|
|
662
|
-
console.log(chalk.bold("\u{1F680} To get started:"));
|
|
663
|
-
if (!useCurrentDir) {
|
|
664
|
-
console.log(chalk.cyan(` cd ${displayName}`));
|
|
665
|
-
}
|
|
666
|
-
if (!shouldInstall) {
|
|
667
|
-
console.log(
|
|
668
|
-
chalk.cyan(` ${getInstallCommand(usedPackageManager)}`)
|
|
669
|
-
);
|
|
670
|
-
}
|
|
671
|
-
console.log(chalk.cyan(` ${getDevCommand(usedPackageManager)}`));
|
|
672
|
-
console.log("");
|
|
673
|
-
console.log(chalk.bold("\u{1F4E4} To deploy:"));
|
|
674
|
-
console.log(
|
|
675
|
-
chalk.cyan(
|
|
676
|
-
` ${usedPackageManager === "yarn" ? "yarn" : usedPackageManager === "pnpm" ? "pnpm" : "npm run"} deploy`
|
|
677
|
-
)
|
|
678
|
-
);
|
|
679
|
-
console.log("");
|
|
680
|
-
if (options.dev) {
|
|
681
|
-
console.log(
|
|
682
|
-
chalk.yellow(
|
|
683
|
-
"\u{1F4A1} Development mode: Your project uses workspace dependencies"
|
|
684
|
-
)
|
|
685
|
-
);
|
|
686
|
-
console.log(
|
|
687
|
-
chalk.yellow(
|
|
688
|
-
" Make sure you're in the mcp-use workspace root for development"
|
|
689
|
-
)
|
|
690
|
-
);
|
|
691
|
-
console.log("");
|
|
692
|
-
}
|
|
693
|
-
console.log(chalk.cyan("\u{1F4DA} Learn more: https://manufact.com/docs"));
|
|
694
|
-
console.log(chalk.gray("\u{1F4AC} For feedback and bug reporting visit:"));
|
|
695
|
-
console.log(
|
|
696
|
-
chalk.gray(
|
|
697
|
-
" https://github.com/mcp-use/mcp-use or https://manufact.com"
|
|
698
|
-
)
|
|
699
|
-
);
|
|
700
|
-
} catch (error) {
|
|
701
|
-
console.error("\u274C Error creating MCP server:", error);
|
|
702
|
-
process.exit(1);
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
);
|
|
706
1640
|
function parseGitHubRepoUrl(url) {
|
|
707
1641
|
const trimmed = url.trim();
|
|
708
1642
|
let match = trimmed.match(
|
|
@@ -758,17 +1692,16 @@ async function cloneGitHubRepo(repoInfo, tempDir) {
|
|
|
758
1692
|
shell: false
|
|
759
1693
|
});
|
|
760
1694
|
if (versionCheck.status !== 0 || versionCheck.error) {
|
|
1695
|
+
console.error(red("\u274C Git is not installed or not available in PATH"));
|
|
761
1696
|
console.error(
|
|
762
|
-
|
|
763
|
-
);
|
|
764
|
-
console.error(
|
|
765
|
-
chalk.yellow(" Please install Git to use GitHub repository templates")
|
|
1697
|
+
yellow(" Please install Git to use GitHub repository templates")
|
|
766
1698
|
);
|
|
767
1699
|
process.exit(1);
|
|
768
1700
|
}
|
|
769
1701
|
const repoUrl = `https://github.com/${repoInfo.owner}/${repoInfo.repo}.git`;
|
|
770
1702
|
const branch = repoInfo.branch || "main";
|
|
771
|
-
const
|
|
1703
|
+
const s = spinner2();
|
|
1704
|
+
s.start("Cloning repository from GitHub...");
|
|
772
1705
|
const cloneWithBranch = (branchName) => {
|
|
773
1706
|
const result = spawnSync(
|
|
774
1707
|
"git",
|
|
@@ -789,33 +1722,33 @@ async function cloneGitHubRepo(repoInfo, tempDir) {
|
|
|
789
1722
|
};
|
|
790
1723
|
const cloneResult = cloneWithBranch(branch);
|
|
791
1724
|
if (cloneResult.success) {
|
|
792
|
-
|
|
1725
|
+
s.stop("Repository cloned successfully");
|
|
793
1726
|
return tempDir;
|
|
794
1727
|
}
|
|
795
1728
|
if (!repoInfo.branch) {
|
|
796
|
-
|
|
1729
|
+
s.message(`Branch "${branch}" not found, trying "main"...`);
|
|
797
1730
|
const mainResult = cloneWithBranch("main");
|
|
798
1731
|
if (mainResult.success) {
|
|
799
|
-
|
|
1732
|
+
s.stop("Repository cloned successfully (using main branch)");
|
|
800
1733
|
return tempDir;
|
|
801
1734
|
}
|
|
802
|
-
|
|
1735
|
+
s.message('Branch "main" not found, trying "master"...');
|
|
803
1736
|
const masterResult = cloneWithBranch("master");
|
|
804
1737
|
if (masterResult.success) {
|
|
805
|
-
|
|
1738
|
+
s.stop("Repository cloned successfully (using master branch)");
|
|
806
1739
|
return tempDir;
|
|
807
1740
|
}
|
|
808
1741
|
}
|
|
809
|
-
|
|
810
|
-
console.error(
|
|
1742
|
+
s.error("Failed to clone repository");
|
|
1743
|
+
console.error(red(`\u274C Error cloning repository: ${repoUrl}`));
|
|
811
1744
|
if (repoInfo.branch) {
|
|
812
|
-
console.error(
|
|
1745
|
+
console.error(yellow(` Branch "${repoInfo.branch}" may not exist`));
|
|
813
1746
|
}
|
|
814
1747
|
const errorMessage = cloneResult.error?.message || "Unknown error";
|
|
815
1748
|
if (errorMessage.includes("not found")) {
|
|
816
|
-
console.error(
|
|
1749
|
+
console.error(yellow(" Repository may not exist or is private"));
|
|
817
1750
|
} else {
|
|
818
|
-
console.error(
|
|
1751
|
+
console.error(yellow(` ${errorMessage}`));
|
|
819
1752
|
}
|
|
820
1753
|
throw cloneResult.error || new Error("Failed to clone repository");
|
|
821
1754
|
}
|
|
@@ -826,20 +1759,19 @@ function validateTemplateName(template) {
|
|
|
826
1759
|
}
|
|
827
1760
|
const aliases = {
|
|
828
1761
|
"apps-sdk": "mcp-apps"
|
|
829
|
-
// Silent redirect for backward compatibility
|
|
830
1762
|
};
|
|
831
1763
|
const resolvedTemplate = aliases[sanitized] || sanitized;
|
|
832
1764
|
if (resolvedTemplate.includes("..") || resolvedTemplate.includes("/") || resolvedTemplate.includes("\\")) {
|
|
833
|
-
console.error(
|
|
1765
|
+
console.error(red("\u274C Invalid template name"));
|
|
834
1766
|
console.error(
|
|
835
|
-
|
|
1767
|
+
yellow(" Template name cannot contain path separators")
|
|
836
1768
|
);
|
|
837
1769
|
process.exit(1);
|
|
838
1770
|
}
|
|
839
1771
|
if (!/^[a-zA-Z0-9_-]+$/.test(resolvedTemplate)) {
|
|
840
|
-
console.error(
|
|
1772
|
+
console.error(red("\u274C Invalid template name"));
|
|
841
1773
|
console.error(
|
|
842
|
-
|
|
1774
|
+
yellow(
|
|
843
1775
|
" Template name can only contain letters, numbers, hyphens, and underscores"
|
|
844
1776
|
)
|
|
845
1777
|
);
|
|
@@ -850,7 +1782,7 @@ function validateTemplateName(template) {
|
|
|
850
1782
|
async function copyTemplate(projectPath, template, versions, isDevelopment = false, useCanary = false) {
|
|
851
1783
|
const repoInfo = parseGitHubRepoUrl(template);
|
|
852
1784
|
if (repoInfo) {
|
|
853
|
-
const tempDir = mkdtempSync(
|
|
1785
|
+
const tempDir = mkdtempSync(join3(tmpdir(), "create-mcp-use-app-"));
|
|
854
1786
|
try {
|
|
855
1787
|
await cloneGitHubRepo(repoInfo, tempDir);
|
|
856
1788
|
copyDirectoryWithProcessing(
|
|
@@ -863,7 +1795,7 @@ async function copyTemplate(projectPath, template, versions, isDevelopment = fal
|
|
|
863
1795
|
} finally {
|
|
864
1796
|
try {
|
|
865
1797
|
rmSync(tempDir, { recursive: true, force: true });
|
|
866
|
-
} catch
|
|
1798
|
+
} catch {
|
|
867
1799
|
if (process.env.NODE_ENV === "development") {
|
|
868
1800
|
console.warn(
|
|
869
1801
|
`Warning: Failed to clean up temp directory: ${tempDir}`
|
|
@@ -873,12 +1805,12 @@ async function copyTemplate(projectPath, template, versions, isDevelopment = fal
|
|
|
873
1805
|
}
|
|
874
1806
|
return;
|
|
875
1807
|
}
|
|
876
|
-
const templatePath =
|
|
877
|
-
if (!
|
|
878
|
-
console.error(
|
|
879
|
-
const templatesDir =
|
|
880
|
-
if (
|
|
881
|
-
const availableTemplates =
|
|
1808
|
+
const templatePath = join3(__dirname, "templates", template);
|
|
1809
|
+
if (!existsSync3(templatePath)) {
|
|
1810
|
+
console.error(red(`\u274C Template "${template}" not found!`));
|
|
1811
|
+
const templatesDir = join3(__dirname, "templates");
|
|
1812
|
+
if (existsSync3(templatesDir)) {
|
|
1813
|
+
const availableTemplates = readdirSync3(templatesDir, {
|
|
882
1814
|
withFileTypes: true
|
|
883
1815
|
}).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name).sort();
|
|
884
1816
|
console.log(`Available templates: ${availableTemplates.join(", ")}`);
|
|
@@ -905,14 +1837,14 @@ async function copyTemplate(projectPath, template, versions, isDevelopment = fal
|
|
|
905
1837
|
);
|
|
906
1838
|
}
|
|
907
1839
|
function copyDirectoryWithProcessing(src, dest, versions, isDevelopment, useCanary = false) {
|
|
908
|
-
const entries =
|
|
1840
|
+
const entries = readdirSync3(src, { withFileTypes: true });
|
|
909
1841
|
for (const entry of entries) {
|
|
910
1842
|
if (entry.name === ".git") {
|
|
911
1843
|
continue;
|
|
912
1844
|
}
|
|
913
|
-
const srcPath =
|
|
1845
|
+
const srcPath = join3(src, entry.name);
|
|
914
1846
|
const destName = entry.name === "gitignore" ? ".gitignore" : entry.name;
|
|
915
|
-
const destPath =
|
|
1847
|
+
const destPath = join3(dest, destName);
|
|
916
1848
|
if (entry.isDirectory()) {
|
|
917
1849
|
mkdirSync(destPath, { recursive: true });
|
|
918
1850
|
copyDirectoryWithProcessing(
|
|
@@ -922,187 +1854,394 @@ function copyDirectoryWithProcessing(src, dest, versions, isDevelopment, useCana
|
|
|
922
1854
|
isDevelopment,
|
|
923
1855
|
useCanary
|
|
924
1856
|
);
|
|
1857
|
+
} else if (entry.name === "package.json" || entry.name.endsWith(".json")) {
|
|
1858
|
+
const processedContent = processTemplateFile(
|
|
1859
|
+
srcPath,
|
|
1860
|
+
versions,
|
|
1861
|
+
isDevelopment,
|
|
1862
|
+
useCanary
|
|
1863
|
+
);
|
|
1864
|
+
writeFileSync2(destPath, processedContent);
|
|
925
1865
|
} else {
|
|
926
|
-
|
|
927
|
-
const processedContent = processTemplateFile(
|
|
928
|
-
srcPath,
|
|
929
|
-
versions,
|
|
930
|
-
isDevelopment,
|
|
931
|
-
useCanary
|
|
932
|
-
);
|
|
933
|
-
writeFileSync2(destPath, processedContent);
|
|
934
|
-
} else {
|
|
935
|
-
copyFileSync(srcPath, destPath);
|
|
936
|
-
}
|
|
1866
|
+
copyFileSync(srcPath, destPath);
|
|
937
1867
|
}
|
|
938
1868
|
}
|
|
939
1869
|
}
|
|
940
|
-
function
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
}
|
|
955
|
-
async function promptForInstall(packageManager) {
|
|
956
|
-
return new Promise((resolve2) => {
|
|
957
|
-
const { unmount } = render(
|
|
958
|
-
/* @__PURE__ */ React.createElement(
|
|
959
|
-
InstallPrompt,
|
|
960
|
-
{
|
|
961
|
-
packageManager,
|
|
962
|
-
onSubmit: (install) => {
|
|
963
|
-
unmount();
|
|
964
|
-
resolve2(install);
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
)
|
|
968
|
-
);
|
|
969
|
-
});
|
|
970
|
-
}
|
|
971
|
-
function SkillsPresetPrompt({
|
|
972
|
-
onSubmit
|
|
973
|
-
}) {
|
|
974
|
-
const [value, setValue] = useState("");
|
|
975
|
-
const handleSubmit = (val) => {
|
|
976
|
-
const trimmed = val.trim().toLowerCase();
|
|
977
|
-
if (trimmed === "" || trimmed === "y" || trimmed === "yes") {
|
|
978
|
-
onSubmit(true);
|
|
979
|
-
} else if (trimmed === "n" || trimmed === "no") {
|
|
980
|
-
onSubmit(false);
|
|
1870
|
+
function getTemplateItems() {
|
|
1871
|
+
const templatesDir = join3(__dirname, "templates");
|
|
1872
|
+
const availableTemplates = getAvailableTemplates();
|
|
1873
|
+
return availableTemplates.map((template) => {
|
|
1874
|
+
const packageJsonPath = join3(templatesDir, template, "package.json");
|
|
1875
|
+
let description = "MCP server template";
|
|
1876
|
+
if (existsSync3(packageJsonPath)) {
|
|
1877
|
+
try {
|
|
1878
|
+
const templatePackageJson = JSON.parse(
|
|
1879
|
+
readFileSync2(packageJsonPath, "utf-8")
|
|
1880
|
+
);
|
|
1881
|
+
description = templatePackageJson.description || description;
|
|
1882
|
+
} catch {
|
|
1883
|
+
}
|
|
981
1884
|
}
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
return new Promise((resolve2) => {
|
|
987
|
-
const { unmount } = render(
|
|
988
|
-
/* @__PURE__ */ React.createElement(
|
|
989
|
-
SkillsPresetPrompt,
|
|
990
|
-
{
|
|
991
|
-
onSubmit: (presets) => {
|
|
992
|
-
unmount();
|
|
993
|
-
resolve2(presets);
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
)
|
|
997
|
-
);
|
|
1885
|
+
return {
|
|
1886
|
+
label: `${template} - ${description}`,
|
|
1887
|
+
value: template
|
|
1888
|
+
};
|
|
998
1889
|
});
|
|
999
1890
|
}
|
|
1000
|
-
function
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
if (unsafeEntries.length > 0) {
|
|
1012
|
-
const list = unsafeEntries.map((entry) => ` \u2022 ${entry}`).join("\n");
|
|
1013
|
-
setError(
|
|
1014
|
-
`Cannot initialize here \u2014 these entries would clash with the template:
|
|
1891
|
+
async function promptForProjectName() {
|
|
1892
|
+
return promptText("What is your project name?", {
|
|
1893
|
+
validate: (value) => {
|
|
1894
|
+
if (!value) {
|
|
1895
|
+
return "Project name is required";
|
|
1896
|
+
}
|
|
1897
|
+
if (value === ".") {
|
|
1898
|
+
const unsafeEntries = findUnsafeEntries(process.cwd());
|
|
1899
|
+
if (unsafeEntries.length > 0) {
|
|
1900
|
+
const list = unsafeEntries.map((entry) => ` \u2022 ${entry}`).join("\n");
|
|
1901
|
+
return `Cannot initialize here \u2014 these entries would clash with the template:
|
|
1015
1902
|
${list}
|
|
1016
1903
|
|
|
1017
|
-
Remove these files, or pick a project name to scaffold into a subdirectory
|
|
1018
|
-
|
|
1019
|
-
return;
|
|
1904
|
+
Remove these files, or pick a project name to scaffold into a subdirectory.`;
|
|
1905
|
+
}
|
|
1906
|
+
return void 0;
|
|
1020
1907
|
}
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
setError(
|
|
1024
|
-
"Project name can only contain letters, numbers, hyphens, and underscores"
|
|
1025
|
-
);
|
|
1026
|
-
return;
|
|
1908
|
+
if (!/^[a-zA-Z0-9-_]+$/.test(value)) {
|
|
1909
|
+
return "Project name can only contain letters, numbers, hyphens, and underscores";
|
|
1027
1910
|
}
|
|
1028
|
-
if (
|
|
1029
|
-
|
|
1030
|
-
`Directory "${trimmed}" already exists! Please choose a different name.`
|
|
1031
|
-
);
|
|
1032
|
-
return;
|
|
1911
|
+
if (existsSync3(join3(process.cwd(), value))) {
|
|
1912
|
+
return `Directory "${value}" already exists! Please choose a different name.`;
|
|
1033
1913
|
}
|
|
1914
|
+
return void 0;
|
|
1034
1915
|
}
|
|
1035
|
-
|
|
1036
|
-
};
|
|
1037
|
-
return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column" }, /* @__PURE__ */ React.createElement(Box, { marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { bold: true }, "What is your project name?")), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, "\u276F "), /* @__PURE__ */ React.createElement(TextInput, { value, onChange: setValue, onSubmit: handleSubmit })), error && /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "red" }, "\u2716 ", error)));
|
|
1916
|
+
});
|
|
1038
1917
|
}
|
|
1039
|
-
async function
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
{
|
|
1045
|
-
onSubmit: (name) => {
|
|
1046
|
-
unmount();
|
|
1047
|
-
resolve2(name);
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
)
|
|
1918
|
+
async function promptForTemplate() {
|
|
1919
|
+
const items = getTemplateItems();
|
|
1920
|
+
if (items.length === 0) {
|
|
1921
|
+
console.error(
|
|
1922
|
+
red(`\u274C No templates found in: ${join3(__dirname, "templates")}`)
|
|
1051
1923
|
);
|
|
1052
|
-
|
|
1924
|
+
process.exit(1);
|
|
1925
|
+
}
|
|
1926
|
+
const defaultIndex = Math.max(
|
|
1927
|
+
0,
|
|
1928
|
+
items.findIndex((item) => item.value === "mcp-apps")
|
|
1929
|
+
);
|
|
1930
|
+
return promptSelect("Select a template:", items, defaultIndex);
|
|
1053
1931
|
}
|
|
1054
|
-
function
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1932
|
+
function printHelp() {
|
|
1933
|
+
console.log(`Usage: create-mcp-use-app [project-name] [options]
|
|
1934
|
+
|
|
1935
|
+
Create a new MCP server project.
|
|
1936
|
+
|
|
1937
|
+
Arguments:
|
|
1938
|
+
project-name Name of the MCP server project
|
|
1939
|
+
|
|
1940
|
+
Options:
|
|
1941
|
+
-t, --template <template> Template to use or GitHub repo URL
|
|
1942
|
+
--list-templates List all available templates
|
|
1943
|
+
--install Install dependencies after creating project
|
|
1944
|
+
--no-install Skip installing dependencies
|
|
1945
|
+
--skills Install skills for all agents
|
|
1946
|
+
--no-skills Skip installing skills
|
|
1947
|
+
--no-git Skip initializing a git repository
|
|
1948
|
+
--dev Use workspace dependencies for development
|
|
1949
|
+
--canary Use canary versions of packages
|
|
1950
|
+
--yarn Use yarn as package manager
|
|
1951
|
+
--npm Use npm as package manager
|
|
1952
|
+
--pnpm Use pnpm as package manager
|
|
1953
|
+
-h, --help Display help
|
|
1954
|
+
-V, --version Display version`);
|
|
1955
|
+
}
|
|
1956
|
+
async function main() {
|
|
1957
|
+
const argv = process.argv.slice(2);
|
|
1958
|
+
const { projectName: initialProjectName, options } = parseCli(argv);
|
|
1959
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
1960
|
+
printHelp();
|
|
1961
|
+
return;
|
|
1064
1962
|
}
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1963
|
+
if (argv.includes("--version") || argv.includes("-V")) {
|
|
1964
|
+
console.log(packageJson.version);
|
|
1965
|
+
return;
|
|
1966
|
+
}
|
|
1967
|
+
if (options.listTemplates) {
|
|
1968
|
+
listTemplates();
|
|
1969
|
+
return;
|
|
1970
|
+
}
|
|
1971
|
+
if (options.dev && options.canary) {
|
|
1972
|
+
console.error(red("\u274C Cannot use --dev and --canary together"));
|
|
1973
|
+
console.error(yellow(" Please choose only one dependency mode"));
|
|
1974
|
+
process.exit(1);
|
|
1975
|
+
}
|
|
1976
|
+
let projectName = initialProjectName;
|
|
1977
|
+
let selectedTemplate = options.template;
|
|
1978
|
+
const interactive = isInteractive();
|
|
1979
|
+
console.log("");
|
|
1980
|
+
renderLogo();
|
|
1981
|
+
console.log("");
|
|
1982
|
+
if (!projectName) {
|
|
1983
|
+
if (!interactive) {
|
|
1984
|
+
console.error(
|
|
1985
|
+
red("\u274C Project name is required in non-interactive mode")
|
|
1986
|
+
);
|
|
1987
|
+
process.exit(1);
|
|
1988
|
+
}
|
|
1989
|
+
projectName = await promptForProjectName();
|
|
1990
|
+
console.log("");
|
|
1991
|
+
}
|
|
1992
|
+
if (!selectedTemplate) {
|
|
1993
|
+
if (interactive) {
|
|
1994
|
+
selectedTemplate = await promptForTemplate();
|
|
1995
|
+
} else {
|
|
1996
|
+
selectedTemplate = "starter";
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
const trimmedProjectName = projectName.trim();
|
|
2000
|
+
if (!trimmedProjectName) {
|
|
2001
|
+
console.error(red("\u274C Project name cannot be empty"));
|
|
2002
|
+
process.exit(1);
|
|
2003
|
+
}
|
|
2004
|
+
const { useCurrentDir, projectPath, displayName, packageName } = deriveProjectInfo(trimmedProjectName, process.cwd());
|
|
2005
|
+
if (useCurrentDir) {
|
|
2006
|
+
const unsafeEntries = findUnsafeEntries(projectPath);
|
|
2007
|
+
if (unsafeEntries.length > 0) {
|
|
2008
|
+
console.error(
|
|
2009
|
+
red(
|
|
2010
|
+
"\u274C Cannot initialize here \u2014 these entries would clash with the template:"
|
|
2011
|
+
)
|
|
2012
|
+
);
|
|
2013
|
+
for (const entry of unsafeEntries) {
|
|
2014
|
+
console.error(red(` \u2022 ${entry}`));
|
|
2015
|
+
}
|
|
2016
|
+
console.error("");
|
|
2017
|
+
console.error(
|
|
2018
|
+
yellow(
|
|
2019
|
+
" Remove these files, or pass a project name to scaffold into a new subdirectory instead."
|
|
2020
|
+
)
|
|
2021
|
+
);
|
|
2022
|
+
process.exit(1);
|
|
2023
|
+
}
|
|
2024
|
+
} else {
|
|
2025
|
+
if (trimmedProjectName.includes("..") || trimmedProjectName.includes("/") || trimmedProjectName.includes("\\")) {
|
|
2026
|
+
console.error(
|
|
2027
|
+
red('\u274C Project name cannot contain path separators or ".."')
|
|
2028
|
+
);
|
|
2029
|
+
console.error(yellow(' Use simple names like "my-mcp-server"'));
|
|
2030
|
+
process.exit(1);
|
|
2031
|
+
}
|
|
2032
|
+
const protectedNames = [
|
|
2033
|
+
"node_modules",
|
|
2034
|
+
".git",
|
|
2035
|
+
".env",
|
|
2036
|
+
"package.json",
|
|
2037
|
+
"src",
|
|
2038
|
+
"dist"
|
|
2039
|
+
];
|
|
2040
|
+
if (protectedNames.includes(trimmedProjectName.toLowerCase())) {
|
|
2041
|
+
console.error(
|
|
2042
|
+
red(`\u274C Cannot use protected name "${trimmedProjectName}"`)
|
|
2043
|
+
);
|
|
2044
|
+
console.error(yellow(" Please choose a different project name"));
|
|
2045
|
+
process.exit(1);
|
|
2046
|
+
}
|
|
2047
|
+
if (existsSync3(projectPath)) {
|
|
2048
|
+
console.error(
|
|
2049
|
+
red(`\u274C Directory "${trimmedProjectName}" already exists!`)
|
|
2050
|
+
);
|
|
2051
|
+
console.error(
|
|
2052
|
+
yellow(
|
|
2053
|
+
" Please choose a different name or remove the existing directory"
|
|
2054
|
+
)
|
|
2055
|
+
);
|
|
2056
|
+
process.exit(1);
|
|
2057
|
+
}
|
|
2058
|
+
mkdirSync(projectPath, { recursive: true });
|
|
2059
|
+
}
|
|
2060
|
+
console.log(cyan(`\u{1F680} Creating MCP server "${displayName}"...`));
|
|
2061
|
+
const validatedTemplate = validateTemplateName(selectedTemplate);
|
|
2062
|
+
const versions = getCurrentPackageVersions(options.dev, options.canary);
|
|
2063
|
+
await copyTemplate(
|
|
2064
|
+
projectPath,
|
|
2065
|
+
validatedTemplate,
|
|
2066
|
+
versions,
|
|
2067
|
+
options.dev,
|
|
2068
|
+
options.canary
|
|
2069
|
+
);
|
|
2070
|
+
updatePackageJson(projectPath, packageName);
|
|
2071
|
+
updateIndexTs(projectPath, packageName);
|
|
2072
|
+
let install = options.install;
|
|
2073
|
+
let skills = options.skills;
|
|
2074
|
+
if (options.template !== void 0) {
|
|
2075
|
+
if (install === void 0) {
|
|
2076
|
+
install = false;
|
|
2077
|
+
}
|
|
2078
|
+
if (skills === void 0) {
|
|
2079
|
+
skills = true;
|
|
2080
|
+
}
|
|
2081
|
+
} else if (!interactive) {
|
|
2082
|
+
if (install === void 0) {
|
|
2083
|
+
install = false;
|
|
2084
|
+
}
|
|
2085
|
+
if (skills === void 0) {
|
|
2086
|
+
skills = false;
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
console.log("");
|
|
2090
|
+
const shouldInstallSkills = skills !== void 0 ? skills : interactive ? await promptConfirm(
|
|
2091
|
+
"Install AI coding skills for Cursor, Claude Code, and Codex? (Recommended)",
|
|
2092
|
+
true
|
|
2093
|
+
) : false;
|
|
2094
|
+
let skillsInstalled = false;
|
|
2095
|
+
if (shouldInstallSkills) {
|
|
2096
|
+
console.log("");
|
|
2097
|
+
const s = spinner2();
|
|
2098
|
+
s.start("Installing skills...");
|
|
2099
|
+
if (!isGitAvailable()) {
|
|
2100
|
+
s.stop("Skills install skipped");
|
|
2101
|
+
warnSkillsInstallFailed(true);
|
|
2102
|
+
} else {
|
|
1069
2103
|
try {
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
2104
|
+
await installSkills(projectPath);
|
|
2105
|
+
skillsInstalled = true;
|
|
2106
|
+
s.stop("Skills installed successfully!");
|
|
2107
|
+
} catch {
|
|
2108
|
+
s.stop("Skills install failed");
|
|
2109
|
+
warnSkillsInstallFailed(false);
|
|
1073
2110
|
}
|
|
1074
2111
|
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
})
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
onSelect: (item) => onSelect(item.value),
|
|
1088
|
-
indicatorComponent: ({ isSelected }) => /* @__PURE__ */ React.createElement(Text, { color: "cyan" }, isSelected ? "\u276F " : " "),
|
|
1089
|
-
itemComponent: ({ isSelected, label }) => /* @__PURE__ */ React.createElement(Text, { color: isSelected ? "cyan" : void 0 }, label)
|
|
2112
|
+
}
|
|
2113
|
+
let usedPackageManager = "npm";
|
|
2114
|
+
if (options.yarn) {
|
|
2115
|
+
usedPackageManager = "yarn";
|
|
2116
|
+
} else if (options.npm) {
|
|
2117
|
+
usedPackageManager = "npm";
|
|
2118
|
+
} else if (options.pnpm) {
|
|
2119
|
+
usedPackageManager = "pnpm";
|
|
2120
|
+
} else {
|
|
2121
|
+
const detected = detectPackageManager();
|
|
2122
|
+
if (detected) {
|
|
2123
|
+
usedPackageManager = detected;
|
|
1090
2124
|
}
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
2125
|
+
}
|
|
2126
|
+
console.log("");
|
|
2127
|
+
const shouldInstall = install !== void 0 ? install : interactive ? await promptConfirm(
|
|
2128
|
+
`Install dependencies with ${usedPackageManager}?`,
|
|
2129
|
+
true
|
|
2130
|
+
) : false;
|
|
2131
|
+
if (shouldInstall) {
|
|
2132
|
+
console.log("");
|
|
2133
|
+
console.log(cyan("\u{1F4E6} Installing dependencies..."));
|
|
2134
|
+
console.log("");
|
|
2135
|
+
const isKnownManager = options.yarn || options.npm || options.pnpm || detectPackageManager();
|
|
2136
|
+
const managersToTry = isKnownManager ? [usedPackageManager] : ["npm", "pnpm", "yarn"];
|
|
2137
|
+
let installed = false;
|
|
2138
|
+
for (const pm of managersToTry) {
|
|
2139
|
+
const s = spinner2();
|
|
2140
|
+
s.start(`Installing packages with ${pm}...`);
|
|
2141
|
+
try {
|
|
2142
|
+
await runPackageManager(pm, getInstallArgs(pm), projectPath);
|
|
2143
|
+
usedPackageManager = pm;
|
|
2144
|
+
s.stop(`Packages installed successfully with ${pm}`);
|
|
2145
|
+
installed = true;
|
|
2146
|
+
break;
|
|
2147
|
+
} catch (err) {
|
|
2148
|
+
const remaining = managersToTry.slice(managersToTry.indexOf(pm) + 1);
|
|
2149
|
+
if (remaining.length > 0) {
|
|
2150
|
+
s.stop(`${pm} not available, trying ${remaining[0]}...`);
|
|
2151
|
+
} else {
|
|
2152
|
+
s.error("Package installation failed");
|
|
2153
|
+
if (err instanceof Error) {
|
|
2154
|
+
console.error(red(err.message));
|
|
1102
2155
|
}
|
|
1103
2156
|
}
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
if (!installed) {
|
|
2160
|
+
console.log(
|
|
2161
|
+
'\u26A0\uFE0F Please run "npm install", "yarn install", or "pnpm install" manually'
|
|
2162
|
+
);
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
console.log("");
|
|
2166
|
+
console.log(green("\u2705 MCP server created successfully!"));
|
|
2167
|
+
if (options.dev) {
|
|
2168
|
+
console.log(
|
|
2169
|
+
yellow("\u{1F527} Development mode: Using workspace dependencies")
|
|
2170
|
+
);
|
|
2171
|
+
} else if (options.canary) {
|
|
2172
|
+
console.log(cyan("\u{1F680} Canary mode: Using canary versions of packages"));
|
|
2173
|
+
}
|
|
2174
|
+
console.log("");
|
|
2175
|
+
console.log(bold("\u{1F4C1} Project structure:"));
|
|
2176
|
+
console.log(` ${useCurrentDir ? "." : displayName}/`);
|
|
2177
|
+
if (skillsInstalled) {
|
|
2178
|
+
console.log(" \u251C\u2500\u2500 .agent/skills/");
|
|
2179
|
+
console.log(" \u251C\u2500\u2500 .claude/skills/");
|
|
2180
|
+
console.log(" \u251C\u2500\u2500 .cursor/skills/");
|
|
2181
|
+
}
|
|
2182
|
+
if (validatedTemplate === "blank") {
|
|
2183
|
+
console.log(" \u251C\u2500\u2500 public/");
|
|
2184
|
+
console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
|
|
2185
|
+
console.log(" \u251C\u2500\u2500 package.json");
|
|
2186
|
+
console.log(" \u251C\u2500\u2500 tsconfig.json");
|
|
2187
|
+
console.log(" \u2514\u2500\u2500 README.md");
|
|
2188
|
+
} else if (validatedTemplate === "mcp-apps") {
|
|
2189
|
+
console.log(" \u251C\u2500\u2500 resources/");
|
|
2190
|
+
console.log(" \u2502 \u2514\u2500\u2500 product-search-result/");
|
|
2191
|
+
console.log(" \u2502 \u2514\u2500\u2500 view.tsx");
|
|
2192
|
+
console.log(" \u251C\u2500\u2500 tools.d.ts");
|
|
2193
|
+
console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
|
|
2194
|
+
console.log(" \u251C\u2500\u2500 package.json");
|
|
2195
|
+
console.log(" \u251C\u2500\u2500 tsconfig.json");
|
|
2196
|
+
console.log(" \u2514\u2500\u2500 README.md");
|
|
2197
|
+
} else if (validatedTemplate === "starter") {
|
|
2198
|
+
console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
|
|
2199
|
+
console.log(" \u251C\u2500\u2500 package.json");
|
|
2200
|
+
console.log(" \u251C\u2500\u2500 tsconfig.json");
|
|
2201
|
+
console.log(" \u2514\u2500\u2500 README.md");
|
|
2202
|
+
} else {
|
|
2203
|
+
console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
|
|
2204
|
+
console.log(" \u251C\u2500\u2500 package.json");
|
|
2205
|
+
console.log(" \u251C\u2500\u2500 tsconfig.json");
|
|
2206
|
+
console.log(" \u2514\u2500\u2500 README.md");
|
|
2207
|
+
}
|
|
2208
|
+
console.log("");
|
|
2209
|
+
console.log(bold("\u{1F680} To get started:"));
|
|
2210
|
+
if (!useCurrentDir) {
|
|
2211
|
+
console.log(cyan(` cd ${displayName}`));
|
|
2212
|
+
}
|
|
2213
|
+
if (!shouldInstall) {
|
|
2214
|
+
console.log(cyan(` ${getInstallCommand(usedPackageManager)}`));
|
|
2215
|
+
}
|
|
2216
|
+
console.log(cyan(` ${getDevCommand(usedPackageManager)}`));
|
|
2217
|
+
console.log("");
|
|
2218
|
+
console.log(bold("\u{1F4E4} To deploy:"));
|
|
2219
|
+
console.log(
|
|
2220
|
+
cyan(
|
|
2221
|
+
` ${usedPackageManager === "yarn" ? "yarn" : usedPackageManager === "pnpm" ? "pnpm" : "npm run"} deploy`
|
|
2222
|
+
)
|
|
2223
|
+
);
|
|
2224
|
+
console.log("");
|
|
2225
|
+
if (options.dev) {
|
|
2226
|
+
console.log(
|
|
2227
|
+
yellow(
|
|
2228
|
+
"\u{1F4A1} Development mode: Your project uses workspace dependencies"
|
|
1104
2229
|
)
|
|
1105
2230
|
);
|
|
1106
|
-
|
|
2231
|
+
console.log(
|
|
2232
|
+
yellow(
|
|
2233
|
+
" Make sure you're in the mcp-use workspace root for development"
|
|
2234
|
+
)
|
|
2235
|
+
);
|
|
2236
|
+
console.log("");
|
|
2237
|
+
}
|
|
2238
|
+
console.log(cyan("\u{1F4DA} Learn more: https://manufact.com/docs"));
|
|
2239
|
+
console.log(gray("\u{1F4AC} For feedback and bug reporting visit:"));
|
|
2240
|
+
console.log(
|
|
2241
|
+
gray(" https://github.com/mcp-use/mcp-use or https://manufact.com")
|
|
2242
|
+
);
|
|
1107
2243
|
}
|
|
1108
|
-
|
|
2244
|
+
main().catch((error) => {
|
|
2245
|
+
console.error("\u274C Error creating MCP server:", error);
|
|
2246
|
+
process.exit(1);
|
|
2247
|
+
});
|