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.
Files changed (97) hide show
  1. package/dist/cli/index.d.ts +9 -0
  2. package/dist/cli/index.d.ts.map +1 -0
  3. package/dist/cli/index.js +77 -0
  4. package/dist/helpers/check-directory.d.ts +6 -0
  5. package/dist/helpers/check-directory.d.ts.map +1 -0
  6. package/dist/helpers/check-directory.js +47 -0
  7. package/dist/helpers/exec-utils.d.ts +29 -0
  8. package/dist/helpers/exec-utils.d.ts.map +1 -0
  9. package/dist/helpers/exec-utils.js +62 -0
  10. package/dist/helpers/get-version.d.ts +2 -0
  11. package/dist/helpers/get-version.d.ts.map +1 -0
  12. package/dist/helpers/get-version.js +11 -0
  13. package/dist/helpers/logger.d.ts +8 -0
  14. package/dist/helpers/logger.d.ts.map +1 -0
  15. package/dist/helpers/logger.js +18 -0
  16. package/dist/helpers/render-title.d.ts +3 -0
  17. package/dist/helpers/render-title.d.ts.map +1 -0
  18. package/dist/{lib → helpers}/render-title.js +10 -0
  19. package/dist/{lib → helpers}/utils.d.ts +9 -0
  20. package/dist/helpers/utils.d.ts.map +1 -0
  21. package/dist/{lib → helpers}/utils.js +43 -1
  22. package/dist/index.js +49 -383
  23. package/dist/lib/cms-setup.d.ts +5 -0
  24. package/dist/lib/cms-setup.d.ts.map +1 -0
  25. package/dist/lib/cms-setup.js +26 -0
  26. package/dist/lib/create-project.d.ts +9 -0
  27. package/dist/lib/create-project.d.ts.map +1 -0
  28. package/dist/lib/create-project.js +69 -0
  29. package/dist/lib/git.d.ts +6 -0
  30. package/dist/lib/git.d.ts.map +1 -0
  31. package/dist/lib/git.js +116 -0
  32. package/dist/lib/install-deps.d.ts +4 -0
  33. package/dist/lib/install-deps.d.ts.map +1 -0
  34. package/dist/lib/install-deps.js +113 -0
  35. package/dist/lib/section-creators.d.ts +13 -0
  36. package/dist/lib/section-creators.d.ts.map +1 -0
  37. package/dist/lib/section-creators.js +201 -0
  38. package/dist/lib/validate-app-name.d.ts +2 -0
  39. package/dist/lib/validate-app-name.d.ts.map +1 -0
  40. package/dist/lib/validate-app-name.js +10 -0
  41. package/package.json +4 -2
  42. package/templates/default/lib/postinstall.js +1 -1
  43. package/templates/default/package.json +2 -1
  44. package/dist/lib/render-title.d.ts +0 -2
  45. package/dist/lib/render-title.d.ts.map +0 -1
  46. package/dist/lib/utils.d.ts.map +0 -1
  47. package/templates/default/.uploads/.photos/categories/000e56fada378de1a84a4 +0 -0
  48. package/templates/default/.uploads/.photos/categories/121e7d13ee3b5fa03795b +0 -0
  49. package/templates/default/.uploads/.photos/categories/17a55c5a53eb62293c69e +0 -0
  50. package/templates/default/.uploads/.photos/categories/4c86ad8c1f51f1e3a953b +0 -0
  51. package/templates/default/.uploads/.photos/categories/4d360813741a45744327c +0 -0
  52. package/templates/default/.uploads/.photos/categories/5238fefaa3cbebf388178 +0 -0
  53. package/templates/default/.uploads/.photos/categories/541d7cf8c69895bcb15cd +0 -0
  54. package/templates/default/.uploads/.photos/categories/57a2f689a910a378247ea +0 -0
  55. package/templates/default/.uploads/.photos/categories/6de4bdb341a3e1f70ddc3 +0 -0
  56. package/templates/default/.uploads/.photos/categories/6f52739eaa686441a28f4 +0 -0
  57. package/templates/default/.uploads/.photos/categories/8a21b9fa8ecd88f460a15 +0 -0
  58. package/templates/default/.uploads/.photos/categories/91948abcb073c9445fdec +0 -0
  59. package/templates/default/.uploads/.photos/categories/9ae700d1abfd6b85780e8 +0 -0
  60. package/templates/default/.uploads/.photos/categories/9edee86e932985fc589b5 +0 -0
  61. package/templates/default/.uploads/.photos/categories/a520e77b082f35b575dba +0 -0
  62. package/templates/default/.uploads/.photos/categories/b19c449029330f0a74b20 +0 -0
  63. package/templates/default/.uploads/.photos/categories/b9802010f68afd4edb0e8 +0 -0
  64. package/templates/default/.uploads/.photos/categories/c1d7c3b986739bf496730 +0 -0
  65. package/templates/default/.uploads/.photos/categories/c25dc38567384513ffe93 +0 -0
  66. package/templates/default/.uploads/.photos/categories/cbe3874a3d13afba388df +0 -0
  67. package/templates/default/.uploads/.photos/categories/d450fdeb04f0d070442d6 +0 -0
  68. package/templates/default/.uploads/.photos/categories/f80bf3a4515680ead5a5c +0 -0
  69. package/templates/default/.uploads/.photos/categories/f8639c2d5b0d24cb76fb1 +0 -0
  70. package/templates/default/.uploads/.photos/categories/f8d997149d10aab046e40 +0 -0
  71. package/templates/default/.uploads/.photos/categories/fa2c55690ff96e33a16fe +0 -0
  72. package/templates/default/.uploads/.photos/featured_slider/d00be4edb4c38ca34b5a5 +0 -0
  73. package/templates/default/.uploads/.thumbs/categories/000e56fada378de1a84a4 +0 -0
  74. package/templates/default/.uploads/.thumbs/categories/121e7d13ee3b5fa03795b +0 -0
  75. package/templates/default/.uploads/.thumbs/categories/17a55c5a53eb62293c69e +0 -0
  76. package/templates/default/.uploads/.thumbs/categories/4c86ad8c1f51f1e3a953b +0 -0
  77. package/templates/default/.uploads/.thumbs/categories/4d360813741a45744327c +0 -0
  78. package/templates/default/.uploads/.thumbs/categories/5238fefaa3cbebf388178 +0 -0
  79. package/templates/default/.uploads/.thumbs/categories/541d7cf8c69895bcb15cd +0 -0
  80. package/templates/default/.uploads/.thumbs/categories/57a2f689a910a378247ea +0 -0
  81. package/templates/default/.uploads/.thumbs/categories/6de4bdb341a3e1f70ddc3 +0 -0
  82. package/templates/default/.uploads/.thumbs/categories/6f52739eaa686441a28f4 +0 -0
  83. package/templates/default/.uploads/.thumbs/categories/8a21b9fa8ecd88f460a15 +0 -0
  84. package/templates/default/.uploads/.thumbs/categories/91948abcb073c9445fdec +0 -0
  85. package/templates/default/.uploads/.thumbs/categories/9ae700d1abfd6b85780e8 +0 -0
  86. package/templates/default/.uploads/.thumbs/categories/9edee86e932985fc589b5 +0 -0
  87. package/templates/default/.uploads/.thumbs/categories/a520e77b082f35b575dba +0 -0
  88. package/templates/default/.uploads/.thumbs/categories/b19c449029330f0a74b20 +0 -0
  89. package/templates/default/.uploads/.thumbs/categories/b9802010f68afd4edb0e8 +0 -0
  90. package/templates/default/.uploads/.thumbs/categories/c1d7c3b986739bf496730 +0 -0
  91. package/templates/default/.uploads/.thumbs/categories/c25dc38567384513ffe93 +0 -0
  92. package/templates/default/.uploads/.thumbs/categories/cbe3874a3d13afba388df +0 -0
  93. package/templates/default/.uploads/.thumbs/categories/d450fdeb04f0d070442d6 +0 -0
  94. package/templates/default/.uploads/.thumbs/categories/f80bf3a4515680ead5a5c +0 -0
  95. package/templates/default/.uploads/.thumbs/categories/f8639c2d5b0d24cb76fb1 +0 -0
  96. package/templates/default/.uploads/.thumbs/categories/f8d997149d10aab046e40 +0 -0
  97. package/templates/default/.uploads/.thumbs/categories/fa2c55690ff96e33a16fe +0 -0
@@ -0,0 +1,9 @@
1
+ interface CliResults {
2
+ appName: string;
3
+ sectionsToAdd: ('blog' | 'category' | 'simple')[];
4
+ git: boolean;
5
+ databaseProvider: 'mysql';
6
+ }
7
+ export declare const runCli: () => Promise<CliResults>;
8
+ export {};
9
+ //# sourceMappingURL=index.d.ts.map
@@ -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,6 @@
1
+ export declare const resolveDirectory: (appName: string) => Promise<{
2
+ targetDir: string;
3
+ projectName: string;
4
+ targetIsCwd: boolean;
5
+ }>;
6
+ //# sourceMappingURL=check-directory.d.ts.map
@@ -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,2 @@
1
+ export declare const getCreateNextjsCmsVersion: () => string;
2
+ //# sourceMappingURL=get-version.d.ts.map
@@ -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,8 @@
1
+ export declare const logger: {
2
+ message(...args: unknown[]): void;
3
+ error(...args: unknown[]): void;
4
+ warn(...args: unknown[]): void;
5
+ info(...args: unknown[]): void;
6
+ success(...args: unknown[]): void;
7
+ };
8
+ //# sourceMappingURL=logger.d.ts.map
@@ -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,3 @@
1
+ export declare const renderTitle: () => void;
2
+ export declare const renderFooter: () => void;
3
+ //# sourceMappingURL=render-title.d.ts.map
@@ -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 'npm';
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
+ }