@launchframe/cli 1.0.0-beta.8 → 1.0.0-beta.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@launchframe/cli",
3
- "version": "1.0.0-beta.8",
3
+ "version": "1.0.0-beta.9",
4
4
  "description": "Production-ready B2B SaaS boilerplate with subscriptions, credits, and multi-tenancy",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -1,11 +1,11 @@
1
1
  const chalk = require('chalk');
2
- const { clearCache, getCacheInfo } = require('../utils/module-cache');
2
+ const { clearCache, getCacheInfo } = require('../utils/service-cache');
3
3
 
4
4
  /**
5
- * Clear module cache
5
+ * Clear service cache
6
6
  */
7
7
  async function cacheClear() {
8
- console.log(chalk.yellow('\n⚠️ This will delete all cached modules'));
8
+ console.log(chalk.yellow('\n⚠️ This will delete all cached services'));
9
9
  console.log(chalk.gray('You will need to re-download on next init or service:add\n'));
10
10
 
11
11
  const inquirer = require('inquirer');
@@ -30,7 +30,7 @@ async function cacheClear() {
30
30
  async function cacheInfo() {
31
31
  const info = await getCacheInfo();
32
32
 
33
- console.log(chalk.blue('\n📦 Module Cache Information\n'));
33
+ console.log(chalk.blue('\n📦 Service Cache Information\n'));
34
34
 
35
35
  console.log(chalk.white('Location:'));
36
36
  console.log(chalk.gray(` ${info.path}\n`));
@@ -54,14 +54,14 @@ async function cacheInfo() {
54
54
  console.log(chalk.gray(` ${info.lastUpdate.toLocaleString()}\n`));
55
55
  }
56
56
 
57
- if (info.modules && info.modules.length > 0) {
58
- console.log(chalk.white('Cached Modules:'));
59
- info.modules.forEach(mod => {
57
+ if (info.services && info.services.length > 0) {
58
+ console.log(chalk.white('Cached Services:'));
59
+ info.services.forEach(mod => {
60
60
  console.log(chalk.gray(` • ${mod}`));
61
61
  });
62
62
  console.log('');
63
63
  } else {
64
- console.log(chalk.gray('No modules cached yet\n'));
64
+ console.log(chalk.gray('No services cached yet\n'));
65
65
  }
66
66
 
67
67
  console.log(chalk.gray('Commands:'));
@@ -73,21 +73,21 @@ async function cacheInfo() {
73
73
  * Force update cache
74
74
  */
75
75
  async function cacheUpdate() {
76
- const { ensureCacheReady, getCacheInfo } = require('../utils/module-cache');
76
+ const { ensureCacheReady, getCacheInfo } = require('../utils/service-cache');
77
77
 
78
78
  console.log(chalk.blue('\n🔄 Forcing cache update...\n'));
79
79
 
80
80
  try {
81
81
  const info = await getCacheInfo();
82
- const currentModules = info.modules || [];
82
+ const currentServices = info.services || [];
83
83
 
84
- if (currentModules.length === 0) {
85
- console.log(chalk.yellow('No modules in cache yet. Use init or service:add to populate.\n'));
84
+ if (currentServices.length === 0) {
85
+ console.log(chalk.yellow('No services in cache yet. Use init or service:add to populate.\n'));
86
86
  return;
87
87
  }
88
88
 
89
- // Update cache with current modules
90
- await ensureCacheReady(currentModules);
89
+ // Update cache with current services
90
+ await ensureCacheReady(currentServices);
91
91
  console.log(chalk.green('\n✓ Cache updated successfully\n'));
92
92
  } catch (error) {
93
93
  console.error(chalk.red(`\n❌ Failed to update cache: ${error.message}\n`));
@@ -40,7 +40,7 @@ function help() {
40
40
  console.log(chalk.white('Available Services:'));
41
41
  console.log(chalk.gray(' waitlist Coming soon page with email collection\n'));
42
42
  console.log(chalk.white('Cache Management:'));
43
- console.log(chalk.gray(' cache:info Show cache location, size, and cached modules'));
43
+ console.log(chalk.gray(' cache:info Show cache location, size, and cached services'));
44
44
  console.log(chalk.gray(' cache:update Force update cache to latest version'));
45
45
  console.log(chalk.gray(' cache:clear Delete cache (re-download on next use)\n'));
46
46
  console.log(chalk.white('Other commands:'));
@@ -75,7 +75,7 @@ function help() {
75
75
  console.log(chalk.gray(' --user-model <b2b|b2b2c> User model (skips prompt)'));
76
76
  console.log(chalk.gray(' help Show this help message\n'));
77
77
  console.log(chalk.white('Cache Management:'));
78
- console.log(chalk.gray(' cache:info Show cache location, size, and cached modules'));
78
+ console.log(chalk.gray(' cache:info Show cache location, size, and cached services'));
79
79
  console.log(chalk.gray(' cache:update Force update cache to latest version'));
80
80
  console.log(chalk.gray(' cache:clear Delete cache (re-download on next use)\n'));
81
81
  console.log(chalk.white('Examples:'));
@@ -4,7 +4,7 @@ const chalk = require('chalk');
4
4
  const { runInitPrompts, runVariantPrompts } = require('../prompts');
5
5
  const { generateProject } = require('../generator');
6
6
  const { checkGitHubAccess, showAccessDeniedMessage } = require('../utils/github-access');
7
- const { ensureCacheReady } = require('../utils/module-cache');
7
+ const { ensureCacheReady } = require('../utils/service-cache');
8
8
  const { isLaunchFrameProject } = require('../utils/project-helpers');
9
9
 
10
10
  /**
@@ -116,8 +116,8 @@ async function init(options = {}) {
116
116
  variantChoices = await runVariantPrompts();
117
117
  }
118
118
 
119
- // Determine which modules are needed based on variant choices
120
- const requiredModules = [
119
+ // Determine which services are needed based on variant choices
120
+ const requiredServices = [
121
121
  'backend',
122
122
  'admin-portal',
123
123
  'infrastructure',
@@ -126,20 +126,20 @@ async function init(options = {}) {
126
126
 
127
127
  // Add customers-portal only if B2B2C mode
128
128
  if (variantChoices.userModel === 'b2b2c') {
129
- requiredModules.push('customers-portal');
129
+ requiredServices.push('customers-portal');
130
130
  }
131
131
 
132
132
  // Determine template source (dev mode = local, production = cache)
133
133
  let templateRoot;
134
134
 
135
135
  if (devMode) {
136
- // Dev mode: Use local modules directory
137
- templateRoot = path.resolve(__dirname, '../../../modules');
138
- console.log(chalk.gray(`[DEV MODE] Using local modules: ${templateRoot}\n`));
136
+ // Dev mode: Use local services directory
137
+ templateRoot = path.resolve(__dirname, '../../../services');
138
+ console.log(chalk.gray(`[DEV MODE] Using local services: ${templateRoot}\n`));
139
139
  } else {
140
140
  // Production mode: Use cache
141
141
  try {
142
- templateRoot = await ensureCacheReady(requiredModules);
142
+ templateRoot = await ensureCacheReady(requiredServices);
143
143
  } catch (error) {
144
144
  console.error(chalk.red(`\n❌ Error: ${error.message}\n`));
145
145
  process.exit(1);
@@ -8,7 +8,7 @@ const { isLaunchFrameProject, getProjectConfig, updateProjectConfig, getPrimaryD
8
8
  const { replaceVariables } = require('../utils/variable-replacer');
9
9
  const { updateEnvFile } = require('../utils/env-generator');
10
10
  const { checkGitHubAccess, showAccessDeniedMessage } = require('../utils/github-access');
11
- const { ensureCacheReady, getModulePath } = require('../utils/module-cache');
11
+ const { ensureCacheReady, getServicePath } = require('../utils/service-cache');
12
12
 
13
13
  async function serviceAdd(serviceName) {
14
14
  // STEP 1: Validation
@@ -75,13 +75,13 @@ async function serviceAdd(serviceName) {
75
75
  let sourceDir;
76
76
 
77
77
  if (isDevMode) {
78
- // Local development: copy from launchframe-dev/modules directory
78
+ // Local development: copy from launchframe-dev/services directory
79
79
  console.log(chalk.blue('\n[DEV MODE] Copying service from local directory...'));
80
- sourceDir = path.resolve(__dirname, '../../../modules', serviceName);
80
+ sourceDir = path.resolve(__dirname, '../../../services', serviceName);
81
81
 
82
82
  if (!fs.existsSync(sourceDir)) {
83
83
  console.error(chalk.red(`Error: Local service directory not found: ${sourceDir}`));
84
- console.log('Make sure the service exists in the modules directory');
84
+ console.log('Make sure the service exists in the services directory');
85
85
  process.exit(1);
86
86
  }
87
87
  } else {
@@ -98,9 +98,9 @@ async function serviceAdd(serviceName) {
98
98
  console.log(chalk.green('✓ Repository access confirmed'));
99
99
 
100
100
  try {
101
- // Ensure cache has this service module
101
+ // Ensure cache has this service
102
102
  await ensureCacheReady([serviceName]);
103
- sourceDir = getModulePath(serviceName);
103
+ sourceDir = getServicePath(serviceName);
104
104
  } catch (error) {
105
105
  console.error(chalk.red(`\n❌ Error: ${error.message}\n`));
106
106
  process.exit(1);
package/src/generator.js CHANGED
@@ -142,7 +142,7 @@ async function generateProject(answers, variantChoices, templateRoot) {
142
142
  await replaceVariables(path.join(destinationRoot, 'website'), variables);
143
143
  initGitRepo(path.join(destinationRoot, 'website'), 'website');
144
144
 
145
- // Step 5: Copy additional files (from project root, not modules/)
145
+ // Step 5: Copy additional files (from project root, not services/)
146
146
  console.log('📋 Copying additional files...');
147
147
  const additionalFiles = [
148
148
  '.github',
@@ -174,13 +174,13 @@ async function generateProject(answers, variantChoices, templateRoot) {
174
174
  // Step 7: Create .launchframe marker file with variant metadata
175
175
  console.log('📝 Creating LaunchFrame marker file...');
176
176
  const markerPath = path.join(destinationRoot, '.launchframe');
177
-
177
+
178
178
  // Determine which services were installed
179
179
  const installedServices = ['backend', 'admin-portal', 'infrastructure', 'website'];
180
180
  if (variantChoices.userModel === 'b2b2c') {
181
181
  installedServices.push('customers-portal');
182
182
  }
183
-
183
+
184
184
  const markerContent = {
185
185
  version: '0.1.0',
186
186
  createdAt: new Date().toISOString(),
@@ -14,14 +14,14 @@ function makeClickable(text, url) {
14
14
  }
15
15
 
16
16
  /**
17
- * Check if user has SSH access to LaunchFrame modules repository
17
+ * Check if user has SSH access to LaunchFrame services repository
18
18
  * @returns {Promise<{hasAccess: boolean, error?: string}>}
19
19
  */
20
20
  async function checkGitHubAccess() {
21
21
  try {
22
22
  // Test SSH access by checking if we can list remote refs
23
23
  execSync(
24
- 'git ls-remote git@github.com:launchframe-dev/modules.git HEAD',
24
+ 'git ls-remote git@github.com:launchframe-dev/services.git HEAD',
25
25
  {
26
26
  timeout: 15000,
27
27
  stdio: 'pipe' // Don't show output
@@ -37,14 +37,14 @@ async function checkGitHubAccess() {
37
37
  }
38
38
 
39
39
  /**
40
- * Display message when user doesn't have access to modules repository
40
+ * Display message when user doesn't have access to services repository
41
41
  * Guides them to either purchase or setup SSH keys
42
42
  */
43
43
  function showAccessDeniedMessage() {
44
44
  const purchaseUrl = 'https://buy.polar.sh/polar_cl_Zy4YqEwhoIEdUrAH8vHaWuZtwZuv306sYMnq118MbKi';
45
45
  const docsUrl = 'https://docs.launchframe.dev/guide/quick-start#add-ssh-key-to-repo';
46
46
 
47
- console.log(chalk.red('\n❌ Cannot access LaunchFrame modules repository\n'));
47
+ console.log(chalk.red('\n❌ Cannot access LaunchFrame services repository\n'));
48
48
 
49
49
  console.log(chalk.white('This could mean:\n'));
50
50
  console.log(chalk.gray(' 1. You haven\'t purchased LaunchFrame yet'));
@@ -4,7 +4,7 @@ const os = require('os');
4
4
  const { execSync } = require('child_process');
5
5
  const chalk = require('chalk');
6
6
 
7
- const MODULES_REPO = 'git@github.com:launchframe-dev/modules.git';
7
+ const SERVICES_REPO = 'git@github.com:launchframe-dev/services.git';
8
8
  const BRANCH = 'main';
9
9
 
10
10
  /**
@@ -15,9 +15,9 @@ const BRANCH = 'main';
15
15
  function getCacheDir() {
16
16
  const homeDir = os.homedir();
17
17
  // Use same path structure on all platforms
18
- // Windows: C:\Users\username\.launchframe\cache\modules
19
- // Mac/Linux: /home/username/.launchframe/cache/modules
20
- return path.join(homeDir, '.launchframe', 'cache', 'modules');
18
+ // Windows: C:\Users\username\.launchframe\cache\services
19
+ // Mac/Linux: /home/username/.launchframe/cache/services
20
+ return path.join(homeDir, '.launchframe', 'cache', 'services');
21
21
  }
22
22
 
23
23
  /**
@@ -32,33 +32,33 @@ async function cacheExists() {
32
32
 
33
33
  /**
34
34
  * Initialize cache with sparse checkout
35
- * Clones only the repository structure, no modules yet
35
+ * Clones only the repository structure, no services yet
36
36
  * @returns {Promise<void>}
37
37
  */
38
38
  async function initializeCache() {
39
39
  const cacheDir = getCacheDir();
40
-
41
- console.log(chalk.blue('🔄 Initializing module cache...'));
42
-
40
+
41
+ console.log(chalk.blue('🔄 Initializing services cache...'));
42
+
43
43
  try {
44
44
  // Ensure parent directory exists
45
45
  await fs.ensureDir(path.dirname(cacheDir));
46
-
47
- // Sparse clone (only root files, no modules)
46
+
47
+ // Sparse clone (only root files, no services)
48
48
  execSync(
49
- `git clone --sparse --depth 1 --branch ${BRANCH} ${MODULES_REPO} "${cacheDir}"`,
50
- {
49
+ `git clone --sparse --depth 1 --branch ${BRANCH} ${SERVICES_REPO} "${cacheDir}"`,
50
+ {
51
51
  stdio: 'pipe', // Hide output
52
52
  timeout: 60000 // 1 minute timeout
53
53
  }
54
54
  );
55
-
55
+
56
56
  // Configure sparse checkout (starts with empty set)
57
57
  execSync('git sparse-checkout init --cone', {
58
58
  cwd: cacheDir,
59
59
  stdio: 'pipe'
60
60
  });
61
-
61
+
62
62
  console.log(chalk.green('✓ Cache initialized'));
63
63
  } catch (error) {
64
64
  // Clean up partial clone on failure
@@ -74,16 +74,16 @@ async function initializeCache() {
74
74
  */
75
75
  async function updateCache() {
76
76
  const cacheDir = getCacheDir();
77
-
78
- console.log(chalk.blue('🔄 Updating module cache...'));
79
-
77
+
78
+ console.log(chalk.blue('🔄 Updating service cache...'));
79
+
80
80
  try {
81
81
  execSync('git pull origin main', {
82
82
  cwd: cacheDir,
83
83
  stdio: 'pipe',
84
84
  timeout: 30000 // 30 seconds
85
85
  });
86
-
86
+
87
87
  console.log(chalk.green('✓ Cache updated'));
88
88
  } catch (error) {
89
89
  throw new Error(`Failed to update cache: ${error.message}`);
@@ -91,53 +91,53 @@ async function updateCache() {
91
91
  }
92
92
 
93
93
  /**
94
- * Expand sparse checkout to include specific modules
95
- * @param {string[]} moduleNames - Array of module names to expand
94
+ * Expand sparse checkout to include specific services
95
+ * @param {string[]} serviceNames - Array of services names to expand
96
96
  * @returns {Promise<void>}
97
97
  */
98
- async function expandModules(moduleNames) {
98
+ async function expandServices(serviceNames) {
99
99
  const cacheDir = getCacheDir();
100
-
101
- console.log(chalk.blue(`📦 Loading modules: ${moduleNames.join(', ')}...`));
102
-
100
+
101
+ console.log(chalk.blue(`📦 Loading services: ${serviceNames.join(', ')}...`));
102
+
103
103
  try {
104
104
  // Get current sparse checkout list
105
- let currentModules = [];
105
+ let currentServices = [];
106
106
  try {
107
107
  const output = execSync('git sparse-checkout list', {
108
108
  cwd: cacheDir,
109
109
  stdio: 'pipe',
110
110
  encoding: 'utf8'
111
111
  });
112
- currentModules = output.trim().split('\n').filter(Boolean);
112
+ currentServices = output.trim().split('\n').filter(Boolean);
113
113
  } catch (error) {
114
- // No modules yet, that's fine
114
+ // No services yet, that's fine
115
115
  }
116
-
117
- // Add new modules to the list
118
- const allModules = [...new Set([...currentModules, ...moduleNames])];
119
-
120
- // Set sparse checkout to include all modules
121
- execSync(`git sparse-checkout set ${allModules.join(' ')}`, {
116
+
117
+ // Add new services to the list
118
+ const allServices = [...new Set([...currentServices, ...serviceNames])];
119
+
120
+ // Set sparse checkout to include all services
121
+ execSync(`git sparse-checkout set ${allServices.join(' ')}`, {
122
122
  cwd: cacheDir,
123
123
  stdio: 'pipe',
124
124
  timeout: 60000 // 1 minute (may need to download files)
125
125
  });
126
-
127
- console.log(chalk.green('✓ Modules loaded'));
126
+
127
+ console.log(chalk.green('✓ Services loaded'));
128
128
  } catch (error) {
129
- throw new Error(`Failed to expand modules: ${error.message}`);
129
+ throw new Error(`Failed to expand services: ${error.message}`);
130
130
  }
131
131
  }
132
132
 
133
133
  /**
134
- * Get path to a specific module in the cache
135
- * @param {string} moduleName - Module name (e.g., 'backend', 'admin-portal')
136
- * @returns {string} Absolute path to module
134
+ * Get path to a specific service in the cache
135
+ * @param {string} serviceName - Service name (e.g., 'backend', 'admin-portal')
136
+ * @returns {string} Absolute path to service
137
137
  */
138
- function getModulePath(moduleName) {
138
+ function getServicePath(serviceName) {
139
139
  const cacheDir = getCacheDir();
140
- return path.join(cacheDir, moduleName);
140
+ return path.join(cacheDir, serviceName);
141
141
  }
142
142
 
143
143
  /**
@@ -149,13 +149,13 @@ function getCachePath() {
149
149
  }
150
150
 
151
151
  /**
152
- * Clear the entire module cache
152
+ * Clear the entire service cache
153
153
  * Useful for troubleshooting or forcing fresh download
154
154
  * @returns {Promise<void>}
155
155
  */
156
156
  async function clearCache() {
157
157
  const cacheDir = getCacheDir();
158
-
158
+
159
159
  if (await fs.pathExists(cacheDir)) {
160
160
  await fs.remove(cacheDir);
161
161
  console.log(chalk.green('✓ Cache cleared'));
@@ -165,8 +165,8 @@ async function clearCache() {
165
165
  }
166
166
 
167
167
  /**
168
- * Get cache information (size, last update, modules)
169
- * @returns {Promise<{exists: boolean, path: string, size?: number, modules?: string[], lastUpdate?: Date}>}
168
+ * Get cache information (size, last update, services)
169
+ * @returns {Promise<{exists: boolean, path: string, size?: number, services?: string[], lastUpdate?: Date}>}
170
170
  */
171
171
  async function getCacheInfo() {
172
172
  const cacheDir = getCacheDir();
@@ -174,13 +174,13 @@ async function getCacheInfo() {
174
174
  exists: false,
175
175
  path: cacheDir
176
176
  };
177
-
177
+
178
178
  if (!(await cacheExists())) {
179
179
  return info;
180
180
  }
181
-
181
+
182
182
  info.exists = true;
183
-
183
+
184
184
  try {
185
185
  // Get cache size (du command works on Unix/Mac, different on Windows)
186
186
  if (process.platform === 'win32') {
@@ -201,19 +201,19 @@ async function getCacheInfo() {
201
201
  } catch (error) {
202
202
  // Size calculation failed, not critical
203
203
  }
204
-
204
+
205
205
  try {
206
- // Get list of expanded modules
206
+ // Get list of expanded services
207
207
  const output = execSync('git sparse-checkout list', {
208
208
  cwd: cacheDir,
209
209
  encoding: 'utf8',
210
210
  stdio: 'pipe'
211
211
  });
212
- info.modules = output.trim().split('\n').filter(Boolean);
212
+ info.services = output.trim().split('\n').filter(Boolean);
213
213
  } catch (error) {
214
- info.modules = [];
214
+ info.services = [];
215
215
  }
216
-
216
+
217
217
  try {
218
218
  // Get last update time from git log
219
219
  const output = execSync('git log -1 --format=%cd --date=iso', {
@@ -225,17 +225,17 @@ async function getCacheInfo() {
225
225
  } catch (error) {
226
226
  // Last update time failed, not critical
227
227
  }
228
-
228
+
229
229
  return info;
230
230
  }
231
231
 
232
232
  /**
233
233
  * Ensure cache is ready (initialize if needed, update if exists)
234
234
  * This is the main entry point for cache management
235
- * @param {string[]} requiredModules - Modules needed for the operation
235
+ * @param {string[]} requiredServices - Services needed for the operation
236
236
  * @returns {Promise<string>} Path to cache root
237
237
  */
238
- async function ensureCacheReady(requiredModules) {
238
+ async function ensureCacheReady(requiredServices) {
239
239
  try {
240
240
  if (!(await cacheExists())) {
241
241
  // Cache doesn't exist, initialize it
@@ -244,10 +244,10 @@ async function ensureCacheReady(requiredModules) {
244
244
  // Cache exists, update it
245
245
  await updateCache();
246
246
  }
247
-
248
- // Expand sparse checkout to include required modules
249
- await expandModules(requiredModules);
250
-
247
+
248
+ // Expand sparse checkout to include required services
249
+ await expandServices(requiredServices);
250
+
251
251
  return getCachePath();
252
252
  } catch (error) {
253
253
  // If we fail and it's a network error, provide helpful message
@@ -265,8 +265,8 @@ module.exports = {
265
265
  cacheExists,
266
266
  initializeCache,
267
267
  updateCache,
268
- expandModules,
269
- getModulePath,
268
+ expandServices,
269
+ getServicePath,
270
270
  getCachePath,
271
271
  clearCache,
272
272
  getCacheInfo,