nextjs-cms 0.6.8 → 0.7.0

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 (105) hide show
  1. package/dist/cli/commands/db-config.d.ts +2 -0
  2. package/dist/cli/commands/db-config.d.ts.map +1 -0
  3. package/dist/cli/commands/db-config.js +22 -0
  4. package/dist/cli/commands/fix-master-admin.d.ts +2 -0
  5. package/dist/cli/commands/fix-master-admin.d.ts.map +1 -0
  6. package/dist/cli/commands/fix-master-admin.js +22 -0
  7. package/dist/cli/commands/set-master-admin.d.ts +2 -0
  8. package/dist/cli/commands/set-master-admin.d.ts.map +1 -0
  9. package/dist/cli/commands/set-master-admin.js +25 -0
  10. package/dist/cli/commands/setup.d.ts +2 -0
  11. package/dist/cli/commands/setup.d.ts.map +1 -0
  12. package/dist/cli/commands/setup.js +34 -0
  13. package/dist/cli/commands/update-sections.d.ts +2 -0
  14. package/dist/cli/commands/update-sections.d.ts.map +1 -0
  15. package/dist/cli/commands/update-sections.js +27 -0
  16. package/dist/cli/index.d.ts +3 -0
  17. package/dist/cli/index.d.ts.map +1 -0
  18. package/dist/cli/index.js +15 -0
  19. package/dist/cli/lib/db-config.d.ts +4 -0
  20. package/dist/cli/lib/db-config.d.ts.map +1 -0
  21. package/dist/cli/lib/db-config.js +238 -0
  22. package/dist/cli/lib/db-migrate.d.ts +2 -0
  23. package/dist/cli/lib/db-migrate.d.ts.map +1 -0
  24. package/dist/cli/lib/db-migrate.js +83 -0
  25. package/dist/cli/lib/fix-master-admin.d.ts +2 -0
  26. package/dist/cli/lib/fix-master-admin.d.ts.map +1 -0
  27. package/dist/cli/lib/fix-master-admin.js +53 -0
  28. package/dist/cli/lib/set-master-admin.d.ts +2 -0
  29. package/dist/cli/lib/set-master-admin.d.ts.map +1 -0
  30. package/dist/cli/lib/set-master-admin.js +88 -0
  31. package/dist/cli/lib/update-sections.d.ts +2 -0
  32. package/dist/cli/lib/update-sections.d.ts.map +1 -0
  33. package/dist/cli/lib/update-sections.js +915 -0
  34. package/dist/cli/program/program.d.ts +4 -0
  35. package/dist/cli/program/program.d.ts.map +1 -0
  36. package/dist/cli/program/program.js +95 -0
  37. package/dist/cli/utils/add-table-keys.d.ts +32 -0
  38. package/dist/cli/utils/add-table-keys.d.ts.map +1 -0
  39. package/dist/cli/utils/add-table-keys.js +171 -0
  40. package/dist/cli/utils/check-version.d.ts +3 -0
  41. package/dist/cli/utils/check-version.d.ts.map +1 -0
  42. package/dist/cli/utils/check-version.js +125 -0
  43. package/dist/cli/utils/display-intro.d.ts +6 -0
  44. package/dist/cli/utils/display-intro.d.ts.map +1 -0
  45. package/dist/cli/utils/display-intro.js +9 -0
  46. package/dist/cli/utils/exec-utils.d.ts +19 -0
  47. package/dist/cli/utils/exec-utils.d.ts.map +1 -0
  48. package/dist/cli/utils/exec-utils.js +95 -0
  49. package/dist/cli/utils/get-package-manager.d.ts +4 -0
  50. package/dist/cli/utils/get-package-manager.d.ts.map +1 -0
  51. package/dist/cli/utils/get-package-manager.js +22 -0
  52. package/dist/cli/utils/reload-env.d.ts +16 -0
  53. package/dist/cli/utils/reload-env.d.ts.map +1 -0
  54. package/dist/cli/utils/reload-env.js +42 -0
  55. package/dist/cli/utils/render-title.d.ts +2 -0
  56. package/dist/cli/utils/render-title.d.ts.map +1 -0
  57. package/dist/cli/utils/render-title.js +12 -0
  58. package/dist/cli/utils/schema-generator.d.ts +10 -0
  59. package/dist/cli/utils/schema-generator.d.ts.map +1 -0
  60. package/dist/cli/utils/schema-generator.js +171 -0
  61. package/dist/core/config/config-loader.d.ts +4 -10
  62. package/dist/core/config/config-loader.d.ts.map +1 -1
  63. package/dist/core/config/config-loader.js +14 -14
  64. package/dist/core/factories/section-factory-with-esbuild.d.ts +1 -1
  65. package/dist/core/factories/section-factory-with-esbuild.js +1 -1
  66. package/dist/core/factories/section-factory-with-jiti.d.ts +1 -1
  67. package/dist/core/factories/section-factory-with-jiti.js +1 -1
  68. package/dist/core/sections/category.d.ts +32 -32
  69. package/dist/core/sections/hasItems.d.ts +32 -32
  70. package/dist/core/sections/section.d.ts +16 -16
  71. package/dist/core/sections/simple.d.ts +8 -8
  72. package/dist/db/config.js +1 -1
  73. package/dist/translations/base/en.d.ts +433 -0
  74. package/dist/translations/base/en.d.ts.map +1 -0
  75. package/dist/translations/base/en.js +444 -0
  76. package/dist/translations/client.d.ts +5178 -1
  77. package/dist/translations/client.d.ts.map +1 -1
  78. package/dist/translations/client.js +29 -4
  79. package/dist/translations/dict-store.d.ts +5 -1
  80. package/dist/translations/dict-store.d.ts.map +1 -1
  81. package/dist/translations/dict-store.js +31 -4
  82. package/dist/translations/index.d.ts +1 -1
  83. package/dist/translations/index.js +1 -1
  84. package/dist/translations/server.d.ts +5171 -1
  85. package/dist/translations/server.d.ts.map +1 -1
  86. package/dist/translations/server.js +26 -4
  87. package/package.json +18 -10
  88. package/dist/core/helpers/i18n.d.ts +0 -2
  89. package/dist/core/helpers/i18n.d.ts.map +0 -1
  90. package/dist/core/helpers/i18n.js +0 -3
  91. package/dist/core/localization.d.ts +0 -40
  92. package/dist/core/localization.d.ts.map +0 -1
  93. package/dist/core/localization.js +0 -48
  94. package/dist/logging/audit.d.ts +0 -20
  95. package/dist/logging/audit.d.ts.map +0 -1
  96. package/dist/logging/audit.js +0 -48
  97. package/dist/translations/localized-string.d.ts +0 -17
  98. package/dist/translations/localized-string.d.ts.map +0 -1
  99. package/dist/translations/localized-string.js +0 -32
  100. package/dist/translations/use-project-translation.d.ts +0 -19
  101. package/dist/translations/use-project-translation.d.ts.map +0 -1
  102. package/dist/translations/use-project-translation.js +0 -25
  103. package/dist/validators/types.d.ts +0 -7
  104. package/dist/validators/types.d.ts.map +0 -1
  105. package/dist/validators/types.js +0 -0
@@ -0,0 +1,4 @@
1
+ import { Command } from 'commander';
2
+ declare const program: Command;
3
+ export default program;
4
+ //# sourceMappingURL=program.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../../../src/cli/program/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAA;AAmB3C,QAAA,MAAM,OAAO,SAAgB,CAAA;AA4F7B,eAAe,OAAO,CAAA"}
@@ -0,0 +1,95 @@
1
+ import { Command, Option } from 'commander';
2
+ import chalk from 'chalk';
3
+ import process from 'node:process';
4
+ import * as p from '@clack/prompts';
5
+ import { displayIntro } from '../utils/display-intro.js';
6
+ import { packageVersion, validateNextjsCmsApp } from '../utils/check-version.js';
7
+ const handleSigTerm = () => {
8
+ p.log.message('\n');
9
+ p.cancel(`Aborted\n`);
10
+ process.exit(1);
11
+ };
12
+ process.on('SIGINT', handleSigTerm);
13
+ process.on('SIGTERM', handleSigTerm);
14
+ // Validate nextjs-cms app and dependencies before proceeding
15
+ validateNextjsCmsApp();
16
+ const program = new Command();
17
+ program
18
+ .name('nextjs-cms')
19
+ .option('-d, --dev', 'use development environment file, use -d/--dev before any command to use the development environment file (e.g. nextjs-cms -d setup)', false)
20
+ .addOption(new Option('-f, --force', 'force the command to run even when version mismatch is detected').hideHelp())
21
+ .description(chalk.green('nextjs-cms CLI toolkit for managing your nextjs-cms application'))
22
+ .version(packageVersion)
23
+ // Include -v option to show the version number
24
+ .addOption(new Option('-v').hideHelp())
25
+ .enablePositionalOptions();
26
+ program
27
+ .command('setup')
28
+ .description('Complete nextjs-cms setup')
29
+ .option('--continue', 'continue the setup if you have already setup the database', false)
30
+ .passThroughOptions()
31
+ .action(async function () {
32
+ const c = Boolean(this.opts().continue);
33
+ const { runSetup } = await import('../commands/setup.js');
34
+ displayIntro({ command: 'setup', dev: Boolean(program.opts().dev), title: 'Setting up nextjs-cms 🚀' });
35
+ await runSetup(Boolean(program.opts().dev), c);
36
+ });
37
+ program
38
+ .command('db-config')
39
+ .description('Initialize nextjs-cms database configuration')
40
+ .passThroughOptions()
41
+ .action(async () => {
42
+ const { runDbConfig } = await import('../commands/db-config.js');
43
+ displayIntro({
44
+ command: 'db-config',
45
+ dev: Boolean(program.opts().dev),
46
+ title: 'Configuring database',
47
+ });
48
+ await runDbConfig(Boolean(program.opts().dev));
49
+ });
50
+ program
51
+ .command('set-master-admin')
52
+ .description('Set or update master admin password')
53
+ .passThroughOptions()
54
+ .action(async () => {
55
+ const { runSetMasterAdmin } = await import('../commands/set-master-admin.js');
56
+ displayIntro({
57
+ command: 'set-master-admin',
58
+ dev: Boolean(program.opts().dev),
59
+ title: 'Setting master admin',
60
+ });
61
+ await runSetMasterAdmin();
62
+ });
63
+ program
64
+ .command('fix-master-admin')
65
+ .description('Fix master admin privileges for all sections')
66
+ .passThroughOptions()
67
+ .action(async () => {
68
+ const { runFixMasterAdmin } = await import('../commands/fix-master-admin.js');
69
+ displayIntro({
70
+ command: 'fix-master-admin',
71
+ dev: Boolean(program.opts().dev),
72
+ title: 'Fixing master admin privileges',
73
+ });
74
+ await runFixMasterAdmin();
75
+ });
76
+ program
77
+ .command('update-sections')
78
+ .description('Update database tables based on current sections and update master admin privileges')
79
+ .passThroughOptions()
80
+ .action(async () => {
81
+ const { runUpdateSections } = await import('../commands/update-sections.js');
82
+ displayIntro({
83
+ command: 'update-sections',
84
+ dev: Boolean(program.opts().dev),
85
+ title: 'Updating sections',
86
+ });
87
+ await runUpdateSections(Boolean(program.opts().dev));
88
+ });
89
+ program.showHelpAfterError('(add --help for additional information)');
90
+ // Show the version number when the -v option is used
91
+ program.on('option:v', () => {
92
+ console.log(program.version());
93
+ process.exit();
94
+ });
95
+ export default program;
@@ -0,0 +1,32 @@
1
+ import type { FieldConfig } from '../../core/fields/index.js';
2
+ export declare function addTableKeys(table: {
3
+ name: string;
4
+ primaryKey: FieldConfig[];
5
+ index?: {
6
+ name?: string;
7
+ columns: FieldConfig[];
8
+ }[];
9
+ unique?: {
10
+ name?: string;
11
+ columns: FieldConfig[];
12
+ }[];
13
+ fulltext?: {
14
+ name?: string;
15
+ columns: FieldConfig[];
16
+ }[];
17
+ }, existingKeys?: {
18
+ primaryKeys: string[];
19
+ uniqueKeys: {
20
+ name: string;
21
+ columns: string[];
22
+ }[];
23
+ indexKeys: {
24
+ name: string;
25
+ columns: string[];
26
+ }[];
27
+ fullTextKeys: {
28
+ name: string;
29
+ columns: string[];
30
+ }[];
31
+ }): Promise<number>;
32
+ //# sourceMappingURL=add-table-keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-table-keys.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/add-table-keys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AAG7D,wBAAsB,YAAY,CAC9B,KAAK,EAAE;IACH,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,WAAW,EAAE,CAAA;IACzB,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,WAAW,EAAE,CAAA;KAAE,EAAE,CAAA;IACnD,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,WAAW,EAAE,CAAA;KAAE,EAAE,CAAA;IACpD,QAAQ,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,WAAW,EAAE,CAAA;KAAE,EAAE,CAAA;CACzD,EACD,YAAY,CAAC,EAAE;IACX,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAA;IACjD,SAAS,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAA;IAChD,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAA;CACtD,mBAoPJ"}
@@ -0,0 +1,171 @@
1
+ import chalk from 'chalk';
2
+ export async function addTableKeys(table, existingKeys) {
3
+ // Lazy import heavy dependencies to avoid eager database connection initialization
4
+ const { db } = await import('../../db/client.js');
5
+ // console.log(chalk.gray(` - Checking table keys`))
6
+ /**
7
+ * Number of SQL errors
8
+ */
9
+ let sqlErrors = 0;
10
+ /**
11
+ * Add the primary key, but first, check if the primary key exists or has changed
12
+ */
13
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
14
+ if (table.primaryKey) {
15
+ if (existingKeys) {
16
+ const { primaryKeys } = existingKeys;
17
+ /**
18
+ * Check if the existing primary key matches the new primary key
19
+ */
20
+ const primaryKeyChanged = primaryKeys.length !== table.primaryKey.length ||
21
+ !table.primaryKey.every((key) => primaryKeys.includes(key.name));
22
+ /**
23
+ * If primary key doesn't exist or has changed, update it
24
+ */
25
+ if ((primaryKeys.length === 0 && table.primaryKey.length > 0) || primaryKeyChanged) {
26
+ /**
27
+ * Drop existing primary key if it exists
28
+ */
29
+ if (primaryKeys.length > 0) {
30
+ console.log(chalk.gray(` - Dropping existing primary key from '${table.name}: [${primaryKeys.join(', ')}]`));
31
+ try {
32
+ await db.execute(`ALTER TABLE \`${table.name}\` DROP PRIMARY KEY`);
33
+ }
34
+ catch (error) {
35
+ sqlErrors++;
36
+ console.error(chalk.red(` - Error dropping primary key for table '${table.name}':`, error));
37
+ }
38
+ }
39
+ /**
40
+ * Add the new primary key
41
+ */
42
+ console.log(chalk.gray(` - Adding primary key to '${table.name}': [${table.primaryKey.map((key) => key.name).join(', ')}]`));
43
+ try {
44
+ const primaryKeyColumns = table.primaryKey.map((column) => `\`${column.name}\``).join(', ');
45
+ await db.execute(`ALTER TABLE \`${table.name}\` ADD PRIMARY KEY (${primaryKeyColumns})`);
46
+ }
47
+ catch (error) {
48
+ sqlErrors++;
49
+ console.error(chalk.red(` - Error updating primary key for table '${table.name}':`, error));
50
+ /**
51
+ * Reverting to the old primary key
52
+ */
53
+ if (primaryKeys.length > 0) {
54
+ console.log(chalk.gray(` - Re-adding old primary key to '${table.name}': [${primaryKeys.map((key) => key).join(', ')}]`));
55
+ try {
56
+ const primaryKeyColumns = primaryKeys.map((column) => `\`${column}\``).join(', ');
57
+ await db.execute(`ALTER TABLE \`${table.name}\` ADD PRIMARY KEY (${primaryKeyColumns})`);
58
+ }
59
+ catch (error) {
60
+ sqlErrors++;
61
+ console.error(chalk.red(` - Error re-adding primary key for table '${table.name}':`, error));
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
67
+ else {
68
+ // TODO: What is this?
69
+ sqlErrors++;
70
+ }
71
+ }
72
+ /**
73
+ * Modify unique keys
74
+ */
75
+ if (table.unique) {
76
+ const existingUniqueKeys = existingKeys?.uniqueKeys ?? [];
77
+ for (const requestedUnique of table.unique) {
78
+ /**
79
+ * Check if the unique key already exists
80
+ */
81
+ const matchingUnique = existingUniqueKeys.find((u) => {
82
+ return (requestedUnique.columns.length === u.columns.length &&
83
+ requestedUnique.columns.every((col) => u.columns.includes(col.name)));
84
+ });
85
+ const uniqueColumns = requestedUnique.columns.map((col) => `\`${col.name}\``).join(', ');
86
+ /**
87
+ * If key doesn't exist, add it
88
+ */
89
+ if (!matchingUnique) {
90
+ console.log(chalk.gray(` - Adding unique key with columns [${requestedUnique.columns.map((col) => col.name).join(', ')}] to '${table.name}'`));
91
+ await db.execute(`ALTER TABLE \`${table.name}\` ADD UNIQUE ${requestedUnique.name ?? ''}(${uniqueColumns})`);
92
+ }
93
+ }
94
+ /**
95
+ * Drop any existing unique keys that are not in the new set (based on columns)
96
+ */
97
+ for (const existingUnique of existingUniqueKeys) {
98
+ if (!table.unique.find((unique) => {
99
+ return (unique.columns.length === existingUnique.columns.length &&
100
+ unique.columns.every((col) => existingUnique.columns.includes(col.name)));
101
+ })) {
102
+ console.log(chalk.gray(` - Dropping unique key with columns [${existingUnique.columns.join(', ')}] from '${table.name}'`));
103
+ await db.execute(`ALTER TABLE \`${table.name}\` DROP INDEX \`${existingUnique.name}\``);
104
+ }
105
+ }
106
+ }
107
+ /**
108
+ * Modify indexes
109
+ */
110
+ if (table.index) {
111
+ const existingIndexes = existingKeys?.indexKeys ?? [];
112
+ for (const index of table.index) {
113
+ const matchingIndex = existingIndexes.find((i) => {
114
+ return (index.columns.length === i.columns.length &&
115
+ index.columns.every((col) => i.columns.includes(col.name)));
116
+ });
117
+ const indexColumns = index.columns.map((col) => `\`${col.name}\``).join(', ');
118
+ if (!matchingIndex) {
119
+ // Add index
120
+ console.log(chalk.gray(` - Adding index with columns [${index.columns.map((col) => col.name).join(', ')}] to '${table.name}'`));
121
+ await db.execute(`ALTER TABLE \`${table.name}\` ADD INDEX ${index.name ?? ''}(${indexColumns})`);
122
+ }
123
+ }
124
+ /**
125
+ * Drop any existing indexes that are not in the new set (based on columns)
126
+ */
127
+ for (const existingIndex of existingIndexes) {
128
+ if (!table.index.find((index) => {
129
+ return (index.columns.length === existingIndex.columns.length &&
130
+ index.columns.every((col) => existingIndex.columns.includes(col.name)));
131
+ })) {
132
+ console.log(chalk.gray(` - Dropping index with columns [${existingIndex.columns.join(', ')}] from '${table.name}'`));
133
+ await db.execute(`ALTER TABLE \`${table.name}\` DROP INDEX \`${existingIndex.name}\``);
134
+ }
135
+ }
136
+ }
137
+ /**
138
+ * Modify fulltext indexes
139
+ */
140
+ if (table.fulltext) {
141
+ const existingIndexes = existingKeys?.fullTextKeys ?? [];
142
+ for (const requestedFullTextIndex of table.fulltext) {
143
+ const matchingFulltext = existingIndexes.find((i) => {
144
+ return (requestedFullTextIndex.columns.length === i.columns.length &&
145
+ requestedFullTextIndex.columns.every((col) => i.columns.includes(col.name)));
146
+ });
147
+ const fulltextColumns = requestedFullTextIndex.columns.map((col) => `\`${col.name}\``).join(', ');
148
+ /**
149
+ * If fulltext index doesn't exist, add it
150
+ */
151
+ if (!matchingFulltext) {
152
+ // Add fulltext index
153
+ console.log(chalk.gray(` - Adding fulltext index with columns [${requestedFullTextIndex.columns.map((col) => col.name).join(', ')}] to '${table.name}'`));
154
+ await db.execute(`ALTER TABLE \`${table.name}\` ADD FULLTEXT ${requestedFullTextIndex.name ?? ''}(${fulltextColumns})`);
155
+ }
156
+ }
157
+ /**
158
+ * Drop any existing fulltext indexes that are not in the new set (based on columns)
159
+ */
160
+ for (const existingFulltext of existingIndexes) {
161
+ if (!table.fulltext.find((fulltext) => {
162
+ return (fulltext.columns.length === existingFulltext.columns.length &&
163
+ fulltext.columns.every((col) => existingFulltext.columns.includes(col.name)));
164
+ })) {
165
+ console.log(chalk.gray(` - Dropping fulltext index with columns [${existingFulltext.columns.join(', ')}] from '${table.name}'`));
166
+ await db.execute(`ALTER TABLE \`${table.name}\` DROP INDEX \`${existingFulltext.name}\``);
167
+ }
168
+ }
169
+ }
170
+ return sqlErrors;
171
+ }
@@ -0,0 +1,3 @@
1
+ export declare function validateNextjsCmsApp(): void;
2
+ export declare const packageVersion: string;
3
+ //# sourceMappingURL=check-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-version.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/check-version.ts"],"names":[],"mappings":"AAoIA,wBAAgB,oBAAoB,IAAI,IAAI,CAsC3C;AAED,eAAO,MAAM,cAAc,QAAsB,CAAA"}
@@ -0,0 +1,125 @@
1
+ import { readFileSync, existsSync, realpathSync } from 'node:fs';
2
+ import { join, dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { createRequire } from 'module';
5
+ import chalk from 'chalk';
6
+ function findPackageJson(startDir) {
7
+ let dir = startDir ?? process.cwd();
8
+ while (true) {
9
+ const candidate = join(dir, 'package.json');
10
+ if (existsSync(candidate))
11
+ return candidate;
12
+ const parent = dirname(dir);
13
+ if (parent === dir)
14
+ break;
15
+ dir = parent;
16
+ }
17
+ return undefined;
18
+ }
19
+ function findConfigFile(startDir) {
20
+ let dir = startDir ?? process.cwd();
21
+ while (true) {
22
+ const candidate = join(dir, 'cms.config.ts');
23
+ if (existsSync(candidate))
24
+ return candidate;
25
+ const parent = dirname(dir);
26
+ if (parent === dir)
27
+ break;
28
+ dir = parent;
29
+ }
30
+ return undefined;
31
+ }
32
+ // Get version dynamically from package.json
33
+ const currentFilePath = fileURLToPath(import.meta.url);
34
+ const currentDir = dirname(currentFilePath);
35
+ const packageJsonPath = join(currentDir, '../../../package.json');
36
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
37
+ function checkNextjsCmsInstallation() {
38
+ const requireFromCwd = createRequire(join(process.cwd(), 'index.js'));
39
+ // Check for cms.config.ts file
40
+ const configFile = findConfigFile();
41
+ if (configFile === undefined) {
42
+ return { error: 'not-nextjs-cms-app' };
43
+ }
44
+ // Check for nextjs-cms dependency in package.json
45
+ const pkgPath = findPackageJson();
46
+ if (pkgPath === undefined) {
47
+ return { error: 'not-nextjs-cms-app' };
48
+ }
49
+ const packageJson = JSON.parse(readFileSync(pkgPath, 'utf8'));
50
+ const deps = {
51
+ ...(packageJson.dependencies ?? {}),
52
+ ...(packageJson.devDependencies ?? {}),
53
+ };
54
+ const versionInProjectPackageJson = deps['nextjs-cms'];
55
+ if (versionInProjectPackageJson === undefined) {
56
+ return { error: 'local-not-found' };
57
+ }
58
+ // Hard check for installed version
59
+ // Resolve whatever the package exports at "." (this IS allowed)
60
+ const entryPath = requireFromCwd.resolve('nextjs-cms');
61
+ // Follow symlinks (helps with pnpm layouts)
62
+ const startPath = realpathSync(entryPath);
63
+ const installedPackageJson = findPackageJson(startPath);
64
+ if (installedPackageJson === undefined) {
65
+ return {
66
+ error: 'local-needs-update',
67
+ installedVersion: 'undefined',
68
+ packageVersion: versionInProjectPackageJson,
69
+ };
70
+ }
71
+ const installedPackageJsonParsed = JSON.parse(readFileSync(installedPackageJson, 'utf8'));
72
+ const localInstalledVersion = installedPackageJsonParsed?.version ?? undefined;
73
+ if (localInstalledVersion !== versionInProjectPackageJson) {
74
+ return {
75
+ error: 'local-needs-update',
76
+ installedVersion: localInstalledVersion ?? 'undefined',
77
+ packageVersion: versionInProjectPackageJson,
78
+ };
79
+ }
80
+ return true;
81
+ }
82
+ function shouldSkipValidation() {
83
+ const args = process.argv.slice(2); // Remove 'node' and script path
84
+ return (args.includes('-h') ||
85
+ args.includes('--help') ||
86
+ args.includes('-V') ||
87
+ args.includes('--version') ||
88
+ args.includes('-v') ||
89
+ args.includes('--force'));
90
+ }
91
+ export function validateNextjsCmsApp() {
92
+ // Skip validation for help and version commands
93
+ if (shouldSkipValidation()) {
94
+ return;
95
+ }
96
+ const result = checkNextjsCmsInstallation();
97
+ if (typeof result === 'object' && 'error' in result) {
98
+ switch (result.error) {
99
+ case 'not-nextjs-cms-app':
100
+ console.error(chalk.red('❌ Error: This command must be run in a nextjs-cms application directory.'));
101
+ console.error(chalk.gray('Make sure you have:'));
102
+ console.error(chalk.gray(' - cms.config.ts file'));
103
+ console.error(chalk.gray(' - nextjs-cms as a dependency in package.json'));
104
+ console.error(chalk.gray(' - Did you forget to run `pnpm install`?'));
105
+ console.error('');
106
+ console.error(chalk.gray('To create a new nextjs-cms application, run:'));
107
+ console.error(chalk.gray(' - pnpm create nextjs-cms@latest'));
108
+ break;
109
+ case 'local-not-found':
110
+ console.error(chalk.red('❌ Error: nextjs-cms is not a dependency in package.json'));
111
+ console.error(chalk.gray('Make sure you have:'));
112
+ console.error(chalk.gray(' - nextjs-cms as a dependency in package.json'));
113
+ console.error(chalk.gray(' - Did you forget to run `pnpm install`?'));
114
+ break;
115
+ case 'local-needs-update':
116
+ console.error(chalk.red('❌ Error: the version of installed nextjs-cms in your cms is different from the version in package.json'));
117
+ console.error(chalk.gray(' - Installed version: ' + result.installedVersion));
118
+ console.error(chalk.gray(' - Package version: ' + result.packageVersion));
119
+ console.error(chalk.green(' - Please run `pnpm install and try again'));
120
+ break;
121
+ }
122
+ process.exit(1);
123
+ }
124
+ }
125
+ export const packageVersion = packageJson.version;
@@ -0,0 +1,6 @@
1
+ export declare const displayIntro: ({ command, dev, title }: {
2
+ command: string;
3
+ dev: boolean;
4
+ title: string;
5
+ }) => void;
6
+ //# sourceMappingURL=display-intro.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display-intro.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/display-intro.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,YAAY,GAAI,yBAAyB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,SASrG,CAAA"}
@@ -0,0 +1,9 @@
1
+ import { getTitle } from './render-title.js';
2
+ import chalk from 'chalk';
3
+ import * as p from '@clack/prompts';
4
+ export const displayIntro = ({ command, dev, title }) => {
5
+ console.log();
6
+ console.log(chalk.white.bold(`${getTitle()} > ${chalk.cyan.italic(command)} ${dev ? chalk.gray('(development)') : chalk.gray('(production)')}`));
7
+ console.log();
8
+ p.intro(chalk.inverse(` ${title} `));
9
+ };
@@ -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/cli/utils/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
+ };
@@ -0,0 +1,4 @@
1
+ /** Detect preferred package manager */
2
+ export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';
3
+ export declare function detectPackageManager(): 'pnpm' | 'npm' | 'yarn' | 'bun';
4
+ //# sourceMappingURL=get-package-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-package-manager.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/get-package-manager.ts"],"names":[],"mappings":"AAAA,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"}
@@ -0,0 +1,22 @@
1
+ export function detectPackageManager() {
2
+ // This environment variable is set by npm and yarn but pnpm seems less consistent
3
+ const userAgent = process.env.npm_config_user_agent;
4
+ if (userAgent) {
5
+ if (userAgent.startsWith('yarn')) {
6
+ return 'yarn';
7
+ }
8
+ else if (userAgent.startsWith('pnpm')) {
9
+ return 'pnpm';
10
+ }
11
+ else if (userAgent.startsWith('bun')) {
12
+ return 'bun';
13
+ }
14
+ else {
15
+ return 'npm';
16
+ }
17
+ }
18
+ else {
19
+ // If no user agent is set, assume npm
20
+ return 'npm';
21
+ }
22
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Reloads environment variables from .env files
3
+ * This is useful after programmatically writing to .env files
4
+ */
5
+ export declare function reloadEnvironmentVariables(envFile?: string): boolean;
6
+ /**
7
+ * Updates specific environment variables in process.env
8
+ * This provides immediate availability without requiring a full reload
9
+ */
10
+ export declare function updateEnvironmentVariables(variables: Record<string, string>): void;
11
+ /**
12
+ * Reloads environment variables and updates specific ones in process.env
13
+ * This combines both approaches for maximum compatibility
14
+ */
15
+ export declare function reloadAndUpdateEnvironmentVariables(variables?: Record<string, string>, envFile?: string): boolean;
16
+ //# sourceMappingURL=reload-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reload-env.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/reload-env.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAepE;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAIlF;AAED;;;GAGG;AACH,wBAAgB,mCAAmC,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAQjH"}