create-nextblock 0.2.38 → 0.2.40

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.
@@ -17,7 +17,6 @@ const __filename = fileURLToPath(import.meta.url);
17
17
  const __dirname = dirname(__filename);
18
18
  const TEMPLATE_DIR = resolve(__dirname, '../templates/nextblock-template');
19
19
  const REPO_ROOT = resolve(__dirname, '../../..');
20
- const require = createRequire(import.meta.url);
21
20
  const EDITOR_UTILS_SOURCE_DIR = resolve(REPO_ROOT, 'libs/editor/src/lib/utils');
22
21
  const IS_WINDOWS = process.platform === 'win32';
23
22
 
@@ -199,7 +198,7 @@ async function runSetupWizard(projectDir, projectName) {
199
198
  if (process.stdin.isTTY) {
200
199
  try {
201
200
  process.stdin.setRawMode(false);
202
- } catch (_) {
201
+ } catch {
203
202
  // ignore
204
203
  }
205
204
  process.stdin.setEncoding('utf8');
@@ -235,11 +234,12 @@ async function runSetupWizard(projectDir, projectName) {
235
234
  clack.note('Please go to your Supabase project dashboard to get the following secrets.');
236
235
  const supabaseKeys = await clack.group(
237
236
  {
238
- dbPassword: () =>
239
- clack.password({
237
+ postgresUrl: () =>
238
+ clack.text({
240
239
  message:
241
- 'What is your Database Password? (Supabase: Database > Database Settings > Reset database password | Vercel: POSTGRES_PASSWORD)',
242
- validate: (val) => (!val ? 'Password is required' : undefined),
240
+ 'What is your Connection String? (Supabase: Project Dashboard > Connect (Top Left) > Connection String > URI | Vercel: POSTGRES_URL)',
241
+ placeholder: 'postgresql://...',
242
+ validate: (val) => (!val ? 'Connection string is required' : undefined),
243
243
  }),
244
244
  anonKey: () =>
245
245
  clack.password({
@@ -261,12 +261,25 @@ async function runSetupWizard(projectDir, projectName) {
261
261
  const revalidationToken = crypto.randomBytes(32).toString('hex');
262
262
  const supabaseUrl = `https://${projectId}.supabase.co`;
263
263
 
264
- const dbHost = `db.${projectId}.supabase.co`;
265
- const dbUser = 'postgres';
266
- const dbPassword = supabaseKeys.dbPassword;
267
- const dbName = 'postgres';
264
+ const postgresUrl = supabaseKeys.postgresUrl;
265
+ let dbPassword = '';
266
+ try {
267
+ const parsedUrl = new URL(postgresUrl);
268
+ dbPassword = parsedUrl.password;
269
+ } catch {
270
+ // Fallback if URL parsing fails, though validation above checks for non-empty
271
+ }
268
272
 
269
- const postgresUrl = `postgresql://${dbUser}:${dbPassword}@${dbHost}:5432/${dbName}`;
273
+ if (!dbPassword) {
274
+ const passwordPrompt = await clack.password({
275
+ message: 'Could not extract password from URL. What is your Database Password?',
276
+ validate: (val) => (!val ? 'Password is required' : undefined),
277
+ });
278
+ if (clack.isCancel(passwordPrompt)) {
279
+ handleWizardCancel('Setup cancelled.');
280
+ }
281
+ dbPassword = passwordPrompt;
282
+ }
270
283
 
271
284
  const envPath = resolve(projectPath, '.env');
272
285
  const appendEnvBlock = async (label, lines) => {
@@ -313,8 +326,9 @@ async function runSetupWizard(projectDir, projectName) {
313
326
  }
314
327
 
315
328
  clack.note('Setting up your database...');
329
+
316
330
  const dbPushSpinner = clack.spinner();
317
- dbPushSpinner.start('Pushing database schema... (~10-15 minutes, please keep this terminal open)');
331
+ dbPushSpinner.start('Pushing database schema...');
318
332
  try {
319
333
  process.env.POSTGRES_URL = postgresUrl;
320
334
  const migrationsDir = resolve(projectPath, 'supabase', 'migrations');
@@ -331,7 +345,34 @@ async function runSetupWizard(projectDir, projectName) {
331
345
  `No migrations found in ${migrationsDir}; skipping db push. Ensure @nextblock-cms/db includes supabase/migrations.`,
332
346
  );
333
347
  } else {
334
- await execa('npx', ['supabase', 'db', 'push'], { stdio: 'inherit', cwd: projectPath });
348
+ const supabaseBin = await getSupabaseBinary(projectPath);
349
+ const command = supabaseBin === 'npx' ? 'npx' : supabaseBin;
350
+
351
+ // 1. Link the project explicitly
352
+ dbPushSpinner.message('Linking to Supabase project...');
353
+ const linkArgs = supabaseBin === 'npx' ? ['supabase', 'link'] : ['link'];
354
+ linkArgs.push('--project-ref', projectId);
355
+ linkArgs.push('--password', dbPassword);
356
+
357
+ await execa(command, linkArgs, {
358
+ stdio: 'inherit',
359
+ cwd: projectPath,
360
+ });
361
+
362
+ // 2. Push the schema using the linked state
363
+ dbPushSpinner.message('Pushing database schema...');
364
+ const pushArgs = supabaseBin === 'npx' ? ['supabase', 'db', 'push'] : ['db', 'push'];
365
+ pushArgs.push('--include-all');
366
+
367
+ await execa(command, pushArgs, {
368
+ stdio: ['pipe', 'inherit', 'inherit'],
369
+ cwd: projectPath,
370
+ input: 'y\n', // Auto-confirm the push prompt
371
+ env: {
372
+ ...process.env,
373
+ SUPABASE_DB_PASSWORD: dbPassword,
374
+ },
375
+ });
335
376
  dbPushSpinner.stop('Database schema pushed successfully!');
336
377
  }
337
378
  } catch (error) {
@@ -1350,8 +1391,12 @@ function runCommand(command, args, options = {}) {
1350
1391
 
1351
1392
  async function runSupabaseCli(args, options = {}) {
1352
1393
  const { cwd } = options;
1394
+ const supabaseBin = await getSupabaseBinary(cwd);
1395
+ const command = supabaseBin === 'npx' ? 'npx' : supabaseBin;
1396
+ const cmdArgs = supabaseBin === 'npx' ? ['supabase', ...args] : args;
1397
+
1353
1398
  return new Promise((resolve, reject) => {
1354
- const child = spawn('npx', ['supabase', ...args], {
1399
+ const child = spawn(command, cmdArgs, {
1355
1400
  cwd,
1356
1401
  shell: IS_WINDOWS,
1357
1402
  stdio: 'inherit',
@@ -1371,6 +1416,16 @@ async function runSupabaseCli(args, options = {}) {
1371
1416
  });
1372
1417
  }
1373
1418
 
1419
+ async function getSupabaseBinary(projectDir) {
1420
+ const binDir = resolve(projectDir, 'node_modules', '.bin');
1421
+ const ext = IS_WINDOWS ? '.cmd' : '';
1422
+ const binaryPath = resolve(binDir, `supabase${ext}`);
1423
+ if (await fs.pathExists(binaryPath)) {
1424
+ return binaryPath;
1425
+ }
1426
+ return 'npx';
1427
+ }
1428
+
1374
1429
  function buildNextConfigContent(editorUtilNames) {
1375
1430
  const aliasLines = [];
1376
1431
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-nextblock",
3
- "version": "0.2.38",
3
+ "version": "0.2.40",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextblock-cms/template",
3
- "version": "0.2.16",
3
+ "version": "0.2.18",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "dev": "next dev",