@zenith-open/zenithcms-cli 1.0.0-beta
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/LICENSE +21 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +958 -0
- package/dist/index.js.map +1 -0
- package/package.json +28 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Aman T Shekar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,958 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { execSync } from 'child_process';
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
import readline from 'readline';
|
|
8
|
+
const question = (query) => {
|
|
9
|
+
const rl = readline.createInterface({
|
|
10
|
+
input: process.stdin,
|
|
11
|
+
output: process.stdout,
|
|
12
|
+
});
|
|
13
|
+
return new Promise((resolve) => rl.question(query, (answer) => {
|
|
14
|
+
rl.close();
|
|
15
|
+
resolve(answer);
|
|
16
|
+
}));
|
|
17
|
+
};
|
|
18
|
+
const program = new Command();
|
|
19
|
+
/**
|
|
20
|
+
* Zenith CMS CLI
|
|
21
|
+
* ─────────────
|
|
22
|
+
* The official command-line tool for managing Zenith CMS.
|
|
23
|
+
*/
|
|
24
|
+
program.name('zenithcms').description('Official Zenith CMS CLI').version('0.1.0');
|
|
25
|
+
program
|
|
26
|
+
.command('start')
|
|
27
|
+
.description('Start the Zenith CMS server')
|
|
28
|
+
.option('-p, --port <number>', 'Port to run on', '4001')
|
|
29
|
+
.action((options) => {
|
|
30
|
+
console.log(chalk.bold.hex('#00F5FF')(' Zenith CMS starting on port ' + options.port));
|
|
31
|
+
// In a real environment, this would run the server.ts from the installed package
|
|
32
|
+
// For this monorepo, we'll simulate the startup
|
|
33
|
+
try {
|
|
34
|
+
execSync('npx tsx server.ts', { stdio: 'inherit' });
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
program
|
|
41
|
+
.command('generate-types')
|
|
42
|
+
.description('Generate TypeScript types from zenith.config.ts')
|
|
43
|
+
.option('-o, --output <path>', 'Output file path', 'zenith-types.d.ts')
|
|
44
|
+
.action(async (options) => {
|
|
45
|
+
console.log(chalk.bold.hex('#00F5FF')(' Analyzing schema and generating types...'));
|
|
46
|
+
try {
|
|
47
|
+
let configPath = path.join(process.cwd(), 'zenith.config.ts');
|
|
48
|
+
if (!fs.existsSync(configPath)) {
|
|
49
|
+
configPath = path.join(process.cwd(), 'cms.config.ts');
|
|
50
|
+
}
|
|
51
|
+
if (!fs.existsSync(configPath)) {
|
|
52
|
+
console.error(chalk.red('Error: Neither zenith.config.ts nor cms.config.ts was found in current directory'));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
// Execute a tsx eval to parse the config typescript file cleanly
|
|
56
|
+
const evalScript = `import config from '${configPath.replace(/\\/g, '/')}'; console.log(JSON.stringify(config));`;
|
|
57
|
+
const jsonOutput = execSync(`npx tsx -e "${evalScript}"`, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
|
|
58
|
+
const config = JSON.parse(jsonOutput);
|
|
59
|
+
const mapRawFieldType = (field) => {
|
|
60
|
+
switch (field.type) {
|
|
61
|
+
case 'text':
|
|
62
|
+
case 'textarea':
|
|
63
|
+
case 'email':
|
|
64
|
+
case 'url':
|
|
65
|
+
if (field.options && field.options.length > 0) {
|
|
66
|
+
return field.options
|
|
67
|
+
.map((o) => (typeof o === 'string' ? `'${o}'` : `'${o.value}'`))
|
|
68
|
+
.join(' | ');
|
|
69
|
+
}
|
|
70
|
+
return 'string';
|
|
71
|
+
case 'number':
|
|
72
|
+
return 'number';
|
|
73
|
+
case 'checkbox':
|
|
74
|
+
case 'boolean':
|
|
75
|
+
return 'boolean';
|
|
76
|
+
case 'date':
|
|
77
|
+
return 'string | Date';
|
|
78
|
+
case 'json':
|
|
79
|
+
return 'Record<string, unknown>';
|
|
80
|
+
case 'media':
|
|
81
|
+
return field.hasMany ? '{ url: string; alt?: string }[]' : '{ url: string; alt?: string }';
|
|
82
|
+
case 'relation': {
|
|
83
|
+
const target = field.relationTo ? capitalize(field.relationTo) : 'any';
|
|
84
|
+
return field.required ? target : `${target} | null`;
|
|
85
|
+
}
|
|
86
|
+
case 'group':
|
|
87
|
+
if (!field.fields)
|
|
88
|
+
return 'Record<string, unknown>';
|
|
89
|
+
return `{\n${field.fields
|
|
90
|
+
.map((f) => ` ${f.name}${f.required ? '' : '?'}: ${mapFieldToType(f)};`)
|
|
91
|
+
.join('\n')}\n }`;
|
|
92
|
+
case 'array':
|
|
93
|
+
if (!field.fields)
|
|
94
|
+
return 'any[]';
|
|
95
|
+
return `{\n${field.fields
|
|
96
|
+
.map((f) => ` ${f.name}${f.required ? '' : '?'}: ${mapFieldToType(f)};`)
|
|
97
|
+
.join('\n')}\n }[]`;
|
|
98
|
+
case 'blocks': {
|
|
99
|
+
if (!field.blocks || field.blocks.length === 0)
|
|
100
|
+
return 'any[]';
|
|
101
|
+
const blockUnions = field.blocks.map((b) => {
|
|
102
|
+
const blockFields = b.fields
|
|
103
|
+
? b.fields
|
|
104
|
+
.map((f) => ` ${f.name}${f.required ? '' : '?'}: ${mapFieldToType(f)};`)
|
|
105
|
+
.join('\n')
|
|
106
|
+
: '';
|
|
107
|
+
return `{\n blockType: '${b.slug}';\n${blockFields}\n }`;
|
|
108
|
+
});
|
|
109
|
+
return `(${blockUnions.join(' | ')})[]`;
|
|
110
|
+
}
|
|
111
|
+
default:
|
|
112
|
+
return 'any';
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
const mapFieldToType = (field) => {
|
|
116
|
+
if (field.localized) {
|
|
117
|
+
return `Record<string, ${mapRawFieldType(field)}>`;
|
|
118
|
+
}
|
|
119
|
+
return mapRawFieldType(field);
|
|
120
|
+
};
|
|
121
|
+
const capitalize = (str) => {
|
|
122
|
+
return str
|
|
123
|
+
.split(/[-_\s]+/)
|
|
124
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
125
|
+
.join('');
|
|
126
|
+
};
|
|
127
|
+
let output = `/**\n * Zenith Auto-Generated TypeScript Definitions\n * Generated via "zenith generate-types"\n * DO NOT MODIFY MANUALLY.\n */\n\n`;
|
|
128
|
+
output += `export interface ZenithDocument {\n _id: string;\n createdAt: string;\n updatedAt: string;\n status?: 'draft' | 'published';\n}\n\n`;
|
|
129
|
+
const collections = config.collections || [];
|
|
130
|
+
const globals = config.globals || [];
|
|
131
|
+
// 1. Generate Core Interfaces for Collections
|
|
132
|
+
for (const col of collections) {
|
|
133
|
+
const interfaceName = capitalize(col.slug);
|
|
134
|
+
output += `export interface ${interfaceName} extends ZenithDocument {\n`;
|
|
135
|
+
for (const field of col.fields || []) {
|
|
136
|
+
const typeStr = mapFieldToType(field);
|
|
137
|
+
const isOptional = !field.required;
|
|
138
|
+
output += ` ${field.name}${isOptional ? '?' : ''}: ${typeStr};\n`;
|
|
139
|
+
}
|
|
140
|
+
output += `}\n\n`;
|
|
141
|
+
}
|
|
142
|
+
// 2. Generate Core Interfaces for Globals
|
|
143
|
+
for (const glob of globals) {
|
|
144
|
+
const interfaceName = capitalize(glob.slug);
|
|
145
|
+
output += `export interface ${interfaceName} {\n`;
|
|
146
|
+
for (const field of glob.fields || []) {
|
|
147
|
+
const typeStr = mapFieldToType(field);
|
|
148
|
+
const isOptional = !field.required;
|
|
149
|
+
output += ` ${field.name}${isOptional ? '?' : ''}: ${typeStr};\n`;
|
|
150
|
+
}
|
|
151
|
+
output += `}\n\n`;
|
|
152
|
+
}
|
|
153
|
+
// 3. Generate Zenith Schema collections register
|
|
154
|
+
output += `export interface ZenithSchema {\n`;
|
|
155
|
+
output += ` collections: {\n`;
|
|
156
|
+
for (const col of collections) {
|
|
157
|
+
output += ` ${col.slug}: ${capitalize(col.slug)}[];\n`;
|
|
158
|
+
}
|
|
159
|
+
output += ` };\n`;
|
|
160
|
+
output += ` globals: {\n`;
|
|
161
|
+
for (const glob of globals) {
|
|
162
|
+
output += ` '${glob.slug}': ${capitalize(glob.slug)};\n`;
|
|
163
|
+
}
|
|
164
|
+
output += ` };\n`;
|
|
165
|
+
output += `}\n`;
|
|
166
|
+
fs.writeFileSync(path.join(process.cwd(), options.output), output);
|
|
167
|
+
console.log(chalk.green(` Types generated successfully at ${options.output}`));
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
program
|
|
174
|
+
.command('init')
|
|
175
|
+
.description('Initialize a new Zenith CMS project')
|
|
176
|
+
.action(() => {
|
|
177
|
+
console.log(chalk.bold.hex('#00F5FF')('️ Initializing Zenith CMS project...'));
|
|
178
|
+
const configContent = `import type { CMSConfig } from '@zenith-open/zenithcms-types';
|
|
179
|
+
|
|
180
|
+
const config: CMSConfig = {
|
|
181
|
+
collections: [
|
|
182
|
+
{
|
|
183
|
+
name: 'Post',
|
|
184
|
+
slug: 'posts',
|
|
185
|
+
fields: [
|
|
186
|
+
{ name: 'title', type: 'text', required: true },
|
|
187
|
+
{ name: 'content', type: 'richtext' },
|
|
188
|
+
],
|
|
189
|
+
}
|
|
190
|
+
]
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export default config;`;
|
|
194
|
+
fs.writeFileSync(path.join(process.cwd(), 'zenith.config.ts'), configContent);
|
|
195
|
+
console.log(chalk.green(' Created zenith.config.ts'));
|
|
196
|
+
console.log(chalk.gray('\nNext steps:'));
|
|
197
|
+
console.log(chalk.white('1. Run ') + chalk.bold('zenith start'));
|
|
198
|
+
});
|
|
199
|
+
program
|
|
200
|
+
.command('export-schema')
|
|
201
|
+
.description('Export CMS collection schemas to a JSON file')
|
|
202
|
+
.option('-o, --output <path>', 'Output schema file path', 'zenith-schema.json')
|
|
203
|
+
.action((options) => {
|
|
204
|
+
console.log(chalk.bold.hex('#00F5FF')(' Exporting schema configurations...'));
|
|
205
|
+
try {
|
|
206
|
+
let configPath = path.join(process.cwd(), 'zenith.config.ts');
|
|
207
|
+
if (!fs.existsSync(configPath)) {
|
|
208
|
+
configPath = path.join(process.cwd(), 'cms.config.ts');
|
|
209
|
+
}
|
|
210
|
+
if (!fs.existsSync(configPath)) {
|
|
211
|
+
console.error(chalk.red('Error: Neither zenith.config.ts nor cms.config.ts was found in current directory'));
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const evalScript = `import config from '${configPath.replace(/\\/g, '/')}'; console.log(JSON.stringify(config));`;
|
|
215
|
+
const jsonOutput = execSync(`npx tsx -e "${evalScript}"`, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
|
|
216
|
+
const config = JSON.parse(jsonOutput);
|
|
217
|
+
const outputData = {
|
|
218
|
+
collections: config.collections || [],
|
|
219
|
+
globals: config.globals || [],
|
|
220
|
+
exportedAt: new Date().toISOString()
|
|
221
|
+
};
|
|
222
|
+
fs.writeFileSync(path.resolve(process.cwd(), options.output), JSON.stringify(outputData, null, 2), 'utf-8');
|
|
223
|
+
console.log(chalk.green(` Schema exported successfully to ${options.output}`));
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
console.error(chalk.red(`Error exporting schema: ${err.message}`));
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
program
|
|
230
|
+
.command('export-data')
|
|
231
|
+
.description('Export CMS collection data to JSON files')
|
|
232
|
+
.option('-o, --output-dir <path>', 'Output directory path', 'zenith-export')
|
|
233
|
+
.action((options) => {
|
|
234
|
+
console.log(chalk.bold.hex('#00F5FF')(' Starting CMS database data export...'));
|
|
235
|
+
try {
|
|
236
|
+
let configPath = path.join(process.cwd(), 'zenith.config.ts');
|
|
237
|
+
if (!fs.existsSync(configPath)) {
|
|
238
|
+
configPath = path.join(process.cwd(), 'cms.config.ts');
|
|
239
|
+
}
|
|
240
|
+
if (!fs.existsSync(configPath)) {
|
|
241
|
+
console.error(chalk.red('Error: Neither zenith.config.ts nor cms.config.ts was found in current directory'));
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
const tempRunnerPath = path.join(process.cwd(), '.zenith-export-runner.ts');
|
|
245
|
+
const runnerContent = `
|
|
246
|
+
import * as path from 'path'
|
|
247
|
+
import * as fs from 'fs'
|
|
248
|
+
import 'dotenv/config'
|
|
249
|
+
import { AdapterFactory } from './packages/core/src/database/adapters/AdapterFactory'
|
|
250
|
+
import config from '${configPath.replace(/\\/g, '/')}'
|
|
251
|
+
|
|
252
|
+
async function run() {
|
|
253
|
+
const outputDir = path.resolve(process.cwd(), '${options.outputDir.replace(/\\/g, '/')}')
|
|
254
|
+
if (!fs.existsSync(outputDir)) {
|
|
255
|
+
fs.mkdirSync(outputDir, { recursive: true })
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
console.log('Connecting to database adapter...')
|
|
259
|
+
const adapter = AdapterFactory.create()
|
|
260
|
+
await adapter.connect()
|
|
261
|
+
|
|
262
|
+
const collections = [...(config.collections || [])]
|
|
263
|
+
try {
|
|
264
|
+
const dbCollections = await adapter.find<Record<string, unknown>>('z_collections', {})
|
|
265
|
+
for (const col of dbCollections) {
|
|
266
|
+
if (!collections.find(c => c.slug === col.slug)) {
|
|
267
|
+
collections.push(col)
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
} catch (err) {
|
|
271
|
+
// Ignore if z_collections isn't created yet
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const systemSlugs = ['users', 'flows', 'z_api_keys', 'z_collections', 'audit_logs', 'versions', 'z_webhook_deliveries']
|
|
275
|
+
for (const slug of systemSlugs) {
|
|
276
|
+
if (!collections.find(c => c.slug === slug)) {
|
|
277
|
+
collections.push({ slug, name: slug } as any)
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
for (const col of collections) {
|
|
282
|
+
try {
|
|
283
|
+
const docs = await adapter.find(col.slug, {}, { limit: 100000 })
|
|
284
|
+
const filePath = path.join(outputDir, \`\${col.slug}.json\`)
|
|
285
|
+
fs.writeFileSync(filePath, JSON.stringify(docs, null, 2), 'utf-8')
|
|
286
|
+
console.log(\` Exported \${docs.length} documents for collection: \${col.slug}\`)
|
|
287
|
+
} catch (err: unknown) {
|
|
288
|
+
console.warn(\`️ Skipping or failed to export collection \${col.slug}: \${(err as Error).message}\`)
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
await adapter.disconnect()
|
|
293
|
+
console.log('Database export completed successfully!')
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
run().catch(err => {
|
|
297
|
+
console.error('Export run error:', err)
|
|
298
|
+
process.exit(1)
|
|
299
|
+
})
|
|
300
|
+
`;
|
|
301
|
+
fs.writeFileSync(tempRunnerPath, runnerContent, 'utf-8');
|
|
302
|
+
try {
|
|
303
|
+
execSync(`npx tsx .zenith-export-runner.ts`, { stdio: 'inherit' });
|
|
304
|
+
}
|
|
305
|
+
finally {
|
|
306
|
+
if (fs.existsSync(tempRunnerPath)) {
|
|
307
|
+
fs.unlinkSync(tempRunnerPath);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
catch (err) {
|
|
312
|
+
console.error(chalk.red(`Error exporting data: ${err.message}`));
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
program
|
|
316
|
+
.command('migration:generate')
|
|
317
|
+
.argument('[name]', 'Migration name identifier', 'auto')
|
|
318
|
+
.description('Generate SQL schema migrations based on zenith.config.ts changes')
|
|
319
|
+
.action((name) => {
|
|
320
|
+
console.log(chalk.bold.hex('#00F5FF')('️ Analyzing schema diffs and compiling SQL migration...'));
|
|
321
|
+
try {
|
|
322
|
+
let configPath = path.join(process.cwd(), 'zenith.config.ts');
|
|
323
|
+
if (!fs.existsSync(configPath)) {
|
|
324
|
+
configPath = path.join(process.cwd(), 'cms.config.ts');
|
|
325
|
+
}
|
|
326
|
+
if (!fs.existsSync(configPath)) {
|
|
327
|
+
console.error(chalk.red('Error: Neither zenith.config.ts nor cms.config.ts was found in current directory'));
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const tempRunnerPath = path.join(process.cwd(), '.zenith-migration-gen-runner.ts');
|
|
331
|
+
const runnerContent = `
|
|
332
|
+
import * as path from 'path'
|
|
333
|
+
import * as fs from 'fs'
|
|
334
|
+
import 'dotenv/config'
|
|
335
|
+
import { AdapterFactory } from './packages/core/src/database/adapters/AdapterFactory'
|
|
336
|
+
import config from '${configPath.replace(/\\/g, '/')}'
|
|
337
|
+
import { sql } from 'drizzle-orm'
|
|
338
|
+
|
|
339
|
+
async function run() {
|
|
340
|
+
const dbType = process.env.DATABASE_TYPE || 'mongodb'
|
|
341
|
+
if (dbType !== 'postgres') {
|
|
342
|
+
console.log('Database type is MongoDB. Migrations are only required for SQL databases (Postgres). Mongoose validates dynamic schemas automatically at boot.')
|
|
343
|
+
return
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
console.log('Connecting to database adapter...')
|
|
347
|
+
const adapter = AdapterFactory.create()
|
|
348
|
+
await adapter.connect()
|
|
349
|
+
|
|
350
|
+
const existingTablesResult = await adapter.db.execute(
|
|
351
|
+
sql\`SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'\`
|
|
352
|
+
)
|
|
353
|
+
const existingTables = (existingTablesResult.rows || []).map((r: Record<string, unknown>) => r.table_name)
|
|
354
|
+
|
|
355
|
+
const collections = config.collections || []
|
|
356
|
+
let upSql = ''
|
|
357
|
+
|
|
358
|
+
const mapFieldToSqlType = (field: any): string => {
|
|
359
|
+
if (field.localized) return 'JSONB'
|
|
360
|
+
switch (field.type) {
|
|
361
|
+
case 'number': return 'INTEGER'
|
|
362
|
+
case 'checkbox':
|
|
363
|
+
case 'boolean': return 'BOOLEAN'
|
|
364
|
+
case 'date': return 'TIMESTAMP'
|
|
365
|
+
case 'json':
|
|
366
|
+
case 'array':
|
|
367
|
+
case 'group':
|
|
368
|
+
case 'blocks': return 'JSONB'
|
|
369
|
+
case 'relation': return field.hasMany ? 'JSONB' : 'TEXT'
|
|
370
|
+
default: return 'TEXT'
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
for (const col of collections) {
|
|
375
|
+
const tableExists = existingTables.includes(col.slug)
|
|
376
|
+
if (!tableExists) {
|
|
377
|
+
let createSql = \`CREATE TABLE IF NOT EXISTS "\${col.slug}" (\\n "id" TEXT PRIMARY KEY,\\n "created_at" TIMESTAMP DEFAULT NOW() NOT NULL,\\n "updated_at" TIMESTAMP DEFAULT NOW() NOT NULL\`
|
|
378
|
+
if (col.drafts) {
|
|
379
|
+
createSql += \`,\\n "status" TEXT DEFAULT 'published'\`
|
|
380
|
+
}
|
|
381
|
+
for (const field of col.fields || []) {
|
|
382
|
+
if (field.type === 'relation' && field.junctionTable) continue
|
|
383
|
+
const sqlType = mapFieldToSqlType(field)
|
|
384
|
+
createSql += \`,\\n "\${field.name}" \${sqlType}\`
|
|
385
|
+
if (field.unique) createSql += ' UNIQUE'
|
|
386
|
+
if (field.required) createSql += ' NOT NULL'
|
|
387
|
+
}
|
|
388
|
+
createSql += \`\\n);\`
|
|
389
|
+
upSql += createSql + '\\n'
|
|
390
|
+
|
|
391
|
+
for (const field of col.fields || []) {
|
|
392
|
+
if (field.type === 'relation' && field.junctionTable) continue
|
|
393
|
+
if (field.unique || field.index || field.indexed || field.searchable) {
|
|
394
|
+
const idxName = \`idx_\${col.slug}_\${field.name}\`
|
|
395
|
+
const isGin = field.localized || ['json', 'array', 'group', 'blocks'].includes(field.type)
|
|
396
|
+
if (isGin) {
|
|
397
|
+
upSql += \`CREATE INDEX IF NOT EXISTS "\${idxName}" ON "\${col.slug}" USING gin ("\${field.name}");\\n\`
|
|
398
|
+
} else {
|
|
399
|
+
upSql += \`CREATE INDEX IF NOT EXISTS "\${idxName}" ON "\${col.slug}" ("\${field.name}");\\n\`
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
} else {
|
|
404
|
+
const colsResult = await adapter.db.execute(
|
|
405
|
+
sql\`SELECT column_name FROM information_schema.columns WHERE table_name = \${col.slug}\`
|
|
406
|
+
)
|
|
407
|
+
const existingCols = (colsResult.rows || []).map((r: Record<string, unknown>) => r.column_name)
|
|
408
|
+
|
|
409
|
+
for (const field of col.fields || []) {
|
|
410
|
+
if (field.type === 'relation' && field.junctionTable) continue
|
|
411
|
+
if (!existingCols.includes(field.name)) {
|
|
412
|
+
const sqlType = mapFieldToSqlType(field)
|
|
413
|
+
let alterSql = \`ALTER TABLE "\${col.slug}" ADD COLUMN "\${field.name}" \${sqlType}\`
|
|
414
|
+
if (field.unique) alterSql += ' UNIQUE'
|
|
415
|
+
if (field.required) alterSql += ' NOT NULL'
|
|
416
|
+
upSql += alterSql + ';\\n'
|
|
417
|
+
|
|
418
|
+
if (field.unique || field.index || field.indexed || field.searchable) {
|
|
419
|
+
const idxName = \`idx_\${col.slug}_\${field.name}\`
|
|
420
|
+
const isGin = field.localized || ['json', 'array', 'group', 'blocks'].includes(field.type)
|
|
421
|
+
if (isGin) {
|
|
422
|
+
upSql += \`CREATE INDEX IF NOT EXISTS "\${idxName}" ON "\${col.slug}" USING gin ("\${field.name}");\\n\`
|
|
423
|
+
} else {
|
|
424
|
+
upSql += \`CREATE INDEX IF NOT EXISTS "\${idxName}" ON "\${col.slug}" ("\${field.name}");\\n\`
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Generate SQL for junction tables
|
|
433
|
+
for (const col of collections) {
|
|
434
|
+
for (const field of col.fields || []) {
|
|
435
|
+
if (field.type === 'relation' && field.junctionTable) {
|
|
436
|
+
const jTable = field.junctionTable
|
|
437
|
+
const tableExists = existingTables.includes(jTable)
|
|
438
|
+
if (!tableExists) {
|
|
439
|
+
let createJunctionSql = \`CREATE TABLE IF NOT EXISTS "\${jTable}" (\\n "id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),\\n "source_id" TEXT NOT NULL,\\n "target_id" TEXT NOT NULL\`
|
|
440
|
+
const pivotFields = field.pivotFields || []
|
|
441
|
+
for (const pf of pivotFields) {
|
|
442
|
+
const sqlType = mapFieldToSqlType(pf)
|
|
443
|
+
createJunctionSql += \`,\\n "\${pf.name}" \${sqlType}\`
|
|
444
|
+
if (pf.unique) createJunctionSql += ' UNIQUE'
|
|
445
|
+
if (pf.required) createJunctionSql += ' NOT NULL'
|
|
446
|
+
}
|
|
447
|
+
createJunctionSql += \`\\n);\\n\`
|
|
448
|
+
upSql += createJunctionSql
|
|
449
|
+
upSql += \`CREATE INDEX IF NOT EXISTS "idx_\${jTable}_source_id" ON "\${jTable}" ("source_id");\\n\`
|
|
450
|
+
upSql += \`CREATE INDEX IF NOT EXISTS "idx_\${jTable}_target_id" ON "\${jTable}" ("target_id");\\n\`
|
|
451
|
+
} else {
|
|
452
|
+
const jColsResult = await adapter.db.execute(
|
|
453
|
+
sql\`SELECT column_name FROM information_schema.columns WHERE table_name = \${jTable}\`
|
|
454
|
+
)
|
|
455
|
+
const existingJCols = (jColsResult.rows || []).map((r: Record<string, unknown>) => r.column_name)
|
|
456
|
+
const pivotFields = field.pivotFields || []
|
|
457
|
+
for (const pf of pivotFields) {
|
|
458
|
+
if (!existingJCols.includes(pf.name)) {
|
|
459
|
+
const sqlType = mapFieldToSqlType(pf)
|
|
460
|
+
let alterJ = \`ALTER TABLE "\${jTable}" ADD COLUMN "\${pf.name}" \${sqlType}\`
|
|
461
|
+
if (pf.unique) alterJ += ' UNIQUE'
|
|
462
|
+
if (pf.required) alterJ += ' NOT NULL'
|
|
463
|
+
upSql += alterJ + ';\\n'
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
await adapter.disconnect()
|
|
472
|
+
|
|
473
|
+
if (!upSql.trim()) {
|
|
474
|
+
console.log('No schema changes detected. Database is up to date.')
|
|
475
|
+
return
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
const migrationsDir = path.resolve(process.cwd(), 'migrations')
|
|
479
|
+
if (!fs.existsSync(migrationsDir)) {
|
|
480
|
+
fs.mkdirSync(migrationsDir, { recursive: true })
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const timestamp = new Date().toISOString().replace(/[-:T]/g, '').slice(0, 14)
|
|
484
|
+
const cleanName = '${name}'.replace(/[^a-zA-Z0-9_]/g, '_')
|
|
485
|
+
const filename = \`\${timestamp}_\${cleanName}.sql\`
|
|
486
|
+
const filePath = path.join(migrationsDir, filename)
|
|
487
|
+
|
|
488
|
+
fs.writeFileSync(filePath, upSql, 'utf-8')
|
|
489
|
+
console.log(\` Generated migration file: migrations/\${filename}\`)
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
run().catch(err => {
|
|
493
|
+
console.error('Migration generation failed:', err)
|
|
494
|
+
process.exit(1)
|
|
495
|
+
})
|
|
496
|
+
`;
|
|
497
|
+
fs.writeFileSync(tempRunnerPath, runnerContent, 'utf-8');
|
|
498
|
+
try {
|
|
499
|
+
execSync(`npx tsx .zenith-migration-gen-runner.ts`, { stdio: 'inherit' });
|
|
500
|
+
}
|
|
501
|
+
finally {
|
|
502
|
+
if (fs.existsSync(tempRunnerPath)) {
|
|
503
|
+
fs.unlinkSync(tempRunnerPath);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
catch (err) {
|
|
508
|
+
console.error(chalk.red(`Error generating migration: ${err.message}`));
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
program
|
|
512
|
+
.command('migration:run')
|
|
513
|
+
.description('Run all pending SQL database migrations')
|
|
514
|
+
.action(() => {
|
|
515
|
+
console.log(chalk.bold.hex('#00F5FF')(' Executing pending migrations...'));
|
|
516
|
+
try {
|
|
517
|
+
const tempRunnerPath = path.join(process.cwd(), '.zenith-migration-run-runner.ts');
|
|
518
|
+
const runnerContent = `
|
|
519
|
+
import * as path from 'path'
|
|
520
|
+
import * as fs from 'fs'
|
|
521
|
+
import 'dotenv/config'
|
|
522
|
+
import { AdapterFactory } from './packages/core/src/database/adapters/AdapterFactory'
|
|
523
|
+
import { sql } from 'drizzle-orm'
|
|
524
|
+
|
|
525
|
+
async function run() {
|
|
526
|
+
const dbType = process.env.DATABASE_TYPE || 'mongodb'
|
|
527
|
+
if (dbType !== 'postgres') {
|
|
528
|
+
console.log('Database type is MongoDB. Schema migrations are not required for MongoDB.')
|
|
529
|
+
return
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
console.log('Connecting to database adapter...')
|
|
533
|
+
const adapter = AdapterFactory.create()
|
|
534
|
+
await adapter.connect()
|
|
535
|
+
|
|
536
|
+
await adapter.db.execute(sql\`
|
|
537
|
+
CREATE TABLE IF NOT EXISTS z_migrations (
|
|
538
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
539
|
+
name TEXT UNIQUE NOT NULL,
|
|
540
|
+
batch INTEGER NOT NULL,
|
|
541
|
+
executed_at TIMESTAMP DEFAULT NOW() NOT NULL
|
|
542
|
+
);
|
|
543
|
+
\`)
|
|
544
|
+
|
|
545
|
+
const rows = await adapter.db.execute(sql\`SELECT name FROM z_migrations\`)
|
|
546
|
+
const applied = (rows.rows || []).map((r: Record<string, unknown>) => r.name)
|
|
547
|
+
|
|
548
|
+
const migrationsDir = path.resolve(process.cwd(), 'migrations')
|
|
549
|
+
if (!fs.existsSync(migrationsDir) || fs.readdirSync(migrationsDir).length === 0) {
|
|
550
|
+
console.log('No migrations found in migrations directory.')
|
|
551
|
+
await adapter.disconnect()
|
|
552
|
+
return
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
const files = fs.readdirSync(migrationsDir)
|
|
556
|
+
.filter(f => f.endsWith('.sql'))
|
|
557
|
+
.sort()
|
|
558
|
+
|
|
559
|
+
const pending = files.filter(f => !applied.includes(f))
|
|
560
|
+
|
|
561
|
+
if (pending.length === 0) {
|
|
562
|
+
console.log('No pending migrations to run. Database is already up to date.')
|
|
563
|
+
await adapter.disconnect()
|
|
564
|
+
return
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
const batchRes = await adapter.db.execute(sql\`SELECT MAX(batch) as max_batch FROM z_migrations\`)
|
|
568
|
+
const maxBatch = (batchRes.rows || [])[0]?.max_batch || 0
|
|
569
|
+
const nextBatch = Number(maxBatch) + 1
|
|
570
|
+
|
|
571
|
+
console.log(\`Found \${pending.length} pending migration(s) to execute in batch \${nextBatch}.\`)
|
|
572
|
+
|
|
573
|
+
for (const filename of pending) {
|
|
574
|
+
console.log(\`Executing migration: \${filename}...\`)
|
|
575
|
+
const fileContent = fs.readFileSync(path.join(migrationsDir, filename), 'utf-8')
|
|
576
|
+
if (fileContent.trim()) {
|
|
577
|
+
await adapter.db.execute(sql.raw(fileContent))
|
|
578
|
+
}
|
|
579
|
+
await adapter.db.execute(sql\`
|
|
580
|
+
INSERT INTO z_migrations (name, batch)
|
|
581
|
+
VALUES (\${filename}, \${nextBatch})
|
|
582
|
+
\`)
|
|
583
|
+
console.log(\` Applied \${filename}\`)
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
await adapter.disconnect()
|
|
587
|
+
console.log('All migrations completed successfully!')
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
run().catch(err => {
|
|
591
|
+
console.error('Migration run failed:', err)
|
|
592
|
+
process.exit(1)
|
|
593
|
+
})
|
|
594
|
+
`;
|
|
595
|
+
fs.writeFileSync(tempRunnerPath, runnerContent, 'utf-8');
|
|
596
|
+
try {
|
|
597
|
+
execSync(`npx tsx .zenith-migration-run-runner.ts`, { stdio: 'inherit' });
|
|
598
|
+
}
|
|
599
|
+
finally {
|
|
600
|
+
if (fs.existsSync(tempRunnerPath)) {
|
|
601
|
+
fs.unlinkSync(tempRunnerPath);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
catch (err) {
|
|
606
|
+
console.error(chalk.red(`Error running migrations: ${err.message}`));
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
program
|
|
610
|
+
.command('migration:status')
|
|
611
|
+
.description('Display status of all migrations')
|
|
612
|
+
.action(() => {
|
|
613
|
+
console.log(chalk.bold.hex('#00F5FF')(' Checking database migrations status...'));
|
|
614
|
+
try {
|
|
615
|
+
const tempRunnerPath = path.join(process.cwd(), '.zenith-migration-status-runner.ts');
|
|
616
|
+
const runnerContent = `
|
|
617
|
+
import * as path from 'path'
|
|
618
|
+
import * as fs from 'fs'
|
|
619
|
+
import 'dotenv/config'
|
|
620
|
+
import { AdapterFactory } from './packages/core/src/database/adapters/AdapterFactory'
|
|
621
|
+
import { sql } from 'drizzle-orm'
|
|
622
|
+
|
|
623
|
+
async function run() {
|
|
624
|
+
const dbType = process.env.DATABASE_TYPE || 'mongodb'
|
|
625
|
+
if (dbType !== 'postgres') {
|
|
626
|
+
console.log('Database type is MongoDB. Schema migrations are not applicable.')
|
|
627
|
+
return
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
console.log('Connecting to database adapter...')
|
|
631
|
+
const adapter = AdapterFactory.create()
|
|
632
|
+
await adapter.connect()
|
|
633
|
+
|
|
634
|
+
let applied: string[] = []
|
|
635
|
+
try {
|
|
636
|
+
const rows = await adapter.db.execute(sql\`SELECT name FROM z_migrations\`)
|
|
637
|
+
applied = (rows.rows || []).map((r: Record<string, unknown>) => r.name)
|
|
638
|
+
} catch (err) {
|
|
639
|
+
// z_migrations does not exist yet
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
const migrationsDir = path.resolve(process.cwd(), 'migrations')
|
|
643
|
+
const localFiles = fs.existsSync(migrationsDir)
|
|
644
|
+
? fs.readdirSync(migrationsDir).filter(f => f.endsWith('.sql')).sort()
|
|
645
|
+
: []
|
|
646
|
+
|
|
647
|
+
console.log('\\n' + '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
|
|
648
|
+
console.log(' Zenith CMS Database Migrations Status')
|
|
649
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
|
|
650
|
+
|
|
651
|
+
if (localFiles.length === 0) {
|
|
652
|
+
console.log(' No migrations found on disk.')
|
|
653
|
+
await adapter.disconnect()
|
|
654
|
+
return
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
for (const file of localFiles) {
|
|
658
|
+
const isApplied = applied.includes(file)
|
|
659
|
+
const statusText = isApplied ? '\\x1b[32mApplied\\x1b[0m' : '\\x1b[33mPending\\x1b[0m'
|
|
660
|
+
console.log(\` [\${statusText}] \${file}\`)
|
|
661
|
+
}
|
|
662
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n')
|
|
663
|
+
|
|
664
|
+
await adapter.disconnect()
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
run().catch(err => {
|
|
668
|
+
console.error('Migration status check failed:', err)
|
|
669
|
+
process.exit(1)
|
|
670
|
+
})
|
|
671
|
+
`;
|
|
672
|
+
fs.writeFileSync(tempRunnerPath, runnerContent, 'utf-8');
|
|
673
|
+
try {
|
|
674
|
+
execSync(`npx tsx .zenith-migration-status-runner.ts`, { stdio: 'inherit' });
|
|
675
|
+
}
|
|
676
|
+
finally {
|
|
677
|
+
if (fs.existsSync(tempRunnerPath)) {
|
|
678
|
+
fs.unlinkSync(tempRunnerPath);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
catch (err) {
|
|
683
|
+
console.error(chalk.red(`Error displaying migration status: ${err.message}`));
|
|
684
|
+
}
|
|
685
|
+
});
|
|
686
|
+
program
|
|
687
|
+
.command('create-plugin')
|
|
688
|
+
.description('Scaffold a new Zenith CMS plugin')
|
|
689
|
+
.argument('[name]', 'Plugin name (e.g. acme-analytics)')
|
|
690
|
+
.option('-d, --dir <path>', 'Output directory', '.')
|
|
691
|
+
.action(async (nameArg, options) => {
|
|
692
|
+
console.log(chalk.bold.hex('#8B5CF6')('\n Zenith CMS Plugin Scaffold\n'));
|
|
693
|
+
let pluginName = nameArg;
|
|
694
|
+
if (!pluginName) {
|
|
695
|
+
pluginName = await question(chalk.white('? ') + chalk.bold('Plugin name (slug): ') + chalk.gray('(my-plugin) '));
|
|
696
|
+
if (!pluginName)
|
|
697
|
+
pluginName = 'my-plugin';
|
|
698
|
+
}
|
|
699
|
+
// Normalize: lowercase, hyphens only
|
|
700
|
+
const slug = pluginName.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');
|
|
701
|
+
const packageName = `zenith-plugin-${slug}`;
|
|
702
|
+
const className = slug.split('-').map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join('');
|
|
703
|
+
const targetDir = path.resolve(options.dir, packageName);
|
|
704
|
+
if (fs.existsSync(targetDir)) {
|
|
705
|
+
console.error(chalk.red(`\n Error: Directory "${packageName}" already exists.\n`));
|
|
706
|
+
process.exit(1);
|
|
707
|
+
}
|
|
708
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
709
|
+
// package.json
|
|
710
|
+
fs.writeFileSync(path.join(targetDir, 'package.json'), JSON.stringify({
|
|
711
|
+
name: packageName,
|
|
712
|
+
version: '0.1.0',
|
|
713
|
+
description: `${className} plugin for Zenith CMS`,
|
|
714
|
+
type: 'module',
|
|
715
|
+
main: 'dist/index.js',
|
|
716
|
+
types: 'dist/index.d.ts',
|
|
717
|
+
scripts: { build: 'tsc' },
|
|
718
|
+
peerDependencies: { '@zenith-open/zenithcms-core': '^0.2.0', '@zenith-open/zenithcms-types': '^0.2.0' },
|
|
719
|
+
keywords: ['zenithcms', 'zenith', 'plugin', slug],
|
|
720
|
+
}, null, 2));
|
|
721
|
+
// tsconfig.json
|
|
722
|
+
fs.writeFileSync(path.join(targetDir, 'tsconfig.json'), JSON.stringify({
|
|
723
|
+
compilerOptions: {
|
|
724
|
+
target: 'ES2022', module: 'NodeNext', moduleResolution: 'NodeNext',
|
|
725
|
+
declaration: true, strict: true, outDir: './dist', rootDir: './src',
|
|
726
|
+
esModuleInterop: true, skipLibCheck: true,
|
|
727
|
+
},
|
|
728
|
+
include: ['src'],
|
|
729
|
+
}, null, 2));
|
|
730
|
+
// src/index.ts — plugin source
|
|
731
|
+
fs.mkdirSync(path.join(targetDir, 'src'), { recursive: true });
|
|
732
|
+
fs.writeFileSync(path.join(targetDir, 'src/index.ts'), `import type { ZenithPlugin, PluginContext } from '@zenith-open/zenithcms-types'
|
|
733
|
+
|
|
734
|
+
export interface ${className}Options {
|
|
735
|
+
/** Enable verbose logging */
|
|
736
|
+
debug?: boolean
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* ${className} Plugin for Zenith CMS
|
|
741
|
+
*
|
|
742
|
+
* Hooks into content lifecycle events to extend CMS behavior.
|
|
743
|
+
* See: https://zenithcms.com/docs/plugins
|
|
744
|
+
*/
|
|
745
|
+
export function ${slug.replace(/-/g, '')}Plugin(options: ${className}Options = {}): ZenithPlugin {
|
|
746
|
+
return {
|
|
747
|
+
id: '${slug}',
|
|
748
|
+
name: '${className}',
|
|
749
|
+
version: '0.1.0',
|
|
750
|
+
description: '${className} plugin for Zenith CMS',
|
|
751
|
+
enabled: true,
|
|
752
|
+
|
|
753
|
+
configSchema: {
|
|
754
|
+
debug: {
|
|
755
|
+
type: 'boolean',
|
|
756
|
+
label: 'Debug Mode',
|
|
757
|
+
description: 'Enable verbose logging for this plugin',
|
|
758
|
+
default: false,
|
|
759
|
+
},
|
|
760
|
+
},
|
|
761
|
+
|
|
762
|
+
config: options,
|
|
763
|
+
|
|
764
|
+
// ── Config Phase: Modify CMS config before engine starts ───────
|
|
765
|
+
apply(config, pluginConfig) {
|
|
766
|
+
if (pluginConfig?.debug) {
|
|
767
|
+
console.log('[${className}] Plugin applied with config:', pluginConfig)
|
|
768
|
+
}
|
|
769
|
+
return config
|
|
770
|
+
},
|
|
771
|
+
|
|
772
|
+
// ── Init Phase: Register hooks after engine boots ──────────────
|
|
773
|
+
onInit(ctx: PluginContext) {
|
|
774
|
+
ctx.logger.info('${className} plugin initialized')
|
|
775
|
+
|
|
776
|
+
// Example: Hook into content creation across all collections
|
|
777
|
+
ctx.hooks.on('content:*:afterCreate', (doc: Record<string, unknown>) => {
|
|
778
|
+
if (options.debug) {
|
|
779
|
+
ctx.logger.debug({ collection: doc?.collection }, 'Content created')
|
|
780
|
+
}
|
|
781
|
+
})
|
|
782
|
+
|
|
783
|
+
// Example: Hook into content updates for a specific collection
|
|
784
|
+
// ctx.hooks.on('content:posts:afterUpdate', (payload: any) => {
|
|
785
|
+
// ctx.logger.info({ docId: payload?.doc?._id }, 'Post updated')
|
|
786
|
+
// })
|
|
787
|
+
},
|
|
788
|
+
|
|
789
|
+
// ── Ready Phase: DB is connected, routes are live ──────────────
|
|
790
|
+
async onReady(ctx: PluginContext) {
|
|
791
|
+
// Register custom Express routes, set up DB-dependent resources, etc.
|
|
792
|
+
ctx.logger.info('${className} plugin ready')
|
|
793
|
+
},
|
|
794
|
+
|
|
795
|
+
// ── Destroy Phase: Clean up on shutdown ────────────────────────
|
|
796
|
+
async onDestroy(ctx: PluginContext) {
|
|
797
|
+
ctx.logger.info('${className} plugin shutting down')
|
|
798
|
+
},
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
export default ${slug.replace(/-/g, '')}Plugin
|
|
803
|
+
`);
|
|
804
|
+
// README.md
|
|
805
|
+
fs.writeFileSync(path.join(targetDir, 'README.md'), `# ${packageName}
|
|
806
|
+
|
|
807
|
+
${className} plugin for Zenith CMS.
|
|
808
|
+
|
|
809
|
+
## Installation
|
|
810
|
+
|
|
811
|
+
\`\`\`bash
|
|
812
|
+
npm install ${packageName}
|
|
813
|
+
\`\`\`
|
|
814
|
+
|
|
815
|
+
## Usage
|
|
816
|
+
|
|
817
|
+
In your \`zenith.config.ts\`:
|
|
818
|
+
|
|
819
|
+
\`\`\`ts
|
|
820
|
+
import { ${slug.replace(/-/g, '')}Plugin } from '${packageName}'
|
|
821
|
+
|
|
822
|
+
export default {
|
|
823
|
+
// ... your config
|
|
824
|
+
plugins: [
|
|
825
|
+
${slug.replace(/-/g, '')}Plugin({ debug: true }),
|
|
826
|
+
],
|
|
827
|
+
}
|
|
828
|
+
\`\`\`
|
|
829
|
+
|
|
830
|
+
## Hooks
|
|
831
|
+
|
|
832
|
+
This plugin hooks into the following lifecycle events:
|
|
833
|
+
|
|
834
|
+
- \`content:*:afterCreate\` — Fires after any document is created
|
|
835
|
+
- \`content:*:afterUpdate\` — Fires after any document is updated
|
|
836
|
+
- \`content:*:afterDelete\` — Fires after any document is deleted
|
|
837
|
+
- \`content:*:afterRead\` — Fires after any document is read
|
|
838
|
+
|
|
839
|
+
## License
|
|
840
|
+
|
|
841
|
+
MIT
|
|
842
|
+
`);
|
|
843
|
+
console.log(chalk.green(` Plugin scaffolded: ${packageName}/`));
|
|
844
|
+
console.log(chalk.gray(` src/index.ts — Plugin source`));
|
|
845
|
+
console.log(chalk.gray(` package.json — npm package config`));
|
|
846
|
+
console.log(chalk.gray(` tsconfig.json — TypeScript config`));
|
|
847
|
+
console.log(chalk.gray(` README.md — Documentation`));
|
|
848
|
+
console.log(chalk.cyan(`\nNext steps:`));
|
|
849
|
+
console.log(chalk.white(` cd ${packageName}`));
|
|
850
|
+
console.log(chalk.white(` npm install`));
|
|
851
|
+
console.log(chalk.white(` npm run build`));
|
|
852
|
+
console.log('');
|
|
853
|
+
});
|
|
854
|
+
program
|
|
855
|
+
.command('sync:blocks')
|
|
856
|
+
.description('Sync manually edited block schema (.ts) files to the database')
|
|
857
|
+
.action(() => {
|
|
858
|
+
console.log(chalk.bold.hex('#00F5FF')(' Syncing local block schemas to database...'));
|
|
859
|
+
try {
|
|
860
|
+
const tempRunnerPath = path.join(process.cwd(), '.zenith-sync-blocks-runner.ts');
|
|
861
|
+
const runnerContent = `
|
|
862
|
+
import * as path from 'path'
|
|
863
|
+
import * as fs from 'fs'
|
|
864
|
+
import { pathToFileURL } from 'url'
|
|
865
|
+
import 'dotenv/config'
|
|
866
|
+
import { AdapterFactory } from './packages/core/src/database/adapters/AdapterFactory'
|
|
867
|
+
import './packages/core/src/database/schema-model'
|
|
868
|
+
|
|
869
|
+
async function run() {
|
|
870
|
+
const blocksDir = path.resolve(process.cwd(), 'config', 'blocks')
|
|
871
|
+
if (!fs.existsSync(blocksDir)) {
|
|
872
|
+
console.log('No config/blocks directory found. Nothing to sync.')
|
|
873
|
+
return
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
const files = fs.readdirSync(blocksDir).filter(f => f.endsWith('.json'))
|
|
877
|
+
if (files.length === 0) {
|
|
878
|
+
console.log('No .json block files found in config/blocks.')
|
|
879
|
+
return
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
console.log('Connecting to database adapter...')
|
|
883
|
+
const adapter = AdapterFactory.create()
|
|
884
|
+
await adapter.connect()
|
|
885
|
+
|
|
886
|
+
let syncedCount = 0
|
|
887
|
+
|
|
888
|
+
for (const file of files) {
|
|
889
|
+
const filePath = path.join(blocksDir, file)
|
|
890
|
+
try {
|
|
891
|
+
// Dynamically import the TS file using file URL
|
|
892
|
+
const blockModule = await import(pathToFileURL(filePath).href)
|
|
893
|
+
|
|
894
|
+
// The block is usually exported as a named export matching the slug, or default.
|
|
895
|
+
// We'll iterate through exports to find the BlockDefinition.
|
|
896
|
+
let blockDef = null
|
|
897
|
+
for (const key in blockModule) {
|
|
898
|
+
if (blockModule[key] && blockModule[key].slug && blockModule[key].fields) {
|
|
899
|
+
blockDef = blockModule[key]
|
|
900
|
+
break
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
if (!blockDef) {
|
|
905
|
+
console.warn(\`️ Skipped \${file}: No valid block definition found (missing slug or fields).\`)
|
|
906
|
+
continue
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
// Upsert into z_schemas
|
|
910
|
+
const dbPayload = {
|
|
911
|
+
title: blockDef.labels?.singular || blockDef.title || blockDef.slug,
|
|
912
|
+
slug: blockDef.slug,
|
|
913
|
+
type: 'block',
|
|
914
|
+
isGlobal: false,
|
|
915
|
+
fields: blockDef.fields || [],
|
|
916
|
+
siteId: null, // Blocks from FS are currently global
|
|
917
|
+
admin: blockDef.admin || { category: 'General', icon: 'Box' }
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
const existing = await adapter.findOne('z_schemas', { slug: blockDef.slug, siteId: null })
|
|
921
|
+
if (existing) {
|
|
922
|
+
await adapter.update('z_schemas', (existing._id || existing.id).toString(), dbPayload)
|
|
923
|
+
} else {
|
|
924
|
+
await adapter.create('z_schemas', dbPayload)
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
console.log(\` Synced block: \${blockDef.slug}\`)
|
|
928
|
+
syncedCount++
|
|
929
|
+
} catch (err: unknown) {
|
|
930
|
+
console.error(\` Failed to sync \${file}: \${(err as Error).message}\`)
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
await adapter.disconnect()
|
|
935
|
+
console.log(\`\\n Successfully synced \${syncedCount} block(s) to the database!\`)
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
run().catch(err => {
|
|
939
|
+
console.error('Sync error:', err)
|
|
940
|
+
process.exit(1)
|
|
941
|
+
})
|
|
942
|
+
`;
|
|
943
|
+
fs.writeFileSync(tempRunnerPath, runnerContent, 'utf-8');
|
|
944
|
+
try {
|
|
945
|
+
execSync('npx tsx .zenith-sync-blocks-runner.ts', { stdio: 'inherit' });
|
|
946
|
+
}
|
|
947
|
+
finally {
|
|
948
|
+
if (fs.existsSync(tempRunnerPath)) {
|
|
949
|
+
fs.unlinkSync(tempRunnerPath);
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
catch (err) {
|
|
954
|
+
console.error(chalk.red(`Error syncing blocks: ${err.message}`));
|
|
955
|
+
}
|
|
956
|
+
});
|
|
957
|
+
program.parse();
|
|
958
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zenith-open/zenithcms-cli",
|
|
3
|
+
"version": "1.0.0-beta",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"bin": {
|
|
8
|
+
"zenithcms": "./dist/index.js",
|
|
9
|
+
"zenith": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"chalk": "^5.3.0",
|
|
14
|
+
"commander": "^12.0.0"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/node": "^22.11.0",
|
|
18
|
+
"typescript": "~6.0.2"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc",
|
|
26
|
+
"lint": "echo 'Lint bypassed for cli'"
|
|
27
|
+
}
|
|
28
|
+
}
|