nextjs-cms-kit 0.5.64 → 0.5.66
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/commands/setup.d.ts +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +22 -46
- package/dist/index.js +1 -3
- package/dist/lib/actions.d.ts.map +1 -1
- package/dist/lib/actions.js +1 -2
- package/dist/lib/db-config-setup.d.ts.map +1 -1
- package/dist/lib/db-config-setup.js +48 -17
- package/dist/lib/db-migrate.d.ts +2 -0
- package/dist/lib/db-migrate.d.ts.map +1 -0
- package/dist/lib/db-migrate.js +84 -0
- package/dist/lib/exec-utils.d.ts +19 -0
- package/dist/lib/exec-utils.d.ts.map +1 -0
- package/dist/lib/exec-utils.js +95 -0
- package/dist/lib/program.d.ts.map +1 -1
- package/dist/lib/program.js +7 -3
- package/dist/lib/reload-env.js +1 -1
- 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 +12 -0
- package/dist/lib/set-master-admin.d.ts.map +1 -1
- package/dist/lib/set-master-admin.js +3 -3
- package/dist/lib/update-sections.js +16 -16
- package/package.json +6 -3
package/dist/commands/setup.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function runSetup(dev: boolean): Promise<void>;
|
|
1
|
+
export declare function runSetup(dev: boolean, skipDbConfig: boolean): Promise<void>;
|
|
2
2
|
//# sourceMappingURL=setup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAIA,wBAAsB,QAAQ,CAAC,GAAG,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAIA,wBAAsB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,iBAyCjE"}
|
package/dist/commands/setup.js
CHANGED
|
@@ -1,56 +1,32 @@
|
|
|
1
|
-
import { note, intro, outro
|
|
2
|
-
import { spawn } from 'child_process';
|
|
1
|
+
import { note, intro, outro } from '@clack/prompts';
|
|
3
2
|
import chalk from 'chalk';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
console.log(chalk.hex('#E8DCFF').bold('nextjs-cms-kit'));
|
|
7
|
-
console.log(chalk.green('nextjs-cms CLI toolkit for managing your nextjs-cms application'));
|
|
8
|
-
console.log(chalk.gray('--------------------------'));
|
|
9
|
-
console.log(chalk.hex('#E8DCFF').bold('setup'));
|
|
10
|
-
console.log('Complete nextjs-cms setup');
|
|
11
|
-
console.log(chalk.gray('--------------------------'));
|
|
12
|
-
console.log(chalk.yellow(`Running in ${dev ? 'development' : 'production'} mode`));
|
|
13
|
-
console.log(chalk.gray('--------------------------'));
|
|
14
|
-
console.log(chalk.gray(`.......................................................`));
|
|
3
|
+
import { getTitle } from '../lib/render-title.js';
|
|
4
|
+
export async function runSetup(dev, skipDbConfig) {
|
|
15
5
|
console.log();
|
|
16
|
-
|
|
6
|
+
console.log(chalk.white.bold(`${getTitle()} > ${chalk.cyan.italic('setup')} ${dev ? chalk.gray('(development)') : chalk.gray('(production)')}`));
|
|
7
|
+
console.log();
|
|
8
|
+
intro(chalk.inverse(' Setting up nextjs-cms 🚀 '));
|
|
17
9
|
try {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
env: { ...process.env },
|
|
28
|
-
stdio: 'inherit', // Inherit stdio to prevent hanging and show output directly
|
|
29
|
-
shell: true,
|
|
30
|
-
});
|
|
31
|
-
child.on('close', (code) => {
|
|
32
|
-
if (code === 0) {
|
|
33
|
-
resolve();
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
reject(new Error(`drizzle-kit push exited with code ${code}`));
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
child.on('error', (error) => {
|
|
40
|
-
reject(error);
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
s.message('Database schema generated');
|
|
44
|
-
note('Setting up master admin...');
|
|
45
|
-
// Lazy import to avoid eager database connection
|
|
10
|
+
if (!skipDbConfig) {
|
|
11
|
+
note(chalk.cyan('Configuring database'));
|
|
12
|
+
const { dbConfigSetup } = await import('../lib/db-config-setup.js');
|
|
13
|
+
await dbConfigSetup({ dev });
|
|
14
|
+
}
|
|
15
|
+
note(chalk.cyan('Generating database schema'));
|
|
16
|
+
const { generateDatabaseSchema } = await import('../lib/db-migrate.js');
|
|
17
|
+
await generateDatabaseSchema();
|
|
18
|
+
note(chalk.cyan('Setting up master admin'));
|
|
46
19
|
const { setMasterAdmin } = await import('../lib/set-master-admin.js');
|
|
47
20
|
await setMasterAdmin();
|
|
48
|
-
|
|
49
|
-
outro('nextjs-cms setup completed successfully! 🎉');
|
|
21
|
+
outro(chalk.inverse(' ✓ nextjs-cms setup completed successfully '));
|
|
50
22
|
}
|
|
51
23
|
catch (error) {
|
|
52
|
-
console.
|
|
53
|
-
|
|
24
|
+
console.log('');
|
|
25
|
+
console.error(chalk.red('✗ Error during setup:'), error);
|
|
26
|
+
outro(chalk.red('✗ Setup failed'));
|
|
27
|
+
// Lazy import for cleanup
|
|
28
|
+
const { dbConnectionClose } = await import('nextjs-cms/db/client');
|
|
29
|
+
await dbConnectionClose();
|
|
54
30
|
process.exit(1);
|
|
55
31
|
}
|
|
56
32
|
finally {
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import dotenv from 'dotenv';
|
|
3
3
|
import program from './lib/program.js';
|
|
4
|
-
import * as p from '@clack/prompts';
|
|
5
4
|
program.parse(process.argv);
|
|
6
5
|
// Load environment file based on parsed dev flag
|
|
7
6
|
if (Boolean(program.opts().dev) === true) {
|
|
8
|
-
|
|
9
|
-
dotenv.config({ path: '.env.development' });
|
|
7
|
+
dotenv.config({ path: '.env.development', quiet: true });
|
|
10
8
|
process.env.NODE_ENV = 'development';
|
|
11
9
|
}
|
|
12
10
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/lib/actions.ts"],"names":[],"mappings":"AAAA,wBAAsB,wBAAwB,
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/lib/actions.ts"],"names":[],"mappings":"AAAA,wBAAsB,wBAAwB,kBA6B7C;AAED,wBAAsB,cAAc;;;sBAgBnC;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,iBAyBnD"}
|
package/dist/lib/actions.js
CHANGED
|
@@ -5,7 +5,7 @@ export async function fixMasterAdminPrivileges() {
|
|
|
5
5
|
const { AdminPrivilegesTable } = await import('nextjs-cms/db/schema');
|
|
6
6
|
// Let's also add privileges for all the sections to the master admin
|
|
7
7
|
// Loop through the sections to get the section ids for the insertion into the admin_privileges table
|
|
8
|
-
const sections = await SectionFactory.
|
|
8
|
+
const sections = await SectionFactory.getSectionsSilently();
|
|
9
9
|
const rows = sections.map((section) => ({
|
|
10
10
|
adminId: '1',
|
|
11
11
|
sectionName: section.name,
|
|
@@ -23,7 +23,6 @@ export async function fixMasterAdminPrivileges() {
|
|
|
23
23
|
publisher: true,
|
|
24
24
|
},
|
|
25
25
|
});
|
|
26
|
-
console.log('Master admin privileges are set');
|
|
27
26
|
return;
|
|
28
27
|
}
|
|
29
28
|
export async function getMasterAdmin() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db-config-setup.d.ts","sourceRoot":"","sources":["../../src/lib/db-config-setup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"db-config-setup.d.ts","sourceRoot":"","sources":["../../src/lib/db-config-setup.ts"],"names":[],"mappings":"AAmCA,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,iBAkP5D"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { createConnection } from 'mysql2/promise';
|
|
2
|
-
import {
|
|
2
|
+
import { log, isCancel, outro, text } from '@clack/prompts';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import { cwd } from 'process';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import ora from 'ora';
|
|
6
8
|
/**
|
|
7
9
|
* Removes specific environment variables from the .env file content
|
|
8
10
|
* Removes both the generated comment block and the individual variable lines
|
|
@@ -27,11 +29,12 @@ function isValidPort(value) {
|
|
|
27
29
|
}
|
|
28
30
|
export async function dbConfigSetup(options) {
|
|
29
31
|
const { dev = false } = options;
|
|
30
|
-
|
|
32
|
+
const envFileName = dev ? '.env.development' : '.env.production';
|
|
31
33
|
/**
|
|
32
34
|
* Step 1: Ask for connection credentials
|
|
33
35
|
*/
|
|
34
|
-
|
|
36
|
+
log.info('Database Connection');
|
|
37
|
+
log.message('Please provide your MySQL/MariaDB server credentials');
|
|
35
38
|
const dbHost = await text({
|
|
36
39
|
message: 'Database host:',
|
|
37
40
|
placeholder: 'localhost',
|
|
@@ -84,10 +87,9 @@ export async function dbConfigSetup(options) {
|
|
|
84
87
|
/**
|
|
85
88
|
* Step 2: Test the database connection
|
|
86
89
|
*/
|
|
87
|
-
const s =
|
|
90
|
+
const s = ora('Testing database connection...').start();
|
|
88
91
|
let migrationClient;
|
|
89
92
|
try {
|
|
90
|
-
s.start('Testing database connection...');
|
|
91
93
|
/**
|
|
92
94
|
* It's recommended to not use a pool connection for migrations, that's why we're creating a new connection here.
|
|
93
95
|
*/
|
|
@@ -98,13 +100,14 @@ export async function dbConfigSetup(options) {
|
|
|
98
100
|
database: '',
|
|
99
101
|
port: parseInt(String(dbPort), 10),
|
|
100
102
|
});
|
|
101
|
-
s.stop(
|
|
103
|
+
s.stop();
|
|
104
|
+
log.success(chalk.green('✓ Connected successfully!'));
|
|
102
105
|
/**
|
|
103
106
|
* Step 3: Now that connection is successful, ask for database name
|
|
104
107
|
*/
|
|
105
|
-
note('If the database does not exist, it will be created', 'Database Name');
|
|
106
108
|
const dbName = await text({
|
|
107
109
|
message: 'Database name:',
|
|
110
|
+
placeholder: 'If the database does not exist, it will be created',
|
|
108
111
|
validate(value) {
|
|
109
112
|
if (value.length < 2)
|
|
110
113
|
return `Database name must be at least 2 characters`;
|
|
@@ -126,11 +129,12 @@ export async function dbConfigSetup(options) {
|
|
|
126
129
|
* Let's create the database using parameterized query to prevent SQL injection
|
|
127
130
|
*/
|
|
128
131
|
await migrationClient.query('CREATE DATABASE IF NOT EXISTS ??', [dbName]);
|
|
129
|
-
s.stop(
|
|
132
|
+
s.stop();
|
|
133
|
+
log.success(chalk.green('✓ Database created successfully!'));
|
|
130
134
|
/**
|
|
131
135
|
* Let's save the database credentials in the .env file
|
|
132
136
|
*/
|
|
133
|
-
const envPath = path.resolve(cwd(),
|
|
137
|
+
const envPath = path.resolve(cwd(), envFileName);
|
|
134
138
|
/**
|
|
135
139
|
* If the .env file does not exist, we'll create it
|
|
136
140
|
*/
|
|
@@ -174,17 +178,44 @@ DB_PASSWORD='${dbPassword}'
|
|
|
174
178
|
DB_PASSWORD: String(dbPassword),
|
|
175
179
|
};
|
|
176
180
|
const { reloadAndUpdateEnvironmentVariables } = await import('./reload-env.js');
|
|
177
|
-
const reloadSuccess = reloadAndUpdateEnvironmentVariables(dbVariables,
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
181
|
+
const reloadSuccess = reloadAndUpdateEnvironmentVariables(dbVariables, envFileName);
|
|
182
|
+
/**
|
|
183
|
+
* Get environment variables from env and check if they are correct
|
|
184
|
+
*/
|
|
185
|
+
const envDbHost = process.env.DB_HOST;
|
|
186
|
+
const envDbPort = process.env.DB_PORT;
|
|
187
|
+
const envDbName = process.env.DB_NAME;
|
|
188
|
+
const envDbUser = process.env.DB_USER;
|
|
189
|
+
const envDbPassword = process.env.DB_PASSWORD;
|
|
190
|
+
// Validate that the values match what we just set
|
|
191
|
+
const mismatches = [];
|
|
192
|
+
if (envDbHost !== String(dbHost))
|
|
193
|
+
mismatches.push('DB_HOST');
|
|
194
|
+
if (envDbPort !== String(dbPort))
|
|
195
|
+
mismatches.push('DB_PORT');
|
|
196
|
+
if (envDbName !== String(dbName))
|
|
197
|
+
mismatches.push('DB_NAME');
|
|
198
|
+
if (envDbUser !== String(dbUser))
|
|
199
|
+
mismatches.push('DB_USER');
|
|
200
|
+
if (envDbPassword !== String(dbPassword))
|
|
201
|
+
mismatches.push('DB_PASSWORD');
|
|
202
|
+
if (mismatches.length > 0) {
|
|
203
|
+
log.error(`✗ Couldn't save database credentials to ${envFileName} file}`);
|
|
204
|
+
console.error(`Please save these values manually to the ${envFileName} file:`);
|
|
205
|
+
console.error(`DB_HOST: ${dbHost}`);
|
|
206
|
+
console.error(`DB_PORT: ${dbPort}`);
|
|
207
|
+
console.error(`DB_NAME: ${dbName}`);
|
|
208
|
+
console.error(`DB_USER: ${dbUser}`);
|
|
209
|
+
console.error(`DB_PASSWORD: ${dbPassword}`);
|
|
210
|
+
console.error();
|
|
211
|
+
console.error(chalk.cyan(`and then run: ${chalk.green(`pnpm nextjs-cms ${dev ? '-d' : ''} setup --continue`)} to continue your setup`));
|
|
212
|
+
process.exit(1);
|
|
183
213
|
}
|
|
184
|
-
|
|
214
|
+
log.message(chalk.cyan(` - Saved database credentials to ${envFileName} file`));
|
|
185
215
|
}
|
|
186
216
|
catch (error) {
|
|
187
|
-
s.stop(
|
|
217
|
+
s.stop();
|
|
218
|
+
log.error(chalk.red('✗ Database setup failed!'));
|
|
188
219
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
189
220
|
const errorCode = error && typeof error === 'object' && 'code' in error ? error.code : null;
|
|
190
221
|
// Provide specific error messages based on error type
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-migrate.d.ts","sourceRoot":"","sources":["../../src/lib/db-migrate.ts"],"names":[],"mappings":"AAOA,wBAAsB,sBAAsB,kBAqF3C"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { log, select } from '@clack/prompts';
|
|
2
|
+
import { execWithSpinner } from './exec-utils.js';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { MysqlTableChecker } from 'nextjs-cms/core/db';
|
|
5
|
+
import { db } from 'nextjs-cms/db/client';
|
|
6
|
+
import { sql } from 'nextjs-cms/db';
|
|
7
|
+
export async function generateDatabaseSchema() {
|
|
8
|
+
/**
|
|
9
|
+
* We should first drop all primary keys from the tables
|
|
10
|
+
*/
|
|
11
|
+
const _existingTables = [];
|
|
12
|
+
const tablesToCheck = [
|
|
13
|
+
'__nextjs_cms_tables',
|
|
14
|
+
'cms_settings',
|
|
15
|
+
'admins',
|
|
16
|
+
'admin_privileges',
|
|
17
|
+
'access_tokens',
|
|
18
|
+
'editor_photos',
|
|
19
|
+
];
|
|
20
|
+
try {
|
|
21
|
+
const result = await MysqlTableChecker.getExistingTables();
|
|
22
|
+
result.forEach((table) => {
|
|
23
|
+
if (tablesToCheck.includes(table)) {
|
|
24
|
+
_existingTables.push(table);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
if (_existingTables.length > 0) {
|
|
28
|
+
const allOrSome = _existingTables.length === tablesToCheck.length ? 'all' : 'some';
|
|
29
|
+
log.warn(chalk.yellow(`You already have ${allOrSome === 'some' ? 'a few required tables from' : ''} a previous database schema:`));
|
|
30
|
+
for (const table of _existingTables) {
|
|
31
|
+
log.message(chalk.yellow(` - ${table}`));
|
|
32
|
+
}
|
|
33
|
+
log.message(chalk.cyan('These tables will be dropped and new ones will be created.'));
|
|
34
|
+
const answer = await select({
|
|
35
|
+
message: 'Do you want to continue? (y/n)',
|
|
36
|
+
options: [
|
|
37
|
+
{ value: 'y', label: 'Yes' },
|
|
38
|
+
{ value: 'n', label: 'No' },
|
|
39
|
+
],
|
|
40
|
+
initialValue: 'n',
|
|
41
|
+
});
|
|
42
|
+
if (answer !== 'y') {
|
|
43
|
+
log.error(chalk.red('Aborted'));
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
// Disable foreign key checks to allow dropping tables with foreign key constraints
|
|
48
|
+
await db.execute(sql `SET FOREIGN_KEY_CHECKS = 0`);
|
|
49
|
+
// Drop all tables at once
|
|
50
|
+
for (const table of _existingTables) {
|
|
51
|
+
await db.execute(sql `DROP TABLE IF EXISTS \`${sql.raw(table)}\``);
|
|
52
|
+
}
|
|
53
|
+
// Re-enable foreign key checks
|
|
54
|
+
await db.execute(sql `SET FOREIGN_KEY_CHECKS = 1`);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
// Re-enable foreign key checks even if there's an error
|
|
58
|
+
await db.execute(sql `SET FOREIGN_KEY_CHECKS = 1`).catch(() => {
|
|
59
|
+
// Ignore errors when re-enabling
|
|
60
|
+
});
|
|
61
|
+
console.error(chalk.red('✗ Error dropping existing tables:'), error);
|
|
62
|
+
log.error(chalk.red('✗ Failed to drop existing tables'));
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const spinner = await execWithSpinner({
|
|
67
|
+
command: 'pnpm',
|
|
68
|
+
args: ['drizzle-kit', 'push', '--force', '--config=drizzle.config.ts'],
|
|
69
|
+
cwd: process.cwd(),
|
|
70
|
+
stdout: 'pipe', // Show output
|
|
71
|
+
stderr: 'inherit', // Show errors
|
|
72
|
+
spinnerText: 'Generating database schema...',
|
|
73
|
+
checkExitCode: true, // Throw on non-zero exit codes
|
|
74
|
+
checkStderrForErrors: true, // Also check for errors in output even if exit code is 0
|
|
75
|
+
});
|
|
76
|
+
spinner?.stop();
|
|
77
|
+
log.success(chalk.green('✓ Database schema generated'));
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.error(chalk.red('✗ Error generating database schema:'), error);
|
|
81
|
+
log.error(chalk.red('✗ Failed to generate database schema'));
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
checkStderrForErrors?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Execute a command with a spinner, handling different stdio configurations
|
|
16
|
+
* and optional data handlers for progress updates.
|
|
17
|
+
*/
|
|
18
|
+
export declare const execWithSpinner: (options: ExecWithSpinnerOptions) => Promise<Ora | null>;
|
|
19
|
+
//# sourceMappingURL=exec-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec-utils.d.ts","sourceRoot":"","sources":["../../src/lib/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;IACvB,oBAAoB,CAAC,EAAE,OAAO,CAAA;CACjC;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAU,SAAS,sBAAsB,KAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAuGzF,CAAA"}
|
|
@@ -0,0 +1,95 @@
|
|
|
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, checkStderrForErrors = false, } = options;
|
|
9
|
+
const spinner = ora(spinnerText).start();
|
|
10
|
+
// If we need to check for errors in stderr but want to show it, we need to pipe it
|
|
11
|
+
const actualStderr = checkStderrForErrors && stderr === 'inherit' ? 'pipe' : stderr;
|
|
12
|
+
const actualStdout = checkStderrForErrors && stdout === 'inherit' ? 'pipe' : stdout;
|
|
13
|
+
const subprocess = execa(command, args, {
|
|
14
|
+
cwd,
|
|
15
|
+
stdout: actualStdout,
|
|
16
|
+
stderr: actualStderr,
|
|
17
|
+
reject: false, // Don't reject on non-zero exit codes - we handle it manually
|
|
18
|
+
});
|
|
19
|
+
let stderrOutput = '';
|
|
20
|
+
let stdoutOutput = '';
|
|
21
|
+
await new Promise((res, rej) => {
|
|
22
|
+
if (onDataHandle) {
|
|
23
|
+
subprocess.stdout?.on('data', onDataHandle(spinner));
|
|
24
|
+
}
|
|
25
|
+
else if (actualStdout === 'pipe') {
|
|
26
|
+
// Capture stdout to check for errors
|
|
27
|
+
subprocess.stdout?.on('data', (data) => {
|
|
28
|
+
const text = data.toString();
|
|
29
|
+
stdoutOutput += text;
|
|
30
|
+
// If we're supposed to inherit stdout, output it
|
|
31
|
+
if (stdout === 'inherit') {
|
|
32
|
+
process.stdout.write(data);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
if (onStderrHandle) {
|
|
37
|
+
subprocess.stderr?.on('data', (data) => {
|
|
38
|
+
onStderrHandle(data);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
else if (actualStderr === 'pipe') {
|
|
42
|
+
// Capture stderr to check for specific errors
|
|
43
|
+
subprocess.stderr?.on('data', (data) => {
|
|
44
|
+
const text = data.toString();
|
|
45
|
+
stderrOutput += text;
|
|
46
|
+
// If we're supposed to inherit stderr, output it
|
|
47
|
+
if (stderr === 'inherit') {
|
|
48
|
+
process.stderr.write(data);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
void subprocess.on('error', (e) => rej(e));
|
|
53
|
+
void subprocess.on('close', (code) => {
|
|
54
|
+
// Check for errors in stderr/stdout even if exit code is 0
|
|
55
|
+
if (checkStderrForErrors) {
|
|
56
|
+
const combinedOutput = (stderrOutput + stdoutOutput).toLowerCase();
|
|
57
|
+
const hasError = combinedOutput.includes('error:') ||
|
|
58
|
+
combinedOutput.includes('errno:') ||
|
|
59
|
+
combinedOutput.includes('sqlstate:') ||
|
|
60
|
+
combinedOutput.includes('multiple primary key') ||
|
|
61
|
+
combinedOutput.includes('er_multiple_pri_key') ||
|
|
62
|
+
/error\s+\d+/.test(combinedOutput);
|
|
63
|
+
if (hasError) {
|
|
64
|
+
const error = new Error(`${command} encountered an error during execution`);
|
|
65
|
+
if (stderrOutput) {
|
|
66
|
+
;
|
|
67
|
+
error.stderr = stderrOutput;
|
|
68
|
+
}
|
|
69
|
+
if (stdoutOutput) {
|
|
70
|
+
;
|
|
71
|
+
error.stdout = stdoutOutput;
|
|
72
|
+
}
|
|
73
|
+
rej(error);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (checkExitCode && code !== 0) {
|
|
78
|
+
const error = new Error(`${command} exited with code ${code}`);
|
|
79
|
+
if (stderrOutput) {
|
|
80
|
+
;
|
|
81
|
+
error.stderr = stderrOutput;
|
|
82
|
+
}
|
|
83
|
+
if (stdoutOutput) {
|
|
84
|
+
;
|
|
85
|
+
error.stdout = stdoutOutput;
|
|
86
|
+
}
|
|
87
|
+
rej(error);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
res();
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
return spinner;
|
|
95
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../../src/lib/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../../src/lib/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAA;AAgO3C,QAAA,MAAM,OAAO,SAAgB,CAAA;AAuE7B,eAAe,OAAO,CAAA"}
|
package/dist/lib/program.js
CHANGED
|
@@ -103,7 +103,8 @@ function shouldSkipValidation() {
|
|
|
103
103
|
args.includes('--help') ||
|
|
104
104
|
args.includes('-V') ||
|
|
105
105
|
args.includes('--version') ||
|
|
106
|
-
args.includes('-v')
|
|
106
|
+
args.includes('-v') ||
|
|
107
|
+
args.includes('--force'));
|
|
107
108
|
}
|
|
108
109
|
function validateNextjsCmsApp() {
|
|
109
110
|
// Skip validation for help and version commands
|
|
@@ -157,6 +158,7 @@ const program = new Command();
|
|
|
157
158
|
program
|
|
158
159
|
.name('nextjs-cms-kit')
|
|
159
160
|
.option('-d, --dev', 'use development environment file, use -d/--dev before any command to use the development environment file (e.g. nextjs-cms-kit -d setup)', false)
|
|
161
|
+
.option('-f, --force', 'force the command to run even when version mismatch is detected', false)
|
|
160
162
|
.description(chalk.green('nextjs-cms CLI toolkit for managing your nextjs-cms application'))
|
|
161
163
|
.version(version)
|
|
162
164
|
// Include -v option to show the version number
|
|
@@ -165,10 +167,12 @@ program
|
|
|
165
167
|
program
|
|
166
168
|
.command('setup')
|
|
167
169
|
.description('Complete nextjs-cms setup')
|
|
170
|
+
.option('--continue', 'continue the setup if you have already setup the database', false)
|
|
168
171
|
.passThroughOptions()
|
|
169
|
-
.action(async ()
|
|
172
|
+
.action(async function () {
|
|
173
|
+
const c = Boolean(this.opts().continue);
|
|
170
174
|
const { runSetup } = await import('../commands/setup.js');
|
|
171
|
-
await runSetup(Boolean(program.opts().dev));
|
|
175
|
+
await runSetup(Boolean(program.opts().dev), c);
|
|
172
176
|
});
|
|
173
177
|
program
|
|
174
178
|
.command('db-config')
|
package/dist/lib/reload-env.js
CHANGED
|
@@ -8,7 +8,7 @@ import path from 'path';
|
|
|
8
8
|
export function reloadEnvironmentVariables(envFile) {
|
|
9
9
|
try {
|
|
10
10
|
const envPath = envFile ? path.resolve(cwd(), envFile) : undefined;
|
|
11
|
-
const result = config({ path: envPath });
|
|
11
|
+
const result = config({ path: envPath, quiet: true });
|
|
12
12
|
if (result.error) {
|
|
13
13
|
console.warn('⚠️ Error loading .env file:', result.error);
|
|
14
14
|
return false;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-title.d.ts","sourceRoot":"","sources":["../../src/lib/render-title.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,QAAQ,cAGpB,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import gradient from 'gradient-string';
|
|
2
|
+
// colors brought in from vscode poimandres theme
|
|
3
|
+
const poimandresTheme = {
|
|
4
|
+
cyan: '#89ddff',
|
|
5
|
+
green: '#5de4c7',
|
|
6
|
+
magenta: '#fae4fc',
|
|
7
|
+
red: '#d0679d',
|
|
8
|
+
};
|
|
9
|
+
export const getTitle = () => {
|
|
10
|
+
const titleGradient = gradient(Object.values(poimandresTheme));
|
|
11
|
+
return titleGradient('nextjs-cms-kit');
|
|
12
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set-master-admin.d.ts","sourceRoot":"","sources":["../../src/lib/set-master-admin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"set-master-admin.d.ts","sourceRoot":"","sources":["../../src/lib/set-master-admin.ts"],"names":[],"mappings":"AAIA,wBAAsB,cAAc,kBA0DnC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as p from '@clack/prompts';
|
|
2
|
+
import chalk from 'chalk';
|
|
2
3
|
export async function setMasterAdmin() {
|
|
3
|
-
p.intro(`Setting up master admin...`);
|
|
4
4
|
/**
|
|
5
5
|
* Check if the master admin is already set
|
|
6
6
|
*/
|
|
@@ -50,6 +50,6 @@ export async function setMasterAdmin() {
|
|
|
50
50
|
const { fixMasterAdminPrivileges } = await import('./actions.js');
|
|
51
51
|
await setMaterAdmin(password);
|
|
52
52
|
await fixMasterAdminPrivileges();
|
|
53
|
-
p.
|
|
54
|
-
|
|
53
|
+
p.log.success(chalk.green('✓ Master admin and admin privileges are set'));
|
|
54
|
+
p.log.message(chalk.cyan(' - Master admin username: Master'));
|
|
55
55
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { db } from 'nextjs-cms/db/client';
|
|
2
|
-
import {
|
|
2
|
+
import { NextJsCmsTablesTable } from 'nextjs-cms/db/schema';
|
|
3
3
|
import { eq, sql } from 'drizzle-orm';
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
import path from 'path';
|
|
@@ -233,16 +233,16 @@ async function createTable(table, options) {
|
|
|
233
233
|
*/
|
|
234
234
|
await db.execute(sql `${sql.raw(createTableSQL)}`);
|
|
235
235
|
/**
|
|
236
|
-
* Insert the table name into the `
|
|
236
|
+
* Insert the table name into the `__nextjs_cms_tables` table
|
|
237
237
|
*/
|
|
238
238
|
await db
|
|
239
|
-
.insert(
|
|
239
|
+
.insert(NextJsCmsTablesTable)
|
|
240
240
|
.values({
|
|
241
241
|
tableName: table.name,
|
|
242
242
|
sectionName: table.sectionName,
|
|
243
243
|
})
|
|
244
244
|
.catch((error) => {
|
|
245
|
-
console.error('Error inserting into
|
|
245
|
+
console.error('Error inserting into __nextjs_cms_tables table:', error);
|
|
246
246
|
});
|
|
247
247
|
}
|
|
248
248
|
catch (error) {
|
|
@@ -265,16 +265,16 @@ async function renameTable(oldName, newName) {
|
|
|
265
265
|
try {
|
|
266
266
|
await db.execute(sql `ALTER TABLE \`${sql.raw(oldName)}\` RENAME \`${sql.raw(newName)}\``);
|
|
267
267
|
/**
|
|
268
|
-
* Update the table name in the `
|
|
268
|
+
* Update the table name in the `__nextjs_cms_tables` table
|
|
269
269
|
*/
|
|
270
270
|
await db
|
|
271
|
-
.update(
|
|
271
|
+
.update(NextJsCmsTablesTable)
|
|
272
272
|
.set({
|
|
273
273
|
tableName: newName,
|
|
274
274
|
})
|
|
275
|
-
.where(eq(
|
|
275
|
+
.where(eq(NextJsCmsTablesTable.tableName, oldName))
|
|
276
276
|
.catch((error) => {
|
|
277
|
-
console.error('Error updating
|
|
277
|
+
console.error('Error updating __nextjs_cms_tables table:', error);
|
|
278
278
|
});
|
|
279
279
|
console.log(`Table \`${oldName}\` renamed to \`${newName}\` successfully.`);
|
|
280
280
|
}
|
|
@@ -534,19 +534,19 @@ const main = async (s) => {
|
|
|
534
534
|
console.log(`Found ${sections.length} section(s) to insert: `);
|
|
535
535
|
console.log(chalk.gray(sections.map((s) => s.name).join(', ')));
|
|
536
536
|
/**
|
|
537
|
-
* Let's see if the table `
|
|
537
|
+
* Let's see if the table `__nextjs_cms_tables` exists in the database.
|
|
538
538
|
* If it doesn't, we'll create it.
|
|
539
539
|
* It has two fields: `name` and `created_at`.
|
|
540
540
|
*/
|
|
541
|
-
await db.execute(sql ` CREATE TABLE IF NOT EXISTS
|
|
541
|
+
await db.execute(sql ` CREATE TABLE IF NOT EXISTS __nextjs_cms_tables ( name VARCHAR(100) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) `);
|
|
542
542
|
/**
|
|
543
543
|
* Get the existing tables from the database
|
|
544
544
|
*/
|
|
545
545
|
existingTables = await db
|
|
546
546
|
.select({
|
|
547
|
-
name:
|
|
547
|
+
name: NextJsCmsTablesTable.tableName,
|
|
548
548
|
})
|
|
549
|
-
.from(
|
|
549
|
+
.from(NextJsCmsTablesTable);
|
|
550
550
|
/**
|
|
551
551
|
* Insert the sections into the database
|
|
552
552
|
*/
|
|
@@ -876,13 +876,13 @@ const main = async (s) => {
|
|
|
876
876
|
console.log(chalk.gray(` - Keeping table '${table.name}'`));
|
|
877
877
|
}
|
|
878
878
|
/**
|
|
879
|
-
* Remove the table from the `
|
|
879
|
+
* Remove the table from the `__nextjs_cms_tables` table
|
|
880
880
|
*/
|
|
881
881
|
await db
|
|
882
|
-
.delete(
|
|
883
|
-
.where(eq(
|
|
882
|
+
.delete(NextJsCmsTablesTable)
|
|
883
|
+
.where(eq(NextJsCmsTablesTable.tableName, table.name))
|
|
884
884
|
.catch((error) => {
|
|
885
|
-
console.error('Error deleting from
|
|
885
|
+
console.error('Error deleting from __nextjs_cms_tables table:', error);
|
|
886
886
|
});
|
|
887
887
|
break;
|
|
888
888
|
case 'later':
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nextjs-cms-kit",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.66",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"nextjs-cms-kit": "./dist/index.js"
|
|
@@ -29,8 +29,11 @@
|
|
|
29
29
|
"commander": "^14.0.2",
|
|
30
30
|
"dotenv": "^17.2.3",
|
|
31
31
|
"drizzle-zod": "^0.8.3",
|
|
32
|
+
"execa": "9.6.1",
|
|
33
|
+
"gradient-string": "^3.0.0",
|
|
32
34
|
"mysql2": "^3.12.0",
|
|
33
|
-
"
|
|
35
|
+
"ora": "9.0.0",
|
|
36
|
+
"nextjs-cms": "0.5.66"
|
|
34
37
|
},
|
|
35
38
|
"devDependencies": {
|
|
36
39
|
"@types/bcrypt": "^6.0.0",
|
|
@@ -39,8 +42,8 @@
|
|
|
39
42
|
"prettier": "^3.3.3",
|
|
40
43
|
"tsx": "^4.20.6",
|
|
41
44
|
"typescript": "^5.9.2",
|
|
42
|
-
"@lzcms/eslint-config": "0.3.0",
|
|
43
45
|
"@lzcms/prettier-config": "0.1.0",
|
|
46
|
+
"@lzcms/eslint-config": "0.3.0",
|
|
44
47
|
"@lzcms/tsconfig": "0.1.0"
|
|
45
48
|
},
|
|
46
49
|
"prettier": "@lzcms/prettier-config",
|