create-nextblock 0.2.20 → 0.2.22

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.
@@ -188,8 +188,9 @@ async function runSetupWizard(projectDir, projectName) {
188
188
  clack.note('I will now open your browser to log into Supabase.');
189
189
  await runSupabaseCli(['login'], { cwd: projectPath });
190
190
 
191
+ const assetsState = await ensureSupabaseAssets(projectPath, { required: true, resetProjectRef: true });
191
192
  clack.note('Now, please select your NextBlock project when prompted.');
192
- const linkResult = await runSupabaseCli(['link'], { cwd: projectPath });
193
+ await runSupabaseCli(['link'], { cwd: projectPath });
193
194
  if (process.stdin.isTTY) {
194
195
  try {
195
196
  process.stdin.setRawMode(false);
@@ -200,8 +201,7 @@ async function runSetupWizard(projectDir, projectName) {
200
201
  process.stdin.resume();
201
202
  }
202
203
 
203
- const assetsState = await ensureSupabaseAssets(projectPath, { required: true });
204
- let projectId = extractProjectRefFromOutput(linkResult.stdout || '');
204
+ let projectId = await readSupabaseProjectRef(projectPath);
205
205
 
206
206
  if (!projectId && assetsState.projectId) {
207
207
  projectId = assetsState.projectId;
@@ -719,14 +719,15 @@ SMTP_FROM_NAME=
719
719
  }
720
720
 
721
721
  async function ensureSupabaseAssets(projectDir, options = {}) {
722
- const { required = false } = options;
722
+ const { required = false, resetProjectRef = false } = options;
723
723
  const destSupabaseDir = resolve(projectDir, 'supabase');
724
724
  await fs.ensureDir(destSupabaseDir);
725
725
 
726
- const packageSupabaseDir = await resolvePackageSupabaseDir();
726
+ const { dir: packageSupabaseDir, triedPaths } = await resolvePackageSupabaseDir(projectDir);
727
727
  if (!packageSupabaseDir) {
728
728
  const message =
729
- 'Unable to locate supabase assets in @nextblock-cms/db. Please reinstall dependencies and try again.';
729
+ 'Unable to locate supabase assets in @nextblock-cms/db. Please ensure dependencies are installed.' +
730
+ (triedPaths.length > 0 ? `\nChecked:\n - ${triedPaths.join('\n - ')}` : '');
730
731
  if (required) {
731
732
  throw new Error(message);
732
733
  } else {
@@ -759,31 +760,105 @@ async function ensureSupabaseAssets(projectDir, options = {}) {
759
760
  migrationsCopied = true;
760
761
  }
761
762
 
763
+ if (resetProjectRef) {
764
+ const tempDir = resolve(destSupabaseDir, '.temp');
765
+ const projectRefPath = resolve(tempDir, 'project-ref');
766
+ if (await fs.pathExists(projectRefPath)) {
767
+ await fs.writeFile(projectRefPath, '');
768
+ }
769
+ }
770
+
762
771
  if (required) {
763
772
  if (!configCopied) {
764
- throw new Error('Missing supabase/config.toml in the installed @nextblock-cms/db package.');
773
+ throw new Error(
774
+ `Missing supabase/config.toml in the installed @nextblock-cms/db package (checked ${packageSupabaseDir}).`,
775
+ );
765
776
  }
766
777
  if (!migrationsCopied) {
767
- throw new Error('Missing supabase/migrations in the installed @nextblock-cms/db package.');
778
+ throw new Error(
779
+ `Missing supabase/migrations in the installed @nextblock-cms/db package (checked ${packageSupabaseDir}).`,
780
+ );
768
781
  }
769
782
  }
770
783
 
771
784
  return { migrationsCopied, configCopied, projectId: detectedProjectId };
772
785
  }
773
786
 
774
- async function resolvePackageSupabaseDir() {
775
- try {
776
- const pkgPath = require.resolve('@nextblock-cms/db/package.json');
777
- const pkgDir = dirname(pkgPath);
778
- const candidates = [resolve(pkgDir, 'supabase'), resolve(pkgDir, 'lib', 'supabase')];
779
- for (const candidate of candidates) {
787
+ async function resolvePackageSupabaseDir(projectDir) {
788
+ const triedPaths = [];
789
+ const candidateBases = new Set();
790
+
791
+ const installDir = resolve(projectDir, 'node_modules', '@nextblock-cms', 'db');
792
+ candidateBases.add(installDir);
793
+
794
+ const tryResolveFrom = (fromPath) => {
795
+ try {
796
+ const resolver = createRequire(fromPath);
797
+ const pkgPath = resolver.resolve('@nextblock-cms/db/package.json');
798
+ return dirname(pkgPath);
799
+ } catch {
800
+ return null;
801
+ }
802
+ };
803
+
804
+ const projectPkg = resolve(projectDir, 'package.json');
805
+ const resolvedProject = tryResolveFrom(projectPkg);
806
+ if (resolvedProject) {
807
+ candidateBases.add(resolvedProject);
808
+ const parent = dirname(resolvedProject);
809
+ candidateBases.add(parent);
810
+ }
811
+
812
+ const localResolve = tryResolveFrom(__filename);
813
+ if (localResolve) {
814
+ candidateBases.add(localResolve);
815
+ candidateBases.add(dirname(localResolve));
816
+ }
817
+
818
+ candidateBases.add(REPO_ROOT);
819
+ candidateBases.add(resolve(REPO_ROOT, 'libs', 'db'));
820
+ candidateBases.add(resolve(REPO_ROOT, 'dist', 'libs', 'db'));
821
+
822
+ const candidateSegments = [
823
+ 'supabase',
824
+ 'src/supabase',
825
+ 'dist/supabase',
826
+ 'dist/libs/db/supabase',
827
+ 'dist/lib/supabase',
828
+ 'lib/supabase',
829
+ ];
830
+
831
+ for (const base of Array.from(candidateBases).filter(Boolean)) {
832
+ for (const segment of candidateSegments) {
833
+ const candidate = resolve(base, segment);
834
+ triedPaths.push(candidate);
780
835
  if (await fs.pathExists(candidate)) {
781
- return candidate;
836
+ return { dir: candidate, triedPaths };
782
837
  }
783
838
  }
784
- } catch {
785
- return null;
786
839
  }
840
+
841
+ return { dir: null, triedPaths };
842
+ }
843
+
844
+ async function readSupabaseProjectRef(projectDir) {
845
+ const configTomlPath = resolve(projectDir, 'supabase', 'config.toml');
846
+ if (await fs.pathExists(configTomlPath)) {
847
+ const config = await fs.readFile(configTomlPath, 'utf8');
848
+ const configMatch = config.match(/project_id\s*=\s*"([^"]+)"/);
849
+ if (configMatch?.[1] && !configMatch[1].includes('env(')) {
850
+ return configMatch[1];
851
+ }
852
+ }
853
+
854
+ const projectRefPath = resolve(projectDir, 'supabase', '.temp', 'project-ref');
855
+ if (await fs.pathExists(projectRefPath)) {
856
+ const value = (await fs.readFile(projectRefPath, 'utf8')).trim();
857
+ if (/^[a-z0-9]{20,}$/i.test(value)) {
858
+ return value;
859
+ }
860
+ }
861
+
787
862
  return null;
788
863
  }
789
864
 
@@ -1282,22 +1357,7 @@ async function runSupabaseCli(args, options = {}) {
1282
1357
  const child = spawn('npx', ['supabase', ...args], {
1283
1358
  cwd,
1284
1359
  shell: IS_WINDOWS,
1285
- stdio: ['inherit', 'pipe', 'pipe'],
1286
- });
1287
-
1288
- let stdout = '';
1289
- let stderr = '';
1290
-
1291
- child.stdout?.on('data', (chunk) => {
1292
- const text = chunk.toString();
1293
- stdout += text;
1294
- process.stdout.write(text);
1295
- });
1296
-
1297
- child.stderr?.on('data', (chunk) => {
1298
- const text = chunk.toString();
1299
- stderr += text;
1300
- process.stderr.write(text);
1360
+ stdio: 'inherit',
1301
1361
  });
1302
1362
 
1303
1363
  child.on('error', (error) => {
@@ -1306,7 +1366,7 @@ async function runSupabaseCli(args, options = {}) {
1306
1366
 
1307
1367
  child.on('close', (code) => {
1308
1368
  if (code === 0) {
1309
- resolve({ stdout, stderr });
1369
+ resolve();
1310
1370
  } else {
1311
1371
  reject(new Error(`supabase ${args.join(' ')} exited with code ${code}`));
1312
1372
  }
@@ -1314,33 +1374,6 @@ async function runSupabaseCli(args, options = {}) {
1314
1374
  });
1315
1375
  }
1316
1376
 
1317
- function extractProjectRefFromOutput(output) {
1318
- const sanitized = stripAnsiCodes(output);
1319
- const regexes = [
1320
- /project(?:\s+ref(?:erence)?)?\s*[:=]\s*([a-z0-9]{20,})/i,
1321
- /project_ref\s*[:=]\s*([a-z0-9]{20,})/i,
1322
- /\(ref:\s*([a-z0-9]{20,})\s*\)/i,
1323
- ];
1324
-
1325
- for (const regex of regexes) {
1326
- const match = sanitized.match(regex);
1327
- if (match?.[1]) {
1328
- return match[1];
1329
- }
1330
- }
1331
-
1332
- const fallback = sanitized.match(/\b[a-z0-9]{20,}\b/gi);
1333
- if (fallback?.length === 1) {
1334
- return fallback[0];
1335
- }
1336
-
1337
- return null;
1338
- }
1339
-
1340
- function stripAnsiCodes(input = '') {
1341
- return input.replace(/\x1b\[[0-9;]*m/g, '').replace(/\u001b\[[0-9;]*[A-Za-z]/g, '');
1342
- }
1343
-
1344
1377
  function buildNextConfigContent(editorUtilNames) {
1345
1378
  const aliasLines = [];
1346
1379
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-nextblock",
3
- "version": "0.2.20",
3
+ "version": "0.2.22",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {