@butterbase/cli 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.
Files changed (59) hide show
  1. package/README.md +255 -0
  2. package/bin/butterbase.ts +137 -0
  3. package/dist/bin/butterbase.d.ts +3 -0
  4. package/dist/bin/butterbase.d.ts.map +1 -0
  5. package/dist/bin/butterbase.js +112 -0
  6. package/dist/bin/butterbase.js.map +1 -0
  7. package/dist/src/commands/apps.d.ts +5 -0
  8. package/dist/src/commands/apps.d.ts.map +1 -0
  9. package/dist/src/commands/apps.js +113 -0
  10. package/dist/src/commands/apps.js.map +1 -0
  11. package/dist/src/commands/config.d.ts +5 -0
  12. package/dist/src/commands/config.d.ts.map +1 -0
  13. package/dist/src/commands/config.js +43 -0
  14. package/dist/src/commands/config.js.map +1 -0
  15. package/dist/src/commands/functions.d.ts +15 -0
  16. package/dist/src/commands/functions.d.ts.map +1 -0
  17. package/dist/src/commands/functions.js +94 -0
  18. package/dist/src/commands/functions.js.map +1 -0
  19. package/dist/src/commands/init.d.ts +2 -0
  20. package/dist/src/commands/init.d.ts.map +1 -0
  21. package/dist/src/commands/init.js +118 -0
  22. package/dist/src/commands/init.js.map +1 -0
  23. package/dist/src/commands/schema.d.ts +10 -0
  24. package/dist/src/commands/schema.d.ts.map +1 -0
  25. package/dist/src/commands/schema.js +69 -0
  26. package/dist/src/commands/schema.js.map +1 -0
  27. package/dist/src/commands/storage.d.ts +10 -0
  28. package/dist/src/commands/storage.d.ts.map +1 -0
  29. package/dist/src/commands/storage.js +105 -0
  30. package/dist/src/commands/storage.js.map +1 -0
  31. package/dist/src/lib/api-client.d.ts +44 -0
  32. package/dist/src/lib/api-client.d.ts.map +1 -0
  33. package/dist/src/lib/api-client.js +129 -0
  34. package/dist/src/lib/api-client.js.map +1 -0
  35. package/dist/src/lib/config.d.ts +47 -0
  36. package/dist/src/lib/config.d.ts.map +1 -0
  37. package/dist/src/lib/config.js +87 -0
  38. package/dist/src/lib/config.js.map +1 -0
  39. package/package.json +35 -0
  40. package/src/commands/apps.ts +130 -0
  41. package/src/commands/config.ts +50 -0
  42. package/src/commands/functions.ts +116 -0
  43. package/src/commands/init.ts +151 -0
  44. package/src/commands/schema.ts +78 -0
  45. package/src/commands/storage.ts +117 -0
  46. package/src/lib/api-client.ts +176 -0
  47. package/src/lib/config.ts +112 -0
  48. package/templates/react-vite/.env.example +2 -0
  49. package/templates/react-vite/README.md +38 -0
  50. package/templates/react-vite/index.html +13 -0
  51. package/templates/react-vite/package.json +25 -0
  52. package/templates/react-vite/src/App.css +33 -0
  53. package/templates/react-vite/src/App.tsx +77 -0
  54. package/templates/react-vite/src/index.css +8 -0
  55. package/templates/react-vite/src/lib.ts +6 -0
  56. package/templates/react-vite/src/main.tsx +10 -0
  57. package/templates/react-vite/tsconfig.json +21 -0
  58. package/templates/react-vite/vite.config.ts +6 -0
  59. package/tsconfig.json +20 -0
@@ -0,0 +1,43 @@
1
+ import prompts from 'prompts';
2
+ import chalk from 'chalk';
3
+ import { updateConfig, loadConfig } from '../lib/config.js';
4
+ export async function loginCommand() {
5
+ console.log(chalk.blue('šŸ” Butterbase Login\n'));
6
+ const { apiKey } = await prompts({
7
+ type: 'password',
8
+ name: 'apiKey',
9
+ message: 'Enter your Butterbase API key:',
10
+ validate: (value) => value.length > 0 || 'API key is required',
11
+ });
12
+ if (!apiKey) {
13
+ console.log(chalk.yellow('Login cancelled'));
14
+ process.exit(0);
15
+ }
16
+ await updateConfig('apiKey', apiKey);
17
+ console.log(chalk.green('āœ“ Successfully logged in!'));
18
+ console.log(chalk.gray(`Config saved to ~/.butterbase/config.json`));
19
+ }
20
+ export async function logoutCommand() {
21
+ await updateConfig('apiKey', undefined);
22
+ console.log(chalk.green('āœ“ Successfully logged out'));
23
+ }
24
+ export async function configGetCommand() {
25
+ const config = await loadConfig();
26
+ console.log(chalk.blue('Current configuration:\n'));
27
+ console.log(JSON.stringify(config, null, 2));
28
+ }
29
+ export async function configSetCommand(key, value) {
30
+ const config = await loadConfig();
31
+ // Type-safe config update
32
+ if (key in config) {
33
+ config[key] = value;
34
+ await updateConfig(key, value);
35
+ console.log(chalk.green(`āœ“ Set ${key} = ${value}`));
36
+ }
37
+ else {
38
+ console.log(chalk.red(`āœ— Unknown config key: ${key}`));
39
+ console.log(chalk.gray('Valid keys: endpoint, apiKey, currentApp'));
40
+ process.exit(1);
41
+ }
42
+ }
43
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE5D,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAEjD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC;QAC/B,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,gCAAgC;QACzC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,qBAAqB;KAC/D,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAErC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,GAAW,EAAE,KAAa;IAC/D,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAElC,0BAA0B;IAC1B,IAAI,GAAG,IAAI,MAAM,EAAE,CAAC;QACjB,MAAc,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QAC7B,MAAM,YAAY,CAAC,GAAU,EAAE,KAAK,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,GAAG,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC;IACtD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,yBAAyB,GAAG,EAAE,CAAC,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC,CAAC;QACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ export declare function functionsListCommand(options: {
2
+ app?: string;
3
+ }): Promise<void>;
4
+ export declare function functionsDeployCommand(file: string, options: {
5
+ app?: string;
6
+ name?: string;
7
+ trigger?: string;
8
+ description?: string;
9
+ }): Promise<void>;
10
+ export declare function functionsLogsCommand(functionName: string, options: {
11
+ app?: string;
12
+ level?: string;
13
+ limit?: number;
14
+ }): Promise<void>;
15
+ //# sourceMappingURL=functions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../../src/commands/functions.ts"],"names":[],"mappings":"AAmBA,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,iBA2BnE;AAED,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,iBAgCA;AAED,wBAAsB,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE;IACxE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,iBAwBA"}
@@ -0,0 +1,94 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import fs from 'fs-extra';
4
+ import { deployFunction, listFunctions, getFunctionLogs } from '../lib/api-client.js';
5
+ import { getCurrentAppId } from '../lib/config.js';
6
+ async function requireAppId(appId) {
7
+ if (appId)
8
+ return appId;
9
+ const currentAppId = await getCurrentAppId();
10
+ if (!currentAppId) {
11
+ console.log(chalk.red('āœ— No app specified and no current app set'));
12
+ console.log(chalk.gray('Use: butterbase apps use <app-id>'));
13
+ process.exit(1);
14
+ }
15
+ return currentAppId;
16
+ }
17
+ export async function functionsListCommand(options) {
18
+ const appId = await requireAppId(options.app);
19
+ const spinner = ora('Fetching functions...').start();
20
+ try {
21
+ const response = await listFunctions(appId);
22
+ spinner.stop();
23
+ if (!response.functions || response.functions.length === 0) {
24
+ console.log(chalk.yellow('No functions found'));
25
+ return;
26
+ }
27
+ console.log(chalk.blue('\nDeployed functions:\n'));
28
+ for (const func of response.functions) {
29
+ console.log(chalk.bold(func.name));
30
+ console.log(chalk.gray(` Trigger: ${func.trigger_type}`));
31
+ if (func.description) {
32
+ console.log(chalk.gray(` Description: ${func.description}`));
33
+ }
34
+ console.log();
35
+ }
36
+ }
37
+ catch (error) {
38
+ spinner.fail('Failed to fetch functions');
39
+ console.error(chalk.red(error.message));
40
+ process.exit(1);
41
+ }
42
+ }
43
+ export async function functionsDeployCommand(file, options) {
44
+ const appId = await requireAppId(options.app);
45
+ if (!await fs.pathExists(file)) {
46
+ console.log(chalk.red(`āœ— File not found: ${file}`));
47
+ process.exit(1);
48
+ }
49
+ const functionName = options.name || file.replace(/\.(ts|js)$/, '').split('/').pop();
50
+ const spinner = ora(`Deploying function "${functionName}"...`).start();
51
+ try {
52
+ const code = await fs.readFile(file, 'utf-8');
53
+ const triggerType = options.trigger || 'http';
54
+ const trigger = { type: triggerType, config: {} };
55
+ await deployFunction(appId, {
56
+ name: functionName,
57
+ code,
58
+ description: options.description,
59
+ trigger,
60
+ });
61
+ spinner.succeed(`Deployed function "${functionName}"`);
62
+ console.log(chalk.green('\nāœ“ Function deployed successfully!'));
63
+ console.log(chalk.gray(` Invoke URL: /v1/${appId}/fn/${functionName}`));
64
+ }
65
+ catch (error) {
66
+ spinner.fail('Failed to deploy function');
67
+ console.error(chalk.red(error.message));
68
+ process.exit(1);
69
+ }
70
+ }
71
+ export async function functionsLogsCommand(functionName, options) {
72
+ const appId = await requireAppId(options.app);
73
+ const spinner = ora('Fetching logs...').start();
74
+ try {
75
+ const response = await getFunctionLogs(appId, functionName, options.level, options.limit);
76
+ spinner.stop();
77
+ if (!response.logs || response.logs.length === 0) {
78
+ console.log(chalk.yellow('No logs found'));
79
+ return;
80
+ }
81
+ console.log(chalk.blue(`\nLogs for ${functionName}:\n`));
82
+ for (const log of response.logs) {
83
+ const timestamp = new Date(log.timestamp).toLocaleString();
84
+ const levelColor = log.level === 'error' ? chalk.red : chalk.gray;
85
+ console.log(`${chalk.gray(timestamp)} ${levelColor(log.level.toUpperCase())} ${log.message}`);
86
+ }
87
+ }
88
+ catch (error) {
89
+ spinner.fail('Failed to fetch logs');
90
+ console.error(chalk.red(error.message));
91
+ process.exit(1);
92
+ }
93
+ }
94
+ //# sourceMappingURL=functions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functions.js","sourceRoot":"","sources":["../../../src/commands/functions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function initCommand(template?: string): Promise<void>;
2
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/commands/init.ts"],"names":[],"mappings":"AA+CA,wBAAsB,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,iBAuGlD"}
@@ -0,0 +1,118 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import prompts from 'prompts';
4
+ import fs from 'fs-extra';
5
+ import path from 'path';
6
+ import { fileURLToPath } from 'url';
7
+ import { getMergedConfig } from '../lib/config.js';
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = path.dirname(__filename);
10
+ async function replaceVariables(content, variables) {
11
+ let result = content;
12
+ for (const [key, value] of Object.entries(variables)) {
13
+ result = result.replace(new RegExp(`{{${key}}}`, 'g'), value);
14
+ }
15
+ return result;
16
+ }
17
+ async function copyTemplate(templateDir, targetDir, variables) {
18
+ const files = await fs.readdir(templateDir, { withFileTypes: true });
19
+ for (const file of files) {
20
+ const sourcePath = path.join(templateDir, file.name);
21
+ const targetPath = path.join(targetDir, file.name);
22
+ if (file.isDirectory()) {
23
+ await fs.ensureDir(targetPath);
24
+ await copyTemplate(sourcePath, targetPath, variables);
25
+ }
26
+ else {
27
+ const content = await fs.readFile(sourcePath, 'utf-8');
28
+ const processedContent = await replaceVariables(content, variables);
29
+ await fs.writeFile(targetPath, processedContent);
30
+ }
31
+ }
32
+ }
33
+ export async function initCommand(template) {
34
+ console.log(chalk.blue('šŸš€ Initialize Butterbase Project\n'));
35
+ // Get project name
36
+ const { projectName } = await prompts({
37
+ type: 'text',
38
+ name: 'projectName',
39
+ message: 'Project name:',
40
+ initial: 'my-butterbase-app',
41
+ validate: (value) => value.length > 0 || 'Project name is required',
42
+ });
43
+ if (!projectName) {
44
+ console.log(chalk.yellow('Cancelled'));
45
+ process.exit(0);
46
+ }
47
+ // Select template
48
+ if (!template) {
49
+ const { selectedTemplate } = await prompts({
50
+ type: 'select',
51
+ name: 'selectedTemplate',
52
+ message: 'Select a template:',
53
+ choices: [
54
+ { title: 'React + Vite', value: 'react-vite' },
55
+ { title: 'Next.js (coming soon)', value: 'nextjs', disabled: true },
56
+ { title: 'Vue + Vite (coming soon)', value: 'vue-vite', disabled: true },
57
+ ],
58
+ });
59
+ if (!selectedTemplate) {
60
+ console.log(chalk.yellow('Cancelled'));
61
+ process.exit(0);
62
+ }
63
+ template = selectedTemplate;
64
+ }
65
+ // Get Butterbase configuration
66
+ const config = await getMergedConfig();
67
+ const { appId } = await prompts({
68
+ type: 'text',
69
+ name: 'appId',
70
+ message: 'Butterbase App ID (leave empty to create later):',
71
+ initial: config.currentApp || '',
72
+ });
73
+ const apiUrl = config.endpoint || 'http://localhost:4000';
74
+ // Create project directory
75
+ const targetDir = path.join(process.cwd(), projectName);
76
+ if (await fs.pathExists(targetDir)) {
77
+ console.log(chalk.red(`āœ— Directory "${projectName}" already exists`));
78
+ process.exit(1);
79
+ }
80
+ const spinner = ora('Creating project...').start();
81
+ try {
82
+ // Get template directory
83
+ const templateDir = path.join(__dirname, '../../templates', template);
84
+ if (!await fs.pathExists(templateDir)) {
85
+ throw new Error(`Template "${template}" not found`);
86
+ }
87
+ // Create target directory
88
+ await fs.ensureDir(targetDir);
89
+ // Copy template with variable replacement
90
+ const variables = {
91
+ PROJECT_NAME: projectName,
92
+ APP_ID: appId || 'your-app-id',
93
+ API_URL: apiUrl,
94
+ };
95
+ await copyTemplate(templateDir, targetDir, variables);
96
+ // Create .env from .env.example
97
+ const envExamplePath = path.join(targetDir, '.env.example');
98
+ const envPath = path.join(targetDir, '.env');
99
+ if (await fs.pathExists(envExamplePath)) {
100
+ await fs.copy(envExamplePath, envPath);
101
+ }
102
+ spinner.succeed('Project created!');
103
+ console.log(chalk.green('\nāœ“ Project initialized successfully!\n'));
104
+ console.log(chalk.gray('Next steps:\n'));
105
+ console.log(chalk.white(` cd ${projectName}`));
106
+ console.log(chalk.white(` npm install`));
107
+ console.log(chalk.white(` npm run dev`));
108
+ if (!appId) {
109
+ console.log(chalk.yellow('\n⚠ Remember to update .env with your Butterbase App ID'));
110
+ }
111
+ }
112
+ catch (error) {
113
+ spinner.fail('Failed to create project');
114
+ console.error(chalk.red(error.message));
115
+ process.exit(1);
116
+ }
117
+ }
118
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export declare function schemaGetCommand(options: {
2
+ app?: string;
3
+ output?: string;
4
+ }): Promise<void>;
5
+ export declare function schemaApplyCommand(file: string, options: {
6
+ app?: string;
7
+ dryRun?: boolean;
8
+ name?: string;
9
+ }): Promise<void>;
10
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/commands/schema.ts"],"names":[],"mappings":"AAoBA,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,iBAqBhF;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,iBAkChH"}
@@ -0,0 +1,69 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import fs from 'fs-extra';
4
+ import { getSchema, applySchema } from '../lib/api-client.js';
5
+ import { getCurrentAppId } from '../lib/config.js';
6
+ async function requireAppId(appId) {
7
+ if (appId)
8
+ return appId;
9
+ const currentAppId = await getCurrentAppId();
10
+ if (!currentAppId) {
11
+ console.log(chalk.red('āœ— No app specified and no current app set'));
12
+ console.log(chalk.gray('Use: butterbase apps use <app-id>'));
13
+ console.log(chalk.gray('Or: butterbase schema get --app <app-id>'));
14
+ process.exit(1);
15
+ }
16
+ return currentAppId;
17
+ }
18
+ export async function schemaGetCommand(options) {
19
+ const appId = await requireAppId(options.app);
20
+ const spinner = ora('Fetching schema...').start();
21
+ try {
22
+ const response = await getSchema(appId);
23
+ spinner.stop();
24
+ const schemaJson = JSON.stringify(response.schema, null, 2);
25
+ if (options.output) {
26
+ await fs.writeFile(options.output, schemaJson);
27
+ console.log(chalk.green(`āœ“ Schema saved to ${options.output}`));
28
+ }
29
+ else {
30
+ console.log(schemaJson);
31
+ }
32
+ }
33
+ catch (error) {
34
+ spinner.fail('Failed to fetch schema');
35
+ console.error(chalk.red(error.message));
36
+ process.exit(1);
37
+ }
38
+ }
39
+ export async function schemaApplyCommand(file, options) {
40
+ const appId = await requireAppId(options.app);
41
+ if (!await fs.pathExists(file)) {
42
+ console.log(chalk.red(`āœ— File not found: ${file}`));
43
+ process.exit(1);
44
+ }
45
+ const spinner = ora('Reading schema file...').start();
46
+ try {
47
+ const schemaContent = await fs.readFile(file, 'utf-8');
48
+ const schema = JSON.parse(schemaContent);
49
+ spinner.text = options.dryRun ? 'Running dry-run...' : 'Applying schema...';
50
+ const response = await applySchema(appId, schema, options.dryRun, options.name);
51
+ spinner.stop();
52
+ if (options.dryRun) {
53
+ console.log(chalk.blue('\nšŸ“‹ Dry-run results:\n'));
54
+ console.log(JSON.stringify(response, null, 2));
55
+ }
56
+ else {
57
+ console.log(chalk.green('\nāœ“ Schema applied successfully!'));
58
+ if (response.migration_id) {
59
+ console.log(chalk.gray(` Migration ID: ${response.migration_id}`));
60
+ }
61
+ }
62
+ }
63
+ catch (error) {
64
+ spinner.fail(options.dryRun ? 'Dry-run failed' : 'Failed to apply schema');
65
+ console.error(chalk.red(error.message));
66
+ process.exit(1);
67
+ }
68
+ }
69
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/commands/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export declare function storageListCommand(options: {
2
+ app?: string;
3
+ }): Promise<void>;
4
+ export declare function storageUploadCommand(file: string, options: {
5
+ app?: string;
6
+ }): Promise<void>;
7
+ export declare function storageDeleteCommand(objectId: string, options: {
8
+ app?: string;
9
+ }): Promise<void>;
10
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/commands/storage.ts"],"names":[],"mappings":"AAmBA,wBAAsB,kBAAkB,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,iBA0BjE;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,iBAgDjF;AAED,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,iBAmBrF"}
@@ -0,0 +1,105 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import fs from 'fs-extra';
4
+ import { generateUploadUrl, listStorageObjects, deleteStorageObject } from '../lib/api-client.js';
5
+ import { getCurrentAppId } from '../lib/config.js';
6
+ async function requireAppId(appId) {
7
+ if (appId)
8
+ return appId;
9
+ const currentAppId = await getCurrentAppId();
10
+ if (!currentAppId) {
11
+ console.log(chalk.red('āœ— No app specified and no current app set'));
12
+ console.log(chalk.gray('Use: butterbase apps use <app-id>'));
13
+ process.exit(1);
14
+ }
15
+ return currentAppId;
16
+ }
17
+ export async function storageListCommand(options) {
18
+ const appId = await requireAppId(options.app);
19
+ const spinner = ora('Fetching storage objects...').start();
20
+ try {
21
+ const response = await listStorageObjects(appId);
22
+ spinner.stop();
23
+ if (!response.objects || response.objects.length === 0) {
24
+ console.log(chalk.yellow('No files found'));
25
+ return;
26
+ }
27
+ console.log(chalk.blue('\nStorage objects:\n'));
28
+ for (const obj of response.objects) {
29
+ console.log(chalk.bold(obj.filename));
30
+ console.log(chalk.gray(` ID: ${obj.id}`));
31
+ console.log(chalk.gray(` Size: ${(obj.size_bytes / 1024).toFixed(2)} KB`));
32
+ console.log(chalk.gray(` Type: ${obj.content_type}`));
33
+ console.log();
34
+ }
35
+ }
36
+ catch (error) {
37
+ spinner.fail('Failed to fetch storage objects');
38
+ console.error(chalk.red(error.message));
39
+ process.exit(1);
40
+ }
41
+ }
42
+ export async function storageUploadCommand(file, options) {
43
+ const appId = await requireAppId(options.app);
44
+ if (!await fs.pathExists(file)) {
45
+ console.log(chalk.red(`āœ— File not found: ${file}`));
46
+ process.exit(1);
47
+ }
48
+ const spinner = ora('Uploading file...').start();
49
+ try {
50
+ const stats = await fs.stat(file);
51
+ const filename = file.split('/').pop();
52
+ // Detect content type (basic implementation)
53
+ let contentType = 'application/octet-stream';
54
+ if (filename.endsWith('.png'))
55
+ contentType = 'image/png';
56
+ else if (filename.endsWith('.jpg') || filename.endsWith('.jpeg'))
57
+ contentType = 'image/jpeg';
58
+ else if (filename.endsWith('.pdf'))
59
+ contentType = 'application/pdf';
60
+ else if (filename.endsWith('.txt'))
61
+ contentType = 'text/plain';
62
+ // Get presigned upload URL
63
+ const uploadData = await generateUploadUrl(appId, filename, contentType, stats.size);
64
+ // Read file and upload to S3
65
+ const fileBuffer = await fs.readFile(file);
66
+ const uploadResponse = await fetch(uploadData.uploadUrl, {
67
+ method: 'PUT',
68
+ headers: {
69
+ 'Content-Type': contentType,
70
+ },
71
+ body: fileBuffer,
72
+ });
73
+ if (!uploadResponse.ok) {
74
+ throw new Error('Failed to upload file to storage');
75
+ }
76
+ spinner.succeed('File uploaded');
77
+ console.log(chalk.green('\nāœ“ File uploaded successfully!'));
78
+ console.log(chalk.gray(` Object ID: ${uploadData.objectId}`));
79
+ console.log(chalk.gray(` Object Key: ${uploadData.objectKey}`));
80
+ }
81
+ catch (error) {
82
+ spinner.fail('Failed to upload file');
83
+ console.error(chalk.red(error.message));
84
+ process.exit(1);
85
+ }
86
+ }
87
+ export async function storageDeleteCommand(objectId, options) {
88
+ const appId = await requireAppId(options.app);
89
+ if (!objectId) {
90
+ console.log(chalk.red('āœ— Object ID is required'));
91
+ console.log(chalk.gray('Usage: butterbase storage delete <object-id>'));
92
+ process.exit(1);
93
+ }
94
+ const spinner = ora('Deleting object...').start();
95
+ try {
96
+ await deleteStorageObject(appId, objectId);
97
+ spinner.succeed('Object deleted');
98
+ }
99
+ catch (error) {
100
+ spinner.fail('Failed to delete object');
101
+ console.error(chalk.red(error.message));
102
+ process.exit(1);
103
+ }
104
+ }
105
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/commands/storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ export interface ApiError {
2
+ error: string;
3
+ details?: unknown;
4
+ hint?: string;
5
+ }
6
+ /**
7
+ * Make a GET request
8
+ */
9
+ export declare function apiGet<T>(path: string): Promise<T>;
10
+ /**
11
+ * Make a POST request
12
+ */
13
+ export declare function apiPost<T>(path: string, data: unknown): Promise<T>;
14
+ /**
15
+ * Make a PATCH request
16
+ */
17
+ export declare function apiPatch<T>(path: string, data: unknown): Promise<T>;
18
+ /**
19
+ * Make a DELETE request
20
+ */
21
+ export declare function apiDelete<T>(path: string): Promise<T>;
22
+ export declare function initApp(name: string): Promise<unknown>;
23
+ export declare function listApps(): Promise<unknown>;
24
+ export declare function deleteApp(appId: string): Promise<unknown>;
25
+ export declare function getSchema(appId: string): Promise<unknown>;
26
+ export declare function applySchema(appId: string, schema: any, dryRun?: boolean, name?: string): Promise<unknown>;
27
+ export declare function deployFunction(appId: string, data: {
28
+ name: string;
29
+ code: string;
30
+ description?: string;
31
+ envVars?: Record<string, string>;
32
+ timeoutMs?: number;
33
+ memoryLimitMb?: number;
34
+ trigger: {
35
+ type: string;
36
+ config?: any;
37
+ };
38
+ }): Promise<unknown>;
39
+ export declare function listFunctions(appId: string): Promise<unknown>;
40
+ export declare function getFunctionLogs(appId: string, functionName: string, level?: string, limit?: number): Promise<unknown>;
41
+ export declare function generateUploadUrl(appId: string, filename: string, contentType: string, sizeBytes: number): Promise<unknown>;
42
+ export declare function listStorageObjects(appId: string): Promise<unknown>;
43
+ export declare function deleteStorageObject(appId: string, objectId: string): Promise<unknown>;
44
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../../src/lib/api-client.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA0BD;;GAEG;AACH,wBAAsB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAYxD;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAiBxE;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAiBzE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAqB3D;AAID,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,oBAEzC;AAED,wBAAsB,QAAQ,qBAE7B;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,oBAE5C;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,oBAE5C;AAED,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,oBAE5F;AAED,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;CACzC,oBAEA;AAED,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,oBAEhD;AAED,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,oBAMxG;AAED,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,oBAE9G;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,oBAErD;AAED,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,oBAExE"}