create-nextjs-cms 0.5.32 → 0.5.34
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/dist/index.js +84 -150
- package/dist/lib/render-title.d.ts +2 -0
- package/dist/lib/render-title.d.ts.map +1 -0
- package/dist/lib/render-title.js +21 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +36 -8
- package/package.json +6 -5
- package/templates/default/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -5,10 +5,11 @@ import { fileURLToPath } from 'node:url';
|
|
|
5
5
|
import { randomBytes } from 'node:crypto';
|
|
6
6
|
import path, { dirname, resolve, relative, basename } from 'node:path';
|
|
7
7
|
import { Command } from 'commander';
|
|
8
|
-
import
|
|
8
|
+
import { text, confirm, spinner, log } from '@clack/prompts';
|
|
9
9
|
import { expandHome, isValidPkgName, isEmptyDir, detectPackageManager, validateTemplate } from './lib/utils.js';
|
|
10
10
|
import { readFileSync } from 'node:fs';
|
|
11
11
|
import chalk from 'chalk';
|
|
12
|
+
import { renderTitle } from './lib/render-title.js';
|
|
12
13
|
/** Resolve __dirname for ESM */
|
|
13
14
|
const __filename = fileURLToPath(import.meta.url);
|
|
14
15
|
const __dirname = dirname(__filename);
|
|
@@ -22,15 +23,6 @@ const templateDir = fileURLToPath(new URL('../templates/default/', import.meta.u
|
|
|
22
23
|
const handleSigTerm = () => process.exit(0);
|
|
23
24
|
process.on('SIGINT', handleSigTerm);
|
|
24
25
|
process.on('SIGTERM', handleSigTerm);
|
|
25
|
-
const onPromptState = (state) => {
|
|
26
|
-
if (state.aborted) {
|
|
27
|
-
// If we don't re-enable the terminal cursor before exiting
|
|
28
|
-
// the program, the cursor will remain hidden
|
|
29
|
-
process.stdout.write('\x1B[?25h');
|
|
30
|
-
process.stdout.write('\n');
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
26
|
/**
|
|
35
27
|
* Creates a blog section file in the sections folder
|
|
36
28
|
*/
|
|
@@ -39,7 +31,7 @@ async function createBlogSection(targetDir) {
|
|
|
39
31
|
const blogSectionPath = path.join(sectionsDir, 'blog.section.ts');
|
|
40
32
|
// Ensure sections directory exists
|
|
41
33
|
await fs.ensureDir(sectionsDir);
|
|
42
|
-
const blogSectionContent = `import {
|
|
34
|
+
const blogSectionContent = `import { photoField, richTextField, textField, tagsField } from 'nextjs-cms/core/fields'
|
|
43
35
|
import { hasItemsSection } from 'nextjs-cms/core/sections'
|
|
44
36
|
|
|
45
37
|
const title = textField({
|
|
@@ -49,67 +41,27 @@ const title = textField({
|
|
|
49
41
|
order: 1,
|
|
50
42
|
})
|
|
51
43
|
|
|
52
|
-
const slug = textField({
|
|
53
|
-
name: 'slug',
|
|
54
|
-
label: 'Slug',
|
|
55
|
-
required: false,
|
|
56
|
-
order: 2,
|
|
57
|
-
})
|
|
58
|
-
|
|
59
44
|
const coverPhotoField = photoField({
|
|
60
45
|
name: 'coverphoto',
|
|
61
46
|
label: 'Cover Photo',
|
|
62
|
-
watermark: false,
|
|
63
47
|
required: true,
|
|
64
|
-
order:
|
|
65
|
-
size: {
|
|
66
|
-
width: 1200,
|
|
67
|
-
height: 628,
|
|
68
|
-
crop: true,
|
|
69
|
-
},
|
|
70
|
-
thumbnail: {
|
|
71
|
-
width: 400,
|
|
72
|
-
height: 209,
|
|
73
|
-
crop: true,
|
|
74
|
-
quality: 80,
|
|
75
|
-
},
|
|
48
|
+
order: 2,
|
|
76
49
|
fileType: ['jpg', 'jpeg', 'png', 'webp'],
|
|
77
50
|
})
|
|
78
51
|
|
|
79
|
-
const excerpt = textField({
|
|
80
|
-
name: 'excerpt',
|
|
81
|
-
label: 'Excerpt',
|
|
82
|
-
required: false,
|
|
83
|
-
order: 4,
|
|
84
|
-
})
|
|
85
|
-
|
|
86
52
|
const content = richTextField({
|
|
87
53
|
name: 'content',
|
|
88
54
|
label: 'Content',
|
|
89
55
|
required: true,
|
|
90
|
-
order:
|
|
91
|
-
allowMedia: true
|
|
56
|
+
order: 3,
|
|
92
57
|
})
|
|
93
58
|
|
|
94
|
-
const publishedAt = dateField({
|
|
95
|
-
name: 'published_at',
|
|
96
|
-
label: 'Published At',
|
|
97
|
-
required: false,
|
|
98
|
-
order: 6,
|
|
99
|
-
})
|
|
100
59
|
|
|
101
|
-
const
|
|
102
|
-
name: '
|
|
103
|
-
label: '
|
|
60
|
+
const keywords = tagsField({
|
|
61
|
+
name: 'keywords',
|
|
62
|
+
label: 'Keywords',
|
|
104
63
|
required: false,
|
|
105
|
-
order:
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
const metaKeywords = textField({
|
|
109
|
-
name: 'meta_keywords',
|
|
110
|
-
label: 'Meta Keywords',
|
|
111
|
-
required: false,
|
|
112
|
-
order: 8,
|
|
64
|
+
order: 4,
|
|
113
65
|
})
|
|
114
66
|
|
|
115
67
|
export default hasItemsSection({
|
|
@@ -133,39 +85,17 @@ export default hasItemsSection({
|
|
|
133
85
|
},
|
|
134
86
|
db: {
|
|
135
87
|
table: 'blog',
|
|
136
|
-
fulltext: [
|
|
137
|
-
{
|
|
138
|
-
columns: [title],
|
|
139
|
-
name: 'title_fulltext',
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
columns: [content],
|
|
143
|
-
name: 'content_fulltext',
|
|
144
|
-
},
|
|
145
|
-
],
|
|
146
|
-
unique: [
|
|
147
|
-
{
|
|
148
|
-
columns: [slug],
|
|
149
|
-
name: 'slug_unique',
|
|
150
|
-
},
|
|
151
|
-
],
|
|
152
|
-
index: [
|
|
153
|
-
{
|
|
154
|
-
columns: [publishedAt],
|
|
155
|
-
name: 'published_at_index',
|
|
156
|
-
},
|
|
157
|
-
],
|
|
158
88
|
},
|
|
159
89
|
search: {
|
|
160
|
-
searchFields: [title
|
|
90
|
+
searchFields: [title],
|
|
161
91
|
},
|
|
162
92
|
coverPhotoField: coverPhotoField,
|
|
163
93
|
generateQR: false,
|
|
164
|
-
fields: [title,
|
|
94
|
+
fields: [title, coverPhotoField, content, keywords],
|
|
165
95
|
})
|
|
166
96
|
`;
|
|
167
97
|
await fs.writeFile(blogSectionPath, blogSectionContent, 'utf-8');
|
|
168
|
-
|
|
98
|
+
log.success('Blog section created successfully!');
|
|
169
99
|
}
|
|
170
100
|
/**
|
|
171
101
|
* Generates a random secret string using crypto.randomBytes
|
|
@@ -179,7 +109,7 @@ function generateSecret() {
|
|
|
179
109
|
async function updateEnvSecrets(targetDir) {
|
|
180
110
|
const envPath = path.join(targetDir, '.env');
|
|
181
111
|
if (!(await fs.pathExists(envPath))) {
|
|
182
|
-
|
|
112
|
+
log.warn('No .env file found; skipping secret generation.');
|
|
183
113
|
return;
|
|
184
114
|
}
|
|
185
115
|
try {
|
|
@@ -191,16 +121,17 @@ async function updateEnvSecrets(targetDir) {
|
|
|
191
121
|
envContent = envContent.replace(/ACCESS_TOKEN_EXPIRATION=.*/, 'ACCESS_TOKEN_EXPIRATION=2h');
|
|
192
122
|
envContent = envContent.replace(/REFRESH_TOKEN_EXPIRATION=.*/, 'REFRESH_TOKEN_EXPIRATION=1y');
|
|
193
123
|
await fs.writeFile(envPath, envContent, 'utf-8');
|
|
194
|
-
|
|
124
|
+
log.step('Generated random secrets and set token expirations in .env file');
|
|
195
125
|
}
|
|
196
126
|
catch (e) {
|
|
197
|
-
|
|
198
|
-
|
|
127
|
+
log.warn('Could not update .env secrets automatically.');
|
|
128
|
+
log.error(` Error: ${e instanceof Error ? e.message : 'Unknown error'}`);
|
|
199
129
|
}
|
|
200
130
|
}
|
|
201
131
|
async function createNextjsCms() {
|
|
202
|
-
|
|
203
|
-
|
|
132
|
+
renderTitle();
|
|
133
|
+
log.info('🚀 Welcome to NextJS CMS!');
|
|
134
|
+
log.message('Creating your new CMS project...\n');
|
|
204
135
|
let projectPath = '';
|
|
205
136
|
const program = new Command(packageJson.name)
|
|
206
137
|
.version(packageJson.version, '-v, --version', 'Output the current version of create-nextjs-cms.')
|
|
@@ -227,34 +158,31 @@ async function createNextjsCms() {
|
|
|
227
158
|
try {
|
|
228
159
|
// Ensure template folder is present in the published package
|
|
229
160
|
if (!(await fs.pathExists(templateDir))) {
|
|
230
|
-
|
|
231
|
-
|
|
161
|
+
log.error('Template directory not found in the published package.');
|
|
162
|
+
log.message(' Make sure "templates/" is included in package.json#files and actually published.');
|
|
232
163
|
process.exit(1);
|
|
233
164
|
}
|
|
234
165
|
// Validate template structure
|
|
235
166
|
await validateTemplate(templateDir);
|
|
236
167
|
// If no directory was provided, prompt for project name
|
|
237
168
|
if (!projectPath) {
|
|
238
|
-
const res = await
|
|
239
|
-
onState: onPromptState,
|
|
240
|
-
type: 'text',
|
|
241
|
-
name: 'path',
|
|
169
|
+
const res = await text({
|
|
242
170
|
message: 'What is your project named?',
|
|
243
|
-
|
|
171
|
+
defaultValue: 'my-cms-app',
|
|
244
172
|
validate: (name) => {
|
|
245
173
|
const validation = isValidPkgName(basename(resolve(name)));
|
|
246
174
|
if (validation) {
|
|
247
|
-
return
|
|
175
|
+
return;
|
|
248
176
|
}
|
|
249
177
|
return 'Invalid project name: Project name can only contain letters, numbers, hyphens, and underscores.';
|
|
250
178
|
},
|
|
251
179
|
});
|
|
252
|
-
if (typeof res
|
|
253
|
-
projectPath = res.
|
|
180
|
+
if (typeof res === 'string') {
|
|
181
|
+
projectPath = res.trim();
|
|
254
182
|
}
|
|
255
183
|
}
|
|
256
184
|
if (!projectPath) {
|
|
257
|
-
|
|
185
|
+
log.error('\nPlease specify the project directory:\n' +
|
|
258
186
|
` ${chalk.cyan(program.name())} ${chalk.green('<project-directory>')}\n` +
|
|
259
187
|
'For example:\n' +
|
|
260
188
|
` ${chalk.cyan(program.name())} ${chalk.green('my-cms-app')}\n\n` +
|
|
@@ -268,8 +196,8 @@ async function createNextjsCms() {
|
|
|
268
196
|
options.projectName = basename(options.targetDir);
|
|
269
197
|
// Validate name
|
|
270
198
|
if (!isValidPkgName(options.projectName)) {
|
|
271
|
-
|
|
272
|
-
|
|
199
|
+
log.error(`Could not create a project called ${chalk.red(`"${options.projectName}"`)} because of npm naming restrictions:`);
|
|
200
|
+
log.message(` ${chalk.red('*')} Project name can only contain letters, numbers, hyphens, and underscores.`);
|
|
273
201
|
process.exit(1);
|
|
274
202
|
}
|
|
275
203
|
targetIsCwd = path.normalize(options.targetDir) === path.normalize(process.cwd());
|
|
@@ -279,34 +207,36 @@ async function createNextjsCms() {
|
|
|
279
207
|
await fs.ensureDir(options.targetDir);
|
|
280
208
|
}
|
|
281
209
|
else if (!(await isEmptyDir(options.targetDir))) {
|
|
282
|
-
|
|
283
|
-
|
|
210
|
+
log.error('Current directory is not empty. Choose an empty folder or a new directory name.');
|
|
211
|
+
log.message(chalk.gray('Tip: You can also specify a directory name like this: \n') +
|
|
212
|
+
chalk.green('pnpm create nextjs-cms ') +
|
|
213
|
+
chalk.italic.magenta('my-app'));
|
|
214
|
+
log.message(' ');
|
|
284
215
|
process.exit(1);
|
|
285
216
|
}
|
|
286
217
|
}
|
|
287
218
|
else {
|
|
288
219
|
if (await fs.pathExists(options.targetDir)) {
|
|
289
|
-
|
|
290
|
-
|
|
220
|
+
if (!(await isEmptyDir(options.targetDir))) {
|
|
221
|
+
log.error(`Directory "${options.targetDir}" is not empty.`);
|
|
222
|
+
log.message('Please choose an empty directory or a different directory name.');
|
|
223
|
+
process.exit(1);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
await fs.ensureDir(options.targetDir);
|
|
291
228
|
}
|
|
292
|
-
await fs.ensureDir(options.targetDir);
|
|
293
229
|
}
|
|
294
230
|
// Ask if user wants to add blog section
|
|
295
|
-
const blogRes = await
|
|
296
|
-
onState: onPromptState,
|
|
297
|
-
type: 'toggle',
|
|
298
|
-
name: 'addBlogSection',
|
|
231
|
+
const blogRes = await confirm({
|
|
299
232
|
message: 'Would you like to add a default blog section config?',
|
|
300
|
-
|
|
301
|
-
active: 'Yes',
|
|
302
|
-
inactive: 'No',
|
|
233
|
+
initialValue: false,
|
|
303
234
|
});
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
}
|
|
307
|
-
console.log(`📁 Creating project in: ${options.targetDir}`);
|
|
235
|
+
options.addBlogSection = Boolean(blogRes);
|
|
236
|
+
log.step(`Creating project in: ${options.targetDir}`);
|
|
308
237
|
// Copy template → project dir with a filter to skip build/cache artifacts
|
|
309
|
-
|
|
238
|
+
const copySpinner = spinner();
|
|
239
|
+
copySpinner.start('Copying template files...');
|
|
310
240
|
await fs.copy(options.templateDir, options.targetDir, {
|
|
311
241
|
filter: (src) => {
|
|
312
242
|
const rel = relative(options.templateDir, src);
|
|
@@ -322,7 +252,7 @@ async function createNextjsCms() {
|
|
|
322
252
|
overwrite: true,
|
|
323
253
|
errorOnExist: false,
|
|
324
254
|
});
|
|
325
|
-
|
|
255
|
+
copySpinner.stop('✅ Template copied successfully!');
|
|
326
256
|
// Generate random secrets for .env file
|
|
327
257
|
await updateEnvSecrets(options.targetDir);
|
|
328
258
|
// npm excludes .gitignore from packages, so we rename it back from _gitignore
|
|
@@ -330,11 +260,11 @@ async function createNextjsCms() {
|
|
|
330
260
|
const gitignorePath = path.join(options.targetDir, '.gitignore');
|
|
331
261
|
if (await fs.pathExists(gitignoreTemplatePath)) {
|
|
332
262
|
await fs.move(gitignoreTemplatePath, gitignorePath);
|
|
333
|
-
|
|
263
|
+
log.step('Restored .gitignore file');
|
|
334
264
|
}
|
|
335
265
|
// Create blog section if requested
|
|
336
266
|
if (options.addBlogSection) {
|
|
337
|
-
|
|
267
|
+
log.info('Creating blog section...');
|
|
338
268
|
await createBlogSection(options.targetDir);
|
|
339
269
|
}
|
|
340
270
|
// Update package.json name (if template contains package.json)
|
|
@@ -344,45 +274,48 @@ async function createNextjsCms() {
|
|
|
344
274
|
const pkg = (await fs.readJson(packageJsonPath));
|
|
345
275
|
pkg.name = options.projectName;
|
|
346
276
|
await fs.writeJson(packageJsonPath, pkg, { spaces: 2 });
|
|
347
|
-
|
|
277
|
+
log.step(`Updated package.json name to: ${options.projectName}`);
|
|
348
278
|
}
|
|
349
279
|
catch (e) {
|
|
350
|
-
|
|
351
|
-
|
|
280
|
+
log.warn('Could not update package.json name automatically.');
|
|
281
|
+
log.error(` Error: ${e instanceof Error ? e.message : 'Unknown error'}`);
|
|
352
282
|
}
|
|
353
283
|
}
|
|
354
284
|
else {
|
|
355
|
-
|
|
285
|
+
log.warn('No package.json found in template root; skipping name update.');
|
|
356
286
|
}
|
|
357
|
-
|
|
287
|
+
log.info('Installing dependencies...');
|
|
358
288
|
process.chdir(options.targetDir);
|
|
289
|
+
const installSpinner = spinner();
|
|
290
|
+
installSpinner.start('Installing dependencies...');
|
|
359
291
|
const preferredPM = detectPackageManager();
|
|
292
|
+
log.step(`Using ${chalk.green(preferredPM)} as the package manager...`);
|
|
360
293
|
let installed = false;
|
|
361
294
|
// Try preferred package manager first
|
|
362
295
|
try {
|
|
363
296
|
if (preferredPM === 'pnpm') {
|
|
364
297
|
execSync('pnpm install', { stdio: 'inherit' });
|
|
365
298
|
installed = true;
|
|
366
|
-
|
|
299
|
+
installSpinner.stop('✅ Dependencies installed with pnpm!');
|
|
367
300
|
}
|
|
368
301
|
else if (preferredPM === 'yarn') {
|
|
369
302
|
execSync('yarn install', { stdio: 'inherit' });
|
|
370
303
|
installed = true;
|
|
371
|
-
|
|
304
|
+
installSpinner.stop('✅ Dependencies installed with yarn!');
|
|
372
305
|
}
|
|
373
306
|
else if (preferredPM === 'bun') {
|
|
374
307
|
execSync('bun install', { stdio: 'inherit' });
|
|
375
308
|
installed = true;
|
|
376
|
-
|
|
309
|
+
installSpinner.stop('✅ Dependencies installed with bun!');
|
|
377
310
|
}
|
|
378
311
|
else {
|
|
379
312
|
execSync('npm install', { stdio: 'inherit' });
|
|
380
313
|
installed = true;
|
|
381
|
-
|
|
314
|
+
installSpinner.stop('✅ Dependencies installed with npm!');
|
|
382
315
|
}
|
|
383
316
|
}
|
|
384
317
|
catch {
|
|
385
|
-
|
|
318
|
+
installSpinner.message(`❌ ${preferredPM} install failed. Trying alternatives...`);
|
|
386
319
|
// Fallback to other package managers
|
|
387
320
|
const fallbacks = preferredPM === 'pnpm'
|
|
388
321
|
? ['npm', 'yarn', 'bun']
|
|
@@ -393,49 +326,50 @@ async function createNextjsCms() {
|
|
|
393
326
|
try {
|
|
394
327
|
execSync(`${pm} install`, { stdio: 'inherit' });
|
|
395
328
|
installed = true;
|
|
396
|
-
|
|
329
|
+
installSpinner.stop(`✅ Dependencies installed with ${pm}!`);
|
|
397
330
|
break;
|
|
398
331
|
}
|
|
399
332
|
catch {
|
|
400
|
-
|
|
333
|
+
installSpinner.message(`❌ ${pm} install failed.`);
|
|
401
334
|
}
|
|
402
335
|
}
|
|
403
336
|
if (!installed) {
|
|
404
|
-
|
|
405
|
-
|
|
337
|
+
installSpinner.stop('❌ Failed to install dependencies automatically.');
|
|
338
|
+
log.error(' Please run "pnpm install", "npm install", "yarn install", or "bun install" manually.');
|
|
406
339
|
}
|
|
407
340
|
}
|
|
408
341
|
// Run CMS setup
|
|
409
|
-
|
|
342
|
+
const setupSpinner = spinner();
|
|
343
|
+
setupSpinner.start('Running CMS setup...');
|
|
410
344
|
try {
|
|
411
345
|
execSync('pnpm next-cms-kit:dev setup', { stdio: 'inherit' });
|
|
412
|
-
|
|
346
|
+
setupSpinner.stop('✅ CMS setup completed successfully!');
|
|
413
347
|
}
|
|
414
348
|
catch (error) {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
349
|
+
setupSpinner.stop('⚠️ CMS setup failed. You may need to run it manually:');
|
|
350
|
+
log.warn(' pnpm next-cms-kit:dev setup');
|
|
351
|
+
log.error(` Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
418
352
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
353
|
+
log.success('\n🎉 Your NextJS CMS project has been created successfully!');
|
|
354
|
+
log.message('\nNext steps:');
|
|
355
|
+
log.message(` cd ${options.projectName}`);
|
|
356
|
+
log.message(installed
|
|
423
357
|
? ` ${preferredPM} dev # or: npm run dev`
|
|
424
358
|
: ` ${preferredPM} install && ${preferredPM} dev # or: npm install && npm run dev`);
|
|
425
|
-
|
|
359
|
+
log.message('\nHappy coding! 🚀');
|
|
426
360
|
}
|
|
427
361
|
catch (error) {
|
|
428
|
-
|
|
362
|
+
log.error(`❌ Failed to create project: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
429
363
|
// Clean up partial installation on error
|
|
430
364
|
if ((await fs.pathExists(options.targetDir)) && !targetIsCwd) {
|
|
431
|
-
|
|
365
|
+
log.info('🧹 Cleaning up partial installation...');
|
|
432
366
|
try {
|
|
433
367
|
await fs.remove(options.targetDir);
|
|
434
|
-
|
|
368
|
+
log.success('✅ Cleanup completed.');
|
|
435
369
|
}
|
|
436
370
|
catch {
|
|
437
|
-
|
|
438
|
-
|
|
371
|
+
log.error('⚠️ Could not clean up partial installation.');
|
|
372
|
+
log.message(` Please manually remove: ${options.targetDir}`);
|
|
439
373
|
}
|
|
440
374
|
}
|
|
441
375
|
process.exit(1);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-title.d.ts","sourceRoot":"","sources":["../../src/lib/render-title.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,WAAW,YASvB,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import gradient from 'gradient-string';
|
|
2
|
+
import { TITLE_TEXT } from './utils.js';
|
|
3
|
+
import { detectPackageManager } from './utils.js';
|
|
4
|
+
// colors brought in from vscode poimandres theme
|
|
5
|
+
const poimandresTheme = {
|
|
6
|
+
blue: '#add7ff',
|
|
7
|
+
cyan: '#89ddff',
|
|
8
|
+
green: '#5de4c7',
|
|
9
|
+
magenta: '#fae4fc',
|
|
10
|
+
red: '#d0679d',
|
|
11
|
+
yellow: '#fffac2',
|
|
12
|
+
};
|
|
13
|
+
export const renderTitle = () => {
|
|
14
|
+
const titleGradient = gradient(Object.values(poimandresTheme));
|
|
15
|
+
// resolves weird behavior where the ascii is offset
|
|
16
|
+
const pkgManager = detectPackageManager();
|
|
17
|
+
if (pkgManager === 'yarn' || pkgManager === 'pnpm') {
|
|
18
|
+
console.log('');
|
|
19
|
+
}
|
|
20
|
+
console.log(titleGradient.multiline(TITLE_TEXT));
|
|
21
|
+
};
|
package/dist/lib/utils.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare const TITLE_TEXT = "\n _\n ___ _ __ ___ __ _| |_ ___\n / __| '__/ _ \\/ _\\` | __/ _ \\\n | (__| | | __/ (_| | || __/\n \\___|_| \\___|\\__,_|\\__\\___|\n _ _\n _ __ _____ _| |_ (_)___\n | '_ \\ / _ \\ \\/ / __|| / __|\n | | | | __/> <| |_ | \\__ \\\n |_| |_|\\___/_/\\_\\__|/ |___/\n |__/\n ___ _ __ ___ ___\n / __| '_ \\` _ \\/ __|\n | (__| | | | | \\__ \\\n \\___|_| |_| |_|___/\n";
|
|
1
2
|
/** Expand ~ to home */
|
|
2
3
|
export declare function expandHome(p: string): string;
|
|
3
4
|
/** Validate npm package name (simple rule) */
|
|
@@ -5,6 +6,7 @@ export declare function isValidPkgName(name: string): boolean;
|
|
|
5
6
|
/** Check if a directory is empty */
|
|
6
7
|
export declare function isEmptyDir(dir: string): Promise<boolean>;
|
|
7
8
|
/** Detect preferred package manager */
|
|
9
|
+
export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';
|
|
8
10
|
export declare function detectPackageManager(): 'pnpm' | 'npm' | 'yarn' | 'bun';
|
|
9
11
|
/** Validate template structure */
|
|
10
12
|
export declare function validateTemplate(templateDir: string): Promise<void>;
|
package/dist/lib/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAIA,uBAAuB;AACvB,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAG5C;AAED,8CAA8C;AAC9C,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,oCAAoC;AACpC,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO9D;AAED,uCAAuC;AACvC,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU,4jBAgBtB,CAAA;AAED,uBAAuB;AACvB,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAG5C;AAED,8CAA8C;AAC9C,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,oCAAoC;AACpC,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO9D;AAED,uCAAuC;AACvC,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAA;AAC5D,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAkBtE;AAED,kCAAkC;AAClC,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAczE"}
|
package/dist/lib/utils.js
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import os from 'node:os';
|
|
4
|
+
export const TITLE_TEXT = `
|
|
5
|
+
_
|
|
6
|
+
___ _ __ ___ __ _| |_ ___
|
|
7
|
+
/ __| '__/ _ \\/ _\\\` | __/ _ \\
|
|
8
|
+
| (__| | | __/ (_| | || __/
|
|
9
|
+
\\___|_| \\___|\\__,_|\\__\\___|
|
|
10
|
+
_ _
|
|
11
|
+
_ __ _____ _| |_ (_)___
|
|
12
|
+
| '_ \\ / _ \\ \\/ / __|| / __|
|
|
13
|
+
| | | | __/> <| |_ | \\__ \\
|
|
14
|
+
|_| |_|\\___/_/\\_\\__|/ |___/
|
|
15
|
+
|__/
|
|
16
|
+
___ _ __ ___ ___
|
|
17
|
+
/ __| '_ \\\` _ \\/ __|
|
|
18
|
+
| (__| | | | | \\__ \\
|
|
19
|
+
\\___|_| |_| |_|___/
|
|
20
|
+
`;
|
|
4
21
|
/** Expand ~ to home */
|
|
5
22
|
export function expandHome(p) {
|
|
6
23
|
if (p.startsWith('~'))
|
|
@@ -21,16 +38,27 @@ export async function isEmptyDir(dir) {
|
|
|
21
38
|
return true;
|
|
22
39
|
}
|
|
23
40
|
}
|
|
24
|
-
/** Detect preferred package manager */
|
|
25
41
|
export function detectPackageManager() {
|
|
42
|
+
// This environment variable is set by npm and yarn but pnpm seems less consistent
|
|
26
43
|
const userAgent = process.env.npm_config_user_agent;
|
|
27
|
-
if (userAgent
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
44
|
+
if (userAgent) {
|
|
45
|
+
if (userAgent.startsWith('yarn')) {
|
|
46
|
+
return 'yarn';
|
|
47
|
+
}
|
|
48
|
+
else if (userAgent.startsWith('pnpm')) {
|
|
49
|
+
return 'pnpm';
|
|
50
|
+
}
|
|
51
|
+
else if (userAgent.startsWith('bun')) {
|
|
52
|
+
return 'bun';
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
return 'npm';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// If no user agent is set, assume npm
|
|
60
|
+
return 'npm';
|
|
61
|
+
}
|
|
34
62
|
}
|
|
35
63
|
/** Validate template structure */
|
|
36
64
|
export async function validateTemplate(templateDir) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-nextjs-cms",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.34",
|
|
4
4
|
"private": false,
|
|
5
|
+
"type": "module",
|
|
5
6
|
"bin": {
|
|
6
7
|
"create-nextjs-cms": "./dist/index.js"
|
|
7
8
|
},
|
|
@@ -10,17 +11,17 @@
|
|
|
10
11
|
"templates"
|
|
11
12
|
],
|
|
12
13
|
"dependencies": {
|
|
14
|
+
"@clack/prompts": "^0.11.0",
|
|
13
15
|
"chalk": "^5.4.1",
|
|
14
16
|
"commander": "^14.0.2",
|
|
15
17
|
"fs-extra": "^11.3.3",
|
|
16
18
|
"glob": "^11.0.3",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
+
"gradient-string": "^3.0.0",
|
|
20
|
+
"js-yaml": "^4.1.1"
|
|
19
21
|
},
|
|
20
22
|
"devDependencies": {
|
|
21
23
|
"@types/fs-extra": "^11.0.4",
|
|
22
24
|
"@types/js-yaml": "^4.0.9",
|
|
23
|
-
"@types/prompts": "^2.4.9",
|
|
24
25
|
"eslint": "^9.12.0",
|
|
25
26
|
"prettier": "^3.3.3",
|
|
26
27
|
"tsx": "^4.20.6",
|
|
@@ -31,7 +32,7 @@
|
|
|
31
32
|
},
|
|
32
33
|
"prettier": "@lzcms/prettier-config",
|
|
33
34
|
"scripts": {
|
|
34
|
-
"dev": "tsc",
|
|
35
|
+
"dev": "tsc --watch",
|
|
35
36
|
"prebuild": "tsx scripts/build.ts",
|
|
36
37
|
"build": "pnpm prebuild && tsc",
|
|
37
38
|
"clean": "git clean -xdf .cache .turbo dist node_modules templates",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"nanoid": "^5.1.2",
|
|
71
71
|
"next": "^15.5.5",
|
|
72
72
|
"next-themes": "^0.4.6",
|
|
73
|
-
"nextjs-cms": "0.5.
|
|
73
|
+
"nextjs-cms": "0.5.34",
|
|
74
74
|
"plaiceholder": "^3.0.0",
|
|
75
75
|
"prettier-plugin-tailwindcss": "^0.7.2",
|
|
76
76
|
"qrcode": "^1.5.4",
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
"eslint-config-prettier": "^10.0.1",
|
|
104
104
|
"eslint-plugin-prettier": "^5.2.3",
|
|
105
105
|
"fs-extra": "^11.3.3",
|
|
106
|
-
"nextjs-cms-kit": "0.5.
|
|
106
|
+
"nextjs-cms-kit": "0.5.34",
|
|
107
107
|
"postcss": "^8.5.1",
|
|
108
108
|
"prettier": "3.5.0",
|
|
109
109
|
"tailwindcss": "^4.1.18",
|