@rulebricks/cli 1.9.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 (93) hide show
  1. package/README.md +62 -0
  2. package/dist/commands/clone.d.ts +6 -0
  3. package/dist/commands/clone.js +60 -0
  4. package/dist/commands/deploy.d.ts +8 -0
  5. package/dist/commands/deploy.js +409 -0
  6. package/dist/commands/destroy.d.ts +8 -0
  7. package/dist/commands/destroy.js +298 -0
  8. package/dist/commands/init.d.ts +7 -0
  9. package/dist/commands/init.js +201 -0
  10. package/dist/commands/logs.d.ts +9 -0
  11. package/dist/commands/logs.js +222 -0
  12. package/dist/commands/open.d.ts +7 -0
  13. package/dist/commands/open.js +139 -0
  14. package/dist/commands/status.d.ts +5 -0
  15. package/dist/commands/status.js +125 -0
  16. package/dist/commands/upgrade.d.ts +7 -0
  17. package/dist/commands/upgrade.js +239 -0
  18. package/dist/components/DNSWaitScreen.d.ts +9 -0
  19. package/dist/components/DNSWaitScreen.js +73 -0
  20. package/dist/components/Wizard/WizardContext.d.ts +176 -0
  21. package/dist/components/Wizard/WizardContext.js +346 -0
  22. package/dist/components/Wizard/index.d.ts +2 -0
  23. package/dist/components/Wizard/index.js +2 -0
  24. package/dist/components/Wizard/steps/CloudProviderStep.d.ts +6 -0
  25. package/dist/components/Wizard/steps/CloudProviderStep.js +210 -0
  26. package/dist/components/Wizard/steps/CredentialsStep.d.ts +6 -0
  27. package/dist/components/Wizard/steps/CredentialsStep.js +22 -0
  28. package/dist/components/Wizard/steps/DatabaseStep.d.ts +6 -0
  29. package/dist/components/Wizard/steps/DatabaseStep.js +80 -0
  30. package/dist/components/Wizard/steps/DeploymentModeStep.d.ts +5 -0
  31. package/dist/components/Wizard/steps/DeploymentModeStep.js +26 -0
  32. package/dist/components/Wizard/steps/DomainStep.d.ts +6 -0
  33. package/dist/components/Wizard/steps/DomainStep.js +126 -0
  34. package/dist/components/Wizard/steps/FeatureConfigStep.d.ts +6 -0
  35. package/dist/components/Wizard/steps/FeatureConfigStep.js +765 -0
  36. package/dist/components/Wizard/steps/FeaturesStep.d.ts +6 -0
  37. package/dist/components/Wizard/steps/FeaturesStep.js +119 -0
  38. package/dist/components/Wizard/steps/ReviewStep.d.ts +6 -0
  39. package/dist/components/Wizard/steps/ReviewStep.js +56 -0
  40. package/dist/components/Wizard/steps/SMTPStep.d.ts +6 -0
  41. package/dist/components/Wizard/steps/SMTPStep.js +191 -0
  42. package/dist/components/Wizard/steps/SupabaseCredentialsStep.d.ts +6 -0
  43. package/dist/components/Wizard/steps/SupabaseCredentialsStep.js +76 -0
  44. package/dist/components/Wizard/steps/TierStep.d.ts +6 -0
  45. package/dist/components/Wizard/steps/TierStep.js +29 -0
  46. package/dist/components/Wizard/steps/VersionStep.d.ts +6 -0
  47. package/dist/components/Wizard/steps/VersionStep.js +113 -0
  48. package/dist/components/Wizard/steps/index.d.ts +12 -0
  49. package/dist/components/Wizard/steps/index.js +12 -0
  50. package/dist/components/common/AppShell.d.ts +31 -0
  51. package/dist/components/common/AppShell.js +31 -0
  52. package/dist/components/common/Box.d.ts +20 -0
  53. package/dist/components/common/Box.js +20 -0
  54. package/dist/components/common/Logo.d.ts +7 -0
  55. package/dist/components/common/Logo.js +22 -0
  56. package/dist/components/common/Spinner.d.ts +12 -0
  57. package/dist/components/common/Spinner.js +28 -0
  58. package/dist/components/common/index.d.ts +6 -0
  59. package/dist/components/common/index.js +5 -0
  60. package/dist/index.d.ts +2 -0
  61. package/dist/index.js +202 -0
  62. package/dist/lib/cloudCli.d.ts +156 -0
  63. package/dist/lib/cloudCli.js +691 -0
  64. package/dist/lib/config.d.ts +91 -0
  65. package/dist/lib/config.js +278 -0
  66. package/dist/lib/dns.d.ts +41 -0
  67. package/dist/lib/dns.js +235 -0
  68. package/dist/lib/dockerHub.d.ts +57 -0
  69. package/dist/lib/dockerHub.js +128 -0
  70. package/dist/lib/helm.d.ts +53 -0
  71. package/dist/lib/helm.js +209 -0
  72. package/dist/lib/helmValues.d.ts +17 -0
  73. package/dist/lib/helmValues.js +693 -0
  74. package/dist/lib/kubernetes.d.ts +161 -0
  75. package/dist/lib/kubernetes.js +755 -0
  76. package/dist/lib/terraform.d.ts +44 -0
  77. package/dist/lib/terraform.js +230 -0
  78. package/dist/lib/theme.d.ts +81 -0
  79. package/dist/lib/theme.js +115 -0
  80. package/dist/lib/validation.d.ts +47 -0
  81. package/dist/lib/validation.js +164 -0
  82. package/dist/lib/versions.d.ts +69 -0
  83. package/dist/lib/versions.js +139 -0
  84. package/dist/types/index.d.ts +718 -0
  85. package/dist/types/index.js +556 -0
  86. package/email-templates/email_change.html +325 -0
  87. package/email-templates/invite.html +383 -0
  88. package/email-templates/password_change.html +414 -0
  89. package/email-templates/verify.html +396 -0
  90. package/package.json +78 -0
  91. package/terraform/aws/main.tf +327 -0
  92. package/terraform/azure/main.tf +326 -0
  93. package/terraform/gcp/main.tf +369 -0
@@ -0,0 +1,80 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { Box, Text, useInput } from 'ink';
4
+ import SelectInput from 'ink-select-input';
5
+ import TextInput from 'ink-text-input';
6
+ import { useWizard } from '../WizardContext.js';
7
+ import { BorderBox, useTheme } from '../../common/index.js';
8
+ export function DatabaseStep({ onComplete, onBack }) {
9
+ const { state, dispatch } = useWizard();
10
+ const { colors } = useTheme();
11
+ const [subStep, setSubStep] = useState('type');
12
+ const [supabaseUrl, setSupabaseUrl] = useState(state.supabaseUrl || '');
13
+ const [anonKey, setAnonKey] = useState(state.supabaseAnonKey || '');
14
+ const [serviceKey, setServiceKey] = useState(state.supabaseServiceKey || '');
15
+ const [currentField, setCurrentField] = useState('anon');
16
+ useInput((input, key) => {
17
+ if (key.escape) {
18
+ if (subStep === 'type') {
19
+ onBack();
20
+ }
21
+ else if (subStep === 'supabase-url') {
22
+ setSubStep('type');
23
+ }
24
+ else if (subStep === 'supabase-keys') {
25
+ if (currentField === 'service') {
26
+ setCurrentField('anon');
27
+ }
28
+ else {
29
+ setSubStep('supabase-url');
30
+ }
31
+ }
32
+ }
33
+ });
34
+ const items = [
35
+ {
36
+ label: 'Self-hosted Supabase',
37
+ value: 'self-hosted',
38
+ description: 'Deploy Supabase as part of the Helm chart'
39
+ },
40
+ {
41
+ label: 'Supabase Cloud',
42
+ value: 'supabase-cloud',
43
+ description: 'Use your existing Supabase Cloud project'
44
+ }
45
+ ];
46
+ const handleTypeSelect = (item) => {
47
+ const dbType = item.value;
48
+ dispatch({ type: 'SET_DATABASE_TYPE', dbType });
49
+ if (dbType === 'supabase-cloud') {
50
+ setSubStep('supabase-url');
51
+ }
52
+ else {
53
+ onComplete();
54
+ }
55
+ };
56
+ const handleUrlSubmit = () => {
57
+ if (!supabaseUrl)
58
+ return;
59
+ dispatch({ type: 'SET_SUPABASE_CONFIG', config: { supabaseUrl } });
60
+ setSubStep('supabase-keys');
61
+ };
62
+ const handleAnonKeySubmit = () => {
63
+ if (!anonKey)
64
+ return;
65
+ setCurrentField('service');
66
+ };
67
+ const handleServiceKeySubmit = () => {
68
+ if (!serviceKey)
69
+ return;
70
+ dispatch({
71
+ type: 'SET_SUPABASE_CONFIG',
72
+ config: {
73
+ supabaseAnonKey: anonKey,
74
+ supabaseServiceKey: serviceKey
75
+ }
76
+ });
77
+ onComplete();
78
+ };
79
+ return (_jsxs(BorderBox, { title: "Database", children: [subStep === 'type' && (_jsxs(_Fragment, { children: [_jsx(Box, { flexDirection: "column", marginY: 1, children: _jsx(Text, { children: "Choose your database setup:" }) }), _jsx(SelectInput, { items: items, onSelect: handleTypeSelect, itemComponent: ({ isSelected, label }) => (_jsx(Text, { color: isSelected ? colors.accent : undefined, children: label })) })] })), subStep === 'supabase-url' && (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { children: "Enter your Supabase project URL:" }), _jsx(Text, { color: "gray", dimColor: true, children: "Find this in your Supabase Dashboard \u2192 Project Settings" }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: colors.accent, children: "\u276F " }), _jsx(TextInput, { value: supabaseUrl, onChange: setSupabaseUrl, onSubmit: handleUrlSubmit, placeholder: "https://xxxxx.supabase.co" })] })] })), subStep === 'supabase-keys' && (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { children: "Enter your Supabase API keys:" }), currentField === 'anon' ? (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { children: "Anon (public) key:" }), _jsxs(Box, { children: [_jsx(Text, { color: colors.accent, children: "\u276F " }), _jsx(TextInput, { value: anonKey, onChange: setAnonKey, onSubmit: handleAnonKeySubmit, placeholder: "eyJhbGciOiJIUzI1NiIs..." })] })] })) : (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: "green", children: "\u2713" }), _jsxs(Text, { children: [" Anon key: ", anonKey.substring(0, 20), "..."] })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { children: "Service role key:" }) }), _jsxs(Box, { children: [_jsx(Text, { color: colors.accent, children: "\u276F " }), _jsx(TextInput, { value: serviceKey, onChange: setServiceKey, onSubmit: handleServiceKeySubmit, placeholder: "eyJhbGciOiJIUzI1NiIs..." })] })] }))] })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", dimColor: true, children: "Esc to go back \u2022 Enter to continue" }) })] }));
80
+ }
@@ -0,0 +1,5 @@
1
+ interface DeploymentModeStepProps {
2
+ onComplete: () => void;
3
+ }
4
+ export declare function DeploymentModeStep({ onComplete }: DeploymentModeStepProps): import("react/jsx-runtime").JSX.Element;
5
+ export {};
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from 'ink';
3
+ import SelectInput from 'ink-select-input';
4
+ import { useWizard } from '../WizardContext.js';
5
+ import { BorderBox, useTheme } from '../../common/index.js';
6
+ export function DeploymentModeStep({ onComplete }) {
7
+ const { dispatch } = useWizard();
8
+ const { colors } = useTheme();
9
+ const items = [
10
+ {
11
+ label: 'Use existing Kubernetes cluster',
12
+ value: 'existing',
13
+ description: 'I already have a cluster configured'
14
+ },
15
+ {
16
+ label: 'Provision new infrastructure',
17
+ value: 'provision',
18
+ description: 'Create a new cluster on AWS, GCP, or Azure'
19
+ }
20
+ ];
21
+ const handleSelect = (item) => {
22
+ dispatch({ type: 'SET_INFRA_MODE', mode: item.value });
23
+ onComplete();
24
+ };
25
+ return (_jsxs(BorderBox, { title: "Deployment Mode", children: [_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { children: "How would you like to deploy Rulebricks?" }), _jsx(Text, { color: "gray", dimColor: true, children: "Select whether to use an existing cluster or provision new infrastructure" })] }), _jsx(Box, { marginY: 1, children: _jsx(SelectInput, { items: items, onSelect: handleSelect, itemComponent: ({ isSelected, label }) => (_jsx(Box, { children: _jsx(Text, { color: isSelected ? colors.accent : undefined, children: label }) })) }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", dimColor: true, children: "\u2191/\u2193 to navigate \u2022 Enter to select" }) })] }));
26
+ }
@@ -0,0 +1,6 @@
1
+ interface DomainStepProps {
2
+ onComplete: () => void;
3
+ onBack: () => void;
4
+ }
5
+ export declare function DomainStep({ onComplete, onBack }: DomainStepProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,126 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { Box, Text, useInput } from 'ink';
4
+ import TextInput from 'ink-text-input';
5
+ import SelectInput from 'ink-select-input';
6
+ import { useWizard } from '../WizardContext.js';
7
+ import { BorderBox, useTheme } from '../../common/index.js';
8
+ import { Spinner } from '../../common/Spinner.js';
9
+ import { validateBaseDomain, isValidEmail, isValidDomainFormat } from '../../../lib/validation.js';
10
+ import { DNS_PROVIDER_NAMES, isSupportedDnsProvider } from '../../../types/index.js';
11
+ const DNS_PROVIDER_OPTIONS = [
12
+ { label: 'Other / Not sure (manual DNS)', value: 'other' },
13
+ { label: 'AWS Route 53', value: 'route53' },
14
+ { label: 'Cloudflare', value: 'cloudflare' },
15
+ { label: 'Google Cloud DNS', value: 'google' },
16
+ { label: 'Azure DNS', value: 'azure' }
17
+ ];
18
+ const AUTO_MANAGE_OPTIONS = [
19
+ { label: 'Yes, automatically manage DNS records', value: true },
20
+ { label: 'No, I\'ll configure DNS manually', value: false }
21
+ ];
22
+ export function DomainStep({ onComplete, onBack }) {
23
+ const { state, dispatch } = useWizard();
24
+ const { colors } = useTheme();
25
+ const [subStep, setSubStep] = useState('domain');
26
+ const [domain, setDomain] = useState(state.domain || '');
27
+ const [adminEmail, setAdminEmail] = useState(state.adminEmail || '');
28
+ const [tlsEmail, setTlsEmail] = useState(state.tlsEmail || '');
29
+ const [error, setError] = useState(null);
30
+ useInput((input, key) => {
31
+ if (key.escape) {
32
+ setError(null);
33
+ if (subStep === 'domain') {
34
+ onBack();
35
+ }
36
+ else if (subStep === 'admin-email') {
37
+ setSubStep('domain');
38
+ }
39
+ else if (subStep === 'tls-email') {
40
+ setSubStep('admin-email');
41
+ }
42
+ else if (subStep === 'dns-provider') {
43
+ setSubStep('tls-email');
44
+ }
45
+ else if (subStep === 'dns-auto-manage') {
46
+ setSubStep('dns-provider');
47
+ }
48
+ }
49
+ });
50
+ const handleDomainSubmit = async () => {
51
+ if (!domain) {
52
+ setError('Domain is required');
53
+ return;
54
+ }
55
+ if (!isValidDomainFormat(domain)) {
56
+ setError('Invalid domain format (e.g., rulebricks.example.com)');
57
+ return;
58
+ }
59
+ setError(null);
60
+ setSubStep('validating');
61
+ try {
62
+ const result = await validateBaseDomain(domain);
63
+ if (!result.valid) {
64
+ setError(result.error || 'Domain validation failed');
65
+ setSubStep('domain');
66
+ return;
67
+ }
68
+ dispatch({ type: 'SET_DOMAIN', domain });
69
+ setSubStep('admin-email');
70
+ }
71
+ catch {
72
+ // If validation fails due to network issues, allow continuing
73
+ dispatch({ type: 'SET_DOMAIN', domain });
74
+ setSubStep('admin-email');
75
+ }
76
+ };
77
+ const handleAdminEmailSubmit = () => {
78
+ if (!adminEmail) {
79
+ setError('Admin email is required');
80
+ return;
81
+ }
82
+ if (!isValidEmail(adminEmail)) {
83
+ setError('Invalid email format');
84
+ return;
85
+ }
86
+ setError(null);
87
+ dispatch({ type: 'SET_ADMIN_EMAIL', email: adminEmail });
88
+ // Default TLS email to admin email if not set
89
+ if (!tlsEmail) {
90
+ setTlsEmail(adminEmail);
91
+ }
92
+ setSubStep('tls-email');
93
+ };
94
+ const handleTlsEmailSubmit = () => {
95
+ if (!tlsEmail) {
96
+ setError('TLS email is required');
97
+ return;
98
+ }
99
+ if (!isValidEmail(tlsEmail)) {
100
+ setError('Invalid email format');
101
+ return;
102
+ }
103
+ setError(null);
104
+ dispatch({ type: 'SET_TLS_EMAIL', email: tlsEmail });
105
+ setSubStep('dns-provider');
106
+ };
107
+ const handleDnsProviderSelect = (item) => {
108
+ dispatch({ type: 'SET_DNS_PROVIDER', provider: item.value });
109
+ // If unsupported provider, skip auto-manage question and complete
110
+ if (!isSupportedDnsProvider(item.value)) {
111
+ dispatch({ type: 'SET_DNS_AUTO_MANAGE', autoManage: false });
112
+ onComplete();
113
+ }
114
+ else {
115
+ // For supported providers, ask if they want auto-management
116
+ setSubStep('dns-auto-manage');
117
+ }
118
+ };
119
+ const handleAutoManageSelect = (item) => {
120
+ dispatch({ type: 'SET_DNS_AUTO_MANAGE', autoManage: item.value });
121
+ onComplete();
122
+ };
123
+ // Progress summary component
124
+ const ProgressSummary = () => (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [domain && (_jsxs(Box, { children: [_jsx(Text, { color: "green", children: "\u2713" }), _jsxs(Text, { color: "gray", children: [" Domain: ", domain] })] })), adminEmail && subStep !== 'admin-email' && (_jsxs(Box, { children: [_jsx(Text, { color: "green", children: "\u2713" }), _jsxs(Text, { color: "gray", children: [" Admin: ", adminEmail] })] })), tlsEmail && subStep !== 'tls-email' && subStep !== 'admin-email' && (_jsxs(Box, { children: [_jsx(Text, { color: "green", children: "\u2713" }), _jsxs(Text, { color: "gray", children: [" TLS email: ", tlsEmail] })] }))] }));
125
+ return (_jsxs(BorderBox, { title: "Domain & DNS", children: [subStep === 'domain' && (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { children: "Enter your Rulebricks domain:" }), _jsx(Text, { color: "gray", dimColor: true, children: "This is where Rulebricks will be accessible (e.g., rulebricks.example.com)" }), _jsx(Box, { marginTop: 1, children: _jsx(TextInput, { value: domain, onChange: setDomain, onSubmit: handleDomainSubmit, placeholder: "rulebricks.example.com" }) }), error && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "red", children: ["\u2717 ", error] }) }))] })), subStep === 'validating' && (_jsx(Box, { flexDirection: "column", marginY: 1, children: _jsx(Spinner, { label: "Validating domain..." }) })), subStep === 'admin-email' && (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { children: "Enter the admin email address:" }), _jsx(Text, { color: "gray", dimColor: true, children: "This email will be used for Rulebricks administration and notifications" }), _jsx(Box, { marginTop: 1, children: _jsx(TextInput, { value: adminEmail, onChange: setAdminEmail, onSubmit: handleAdminEmailSubmit, placeholder: "admin@example.com" }) }), _jsx(ProgressSummary, {}), error && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "red", children: ["\u2717 ", error] }) }))] })), subStep === 'tls-email' && (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { children: "Enter the email for TLS certificates:" }), _jsx(Text, { color: "gray", dimColor: true, children: "Let's Encrypt will send certificate expiration notices here" }), _jsx(Box, { marginTop: 1, children: _jsx(TextInput, { value: tlsEmail, onChange: setTlsEmail, onSubmit: handleTlsEmailSubmit, placeholder: adminEmail || 'admin@example.com' }) }), _jsx(ProgressSummary, {}), error && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "red", children: ["\u2717 ", error] }) }))] })), subStep === 'dns-provider' && (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { bold: true, children: "Where is your domain's DNS hosted?" }), _jsx(Text, { color: "gray", dimColor: true, children: "This determines whether we can automatically manage DNS records for you" }), _jsx(Box, { marginTop: 1, children: _jsx(SelectInput, { items: DNS_PROVIDER_OPTIONS, onSelect: handleDnsProviderSelect, itemComponent: ({ isSelected, label }) => (_jsx(Text, { color: isSelected ? colors.accent : undefined, children: label })) }) }), _jsx(ProgressSummary, {})] })), subStep === 'dns-auto-manage' && (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { bold: true, children: "Automatic DNS Management" }), _jsx(Text, { color: "gray", dimColor: true, children: "Would you like Rulebricks to automatically create and manage DNS records?" }), _jsx(Text, { color: "gray", dimColor: true, children: "This enables single-step deployment without manual DNS configuration." }), _jsx(Box, { marginTop: 1, children: _jsx(SelectInput, { items: AUTO_MANAGE_OPTIONS, onSelect: handleAutoManageSelect, itemComponent: ({ isSelected, label }) => (_jsx(Text, { color: isSelected ? colors.accent : undefined, children: label })) }) }), _jsx(ProgressSummary, {}), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "green", children: "\u2713" }), _jsxs(Text, { color: "gray", children: [" DNS Provider: ", DNS_PROVIDER_NAMES[state.dnsProvider]] })] }), state.infrastructureMode === 'existing' && (_jsx(Box, { marginTop: 1, borderStyle: "round", borderColor: "yellow", paddingX: 1, children: _jsx(Text, { color: "yellow", children: "Note: Auto-DNS requires external-dns with proper IAM credentials in your cluster." }) }))] })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "gray", dimColor: true, children: "Esc to go back \u2022 Enter to continue" }) })] }));
126
+ }
@@ -0,0 +1,6 @@
1
+ interface FeatureConfigStepProps {
2
+ onComplete: () => void;
3
+ onBack: () => void;
4
+ }
5
+ export declare function FeatureConfigStep({ onComplete, onBack, }: FeatureConfigStepProps): import("react/jsx-runtime").JSX.Element | null;
6
+ export {};