@openbuilder/cli 0.31.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.
Files changed (78) hide show
  1. package/README.md +1053 -0
  2. package/bin/openbuilder.js +31 -0
  3. package/dist/chunks/Banner-D4tqKfzA.js +113 -0
  4. package/dist/chunks/Banner-D4tqKfzA.js.map +1 -0
  5. package/dist/chunks/auto-update-Dj3lWPWO.js +350 -0
  6. package/dist/chunks/auto-update-Dj3lWPWO.js.map +1 -0
  7. package/dist/chunks/build-D0qYqIq0.js +116 -0
  8. package/dist/chunks/build-D0qYqIq0.js.map +1 -0
  9. package/dist/chunks/cleanup-qVTsA3tk.js +141 -0
  10. package/dist/chunks/cleanup-qVTsA3tk.js.map +1 -0
  11. package/dist/chunks/cli-error-BjQwvWtK.js +140 -0
  12. package/dist/chunks/cli-error-BjQwvWtK.js.map +1 -0
  13. package/dist/chunks/config-BGP1jZJ4.js +167 -0
  14. package/dist/chunks/config-BGP1jZJ4.js.map +1 -0
  15. package/dist/chunks/config-manager-BkbjtN-H.js +133 -0
  16. package/dist/chunks/config-manager-BkbjtN-H.js.map +1 -0
  17. package/dist/chunks/database-BvAbD4sP.js +68 -0
  18. package/dist/chunks/database-BvAbD4sP.js.map +1 -0
  19. package/dist/chunks/database-setup-BYjIRAmT.js +253 -0
  20. package/dist/chunks/database-setup-BYjIRAmT.js.map +1 -0
  21. package/dist/chunks/exports-ij9sv4UM.js +7793 -0
  22. package/dist/chunks/exports-ij9sv4UM.js.map +1 -0
  23. package/dist/chunks/init-CZoN6soU.js +468 -0
  24. package/dist/chunks/init-CZoN6soU.js.map +1 -0
  25. package/dist/chunks/init-tui-BNzk_7Yx.js +1127 -0
  26. package/dist/chunks/init-tui-BNzk_7Yx.js.map +1 -0
  27. package/dist/chunks/logger-ZpJi7chw.js +38 -0
  28. package/dist/chunks/logger-ZpJi7chw.js.map +1 -0
  29. package/dist/chunks/main-tui-Cq1hLCx-.js +644 -0
  30. package/dist/chunks/main-tui-Cq1hLCx-.js.map +1 -0
  31. package/dist/chunks/manager-CvGX9qqe.js +1161 -0
  32. package/dist/chunks/manager-CvGX9qqe.js.map +1 -0
  33. package/dist/chunks/port-allocator-BRFzgH9b.js +749 -0
  34. package/dist/chunks/port-allocator-BRFzgH9b.js.map +1 -0
  35. package/dist/chunks/process-killer-CaUL7Kpl.js +87 -0
  36. package/dist/chunks/process-killer-CaUL7Kpl.js.map +1 -0
  37. package/dist/chunks/prompts-1QbE_bRr.js +128 -0
  38. package/dist/chunks/prompts-1QbE_bRr.js.map +1 -0
  39. package/dist/chunks/repo-cloner-CpOQjFSo.js +219 -0
  40. package/dist/chunks/repo-cloner-CpOQjFSo.js.map +1 -0
  41. package/dist/chunks/repo-detector-B_oj696o.js +66 -0
  42. package/dist/chunks/repo-detector-B_oj696o.js.map +1 -0
  43. package/dist/chunks/run-D23hg4xy.js +630 -0
  44. package/dist/chunks/run-D23hg4xy.js.map +1 -0
  45. package/dist/chunks/runner-logger-instance-nDWv2h2T.js +899 -0
  46. package/dist/chunks/runner-logger-instance-nDWv2h2T.js.map +1 -0
  47. package/dist/chunks/spinner-BJL9zWAJ.js +53 -0
  48. package/dist/chunks/spinner-BJL9zWAJ.js.map +1 -0
  49. package/dist/chunks/start-BygPCbvw.js +1708 -0
  50. package/dist/chunks/start-BygPCbvw.js.map +1 -0
  51. package/dist/chunks/start-traditional-uoLZXdxm.js +255 -0
  52. package/dist/chunks/start-traditional-uoLZXdxm.js.map +1 -0
  53. package/dist/chunks/status-cS8YwtUx.js +97 -0
  54. package/dist/chunks/status-cS8YwtUx.js.map +1 -0
  55. package/dist/chunks/theme-DhorI2Hb.js +44 -0
  56. package/dist/chunks/theme-DhorI2Hb.js.map +1 -0
  57. package/dist/chunks/upgrade-CT6w0lKp.js +323 -0
  58. package/dist/chunks/upgrade-CT6w0lKp.js.map +1 -0
  59. package/dist/chunks/useBuildState-CdBSu9y_.js +331 -0
  60. package/dist/chunks/useBuildState-CdBSu9y_.js.map +1 -0
  61. package/dist/cli/index.js +694 -0
  62. package/dist/cli/index.js.map +1 -0
  63. package/dist/index.js +14358 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/instrument.js +64226 -0
  66. package/dist/instrument.js.map +1 -0
  67. package/dist/templates.json +295 -0
  68. package/package.json +98 -0
  69. package/scripts/install-vendor-deps.js +34 -0
  70. package/scripts/install-vendor.js +167 -0
  71. package/scripts/prepare-release.js +71 -0
  72. package/templates/config.template.json +18 -0
  73. package/templates.json +295 -0
  74. package/vendor/ai-sdk-provider-claude-code-LOCAL.tgz +0 -0
  75. package/vendor/sentry-core-LOCAL.tgz +0 -0
  76. package/vendor/sentry-nextjs-LOCAL.tgz +0 -0
  77. package/vendor/sentry-node-LOCAL.tgz +0 -0
  78. package/vendor/sentry-node-core-LOCAL.tgz +0 -0
@@ -0,0 +1,133 @@
1
+ // OpenBuilder CLI - Built with Rollup
2
+ import Conf from 'conf';
3
+ import { homedir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { existsSync } from 'node:fs';
6
+
7
+ /**
8
+ * Config manager using conf library
9
+ * Handles platform-specific config locations
10
+ */
11
+ class ConfigManager {
12
+ constructor() {
13
+ this.conf = new Conf({
14
+ projectName: 'openbuilder',
15
+ projectSuffix: '', // No suffix, just 'openbuilder'
16
+ defaults: this.getDefaults(),
17
+ });
18
+ }
19
+ getDefaults() {
20
+ return {
21
+ version: '0.1.0',
22
+ workspace: join(homedir(), 'openbuilder-workspace'),
23
+ apiUrl: 'http://localhost:3000', // Default API URL
24
+ server: {
25
+ wsUrl: 'ws://localhost:3000/ws/runner', // Direct WebSocket connection to Next.js
26
+ secret: 'dev-secret', // Default local secret
27
+ },
28
+ runner: {
29
+ id: 'local',
30
+ reconnectAttempts: 5,
31
+ heartbeatInterval: 15000,
32
+ },
33
+ tunnel: {
34
+ provider: 'cloudflare',
35
+ autoCreate: true,
36
+ },
37
+ };
38
+ }
39
+ get(key) {
40
+ if (!key) {
41
+ return this.conf.store;
42
+ }
43
+ return this.conf.get(key);
44
+ }
45
+ set(key, value) {
46
+ this.conf.set(key, value);
47
+ }
48
+ delete(key) {
49
+ this.conf.delete(key);
50
+ }
51
+ reset() {
52
+ this.conf.clear();
53
+ this.conf.store = this.getDefaults();
54
+ }
55
+ has(key) {
56
+ return this.conf.has(key);
57
+ }
58
+ get path() {
59
+ return this.conf.path;
60
+ }
61
+ validate() {
62
+ const errors = [];
63
+ const config = this.conf.store;
64
+ if (!config.workspace) {
65
+ errors.push('Workspace path is required');
66
+ }
67
+ // Check for server config (new) or legacy broker config
68
+ const hasServerConfig = config.server?.secret && config.server?.wsUrl;
69
+ const hasLegacyBrokerConfig = config.broker?.secret && config.broker?.url;
70
+ if (!hasServerConfig && !hasLegacyBrokerConfig) {
71
+ errors.push('Server shared secret is required');
72
+ errors.push('Server WebSocket URL is required');
73
+ }
74
+ if (!config.runner?.id) {
75
+ errors.push('Runner ID is required');
76
+ }
77
+ // Check if workspace exists
78
+ if (config.workspace && !existsSync(config.workspace)) {
79
+ errors.push(`Workspace directory does not exist: ${config.workspace}`);
80
+ }
81
+ return {
82
+ valid: errors.length === 0,
83
+ errors,
84
+ };
85
+ }
86
+ /**
87
+ * Check if config has been initialized properly
88
+ * Requires monorepo to be cloned and databaseUrl to be configured
89
+ */
90
+ isInitialized() {
91
+ const monorepoPath = this.get('monorepoPath');
92
+ const databaseUrl = this.get('databaseUrl');
93
+ // Must have monorepo path set and the directory must exist
94
+ if (!monorepoPath || !existsSync(monorepoPath)) {
95
+ return false;
96
+ }
97
+ // Must have database URL configured
98
+ if (!databaseUrl) {
99
+ return false;
100
+ }
101
+ return true;
102
+ }
103
+ /**
104
+ * Get the WebSocket URL (supports both new and legacy config)
105
+ */
106
+ getWsUrl() {
107
+ const server = this.get('server');
108
+ const broker = this.get('broker');
109
+ // Prefer new server config
110
+ if (server?.wsUrl) {
111
+ return server.wsUrl;
112
+ }
113
+ // Fall back to legacy broker URL
114
+ return broker?.url ?? 'ws://localhost:3000/ws/runner';
115
+ }
116
+ /**
117
+ * Get the shared secret (supports both new and legacy config)
118
+ */
119
+ getSecret() {
120
+ const server = this.get('server');
121
+ const broker = this.get('broker');
122
+ // Prefer new server config
123
+ if (server?.secret) {
124
+ return server.secret;
125
+ }
126
+ // Fall back to legacy broker secret
127
+ return broker?.secret ?? '';
128
+ }
129
+ }
130
+ const configManager = new ConfigManager();
131
+
132
+ export { configManager as c };
133
+ //# sourceMappingURL=config-manager-BkbjtN-H.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-manager-BkbjtN-H.js","sources":["../../src/cli/utils/config-manager.ts"],"sourcesContent":["import Conf from 'conf';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { existsSync } from 'node:fs';\n\n// Theme names for the TUI\nexport type ThemeName = 'sentry' | 'ocean' | 'ember' | 'forest' | 'noir';\n\nexport interface RunnerConfig {\n version: string;\n workspace: string;\n monorepoPath?: string; // Path to cloned openbuilder repository\n databaseUrl?: string; // PostgreSQL connection string\n apiUrl?: string; // API base URL (e.g., http://localhost:3000)\n autoUpdate?: boolean; // Enable automatic CLI updates (default: true)\n // Server connection config (formerly \"broker\" - now connects directly to Next.js)\n server: {\n wsUrl: string; // WebSocket URL (e.g., ws://localhost:3000/ws/runner)\n secret: string;\n };\n // Legacy broker config for backward compatibility\n broker?: {\n url: string;\n httpUrl?: string;\n secret: string;\n };\n runner: {\n id: string; // This runner's ID and default ID for web app in local mode\n lastRunnerId?: string; // Last used runner ID (for runner mode)\n reconnectAttempts?: number;\n heartbeatInterval?: number;\n };\n tunnel?: {\n provider: 'cloudflare';\n autoCreate: boolean;\n };\n // TUI preferences\n ui?: {\n theme: ThemeName;\n };\n}\n\n/**\n * Config manager using conf library\n * Handles platform-specific config locations\n */\nexport class ConfigManager {\n private conf: Conf<RunnerConfig>;\n\n constructor() {\n this.conf = new Conf<RunnerConfig>({\n projectName: 'openbuilder',\n projectSuffix: '', // No suffix, just 'openbuilder'\n defaults: this.getDefaults(),\n });\n }\n\n private getDefaults(): RunnerConfig {\n return {\n version: '0.1.0',\n workspace: join(homedir(), 'openbuilder-workspace'),\n apiUrl: 'http://localhost:3000', // Default API URL\n server: {\n wsUrl: 'ws://localhost:3000/ws/runner', // Direct WebSocket connection to Next.js\n secret: 'dev-secret', // Default local secret\n },\n runner: {\n id: 'local',\n reconnectAttempts: 5,\n heartbeatInterval: 15000,\n },\n tunnel: {\n provider: 'cloudflare',\n autoCreate: true,\n },\n };\n }\n\n get(key?: keyof RunnerConfig): any {\n if (!key) {\n return this.conf.store;\n }\n return this.conf.get(key);\n }\n\n set(key: keyof RunnerConfig | string, value: any): void {\n this.conf.set(key as any, value);\n }\n\n delete(key: keyof RunnerConfig): void {\n this.conf.delete(key);\n }\n\n reset(): void {\n this.conf.clear();\n this.conf.store = this.getDefaults();\n }\n\n has(key: keyof RunnerConfig): boolean {\n return this.conf.has(key);\n }\n\n get path(): string {\n return this.conf.path;\n }\n\n validate(): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n const config = this.conf.store;\n\n if (!config.workspace) {\n errors.push('Workspace path is required');\n }\n\n // Check for server config (new) or legacy broker config\n const hasServerConfig = config.server?.secret && config.server?.wsUrl;\n const hasLegacyBrokerConfig = config.broker?.secret && config.broker?.url;\n \n if (!hasServerConfig && !hasLegacyBrokerConfig) {\n errors.push('Server shared secret is required');\n errors.push('Server WebSocket URL is required');\n }\n\n if (!config.runner?.id) {\n errors.push('Runner ID is required');\n }\n\n // Check if workspace exists\n if (config.workspace && !existsSync(config.workspace)) {\n errors.push(`Workspace directory does not exist: ${config.workspace}`);\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n\n /**\n * Check if config has been initialized properly\n * Requires monorepo to be cloned and databaseUrl to be configured\n */\n isInitialized(): boolean {\n const monorepoPath = this.get('monorepoPath');\n const databaseUrl = this.get('databaseUrl');\n \n // Must have monorepo path set and the directory must exist\n if (!monorepoPath || !existsSync(monorepoPath)) {\n return false;\n }\n \n // Must have database URL configured\n if (!databaseUrl) {\n return false;\n }\n \n return true;\n }\n \n /**\n * Get the WebSocket URL (supports both new and legacy config)\n */\n getWsUrl(): string {\n const server = this.get('server');\n const broker = this.get('broker');\n \n // Prefer new server config\n if (server?.wsUrl) {\n return server.wsUrl;\n }\n \n // Fall back to legacy broker URL\n return broker?.url ?? 'ws://localhost:3000/ws/runner';\n }\n \n /**\n * Get the shared secret (supports both new and legacy config)\n */\n getSecret(): string {\n const server = this.get('server');\n const broker = this.get('broker');\n \n // Prefer new server config\n if (server?.secret) {\n return server.secret;\n }\n \n // Fall back to legacy broker secret\n return broker?.secret ?? '';\n }\n}\n\nexport const configManager = new ConfigManager();\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ // OpenBuilder CLI - Built with Rollup
2
+ import chalk from 'chalk';
3
+ import { l as logger } from './logger-ZpJi7chw.js';
4
+ import { c as configManager } from './config-manager-BkbjtN-H.js';
5
+ import { s as setupDatabase, p as pushDatabaseSchema } from './database-setup-BYjIRAmT.js';
6
+ import 'conf';
7
+ import 'node:os';
8
+ import 'node:path';
9
+ import 'node:fs';
10
+ import 'node:child_process';
11
+ import 'node:fs/promises';
12
+ import './spinner-BJL9zWAJ.js';
13
+ import 'ora';
14
+ import './prompts-1QbE_bRr.js';
15
+ import 'inquirer';
16
+
17
+ async function databaseCommand() {
18
+ logger.section('Database Setup');
19
+ logger.log('');
20
+ // Check if monorepo is configured
21
+ const config = configManager.get();
22
+ const monorepoPath = config.monorepoPath;
23
+ if (!monorepoPath) {
24
+ logger.error('Monorepo path not found in config');
25
+ logger.info('Run "openbuilder init" first to set up the repository');
26
+ process.exit(1);
27
+ }
28
+ // Step 1: Setup new database
29
+ logger.info('Setting up new Neon PostgreSQL database...');
30
+ logger.log('');
31
+ const databaseUrl = await setupDatabase(monorepoPath);
32
+ if (!databaseUrl) {
33
+ logger.error('Failed to create database');
34
+ logger.log('');
35
+ logger.info('You can manually set a database URL with:');
36
+ logger.log(` ${chalk.cyan('openbuilder config set databaseUrl <url>')}`);
37
+ process.exit(1);
38
+ }
39
+ logger.log('');
40
+ logger.success('Database created!');
41
+ logger.info(`Connection string saved to config`);
42
+ logger.log('');
43
+ // Save to config
44
+ configManager.set('databaseUrl', databaseUrl);
45
+ // Step 2: Push schema
46
+ logger.info('Initializing database schema...');
47
+ logger.log('');
48
+ const pushed = await pushDatabaseSchema(monorepoPath, databaseUrl);
49
+ if (!pushed) {
50
+ logger.warn('Failed to push database schema');
51
+ logger.log('');
52
+ logger.info('You can try manually:');
53
+ logger.log(` ${chalk.cyan('cd apps/openbuilder')}`);
54
+ logger.log(` ${chalk.cyan('npx drizzle-kit push --config=drizzle.config.ts')}`);
55
+ logger.log('');
56
+ process.exit(1);
57
+ }
58
+ // Success!
59
+ logger.log('');
60
+ logger.success('Database setup complete! 🎉');
61
+ logger.log('');
62
+ logger.info('Database is ready for use');
63
+ logger.info(`You can now run: ${chalk.cyan('openbuilder run')}`);
64
+ logger.log('');
65
+ }
66
+
67
+ export { databaseCommand };
68
+ //# sourceMappingURL=database-BvAbD4sP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-BvAbD4sP.js","sources":["../../src/cli/commands/database.ts"],"sourcesContent":["import chalk from 'chalk';\nimport { logger } from '../utils/logger.js';\nimport { configManager } from '../utils/config-manager.js';\nimport { setupDatabase, pushDatabaseSchema } from '../utils/database-setup.js';\nimport { prompts } from '../utils/prompts.js';\n\nexport async function databaseCommand() {\n logger.section('Database Setup');\n logger.log('');\n\n // Check if monorepo is configured\n const config = configManager.get();\n const monorepoPath = config.monorepoPath;\n\n if (!monorepoPath) {\n logger.error('Monorepo path not found in config');\n logger.info('Run \"openbuilder init\" first to set up the repository');\n process.exit(1);\n }\n\n // Step 1: Setup new database\n logger.info('Setting up new Neon PostgreSQL database...');\n logger.log('');\n\n const databaseUrl = await setupDatabase(monorepoPath);\n\n if (!databaseUrl) {\n logger.error('Failed to create database');\n logger.log('');\n logger.info('You can manually set a database URL with:');\n logger.log(` ${chalk.cyan('openbuilder config set databaseUrl <url>')}`);\n process.exit(1);\n }\n\n logger.log('');\n logger.success('Database created!');\n logger.info(`Connection string saved to config`);\n logger.log('');\n\n // Save to config\n configManager.set('databaseUrl', databaseUrl);\n\n // Step 2: Push schema\n logger.info('Initializing database schema...');\n logger.log('');\n\n const pushed = await pushDatabaseSchema(monorepoPath, databaseUrl);\n\n if (!pushed) {\n logger.warn('Failed to push database schema');\n logger.log('');\n logger.info('You can try manually:');\n logger.log(` ${chalk.cyan('cd apps/openbuilder')}`);\n logger.log(` ${chalk.cyan('npx drizzle-kit push --config=drizzle.config.ts')}`);\n logger.log('');\n process.exit(1);\n }\n\n // Success!\n logger.log('');\n logger.success('Database setup complete! 🎉');\n logger.log('');\n logger.info('Database is ready for use');\n logger.info(`You can now run: ${chalk.cyan('openbuilder run')}`);\n logger.log('');\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAMO,eAAe,eAAe,GAAA;AACnC,IAAA,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC;AAChC,IAAA,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;;AAGd,IAAA,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,EAAE;AAClC,IAAA,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY;IAExC,IAAI,CAAC,YAAY,EAAE;AACjB,QAAA,MAAM,CAAC,KAAK,CAAC,mCAAmC,CAAC;AACjD,QAAA,MAAM,CAAC,IAAI,CAAC,uDAAuD,CAAC;AACpE,QAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACjB;;AAGA,IAAA,MAAM,CAAC,IAAI,CAAC,4CAA4C,CAAC;AACzD,IAAA,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AAEd,IAAA,MAAM,WAAW,GAAG,MAAM,aAAa,CAAC,YAAY,CAAC;IAErD,IAAI,CAAC,WAAW,EAAE;AAChB,QAAA,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC;AACzC,QAAA,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AACd,QAAA,MAAM,CAAC,IAAI,CAAC,2CAA2C,CAAC;AACxD,QAAA,MAAM,CAAC,GAAG,CAAC,CAAA,EAAA,EAAK,KAAK,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAA,CAAE,CAAC;AACzE,QAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACjB;AAEA,IAAA,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AACd,IAAA,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC;AACnC,IAAA,MAAM,CAAC,IAAI,CAAC,CAAA,iCAAA,CAAmC,CAAC;AAChD,IAAA,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;;AAGd,IAAA,aAAa,CAAC,GAAG,CAAC,aAAa,EAAE,WAAW,CAAC;;AAG7C,IAAA,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC;AAC9C,IAAA,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IAEd,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,YAAY,EAAE,WAAW,CAAC;IAElE,IAAI,CAAC,MAAM,EAAE;AACX,QAAA,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC;AAC7C,QAAA,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AACd,QAAA,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC;AACpC,QAAA,MAAM,CAAC,GAAG,CAAC,CAAA,EAAA,EAAK,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA,CAAE,CAAC;AACpD,QAAA,MAAM,CAAC,GAAG,CAAC,CAAA,EAAA,EAAK,KAAK,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAA,CAAE,CAAC;AAChF,QAAA,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AACd,QAAA,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACjB;;AAGA,IAAA,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AACd,IAAA,MAAM,CAAC,OAAO,CAAC,6BAA6B,CAAC;AAC7C,IAAA,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AACd,IAAA,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC;AACxC,IAAA,MAAM,CAAC,IAAI,CAAC,CAAA,iBAAA,EAAoB,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA,CAAE,CAAC;AAChE,IAAA,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AAChB;;;;"}
@@ -0,0 +1,253 @@
1
+ // OpenBuilder CLI - Built with Rollup
2
+ import { spawn, execFileSync } from 'node:child_process';
3
+ import { readFile, writeFile } from 'node:fs/promises';
4
+ import { existsSync } from 'node:fs';
5
+ import { join } from 'node:path';
6
+ import { l as logger } from './logger-ZpJi7chw.js';
7
+ import { s as spinner } from './spinner-BJL9zWAJ.js';
8
+ import { p as prompts } from './prompts-1QbE_bRr.js';
9
+
10
+ /**
11
+ * Read DATABASE_URL from .env file in monorepo root
12
+ */
13
+ async function readDatabaseUrlFromEnv(monorepoPath) {
14
+ const envPath = join(monorepoPath, '.env');
15
+ if (!existsSync(envPath)) {
16
+ return null;
17
+ }
18
+ try {
19
+ const content = await readFile(envPath, 'utf-8');
20
+ const match = content.match(/^DATABASE_URL\s*=\s*['"]?([^'"\n]+)['"]?/m);
21
+ return match ? match[1] : null;
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ }
27
+ /**
28
+ * Clear DATABASE_URL from .env file (removes stale value)
29
+ */
30
+ async function clearDatabaseUrlFromEnv(monorepoPath) {
31
+ const envPath = join(monorepoPath, '.env');
32
+ if (!existsSync(envPath)) {
33
+ return;
34
+ }
35
+ try {
36
+ const content = await readFile(envPath, 'utf-8');
37
+ const updated = content
38
+ .split('\n')
39
+ .filter(line => !line.trim().startsWith('DATABASE_URL'))
40
+ .join('\n');
41
+ await writeFile(envPath, updated, 'utf-8');
42
+ }
43
+ catch (error) {
44
+ logger.warn('Could not clear DATABASE_URL from .env');
45
+ }
46
+ }
47
+ /**
48
+ * Run neondb setup to create a database and get the connection string
49
+ * Returns the DATABASE_URL if successful
50
+ */
51
+ async function setupDatabase(monorepoPath, silent = false) {
52
+ // Clear any stale DATABASE_URL first
53
+ await clearDatabaseUrlFromEnv(monorepoPath);
54
+ if (!silent) {
55
+ spinner.start('Setting up Neon PostgreSQL database...');
56
+ }
57
+ return new Promise((resolve) => {
58
+ const proc = spawn('npx', ['neondb', '-y'], {
59
+ cwd: monorepoPath, // Run in monorepo root so .env is created there
60
+ stdio: ['ignore', 'pipe', 'pipe'],
61
+ shell: true,
62
+ });
63
+ let databaseUrl = null;
64
+ proc.stdout?.on('data', (data) => {
65
+ const text = data.toString();
66
+ // Look for DATABASE_URL in the output
67
+ const match = text.match(/DATABASE_URL[=:]?\s*['"]?([^'"\s]+)['"]?/);
68
+ if (match && match[1]) {
69
+ databaseUrl = match[1];
70
+ }
71
+ // Also check for postgres:// connection strings
72
+ const connMatch = text.match(/(postgres(?:ql)?:\/\/[^\s'"]+)/);
73
+ if (connMatch && connMatch[1]) {
74
+ databaseUrl = connMatch[1];
75
+ }
76
+ });
77
+ proc.stderr?.on('data', (data) => {
78
+ const text = data.toString();
79
+ // Only log actual errors (and only if not silent)
80
+ if (!silent && (text.includes('error') || text.includes('Error'))) {
81
+ logger.debug(text.trim());
82
+ }
83
+ });
84
+ proc.on('exit', async (code) => {
85
+ if (code === 0) {
86
+ // Try to read DATABASE_URL from .env file (neondb writes it there)
87
+ const urlFromEnv = await readDatabaseUrlFromEnv(monorepoPath);
88
+ if (urlFromEnv) {
89
+ databaseUrl = urlFromEnv;
90
+ if (!silent) {
91
+ spinner.succeed('Database created successfully');
92
+ }
93
+ resolve(databaseUrl);
94
+ }
95
+ else if (databaseUrl) {
96
+ // Fallback to what we parsed from output
97
+ if (!silent) {
98
+ spinner.succeed('Database created successfully');
99
+ }
100
+ resolve(databaseUrl);
101
+ }
102
+ else {
103
+ if (!silent) {
104
+ spinner.warn('Database command completed but DATABASE_URL not found');
105
+ logger.info('Check .env file in monorepo root for DATABASE_URL');
106
+ }
107
+ resolve(null);
108
+ }
109
+ }
110
+ else {
111
+ if (!silent) {
112
+ spinner.fail('Failed to create database');
113
+ }
114
+ resolve(null);
115
+ }
116
+ });
117
+ proc.on('error', (error) => {
118
+ if (!silent) {
119
+ spinner.fail('Failed to run neondb');
120
+ logger.error(`Error: ${error.message}`);
121
+ }
122
+ resolve(null);
123
+ });
124
+ });
125
+ }
126
+ /**
127
+ * Push database schema using drizzle-kit
128
+ */
129
+ async function pushDatabaseSchema(monorepoPath, databaseUrl, silent = false) {
130
+ const { join } = await import('path');
131
+ const { existsSync } = await import('fs');
132
+ const openbuilderAppPath = join(monorepoPath, 'apps/openbuilder');
133
+ const configPath = join(openbuilderAppPath, 'drizzle.config.ts');
134
+ // Verify paths exist
135
+ if (!existsSync(openbuilderAppPath)) {
136
+ if (!silent) {
137
+ logger.error(`Directory not found: ${openbuilderAppPath}`);
138
+ }
139
+ return false;
140
+ }
141
+ if (!existsSync(configPath)) {
142
+ if (!silent) {
143
+ logger.error(`Drizzle config not found: ${configPath}`);
144
+ }
145
+ return false;
146
+ }
147
+ if (!silent) {
148
+ spinner.start('Ensuring openbuilder dependencies are installed...');
149
+ }
150
+ try {
151
+ execFileSync('pnpm', ['install'], {
152
+ cwd: openbuilderAppPath,
153
+ stdio: 'pipe',
154
+ });
155
+ execFileSync('pnpm', ['--filter', '@openbuilder/agent-core', 'build'], {
156
+ cwd: monorepoPath,
157
+ stdio: 'pipe',
158
+ });
159
+ if (!silent) {
160
+ spinner.succeed('Dependencies ready');
161
+ }
162
+ }
163
+ catch (error) {
164
+ if (!silent) {
165
+ spinner.warn('Dependency installation failed, trying schema push anyway');
166
+ }
167
+ }
168
+ if (!silent) {
169
+ spinner.start('Initializing database schema (this may take a moment)...');
170
+ }
171
+ return new Promise((resolve) => {
172
+ const proc = spawn('npx', ['drizzle-kit', 'push', '--config=drizzle.config.ts'], {
173
+ cwd: openbuilderAppPath,
174
+ stdio: ['ignore', 'pipe', 'pipe'],
175
+ shell: true,
176
+ env: {
177
+ ...process.env,
178
+ DATABASE_URL: databaseUrl, // Ensure drizzle-kit has access
179
+ },
180
+ });
181
+ let allOutput = '';
182
+ // Capture all output for debugging
183
+ proc.stdout?.on('data', (data) => {
184
+ allOutput += data.toString();
185
+ });
186
+ proc.stderr?.on('data', (data) => {
187
+ allOutput += data.toString();
188
+ });
189
+ proc.on('exit', (code) => {
190
+ if (code === 0) {
191
+ if (!silent) {
192
+ spinner.succeed('Database schema initialized successfully');
193
+ }
194
+ resolve(true);
195
+ }
196
+ else {
197
+ if (!silent) {
198
+ spinner.fail('Failed to push database schema');
199
+ // Show all output when it fails so user can see what went wrong
200
+ if (allOutput.trim()) {
201
+ logger.log(''); // Blank line
202
+ logger.log('Output from drizzle-kit push:');
203
+ logger.log(allOutput.trim());
204
+ logger.log(''); // Blank line
205
+ }
206
+ }
207
+ resolve(false);
208
+ }
209
+ });
210
+ proc.on('error', (error) => {
211
+ if (!silent) {
212
+ spinner.fail('Failed to run drizzle-kit');
213
+ logger.error(`Error: ${error.message}`);
214
+ }
215
+ resolve(false);
216
+ });
217
+ });
218
+ }
219
+ /**
220
+ * Connect to an existing database manually by prompting for connection string
221
+ */
222
+ async function connectManualDatabase() {
223
+ logger.log('');
224
+ // Ask user what type of connection they want
225
+ const connectionType = await prompts.select('How would you like to connect your database?', [
226
+ 'Connect an existing OpenBuilder database',
227
+ 'Provide a connection string directly',
228
+ ]);
229
+ logger.log('');
230
+ // Prompt for the connection string
231
+ let message;
232
+ if (connectionType === 'Connect an existing OpenBuilder database') {
233
+ message = 'Enter your OpenBuilder database connection string:';
234
+ }
235
+ else {
236
+ message = 'Enter your PostgreSQL connection string:';
237
+ }
238
+ const connectionString = await prompts.input(message);
239
+ // Basic validation
240
+ if (!connectionString || connectionString.trim() === '') {
241
+ logger.error('Connection string cannot be empty');
242
+ return null;
243
+ }
244
+ // Validate it looks like a PostgreSQL connection string
245
+ if (!connectionString.match(/^postgres(?:ql)?:\/\//)) {
246
+ logger.error('Connection string must start with postgres:// or postgresql://');
247
+ return null;
248
+ }
249
+ return connectionString.trim();
250
+ }
251
+
252
+ export { connectManualDatabase as c, pushDatabaseSchema as p, setupDatabase as s };
253
+ //# sourceMappingURL=database-setup-BYjIRAmT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-setup-BYjIRAmT.js","sources":["../../src/cli/utils/database-setup.ts"],"sourcesContent":["import { spawn, execFileSync } from 'node:child_process';\nimport { readFile, writeFile } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { logger } from './logger.js';\nimport { spinner } from './spinner.js';\nimport { prompts } from './prompts.js';\n\n/**\n * Read DATABASE_URL from .env file in monorepo root\n */\nexport async function readDatabaseUrlFromEnv(monorepoPath: string): Promise<string | null> {\n const envPath = join(monorepoPath, '.env');\n\n if (!existsSync(envPath)) {\n return null;\n }\n\n try {\n const content = await readFile(envPath, 'utf-8');\n const match = content.match(/^DATABASE_URL\\s*=\\s*['\"]?([^'\"\\n]+)['\"]?/m);\n return match ? match[1] : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Clear DATABASE_URL from .env file (removes stale value)\n */\nexport async function clearDatabaseUrlFromEnv(monorepoPath: string): Promise<void> {\n const envPath = join(monorepoPath, '.env');\n\n if (!existsSync(envPath)) {\n return;\n }\n\n try {\n const content = await readFile(envPath, 'utf-8');\n const updated = content\n .split('\\n')\n .filter(line => !line.trim().startsWith('DATABASE_URL'))\n .join('\\n');\n await writeFile(envPath, updated, 'utf-8');\n } catch (error) {\n logger.warn('Could not clear DATABASE_URL from .env');\n }\n}\n\n/**\n * Run neondb setup to create a database and get the connection string\n * Returns the DATABASE_URL if successful\n */\nexport async function setupDatabase(monorepoPath: string, silent: boolean = false): Promise<string | null> {\n // Clear any stale DATABASE_URL first\n await clearDatabaseUrlFromEnv(monorepoPath);\n\n if (!silent) {\n spinner.start('Setting up Neon PostgreSQL database...');\n }\n\n return new Promise((resolve) => {\n const proc = spawn('npx', ['neondb', '-y'], {\n cwd: monorepoPath, // Run in monorepo root so .env is created there\n stdio: ['ignore', 'pipe', 'pipe'],\n shell: true,\n });\n\n let databaseUrl: string | null = null;\n let output = '';\n\n proc.stdout?.on('data', (data) => {\n const text = data.toString();\n output += text;\n\n // Look for DATABASE_URL in the output\n const match = text.match(/DATABASE_URL[=:]?\\s*['\"]?([^'\"\\s]+)['\"]?/);\n if (match && match[1]) {\n databaseUrl = match[1];\n }\n\n // Also check for postgres:// connection strings\n const connMatch = text.match(/(postgres(?:ql)?:\\/\\/[^\\s'\"]+)/);\n if (connMatch && connMatch[1]) {\n databaseUrl = connMatch[1];\n }\n });\n\n proc.stderr?.on('data', (data) => {\n const text = data.toString();\n // Only log actual errors (and only if not silent)\n if (!silent && (text.includes('error') || text.includes('Error'))) {\n logger.debug(text.trim());\n }\n });\n\n proc.on('exit', async (code) => {\n if (code === 0) {\n // Try to read DATABASE_URL from .env file (neondb writes it there)\n const urlFromEnv = await readDatabaseUrlFromEnv(monorepoPath);\n\n if (urlFromEnv) {\n databaseUrl = urlFromEnv;\n if (!silent) {\n spinner.succeed('Database created successfully');\n }\n resolve(databaseUrl);\n } else if (databaseUrl) {\n // Fallback to what we parsed from output\n if (!silent) {\n spinner.succeed('Database created successfully');\n }\n resolve(databaseUrl);\n } else {\n if (!silent) {\n spinner.warn('Database command completed but DATABASE_URL not found');\n logger.info('Check .env file in monorepo root for DATABASE_URL');\n }\n resolve(null);\n }\n } else {\n if (!silent) {\n spinner.fail('Failed to create database');\n }\n resolve(null);\n }\n });\n\n proc.on('error', (error) => {\n if (!silent) {\n spinner.fail('Failed to run neondb');\n logger.error(`Error: ${error.message}`);\n }\n resolve(null);\n });\n });\n}\n\n/**\n * Check if neondb is available\n */\nexport async function isNeondbAvailable(): Promise<boolean> {\n return new Promise((resolve) => {\n const proc = spawn('npx', ['neondb', '--version'], {\n stdio: 'ignore',\n shell: true,\n });\n\n proc.on('exit', (code) => {\n resolve(code === 0);\n });\n\n proc.on('error', () => {\n resolve(false);\n });\n });\n}\n\n/**\n * Push database schema using drizzle-kit\n */\nexport async function pushDatabaseSchema(monorepoPath: string, databaseUrl: string, silent: boolean = false): Promise<boolean> {\n const { join } = await import('path');\n const { existsSync } = await import('fs');\n\n const openbuilderAppPath = join(monorepoPath, 'apps/openbuilder');\n const configPath = join(openbuilderAppPath, 'drizzle.config.ts');\n\n // Verify paths exist\n if (!existsSync(openbuilderAppPath)) {\n if (!silent) {\n logger.error(`Directory not found: ${openbuilderAppPath}`);\n }\n return false;\n }\n\n if (!existsSync(configPath)) {\n if (!silent) {\n logger.error(`Drizzle config not found: ${configPath}`);\n }\n return false;\n }\n\n if (!silent) {\n spinner.start('Ensuring openbuilder dependencies are installed...');\n }\n\n try {\n execFileSync('pnpm', ['install'], {\n cwd: openbuilderAppPath,\n stdio: 'pipe',\n });\n execFileSync('pnpm', ['--filter', '@openbuilder/agent-core', 'build'], {\n cwd: monorepoPath,\n stdio: 'pipe',\n });\n if (!silent) {\n spinner.succeed('Dependencies ready');\n }\n } catch (error) {\n if (!silent) {\n spinner.warn('Dependency installation failed, trying schema push anyway');\n }\n }\n\n if (!silent) {\n spinner.start('Initializing database schema (this may take a moment)...');\n }\n\n return new Promise((resolve) => {\n const proc = spawn('npx', ['drizzle-kit', 'push', '--config=drizzle.config.ts'], {\n cwd: openbuilderAppPath,\n stdio: ['ignore', 'pipe', 'pipe'],\n shell: true,\n env: {\n ...process.env,\n DATABASE_URL: databaseUrl, // Ensure drizzle-kit has access\n },\n });\n\n let allOutput = '';\n\n // Capture all output for debugging\n proc.stdout?.on('data', (data) => {\n allOutput += data.toString();\n });\n\n proc.stderr?.on('data', (data) => {\n allOutput += data.toString();\n });\n\n proc.on('exit', (code) => {\n if (code === 0) {\n if (!silent) {\n spinner.succeed('Database schema initialized successfully');\n }\n resolve(true);\n } else {\n if (!silent) {\n spinner.fail('Failed to push database schema');\n // Show all output when it fails so user can see what went wrong\n if (allOutput.trim()) {\n logger.log(''); // Blank line\n logger.log('Output from drizzle-kit push:');\n logger.log(allOutput.trim());\n logger.log(''); // Blank line\n }\n }\n resolve(false);\n }\n });\n\n proc.on('error', (error) => {\n if (!silent) {\n spinner.fail('Failed to run drizzle-kit');\n logger.error(`Error: ${error.message}`);\n }\n resolve(false);\n });\n });\n}\n\n/**\n * Connect to an existing database manually by prompting for connection string\n */\nexport async function connectManualDatabase(): Promise<string | null> {\n logger.log('');\n\n // Ask user what type of connection they want\n const connectionType = await prompts.select(\n 'How would you like to connect your database?',\n [\n 'Connect an existing OpenBuilder database',\n 'Provide a connection string directly',\n ]\n );\n\n logger.log('');\n\n // Prompt for the connection string\n let message: string;\n if (connectionType === 'Connect an existing OpenBuilder database') {\n message = 'Enter your OpenBuilder database connection string:';\n } else {\n message = 'Enter your PostgreSQL connection string:';\n }\n\n const connectionString = await prompts.input(message);\n\n // Basic validation\n if (!connectionString || connectionString.trim() === '') {\n logger.error('Connection string cannot be empty');\n return null;\n }\n\n // Validate it looks like a PostgreSQL connection string\n if (!connectionString.match(/^postgres(?:ql)?:\\/\\//)) {\n logger.error('Connection string must start with postgres:// or postgresql://');\n return null;\n }\n\n return connectionString.trim();\n}\n"],"names":[],"mappings":"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"}