gramobase 1.0.8 → 1.0.11
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 +18 -1
- package/dist/bin/gramobase.cjs +52 -19
- package/dist/bin/gramobase.cjs.map +1 -1
- package/dist/bin/gramobase.js +51 -20
- package/dist/bin/gramobase.js.map +1 -1
- package/dist/studio/server.cjs +2790 -0
- package/dist/studio/server.cjs.map +1 -0
- package/dist/studio/server.d.cts +5 -0
- package/dist/studio/server.d.ts +5 -0
- package/dist/studio/server.js +2759 -0
- package/dist/studio/server.js.map +1 -0
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
[](https://github.com/besaoct/gramobase/actions)
|
|
5
5
|
[](https://github.com/besaoct/gramobase/blob/main/LICENSE)
|
|
6
6
|
[](https://github.com/besaoct/gramobase/actions)
|
|
7
|
+
[](https://codecov.io/gh/besaoct/gramobase)
|
|
7
8
|
[](https://github.com/besaoct/gramobase/pulls)
|
|
8
9
|
|
|
9
10
|
**Telegram as a free, infinite, production-grade backend database.**
|
|
@@ -307,11 +308,27 @@ npx gramobase migrate # run pending migrations
|
|
|
307
308
|
npx gramobase migrate --rollback 1 # rollback last migration
|
|
308
309
|
npx gramobase migrate --status # show migration history
|
|
309
310
|
npx gramobase generate post --fields "title:string,views:number"
|
|
310
|
-
npx gramobase studio # open browser UI (
|
|
311
|
+
npx gramobase studio # open browser UI (see below)
|
|
312
|
+
npx gramobase studio --port 9000 # custom port
|
|
311
313
|
```
|
|
312
314
|
|
|
313
315
|
---
|
|
314
316
|
|
|
317
|
+
## gramobase Studio
|
|
318
|
+
|
|
319
|
+
`npx gramobase studio` spins up a local browser admin panel at **http://localhost:4242**. Zero extra dependencies — it reads your `.env` and starts a Node HTTP server backed by a real live `GramoBase` client.
|
|
320
|
+
|
|
321
|
+
**Features:**
|
|
322
|
+
- 🔍 **Collection Browser** — Paginated table view of every document in any collection
|
|
323
|
+
- 📋 **Sortable Columns** — Click any column header to sort ASC/DESC
|
|
324
|
+
- 🔎 **Filter Bar** — Filter with `field:value` syntax or free-text regex search
|
|
325
|
+
- 📄 **JSON Inspector** — Click any row to open a full syntax-highlighted document drawer
|
|
326
|
+
- 📡 **Realtime Feed** — Live SSE stream of all insert/update/delete/WAL events
|
|
327
|
+
- ⚡ **Stats Dashboard** — Cache hit rate, bytes used, worker pool status, token count
|
|
328
|
+
- 🤖 **Bot Info Panel** — Bot username, channel ID, token pool capacity
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
315
332
|
## Configuration
|
|
316
333
|
|
|
317
334
|
```ts
|
package/dist/bin/gramobase.cjs
CHANGED
|
@@ -4,18 +4,30 @@
|
|
|
4
4
|
var commander = require('commander');
|
|
5
5
|
var chalk = require('chalk');
|
|
6
6
|
var ora = require('ora');
|
|
7
|
-
var readline = require('readline');
|
|
8
7
|
var fs = require('fs');
|
|
9
8
|
var path = require('path');
|
|
9
|
+
var inquirer = require('inquirer');
|
|
10
10
|
|
|
11
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
11
12
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
13
|
|
|
13
14
|
var chalk__default = /*#__PURE__*/_interopDefault(chalk);
|
|
14
15
|
var ora__default = /*#__PURE__*/_interopDefault(ora);
|
|
16
|
+
var inquirer__default = /*#__PURE__*/_interopDefault(inquirer);
|
|
15
17
|
|
|
16
18
|
// gramobase — Telegram as your free, infinite backend
|
|
17
19
|
|
|
18
|
-
var pkg = { version: "0.
|
|
20
|
+
var pkg = { version: "0.0.0" };
|
|
21
|
+
try {
|
|
22
|
+
const pkgUrl = new URL("../../package.json", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('gramobase.cjs', document.baseURI).href)));
|
|
23
|
+
pkg = JSON.parse(fs.readFileSync(pkgUrl, "utf-8"));
|
|
24
|
+
} catch (e) {
|
|
25
|
+
try {
|
|
26
|
+
const pkgUrl2 = new URL("../package.json", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('gramobase.cjs', document.baseURI).href)));
|
|
27
|
+
pkg = JSON.parse(fs.readFileSync(pkgUrl2, "utf-8"));
|
|
28
|
+
} catch (e2) {
|
|
29
|
+
}
|
|
30
|
+
}
|
|
19
31
|
var program = new commander.Command();
|
|
20
32
|
program.name("gramobase").description(chalk__default.default.cyan("Telegram as your free, infinite backend database")).version(pkg.version);
|
|
21
33
|
program.command("init").description("Initialize a new gramobase project").option("--yes", "Skip prompts, use defaults").action(async (opts) => {
|
|
@@ -24,22 +36,33 @@ program.command("init").description("Initialize a new gramobase project").option
|
|
|
24
36
|
let channelId = "";
|
|
25
37
|
let encryptionKey = "";
|
|
26
38
|
if (!opts.yes) {
|
|
27
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
28
|
-
const ask = (q) => new Promise((res) => rl.question(q, res));
|
|
29
39
|
console.log(chalk__default.default.cyan.bold("\n Step 1: Bot Tokens (Anti-flood rotation)"));
|
|
30
40
|
console.log(chalk__default.default.gray(" You can use multiple bot tokens to increase your rate limit (30 req/s per bot)."));
|
|
31
|
-
const numBotsStr = await
|
|
41
|
+
const { numBotsStr } = await inquirer__default.default.prompt([{
|
|
42
|
+
type: "input",
|
|
43
|
+
name: "numBotsStr",
|
|
44
|
+
message: chalk__default.default.white("How many bot tokens do you want to add? (Default: 1):")
|
|
45
|
+
}]);
|
|
32
46
|
const numBots = Math.max(1, parseInt(numBotsStr, 10) || 1);
|
|
33
47
|
console.log(chalk__default.default.gray(" Create your bots by messaging @BotFather on Telegram and copy the HTTP API tokens."));
|
|
34
48
|
for (let i = 1; i <= numBots; i++) {
|
|
35
|
-
const token = await
|
|
49
|
+
const { token } = await inquirer__default.default.prompt([{
|
|
50
|
+
type: "password",
|
|
51
|
+
name: "token",
|
|
52
|
+
message: chalk__default.default.white(`Bot token ${i}:`),
|
|
53
|
+
mask: chalk__default.default.red("*")
|
|
54
|
+
}]);
|
|
36
55
|
botTokens.push(token.trim());
|
|
37
56
|
}
|
|
38
57
|
console.log(chalk__default.default.cyan.bold("\n Step 2: Channel ID"));
|
|
39
58
|
console.log(chalk__default.default.gray(" You can enter your Channel ID manually (e.g. -100123456789)"));
|
|
40
59
|
console.log(chalk__default.default.gray(" OR leave it blank to auto-detect it."));
|
|
41
|
-
|
|
42
|
-
|
|
60
|
+
const { channelIdInput } = await inquirer__default.default.prompt([{
|
|
61
|
+
type: "input",
|
|
62
|
+
name: "channelIdInput",
|
|
63
|
+
message: chalk__default.default.white("Channel ID (Press Enter to auto-detect):")
|
|
64
|
+
}]);
|
|
65
|
+
channelId = channelIdInput.trim();
|
|
43
66
|
if (!channelId) {
|
|
44
67
|
console.log(chalk__default.default.yellow("\n [Auto-Detect Mode]"));
|
|
45
68
|
console.log(chalk__default.default.gray(` 1. Create a private Telegram channel.`));
|
|
@@ -77,8 +100,12 @@ program.command("init").description("Initialize a new gramobase project").option
|
|
|
77
100
|
}
|
|
78
101
|
}
|
|
79
102
|
console.log(chalk__default.default.cyan.bold("\n Step 3: Security (Optional)"));
|
|
80
|
-
|
|
81
|
-
|
|
103
|
+
const { encryptionKeyInput } = await inquirer__default.default.prompt([{
|
|
104
|
+
type: "input",
|
|
105
|
+
name: "encryptionKeyInput",
|
|
106
|
+
message: chalk__default.default.white("Encryption key (optional, press enter to skip):")
|
|
107
|
+
}]);
|
|
108
|
+
encryptionKey = encryptionKeyInput;
|
|
82
109
|
}
|
|
83
110
|
const spinner = ora__default.default("Setting up gramobase...").start();
|
|
84
111
|
const cwd = process.cwd();
|
|
@@ -127,9 +154,8 @@ export default config;
|
|
|
127
154
|
${chalk__default.default.gray("\u2514\u2500")} gramobase/migrations/
|
|
128
155
|
|
|
129
156
|
${chalk__default.default.bold("Next steps:")}
|
|
130
|
-
${chalk__default.default.cyan("1.")}
|
|
131
|
-
${chalk__default.default.cyan("2.")}
|
|
132
|
-
${chalk__default.default.cyan("3.")} Import and use: ${chalk__default.default.gray("import { createClient } from 'gramobase'")}
|
|
157
|
+
${chalk__default.default.cyan("1.")} Run ${chalk__default.default.bold("npx gramobase migrate")} to initialize the database
|
|
158
|
+
${chalk__default.default.cyan("2.")} Import and use: ${chalk__default.default.gray("import { createClient } from 'gramobase'")}
|
|
133
159
|
`);
|
|
134
160
|
});
|
|
135
161
|
program.command("migrate").description("Run pending migrations").option("--rollback <steps>", "Rollback N migration steps", "0").option("--status", "Show migration status").action(async (opts) => {
|
|
@@ -202,18 +228,25 @@ export type ${capitalize(safeName)} = z.infer<typeof ${safeName}Schema>;
|
|
|
202
228
|
${chalk__default.default.green("\u2713")} Generated ${chalk__default.default.cyan(`gramobase/${safeName}.schema.ts`)}
|
|
203
229
|
`);
|
|
204
230
|
});
|
|
205
|
-
program.command("studio").description("Open the gramobase browser studio UI").option("--port <port>", "Port to listen on", "4242").action((opts) => {
|
|
231
|
+
program.command("studio").description("Open the gramobase browser studio UI").option("--port <port>", "Port to listen on", "4242").action(async (opts) => {
|
|
206
232
|
const port = parseInt(opts.port, 10);
|
|
207
233
|
if (isNaN(port) || port < 1 || port > 65535) {
|
|
208
234
|
console.error(chalk__default.default.red(" Error: Invalid port number"));
|
|
209
235
|
process.exit(1);
|
|
210
236
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
237
|
+
const spinner = ora__default.default("Starting gramobase studio...").start();
|
|
238
|
+
try {
|
|
239
|
+
const { startStudio } = await import(new URL("../../dist/studio/server.js", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('gramobase.cjs', document.baseURI).href))).href);
|
|
240
|
+
await startStudio(port, process.cwd());
|
|
241
|
+
spinner.succeed(chalk__default.default.green("gramobase studio is running!"));
|
|
242
|
+
console.log(`
|
|
243
|
+
${chalk__default.default.bold("Studio")} ${chalk__default.default.cyan(`http://localhost:${port}`)}
|
|
244
|
+
${chalk__default.default.gray("Press Ctrl+C to stop.")}
|
|
215
245
|
`);
|
|
216
|
-
|
|
246
|
+
} catch (e) {
|
|
247
|
+
spinner.fail(chalk__default.default.red("Failed to start studio: " + (e?.message || String(e))));
|
|
248
|
+
process.exit(1);
|
|
249
|
+
}
|
|
217
250
|
});
|
|
218
251
|
function capitalize(s) {
|
|
219
252
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../bin/gramobase.ts"],"names":["Command","chalk","createInterface","spinner","ora","join","writeFileSync","existsSync","mkdirSync"],"mappings":"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","file":"gramobase.cjs","sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { createInterface } from 'readline';\nimport { writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join } from 'path';\n\nconst pkg = { version: '0.1.0' };\n\nconst program = new Command();\n\nprogram\n .name('gramobase')\n .description(chalk.cyan('Telegram as your free, infinite backend database'))\n .version(pkg.version);\n\n// ─── gramobase init ──────────────────────────────────────────────────────────\n\nprogram\n .command('init')\n .description('Initialize a new gramobase project')\n .option('--yes', 'Skip prompts, use defaults')\n .action(async (opts) => {\n console.log('\\n' + chalk.bold.cyan(' gramobase') + chalk.gray(' — Telegram backend\\n'));\n\n let botTokens: string[] = [];\n let channelId = '';\n let encryptionKey = '';\n\n if (!opts.yes) {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const ask = (q: string) => new Promise<string>((res) => rl.question(q, res));\n\n console.log(chalk.cyan.bold('\\n Step 1: Bot Tokens (Anti-flood rotation)'));\n console.log(chalk.gray(' You can use multiple bot tokens to increase your rate limit (30 req/s per bot).'));\n const numBotsStr = await ask(chalk.white(' How many bot tokens do you want to add? (Default: 1): '));\n const numBots = Math.max(1, parseInt(numBotsStr, 10) || 1);\n\n console.log(chalk.gray(' Create your bots by messaging @BotFather on Telegram and copy the HTTP API tokens.'));\n for (let i = 1; i <= numBots; i++) {\n const token = await ask(chalk.white(` Bot token ${i}: `));\n botTokens.push(token.trim());\n }\n\n console.log(chalk.cyan.bold('\\n Step 2: Channel ID'));\n console.log(chalk.gray(' You can enter your Channel ID manually (e.g. -100123456789)'));\n console.log(chalk.gray(' OR leave it blank to auto-detect it.'));\n channelId = await ask(chalk.white(' Channel ID (Press Enter to auto-detect): '));\n\n channelId = channelId.trim();\n\n if (!channelId) {\n console.log(chalk.yellow('\\n [Auto-Detect Mode]'));\n console.log(chalk.gray(` 1. Create a private Telegram channel.`));\n console.log(chalk.gray(` 2. Add your bot as an Administrator with full permissions.`));\n console.log(chalk.gray(` 3. Send any message in the channel (e.g. \"hello\").\\n`));\n \n const spinner = ora('Waiting for a message in your channel...').start();\n \n let detected = false;\n let offset = 0;\n // Use the first token to poll\n const pollToken = botTokens[0] || '';\n \n while (!detected) {\n try {\n const res = await fetch(`https://api.telegram.org/bot${pollToken}/getUpdates?offset=${offset}&timeout=2`);\n const json: any = await res.json();\n \n if (json.ok && json.result.length > 0) {\n for (const update of json.result) {\n offset = update.update_id + 1;\n if (update.channel_post && update.channel_post.chat) {\n channelId = update.channel_post.chat.id.toString();\n const title = update.channel_post.chat.title || 'Unknown Channel';\n spinner.succeed(chalk.green(`Found channel: ${title} (${channelId})`));\n detected = true;\n break;\n }\n }\n } else if (!json.ok) {\n spinner.fail(chalk.red('Invalid Bot Token or Telegram API error.'));\n process.exit(1);\n }\n } catch (e) {\n // Ignore fetch errors and continue polling\n }\n \n if (!detected) {\n await new Promise((resolve) => setTimeout(resolve, 2000));\n }\n }\n }\n\n console.log(chalk.cyan.bold('\\n Step 3: Security (Optional)'));\n encryptionKey = await ask(chalk.white(' Encryption key (optional, press enter to skip): '));\n rl.close();\n }\n\n const spinner = ora('Setting up gramobase...').start();\n\n // Create .env — never write tokens to paths derived from user input\n const cwd = process.cwd();\n const envPath = join(cwd, '.env');\n const envContentLines = [];\n \n if (botTokens.length === 1) {\n envContentLines.push(`GRAMOBASE_BOT_TOKEN=${botTokens[0]}`);\n } else {\n botTokens.forEach((token, i) => {\n envContentLines.push(`GRAMOBASE_BOT_TOKEN_${i + 1}=${token}`);\n });\n }\n \n const safeChannelId = channelId.trim();\n const safeKey = encryptionKey.trim();\n \n envContentLines.push(`GRAMOBASE_CHANNEL_ID=${safeChannelId}`);\n envContentLines.push(safeKey ? `GRAMOBASE_ENCRYPTION_KEY=${safeKey}` : '# GRAMOBASE_ENCRYPTION_KEY=');\n \n const envContent = envContentLines.join('\\n');\n writeFileSync(envPath, envContent + '\\n');\n\n const botTokenConfigStr = botTokens.length === 1\n ? `process.env.GRAMOBASE_BOT_TOKEN!`\n : `[\\n${botTokens.map((_, i) => ` process.env.GRAMOBASE_BOT_TOKEN_${i + 1}!,`).join('\\n')}\\n ]`;\n\n // Create gramobase.config.ts\n const configContent = `import { GramoBaseConfig } from 'gramobase';\n\nconst config: GramoBaseConfig = {\n botToken: ${botTokenConfigStr},\n channelId: process.env.GRAMOBASE_CHANNEL_ID!,\n // encryptionKey: process.env.GRAMOBASE_ENCRYPTION_KEY,\n cacheMaxBytes: 64 * 1024 * 1024, // 64MB hot cache\n cacheTtlMs: 60_000,\n concurrency: 25,\n debug: process.env.NODE_ENV === 'development',\n};\n\nexport default config;\n`;\n\n writeFileSync(join(cwd, 'gramobase.config.ts'), configContent);\n\n // Create migrations folder — path is hardcoded, not from user input\n const migrationsDir = join(cwd, 'gramobase', 'migrations');\n if (!existsSync(migrationsDir)) {\n mkdirSync(migrationsDir, { recursive: true });\n }\n\n spinner.succeed(chalk.green('gramobase initialized!'));\n\n console.log(`\n ${chalk.bold('Files created:')}\n ${chalk.gray('├─')} .env\n ${chalk.gray('└─')} gramobase.config.ts\n ${chalk.gray('└─')} gramobase/migrations/\n\n ${chalk.bold('Next steps:')}\n ${chalk.cyan('1.')} Add your bot token and channel ID to .env\n ${chalk.cyan('2.')} Run ${chalk.bold('gramobase migrate')} to initialize the database\n ${chalk.cyan('3.')} Import and use: ${chalk.gray(\"import { createClient } from 'gramobase'\")}\n`);\n });\n\n// ─── gramobase migrate ───────────────────────────────────────────────────────\n\nprogram\n .command('migrate')\n .description('Run pending migrations')\n .option('--rollback <steps>', 'Rollback N migration steps', '0')\n .option('--status', 'Show migration status')\n .action(async (opts) => {\n const spinner = ora('Loading migrations...').start();\n try {\n const configPath = join(process.cwd(), 'gramobase.config.ts');\n\n spinner.text = 'Connecting...';\n spinner.succeed('Migration runner ready (run in your project after build)');\n } catch (e: any) {\n spinner.fail(chalk.red('Failed: ' + (e instanceof Error ? e.message : 'Unknown error')));\n }\n });\n\n// ─── gramobase status ────────────────────────────────────────────────────────\n\nprogram\n .command('status')\n .description('Show database and connection status')\n .action(async () => {\n const spinner = ora('Checking status...').start();\n try {\n const token = process.env['GRAMOBASE_BOT_TOKEN'];\n const channelId = process.env['GRAMOBASE_CHANNEL_ID'];\n\n if (!token || !channelId) {\n spinner.fail('.env not found — run gramobase init first');\n return;\n }\n\n // Ping Telegram Bot API — token is from env, not user input in this context\n const res = await fetch(`https://api.telegram.org/bot${encodeURIComponent(token)}/getMe`);\n const json = await res.json() as any;\n\n if (json.ok) {\n spinner.succeed(chalk.green('Connected'));\n console.log(`\n ${chalk.bold('Bot:')} ${chalk.cyan('@' + json.result.username)} (${json.result.first_name})\n ${chalk.bold('Channel:')} ${chalk.cyan(channelId)}\n ${chalk.bold('Status:')} ${chalk.green('● Online')}\n`);\n } else {\n spinner.fail(chalk.red('Bot API error — check your token'));\n }\n } catch (e: any) {\n spinner.fail(chalk.red('Connection failed'));\n }\n });\n\n// ─── gramobase generate ──────────────────────────────────────────────────────\n\nprogram\n .command('generate <name>')\n .description('Generate a typed collection schema')\n .option('--fields <fields>', 'Comma-separated fields (e.g. name:string,age:number)')\n .action((name: string, opts) => {\n // Sanitize name — only allow alphanumeric + underscore/hyphen\n const safeName = name.replace(/[^a-zA-Z0-9_-]/g, '');\n if (!safeName || safeName !== name) {\n console.error(chalk.red(' Error: Schema name must contain only letters, numbers, underscores, and hyphens'));\n process.exit(1);\n }\n\n const fields: string[] = opts.fields\n ? (opts.fields as string).split(',').map((f: string) => f.trim())\n : ['name:string'];\n\n const schemaFields = fields.map((f: string) => {\n const [fname, ftype] = f.split(':');\n // Sanitize field name\n const safeFname = (fname ?? 'field').replace(/[^a-zA-Z0-9_]/g, '');\n const zodType =\n ftype === 'number' ? 'z.number()' :\n ftype === 'boolean' ? 'z.boolean()' :\n ftype === 'date' ? 'z.string()' :\n 'z.string()';\n return ` ${safeFname}: ${zodType},`;\n }).join('\\n');\n\n const output = `import { z } from 'zod';\nimport { createClient } from 'gramobase';\n\nexport const ${safeName}Schema = z.object({\n${schemaFields}\n});\n\nexport type ${capitalize(safeName)} = z.infer<typeof ${safeName}Schema>;\n\n// Usage:\n// const db = createClient(config);\n// const ${safeName}s = db.collection('${safeName}s', { schema: ${safeName}Schema });\n// await ${safeName}s.insertOne({ ${fields.map((f: string) => (f.split(':')[0] ?? 'field').replace(/[^a-zA-Z0-9_]/g, '') + ': ...' ).join(', ')} });\n`;\n\n // Path is constructed from sanitized name only — no user-controlled path traversal\n const dir = join(process.cwd(), 'gramobase');\n const outPath = join(dir, `${safeName}.schema.ts`);\n\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(outPath, output);\n\n console.log(`\\n ${chalk.green('✓')} Generated ${chalk.cyan(`gramobase/${safeName}.schema.ts`)}\\n`);\n });\n\n// ─── gramobase studio ────────────────────────────────────────────────────────\n\nprogram\n .command('studio')\n .description('Open the gramobase browser studio UI')\n .option('--port <port>', 'Port to listen on', '4242')\n .action((opts) => {\n // Validate port is numeric and in valid range\n const port = parseInt(opts.port as string, 10);\n if (isNaN(port) || port < 1 || port > 65535) {\n console.error(chalk.red(' Error: Invalid port number'));\n process.exit(1);\n }\n console.log(`\\n ${chalk.bold.cyan('gramobase studio')}\\n`);\n console.log(` ${chalk.gray('Open')} ${chalk.cyan(`http://localhost:${port}`)} ${chalk.gray('in your browser')}\\n`);\n console.log(chalk.yellow(' Studio UI coming in v0.2.0 — contribute at github.com/yourusername/gramobase\\n'));\n });\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\nprogram.parse();\n"]}
|
|
1
|
+
{"version":3,"sources":["../../bin/gramobase.ts"],"names":["readFileSync","Command","chalk","inquirer","spinner","ora","join","writeFileSync","existsSync","mkdirSync"],"mappings":"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","file":"gramobase.cjs","sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { writeFileSync, existsSync, mkdirSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport inquirer from 'inquirer';\n\nlet pkg = { version: '0.0.0' };\ntry {\n const pkgUrl = new URL('../../package.json', import.meta.url);\n pkg = JSON.parse(readFileSync(pkgUrl, 'utf-8'));\n} catch (e) {\n try {\n const pkgUrl2 = new URL('../package.json', import.meta.url);\n pkg = JSON.parse(readFileSync(pkgUrl2, 'utf-8'));\n } catch (e2) {}\n}\n\nconst program = new Command();\n\nprogram\n .name('gramobase')\n .description(chalk.cyan('Telegram as your free, infinite backend database'))\n .version(pkg.version);\n\n// ─── gramobase init ──────────────────────────────────────────────────────────\n\nprogram\n .command('init')\n .description('Initialize a new gramobase project')\n .option('--yes', 'Skip prompts, use defaults')\n .action(async (opts) => {\n console.log('\\n' + chalk.bold.cyan(' gramobase') + chalk.gray(' — Telegram backend\\n'));\n\n let botTokens: string[] = [];\n let channelId = '';\n let encryptionKey = '';\n\n if (!opts.yes) {\n console.log(chalk.cyan.bold('\\n Step 1: Bot Tokens (Anti-flood rotation)'));\n console.log(chalk.gray(' You can use multiple bot tokens to increase your rate limit (30 req/s per bot).'));\n \n const { numBotsStr } = await inquirer.prompt([{\n type: 'input',\n name: 'numBotsStr',\n message: chalk.white('How many bot tokens do you want to add? (Default: 1):')\n }]);\n const numBots = Math.max(1, parseInt(numBotsStr, 10) || 1);\n\n console.log(chalk.gray(' Create your bots by messaging @BotFather on Telegram and copy the HTTP API tokens.'));\n for (let i = 1; i <= numBots; i++) {\n const { token } = await inquirer.prompt([{\n type: 'password',\n name: 'token',\n message: chalk.white(`Bot token ${i}:`),\n mask: chalk.red('*')\n }]);\n botTokens.push(token.trim());\n }\n\n console.log(chalk.cyan.bold('\\n Step 2: Channel ID'));\n console.log(chalk.gray(' You can enter your Channel ID manually (e.g. -100123456789)'));\n console.log(chalk.gray(' OR leave it blank to auto-detect it.'));\n \n const { channelIdInput } = await inquirer.prompt([{\n type: 'input',\n name: 'channelIdInput',\n message: chalk.white('Channel ID (Press Enter to auto-detect):')\n }]);\n \n channelId = channelIdInput.trim();\n\n if (!channelId) {\n console.log(chalk.yellow('\\n [Auto-Detect Mode]'));\n console.log(chalk.gray(` 1. Create a private Telegram channel.`));\n console.log(chalk.gray(` 2. Add your bot as an Administrator with full permissions.`));\n console.log(chalk.gray(` 3. Send any message in the channel (e.g. \"hello\").\\n`));\n \n const spinner = ora('Waiting for a message in your channel...').start();\n \n let detected = false;\n let offset = 0;\n // Use the first token to poll\n const pollToken = botTokens[0] || '';\n \n while (!detected) {\n try {\n const res = await fetch(`https://api.telegram.org/bot${pollToken}/getUpdates?offset=${offset}&timeout=2`);\n const json: any = await res.json();\n \n if (json.ok && json.result.length > 0) {\n for (const update of json.result) {\n offset = update.update_id + 1;\n if (update.channel_post && update.channel_post.chat) {\n channelId = update.channel_post.chat.id.toString();\n const title = update.channel_post.chat.title || 'Unknown Channel';\n spinner.succeed(chalk.green(`Found channel: ${title} (${channelId})`));\n detected = true;\n break;\n }\n }\n } else if (!json.ok) {\n spinner.fail(chalk.red('Invalid Bot Token or Telegram API error.'));\n process.exit(1);\n }\n } catch (e) {\n // Ignore fetch errors and continue polling\n }\n \n if (!detected) {\n await new Promise((resolve) => setTimeout(resolve, 2000));\n }\n }\n }\n\n console.log(chalk.cyan.bold('\\n Step 3: Security (Optional)'));\n const { encryptionKeyInput } = await inquirer.prompt([{\n type: 'input',\n name: 'encryptionKeyInput',\n message: chalk.white('Encryption key (optional, press enter to skip):')\n }]);\n encryptionKey = encryptionKeyInput;\n }\n\n const spinner = ora('Setting up gramobase...').start();\n\n // Create .env — never write tokens to paths derived from user input\n const cwd = process.cwd();\n const envPath = join(cwd, '.env');\n const envContentLines = [];\n \n if (botTokens.length === 1) {\n envContentLines.push(`GRAMOBASE_BOT_TOKEN=${botTokens[0]}`);\n } else {\n botTokens.forEach((token, i) => {\n envContentLines.push(`GRAMOBASE_BOT_TOKEN_${i + 1}=${token}`);\n });\n }\n \n const safeChannelId = channelId.trim();\n const safeKey = encryptionKey.trim();\n \n envContentLines.push(`GRAMOBASE_CHANNEL_ID=${safeChannelId}`);\n envContentLines.push(safeKey ? `GRAMOBASE_ENCRYPTION_KEY=${safeKey}` : '# GRAMOBASE_ENCRYPTION_KEY=');\n \n const envContent = envContentLines.join('\\n');\n writeFileSync(envPath, envContent + '\\n');\n\n const botTokenConfigStr = botTokens.length === 1\n ? `process.env.GRAMOBASE_BOT_TOKEN!`\n : `[\\n${botTokens.map((_, i) => ` process.env.GRAMOBASE_BOT_TOKEN_${i + 1}!,`).join('\\n')}\\n ]`;\n\n // Create gramobase.config.ts\n const configContent = `import { GramoBaseConfig } from 'gramobase';\n\nconst config: GramoBaseConfig = {\n botToken: ${botTokenConfigStr},\n channelId: process.env.GRAMOBASE_CHANNEL_ID!,\n // encryptionKey: process.env.GRAMOBASE_ENCRYPTION_KEY,\n cacheMaxBytes: 64 * 1024 * 1024, // 64MB hot cache\n cacheTtlMs: 60_000,\n concurrency: 25,\n debug: process.env.NODE_ENV === 'development',\n};\n\nexport default config;\n`;\n\n writeFileSync(join(cwd, 'gramobase.config.ts'), configContent);\n\n // Create migrations folder — path is hardcoded, not from user input\n const migrationsDir = join(cwd, 'gramobase', 'migrations');\n if (!existsSync(migrationsDir)) {\n mkdirSync(migrationsDir, { recursive: true });\n }\n\n spinner.succeed(chalk.green('gramobase initialized!'));\n\n console.log(`\n ${chalk.bold('Files created:')}\n ${chalk.gray('├─')} .env\n ${chalk.gray('└─')} gramobase.config.ts\n ${chalk.gray('└─')} gramobase/migrations/\n\n ${chalk.bold('Next steps:')}\n ${chalk.cyan('1.')} Run ${chalk.bold('npx gramobase migrate')} to initialize the database\n ${chalk.cyan('2.')} Import and use: ${chalk.gray(\"import { createClient } from 'gramobase'\")}\n`);\n });\n\n// ─── gramobase migrate ───────────────────────────────────────────────────────\n\nprogram\n .command('migrate')\n .description('Run pending migrations')\n .option('--rollback <steps>', 'Rollback N migration steps', '0')\n .option('--status', 'Show migration status')\n .action(async (opts) => {\n const spinner = ora('Loading migrations...').start();\n try {\n const configPath = join(process.cwd(), 'gramobase.config.ts');\n\n spinner.text = 'Connecting...';\n spinner.succeed('Migration runner ready (run in your project after build)');\n } catch (e: any) {\n spinner.fail(chalk.red('Failed: ' + (e instanceof Error ? e.message : 'Unknown error')));\n }\n });\n\n// ─── gramobase status ────────────────────────────────────────────────────────\n\nprogram\n .command('status')\n .description('Show database and connection status')\n .action(async () => {\n const spinner = ora('Checking status...').start();\n try {\n const token = process.env['GRAMOBASE_BOT_TOKEN'];\n const channelId = process.env['GRAMOBASE_CHANNEL_ID'];\n\n if (!token || !channelId) {\n spinner.fail('.env not found — run gramobase init first');\n return;\n }\n\n // Ping Telegram Bot API — token is from env, not user input in this context\n const res = await fetch(`https://api.telegram.org/bot${encodeURIComponent(token)}/getMe`);\n const json = await res.json() as any;\n\n if (json.ok) {\n spinner.succeed(chalk.green('Connected'));\n console.log(`\n ${chalk.bold('Bot:')} ${chalk.cyan('@' + json.result.username)} (${json.result.first_name})\n ${chalk.bold('Channel:')} ${chalk.cyan(channelId)}\n ${chalk.bold('Status:')} ${chalk.green('● Online')}\n`);\n } else {\n spinner.fail(chalk.red('Bot API error — check your token'));\n }\n } catch (e: any) {\n spinner.fail(chalk.red('Connection failed'));\n }\n });\n\n// ─── gramobase generate ──────────────────────────────────────────────────────\n\nprogram\n .command('generate <name>')\n .description('Generate a typed collection schema')\n .option('--fields <fields>', 'Comma-separated fields (e.g. name:string,age:number)')\n .action((name: string, opts) => {\n // Sanitize name — only allow alphanumeric + underscore/hyphen\n const safeName = name.replace(/[^a-zA-Z0-9_-]/g, '');\n if (!safeName || safeName !== name) {\n console.error(chalk.red(' Error: Schema name must contain only letters, numbers, underscores, and hyphens'));\n process.exit(1);\n }\n\n const fields: string[] = opts.fields\n ? (opts.fields as string).split(',').map((f: string) => f.trim())\n : ['name:string'];\n\n const schemaFields = fields.map((f: string) => {\n const [fname, ftype] = f.split(':');\n // Sanitize field name\n const safeFname = (fname ?? 'field').replace(/[^a-zA-Z0-9_]/g, '');\n const zodType =\n ftype === 'number' ? 'z.number()' :\n ftype === 'boolean' ? 'z.boolean()' :\n ftype === 'date' ? 'z.string()' :\n 'z.string()';\n return ` ${safeFname}: ${zodType},`;\n }).join('\\n');\n\n const output = `import { z } from 'zod';\nimport { createClient } from 'gramobase';\n\nexport const ${safeName}Schema = z.object({\n${schemaFields}\n});\n\nexport type ${capitalize(safeName)} = z.infer<typeof ${safeName}Schema>;\n\n// Usage:\n// const db = createClient(config);\n// const ${safeName}s = db.collection('${safeName}s', { schema: ${safeName}Schema });\n// await ${safeName}s.insertOne({ ${fields.map((f: string) => (f.split(':')[0] ?? 'field').replace(/[^a-zA-Z0-9_]/g, '') + ': ...' ).join(', ')} });\n`;\n\n // Path is constructed from sanitized name only — no user-controlled path traversal\n const dir = join(process.cwd(), 'gramobase');\n const outPath = join(dir, `${safeName}.schema.ts`);\n\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(outPath, output);\n\n console.log(`\\n ${chalk.green('✓')} Generated ${chalk.cyan(`gramobase/${safeName}.schema.ts`)}\\n`);\n });\n\n// ─── gramobase studio ────────────────────────────────────────────────────────\n\nprogram\n .command('studio')\n .description('Open the gramobase browser studio UI')\n .option('--port <port>', 'Port to listen on', '4242')\n .action(async (opts) => {\n // Validate port is numeric and in valid range\n const port = parseInt(opts.port as string, 10);\n if (isNaN(port) || port < 1 || port > 65535) {\n console.error(chalk.red(' Error: Invalid port number'));\n process.exit(1);\n }\n\n const spinner = ora('Starting gramobase studio...').start();\n\n try {\n const { startStudio } = await import(new URL('../../dist/studio/server.js', import.meta.url).href);\n await startStudio(port, process.cwd());\n spinner.succeed(chalk.green('gramobase studio is running!'));\n console.log(`\n ${chalk.bold('Studio')} ${chalk.cyan(`http://localhost:${port}`)}\n ${chalk.gray('Press Ctrl+C to stop.')}\n`);\n } catch (e: any) {\n spinner.fail(chalk.red('Failed to start studio: ' + (e?.message || String(e))));\n process.exit(1);\n }\n });\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\nprogram.parse();\n"]}
|
package/dist/bin/gramobase.js
CHANGED
|
@@ -2,13 +2,23 @@
|
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import ora from 'ora';
|
|
5
|
-
import {
|
|
6
|
-
import { writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
5
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
7
6
|
import { join } from 'path';
|
|
7
|
+
import inquirer from 'inquirer';
|
|
8
8
|
|
|
9
9
|
// gramobase — Telegram as your free, infinite backend
|
|
10
10
|
|
|
11
|
-
var pkg = { version: "0.
|
|
11
|
+
var pkg = { version: "0.0.0" };
|
|
12
|
+
try {
|
|
13
|
+
const pkgUrl = new URL("../../package.json", import.meta.url);
|
|
14
|
+
pkg = JSON.parse(readFileSync(pkgUrl, "utf-8"));
|
|
15
|
+
} catch (e) {
|
|
16
|
+
try {
|
|
17
|
+
const pkgUrl2 = new URL("../package.json", import.meta.url);
|
|
18
|
+
pkg = JSON.parse(readFileSync(pkgUrl2, "utf-8"));
|
|
19
|
+
} catch (e2) {
|
|
20
|
+
}
|
|
21
|
+
}
|
|
12
22
|
var program = new Command();
|
|
13
23
|
program.name("gramobase").description(chalk.cyan("Telegram as your free, infinite backend database")).version(pkg.version);
|
|
14
24
|
program.command("init").description("Initialize a new gramobase project").option("--yes", "Skip prompts, use defaults").action(async (opts) => {
|
|
@@ -17,22 +27,33 @@ program.command("init").description("Initialize a new gramobase project").option
|
|
|
17
27
|
let channelId = "";
|
|
18
28
|
let encryptionKey = "";
|
|
19
29
|
if (!opts.yes) {
|
|
20
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
21
|
-
const ask = (q) => new Promise((res) => rl.question(q, res));
|
|
22
30
|
console.log(chalk.cyan.bold("\n Step 1: Bot Tokens (Anti-flood rotation)"));
|
|
23
31
|
console.log(chalk.gray(" You can use multiple bot tokens to increase your rate limit (30 req/s per bot)."));
|
|
24
|
-
const numBotsStr = await
|
|
32
|
+
const { numBotsStr } = await inquirer.prompt([{
|
|
33
|
+
type: "input",
|
|
34
|
+
name: "numBotsStr",
|
|
35
|
+
message: chalk.white("How many bot tokens do you want to add? (Default: 1):")
|
|
36
|
+
}]);
|
|
25
37
|
const numBots = Math.max(1, parseInt(numBotsStr, 10) || 1);
|
|
26
38
|
console.log(chalk.gray(" Create your bots by messaging @BotFather on Telegram and copy the HTTP API tokens."));
|
|
27
39
|
for (let i = 1; i <= numBots; i++) {
|
|
28
|
-
const token = await
|
|
40
|
+
const { token } = await inquirer.prompt([{
|
|
41
|
+
type: "password",
|
|
42
|
+
name: "token",
|
|
43
|
+
message: chalk.white(`Bot token ${i}:`),
|
|
44
|
+
mask: chalk.red("*")
|
|
45
|
+
}]);
|
|
29
46
|
botTokens.push(token.trim());
|
|
30
47
|
}
|
|
31
48
|
console.log(chalk.cyan.bold("\n Step 2: Channel ID"));
|
|
32
49
|
console.log(chalk.gray(" You can enter your Channel ID manually (e.g. -100123456789)"));
|
|
33
50
|
console.log(chalk.gray(" OR leave it blank to auto-detect it."));
|
|
34
|
-
|
|
35
|
-
|
|
51
|
+
const { channelIdInput } = await inquirer.prompt([{
|
|
52
|
+
type: "input",
|
|
53
|
+
name: "channelIdInput",
|
|
54
|
+
message: chalk.white("Channel ID (Press Enter to auto-detect):")
|
|
55
|
+
}]);
|
|
56
|
+
channelId = channelIdInput.trim();
|
|
36
57
|
if (!channelId) {
|
|
37
58
|
console.log(chalk.yellow("\n [Auto-Detect Mode]"));
|
|
38
59
|
console.log(chalk.gray(` 1. Create a private Telegram channel.`));
|
|
@@ -70,8 +91,12 @@ program.command("init").description("Initialize a new gramobase project").option
|
|
|
70
91
|
}
|
|
71
92
|
}
|
|
72
93
|
console.log(chalk.cyan.bold("\n Step 3: Security (Optional)"));
|
|
73
|
-
|
|
74
|
-
|
|
94
|
+
const { encryptionKeyInput } = await inquirer.prompt([{
|
|
95
|
+
type: "input",
|
|
96
|
+
name: "encryptionKeyInput",
|
|
97
|
+
message: chalk.white("Encryption key (optional, press enter to skip):")
|
|
98
|
+
}]);
|
|
99
|
+
encryptionKey = encryptionKeyInput;
|
|
75
100
|
}
|
|
76
101
|
const spinner = ora("Setting up gramobase...").start();
|
|
77
102
|
const cwd = process.cwd();
|
|
@@ -120,9 +145,8 @@ export default config;
|
|
|
120
145
|
${chalk.gray("\u2514\u2500")} gramobase/migrations/
|
|
121
146
|
|
|
122
147
|
${chalk.bold("Next steps:")}
|
|
123
|
-
${chalk.cyan("1.")}
|
|
124
|
-
${chalk.cyan("2.")}
|
|
125
|
-
${chalk.cyan("3.")} Import and use: ${chalk.gray("import { createClient } from 'gramobase'")}
|
|
148
|
+
${chalk.cyan("1.")} Run ${chalk.bold("npx gramobase migrate")} to initialize the database
|
|
149
|
+
${chalk.cyan("2.")} Import and use: ${chalk.gray("import { createClient } from 'gramobase'")}
|
|
126
150
|
`);
|
|
127
151
|
});
|
|
128
152
|
program.command("migrate").description("Run pending migrations").option("--rollback <steps>", "Rollback N migration steps", "0").option("--status", "Show migration status").action(async (opts) => {
|
|
@@ -195,18 +219,25 @@ export type ${capitalize(safeName)} = z.infer<typeof ${safeName}Schema>;
|
|
|
195
219
|
${chalk.green("\u2713")} Generated ${chalk.cyan(`gramobase/${safeName}.schema.ts`)}
|
|
196
220
|
`);
|
|
197
221
|
});
|
|
198
|
-
program.command("studio").description("Open the gramobase browser studio UI").option("--port <port>", "Port to listen on", "4242").action((opts) => {
|
|
222
|
+
program.command("studio").description("Open the gramobase browser studio UI").option("--port <port>", "Port to listen on", "4242").action(async (opts) => {
|
|
199
223
|
const port = parseInt(opts.port, 10);
|
|
200
224
|
if (isNaN(port) || port < 1 || port > 65535) {
|
|
201
225
|
console.error(chalk.red(" Error: Invalid port number"));
|
|
202
226
|
process.exit(1);
|
|
203
227
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
228
|
+
const spinner = ora("Starting gramobase studio...").start();
|
|
229
|
+
try {
|
|
230
|
+
const { startStudio } = await import(new URL("../../dist/studio/server.js", import.meta.url).href);
|
|
231
|
+
await startStudio(port, process.cwd());
|
|
232
|
+
spinner.succeed(chalk.green("gramobase studio is running!"));
|
|
233
|
+
console.log(`
|
|
234
|
+
${chalk.bold("Studio")} ${chalk.cyan(`http://localhost:${port}`)}
|
|
235
|
+
${chalk.gray("Press Ctrl+C to stop.")}
|
|
208
236
|
`);
|
|
209
|
-
|
|
237
|
+
} catch (e) {
|
|
238
|
+
spinner.fail(chalk.red("Failed to start studio: " + (e?.message || String(e))));
|
|
239
|
+
process.exit(1);
|
|
240
|
+
}
|
|
210
241
|
});
|
|
211
242
|
function capitalize(s) {
|
|
212
243
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../bin/gramobase.ts"],"names":["spinner"],"mappings":"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","file":"gramobase.js","sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { createInterface } from 'readline';\nimport { writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join } from 'path';\n\nconst pkg = { version: '0.1.0' };\n\nconst program = new Command();\n\nprogram\n .name('gramobase')\n .description(chalk.cyan('Telegram as your free, infinite backend database'))\n .version(pkg.version);\n\n// ─── gramobase init ──────────────────────────────────────────────────────────\n\nprogram\n .command('init')\n .description('Initialize a new gramobase project')\n .option('--yes', 'Skip prompts, use defaults')\n .action(async (opts) => {\n console.log('\\n' + chalk.bold.cyan(' gramobase') + chalk.gray(' — Telegram backend\\n'));\n\n let botTokens: string[] = [];\n let channelId = '';\n let encryptionKey = '';\n\n if (!opts.yes) {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const ask = (q: string) => new Promise<string>((res) => rl.question(q, res));\n\n console.log(chalk.cyan.bold('\\n Step 1: Bot Tokens (Anti-flood rotation)'));\n console.log(chalk.gray(' You can use multiple bot tokens to increase your rate limit (30 req/s per bot).'));\n const numBotsStr = await ask(chalk.white(' How many bot tokens do you want to add? (Default: 1): '));\n const numBots = Math.max(1, parseInt(numBotsStr, 10) || 1);\n\n console.log(chalk.gray(' Create your bots by messaging @BotFather on Telegram and copy the HTTP API tokens.'));\n for (let i = 1; i <= numBots; i++) {\n const token = await ask(chalk.white(` Bot token ${i}: `));\n botTokens.push(token.trim());\n }\n\n console.log(chalk.cyan.bold('\\n Step 2: Channel ID'));\n console.log(chalk.gray(' You can enter your Channel ID manually (e.g. -100123456789)'));\n console.log(chalk.gray(' OR leave it blank to auto-detect it.'));\n channelId = await ask(chalk.white(' Channel ID (Press Enter to auto-detect): '));\n\n channelId = channelId.trim();\n\n if (!channelId) {\n console.log(chalk.yellow('\\n [Auto-Detect Mode]'));\n console.log(chalk.gray(` 1. Create a private Telegram channel.`));\n console.log(chalk.gray(` 2. Add your bot as an Administrator with full permissions.`));\n console.log(chalk.gray(` 3. Send any message in the channel (e.g. \"hello\").\\n`));\n \n const spinner = ora('Waiting for a message in your channel...').start();\n \n let detected = false;\n let offset = 0;\n // Use the first token to poll\n const pollToken = botTokens[0] || '';\n \n while (!detected) {\n try {\n const res = await fetch(`https://api.telegram.org/bot${pollToken}/getUpdates?offset=${offset}&timeout=2`);\n const json: any = await res.json();\n \n if (json.ok && json.result.length > 0) {\n for (const update of json.result) {\n offset = update.update_id + 1;\n if (update.channel_post && update.channel_post.chat) {\n channelId = update.channel_post.chat.id.toString();\n const title = update.channel_post.chat.title || 'Unknown Channel';\n spinner.succeed(chalk.green(`Found channel: ${title} (${channelId})`));\n detected = true;\n break;\n }\n }\n } else if (!json.ok) {\n spinner.fail(chalk.red('Invalid Bot Token or Telegram API error.'));\n process.exit(1);\n }\n } catch (e) {\n // Ignore fetch errors and continue polling\n }\n \n if (!detected) {\n await new Promise((resolve) => setTimeout(resolve, 2000));\n }\n }\n }\n\n console.log(chalk.cyan.bold('\\n Step 3: Security (Optional)'));\n encryptionKey = await ask(chalk.white(' Encryption key (optional, press enter to skip): '));\n rl.close();\n }\n\n const spinner = ora('Setting up gramobase...').start();\n\n // Create .env — never write tokens to paths derived from user input\n const cwd = process.cwd();\n const envPath = join(cwd, '.env');\n const envContentLines = [];\n \n if (botTokens.length === 1) {\n envContentLines.push(`GRAMOBASE_BOT_TOKEN=${botTokens[0]}`);\n } else {\n botTokens.forEach((token, i) => {\n envContentLines.push(`GRAMOBASE_BOT_TOKEN_${i + 1}=${token}`);\n });\n }\n \n const safeChannelId = channelId.trim();\n const safeKey = encryptionKey.trim();\n \n envContentLines.push(`GRAMOBASE_CHANNEL_ID=${safeChannelId}`);\n envContentLines.push(safeKey ? `GRAMOBASE_ENCRYPTION_KEY=${safeKey}` : '# GRAMOBASE_ENCRYPTION_KEY=');\n \n const envContent = envContentLines.join('\\n');\n writeFileSync(envPath, envContent + '\\n');\n\n const botTokenConfigStr = botTokens.length === 1\n ? `process.env.GRAMOBASE_BOT_TOKEN!`\n : `[\\n${botTokens.map((_, i) => ` process.env.GRAMOBASE_BOT_TOKEN_${i + 1}!,`).join('\\n')}\\n ]`;\n\n // Create gramobase.config.ts\n const configContent = `import { GramoBaseConfig } from 'gramobase';\n\nconst config: GramoBaseConfig = {\n botToken: ${botTokenConfigStr},\n channelId: process.env.GRAMOBASE_CHANNEL_ID!,\n // encryptionKey: process.env.GRAMOBASE_ENCRYPTION_KEY,\n cacheMaxBytes: 64 * 1024 * 1024, // 64MB hot cache\n cacheTtlMs: 60_000,\n concurrency: 25,\n debug: process.env.NODE_ENV === 'development',\n};\n\nexport default config;\n`;\n\n writeFileSync(join(cwd, 'gramobase.config.ts'), configContent);\n\n // Create migrations folder — path is hardcoded, not from user input\n const migrationsDir = join(cwd, 'gramobase', 'migrations');\n if (!existsSync(migrationsDir)) {\n mkdirSync(migrationsDir, { recursive: true });\n }\n\n spinner.succeed(chalk.green('gramobase initialized!'));\n\n console.log(`\n ${chalk.bold('Files created:')}\n ${chalk.gray('├─')} .env\n ${chalk.gray('└─')} gramobase.config.ts\n ${chalk.gray('└─')} gramobase/migrations/\n\n ${chalk.bold('Next steps:')}\n ${chalk.cyan('1.')} Add your bot token and channel ID to .env\n ${chalk.cyan('2.')} Run ${chalk.bold('gramobase migrate')} to initialize the database\n ${chalk.cyan('3.')} Import and use: ${chalk.gray(\"import { createClient } from 'gramobase'\")}\n`);\n });\n\n// ─── gramobase migrate ───────────────────────────────────────────────────────\n\nprogram\n .command('migrate')\n .description('Run pending migrations')\n .option('--rollback <steps>', 'Rollback N migration steps', '0')\n .option('--status', 'Show migration status')\n .action(async (opts) => {\n const spinner = ora('Loading migrations...').start();\n try {\n const configPath = join(process.cwd(), 'gramobase.config.ts');\n\n spinner.text = 'Connecting...';\n spinner.succeed('Migration runner ready (run in your project after build)');\n } catch (e: any) {\n spinner.fail(chalk.red('Failed: ' + (e instanceof Error ? e.message : 'Unknown error')));\n }\n });\n\n// ─── gramobase status ────────────────────────────────────────────────────────\n\nprogram\n .command('status')\n .description('Show database and connection status')\n .action(async () => {\n const spinner = ora('Checking status...').start();\n try {\n const token = process.env['GRAMOBASE_BOT_TOKEN'];\n const channelId = process.env['GRAMOBASE_CHANNEL_ID'];\n\n if (!token || !channelId) {\n spinner.fail('.env not found — run gramobase init first');\n return;\n }\n\n // Ping Telegram Bot API — token is from env, not user input in this context\n const res = await fetch(`https://api.telegram.org/bot${encodeURIComponent(token)}/getMe`);\n const json = await res.json() as any;\n\n if (json.ok) {\n spinner.succeed(chalk.green('Connected'));\n console.log(`\n ${chalk.bold('Bot:')} ${chalk.cyan('@' + json.result.username)} (${json.result.first_name})\n ${chalk.bold('Channel:')} ${chalk.cyan(channelId)}\n ${chalk.bold('Status:')} ${chalk.green('● Online')}\n`);\n } else {\n spinner.fail(chalk.red('Bot API error — check your token'));\n }\n } catch (e: any) {\n spinner.fail(chalk.red('Connection failed'));\n }\n });\n\n// ─── gramobase generate ──────────────────────────────────────────────────────\n\nprogram\n .command('generate <name>')\n .description('Generate a typed collection schema')\n .option('--fields <fields>', 'Comma-separated fields (e.g. name:string,age:number)')\n .action((name: string, opts) => {\n // Sanitize name — only allow alphanumeric + underscore/hyphen\n const safeName = name.replace(/[^a-zA-Z0-9_-]/g, '');\n if (!safeName || safeName !== name) {\n console.error(chalk.red(' Error: Schema name must contain only letters, numbers, underscores, and hyphens'));\n process.exit(1);\n }\n\n const fields: string[] = opts.fields\n ? (opts.fields as string).split(',').map((f: string) => f.trim())\n : ['name:string'];\n\n const schemaFields = fields.map((f: string) => {\n const [fname, ftype] = f.split(':');\n // Sanitize field name\n const safeFname = (fname ?? 'field').replace(/[^a-zA-Z0-9_]/g, '');\n const zodType =\n ftype === 'number' ? 'z.number()' :\n ftype === 'boolean' ? 'z.boolean()' :\n ftype === 'date' ? 'z.string()' :\n 'z.string()';\n return ` ${safeFname}: ${zodType},`;\n }).join('\\n');\n\n const output = `import { z } from 'zod';\nimport { createClient } from 'gramobase';\n\nexport const ${safeName}Schema = z.object({\n${schemaFields}\n});\n\nexport type ${capitalize(safeName)} = z.infer<typeof ${safeName}Schema>;\n\n// Usage:\n// const db = createClient(config);\n// const ${safeName}s = db.collection('${safeName}s', { schema: ${safeName}Schema });\n// await ${safeName}s.insertOne({ ${fields.map((f: string) => (f.split(':')[0] ?? 'field').replace(/[^a-zA-Z0-9_]/g, '') + ': ...' ).join(', ')} });\n`;\n\n // Path is constructed from sanitized name only — no user-controlled path traversal\n const dir = join(process.cwd(), 'gramobase');\n const outPath = join(dir, `${safeName}.schema.ts`);\n\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(outPath, output);\n\n console.log(`\\n ${chalk.green('✓')} Generated ${chalk.cyan(`gramobase/${safeName}.schema.ts`)}\\n`);\n });\n\n// ─── gramobase studio ────────────────────────────────────────────────────────\n\nprogram\n .command('studio')\n .description('Open the gramobase browser studio UI')\n .option('--port <port>', 'Port to listen on', '4242')\n .action((opts) => {\n // Validate port is numeric and in valid range\n const port = parseInt(opts.port as string, 10);\n if (isNaN(port) || port < 1 || port > 65535) {\n console.error(chalk.red(' Error: Invalid port number'));\n process.exit(1);\n }\n console.log(`\\n ${chalk.bold.cyan('gramobase studio')}\\n`);\n console.log(` ${chalk.gray('Open')} ${chalk.cyan(`http://localhost:${port}`)} ${chalk.gray('in your browser')}\\n`);\n console.log(chalk.yellow(' Studio UI coming in v0.2.0 — contribute at github.com/yourusername/gramobase\\n'));\n });\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\nprogram.parse();\n"]}
|
|
1
|
+
{"version":3,"sources":["../../bin/gramobase.ts"],"names":["spinner"],"mappings":"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","file":"gramobase.js","sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { writeFileSync, existsSync, mkdirSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport inquirer from 'inquirer';\n\nlet pkg = { version: '0.0.0' };\ntry {\n const pkgUrl = new URL('../../package.json', import.meta.url);\n pkg = JSON.parse(readFileSync(pkgUrl, 'utf-8'));\n} catch (e) {\n try {\n const pkgUrl2 = new URL('../package.json', import.meta.url);\n pkg = JSON.parse(readFileSync(pkgUrl2, 'utf-8'));\n } catch (e2) {}\n}\n\nconst program = new Command();\n\nprogram\n .name('gramobase')\n .description(chalk.cyan('Telegram as your free, infinite backend database'))\n .version(pkg.version);\n\n// ─── gramobase init ──────────────────────────────────────────────────────────\n\nprogram\n .command('init')\n .description('Initialize a new gramobase project')\n .option('--yes', 'Skip prompts, use defaults')\n .action(async (opts) => {\n console.log('\\n' + chalk.bold.cyan(' gramobase') + chalk.gray(' — Telegram backend\\n'));\n\n let botTokens: string[] = [];\n let channelId = '';\n let encryptionKey = '';\n\n if (!opts.yes) {\n console.log(chalk.cyan.bold('\\n Step 1: Bot Tokens (Anti-flood rotation)'));\n console.log(chalk.gray(' You can use multiple bot tokens to increase your rate limit (30 req/s per bot).'));\n \n const { numBotsStr } = await inquirer.prompt([{\n type: 'input',\n name: 'numBotsStr',\n message: chalk.white('How many bot tokens do you want to add? (Default: 1):')\n }]);\n const numBots = Math.max(1, parseInt(numBotsStr, 10) || 1);\n\n console.log(chalk.gray(' Create your bots by messaging @BotFather on Telegram and copy the HTTP API tokens.'));\n for (let i = 1; i <= numBots; i++) {\n const { token } = await inquirer.prompt([{\n type: 'password',\n name: 'token',\n message: chalk.white(`Bot token ${i}:`),\n mask: chalk.red('*')\n }]);\n botTokens.push(token.trim());\n }\n\n console.log(chalk.cyan.bold('\\n Step 2: Channel ID'));\n console.log(chalk.gray(' You can enter your Channel ID manually (e.g. -100123456789)'));\n console.log(chalk.gray(' OR leave it blank to auto-detect it.'));\n \n const { channelIdInput } = await inquirer.prompt([{\n type: 'input',\n name: 'channelIdInput',\n message: chalk.white('Channel ID (Press Enter to auto-detect):')\n }]);\n \n channelId = channelIdInput.trim();\n\n if (!channelId) {\n console.log(chalk.yellow('\\n [Auto-Detect Mode]'));\n console.log(chalk.gray(` 1. Create a private Telegram channel.`));\n console.log(chalk.gray(` 2. Add your bot as an Administrator with full permissions.`));\n console.log(chalk.gray(` 3. Send any message in the channel (e.g. \"hello\").\\n`));\n \n const spinner = ora('Waiting for a message in your channel...').start();\n \n let detected = false;\n let offset = 0;\n // Use the first token to poll\n const pollToken = botTokens[0] || '';\n \n while (!detected) {\n try {\n const res = await fetch(`https://api.telegram.org/bot${pollToken}/getUpdates?offset=${offset}&timeout=2`);\n const json: any = await res.json();\n \n if (json.ok && json.result.length > 0) {\n for (const update of json.result) {\n offset = update.update_id + 1;\n if (update.channel_post && update.channel_post.chat) {\n channelId = update.channel_post.chat.id.toString();\n const title = update.channel_post.chat.title || 'Unknown Channel';\n spinner.succeed(chalk.green(`Found channel: ${title} (${channelId})`));\n detected = true;\n break;\n }\n }\n } else if (!json.ok) {\n spinner.fail(chalk.red('Invalid Bot Token or Telegram API error.'));\n process.exit(1);\n }\n } catch (e) {\n // Ignore fetch errors and continue polling\n }\n \n if (!detected) {\n await new Promise((resolve) => setTimeout(resolve, 2000));\n }\n }\n }\n\n console.log(chalk.cyan.bold('\\n Step 3: Security (Optional)'));\n const { encryptionKeyInput } = await inquirer.prompt([{\n type: 'input',\n name: 'encryptionKeyInput',\n message: chalk.white('Encryption key (optional, press enter to skip):')\n }]);\n encryptionKey = encryptionKeyInput;\n }\n\n const spinner = ora('Setting up gramobase...').start();\n\n // Create .env — never write tokens to paths derived from user input\n const cwd = process.cwd();\n const envPath = join(cwd, '.env');\n const envContentLines = [];\n \n if (botTokens.length === 1) {\n envContentLines.push(`GRAMOBASE_BOT_TOKEN=${botTokens[0]}`);\n } else {\n botTokens.forEach((token, i) => {\n envContentLines.push(`GRAMOBASE_BOT_TOKEN_${i + 1}=${token}`);\n });\n }\n \n const safeChannelId = channelId.trim();\n const safeKey = encryptionKey.trim();\n \n envContentLines.push(`GRAMOBASE_CHANNEL_ID=${safeChannelId}`);\n envContentLines.push(safeKey ? `GRAMOBASE_ENCRYPTION_KEY=${safeKey}` : '# GRAMOBASE_ENCRYPTION_KEY=');\n \n const envContent = envContentLines.join('\\n');\n writeFileSync(envPath, envContent + '\\n');\n\n const botTokenConfigStr = botTokens.length === 1\n ? `process.env.GRAMOBASE_BOT_TOKEN!`\n : `[\\n${botTokens.map((_, i) => ` process.env.GRAMOBASE_BOT_TOKEN_${i + 1}!,`).join('\\n')}\\n ]`;\n\n // Create gramobase.config.ts\n const configContent = `import { GramoBaseConfig } from 'gramobase';\n\nconst config: GramoBaseConfig = {\n botToken: ${botTokenConfigStr},\n channelId: process.env.GRAMOBASE_CHANNEL_ID!,\n // encryptionKey: process.env.GRAMOBASE_ENCRYPTION_KEY,\n cacheMaxBytes: 64 * 1024 * 1024, // 64MB hot cache\n cacheTtlMs: 60_000,\n concurrency: 25,\n debug: process.env.NODE_ENV === 'development',\n};\n\nexport default config;\n`;\n\n writeFileSync(join(cwd, 'gramobase.config.ts'), configContent);\n\n // Create migrations folder — path is hardcoded, not from user input\n const migrationsDir = join(cwd, 'gramobase', 'migrations');\n if (!existsSync(migrationsDir)) {\n mkdirSync(migrationsDir, { recursive: true });\n }\n\n spinner.succeed(chalk.green('gramobase initialized!'));\n\n console.log(`\n ${chalk.bold('Files created:')}\n ${chalk.gray('├─')} .env\n ${chalk.gray('└─')} gramobase.config.ts\n ${chalk.gray('└─')} gramobase/migrations/\n\n ${chalk.bold('Next steps:')}\n ${chalk.cyan('1.')} Run ${chalk.bold('npx gramobase migrate')} to initialize the database\n ${chalk.cyan('2.')} Import and use: ${chalk.gray(\"import { createClient } from 'gramobase'\")}\n`);\n });\n\n// ─── gramobase migrate ───────────────────────────────────────────────────────\n\nprogram\n .command('migrate')\n .description('Run pending migrations')\n .option('--rollback <steps>', 'Rollback N migration steps', '0')\n .option('--status', 'Show migration status')\n .action(async (opts) => {\n const spinner = ora('Loading migrations...').start();\n try {\n const configPath = join(process.cwd(), 'gramobase.config.ts');\n\n spinner.text = 'Connecting...';\n spinner.succeed('Migration runner ready (run in your project after build)');\n } catch (e: any) {\n spinner.fail(chalk.red('Failed: ' + (e instanceof Error ? e.message : 'Unknown error')));\n }\n });\n\n// ─── gramobase status ────────────────────────────────────────────────────────\n\nprogram\n .command('status')\n .description('Show database and connection status')\n .action(async () => {\n const spinner = ora('Checking status...').start();\n try {\n const token = process.env['GRAMOBASE_BOT_TOKEN'];\n const channelId = process.env['GRAMOBASE_CHANNEL_ID'];\n\n if (!token || !channelId) {\n spinner.fail('.env not found — run gramobase init first');\n return;\n }\n\n // Ping Telegram Bot API — token is from env, not user input in this context\n const res = await fetch(`https://api.telegram.org/bot${encodeURIComponent(token)}/getMe`);\n const json = await res.json() as any;\n\n if (json.ok) {\n spinner.succeed(chalk.green('Connected'));\n console.log(`\n ${chalk.bold('Bot:')} ${chalk.cyan('@' + json.result.username)} (${json.result.first_name})\n ${chalk.bold('Channel:')} ${chalk.cyan(channelId)}\n ${chalk.bold('Status:')} ${chalk.green('● Online')}\n`);\n } else {\n spinner.fail(chalk.red('Bot API error — check your token'));\n }\n } catch (e: any) {\n spinner.fail(chalk.red('Connection failed'));\n }\n });\n\n// ─── gramobase generate ──────────────────────────────────────────────────────\n\nprogram\n .command('generate <name>')\n .description('Generate a typed collection schema')\n .option('--fields <fields>', 'Comma-separated fields (e.g. name:string,age:number)')\n .action((name: string, opts) => {\n // Sanitize name — only allow alphanumeric + underscore/hyphen\n const safeName = name.replace(/[^a-zA-Z0-9_-]/g, '');\n if (!safeName || safeName !== name) {\n console.error(chalk.red(' Error: Schema name must contain only letters, numbers, underscores, and hyphens'));\n process.exit(1);\n }\n\n const fields: string[] = opts.fields\n ? (opts.fields as string).split(',').map((f: string) => f.trim())\n : ['name:string'];\n\n const schemaFields = fields.map((f: string) => {\n const [fname, ftype] = f.split(':');\n // Sanitize field name\n const safeFname = (fname ?? 'field').replace(/[^a-zA-Z0-9_]/g, '');\n const zodType =\n ftype === 'number' ? 'z.number()' :\n ftype === 'boolean' ? 'z.boolean()' :\n ftype === 'date' ? 'z.string()' :\n 'z.string()';\n return ` ${safeFname}: ${zodType},`;\n }).join('\\n');\n\n const output = `import { z } from 'zod';\nimport { createClient } from 'gramobase';\n\nexport const ${safeName}Schema = z.object({\n${schemaFields}\n});\n\nexport type ${capitalize(safeName)} = z.infer<typeof ${safeName}Schema>;\n\n// Usage:\n// const db = createClient(config);\n// const ${safeName}s = db.collection('${safeName}s', { schema: ${safeName}Schema });\n// await ${safeName}s.insertOne({ ${fields.map((f: string) => (f.split(':')[0] ?? 'field').replace(/[^a-zA-Z0-9_]/g, '') + ': ...' ).join(', ')} });\n`;\n\n // Path is constructed from sanitized name only — no user-controlled path traversal\n const dir = join(process.cwd(), 'gramobase');\n const outPath = join(dir, `${safeName}.schema.ts`);\n\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(outPath, output);\n\n console.log(`\\n ${chalk.green('✓')} Generated ${chalk.cyan(`gramobase/${safeName}.schema.ts`)}\\n`);\n });\n\n// ─── gramobase studio ────────────────────────────────────────────────────────\n\nprogram\n .command('studio')\n .description('Open the gramobase browser studio UI')\n .option('--port <port>', 'Port to listen on', '4242')\n .action(async (opts) => {\n // Validate port is numeric and in valid range\n const port = parseInt(opts.port as string, 10);\n if (isNaN(port) || port < 1 || port > 65535) {\n console.error(chalk.red(' Error: Invalid port number'));\n process.exit(1);\n }\n\n const spinner = ora('Starting gramobase studio...').start();\n\n try {\n const { startStudio } = await import(new URL('../../dist/studio/server.js', import.meta.url).href);\n await startStudio(port, process.cwd());\n spinner.succeed(chalk.green('gramobase studio is running!'));\n console.log(`\n ${chalk.bold('Studio')} ${chalk.cyan(`http://localhost:${port}`)}\n ${chalk.gray('Press Ctrl+C to stop.')}\n`);\n } catch (e: any) {\n spinner.fail(chalk.red('Failed to start studio: ' + (e?.message || String(e))));\n process.exit(1);\n }\n });\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\nprogram.parse();\n"]}
|