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.
- package/bin/create-nextblock.js +94 -61
- package/package.json +1 -1
package/bin/create-nextblock.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
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:
|
|
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(
|
|
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
|
|