@tgcloud/create-bot 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +24 -0
- package/bin/index.js +120 -0
- package/package.json +28 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Telegram Messenger
|
|
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,24 @@
|
|
|
1
|
+
# @tgcloud/create-bot
|
|
2
|
+
|
|
3
|
+
Scaffold a new project for the Telegram serverless platform:
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npm create @tgcloud/bot example_bot
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
It installs [`@tgcloud/cli`](https://www.npmjs.com/package/@tgcloud/cli) as a local
|
|
10
|
+
dev-dependency, then uses it (`tgcloud init`) to scaffold a starter project and offers
|
|
11
|
+
to link your bot — printing the next steps when it's done.
|
|
12
|
+
|
|
13
|
+
The argument is the target folder — pass `.` to scaffold into the current folder,
|
|
14
|
+
or any path. It works in an existing folder too and never overwrites your files.
|
|
15
|
+
|
|
16
|
+
Requires Node.js 18 or newer.
|
|
17
|
+
|
|
18
|
+
## Documentation
|
|
19
|
+
|
|
20
|
+
Full documentation: https://core.telegram.org/bots/serverless
|
|
21
|
+
|
|
22
|
+
## License
|
|
23
|
+
|
|
24
|
+
MIT
|
package/bin/index.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @tgcloud/create-bot — bootstrap invoked via `npm create @tgcloud/bot <directory>`.
|
|
3
|
+
//
|
|
4
|
+
// A THIN bootstrap: it does only the things that must happen BEFORE @tgcloud/cli
|
|
5
|
+
// exists in the project — create the target directory, write a minimal package.json
|
|
6
|
+
// (only if none exists), and `npm install --save-dev @tgcloud/cli` — then delegates
|
|
7
|
+
// ALL scaffolding to `tgcloud init` (run through the freshly installed local CLI).
|
|
8
|
+
// This keeps a single source of truth for the project layout (init) and makes a
|
|
9
|
+
// create-bot project byte-identical to an `init` one (including .tgcloud/state.json).
|
|
10
|
+
// It mirrors `init`: works in an empty OR existing folder and never overwrites your files.
|
|
11
|
+
//
|
|
12
|
+
// It has no dependency on @tgcloud/cli (runs via npx before anything is installed)
|
|
13
|
+
// and uses node builtins only.
|
|
14
|
+
|
|
15
|
+
import fs from 'node:fs';
|
|
16
|
+
import path from 'node:path';
|
|
17
|
+
import readline from 'node:readline';
|
|
18
|
+
import { execSync } from 'node:child_process';
|
|
19
|
+
import { basename } from 'node:path';
|
|
20
|
+
|
|
21
|
+
function fail(msg) {
|
|
22
|
+
console.error(msg);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function askYesNo(question) {
|
|
27
|
+
return new Promise((resolve) => {
|
|
28
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
29
|
+
rl.question(question, (a) => {
|
|
30
|
+
rl.close();
|
|
31
|
+
resolve(/^y(es)?$/i.test(a.trim()));
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function main() {
|
|
37
|
+
// Parse args positionally: the first non-flag token is the target directory, and
|
|
38
|
+
// --no-git may appear anywhere (npm create passes flags through positionally).
|
|
39
|
+
const args = process.argv.slice(2);
|
|
40
|
+
const noGit = args.includes('--no-git');
|
|
41
|
+
const target = args.find((a) => !a.startsWith('-'));
|
|
42
|
+
|
|
43
|
+
if (!target) {
|
|
44
|
+
fail('Usage: npm create @tgcloud/bot <directory> [--no-git]');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// The argument is a directory path — a bare name (→ ./name), "." (current folder),
|
|
48
|
+
// or a relative/absolute path. The project name is the resolved folder's basename.
|
|
49
|
+
const targetDir = path.resolve(process.cwd(), target);
|
|
50
|
+
const name = basename(targetDir);
|
|
51
|
+
if (!name) {
|
|
52
|
+
fail(`Invalid target directory: ${target}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 1. Create the target directory (if needed) and — only when there is no
|
|
56
|
+
// package.json yet — a MINIMAL, frozen stub. `npm install --save-dev` needs a
|
|
57
|
+
// manifest to write into; `tgcloud init` fills in the evolving shape (type,
|
|
58
|
+
// scripts, version) below. We NEVER overwrite an existing package.json, so
|
|
59
|
+
// create-bot is non-destructive in an existing folder — like `tgcloud init`.
|
|
60
|
+
const dirExisted = fs.existsSync(targetDir);
|
|
61
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
62
|
+
const pkgPath = path.join(targetDir, 'package.json');
|
|
63
|
+
if (!fs.existsSync(pkgPath)) {
|
|
64
|
+
fs.writeFileSync(pkgPath, JSON.stringify({ name, private: true }, null, 2) + '\n');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 2. Install the CLI as a dev-dependency. On failure, remove the directory ONLY if
|
|
68
|
+
// we created it — never delete a folder that was already there (e.g. `create-bot .`
|
|
69
|
+
// in an existing project). A re-run is idempotent either way.
|
|
70
|
+
console.log('Installing @tgcloud/cli...');
|
|
71
|
+
try {
|
|
72
|
+
execSync('npm install --save-dev @tgcloud/cli', { cwd: targetDir, stdio: 'inherit' });
|
|
73
|
+
} catch {
|
|
74
|
+
if (!dirExisted) fs.rmSync(targetDir, { recursive: true, force: true });
|
|
75
|
+
fail('\nFailed to install @tgcloud/cli. Check the error above and try again.');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// 3. Delegate scaffolding to the installed CLI. `npx` run from targetDir resolves
|
|
79
|
+
// the local node_modules/.bin/tgcloud we just installed (NOT the unrelated
|
|
80
|
+
// `tgcloud` npm package — the successful install above guarantees the local
|
|
81
|
+
// bin exists). init owns the whole scaffold; --no-git passes through.
|
|
82
|
+
try {
|
|
83
|
+
execSync('npx tgcloud init' + (noGit ? ' --no-git' : ''), {
|
|
84
|
+
cwd: targetDir,
|
|
85
|
+
stdio: 'inherit',
|
|
86
|
+
// create-bot owns the final "Next steps" — it alone knows the cd target,
|
|
87
|
+
// the npx runner, and whether the user links a bot below. Suppress init's
|
|
88
|
+
// own tail so there aren't two contradictory "Next steps" blocks.
|
|
89
|
+
env: { ...process.env, TGCLOUD_INIT_QUIET_NEXT: '1' },
|
|
90
|
+
});
|
|
91
|
+
} catch {
|
|
92
|
+
fail('\nScaffolding failed. Fix the error above and run "npx tgcloud init" in the project.');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// 4. Optionally link the bot now. Interactive only; delegates to the real
|
|
96
|
+
// `tgcloud login` (no duplicated prompt).
|
|
97
|
+
let loggedIn = false;
|
|
98
|
+
if (process.stdin.isTTY) {
|
|
99
|
+
if (await askYesNo('\nLink your bot now? [y/N] ')) {
|
|
100
|
+
try {
|
|
101
|
+
execSync('npx tgcloud login', { cwd: targetDir, stdio: 'inherit' });
|
|
102
|
+
loggedIn = true;
|
|
103
|
+
} catch {
|
|
104
|
+
console.log('Skipped — run "npx tgcloud login" later.');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 5. The single "Next steps" for the whole bootstrap (init's was suppressed;
|
|
110
|
+
// init still printed "Project ready" + the files note above). Leads with
|
|
111
|
+
// `cd` — the one thing init can't say, since a child process can't change
|
|
112
|
+
// the parent shell's cwd — then npx commands, skipping login if the user
|
|
113
|
+
// just linked. Plain text: create-bot has no chalk.
|
|
114
|
+
console.log('\nNext steps:');
|
|
115
|
+
if (target !== '.') console.log(` cd ${target}`);
|
|
116
|
+
if (!loggedIn) console.log(` ${'npx tgcloud login'.padEnd(17)} # link your bot`);
|
|
117
|
+
console.log(` ${'npx tgcloud push'.padEnd(17)} # deploy to the cloud`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tgcloud/create-bot",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Scaffold a new tgcloud bot project (npm create @tgcloud/bot)",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"telegram",
|
|
7
|
+
"telegram-bot",
|
|
8
|
+
"bot",
|
|
9
|
+
"serverless",
|
|
10
|
+
"tgcloud",
|
|
11
|
+
"scaffold",
|
|
12
|
+
"starter"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"type": "module",
|
|
16
|
+
"bin": {
|
|
17
|
+
"create-bot": "bin/index.js"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"bin"
|
|
21
|
+
],
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=18.0.0"
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
}
|
|
28
|
+
}
|