towns-bot 0.0.266
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/LICENSE.txt +21 -0
- package/README.md +61 -0
- package/dist/index.js +493 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +466 -0
- package/dist/index.mjs.map +1 -0
- package/index.js +2 -0
- package/package.json +53 -0
package/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 River Association
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# towns-bot
|
|
2
|
+
|
|
3
|
+
CLI for creating and managing Towns Protocol bot projects.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
### Create a new bot project
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx towns-bot init my-bot
|
|
11
|
+
# or
|
|
12
|
+
bunx towns-bot init my-bot
|
|
13
|
+
# or
|
|
14
|
+
yarn dlx towns-bot init my-bot
|
|
15
|
+
# or
|
|
16
|
+
pnpm dlx towns-bot init my-bot
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
This will create a new bot project with the default quickstart template.
|
|
20
|
+
|
|
21
|
+
### Available templates
|
|
22
|
+
|
|
23
|
+
Any template from the [examples](https://github.com/towns-protocol/towns/tree/main/packages/examples) directory can be used.
|
|
24
|
+
|
|
25
|
+
Here's a few examples:
|
|
26
|
+
|
|
27
|
+
- `quickstart` (default) - Simple starter bot with basic commands
|
|
28
|
+
- `thread-ai` - AI-powered conversational bot using OpenAI
|
|
29
|
+
- `poll` - Interactive poll bot for creating votes
|
|
30
|
+
|
|
31
|
+
To use a specific template:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx towns-bot init my-ai-bot --template thread-ai
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Update dependencies
|
|
38
|
+
|
|
39
|
+
Update all `@towns-protocol/*` dependencies to their latest versions:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npx towns-bot update
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
This command should be run from within a Towns Protocol bot project directory.
|
|
46
|
+
|
|
47
|
+
## Commands
|
|
48
|
+
|
|
49
|
+
### `towns-bot init [project-name]`
|
|
50
|
+
|
|
51
|
+
Create a new bot project.
|
|
52
|
+
|
|
53
|
+
Options:
|
|
54
|
+
|
|
55
|
+
- `-t, --template <name>` - Template to use (quickstart, thread-ai, poll)
|
|
56
|
+
|
|
57
|
+
### `towns-bot update`
|
|
58
|
+
|
|
59
|
+
Update `@towns-protocol/*` dependencies to latest versions.
|
|
60
|
+
|
|
61
|
+
### `towns-bot help`
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
"use strict";
|
|
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 __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
25
|
+
|
|
26
|
+
// src/index.ts
|
|
27
|
+
var src_exports = {};
|
|
28
|
+
module.exports = __toCommonJS(src_exports);
|
|
29
|
+
var import_minimist = __toESM(require("minimist"));
|
|
30
|
+
var import_picocolors4 = require("picocolors");
|
|
31
|
+
|
|
32
|
+
// src/modules/init.ts
|
|
33
|
+
var fs2 = __toESM(require("fs"));
|
|
34
|
+
var path2 = __toESM(require("path"));
|
|
35
|
+
var import_prompts = __toESM(require("prompts"));
|
|
36
|
+
var import_picocolors2 = require("picocolors");
|
|
37
|
+
var jsonc = __toESM(require("jsonc-parser"));
|
|
38
|
+
|
|
39
|
+
// src/modules/utils.ts
|
|
40
|
+
var fs = __toESM(require("fs"));
|
|
41
|
+
var path = __toESM(require("path"));
|
|
42
|
+
var import_cross_spawn = __toESM(require("cross-spawn"));
|
|
43
|
+
var import_picocolors = __toESM(require("picocolors"));
|
|
44
|
+
var getPackageManager = () => {
|
|
45
|
+
if (process.env.npm_config_user_agent) {
|
|
46
|
+
const agent = process.env.npm_config_user_agent;
|
|
47
|
+
if (agent.startsWith("yarn")) return "yarn";
|
|
48
|
+
if (agent.startsWith("npm")) return "npm";
|
|
49
|
+
if (agent.startsWith("pnpm")) return "pnpm";
|
|
50
|
+
if (agent.startsWith("bun")) return "bun";
|
|
51
|
+
}
|
|
52
|
+
return "npm";
|
|
53
|
+
};
|
|
54
|
+
function getInstallCommand(packageManager) {
|
|
55
|
+
switch (packageManager) {
|
|
56
|
+
case "bun":
|
|
57
|
+
return "bun install";
|
|
58
|
+
case "yarn":
|
|
59
|
+
return "yarn";
|
|
60
|
+
case "pnpm":
|
|
61
|
+
return "pnpm install";
|
|
62
|
+
default:
|
|
63
|
+
return "npm install";
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function getRunCommand(packageManager, script) {
|
|
67
|
+
switch (packageManager) {
|
|
68
|
+
case "bun":
|
|
69
|
+
return `bun run ${script}`;
|
|
70
|
+
case "yarn":
|
|
71
|
+
return `yarn ${script}`;
|
|
72
|
+
case "pnpm":
|
|
73
|
+
return `pnpm ${script}`;
|
|
74
|
+
default:
|
|
75
|
+
return `npm run ${script}`;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function runCommand(command, args, cwd) {
|
|
79
|
+
return new Promise((resolve2, reject) => {
|
|
80
|
+
const child = (0, import_cross_spawn.default)(command, args, {
|
|
81
|
+
stdio: "inherit",
|
|
82
|
+
cwd,
|
|
83
|
+
shell: process.platform === "win32"
|
|
84
|
+
});
|
|
85
|
+
child.on("close", (code) => {
|
|
86
|
+
if (code !== 0) {
|
|
87
|
+
reject(new Error(`Command failed with exit code ${code}`));
|
|
88
|
+
} else {
|
|
89
|
+
resolve2();
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
child.on("error", reject);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
async function getLatestTownsProtocolVersion() {
|
|
96
|
+
return new Promise((resolve2, reject) => {
|
|
97
|
+
const child = (0, import_cross_spawn.default)("npm", ["view", "@towns-protocol/bot", "version"], {
|
|
98
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
99
|
+
});
|
|
100
|
+
let output = "";
|
|
101
|
+
child.stdout?.on("data", (data) => {
|
|
102
|
+
output += data.toString();
|
|
103
|
+
});
|
|
104
|
+
child.on("close", (code) => {
|
|
105
|
+
if (code !== 0) {
|
|
106
|
+
reject(new Error("Failed to fetch latest @towns-protocol/bot version"));
|
|
107
|
+
} else {
|
|
108
|
+
resolve2(output.trim());
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
child.on("error", reject);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
function getLatestSdkTag() {
|
|
115
|
+
const tagsResult = import_cross_spawn.default.sync(
|
|
116
|
+
"git",
|
|
117
|
+
["ls-remote", "--tags", "https://github.com/towns-protocol/towns.git", "sdk-*"],
|
|
118
|
+
{ encoding: "utf8" }
|
|
119
|
+
);
|
|
120
|
+
if (tagsResult.status !== 0 || !tagsResult.stdout) return null;
|
|
121
|
+
const tags = tagsResult.stdout.split("\n").filter(Boolean).map((line) => {
|
|
122
|
+
const [_hash, ref] = line.split(" ");
|
|
123
|
+
const tag = ref.replace("refs/tags/", "").replace(/\^{}$/, "");
|
|
124
|
+
const match = tag.match(/^sdk-[0-9a-f]+-(\d+)\.(\d+)\.(\d+)$/);
|
|
125
|
+
if (!match) return null;
|
|
126
|
+
return {
|
|
127
|
+
tag,
|
|
128
|
+
version: [parseInt(match[1]), parseInt(match[2]), parseInt(match[3])]
|
|
129
|
+
};
|
|
130
|
+
}).filter(
|
|
131
|
+
(item) => item !== null && Array.isArray(item.version) && item.version.length === 3
|
|
132
|
+
).sort((a, b) => {
|
|
133
|
+
for (let i = 0; i < 3; i++) {
|
|
134
|
+
if (a.version[i] !== b.version[i]) {
|
|
135
|
+
return b.version[i] - a.version[i];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return 0;
|
|
139
|
+
});
|
|
140
|
+
return tags.length > 0 ? tags[0].tag : null;
|
|
141
|
+
}
|
|
142
|
+
async function cloneTemplate(packagePath, targetDir) {
|
|
143
|
+
console.log(import_picocolors.default.blue("Cloning template from GitHub..."));
|
|
144
|
+
const tempDir = `${targetDir}-temp`;
|
|
145
|
+
const fullTemplatePath = `packages/examples/${packagePath}`;
|
|
146
|
+
const latestSdkTag = getLatestSdkTag();
|
|
147
|
+
if (!latestSdkTag) {
|
|
148
|
+
console.error(import_picocolors.default.red("Failed to get latest SDK tag."));
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
const cloneResult = import_cross_spawn.default.sync(
|
|
152
|
+
"git",
|
|
153
|
+
[
|
|
154
|
+
"clone",
|
|
155
|
+
"--no-checkout",
|
|
156
|
+
"--depth",
|
|
157
|
+
"1",
|
|
158
|
+
"--sparse",
|
|
159
|
+
"--branch",
|
|
160
|
+
latestSdkTag,
|
|
161
|
+
"https://github.com/towns-protocol/towns.git",
|
|
162
|
+
tempDir
|
|
163
|
+
],
|
|
164
|
+
{ stdio: "pipe" }
|
|
165
|
+
);
|
|
166
|
+
if (cloneResult.status !== 0) return false;
|
|
167
|
+
const sparseResult = import_cross_spawn.default.sync("git", ["sparse-checkout", "set", fullTemplatePath], {
|
|
168
|
+
stdio: "pipe",
|
|
169
|
+
cwd: tempDir
|
|
170
|
+
});
|
|
171
|
+
if (sparseResult.status !== 0) {
|
|
172
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
const checkoutResult = import_cross_spawn.default.sync("git", ["checkout"], {
|
|
176
|
+
stdio: "pipe",
|
|
177
|
+
cwd: tempDir
|
|
178
|
+
});
|
|
179
|
+
if (checkoutResult.status !== 0) {
|
|
180
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
const sourceDir = path.join(tempDir, fullTemplatePath);
|
|
184
|
+
if (!fs.existsSync(sourceDir)) {
|
|
185
|
+
console.error(import_picocolors.default.red(`
|
|
186
|
+
Template directory not found at ${sourceDir}`));
|
|
187
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
191
|
+
fs.cpSync(sourceDir, targetDir, {
|
|
192
|
+
recursive: true,
|
|
193
|
+
filter: () => {
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
198
|
+
console.log(import_picocolors.default.green("\u2713"), "Template cloned successfully!");
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
function applyReplacements(targetDir, replacements) {
|
|
202
|
+
function processDirectory(dir) {
|
|
203
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
204
|
+
for (const entry of entries) {
|
|
205
|
+
const fullPath = path.join(dir, entry.name);
|
|
206
|
+
if (entry.isDirectory()) {
|
|
207
|
+
if (entry.name === "node_modules" || entry.name === "dist") {
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
processDirectory(fullPath);
|
|
211
|
+
} else {
|
|
212
|
+
let content = fs.readFileSync(fullPath, "utf-8");
|
|
213
|
+
let modified = false;
|
|
214
|
+
if (entry.name === "package.json" || entry.name.endsWith(".ts") || entry.name.endsWith(".js")) {
|
|
215
|
+
for (const [search, replace] of replacements) {
|
|
216
|
+
const regex = new RegExp(search, "g");
|
|
217
|
+
if (regex.test(content)) {
|
|
218
|
+
content = content.replace(regex, replace);
|
|
219
|
+
modified = true;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (modified) {
|
|
223
|
+
fs.writeFileSync(fullPath, content);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
processDirectory(targetDir);
|
|
230
|
+
}
|
|
231
|
+
function printSuccess(projectName, packageManager) {
|
|
232
|
+
console.log(import_picocolors.default.green("\u2713"), "Bot project created successfully!");
|
|
233
|
+
console.log();
|
|
234
|
+
console.log("Next steps:");
|
|
235
|
+
console.log(import_picocolors.default.cyan(` cd ${projectName}`));
|
|
236
|
+
console.log(import_picocolors.default.cyan(` ${getInstallCommand(packageManager)}`));
|
|
237
|
+
console.log("Set up your environment variables:");
|
|
238
|
+
console.log(import_picocolors.default.cyan(" cp .env.sample .env"));
|
|
239
|
+
console.log(" Edit .env with your bot credentials");
|
|
240
|
+
console.log("Start your bot:");
|
|
241
|
+
console.log(import_picocolors.default.cyan(` ${getRunCommand(packageManager, "dev")}`));
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// src/modules/init.ts
|
|
245
|
+
var TEMPLATES = {
|
|
246
|
+
quickstart: {
|
|
247
|
+
name: "Bot Quickstart",
|
|
248
|
+
description: "Simple starter bot with basic commands",
|
|
249
|
+
packagePath: "bot-quickstart"
|
|
250
|
+
},
|
|
251
|
+
"thread-ai": {
|
|
252
|
+
name: "Thread AI Bot",
|
|
253
|
+
description: "AI-powered conversational bot using OpenAI",
|
|
254
|
+
packagePath: "bot-thread-ai"
|
|
255
|
+
},
|
|
256
|
+
poll: {
|
|
257
|
+
name: "Poll Bot",
|
|
258
|
+
description: "Interactive poll bot for creating votes",
|
|
259
|
+
packagePath: "bot-ask-poll"
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
async function init(argv2) {
|
|
263
|
+
const projectName = argv2._[1];
|
|
264
|
+
const template = argv2.template || "quickstart";
|
|
265
|
+
if (!projectName) {
|
|
266
|
+
console.error((0, import_picocolors2.red)("Error: Please provide a project name"));
|
|
267
|
+
console.log((0, import_picocolors2.yellow)("Usage: towns-bot init <project-name>"));
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
if (!TEMPLATES[template]) {
|
|
271
|
+
console.error((0, import_picocolors2.red)(`Error: Unknown template "${template}"`));
|
|
272
|
+
console.log((0, import_picocolors2.yellow)("Available templates:"), Object.keys(TEMPLATES).join(", "));
|
|
273
|
+
process.exit(1);
|
|
274
|
+
}
|
|
275
|
+
const targetDir = path2.resolve(process.cwd(), projectName);
|
|
276
|
+
if (fs2.existsSync(targetDir)) {
|
|
277
|
+
const { overwrite } = await (0, import_prompts.default)({
|
|
278
|
+
type: "confirm",
|
|
279
|
+
name: "overwrite",
|
|
280
|
+
message: `Directory ${projectName} already exists. Overwrite?`,
|
|
281
|
+
initial: false
|
|
282
|
+
});
|
|
283
|
+
if (!overwrite) {
|
|
284
|
+
console.log((0, import_picocolors2.yellow)("Operation cancelled"));
|
|
285
|
+
process.exit(0);
|
|
286
|
+
}
|
|
287
|
+
fs2.rmSync(targetDir, { recursive: true, force: true });
|
|
288
|
+
}
|
|
289
|
+
console.log((0, import_picocolors2.cyan)(`Creating a new Towns Protocol bot in ${targetDir}`));
|
|
290
|
+
if (template !== "quickstart") {
|
|
291
|
+
console.log((0, import_picocolors2.cyan)(`Using template: ${TEMPLATES[template].name}`));
|
|
292
|
+
}
|
|
293
|
+
const packageManager = getPackageManager();
|
|
294
|
+
const selectedTemplate = TEMPLATES[template];
|
|
295
|
+
try {
|
|
296
|
+
const success = await cloneTemplate(selectedTemplate.packagePath, targetDir);
|
|
297
|
+
if (!success) {
|
|
298
|
+
console.error((0, import_picocolors2.red)("Failed to clone template"));
|
|
299
|
+
process.exit(1);
|
|
300
|
+
}
|
|
301
|
+
const latestVersion = await getLatestTownsProtocolVersion();
|
|
302
|
+
const replacements = /* @__PURE__ */ new Map([
|
|
303
|
+
["workspace:\\^", `^${latestVersion}`],
|
|
304
|
+
["workspace:\\*", `^${latestVersion}`]
|
|
305
|
+
]);
|
|
306
|
+
applyReplacements(targetDir, replacements);
|
|
307
|
+
const packageJsonPath = path2.join(targetDir, "package.json");
|
|
308
|
+
if (fs2.existsSync(packageJsonPath)) {
|
|
309
|
+
const content = fs2.readFileSync(packageJsonPath, "utf-8");
|
|
310
|
+
const edits = [
|
|
311
|
+
jsonc.modify(content, ["name"], projectName, {}),
|
|
312
|
+
jsonc.modify(content, ["version"], "0.0.1", {})
|
|
313
|
+
];
|
|
314
|
+
let modifiedContent = jsonc.applyEdits(content, edits.flat());
|
|
315
|
+
const parsed = jsonc.parse(modifiedContent);
|
|
316
|
+
delete parsed.private;
|
|
317
|
+
modifiedContent = JSON.stringify(parsed, null, 2);
|
|
318
|
+
fs2.writeFileSync(packageJsonPath, modifiedContent);
|
|
319
|
+
}
|
|
320
|
+
printSuccess(projectName, packageManager);
|
|
321
|
+
} catch (error) {
|
|
322
|
+
console.error((0, import_picocolors2.red)("Error:"), error instanceof Error ? error.message : error);
|
|
323
|
+
console.error((0, import_picocolors2.red)(`Please delete the directory ${targetDir} and try again.`));
|
|
324
|
+
process.exit(1);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// src/modules/update.ts
|
|
329
|
+
var import_fs = __toESM(require("fs"));
|
|
330
|
+
var import_path = __toESM(require("path"));
|
|
331
|
+
var import_cross_spawn2 = __toESM(require("cross-spawn"));
|
|
332
|
+
var import_picocolors3 = require("picocolors");
|
|
333
|
+
var jsonc2 = __toESM(require("jsonc-parser"));
|
|
334
|
+
async function update(_argv) {
|
|
335
|
+
const packageJsonPath = import_path.default.join(process.cwd(), "package.json");
|
|
336
|
+
if (!import_fs.default.existsSync(packageJsonPath)) {
|
|
337
|
+
console.error((0, import_picocolors3.red)("Error: No package.json found in the current directory"));
|
|
338
|
+
console.log((0, import_picocolors3.yellow)("Please run this command from a Towns Protocol bot project directory"));
|
|
339
|
+
process.exit(1);
|
|
340
|
+
}
|
|
341
|
+
const packageJson = jsonc2.parse(import_fs.default.readFileSync(packageJsonPath, "utf-8"));
|
|
342
|
+
const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
343
|
+
const townsPackages = Object.keys(dependencies).filter(
|
|
344
|
+
(pkg) => pkg.startsWith("@towns-protocol/")
|
|
345
|
+
);
|
|
346
|
+
if (townsPackages.length === 0) {
|
|
347
|
+
console.log((0, import_picocolors3.yellow)("No @towns-protocol packages found in this project"));
|
|
348
|
+
process.exit(0);
|
|
349
|
+
}
|
|
350
|
+
console.log((0, import_picocolors3.cyan)("Found Towns Protocol packages:"));
|
|
351
|
+
townsPackages.forEach((pkg) => {
|
|
352
|
+
console.log(` - ${pkg}@${dependencies[pkg]}`);
|
|
353
|
+
});
|
|
354
|
+
console.log();
|
|
355
|
+
console.log((0, import_picocolors3.cyan)("Fetching latest versions..."));
|
|
356
|
+
const latestVersions = {};
|
|
357
|
+
for (const pkg of townsPackages) {
|
|
358
|
+
try {
|
|
359
|
+
const version = await getLatestVersion(pkg);
|
|
360
|
+
latestVersions[pkg] = version;
|
|
361
|
+
console.log((0, import_picocolors3.green)("\u2713"), `${pkg}: ${version}`);
|
|
362
|
+
} catch {
|
|
363
|
+
console.error((0, import_picocolors3.red)("\u2717"), `Failed to fetch version for ${pkg}`);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
console.log();
|
|
367
|
+
console.log((0, import_picocolors3.cyan)("Updating package.json..."));
|
|
368
|
+
const content = import_fs.default.readFileSync(packageJsonPath, "utf-8");
|
|
369
|
+
const edits = [];
|
|
370
|
+
for (const [pkg, version] of Object.entries(latestVersions)) {
|
|
371
|
+
const currentVersion = dependencies[pkg];
|
|
372
|
+
if (currentVersion !== `^${version}`) {
|
|
373
|
+
if (packageJson.dependencies?.[pkg]) {
|
|
374
|
+
edits.push(...jsonc2.modify(content, ["dependencies", pkg], `^${version}`, {}));
|
|
375
|
+
}
|
|
376
|
+
if (packageJson.devDependencies?.[pkg]) {
|
|
377
|
+
edits.push(...jsonc2.modify(content, ["devDependencies", pkg], `^${version}`, {}));
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
if (edits.length > 0) {
|
|
382
|
+
const modifiedContent = jsonc2.applyEdits(content, edits);
|
|
383
|
+
import_fs.default.writeFileSync(packageJsonPath, modifiedContent);
|
|
384
|
+
console.log((0, import_picocolors3.green)("\u2713"), "Updated package.json");
|
|
385
|
+
const packageManager = getPackageManager();
|
|
386
|
+
console.log();
|
|
387
|
+
console.log((0, import_picocolors3.cyan)(`Installing dependencies with ${packageManager}...`));
|
|
388
|
+
try {
|
|
389
|
+
await runCommand(packageManager, [
|
|
390
|
+
getInstallCommand(packageManager).split(" ")[1] || "install"
|
|
391
|
+
]);
|
|
392
|
+
console.log();
|
|
393
|
+
console.log((0, import_picocolors3.green)("\u2713"), "Dependencies updated successfully!");
|
|
394
|
+
} catch {
|
|
395
|
+
console.error((0, import_picocolors3.red)("Error:"), "Failed to install dependencies");
|
|
396
|
+
console.log(
|
|
397
|
+
(0, import_picocolors3.yellow)("Please run"),
|
|
398
|
+
(0, import_picocolors3.cyan)(getInstallCommand(packageManager)),
|
|
399
|
+
(0, import_picocolors3.yellow)("manually")
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
} else {
|
|
403
|
+
console.log((0, import_picocolors3.green)("\u2713"), "All packages are already up to date!");
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
async function getLatestVersion(packageName) {
|
|
407
|
+
return new Promise((resolve2, reject) => {
|
|
408
|
+
const child = (0, import_cross_spawn2.default)("npm", ["view", packageName, "version"], {
|
|
409
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
410
|
+
});
|
|
411
|
+
let output = "";
|
|
412
|
+
child.stdout?.on("data", (data) => {
|
|
413
|
+
output += data.toString();
|
|
414
|
+
});
|
|
415
|
+
child.on("close", (code) => {
|
|
416
|
+
if (code !== 0) {
|
|
417
|
+
reject(new Error(`Failed to fetch version for ${packageName}`));
|
|
418
|
+
} else {
|
|
419
|
+
resolve2(output.trim());
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
child.on("error", reject);
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// src/index.ts
|
|
427
|
+
var argv = (0, import_minimist.default)(process.argv.slice(2), {
|
|
428
|
+
string: ["template"],
|
|
429
|
+
boolean: ["help"],
|
|
430
|
+
alias: {
|
|
431
|
+
h: "help",
|
|
432
|
+
t: "template"
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
async function main() {
|
|
436
|
+
const command = argv._[0];
|
|
437
|
+
if (argv.help || !command) {
|
|
438
|
+
showHelp();
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
try {
|
|
442
|
+
switch (command) {
|
|
443
|
+
case "init":
|
|
444
|
+
await init(argv);
|
|
445
|
+
break;
|
|
446
|
+
case "update":
|
|
447
|
+
await update(argv);
|
|
448
|
+
break;
|
|
449
|
+
default:
|
|
450
|
+
console.error((0, import_picocolors4.red)(`Unknown command: ${command}`));
|
|
451
|
+
showHelp();
|
|
452
|
+
process.exit(1);
|
|
453
|
+
}
|
|
454
|
+
} catch (error) {
|
|
455
|
+
console.error((0, import_picocolors4.red)("Error:"), error instanceof Error ? error.message : error);
|
|
456
|
+
process.exit(1);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
function showHelp() {
|
|
460
|
+
console.log(`
|
|
461
|
+
${(0, import_picocolors4.cyan)("towns-bot")} - CLI for creating and managing Towns Protocol bot projects
|
|
462
|
+
|
|
463
|
+
${(0, import_picocolors4.yellow)("Usage:")}
|
|
464
|
+
towns-bot <command> [options]
|
|
465
|
+
|
|
466
|
+
${(0, import_picocolors4.yellow)("Commands:")}
|
|
467
|
+
${(0, import_picocolors4.green)("init")} [project-name] Create a new bot project
|
|
468
|
+
${(0, import_picocolors4.green)("update")} Update @towns-protocol dependencies to latest versions
|
|
469
|
+
|
|
470
|
+
${(0, import_picocolors4.yellow)("Options:")}
|
|
471
|
+
-t, --template <name> Template to use:
|
|
472
|
+
${Object.entries(TEMPLATES).map(
|
|
473
|
+
([key, template]) => ` ${key} - ${template.description}`
|
|
474
|
+
).join("\n")}
|
|
475
|
+
Default: quickstart
|
|
476
|
+
-h, --help Show this help message
|
|
477
|
+
|
|
478
|
+
${(0, import_picocolors4.yellow)("Examples:")}
|
|
479
|
+
${(0, import_picocolors4.cyan)("# Create a new bot project with the default template")}
|
|
480
|
+
towns-bot init my-bot
|
|
481
|
+
|
|
482
|
+
${(0, import_picocolors4.cyan)("# Create an AI bot project")}
|
|
483
|
+
towns-bot init my-ai-bot --template thread-ai
|
|
484
|
+
|
|
485
|
+
${(0, import_picocolors4.cyan)("# Update dependencies in current project")}
|
|
486
|
+
towns-bot update
|
|
487
|
+
`);
|
|
488
|
+
}
|
|
489
|
+
main().catch((error) => {
|
|
490
|
+
console.error((0, import_picocolors4.red)("Unexpected error:"), error);
|
|
491
|
+
process.exit(1);
|
|
492
|
+
});
|
|
493
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/modules/init.ts","../src/modules/utils.ts","../src/modules/update.ts"],"sourcesContent":["import minimist from 'minimist'\nimport { green, red, yellow, cyan } from 'picocolors'\nimport { init, TEMPLATES, type Template } from './modules/init.js'\nimport { update } from './modules/update.js'\n\nexport type Argv = typeof argv\n\nconst argv = minimist(process.argv.slice(2), {\n string: ['template'],\n boolean: ['help'],\n alias: {\n h: 'help',\n t: 'template',\n },\n})\n\nasync function main() {\n const command = argv._[0]\n\n if (argv.help || !command) {\n showHelp()\n return\n }\n\n try {\n switch (command) {\n case 'init':\n await init(argv)\n break\n case 'update':\n await update(argv)\n break\n default:\n console.error(red(`Unknown command: ${command}`))\n showHelp()\n process.exit(1)\n }\n } catch (error) {\n console.error(red('Error:'), error instanceof Error ? error.message : error)\n process.exit(1)\n }\n}\n\nfunction showHelp() {\n console.log(`\n${cyan('towns-bot')} - CLI for creating and managing Towns Protocol bot projects\n\n${yellow('Usage:')}\n towns-bot <command> [options]\n\n${yellow('Commands:')}\n ${green('init')} [project-name] Create a new bot project\n ${green('update')} Update @towns-protocol dependencies to latest versions\n\n${yellow('Options:')}\n -t, --template <name> Template to use:\n${Object.entries(TEMPLATES)\n .map(\n ([key, template]: [string, Template]) =>\n ` ${key} - ${template.description}`,\n )\n .join('\\n')}\n Default: quickstart\n -h, --help Show this help message\n\n${yellow('Examples:')}\n ${cyan('# Create a new bot project with the default template')}\n towns-bot init my-bot\n\n ${cyan('# Create an AI bot project')}\n towns-bot init my-ai-bot --template thread-ai\n\n ${cyan('# Update dependencies in current project')}\n towns-bot update\n`)\n}\n\nmain().catch((error) => {\n console.error(red('Unexpected error:'), error)\n process.exit(1)\n})\n","import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { default as prompts } from 'prompts'\nimport { red, yellow, cyan } from 'picocolors'\nimport * as jsonc from 'jsonc-parser'\nimport {\n getPackageManager,\n getLatestTownsProtocolVersion,\n cloneTemplate,\n applyReplacements,\n printSuccess,\n type PackageJson,\n} from './utils.js'\nimport type { Argv } from '../index.js'\n\nexport type Template = (typeof TEMPLATES)[keyof typeof TEMPLATES]\nexport const TEMPLATES = {\n quickstart: {\n name: 'Bot Quickstart',\n description: 'Simple starter bot with basic commands',\n packagePath: 'bot-quickstart',\n },\n 'thread-ai': {\n name: 'Thread AI Bot',\n description: 'AI-powered conversational bot using OpenAI',\n packagePath: 'bot-thread-ai',\n },\n poll: {\n name: 'Poll Bot',\n description: 'Interactive poll bot for creating votes',\n packagePath: 'bot-ask-poll',\n },\n} as const\n\nexport async function init(argv: Argv) {\n const projectName = argv._[1]\n const template = argv.template || 'quickstart'\n\n if (!projectName) {\n console.error(red('Error: Please provide a project name'))\n console.log(yellow('Usage: towns-bot init <project-name>'))\n process.exit(1)\n }\n\n if (!TEMPLATES[template as keyof typeof TEMPLATES]) {\n console.error(red(`Error: Unknown template \"${template}\"`))\n console.log(yellow('Available templates:'), Object.keys(TEMPLATES).join(', '))\n process.exit(1)\n }\n\n const targetDir = path.resolve(process.cwd(), projectName)\n\n if (fs.existsSync(targetDir)) {\n const { overwrite } = await prompts({\n type: 'confirm',\n name: 'overwrite',\n message: `Directory ${projectName} already exists. Overwrite?`,\n initial: false,\n })\n\n if (!overwrite) {\n console.log(yellow('Operation cancelled'))\n process.exit(0)\n }\n\n fs.rmSync(targetDir, { recursive: true, force: true })\n }\n\n console.log(cyan(`Creating a new Towns Protocol bot in ${targetDir}`))\n if (template !== 'quickstart') {\n console.log(cyan(`Using template: ${TEMPLATES[template as keyof typeof TEMPLATES].name}`))\n }\n\n const packageManager = getPackageManager()\n const selectedTemplate = TEMPLATES[template as keyof typeof TEMPLATES]\n\n try {\n // Clone template from GitHub\n const success = await cloneTemplate(selectedTemplate.packagePath, targetDir)\n if (!success) {\n console.error(red('Failed to clone template'))\n process.exit(1)\n }\n const latestVersion = await getLatestTownsProtocolVersion()\n // Replace workspace dependencies in package.json and other files\n const replacements = new Map([\n ['workspace:\\\\^', `^${latestVersion}`],\n ['workspace:\\\\*', `^${latestVersion}`],\n ])\n\n // Apply replacements to all relevant files\n applyReplacements(targetDir, replacements)\n\n const packageJsonPath = path.join(targetDir, 'package.json')\n if (fs.existsSync(packageJsonPath)) {\n const content = fs.readFileSync(packageJsonPath, 'utf-8')\n const edits = [\n jsonc.modify(content, ['name'], projectName, {}),\n jsonc.modify(content, ['version'], '0.0.1', {}),\n ]\n\n let modifiedContent = jsonc.applyEdits(content, edits.flat())\n\n const parsed = jsonc.parse(modifiedContent) as PackageJson\n delete parsed.private\n\n modifiedContent = JSON.stringify(parsed, null, 2)\n fs.writeFileSync(packageJsonPath, modifiedContent)\n }\n\n printSuccess(projectName, packageManager)\n } catch (error) {\n console.error(red('Error:'), error instanceof Error ? error.message : error)\n console.error(red(`Please delete the directory ${targetDir} and try again.`))\n process.exit(1)\n }\n}\n","import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { default as spawn } from 'cross-spawn'\nimport picocolors from 'picocolors'\n\nexport type PackageJson = {\n private?: boolean\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n}\n\nexport const getPackageManager = () => {\n if (process.env.npm_config_user_agent) {\n const agent = process.env.npm_config_user_agent\n if (agent.startsWith('yarn')) return 'yarn'\n if (agent.startsWith('npm')) return 'npm'\n if (agent.startsWith('pnpm')) return 'pnpm'\n if (agent.startsWith('bun')) return 'bun'\n }\n // Default to npm if no user agent is found\n return 'npm'\n}\n\nexport function getInstallCommand(packageManager: string): string {\n switch (packageManager) {\n case 'bun':\n return 'bun install'\n case 'yarn':\n return 'yarn'\n case 'pnpm':\n return 'pnpm install'\n default:\n return 'npm install'\n }\n}\n\nexport function getRunCommand(packageManager: string, script: string): string {\n switch (packageManager) {\n case 'bun':\n return `bun run ${script}`\n case 'yarn':\n return `yarn ${script}`\n case 'pnpm':\n return `pnpm ${script}`\n default:\n return `npm run ${script}`\n }\n}\n\nexport function runCommand(command: string, args: string[], cwd?: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n stdio: 'inherit',\n cwd,\n shell: process.platform === 'win32',\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Command failed with exit code ${code}`))\n } else {\n resolve()\n }\n })\n\n child.on('error', reject)\n })\n}\n\nexport async function getLatestTownsProtocolVersion(): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn('npm', ['view', '@towns-protocol/bot', 'version'], {\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n\n let output = ''\n child.stdout?.on('data', (data) => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n output += data.toString()\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error('Failed to fetch latest @towns-protocol/bot version'))\n } else {\n resolve(output.trim())\n }\n })\n\n child.on('error', reject)\n })\n}\n\nexport function copyDirectory(src: string, dest: string, replacements?: Map<string, string>) {\n if (!fs.existsSync(dest)) {\n fs.mkdirSync(dest, { recursive: true })\n }\n\n const entries = fs.readdirSync(src, { withFileTypes: true })\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name)\n const destPath = path.join(dest, entry.name)\n\n if (entry.isDirectory()) {\n if (entry.name === 'node_modules' || entry.name === 'dist') {\n continue\n }\n copyDirectory(srcPath, destPath, replacements)\n } else {\n let content = fs.readFileSync(srcPath, 'utf-8')\n\n if (\n replacements &&\n (entry.name === 'package.json' ||\n entry.name.endsWith('.ts') ||\n entry.name.endsWith('.js'))\n ) {\n for (const [search, replace] of replacements) {\n content = content.replace(new RegExp(search, 'g'), replace)\n }\n }\n\n fs.writeFileSync(destPath, content)\n }\n }\n}\n\nexport function getLatestSdkTag(): string | null {\n const tagsResult = spawn.sync(\n 'git',\n ['ls-remote', '--tags', 'https://github.com/towns-protocol/towns.git', 'sdk-*'],\n { encoding: 'utf8' },\n )\n\n if (tagsResult.status !== 0 || !tagsResult.stdout) return null\n\n const tags = tagsResult.stdout\n .split('\\n')\n .filter(Boolean)\n .map((line) => {\n const [_hash, ref] = line.split('\\t')\n const tag = ref.replace('refs/tags/', '').replace(/\\^{}$/, '')\n\n // Extract version numbers from tags like sdk-hash-1.2.3\n const match = tag.match(/^sdk-[0-9a-f]+-(\\d+)\\.(\\d+)\\.(\\d+)$/)\n if (!match) return null\n\n return {\n tag,\n version: [parseInt(match[1]), parseInt(match[2]), parseInt(match[3])],\n }\n })\n .filter(\n (item): item is { tag: string; version: number[] } =>\n item !== null && Array.isArray(item.version) && item.version.length === 3,\n )\n .sort((a, b) => {\n // Compare version numbers\n for (let i = 0; i < 3; i++) {\n if (a.version[i] !== b.version[i]) {\n return b.version[i] - a.version[i]\n }\n }\n return 0\n })\n\n return tags.length > 0 ? tags[0].tag : null\n}\n\nexport async function cloneTemplate(packagePath: string, targetDir: string): Promise<boolean> {\n console.log(picocolors.blue('Cloning template from GitHub...'))\n\n const tempDir = `${targetDir}-temp`\n const fullTemplatePath = `packages/examples/${packagePath}`\n\n // Get latest SDK tag\n const latestSdkTag = getLatestSdkTag()\n if (!latestSdkTag) {\n console.error(picocolors.red('Failed to get latest SDK tag.'))\n return false\n }\n\n // Clone with minimal data to a temporary directory\n const cloneResult = spawn.sync(\n 'git',\n [\n 'clone',\n '--no-checkout',\n '--depth',\n '1',\n '--sparse',\n '--branch',\n latestSdkTag,\n 'https://github.com/towns-protocol/towns.git',\n tempDir,\n ],\n { stdio: 'pipe' },\n )\n if (cloneResult.status !== 0) return false\n\n // Set up sparse checkout for the specific template\n const sparseResult = spawn.sync('git', ['sparse-checkout', 'set', fullTemplatePath], {\n stdio: 'pipe',\n cwd: tempDir,\n })\n if (sparseResult.status !== 0) {\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Checkout the content\n const checkoutResult = spawn.sync('git', ['checkout'], {\n stdio: 'pipe',\n cwd: tempDir,\n })\n if (checkoutResult.status !== 0) {\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Verify template directory exists\n const sourceDir = path.join(tempDir, fullTemplatePath)\n if (!fs.existsSync(sourceDir)) {\n console.error(picocolors.red(`\\nTemplate directory not found at ${sourceDir}`))\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Copy template contents to target directory\n fs.mkdirSync(targetDir, { recursive: true })\n // Use filter to ensure all files (including hidden) are copied\n fs.cpSync(sourceDir, targetDir, {\n recursive: true,\n filter: () => {\n // Copy all files, including hidden ones\n return true\n },\n })\n\n // Clean up temporary directory\n fs.rmSync(tempDir, { recursive: true, force: true })\n\n console.log(picocolors.green('✓'), 'Template cloned successfully!')\n return true\n}\n\nexport function applyReplacements(targetDir: string, replacements: Map<string, string>) {\n function processDirectory(dir: string) {\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n\n if (entry.isDirectory()) {\n if (entry.name === 'node_modules' || entry.name === 'dist') {\n continue\n }\n processDirectory(fullPath)\n } else {\n let content = fs.readFileSync(fullPath, 'utf-8')\n let modified = false\n\n if (\n entry.name === 'package.json' ||\n entry.name.endsWith('.ts') ||\n entry.name.endsWith('.js')\n ) {\n for (const [search, replace] of replacements) {\n const regex = new RegExp(search, 'g')\n if (regex.test(content)) {\n content = content.replace(regex, replace)\n modified = true\n }\n }\n\n if (modified) {\n fs.writeFileSync(fullPath, content)\n }\n }\n }\n }\n }\n\n processDirectory(targetDir)\n}\n\nexport function printSuccess(projectName: string, packageManager: string) {\n console.log(picocolors.green('✓'), 'Bot project created successfully!')\n console.log()\n console.log('Next steps:')\n console.log(picocolors.cyan(` cd ${projectName}`))\n console.log(picocolors.cyan(` ${getInstallCommand(packageManager)}`))\n console.log('Set up your environment variables:')\n console.log(picocolors.cyan(' cp .env.sample .env'))\n console.log(' Edit .env with your bot credentials')\n console.log('Start your bot:')\n console.log(picocolors.cyan(` ${getRunCommand(packageManager, 'dev')}`))\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { default as spawn } from 'cross-spawn'\nimport { green, red, yellow, cyan } from 'picocolors'\nimport * as jsonc from 'jsonc-parser'\nimport { getPackageManager, getInstallCommand, runCommand, type PackageJson } from './utils.js'\nimport type { Argv } from '../index.js'\n\ninterface PackageVersions {\n [key: string]: string\n}\n\nexport async function update(_argv: Argv) {\n const packageJsonPath = path.join(process.cwd(), 'package.json')\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(red('Error: No package.json found in the current directory'))\n console.log(yellow('Please run this command from a Towns Protocol bot project directory'))\n process.exit(1)\n }\n\n const packageJson = jsonc.parse(fs.readFileSync(packageJsonPath, 'utf-8')) as PackageJson\n const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies }\n\n const townsPackages = Object.keys(dependencies).filter((pkg) =>\n pkg.startsWith('@towns-protocol/'),\n )\n\n if (townsPackages.length === 0) {\n console.log(yellow('No @towns-protocol packages found in this project'))\n process.exit(0)\n }\n\n console.log(cyan('Found Towns Protocol packages:'))\n townsPackages.forEach((pkg) => {\n console.log(` - ${pkg}@${dependencies[pkg]}`)\n })\n console.log()\n\n console.log(cyan('Fetching latest versions...'))\n const latestVersions: PackageVersions = {}\n\n for (const pkg of townsPackages) {\n try {\n const version = await getLatestVersion(pkg)\n latestVersions[pkg] = version\n console.log(green('✓'), `${pkg}: ${version}`)\n } catch {\n console.error(red('✗'), `Failed to fetch version for ${pkg}`)\n }\n }\n\n console.log()\n console.log(cyan('Updating package.json...'))\n\n const content = fs.readFileSync(packageJsonPath, 'utf-8')\n const edits: jsonc.Edit[] = []\n\n for (const [pkg, version] of Object.entries(latestVersions)) {\n const currentVersion = dependencies[pkg]\n if (currentVersion !== `^${version}`) {\n if (packageJson.dependencies?.[pkg]) {\n edits.push(...jsonc.modify(content, ['dependencies', pkg], `^${version}`, {}))\n }\n if (packageJson.devDependencies?.[pkg]) {\n edits.push(...jsonc.modify(content, ['devDependencies', pkg], `^${version}`, {}))\n }\n }\n }\n\n if (edits.length > 0) {\n const modifiedContent = jsonc.applyEdits(content, edits)\n fs.writeFileSync(packageJsonPath, modifiedContent)\n console.log(green('✓'), 'Updated package.json')\n\n const packageManager = getPackageManager()\n console.log()\n console.log(cyan(`Installing dependencies with ${packageManager}...`))\n\n try {\n await runCommand(packageManager, [\n getInstallCommand(packageManager).split(' ')[1] || 'install',\n ])\n console.log()\n console.log(green('✓'), 'Dependencies updated successfully!')\n } catch {\n console.error(red('Error:'), 'Failed to install dependencies')\n console.log(\n yellow('Please run'),\n cyan(getInstallCommand(packageManager)),\n yellow('manually'),\n )\n }\n } else {\n console.log(green('✓'), 'All packages are already up to date!')\n }\n}\n\nasync function getLatestVersion(packageName: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn('npm', ['view', packageName, 'version'], {\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n\n let output = ''\n child.stdout?.on('data', (data) => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n output += data.toString()\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Failed to fetch version for ${packageName}`))\n } else {\n resolve(output.trim())\n }\n })\n\n child.on('error', reject)\n })\n}\n"],"mappings":"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","names":["import_picocolors","fs","path","import_picocolors","resolve","spawn","spawn","picocolors","argv","prompts","import_cross_spawn","import_picocolors","jsonc","path","fs","resolve","spawn","minimist"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import minimist from "minimist";
|
|
3
|
+
import { green as green2, red as red3, yellow as yellow3, cyan as cyan3 } from "picocolors";
|
|
4
|
+
|
|
5
|
+
// src/modules/init.ts
|
|
6
|
+
import * as fs2 from "node:fs";
|
|
7
|
+
import * as path2 from "node:path";
|
|
8
|
+
import { default as prompts } from "prompts";
|
|
9
|
+
import { red, yellow, cyan } from "picocolors";
|
|
10
|
+
import * as jsonc from "jsonc-parser";
|
|
11
|
+
|
|
12
|
+
// src/modules/utils.ts
|
|
13
|
+
import * as fs from "node:fs";
|
|
14
|
+
import * as path from "node:path";
|
|
15
|
+
import { default as spawn } from "cross-spawn";
|
|
16
|
+
import picocolors from "picocolors";
|
|
17
|
+
var getPackageManager = () => {
|
|
18
|
+
if (process.env.npm_config_user_agent) {
|
|
19
|
+
const agent = process.env.npm_config_user_agent;
|
|
20
|
+
if (agent.startsWith("yarn")) return "yarn";
|
|
21
|
+
if (agent.startsWith("npm")) return "npm";
|
|
22
|
+
if (agent.startsWith("pnpm")) return "pnpm";
|
|
23
|
+
if (agent.startsWith("bun")) return "bun";
|
|
24
|
+
}
|
|
25
|
+
return "npm";
|
|
26
|
+
};
|
|
27
|
+
function getInstallCommand(packageManager) {
|
|
28
|
+
switch (packageManager) {
|
|
29
|
+
case "bun":
|
|
30
|
+
return "bun install";
|
|
31
|
+
case "yarn":
|
|
32
|
+
return "yarn";
|
|
33
|
+
case "pnpm":
|
|
34
|
+
return "pnpm install";
|
|
35
|
+
default:
|
|
36
|
+
return "npm install";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function getRunCommand(packageManager, script) {
|
|
40
|
+
switch (packageManager) {
|
|
41
|
+
case "bun":
|
|
42
|
+
return `bun run ${script}`;
|
|
43
|
+
case "yarn":
|
|
44
|
+
return `yarn ${script}`;
|
|
45
|
+
case "pnpm":
|
|
46
|
+
return `pnpm ${script}`;
|
|
47
|
+
default:
|
|
48
|
+
return `npm run ${script}`;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function runCommand(command, args, cwd) {
|
|
52
|
+
return new Promise((resolve2, reject) => {
|
|
53
|
+
const child = spawn(command, args, {
|
|
54
|
+
stdio: "inherit",
|
|
55
|
+
cwd,
|
|
56
|
+
shell: process.platform === "win32"
|
|
57
|
+
});
|
|
58
|
+
child.on("close", (code) => {
|
|
59
|
+
if (code !== 0) {
|
|
60
|
+
reject(new Error(`Command failed with exit code ${code}`));
|
|
61
|
+
} else {
|
|
62
|
+
resolve2();
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
child.on("error", reject);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
async function getLatestTownsProtocolVersion() {
|
|
69
|
+
return new Promise((resolve2, reject) => {
|
|
70
|
+
const child = spawn("npm", ["view", "@towns-protocol/bot", "version"], {
|
|
71
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
72
|
+
});
|
|
73
|
+
let output = "";
|
|
74
|
+
child.stdout?.on("data", (data) => {
|
|
75
|
+
output += data.toString();
|
|
76
|
+
});
|
|
77
|
+
child.on("close", (code) => {
|
|
78
|
+
if (code !== 0) {
|
|
79
|
+
reject(new Error("Failed to fetch latest @towns-protocol/bot version"));
|
|
80
|
+
} else {
|
|
81
|
+
resolve2(output.trim());
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
child.on("error", reject);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function getLatestSdkTag() {
|
|
88
|
+
const tagsResult = spawn.sync(
|
|
89
|
+
"git",
|
|
90
|
+
["ls-remote", "--tags", "https://github.com/towns-protocol/towns.git", "sdk-*"],
|
|
91
|
+
{ encoding: "utf8" }
|
|
92
|
+
);
|
|
93
|
+
if (tagsResult.status !== 0 || !tagsResult.stdout) return null;
|
|
94
|
+
const tags = tagsResult.stdout.split("\n").filter(Boolean).map((line) => {
|
|
95
|
+
const [_hash, ref] = line.split(" ");
|
|
96
|
+
const tag = ref.replace("refs/tags/", "").replace(/\^{}$/, "");
|
|
97
|
+
const match = tag.match(/^sdk-[0-9a-f]+-(\d+)\.(\d+)\.(\d+)$/);
|
|
98
|
+
if (!match) return null;
|
|
99
|
+
return {
|
|
100
|
+
tag,
|
|
101
|
+
version: [parseInt(match[1]), parseInt(match[2]), parseInt(match[3])]
|
|
102
|
+
};
|
|
103
|
+
}).filter(
|
|
104
|
+
(item) => item !== null && Array.isArray(item.version) && item.version.length === 3
|
|
105
|
+
).sort((a, b) => {
|
|
106
|
+
for (let i = 0; i < 3; i++) {
|
|
107
|
+
if (a.version[i] !== b.version[i]) {
|
|
108
|
+
return b.version[i] - a.version[i];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return 0;
|
|
112
|
+
});
|
|
113
|
+
return tags.length > 0 ? tags[0].tag : null;
|
|
114
|
+
}
|
|
115
|
+
async function cloneTemplate(packagePath, targetDir) {
|
|
116
|
+
console.log(picocolors.blue("Cloning template from GitHub..."));
|
|
117
|
+
const tempDir = `${targetDir}-temp`;
|
|
118
|
+
const fullTemplatePath = `packages/examples/${packagePath}`;
|
|
119
|
+
const latestSdkTag = getLatestSdkTag();
|
|
120
|
+
if (!latestSdkTag) {
|
|
121
|
+
console.error(picocolors.red("Failed to get latest SDK tag."));
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
const cloneResult = spawn.sync(
|
|
125
|
+
"git",
|
|
126
|
+
[
|
|
127
|
+
"clone",
|
|
128
|
+
"--no-checkout",
|
|
129
|
+
"--depth",
|
|
130
|
+
"1",
|
|
131
|
+
"--sparse",
|
|
132
|
+
"--branch",
|
|
133
|
+
latestSdkTag,
|
|
134
|
+
"https://github.com/towns-protocol/towns.git",
|
|
135
|
+
tempDir
|
|
136
|
+
],
|
|
137
|
+
{ stdio: "pipe" }
|
|
138
|
+
);
|
|
139
|
+
if (cloneResult.status !== 0) return false;
|
|
140
|
+
const sparseResult = spawn.sync("git", ["sparse-checkout", "set", fullTemplatePath], {
|
|
141
|
+
stdio: "pipe",
|
|
142
|
+
cwd: tempDir
|
|
143
|
+
});
|
|
144
|
+
if (sparseResult.status !== 0) {
|
|
145
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
const checkoutResult = spawn.sync("git", ["checkout"], {
|
|
149
|
+
stdio: "pipe",
|
|
150
|
+
cwd: tempDir
|
|
151
|
+
});
|
|
152
|
+
if (checkoutResult.status !== 0) {
|
|
153
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
const sourceDir = path.join(tempDir, fullTemplatePath);
|
|
157
|
+
if (!fs.existsSync(sourceDir)) {
|
|
158
|
+
console.error(picocolors.red(`
|
|
159
|
+
Template directory not found at ${sourceDir}`));
|
|
160
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
164
|
+
fs.cpSync(sourceDir, targetDir, {
|
|
165
|
+
recursive: true,
|
|
166
|
+
filter: () => {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
171
|
+
console.log(picocolors.green("\u2713"), "Template cloned successfully!");
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
function applyReplacements(targetDir, replacements) {
|
|
175
|
+
function processDirectory(dir) {
|
|
176
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
177
|
+
for (const entry of entries) {
|
|
178
|
+
const fullPath = path.join(dir, entry.name);
|
|
179
|
+
if (entry.isDirectory()) {
|
|
180
|
+
if (entry.name === "node_modules" || entry.name === "dist") {
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
processDirectory(fullPath);
|
|
184
|
+
} else {
|
|
185
|
+
let content = fs.readFileSync(fullPath, "utf-8");
|
|
186
|
+
let modified = false;
|
|
187
|
+
if (entry.name === "package.json" || entry.name.endsWith(".ts") || entry.name.endsWith(".js")) {
|
|
188
|
+
for (const [search, replace] of replacements) {
|
|
189
|
+
const regex = new RegExp(search, "g");
|
|
190
|
+
if (regex.test(content)) {
|
|
191
|
+
content = content.replace(regex, replace);
|
|
192
|
+
modified = true;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (modified) {
|
|
196
|
+
fs.writeFileSync(fullPath, content);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
processDirectory(targetDir);
|
|
203
|
+
}
|
|
204
|
+
function printSuccess(projectName, packageManager) {
|
|
205
|
+
console.log(picocolors.green("\u2713"), "Bot project created successfully!");
|
|
206
|
+
console.log();
|
|
207
|
+
console.log("Next steps:");
|
|
208
|
+
console.log(picocolors.cyan(` cd ${projectName}`));
|
|
209
|
+
console.log(picocolors.cyan(` ${getInstallCommand(packageManager)}`));
|
|
210
|
+
console.log("Set up your environment variables:");
|
|
211
|
+
console.log(picocolors.cyan(" cp .env.sample .env"));
|
|
212
|
+
console.log(" Edit .env with your bot credentials");
|
|
213
|
+
console.log("Start your bot:");
|
|
214
|
+
console.log(picocolors.cyan(` ${getRunCommand(packageManager, "dev")}`));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// src/modules/init.ts
|
|
218
|
+
var TEMPLATES = {
|
|
219
|
+
quickstart: {
|
|
220
|
+
name: "Bot Quickstart",
|
|
221
|
+
description: "Simple starter bot with basic commands",
|
|
222
|
+
packagePath: "bot-quickstart"
|
|
223
|
+
},
|
|
224
|
+
"thread-ai": {
|
|
225
|
+
name: "Thread AI Bot",
|
|
226
|
+
description: "AI-powered conversational bot using OpenAI",
|
|
227
|
+
packagePath: "bot-thread-ai"
|
|
228
|
+
},
|
|
229
|
+
poll: {
|
|
230
|
+
name: "Poll Bot",
|
|
231
|
+
description: "Interactive poll bot for creating votes",
|
|
232
|
+
packagePath: "bot-ask-poll"
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
async function init(argv2) {
|
|
236
|
+
const projectName = argv2._[1];
|
|
237
|
+
const template = argv2.template || "quickstart";
|
|
238
|
+
if (!projectName) {
|
|
239
|
+
console.error(red("Error: Please provide a project name"));
|
|
240
|
+
console.log(yellow("Usage: towns-bot init <project-name>"));
|
|
241
|
+
process.exit(1);
|
|
242
|
+
}
|
|
243
|
+
if (!TEMPLATES[template]) {
|
|
244
|
+
console.error(red(`Error: Unknown template "${template}"`));
|
|
245
|
+
console.log(yellow("Available templates:"), Object.keys(TEMPLATES).join(", "));
|
|
246
|
+
process.exit(1);
|
|
247
|
+
}
|
|
248
|
+
const targetDir = path2.resolve(process.cwd(), projectName);
|
|
249
|
+
if (fs2.existsSync(targetDir)) {
|
|
250
|
+
const { overwrite } = await prompts({
|
|
251
|
+
type: "confirm",
|
|
252
|
+
name: "overwrite",
|
|
253
|
+
message: `Directory ${projectName} already exists. Overwrite?`,
|
|
254
|
+
initial: false
|
|
255
|
+
});
|
|
256
|
+
if (!overwrite) {
|
|
257
|
+
console.log(yellow("Operation cancelled"));
|
|
258
|
+
process.exit(0);
|
|
259
|
+
}
|
|
260
|
+
fs2.rmSync(targetDir, { recursive: true, force: true });
|
|
261
|
+
}
|
|
262
|
+
console.log(cyan(`Creating a new Towns Protocol bot in ${targetDir}`));
|
|
263
|
+
if (template !== "quickstart") {
|
|
264
|
+
console.log(cyan(`Using template: ${TEMPLATES[template].name}`));
|
|
265
|
+
}
|
|
266
|
+
const packageManager = getPackageManager();
|
|
267
|
+
const selectedTemplate = TEMPLATES[template];
|
|
268
|
+
try {
|
|
269
|
+
const success = await cloneTemplate(selectedTemplate.packagePath, targetDir);
|
|
270
|
+
if (!success) {
|
|
271
|
+
console.error(red("Failed to clone template"));
|
|
272
|
+
process.exit(1);
|
|
273
|
+
}
|
|
274
|
+
const latestVersion = await getLatestTownsProtocolVersion();
|
|
275
|
+
const replacements = /* @__PURE__ */ new Map([
|
|
276
|
+
["workspace:\\^", `^${latestVersion}`],
|
|
277
|
+
["workspace:\\*", `^${latestVersion}`]
|
|
278
|
+
]);
|
|
279
|
+
applyReplacements(targetDir, replacements);
|
|
280
|
+
const packageJsonPath = path2.join(targetDir, "package.json");
|
|
281
|
+
if (fs2.existsSync(packageJsonPath)) {
|
|
282
|
+
const content = fs2.readFileSync(packageJsonPath, "utf-8");
|
|
283
|
+
const edits = [
|
|
284
|
+
jsonc.modify(content, ["name"], projectName, {}),
|
|
285
|
+
jsonc.modify(content, ["version"], "0.0.1", {})
|
|
286
|
+
];
|
|
287
|
+
let modifiedContent = jsonc.applyEdits(content, edits.flat());
|
|
288
|
+
const parsed = jsonc.parse(modifiedContent);
|
|
289
|
+
delete parsed.private;
|
|
290
|
+
modifiedContent = JSON.stringify(parsed, null, 2);
|
|
291
|
+
fs2.writeFileSync(packageJsonPath, modifiedContent);
|
|
292
|
+
}
|
|
293
|
+
printSuccess(projectName, packageManager);
|
|
294
|
+
} catch (error) {
|
|
295
|
+
console.error(red("Error:"), error instanceof Error ? error.message : error);
|
|
296
|
+
console.error(red(`Please delete the directory ${targetDir} and try again.`));
|
|
297
|
+
process.exit(1);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// src/modules/update.ts
|
|
302
|
+
import fs3 from "fs";
|
|
303
|
+
import path3 from "path";
|
|
304
|
+
import { default as spawn2 } from "cross-spawn";
|
|
305
|
+
import { green, red as red2, yellow as yellow2, cyan as cyan2 } from "picocolors";
|
|
306
|
+
import * as jsonc2 from "jsonc-parser";
|
|
307
|
+
async function update(_argv) {
|
|
308
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
309
|
+
if (!fs3.existsSync(packageJsonPath)) {
|
|
310
|
+
console.error(red2("Error: No package.json found in the current directory"));
|
|
311
|
+
console.log(yellow2("Please run this command from a Towns Protocol bot project directory"));
|
|
312
|
+
process.exit(1);
|
|
313
|
+
}
|
|
314
|
+
const packageJson = jsonc2.parse(fs3.readFileSync(packageJsonPath, "utf-8"));
|
|
315
|
+
const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
316
|
+
const townsPackages = Object.keys(dependencies).filter(
|
|
317
|
+
(pkg) => pkg.startsWith("@towns-protocol/")
|
|
318
|
+
);
|
|
319
|
+
if (townsPackages.length === 0) {
|
|
320
|
+
console.log(yellow2("No @towns-protocol packages found in this project"));
|
|
321
|
+
process.exit(0);
|
|
322
|
+
}
|
|
323
|
+
console.log(cyan2("Found Towns Protocol packages:"));
|
|
324
|
+
townsPackages.forEach((pkg) => {
|
|
325
|
+
console.log(` - ${pkg}@${dependencies[pkg]}`);
|
|
326
|
+
});
|
|
327
|
+
console.log();
|
|
328
|
+
console.log(cyan2("Fetching latest versions..."));
|
|
329
|
+
const latestVersions = {};
|
|
330
|
+
for (const pkg of townsPackages) {
|
|
331
|
+
try {
|
|
332
|
+
const version = await getLatestVersion(pkg);
|
|
333
|
+
latestVersions[pkg] = version;
|
|
334
|
+
console.log(green("\u2713"), `${pkg}: ${version}`);
|
|
335
|
+
} catch {
|
|
336
|
+
console.error(red2("\u2717"), `Failed to fetch version for ${pkg}`);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
console.log();
|
|
340
|
+
console.log(cyan2("Updating package.json..."));
|
|
341
|
+
const content = fs3.readFileSync(packageJsonPath, "utf-8");
|
|
342
|
+
const edits = [];
|
|
343
|
+
for (const [pkg, version] of Object.entries(latestVersions)) {
|
|
344
|
+
const currentVersion = dependencies[pkg];
|
|
345
|
+
if (currentVersion !== `^${version}`) {
|
|
346
|
+
if (packageJson.dependencies?.[pkg]) {
|
|
347
|
+
edits.push(...jsonc2.modify(content, ["dependencies", pkg], `^${version}`, {}));
|
|
348
|
+
}
|
|
349
|
+
if (packageJson.devDependencies?.[pkg]) {
|
|
350
|
+
edits.push(...jsonc2.modify(content, ["devDependencies", pkg], `^${version}`, {}));
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
if (edits.length > 0) {
|
|
355
|
+
const modifiedContent = jsonc2.applyEdits(content, edits);
|
|
356
|
+
fs3.writeFileSync(packageJsonPath, modifiedContent);
|
|
357
|
+
console.log(green("\u2713"), "Updated package.json");
|
|
358
|
+
const packageManager = getPackageManager();
|
|
359
|
+
console.log();
|
|
360
|
+
console.log(cyan2(`Installing dependencies with ${packageManager}...`));
|
|
361
|
+
try {
|
|
362
|
+
await runCommand(packageManager, [
|
|
363
|
+
getInstallCommand(packageManager).split(" ")[1] || "install"
|
|
364
|
+
]);
|
|
365
|
+
console.log();
|
|
366
|
+
console.log(green("\u2713"), "Dependencies updated successfully!");
|
|
367
|
+
} catch {
|
|
368
|
+
console.error(red2("Error:"), "Failed to install dependencies");
|
|
369
|
+
console.log(
|
|
370
|
+
yellow2("Please run"),
|
|
371
|
+
cyan2(getInstallCommand(packageManager)),
|
|
372
|
+
yellow2("manually")
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
} else {
|
|
376
|
+
console.log(green("\u2713"), "All packages are already up to date!");
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
async function getLatestVersion(packageName) {
|
|
380
|
+
return new Promise((resolve2, reject) => {
|
|
381
|
+
const child = spawn2("npm", ["view", packageName, "version"], {
|
|
382
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
383
|
+
});
|
|
384
|
+
let output = "";
|
|
385
|
+
child.stdout?.on("data", (data) => {
|
|
386
|
+
output += data.toString();
|
|
387
|
+
});
|
|
388
|
+
child.on("close", (code) => {
|
|
389
|
+
if (code !== 0) {
|
|
390
|
+
reject(new Error(`Failed to fetch version for ${packageName}`));
|
|
391
|
+
} else {
|
|
392
|
+
resolve2(output.trim());
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
child.on("error", reject);
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// src/index.ts
|
|
400
|
+
var argv = minimist(process.argv.slice(2), {
|
|
401
|
+
string: ["template"],
|
|
402
|
+
boolean: ["help"],
|
|
403
|
+
alias: {
|
|
404
|
+
h: "help",
|
|
405
|
+
t: "template"
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
async function main() {
|
|
409
|
+
const command = argv._[0];
|
|
410
|
+
if (argv.help || !command) {
|
|
411
|
+
showHelp();
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
try {
|
|
415
|
+
switch (command) {
|
|
416
|
+
case "init":
|
|
417
|
+
await init(argv);
|
|
418
|
+
break;
|
|
419
|
+
case "update":
|
|
420
|
+
await update(argv);
|
|
421
|
+
break;
|
|
422
|
+
default:
|
|
423
|
+
console.error(red3(`Unknown command: ${command}`));
|
|
424
|
+
showHelp();
|
|
425
|
+
process.exit(1);
|
|
426
|
+
}
|
|
427
|
+
} catch (error) {
|
|
428
|
+
console.error(red3("Error:"), error instanceof Error ? error.message : error);
|
|
429
|
+
process.exit(1);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
function showHelp() {
|
|
433
|
+
console.log(`
|
|
434
|
+
${cyan3("towns-bot")} - CLI for creating and managing Towns Protocol bot projects
|
|
435
|
+
|
|
436
|
+
${yellow3("Usage:")}
|
|
437
|
+
towns-bot <command> [options]
|
|
438
|
+
|
|
439
|
+
${yellow3("Commands:")}
|
|
440
|
+
${green2("init")} [project-name] Create a new bot project
|
|
441
|
+
${green2("update")} Update @towns-protocol dependencies to latest versions
|
|
442
|
+
|
|
443
|
+
${yellow3("Options:")}
|
|
444
|
+
-t, --template <name> Template to use:
|
|
445
|
+
${Object.entries(TEMPLATES).map(
|
|
446
|
+
([key, template]) => ` ${key} - ${template.description}`
|
|
447
|
+
).join("\n")}
|
|
448
|
+
Default: quickstart
|
|
449
|
+
-h, --help Show this help message
|
|
450
|
+
|
|
451
|
+
${yellow3("Examples:")}
|
|
452
|
+
${cyan3("# Create a new bot project with the default template")}
|
|
453
|
+
towns-bot init my-bot
|
|
454
|
+
|
|
455
|
+
${cyan3("# Create an AI bot project")}
|
|
456
|
+
towns-bot init my-ai-bot --template thread-ai
|
|
457
|
+
|
|
458
|
+
${cyan3("# Update dependencies in current project")}
|
|
459
|
+
towns-bot update
|
|
460
|
+
`);
|
|
461
|
+
}
|
|
462
|
+
main().catch((error) => {
|
|
463
|
+
console.error(red3("Unexpected error:"), error);
|
|
464
|
+
process.exit(1);
|
|
465
|
+
});
|
|
466
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/modules/init.ts","../src/modules/utils.ts","../src/modules/update.ts"],"sourcesContent":["import minimist from 'minimist'\nimport { green, red, yellow, cyan } from 'picocolors'\nimport { init, TEMPLATES, type Template } from './modules/init.js'\nimport { update } from './modules/update.js'\n\nexport type Argv = typeof argv\n\nconst argv = minimist(process.argv.slice(2), {\n string: ['template'],\n boolean: ['help'],\n alias: {\n h: 'help',\n t: 'template',\n },\n})\n\nasync function main() {\n const command = argv._[0]\n\n if (argv.help || !command) {\n showHelp()\n return\n }\n\n try {\n switch (command) {\n case 'init':\n await init(argv)\n break\n case 'update':\n await update(argv)\n break\n default:\n console.error(red(`Unknown command: ${command}`))\n showHelp()\n process.exit(1)\n }\n } catch (error) {\n console.error(red('Error:'), error instanceof Error ? error.message : error)\n process.exit(1)\n }\n}\n\nfunction showHelp() {\n console.log(`\n${cyan('towns-bot')} - CLI for creating and managing Towns Protocol bot projects\n\n${yellow('Usage:')}\n towns-bot <command> [options]\n\n${yellow('Commands:')}\n ${green('init')} [project-name] Create a new bot project\n ${green('update')} Update @towns-protocol dependencies to latest versions\n\n${yellow('Options:')}\n -t, --template <name> Template to use:\n${Object.entries(TEMPLATES)\n .map(\n ([key, template]: [string, Template]) =>\n ` ${key} - ${template.description}`,\n )\n .join('\\n')}\n Default: quickstart\n -h, --help Show this help message\n\n${yellow('Examples:')}\n ${cyan('# Create a new bot project with the default template')}\n towns-bot init my-bot\n\n ${cyan('# Create an AI bot project')}\n towns-bot init my-ai-bot --template thread-ai\n\n ${cyan('# Update dependencies in current project')}\n towns-bot update\n`)\n}\n\nmain().catch((error) => {\n console.error(red('Unexpected error:'), error)\n process.exit(1)\n})\n","import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { default as prompts } from 'prompts'\nimport { red, yellow, cyan } from 'picocolors'\nimport * as jsonc from 'jsonc-parser'\nimport {\n getPackageManager,\n getLatestTownsProtocolVersion,\n cloneTemplate,\n applyReplacements,\n printSuccess,\n type PackageJson,\n} from './utils.js'\nimport type { Argv } from '../index.js'\n\nexport type Template = (typeof TEMPLATES)[keyof typeof TEMPLATES]\nexport const TEMPLATES = {\n quickstart: {\n name: 'Bot Quickstart',\n description: 'Simple starter bot with basic commands',\n packagePath: 'bot-quickstart',\n },\n 'thread-ai': {\n name: 'Thread AI Bot',\n description: 'AI-powered conversational bot using OpenAI',\n packagePath: 'bot-thread-ai',\n },\n poll: {\n name: 'Poll Bot',\n description: 'Interactive poll bot for creating votes',\n packagePath: 'bot-ask-poll',\n },\n} as const\n\nexport async function init(argv: Argv) {\n const projectName = argv._[1]\n const template = argv.template || 'quickstart'\n\n if (!projectName) {\n console.error(red('Error: Please provide a project name'))\n console.log(yellow('Usage: towns-bot init <project-name>'))\n process.exit(1)\n }\n\n if (!TEMPLATES[template as keyof typeof TEMPLATES]) {\n console.error(red(`Error: Unknown template \"${template}\"`))\n console.log(yellow('Available templates:'), Object.keys(TEMPLATES).join(', '))\n process.exit(1)\n }\n\n const targetDir = path.resolve(process.cwd(), projectName)\n\n if (fs.existsSync(targetDir)) {\n const { overwrite } = await prompts({\n type: 'confirm',\n name: 'overwrite',\n message: `Directory ${projectName} already exists. Overwrite?`,\n initial: false,\n })\n\n if (!overwrite) {\n console.log(yellow('Operation cancelled'))\n process.exit(0)\n }\n\n fs.rmSync(targetDir, { recursive: true, force: true })\n }\n\n console.log(cyan(`Creating a new Towns Protocol bot in ${targetDir}`))\n if (template !== 'quickstart') {\n console.log(cyan(`Using template: ${TEMPLATES[template as keyof typeof TEMPLATES].name}`))\n }\n\n const packageManager = getPackageManager()\n const selectedTemplate = TEMPLATES[template as keyof typeof TEMPLATES]\n\n try {\n // Clone template from GitHub\n const success = await cloneTemplate(selectedTemplate.packagePath, targetDir)\n if (!success) {\n console.error(red('Failed to clone template'))\n process.exit(1)\n }\n const latestVersion = await getLatestTownsProtocolVersion()\n // Replace workspace dependencies in package.json and other files\n const replacements = new Map([\n ['workspace:\\\\^', `^${latestVersion}`],\n ['workspace:\\\\*', `^${latestVersion}`],\n ])\n\n // Apply replacements to all relevant files\n applyReplacements(targetDir, replacements)\n\n const packageJsonPath = path.join(targetDir, 'package.json')\n if (fs.existsSync(packageJsonPath)) {\n const content = fs.readFileSync(packageJsonPath, 'utf-8')\n const edits = [\n jsonc.modify(content, ['name'], projectName, {}),\n jsonc.modify(content, ['version'], '0.0.1', {}),\n ]\n\n let modifiedContent = jsonc.applyEdits(content, edits.flat())\n\n const parsed = jsonc.parse(modifiedContent) as PackageJson\n delete parsed.private\n\n modifiedContent = JSON.stringify(parsed, null, 2)\n fs.writeFileSync(packageJsonPath, modifiedContent)\n }\n\n printSuccess(projectName, packageManager)\n } catch (error) {\n console.error(red('Error:'), error instanceof Error ? error.message : error)\n console.error(red(`Please delete the directory ${targetDir} and try again.`))\n process.exit(1)\n }\n}\n","import * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { default as spawn } from 'cross-spawn'\nimport picocolors from 'picocolors'\n\nexport type PackageJson = {\n private?: boolean\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n}\n\nexport const getPackageManager = () => {\n if (process.env.npm_config_user_agent) {\n const agent = process.env.npm_config_user_agent\n if (agent.startsWith('yarn')) return 'yarn'\n if (agent.startsWith('npm')) return 'npm'\n if (agent.startsWith('pnpm')) return 'pnpm'\n if (agent.startsWith('bun')) return 'bun'\n }\n // Default to npm if no user agent is found\n return 'npm'\n}\n\nexport function getInstallCommand(packageManager: string): string {\n switch (packageManager) {\n case 'bun':\n return 'bun install'\n case 'yarn':\n return 'yarn'\n case 'pnpm':\n return 'pnpm install'\n default:\n return 'npm install'\n }\n}\n\nexport function getRunCommand(packageManager: string, script: string): string {\n switch (packageManager) {\n case 'bun':\n return `bun run ${script}`\n case 'yarn':\n return `yarn ${script}`\n case 'pnpm':\n return `pnpm ${script}`\n default:\n return `npm run ${script}`\n }\n}\n\nexport function runCommand(command: string, args: string[], cwd?: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n stdio: 'inherit',\n cwd,\n shell: process.platform === 'win32',\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Command failed with exit code ${code}`))\n } else {\n resolve()\n }\n })\n\n child.on('error', reject)\n })\n}\n\nexport async function getLatestTownsProtocolVersion(): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn('npm', ['view', '@towns-protocol/bot', 'version'], {\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n\n let output = ''\n child.stdout?.on('data', (data) => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n output += data.toString()\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error('Failed to fetch latest @towns-protocol/bot version'))\n } else {\n resolve(output.trim())\n }\n })\n\n child.on('error', reject)\n })\n}\n\nexport function copyDirectory(src: string, dest: string, replacements?: Map<string, string>) {\n if (!fs.existsSync(dest)) {\n fs.mkdirSync(dest, { recursive: true })\n }\n\n const entries = fs.readdirSync(src, { withFileTypes: true })\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name)\n const destPath = path.join(dest, entry.name)\n\n if (entry.isDirectory()) {\n if (entry.name === 'node_modules' || entry.name === 'dist') {\n continue\n }\n copyDirectory(srcPath, destPath, replacements)\n } else {\n let content = fs.readFileSync(srcPath, 'utf-8')\n\n if (\n replacements &&\n (entry.name === 'package.json' ||\n entry.name.endsWith('.ts') ||\n entry.name.endsWith('.js'))\n ) {\n for (const [search, replace] of replacements) {\n content = content.replace(new RegExp(search, 'g'), replace)\n }\n }\n\n fs.writeFileSync(destPath, content)\n }\n }\n}\n\nexport function getLatestSdkTag(): string | null {\n const tagsResult = spawn.sync(\n 'git',\n ['ls-remote', '--tags', 'https://github.com/towns-protocol/towns.git', 'sdk-*'],\n { encoding: 'utf8' },\n )\n\n if (tagsResult.status !== 0 || !tagsResult.stdout) return null\n\n const tags = tagsResult.stdout\n .split('\\n')\n .filter(Boolean)\n .map((line) => {\n const [_hash, ref] = line.split('\\t')\n const tag = ref.replace('refs/tags/', '').replace(/\\^{}$/, '')\n\n // Extract version numbers from tags like sdk-hash-1.2.3\n const match = tag.match(/^sdk-[0-9a-f]+-(\\d+)\\.(\\d+)\\.(\\d+)$/)\n if (!match) return null\n\n return {\n tag,\n version: [parseInt(match[1]), parseInt(match[2]), parseInt(match[3])],\n }\n })\n .filter(\n (item): item is { tag: string; version: number[] } =>\n item !== null && Array.isArray(item.version) && item.version.length === 3,\n )\n .sort((a, b) => {\n // Compare version numbers\n for (let i = 0; i < 3; i++) {\n if (a.version[i] !== b.version[i]) {\n return b.version[i] - a.version[i]\n }\n }\n return 0\n })\n\n return tags.length > 0 ? tags[0].tag : null\n}\n\nexport async function cloneTemplate(packagePath: string, targetDir: string): Promise<boolean> {\n console.log(picocolors.blue('Cloning template from GitHub...'))\n\n const tempDir = `${targetDir}-temp`\n const fullTemplatePath = `packages/examples/${packagePath}`\n\n // Get latest SDK tag\n const latestSdkTag = getLatestSdkTag()\n if (!latestSdkTag) {\n console.error(picocolors.red('Failed to get latest SDK tag.'))\n return false\n }\n\n // Clone with minimal data to a temporary directory\n const cloneResult = spawn.sync(\n 'git',\n [\n 'clone',\n '--no-checkout',\n '--depth',\n '1',\n '--sparse',\n '--branch',\n latestSdkTag,\n 'https://github.com/towns-protocol/towns.git',\n tempDir,\n ],\n { stdio: 'pipe' },\n )\n if (cloneResult.status !== 0) return false\n\n // Set up sparse checkout for the specific template\n const sparseResult = spawn.sync('git', ['sparse-checkout', 'set', fullTemplatePath], {\n stdio: 'pipe',\n cwd: tempDir,\n })\n if (sparseResult.status !== 0) {\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Checkout the content\n const checkoutResult = spawn.sync('git', ['checkout'], {\n stdio: 'pipe',\n cwd: tempDir,\n })\n if (checkoutResult.status !== 0) {\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Verify template directory exists\n const sourceDir = path.join(tempDir, fullTemplatePath)\n if (!fs.existsSync(sourceDir)) {\n console.error(picocolors.red(`\\nTemplate directory not found at ${sourceDir}`))\n fs.rmSync(tempDir, { recursive: true, force: true })\n return false\n }\n\n // Copy template contents to target directory\n fs.mkdirSync(targetDir, { recursive: true })\n // Use filter to ensure all files (including hidden) are copied\n fs.cpSync(sourceDir, targetDir, {\n recursive: true,\n filter: () => {\n // Copy all files, including hidden ones\n return true\n },\n })\n\n // Clean up temporary directory\n fs.rmSync(tempDir, { recursive: true, force: true })\n\n console.log(picocolors.green('✓'), 'Template cloned successfully!')\n return true\n}\n\nexport function applyReplacements(targetDir: string, replacements: Map<string, string>) {\n function processDirectory(dir: string) {\n const entries = fs.readdirSync(dir, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name)\n\n if (entry.isDirectory()) {\n if (entry.name === 'node_modules' || entry.name === 'dist') {\n continue\n }\n processDirectory(fullPath)\n } else {\n let content = fs.readFileSync(fullPath, 'utf-8')\n let modified = false\n\n if (\n entry.name === 'package.json' ||\n entry.name.endsWith('.ts') ||\n entry.name.endsWith('.js')\n ) {\n for (const [search, replace] of replacements) {\n const regex = new RegExp(search, 'g')\n if (regex.test(content)) {\n content = content.replace(regex, replace)\n modified = true\n }\n }\n\n if (modified) {\n fs.writeFileSync(fullPath, content)\n }\n }\n }\n }\n }\n\n processDirectory(targetDir)\n}\n\nexport function printSuccess(projectName: string, packageManager: string) {\n console.log(picocolors.green('✓'), 'Bot project created successfully!')\n console.log()\n console.log('Next steps:')\n console.log(picocolors.cyan(` cd ${projectName}`))\n console.log(picocolors.cyan(` ${getInstallCommand(packageManager)}`))\n console.log('Set up your environment variables:')\n console.log(picocolors.cyan(' cp .env.sample .env'))\n console.log(' Edit .env with your bot credentials')\n console.log('Start your bot:')\n console.log(picocolors.cyan(` ${getRunCommand(packageManager, 'dev')}`))\n}\n","import fs from 'fs'\nimport path from 'path'\nimport { default as spawn } from 'cross-spawn'\nimport { green, red, yellow, cyan } from 'picocolors'\nimport * as jsonc from 'jsonc-parser'\nimport { getPackageManager, getInstallCommand, runCommand, type PackageJson } from './utils.js'\nimport type { Argv } from '../index.js'\n\ninterface PackageVersions {\n [key: string]: string\n}\n\nexport async function update(_argv: Argv) {\n const packageJsonPath = path.join(process.cwd(), 'package.json')\n\n if (!fs.existsSync(packageJsonPath)) {\n console.error(red('Error: No package.json found in the current directory'))\n console.log(yellow('Please run this command from a Towns Protocol bot project directory'))\n process.exit(1)\n }\n\n const packageJson = jsonc.parse(fs.readFileSync(packageJsonPath, 'utf-8')) as PackageJson\n const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies }\n\n const townsPackages = Object.keys(dependencies).filter((pkg) =>\n pkg.startsWith('@towns-protocol/'),\n )\n\n if (townsPackages.length === 0) {\n console.log(yellow('No @towns-protocol packages found in this project'))\n process.exit(0)\n }\n\n console.log(cyan('Found Towns Protocol packages:'))\n townsPackages.forEach((pkg) => {\n console.log(` - ${pkg}@${dependencies[pkg]}`)\n })\n console.log()\n\n console.log(cyan('Fetching latest versions...'))\n const latestVersions: PackageVersions = {}\n\n for (const pkg of townsPackages) {\n try {\n const version = await getLatestVersion(pkg)\n latestVersions[pkg] = version\n console.log(green('✓'), `${pkg}: ${version}`)\n } catch {\n console.error(red('✗'), `Failed to fetch version for ${pkg}`)\n }\n }\n\n console.log()\n console.log(cyan('Updating package.json...'))\n\n const content = fs.readFileSync(packageJsonPath, 'utf-8')\n const edits: jsonc.Edit[] = []\n\n for (const [pkg, version] of Object.entries(latestVersions)) {\n const currentVersion = dependencies[pkg]\n if (currentVersion !== `^${version}`) {\n if (packageJson.dependencies?.[pkg]) {\n edits.push(...jsonc.modify(content, ['dependencies', pkg], `^${version}`, {}))\n }\n if (packageJson.devDependencies?.[pkg]) {\n edits.push(...jsonc.modify(content, ['devDependencies', pkg], `^${version}`, {}))\n }\n }\n }\n\n if (edits.length > 0) {\n const modifiedContent = jsonc.applyEdits(content, edits)\n fs.writeFileSync(packageJsonPath, modifiedContent)\n console.log(green('✓'), 'Updated package.json')\n\n const packageManager = getPackageManager()\n console.log()\n console.log(cyan(`Installing dependencies with ${packageManager}...`))\n\n try {\n await runCommand(packageManager, [\n getInstallCommand(packageManager).split(' ')[1] || 'install',\n ])\n console.log()\n console.log(green('✓'), 'Dependencies updated successfully!')\n } catch {\n console.error(red('Error:'), 'Failed to install dependencies')\n console.log(\n yellow('Please run'),\n cyan(getInstallCommand(packageManager)),\n yellow('manually'),\n )\n }\n } else {\n console.log(green('✓'), 'All packages are already up to date!')\n }\n}\n\nasync function getLatestVersion(packageName: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const child = spawn('npm', ['view', packageName, 'version'], {\n stdio: ['ignore', 'pipe', 'ignore'],\n })\n\n let output = ''\n child.stdout?.on('data', (data) => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n output += data.toString()\n })\n\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Failed to fetch version for ${packageName}`))\n } else {\n resolve(output.trim())\n }\n })\n\n child.on('error', reject)\n })\n}\n"],"mappings":"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","names":["green","red","yellow","cyan","fs","path","resolve","argv","fs","path","spawn","red","yellow","cyan","jsonc","path","fs","red","yellow","cyan","resolve","spawn","red","cyan","yellow","green"]}
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "towns-bot",
|
|
3
|
+
"version": "0.0.266",
|
|
4
|
+
"description": "CLI for creating and managing Towns Protocol bot projects",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"towns",
|
|
7
|
+
"protocol",
|
|
8
|
+
"bot",
|
|
9
|
+
"cli",
|
|
10
|
+
"scaffold"
|
|
11
|
+
],
|
|
12
|
+
"author": "Towns Protocol",
|
|
13
|
+
"bin": "index.js",
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": "^18.0.0 || >=20.0.0"
|
|
16
|
+
},
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"index.js",
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"watch": "tsup --watch",
|
|
27
|
+
"dev": "tsx src/index.ts",
|
|
28
|
+
"lint": "eslint src --ext .ts",
|
|
29
|
+
"lint:fix": "eslint src --ext .ts --fix"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/cross-spawn": "^6.0.6",
|
|
33
|
+
"@types/minimist": "^1.2.5",
|
|
34
|
+
"@types/node": "^20.14.8",
|
|
35
|
+
"@types/prompts": "^2.4.9",
|
|
36
|
+
"@typescript-eslint/eslint-plugin": "^8.29.0",
|
|
37
|
+
"@typescript-eslint/parser": "^8.29.0",
|
|
38
|
+
"eslint": "^8.57.1",
|
|
39
|
+
"eslint-import-resolver-typescript": "^4.3.2",
|
|
40
|
+
"eslint-plugin-import-x": "^4.10.2",
|
|
41
|
+
"tsup": "^8.3.5",
|
|
42
|
+
"tsx": "^4.7.1",
|
|
43
|
+
"typescript": "^5.8.2"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"cross-spawn": "^7.0.5",
|
|
47
|
+
"jsonc-parser": "^3.3.1",
|
|
48
|
+
"minimist": "^1.2.8",
|
|
49
|
+
"picocolors": "^1.1.1",
|
|
50
|
+
"prompts": "^2.4.2"
|
|
51
|
+
},
|
|
52
|
+
"gitHead": "8848d4888253d499e4d0f007c03edfa0982b102b"
|
|
53
|
+
}
|