create-nextblock 0.8.0 → 0.8.2
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
CHANGED
|
@@ -19,6 +19,7 @@ const TEMPLATE_DIR = resolve(__dirname, '../templates/nextblock-template');
|
|
|
19
19
|
const REPO_ROOT = resolve(__dirname, '../../..');
|
|
20
20
|
const EDITOR_UTILS_SOURCE_DIR = resolve(REPO_ROOT, 'libs/editor/src/lib/utils');
|
|
21
21
|
const IS_WINDOWS = process.platform === 'win32';
|
|
22
|
+
const CLI_VERSION = createRequire(import.meta.url)('../package.json').version;
|
|
22
23
|
|
|
23
24
|
const UI_PROXY_MODULES = [
|
|
24
25
|
'avatar',
|
|
@@ -52,7 +53,10 @@ const PACKAGE_VERSION_SOURCES = {
|
|
|
52
53
|
'@nextblock-cms/sdk': resolve(REPO_ROOT, 'libs/sdk/package.json'),
|
|
53
54
|
};
|
|
54
55
|
|
|
55
|
-
program
|
|
56
|
+
program
|
|
57
|
+
.name('create-nextblock')
|
|
58
|
+
.description('NextBlock™ CMS CLI')
|
|
59
|
+
.version(CLI_VERSION, '-v, --version');
|
|
56
60
|
|
|
57
61
|
program
|
|
58
62
|
.command('create [project-directory]', { isDefault: true })
|
|
@@ -77,6 +81,46 @@ async function handleCommand(projectDirectory, options) {
|
|
|
77
81
|
const { skipInstall, yes } = options;
|
|
78
82
|
|
|
79
83
|
try {
|
|
84
|
+
console.log(chalk.bold.cyan(`\n🧱 create-nextblock v${CLI_VERSION}\n`));
|
|
85
|
+
|
|
86
|
+
// Prerequisites gate (interactive only) — shown BEFORE we ask for a name, scaffold, or
|
|
87
|
+
// install, so anyone who isn't ready can cancel without creating anything.
|
|
88
|
+
if (!yes) {
|
|
89
|
+
clack.note(
|
|
90
|
+
[
|
|
91
|
+
'1. A Supabase project https://supabase.com/dashboard',
|
|
92
|
+
' • Reference ID — Project Settings > General > "Reference ID"',
|
|
93
|
+
' • Connection string — Connect (top bar) > Direct connection > URI',
|
|
94
|
+
' • anon + service_role keys — Project Settings > API Keys',
|
|
95
|
+
' • Personal Access Token — Account > Access Tokens > Generate new token',
|
|
96
|
+
'',
|
|
97
|
+
'2. A Cloudflare R2 bucket https://dash.cloudflare.com > R2',
|
|
98
|
+
' • Create a bucket, then enable its Public Development URL (Bucket > Settings > General)',
|
|
99
|
+
' • Create an R2 API token (Object Read & Write); copy the Access Key ID + Secret (shown once)',
|
|
100
|
+
'',
|
|
101
|
+
'3. SMTP credentials SMTP2GO works very well: https://www.smtp2go.com',
|
|
102
|
+
' • Required so Supabase can email the confirmation link your first admin needs to sign in',
|
|
103
|
+
].join('\n'),
|
|
104
|
+
'Before you continue, have all of the following ready',
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
const ready = await clack.confirm({
|
|
108
|
+
message:
|
|
109
|
+
'Do you have your Supabase, Cloudflare R2, and SMTP details ready?',
|
|
110
|
+
initialValue: true,
|
|
111
|
+
});
|
|
112
|
+
if (clack.isCancel(ready)) {
|
|
113
|
+
handleWizardCancel('Setup cancelled.');
|
|
114
|
+
}
|
|
115
|
+
if (!ready) {
|
|
116
|
+
clack.note(
|
|
117
|
+
'No problem — nothing was created. Gather the items above, then run\n`npm create nextblock` again. Full guide: docs/05-DEVELOPER-GUIDE.md',
|
|
118
|
+
'Come back when ready',
|
|
119
|
+
);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
80
124
|
let projectName = projectDirectory;
|
|
81
125
|
|
|
82
126
|
if (!projectName) {
|
|
@@ -162,32 +206,35 @@ async function handleCommand(projectDirectory, options) {
|
|
|
162
206
|
await ensurePublicNpmrc(projectDir);
|
|
163
207
|
console.log(chalk.green('Enforced public registry for initial install.'));
|
|
164
208
|
|
|
209
|
+
await initializeGit(projectDir);
|
|
210
|
+
|
|
165
211
|
if (!skipInstall) {
|
|
166
212
|
await installDependencies(projectDir);
|
|
167
213
|
} else {
|
|
168
214
|
console.log(chalk.yellow('Skipping dependency installation.'));
|
|
169
215
|
}
|
|
170
216
|
|
|
171
|
-
// Run setup wizard after dependencies are installed so package assets are available
|
|
217
|
+
// Run the setup wizard after dependencies are installed so package assets are available.
|
|
218
|
+
// When it runs, its own "next steps" outro (cd + npm run dev) is the final message, so we
|
|
219
|
+
// don't print a second closing block here — the whole flow completes in this one command.
|
|
172
220
|
if (!yes) {
|
|
173
221
|
await runSetupWizard(projectDir, projectName);
|
|
174
222
|
} else {
|
|
223
|
+
// Non-interactive path: nothing was configured, so point the user at their env file.
|
|
224
|
+
console.log(
|
|
225
|
+
chalk.green(
|
|
226
|
+
`\nSuccess! Your NextBlock™ CMS project "${projectName}" is scaffolded.\n`,
|
|
227
|
+
),
|
|
228
|
+
);
|
|
229
|
+
console.log(chalk.cyan('Next steps:'));
|
|
230
|
+
console.log(chalk.cyan(` 1. cd ${projectName}`));
|
|
175
231
|
console.log(
|
|
176
|
-
chalk.
|
|
177
|
-
'
|
|
232
|
+
chalk.gray(
|
|
233
|
+
' 2. Add your Supabase / R2 / SMTP values to .env.local (template in .env.example)',
|
|
178
234
|
),
|
|
179
235
|
);
|
|
236
|
+
console.log(chalk.cyan(' 3. npm run dev'));
|
|
180
237
|
}
|
|
181
|
-
|
|
182
|
-
await initializeGit(projectDir);
|
|
183
|
-
|
|
184
|
-
console.log(
|
|
185
|
-
chalk.green(
|
|
186
|
-
`\nSuccess! Your NextBlock™ CMS project "${projectName}" is ready.\n`,
|
|
187
|
-
),
|
|
188
|
-
);
|
|
189
|
-
console.log(chalk.cyan('Next step:'));
|
|
190
|
-
console.log(chalk.cyan(` cd ${projectName} && npm run dev`));
|
|
191
238
|
} catch (error) {
|
|
192
239
|
console.error(
|
|
193
240
|
chalk.red(
|
|
@@ -506,42 +553,9 @@ async function runSetupWizard(projectDir, projectName) {
|
|
|
506
553
|
const projectPath = resolve(projectDir);
|
|
507
554
|
process.chdir(projectPath);
|
|
508
555
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
// developer has everything BEFORE we start prompting.
|
|
513
|
-
clack.note(
|
|
514
|
-
[
|
|
515
|
-
'1. A Supabase project https://supabase.com/dashboard',
|
|
516
|
-
' • Reference ID — Project Settings > General > "Reference ID"',
|
|
517
|
-
' • Connection string — Connect (top bar) > Direct connection > URI',
|
|
518
|
-
' • anon + service_role keys — Project Settings > API Keys',
|
|
519
|
-
' • Personal Access Token — Account > Access Tokens > Generate new token',
|
|
520
|
-
'',
|
|
521
|
-
'2. A Cloudflare R2 bucket https://dash.cloudflare.com > R2',
|
|
522
|
-
' • Create a bucket, then enable its Public Development URL (Bucket > Settings > General)',
|
|
523
|
-
' • Create an R2 API token (Object Read & Write); copy the Access Key ID + Secret (shown once)',
|
|
524
|
-
'',
|
|
525
|
-
'3. SMTP credentials SMTP2GO works very well: https://www.smtp2go.com',
|
|
526
|
-
' • Required so Supabase can email the confirmation link your first admin needs to sign in',
|
|
527
|
-
].join('\n'),
|
|
528
|
-
'Before you continue, have all of the following ready',
|
|
529
|
-
);
|
|
530
|
-
|
|
531
|
-
const ready = await clack.confirm({
|
|
532
|
-
message: 'Do you have your Supabase, Cloudflare R2, and SMTP details ready?',
|
|
533
|
-
initialValue: true,
|
|
534
|
-
});
|
|
535
|
-
if (clack.isCancel(ready)) {
|
|
536
|
-
handleWizardCancel('Setup cancelled.');
|
|
537
|
-
}
|
|
538
|
-
if (!ready) {
|
|
539
|
-
clack.note(
|
|
540
|
-
'No problem — your project files are ready. Gather the items above, then copy\n.env.example to .env.local and fill it in. Full guide: docs/05-DEVELOPER-GUIDE.md',
|
|
541
|
-
'Setup paused',
|
|
542
|
-
);
|
|
543
|
-
return;
|
|
544
|
-
}
|
|
556
|
+
// Prerequisites + readiness were already confirmed up front in handleCommand (before any
|
|
557
|
+
// scaffolding), so the wizard goes straight to collecting configuration.
|
|
558
|
+
clack.intro('🚀 NextBlock™ CMS setup');
|
|
545
559
|
|
|
546
560
|
await fs.ensureDir(resolve(projectPath, 'supabase'));
|
|
547
561
|
|
|
@@ -1801,6 +1815,46 @@ async function transformPackageJson(projectDir) {
|
|
|
1801
1815
|
}
|
|
1802
1816
|
}
|
|
1803
1817
|
|
|
1818
|
+
// Mirror the monorepo's defensive dependency overrides into the generated project so a
|
|
1819
|
+
// fresh `npm install` reproduces the "0 vulnerabilities" posture and silences deprecated
|
|
1820
|
+
// transitive deps (e.g. uuid@10). Read live from the repo root when available (local dev /
|
|
1821
|
+
// `npm run test-create`); fall back to this baked-in set in the published CLI where the
|
|
1822
|
+
// monorepo root is not on disk. Keep the fallback in sync with the root package.json.
|
|
1823
|
+
const FALLBACK_OVERRIDES = {
|
|
1824
|
+
postcss: '^8.5.12',
|
|
1825
|
+
qs: '^6.15.2',
|
|
1826
|
+
uuid: '^11.1.1',
|
|
1827
|
+
glob: '^10.4.5',
|
|
1828
|
+
'whatwg-encoding': 'npm:@exodus/bytes@latest',
|
|
1829
|
+
'node-domexception': 'npm:domexception@latest',
|
|
1830
|
+
keygrip: 'npm:keygrip@latest',
|
|
1831
|
+
};
|
|
1832
|
+
let rootOverrides = FALLBACK_OVERRIDES;
|
|
1833
|
+
try {
|
|
1834
|
+
const rootPkg = await fs.readJSON(resolve(REPO_ROOT, 'package.json'));
|
|
1835
|
+
if (rootPkg?.overrides && Object.keys(rootPkg.overrides).length > 0) {
|
|
1836
|
+
rootOverrides = rootPkg.overrides;
|
|
1837
|
+
}
|
|
1838
|
+
} catch {
|
|
1839
|
+
// Published CLI: repo root package.json not present — keep the baked-in fallback.
|
|
1840
|
+
}
|
|
1841
|
+
// Project-specific overrides (if any) win over the inherited defaults.
|
|
1842
|
+
packageJson.overrides = { ...rootOverrides, ...(packageJson.overrides ?? {}) };
|
|
1843
|
+
|
|
1844
|
+
// npm throws EOVERRIDE when a package is BOTH a direct dependency and has an override with a
|
|
1845
|
+
// different spec (e.g. dependencies.uuid ^11.0.4 vs overrides.uuid ^11.1.1). Align any such
|
|
1846
|
+
// direct (dev)dependency to the override value so they share the exact same spec — which is
|
|
1847
|
+
// also what lets the override dedupe that package's transitive copies.
|
|
1848
|
+
for (const [name, spec] of Object.entries(packageJson.overrides)) {
|
|
1849
|
+
if (typeof spec !== 'string') continue;
|
|
1850
|
+
if (packageJson.dependencies?.[name] !== undefined) {
|
|
1851
|
+
packageJson.dependencies[name] = spec;
|
|
1852
|
+
}
|
|
1853
|
+
if (packageJson.devDependencies?.[name] !== undefined) {
|
|
1854
|
+
packageJson.devDependencies[name] = spec;
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1804
1858
|
await fs.writeJSON(packageJsonPath, packageJson, { spaces: 2 });
|
|
1805
1859
|
}
|
|
1806
1860
|
|
package/package.json
CHANGED