create-nextjs-cms 0.5.63 → 0.5.67
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/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +77 -0
- package/dist/helpers/check-directory.d.ts +6 -0
- package/dist/helpers/check-directory.d.ts.map +1 -0
- package/dist/helpers/check-directory.js +47 -0
- package/dist/helpers/exec-utils.d.ts +29 -0
- package/dist/helpers/exec-utils.d.ts.map +1 -0
- package/dist/helpers/exec-utils.js +62 -0
- package/dist/helpers/get-version.d.ts +2 -0
- package/dist/helpers/get-version.d.ts.map +1 -0
- package/dist/helpers/get-version.js +11 -0
- package/dist/helpers/logger.d.ts +8 -0
- package/dist/helpers/logger.d.ts.map +1 -0
- package/dist/helpers/logger.js +18 -0
- package/dist/helpers/render-title.d.ts +3 -0
- package/dist/helpers/render-title.d.ts.map +1 -0
- package/dist/{lib → helpers}/render-title.js +10 -0
- package/dist/{lib → helpers}/utils.d.ts +9 -0
- package/dist/helpers/utils.d.ts.map +1 -0
- package/dist/{lib → helpers}/utils.js +43 -1
- package/dist/index.js +49 -383
- package/dist/lib/cms-setup.d.ts +5 -0
- package/dist/lib/cms-setup.d.ts.map +1 -0
- package/dist/lib/cms-setup.js +26 -0
- package/dist/lib/create-project.d.ts +9 -0
- package/dist/lib/create-project.d.ts.map +1 -0
- package/dist/lib/create-project.js +69 -0
- package/dist/lib/git.d.ts +6 -0
- package/dist/lib/git.d.ts.map +1 -0
- package/dist/lib/git.js +116 -0
- package/dist/lib/install-deps.d.ts +4 -0
- package/dist/lib/install-deps.d.ts.map +1 -0
- package/dist/lib/install-deps.js +113 -0
- package/dist/lib/section-creators.d.ts +13 -0
- package/dist/lib/section-creators.d.ts.map +1 -0
- package/dist/lib/section-creators.js +201 -0
- package/dist/lib/validate-app-name.d.ts +2 -0
- package/dist/lib/validate-app-name.d.ts.map +1 -0
- package/dist/lib/validate-app-name.js +10 -0
- package/package.json +4 -2
- package/templates/default/lib/postinstall.js +1 -1
- package/templates/default/package.json +2 -1
- package/dist/lib/render-title.d.ts +0 -2
- package/dist/lib/render-title.d.ts.map +0 -1
- package/dist/lib/utils.d.ts.map +0 -1
- package/templates/default/.uploads/.photos/categories/000e56fada378de1a84a4 +0 -0
- package/templates/default/.uploads/.photos/categories/121e7d13ee3b5fa03795b +0 -0
- package/templates/default/.uploads/.photos/categories/17a55c5a53eb62293c69e +0 -0
- package/templates/default/.uploads/.photos/categories/4c86ad8c1f51f1e3a953b +0 -0
- package/templates/default/.uploads/.photos/categories/4d360813741a45744327c +0 -0
- package/templates/default/.uploads/.photos/categories/5238fefaa3cbebf388178 +0 -0
- package/templates/default/.uploads/.photos/categories/541d7cf8c69895bcb15cd +0 -0
- package/templates/default/.uploads/.photos/categories/57a2f689a910a378247ea +0 -0
- package/templates/default/.uploads/.photos/categories/6de4bdb341a3e1f70ddc3 +0 -0
- package/templates/default/.uploads/.photos/categories/6f52739eaa686441a28f4 +0 -0
- package/templates/default/.uploads/.photos/categories/8a21b9fa8ecd88f460a15 +0 -0
- package/templates/default/.uploads/.photos/categories/91948abcb073c9445fdec +0 -0
- package/templates/default/.uploads/.photos/categories/9ae700d1abfd6b85780e8 +0 -0
- package/templates/default/.uploads/.photos/categories/9edee86e932985fc589b5 +0 -0
- package/templates/default/.uploads/.photos/categories/a520e77b082f35b575dba +0 -0
- package/templates/default/.uploads/.photos/categories/b19c449029330f0a74b20 +0 -0
- package/templates/default/.uploads/.photos/categories/b9802010f68afd4edb0e8 +0 -0
- package/templates/default/.uploads/.photos/categories/c1d7c3b986739bf496730 +0 -0
- package/templates/default/.uploads/.photos/categories/c25dc38567384513ffe93 +0 -0
- package/templates/default/.uploads/.photos/categories/cbe3874a3d13afba388df +0 -0
- package/templates/default/.uploads/.photos/categories/d450fdeb04f0d070442d6 +0 -0
- package/templates/default/.uploads/.photos/categories/f80bf3a4515680ead5a5c +0 -0
- package/templates/default/.uploads/.photos/categories/f8639c2d5b0d24cb76fb1 +0 -0
- package/templates/default/.uploads/.photos/categories/f8d997149d10aab046e40 +0 -0
- package/templates/default/.uploads/.photos/categories/fa2c55690ff96e33a16fe +0 -0
- package/templates/default/.uploads/.photos/featured_slider/d00be4edb4c38ca34b5a5 +0 -0
- package/templates/default/.uploads/.thumbs/categories/000e56fada378de1a84a4 +0 -0
- package/templates/default/.uploads/.thumbs/categories/121e7d13ee3b5fa03795b +0 -0
- package/templates/default/.uploads/.thumbs/categories/17a55c5a53eb62293c69e +0 -0
- package/templates/default/.uploads/.thumbs/categories/4c86ad8c1f51f1e3a953b +0 -0
- package/templates/default/.uploads/.thumbs/categories/4d360813741a45744327c +0 -0
- package/templates/default/.uploads/.thumbs/categories/5238fefaa3cbebf388178 +0 -0
- package/templates/default/.uploads/.thumbs/categories/541d7cf8c69895bcb15cd +0 -0
- package/templates/default/.uploads/.thumbs/categories/57a2f689a910a378247ea +0 -0
- package/templates/default/.uploads/.thumbs/categories/6de4bdb341a3e1f70ddc3 +0 -0
- package/templates/default/.uploads/.thumbs/categories/6f52739eaa686441a28f4 +0 -0
- package/templates/default/.uploads/.thumbs/categories/8a21b9fa8ecd88f460a15 +0 -0
- package/templates/default/.uploads/.thumbs/categories/91948abcb073c9445fdec +0 -0
- package/templates/default/.uploads/.thumbs/categories/9ae700d1abfd6b85780e8 +0 -0
- package/templates/default/.uploads/.thumbs/categories/9edee86e932985fc589b5 +0 -0
- package/templates/default/.uploads/.thumbs/categories/a520e77b082f35b575dba +0 -0
- package/templates/default/.uploads/.thumbs/categories/b19c449029330f0a74b20 +0 -0
- package/templates/default/.uploads/.thumbs/categories/b9802010f68afd4edb0e8 +0 -0
- package/templates/default/.uploads/.thumbs/categories/c1d7c3b986739bf496730 +0 -0
- package/templates/default/.uploads/.thumbs/categories/c25dc38567384513ffe93 +0 -0
- package/templates/default/.uploads/.thumbs/categories/cbe3874a3d13afba388df +0 -0
- package/templates/default/.uploads/.thumbs/categories/d450fdeb04f0d070442d6 +0 -0
- package/templates/default/.uploads/.thumbs/categories/f80bf3a4515680ead5a5c +0 -0
- package/templates/default/.uploads/.thumbs/categories/f8639c2d5b0d24cb76fb1 +0 -0
- package/templates/default/.uploads/.thumbs/categories/f8d997149d10aab046e40 +0 -0
- package/templates/default/.uploads/.thumbs/categories/fa2c55690ff96e33a16fe +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAOA,UAAU,UAAU;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,CAAC,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAC,EAAE,CAAA;IACjD,GAAG,EAAE,OAAO,CAAA;IACZ,gBAAgB,EAAE,OAAO,CAAA;CAC5B;AASD,eAAO,MAAM,MAAM,QAAa,OAAO,CAAC,UAAU,CAwEjD,CAAA"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { validateAppName } from '../lib/validate-app-name.js';
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
import { removeTrailingSlash } from '../helpers/utils.js';
|
|
6
|
+
import { getCreateNextjsCmsVersion } from '../helpers/get-version.js';
|
|
7
|
+
const defaultOptions = {
|
|
8
|
+
appName: 'my-cms-app',
|
|
9
|
+
sectionsToAdd: [],
|
|
10
|
+
git: false,
|
|
11
|
+
databaseProvider: 'mysql',
|
|
12
|
+
};
|
|
13
|
+
export const runCli = async () => {
|
|
14
|
+
const version = getCreateNextjsCmsVersion();
|
|
15
|
+
const program = new Command('create-nextjs-cms')
|
|
16
|
+
.version(version, '-v, --version', 'Output the current version of create-nextjs-cms.')
|
|
17
|
+
.argument('[directory]', 'The directory to create the project in')
|
|
18
|
+
.usage('[directory] [options]')
|
|
19
|
+
.helpOption('-h, --help', 'Display this help message.')
|
|
20
|
+
.allowUnknownOption()
|
|
21
|
+
.parse(process.argv);
|
|
22
|
+
let providedName = program.args[0];
|
|
23
|
+
if (providedName) {
|
|
24
|
+
providedName = removeTrailingSlash(providedName).trim();
|
|
25
|
+
// Validate name
|
|
26
|
+
const _notValid = validateAppName(providedName);
|
|
27
|
+
if (_notValid !== undefined) {
|
|
28
|
+
p.log.message(`${chalk.gray(`${_notValid}`)}`);
|
|
29
|
+
providedName = undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const project = await p.group({
|
|
33
|
+
name: providedName
|
|
34
|
+
? () => Promise.resolve(providedName)
|
|
35
|
+
: () => p.text({
|
|
36
|
+
message: 'What is your project named?',
|
|
37
|
+
placeholder: defaultOptions.appName,
|
|
38
|
+
defaultValue: defaultOptions.appName,
|
|
39
|
+
validate: validateAppName,
|
|
40
|
+
}),
|
|
41
|
+
sections: () => {
|
|
42
|
+
return p.multiselect({
|
|
43
|
+
message: `Add sample sections? ${chalk.gray('(hit enter with no selections to skip)')}`,
|
|
44
|
+
options: [
|
|
45
|
+
{ value: 'blog', label: 'Blog' },
|
|
46
|
+
{ value: 'category', label: 'Category' },
|
|
47
|
+
{ value: 'simple', label: 'Settings' },
|
|
48
|
+
],
|
|
49
|
+
required: false,
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
database: () => {
|
|
53
|
+
return p.select({
|
|
54
|
+
message: 'What database provider would you like to use?',
|
|
55
|
+
options: [{ value: 'mysql', label: 'MySQL', hint: 'Other database providers coming soon' }],
|
|
56
|
+
initialValue: 'mysql',
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
git: () => {
|
|
60
|
+
return p.confirm({
|
|
61
|
+
message: 'Should we initialize a Git repository and stage the changes?',
|
|
62
|
+
initialValue: false,
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
}, {
|
|
66
|
+
onCancel() {
|
|
67
|
+
p.outro('❌ Aborting installation');
|
|
68
|
+
process.exit(1);
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
appName: project.name,
|
|
73
|
+
sectionsToAdd: project.sections,
|
|
74
|
+
git: project.git,
|
|
75
|
+
databaseProvider: project.database,
|
|
76
|
+
};
|
|
77
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-directory.d.ts","sourceRoot":"","sources":["../../src/helpers/check-directory.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,gBAAgB,GACzB,SAAS,MAAM,KAChB,OAAO,CAAC;IACP,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,OAAO,CAAA;CACvB,CAwCA,CAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { expandHome } from './utils.js';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import { basename } from 'node:path';
|
|
5
|
+
import fs from 'fs-extra';
|
|
6
|
+
import { isEmptyDir } from './utils.js';
|
|
7
|
+
import * as p from '@clack/prompts';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
export const resolveDirectory = async (appName) => {
|
|
10
|
+
// Resolve target path from the caller's CWD
|
|
11
|
+
const rawTarget = expandHome(appName);
|
|
12
|
+
const targetDir = path.isAbsolute(rawTarget) ? rawTarget : resolve(process.cwd(), rawTarget);
|
|
13
|
+
// Derive package name from final path
|
|
14
|
+
const projectName = basename(targetDir);
|
|
15
|
+
const targetIsCwd = path.normalize(targetDir) === path.normalize(process.cwd());
|
|
16
|
+
if (targetIsCwd) {
|
|
17
|
+
// Using current directory (".")
|
|
18
|
+
if (!(await fs.pathExists(targetDir))) {
|
|
19
|
+
await fs.ensureDir(targetDir);
|
|
20
|
+
}
|
|
21
|
+
else if (!(await isEmptyDir(targetDir))) {
|
|
22
|
+
p.log.error('Current directory is not empty. Choose an empty folder or a new directory name.');
|
|
23
|
+
p.log.message(chalk.gray('Tip: You can also specify a directory name like this: \n') +
|
|
24
|
+
chalk.green('pnpm create nextjs-cms ') +
|
|
25
|
+
chalk.italic.magenta('my-app'));
|
|
26
|
+
p.log.message(' ');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
if (await fs.pathExists(targetDir)) {
|
|
32
|
+
if (!(await isEmptyDir(targetDir))) {
|
|
33
|
+
p.log.error(`Directory "${targetDir}" is not empty.`);
|
|
34
|
+
p.log.message('Please choose an empty directory or a different directory name.');
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
await fs.ensureDir(targetDir);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
targetDir,
|
|
44
|
+
projectName,
|
|
45
|
+
targetIsCwd,
|
|
46
|
+
};
|
|
47
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Ora } from 'ora';
|
|
2
|
+
export interface ExecWithSpinnerOptions {
|
|
3
|
+
command: string;
|
|
4
|
+
args: string[];
|
|
5
|
+
cwd?: string;
|
|
6
|
+
stdout?: 'pipe' | 'ignore' | 'inherit';
|
|
7
|
+
stderr?: 'pipe' | 'ignore' | 'inherit';
|
|
8
|
+
spinnerText?: string;
|
|
9
|
+
onDataHandle?: (spinner: Ora) => (data: Buffer) => void;
|
|
10
|
+
onStderrHandle?: (data: Buffer) => void;
|
|
11
|
+
checkExitCode?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Execute a command with a spinner, handling different stdio configurations
|
|
15
|
+
* and optional data handlers for progress updates.
|
|
16
|
+
*/
|
|
17
|
+
export declare const execWithSpinner: (options: ExecWithSpinnerOptions) => Promise<Ora | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Execute a command without a spinner (for cases where we want direct output)
|
|
20
|
+
*/
|
|
21
|
+
export declare const execWithoutSpinner: (command: string, args: string[], options?: {
|
|
22
|
+
cwd?: string;
|
|
23
|
+
stdin?: "pipe" | "ignore" | "inherit";
|
|
24
|
+
stdout?: "pipe" | "ignore" | "inherit";
|
|
25
|
+
stderr?: "pipe" | "ignore" | "inherit";
|
|
26
|
+
reject?: boolean;
|
|
27
|
+
env?: Record<string, string>;
|
|
28
|
+
}) => Promise<void>;
|
|
29
|
+
//# sourceMappingURL=exec-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-utils.d.ts","sourceRoot":"","sources":["../../src/helpers/exec-utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAE9B,MAAM,WAAW,sBAAsB;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAA;IACtC,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAA;IACtC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACvD,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,aAAa,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAU,SAAS,sBAAsB,KAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAsDzF,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC3B,SAAS,MAAM,EACf,MAAM,MAAM,EAAE,EACd,UAAS;IACL,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAA;IACrC,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAA;IACtC,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAA;IACtC,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC1B,KACP,OAAO,CAAC,IAAI,CAWd,CAAA"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { execa } from 'execa';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
/**
|
|
4
|
+
* Execute a command with a spinner, handling different stdio configurations
|
|
5
|
+
* and optional data handlers for progress updates.
|
|
6
|
+
*/
|
|
7
|
+
export const execWithSpinner = async (options) => {
|
|
8
|
+
const { command, args, cwd, stdout = 'pipe', stderr = 'pipe', spinnerText = `Running ${command}...`, onDataHandle, onStderrHandle, checkExitCode = false, } = options;
|
|
9
|
+
const spinner = ora(spinnerText).start();
|
|
10
|
+
const subprocess = execa(command, args, {
|
|
11
|
+
cwd,
|
|
12
|
+
stdout,
|
|
13
|
+
stderr,
|
|
14
|
+
reject: false, // Don't reject on non-zero exit codes - we handle it manually
|
|
15
|
+
});
|
|
16
|
+
let stderrOutput = '';
|
|
17
|
+
await new Promise((res, rej) => {
|
|
18
|
+
if (onDataHandle) {
|
|
19
|
+
subprocess.stdout?.on('data', onDataHandle(spinner));
|
|
20
|
+
}
|
|
21
|
+
if (onStderrHandle) {
|
|
22
|
+
subprocess.stderr?.on('data', (data) => {
|
|
23
|
+
onStderrHandle(data);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
else if (stderr === 'pipe') {
|
|
27
|
+
// Capture stderr to check for specific errors
|
|
28
|
+
subprocess.stderr?.on('data', (data) => {
|
|
29
|
+
stderrOutput += data.toString();
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
void subprocess.on('error', (e) => rej(e));
|
|
33
|
+
void subprocess.on('close', (code) => {
|
|
34
|
+
if (checkExitCode && code !== 0) {
|
|
35
|
+
const error = new Error(`${command} exited with code ${code}`);
|
|
36
|
+
if (stderrOutput) {
|
|
37
|
+
;
|
|
38
|
+
error.stderr = stderrOutput;
|
|
39
|
+
}
|
|
40
|
+
rej(error);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
res();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
return spinner;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Execute a command without a spinner (for cases where we want direct output)
|
|
51
|
+
*/
|
|
52
|
+
export const execWithoutSpinner = async (command, args, options = {}) => {
|
|
53
|
+
const { cwd, stdin, stdout, stderr, reject = true, env } = options;
|
|
54
|
+
await execa(command, args, {
|
|
55
|
+
cwd,
|
|
56
|
+
stdin: stdin ?? (stdout === 'inherit' || stderr === 'inherit' ? 'inherit' : undefined),
|
|
57
|
+
stdout,
|
|
58
|
+
stderr,
|
|
59
|
+
reject,
|
|
60
|
+
env: env ? { ...process.env, ...env } : undefined,
|
|
61
|
+
});
|
|
62
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-version.d.ts","sourceRoot":"","sources":["../../src/helpers/get-version.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,yBAAyB,QAAO,MAW5C,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
export const getCreateNextjsCmsVersion = () => {
|
|
6
|
+
/** Resolve __dirname for ESM */
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
const packageJson = JSON.parse(readFileSync(path.join(__dirname, '../../package.json'), 'utf-8'));
|
|
10
|
+
return packageJson.version;
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/helpers/logger.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM;qBACE,OAAO,EAAE;mBAGX,OAAO,EAAE;kBAGV,OAAO,EAAE;kBAGT,OAAO,EAAE;qBAGN,OAAO,EAAE;CAG7B,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
export const logger = {
|
|
3
|
+
message(...args) {
|
|
4
|
+
console.log(chalk.gray(...args));
|
|
5
|
+
},
|
|
6
|
+
error(...args) {
|
|
7
|
+
console.log(chalk.red(...args));
|
|
8
|
+
},
|
|
9
|
+
warn(...args) {
|
|
10
|
+
console.log(chalk.yellow(...args));
|
|
11
|
+
},
|
|
12
|
+
info(...args) {
|
|
13
|
+
console.log(chalk.cyan(...args));
|
|
14
|
+
},
|
|
15
|
+
success(...args) {
|
|
16
|
+
console.log(chalk.green(...args));
|
|
17
|
+
},
|
|
18
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-title.d.ts","sourceRoot":"","sources":["../../src/helpers/render-title.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,WAAW,YASvB,CAAA;AAED,eAAO,MAAM,YAAY,YAUxB,CAAA"}
|
|
@@ -19,3 +19,13 @@ export const renderTitle = () => {
|
|
|
19
19
|
}
|
|
20
20
|
console.log(titleGradient.multiline(TITLE_TEXT));
|
|
21
21
|
};
|
|
22
|
+
export const renderFooter = () => {
|
|
23
|
+
const titleGradient = gradient(Object.values(poimandresTheme));
|
|
24
|
+
// resolves weird behavior where the ascii is offset
|
|
25
|
+
const pkgManager = detectPackageManager();
|
|
26
|
+
if (pkgManager === 'yarn' || pkgManager === 'pnpm') {
|
|
27
|
+
console.log('');
|
|
28
|
+
}
|
|
29
|
+
console.log();
|
|
30
|
+
console.log(titleGradient.multiline('Your NextJS CMS project has been created successfully!'));
|
|
31
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export declare const TITLE_TEXT = "\n _\n ___ _ __ ___ __ _| |_ ___\n / __| '__/ _ \\/ _\\` | __/ _ \\\n | (__| | | __/ (_| | || __/\n \\___|_| \\___|\\__,_|\\__\\___|\n _ _\n _ __ _____ _| |_ (_)___\n | '_ \\ / _ \\ \\/ / __|| / __|\n | | | | __/> <| |_ | \\__ \\\n |_| |_|\\___/_/\\_\\__|/ |___/\n |__/\n ___ _ __ ___ ___\n / __| '_ \\` _ \\/ __|\n | (__| | | | | \\__ \\\n \\___|_| |_| |_|___/\n";
|
|
2
2
|
/** Expand ~ to home */
|
|
3
3
|
export declare function expandHome(p: string): string;
|
|
4
|
+
export declare const removeTrailingSlash: (input: string) => string;
|
|
4
5
|
/** Validate npm package name (simple rule) */
|
|
5
6
|
export declare function isValidPkgName(name: string): boolean;
|
|
6
7
|
/** Check if a directory is empty */
|
|
@@ -10,4 +11,12 @@ export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';
|
|
|
10
11
|
export declare function detectPackageManager(): 'pnpm' | 'npm' | 'yarn' | 'bun';
|
|
11
12
|
/** Validate template structure */
|
|
12
13
|
export declare function validateTemplate(templateDir: string): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Generates a random secret string using crypto.randomBytes
|
|
16
|
+
*/
|
|
17
|
+
export declare function generateSecret(): string;
|
|
18
|
+
/**
|
|
19
|
+
* Updates .env file with generated random secrets
|
|
20
|
+
*/
|
|
21
|
+
export declare function updateEnvSecrets(targetDir: string): Promise<void>;
|
|
13
22
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/helpers/utils.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,UAAU,4jBAgBtB,CAAA;AAED,uBAAuB;AACvB,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAG5C;AAED,eAAO,MAAM,mBAAmB,GAAI,OAAO,MAAM,WAMhD,CAAA;AAED,8CAA8C;AAC9C,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGpD;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;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBvE"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import os from 'node:os';
|
|
4
|
+
import { randomBytes } from 'node:crypto';
|
|
5
|
+
import { log } from '@clack/prompts';
|
|
6
|
+
import chalk from 'chalk';
|
|
4
7
|
export const TITLE_TEXT = `
|
|
5
8
|
_
|
|
6
9
|
___ _ __ ___ __ _| |_ ___
|
|
@@ -24,8 +27,16 @@ export function expandHome(p) {
|
|
|
24
27
|
return path.join(os.homedir(), p.slice(1));
|
|
25
28
|
return p;
|
|
26
29
|
}
|
|
30
|
+
export const removeTrailingSlash = (input) => {
|
|
31
|
+
if (input.length > 1 && input.endsWith('/')) {
|
|
32
|
+
input = input.slice(0, -1);
|
|
33
|
+
}
|
|
34
|
+
return input;
|
|
35
|
+
};
|
|
27
36
|
/** Validate npm package name (simple rule) */
|
|
28
37
|
export function isValidPkgName(name) {
|
|
38
|
+
if (name === '.')
|
|
39
|
+
return true;
|
|
29
40
|
return /^[a-zA-Z0-9-_]+$/.test(name);
|
|
30
41
|
}
|
|
31
42
|
/** Check if a directory is empty */
|
|
@@ -57,7 +68,7 @@ export function detectPackageManager() {
|
|
|
57
68
|
}
|
|
58
69
|
else {
|
|
59
70
|
// If no user agent is set, assume npm
|
|
60
|
-
return '
|
|
71
|
+
return 'pnpm';
|
|
61
72
|
}
|
|
62
73
|
}
|
|
63
74
|
/** Validate template structure */
|
|
@@ -74,3 +85,34 @@ export async function validateTemplate(templateDir) {
|
|
|
74
85
|
missingFiles.forEach((file) => console.warn(` - ${file}`));
|
|
75
86
|
}
|
|
76
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* Generates a random secret string using crypto.randomBytes
|
|
90
|
+
*/
|
|
91
|
+
export function generateSecret() {
|
|
92
|
+
return randomBytes(32).toString('hex');
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Updates .env file with generated random secrets
|
|
96
|
+
*/
|
|
97
|
+
export async function updateEnvSecrets(targetDir) {
|
|
98
|
+
const envPath = path.join(targetDir, '.env');
|
|
99
|
+
if (!(await fs.pathExists(envPath))) {
|
|
100
|
+
log.warn('No .env file found; skipping secret generation.');
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
let envContent = await fs.readFile(envPath, 'utf-8');
|
|
105
|
+
// Replace placeholder secrets with generated ones
|
|
106
|
+
envContent = envContent.replace(/ACCESS_TOKEN_SECRET=.*/, `ACCESS_TOKEN_SECRET=${generateSecret()}`);
|
|
107
|
+
envContent = envContent.replace(/REFRESH_TOKEN_SECRET=.*/, `REFRESH_TOKEN_SECRET=${generateSecret()}`);
|
|
108
|
+
envContent = envContent.replace(/CSRF_TOKEN_SECRET=.*/, `CSRF_TOKEN_SECRET=${generateSecret()}`);
|
|
109
|
+
envContent = envContent.replace(/ACCESS_TOKEN_EXPIRATION=.*/, 'ACCESS_TOKEN_EXPIRATION=2h');
|
|
110
|
+
envContent = envContent.replace(/REFRESH_TOKEN_EXPIRATION=.*/, 'REFRESH_TOKEN_EXPIRATION=1y');
|
|
111
|
+
await fs.writeFile(envPath, envContent, 'utf-8');
|
|
112
|
+
log.message(` - Generated random secrets in root ${chalk.green('.env')} file`);
|
|
113
|
+
}
|
|
114
|
+
catch (e) {
|
|
115
|
+
log.warn('Could not update .env secrets automatically.');
|
|
116
|
+
log.error(` Error: ${e instanceof Error ? e.message : 'Unknown error'}`);
|
|
117
|
+
}
|
|
118
|
+
}
|