@actuate-media/cli 0.4.1 → 0.4.2
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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-test.log +21 -10
- package/CHANGELOG.md +28 -0
- package/dist/__tests__/deployment-diagnostics.test.js.map +1 -1
- package/dist/__tests__/init.test.js.map +1 -1
- package/dist/__tests__/schema-fragment.test.js +1 -1
- package/dist/__tests__/schema-fragment.test.js.map +1 -1
- package/dist/__tests__/seed.test.js.map +1 -1
- package/dist/commands/db-init.d.ts +2 -2
- package/dist/commands/db-init.d.ts.map +1 -1
- package/dist/commands/db-init.js +32 -32
- package/dist/commands/db-init.js.map +1 -1
- package/dist/commands/db-status.d.ts +1 -1
- package/dist/commands/db-status.d.ts.map +1 -1
- package/dist/commands/db-status.js +33 -33
- package/dist/commands/db-status.js.map +1 -1
- package/dist/commands/doctor.d.ts +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +48 -41
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/export.d.ts +1 -1
- package/dist/commands/export.d.ts.map +1 -1
- package/dist/commands/export.js +32 -32
- package/dist/commands/export.js.map +1 -1
- package/dist/commands/generate.d.ts +1 -1
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +8 -8
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/import.d.ts +1 -1
- package/dist/commands/import.d.ts.map +1 -1
- package/dist/commands/import.js +55 -58
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/migrate.d.ts +1 -1
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +18 -24
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/seed.d.ts +1 -1
- package/dist/commands/seed.d.ts.map +1 -1
- package/dist/commands/seed.js +156 -157
- package/dist/commands/seed.js.map +1 -1
- package/dist/commands/update-check.d.ts +1 -1
- package/dist/commands/update-check.d.ts.map +1 -1
- package/dist/commands/update-check.js +34 -27
- package/dist/commands/update-check.js.map +1 -1
- package/dist/commands/upgrade.d.ts +1 -1
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +41 -34
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/deployment/diagnostics.d.ts.map +1 -1
- package/dist/deployment/diagnostics.js +7 -2
- package/dist/deployment/diagnostics.js.map +1 -1
- package/dist/index.js +15 -15
- package/dist/index.js.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +5 -5
- package/dist/utils/logger.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/deployment-diagnostics.test.ts +68 -60
- package/src/__tests__/init.test.ts +17 -17
- package/src/__tests__/schema-fragment.test.ts +29 -25
- package/src/__tests__/seed.test.ts +25 -25
- package/src/commands/db-init.ts +59 -59
- package/src/commands/db-status.ts +70 -68
- package/src/commands/doctor.ts +102 -88
- package/src/commands/export.ts +65 -75
- package/src/commands/generate.ts +14 -16
- package/src/commands/import.ts +125 -140
- package/src/commands/init.ts +14 -14
- package/src/commands/migrate.ts +29 -35
- package/src/commands/seed.ts +294 -300
- package/src/commands/update-check.ts +77 -72
- package/src/commands/upgrade.ts +92 -85
- package/src/deployment/diagnostics.ts +86 -72
- package/src/index.ts +30 -30
- package/src/utils/logger.ts +10 -10
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
export type DiagnosticStatus = 'pass' | 'warn' | 'fail'
|
|
1
|
+
export type DiagnosticStatus = 'pass' | 'warn' | 'fail'
|
|
2
2
|
|
|
3
3
|
export interface DiagnosticCheck {
|
|
4
|
-
id: string
|
|
5
|
-
label: string
|
|
6
|
-
status: DiagnosticStatus
|
|
7
|
-
message: string
|
|
8
|
-
fix?: string
|
|
9
|
-
docs?: string
|
|
4
|
+
id: string
|
|
5
|
+
label: string
|
|
6
|
+
status: DiagnosticStatus
|
|
7
|
+
message: string
|
|
8
|
+
fix?: string
|
|
9
|
+
docs?: string
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export interface DiagnosticReport {
|
|
13
|
-
status: DiagnosticStatus
|
|
14
|
-
checks: DiagnosticCheck[]
|
|
13
|
+
status: DiagnosticStatus
|
|
14
|
+
checks: DiagnosticCheck[]
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export const REQUIRED_CMS_MODELS = [
|
|
@@ -29,94 +29,106 @@ export const REQUIRED_CMS_MODELS = [
|
|
|
29
29
|
'ScriptTag',
|
|
30
30
|
'PageTemplate',
|
|
31
31
|
'SavedSection',
|
|
32
|
-
] as const
|
|
32
|
+
] as const
|
|
33
33
|
|
|
34
34
|
export const REQUIRED_ENV_VARS = [
|
|
35
35
|
'DATABASE_URL',
|
|
36
36
|
'CMS_SECRET',
|
|
37
37
|
'CMS_ENCRYPTION_KEY',
|
|
38
38
|
'NEXT_PUBLIC_SITE_URL',
|
|
39
|
-
] as const
|
|
39
|
+
] as const
|
|
40
40
|
|
|
41
41
|
export interface DiagnosticInput {
|
|
42
|
-
schemaModels: Set<string
|
|
43
|
-
schemaContent?: string
|
|
44
|
-
configContent?: string
|
|
45
|
-
env: Record<string, string | undefined
|
|
46
|
-
packageManager: string
|
|
47
|
-
schemaPath: string
|
|
48
|
-
mode?: 'doctor' | 'deploy'
|
|
42
|
+
schemaModels: Set<string>
|
|
43
|
+
schemaContent?: string
|
|
44
|
+
configContent?: string
|
|
45
|
+
env: Record<string, string | undefined>
|
|
46
|
+
packageManager: string
|
|
47
|
+
schemaPath: string
|
|
48
|
+
mode?: 'doctor' | 'deploy'
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
export function missingModels(schemaModels: Set<string>): string[] {
|
|
52
|
-
return REQUIRED_CMS_MODELS.filter((model) => !schemaModels.has(model))
|
|
52
|
+
return REQUIRED_CMS_MODELS.filter((model) => !schemaModels.has(model))
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
export function missingEnvVars(env: Record<string, string | undefined>): string[] {
|
|
56
|
-
return REQUIRED_ENV_VARS.filter((name) => !env[name])
|
|
56
|
+
return REQUIRED_ENV_VARS.filter((name) => !env[name])
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
export function detectPackageManager(lockfiles: Set<string>): string {
|
|
60
|
-
if (lockfiles.has('pnpm-lock.yaml')) return 'pnpm'
|
|
61
|
-
if (lockfiles.has('yarn.lock')) return 'yarn'
|
|
62
|
-
if (lockfiles.has('package-lock.json')) return 'npm'
|
|
63
|
-
return 'npm'
|
|
60
|
+
if (lockfiles.has('pnpm-lock.yaml')) return 'pnpm'
|
|
61
|
+
if (lockfiles.has('yarn.lock')) return 'yarn'
|
|
62
|
+
if (lockfiles.has('package-lock.json')) return 'npm'
|
|
63
|
+
return 'npm'
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
export function createDiagnosticReport(input: DiagnosticInput): DiagnosticReport {
|
|
67
|
-
const checks: DiagnosticCheck[] = []
|
|
68
|
-
const models = missingModels(input.schemaModels)
|
|
69
|
-
const envVars =
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
const checks: DiagnosticCheck[] = []
|
|
68
|
+
const models = missingModels(input.schemaModels)
|
|
69
|
+
const envVars =
|
|
70
|
+
input.mode === 'deploy'
|
|
71
|
+
? [
|
|
72
|
+
...missingEnvVars(input.env),
|
|
73
|
+
...(!input.env.DIRECT_DATABASE_URL ? ['DIRECT_DATABASE_URL'] : []),
|
|
74
|
+
]
|
|
75
|
+
: missingEnvVars(input.env)
|
|
76
|
+
const fieldProblems = input.schemaContent ? missingCriticalFields(input.schemaContent) : []
|
|
77
|
+
const pageBuilderRisk = input.configContent
|
|
78
|
+
? detectsFlatMarketingPageModel(input.configContent)
|
|
79
|
+
: false
|
|
74
80
|
|
|
75
81
|
checks.push({
|
|
76
82
|
id: 'schema-models',
|
|
77
83
|
label: 'Prisma schema models',
|
|
78
84
|
status: models.length === 0 ? 'pass' : 'fail',
|
|
79
|
-
message:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
message:
|
|
86
|
+
models.length === 0
|
|
87
|
+
? 'All deploy-critical Actuate models are present.'
|
|
88
|
+
: `Missing deploy-critical Actuate models: ${models.join(', ')}.`,
|
|
89
|
+
fix:
|
|
90
|
+
models.length === 0
|
|
91
|
+
? undefined
|
|
92
|
+
: `Run \`actuate db:init --schema ${input.schemaPath}\` for new schemas, or update the existing Actuate block from the database setup docs, then create and apply a Prisma migration.`,
|
|
85
93
|
docs: 'https://actuatecms.dev/docs/database-setup',
|
|
86
|
-
})
|
|
94
|
+
})
|
|
87
95
|
|
|
88
96
|
checks.push({
|
|
89
97
|
id: 'schema-fields',
|
|
90
98
|
label: 'Prisma schema fields',
|
|
91
99
|
status: fieldProblems.length === 0 ? 'pass' : 'fail',
|
|
92
|
-
message:
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
100
|
+
message:
|
|
101
|
+
fieldProblems.length === 0
|
|
102
|
+
? 'Deploy-critical model fields are present.'
|
|
103
|
+
: `Missing deploy-critical model fields: ${fieldProblems.join(', ')}.`,
|
|
104
|
+
fix:
|
|
105
|
+
fieldProblems.length === 0
|
|
106
|
+
? undefined
|
|
107
|
+
: 'Update the Actuate Prisma models from the database setup docs, then create and apply a Prisma migration.',
|
|
98
108
|
docs: 'https://actuatecms.dev/docs/database-setup',
|
|
99
|
-
})
|
|
109
|
+
})
|
|
100
110
|
|
|
101
111
|
checks.push({
|
|
102
112
|
id: 'environment',
|
|
103
113
|
label: 'Required environment variables',
|
|
104
114
|
status: envVars.length === 0 ? 'pass' : 'fail',
|
|
105
|
-
message:
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
115
|
+
message:
|
|
116
|
+
envVars.length === 0
|
|
117
|
+
? 'Required deployment environment variables are set.'
|
|
118
|
+
: `Missing required environment variables: ${envVars.join(', ')}.`,
|
|
119
|
+
fix:
|
|
120
|
+
envVars.length === 0
|
|
121
|
+
? undefined
|
|
122
|
+
: `Set missing environment variables before deploying: ${envVars.join(', ')}.`,
|
|
111
123
|
docs: 'https://actuatecms.dev/docs/environment-variables',
|
|
112
|
-
})
|
|
124
|
+
})
|
|
113
125
|
|
|
114
126
|
checks.push({
|
|
115
127
|
id: 'package-manager',
|
|
116
128
|
label: 'Package manager',
|
|
117
129
|
status: 'pass',
|
|
118
130
|
message: `Detected ${input.packageManager}. Use the same package manager for install, build, and deploy checks.`,
|
|
119
|
-
})
|
|
131
|
+
})
|
|
120
132
|
|
|
121
133
|
checks.push({
|
|
122
134
|
id: 'design-first-page-builder',
|
|
@@ -129,15 +141,15 @@ export function createDiagnosticReport(input: DiagnosticInput): DiagnosticReport
|
|
|
129
141
|
? 'Create a design inventory and block coverage plan, then model section-based pages with page-builder content or document why field-mapped mode is intentional.'
|
|
130
142
|
: undefined,
|
|
131
143
|
docs: pageBuilderRisk ? 'https://actuatecms.dev/docs/design-first-page-builder' : undefined,
|
|
132
|
-
})
|
|
144
|
+
})
|
|
133
145
|
|
|
134
146
|
const status: DiagnosticStatus = checks.some((check) => check.status === 'fail')
|
|
135
147
|
? 'fail'
|
|
136
148
|
: checks.some((check) => check.status === 'warn')
|
|
137
|
-
|
|
138
|
-
|
|
149
|
+
? 'warn'
|
|
150
|
+
: 'pass'
|
|
139
151
|
|
|
140
|
-
return { status, checks }
|
|
152
|
+
return { status, checks }
|
|
141
153
|
}
|
|
142
154
|
|
|
143
155
|
export function buildDeploymentManifest() {
|
|
@@ -177,7 +189,7 @@ export function buildDeploymentManifest() {
|
|
|
177
189
|
environmentVariables: 'https://actuatecms.dev/docs/environment-variables',
|
|
178
190
|
aiRunbook: 'https://actuatecms.dev/docs/ai-runbook',
|
|
179
191
|
},
|
|
180
|
-
}
|
|
192
|
+
}
|
|
181
193
|
}
|
|
182
194
|
|
|
183
195
|
export function missingCriticalFields(schemaContent: string): string[] {
|
|
@@ -187,26 +199,28 @@ export function missingCriticalFields(schemaContent: string): string[] {
|
|
|
187
199
|
SavedSection: ['tree', 'usageCount', 'category'],
|
|
188
200
|
PasswordResetToken: ['tokenHash', 'expiresAt', 'usedAt'],
|
|
189
201
|
MediaUsage: ['mediaId', 'documentId', 'fieldPath'],
|
|
190
|
-
}
|
|
191
|
-
const missing: string[] = []
|
|
202
|
+
}
|
|
203
|
+
const missing: string[] = []
|
|
192
204
|
|
|
193
205
|
for (const [model, fields] of Object.entries(requiredFields)) {
|
|
194
|
-
const body =
|
|
195
|
-
|
|
206
|
+
const body =
|
|
207
|
+
schemaContent.match(new RegExp(`model\\s+${model}\\s+\\{([\\s\\S]*?)\\n\\}`))?.[1] ?? ''
|
|
208
|
+
if (!body) continue
|
|
196
209
|
for (const field of fields) {
|
|
197
210
|
if (!new RegExp(`^\\s*${field}\\s+`, 'm').test(body)) {
|
|
198
|
-
missing.push(`${model}.${field}`)
|
|
211
|
+
missing.push(`${model}.${field}`)
|
|
199
212
|
}
|
|
200
213
|
}
|
|
201
214
|
}
|
|
202
215
|
|
|
203
|
-
return missing
|
|
216
|
+
return missing
|
|
204
217
|
}
|
|
205
218
|
|
|
206
219
|
export function detectsFlatMarketingPageModel(configContent: string): boolean {
|
|
207
|
-
const normalized = configContent.toLowerCase()
|
|
208
|
-
const hasPagesCollection =
|
|
209
|
-
|
|
220
|
+
const normalized = configContent.toLowerCase()
|
|
221
|
+
const hasPagesCollection =
|
|
222
|
+
/\bpages\b/.test(normalized) || /slug\s*:\s*['"]pages['"]/.test(normalized)
|
|
223
|
+
if (!hasPagesCollection) return false
|
|
210
224
|
|
|
211
225
|
const hasPageBuilderSignals = [
|
|
212
226
|
'pagebuilder',
|
|
@@ -216,9 +230,9 @@ export function detectsFlatMarketingPageModel(configContent: string): boolean {
|
|
|
216
230
|
'layout:',
|
|
217
231
|
'savedsections',
|
|
218
232
|
'pagetemplate',
|
|
219
|
-
].some((signal) => normalized.includes(signal.toLowerCase()))
|
|
233
|
+
].some((signal) => normalized.includes(signal.toLowerCase()))
|
|
220
234
|
|
|
221
|
-
if (hasPageBuilderSignals) return false
|
|
235
|
+
if (hasPageBuilderSignals) return false
|
|
222
236
|
|
|
223
237
|
const flatMarketingSignals = [
|
|
224
238
|
'heroheadline',
|
|
@@ -231,8 +245,8 @@ export function detectsFlatMarketingPageModel(configContent: string): boolean {
|
|
|
231
245
|
'servicecards',
|
|
232
246
|
'testimonial',
|
|
233
247
|
'reviews',
|
|
234
|
-
]
|
|
248
|
+
]
|
|
235
249
|
|
|
236
|
-
const signalCount = flatMarketingSignals.filter((signal) => normalized.includes(signal)).length
|
|
237
|
-
return signalCount >= 3
|
|
250
|
+
const signalCount = flatMarketingSignals.filter((signal) => normalized.includes(signal)).length
|
|
251
|
+
return signalCount >= 3
|
|
238
252
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Command } from
|
|
3
|
-
import { registerMigrateCommand } from
|
|
4
|
-
import { registerGenerateCommand } from
|
|
5
|
-
import { registerSeedCommand } from
|
|
6
|
-
import { registerImportCommand } from
|
|
7
|
-
import { registerExportCommand } from
|
|
8
|
-
import { registerUpgradeCommand } from
|
|
9
|
-
import { registerUpdateCheckCommand } from
|
|
10
|
-
import { registerDbInitCommand } from
|
|
11
|
-
import { registerDbStatusCommand } from
|
|
12
|
-
import { registerInitCommand } from
|
|
2
|
+
import { Command } from 'commander'
|
|
3
|
+
import { registerMigrateCommand } from './commands/migrate.js'
|
|
4
|
+
import { registerGenerateCommand } from './commands/generate.js'
|
|
5
|
+
import { registerSeedCommand } from './commands/seed.js'
|
|
6
|
+
import { registerImportCommand } from './commands/import.js'
|
|
7
|
+
import { registerExportCommand } from './commands/export.js'
|
|
8
|
+
import { registerUpgradeCommand } from './commands/upgrade.js'
|
|
9
|
+
import { registerUpdateCheckCommand } from './commands/update-check.js'
|
|
10
|
+
import { registerDbInitCommand } from './commands/db-init.js'
|
|
11
|
+
import { registerDbStatusCommand } from './commands/db-status.js'
|
|
12
|
+
import { registerInitCommand } from './commands/init.js'
|
|
13
13
|
import {
|
|
14
14
|
registerDeployCheckCommand,
|
|
15
15
|
registerDoctorCommand,
|
|
16
16
|
registerVerifyCommand,
|
|
17
|
-
} from
|
|
17
|
+
} from './commands/doctor.js'
|
|
18
18
|
|
|
19
|
-
const program = new Command()
|
|
19
|
+
const program = new Command()
|
|
20
20
|
|
|
21
21
|
program
|
|
22
|
-
.name(
|
|
23
|
-
.description(
|
|
24
|
-
.version(
|
|
22
|
+
.name('actuate')
|
|
23
|
+
.description('Actuate CMS — CLI toolkit for migrations, codegen, and more')
|
|
24
|
+
.version('0.1.0')
|
|
25
25
|
|
|
26
|
-
registerMigrateCommand(program)
|
|
27
|
-
registerGenerateCommand(program)
|
|
28
|
-
registerSeedCommand(program)
|
|
29
|
-
registerImportCommand(program)
|
|
30
|
-
registerExportCommand(program)
|
|
31
|
-
registerUpgradeCommand(program)
|
|
32
|
-
registerUpdateCheckCommand(program)
|
|
33
|
-
registerDbInitCommand(program)
|
|
34
|
-
registerDbStatusCommand(program)
|
|
35
|
-
registerInitCommand(program)
|
|
36
|
-
registerDoctorCommand(program)
|
|
37
|
-
registerDeployCheckCommand(program)
|
|
38
|
-
registerVerifyCommand(program)
|
|
26
|
+
registerMigrateCommand(program)
|
|
27
|
+
registerGenerateCommand(program)
|
|
28
|
+
registerSeedCommand(program)
|
|
29
|
+
registerImportCommand(program)
|
|
30
|
+
registerExportCommand(program)
|
|
31
|
+
registerUpgradeCommand(program)
|
|
32
|
+
registerUpdateCheckCommand(program)
|
|
33
|
+
registerDbInitCommand(program)
|
|
34
|
+
registerDbStatusCommand(program)
|
|
35
|
+
registerInitCommand(program)
|
|
36
|
+
registerDoctorCommand(program)
|
|
37
|
+
registerDeployCheckCommand(program)
|
|
38
|
+
registerVerifyCommand(program)
|
|
39
39
|
|
|
40
|
-
program.parse()
|
|
40
|
+
program.parse()
|
package/src/utils/logger.ts
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import chalk from
|
|
1
|
+
import chalk from 'chalk'
|
|
2
2
|
|
|
3
3
|
export interface Logger {
|
|
4
|
-
info(message: string): void
|
|
5
|
-
success(message: string): void
|
|
6
|
-
warn(message: string): void
|
|
7
|
-
error(message: string): void
|
|
4
|
+
info(message: string): void
|
|
5
|
+
success(message: string): void
|
|
6
|
+
warn(message: string): void
|
|
7
|
+
error(message: string): void
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export const logger: Logger = {
|
|
11
11
|
info(message: string): void {
|
|
12
|
-
console.log(chalk.blue(
|
|
12
|
+
console.log(chalk.blue('ℹ'), message)
|
|
13
13
|
},
|
|
14
14
|
|
|
15
15
|
success(message: string): void {
|
|
16
|
-
console.log(chalk.green(
|
|
16
|
+
console.log(chalk.green('✔'), message)
|
|
17
17
|
},
|
|
18
18
|
|
|
19
19
|
warn(message: string): void {
|
|
20
|
-
console.warn(chalk.yellow(
|
|
20
|
+
console.warn(chalk.yellow('⚠'), message)
|
|
21
21
|
},
|
|
22
22
|
|
|
23
23
|
error(message: string): void {
|
|
24
|
-
console.error(chalk.red(
|
|
24
|
+
console.error(chalk.red('✖'), message)
|
|
25
25
|
},
|
|
26
|
-
}
|
|
26
|
+
}
|