@actuate-media/cli 0.4.0 → 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 +34 -0
- package/dist/__tests__/deployment-diagnostics.test.js +40 -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 +55 -38
- 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 +2 -0
- package/dist/deployment/diagnostics.d.ts.map +1 -1
- package/dist/deployment/diagnostics.js +50 -1
- 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 +100 -50
- 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 +110 -86
- 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 +124 -61
- 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,100 +29,127 @@ 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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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'
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
export function missingModels(schemaModels: Set<string>): string[] {
|
|
51
|
-
return REQUIRED_CMS_MODELS.filter((model) => !schemaModels.has(model))
|
|
52
|
+
return REQUIRED_CMS_MODELS.filter((model) => !schemaModels.has(model))
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
export function missingEnvVars(env: Record<string, string | undefined>): string[] {
|
|
55
|
-
return REQUIRED_ENV_VARS.filter((name) => !env[name])
|
|
56
|
+
return REQUIRED_ENV_VARS.filter((name) => !env[name])
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
export function detectPackageManager(lockfiles: Set<string>): string {
|
|
59
|
-
if (lockfiles.has('pnpm-lock.yaml')) return 'pnpm'
|
|
60
|
-
if (lockfiles.has('yarn.lock')) return 'yarn'
|
|
61
|
-
if (lockfiles.has('package-lock.json')) return 'npm'
|
|
62
|
-
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'
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
export function createDiagnosticReport(input: DiagnosticInput): DiagnosticReport {
|
|
66
|
-
const checks: DiagnosticCheck[] = []
|
|
67
|
-
const models = missingModels(input.schemaModels)
|
|
68
|
-
const envVars =
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
|
72
80
|
|
|
73
81
|
checks.push({
|
|
74
82
|
id: 'schema-models',
|
|
75
83
|
label: 'Prisma schema models',
|
|
76
84
|
status: models.length === 0 ? 'pass' : 'fail',
|
|
77
|
-
message:
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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.`,
|
|
83
93
|
docs: 'https://actuatecms.dev/docs/database-setup',
|
|
84
|
-
})
|
|
94
|
+
})
|
|
85
95
|
|
|
86
96
|
checks.push({
|
|
87
97
|
id: 'schema-fields',
|
|
88
98
|
label: 'Prisma schema fields',
|
|
89
99
|
status: fieldProblems.length === 0 ? 'pass' : 'fail',
|
|
90
|
-
message:
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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.',
|
|
96
108
|
docs: 'https://actuatecms.dev/docs/database-setup',
|
|
97
|
-
})
|
|
109
|
+
})
|
|
98
110
|
|
|
99
111
|
checks.push({
|
|
100
112
|
id: 'environment',
|
|
101
113
|
label: 'Required environment variables',
|
|
102
114
|
status: envVars.length === 0 ? 'pass' : 'fail',
|
|
103
|
-
message:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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(', ')}.`,
|
|
109
123
|
docs: 'https://actuatecms.dev/docs/environment-variables',
|
|
110
|
-
})
|
|
124
|
+
})
|
|
111
125
|
|
|
112
126
|
checks.push({
|
|
113
127
|
id: 'package-manager',
|
|
114
128
|
label: 'Package manager',
|
|
115
129
|
status: 'pass',
|
|
116
130
|
message: `Detected ${input.packageManager}. Use the same package manager for install, build, and deploy checks.`,
|
|
117
|
-
})
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
checks.push({
|
|
134
|
+
id: 'design-first-page-builder',
|
|
135
|
+
label: 'Design-first page builder fit',
|
|
136
|
+
status: pageBuilderRisk ? 'warn' : 'pass',
|
|
137
|
+
message: pageBuilderRisk
|
|
138
|
+
? 'A pages collection appears to model a designed marketing page as flat hero/body/CTA fields. For marketing, service, location, landing, and homepage routes, prefer a page-builder template with blocks, saved sections, forms, media, and seeded layout content unless field-mapped mode was explicitly approved.'
|
|
139
|
+
: 'No obvious flat marketing-page model detected in the Actuate config.',
|
|
140
|
+
fix: pageBuilderRisk
|
|
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.'
|
|
142
|
+
: undefined,
|
|
143
|
+
docs: pageBuilderRisk ? 'https://actuatecms.dev/docs/design-first-page-builder' : undefined,
|
|
144
|
+
})
|
|
118
145
|
|
|
119
146
|
const status: DiagnosticStatus = checks.some((check) => check.status === 'fail')
|
|
120
147
|
? 'fail'
|
|
121
148
|
: checks.some((check) => check.status === 'warn')
|
|
122
|
-
|
|
123
|
-
|
|
149
|
+
? 'warn'
|
|
150
|
+
: 'pass'
|
|
124
151
|
|
|
125
|
-
return { status, checks }
|
|
152
|
+
return { status, checks }
|
|
126
153
|
}
|
|
127
154
|
|
|
128
155
|
export function buildDeploymentManifest() {
|
|
@@ -162,7 +189,7 @@ export function buildDeploymentManifest() {
|
|
|
162
189
|
environmentVariables: 'https://actuatecms.dev/docs/environment-variables',
|
|
163
190
|
aiRunbook: 'https://actuatecms.dev/docs/ai-runbook',
|
|
164
191
|
},
|
|
165
|
-
}
|
|
192
|
+
}
|
|
166
193
|
}
|
|
167
194
|
|
|
168
195
|
export function missingCriticalFields(schemaContent: string): string[] {
|
|
@@ -172,18 +199,54 @@ export function missingCriticalFields(schemaContent: string): string[] {
|
|
|
172
199
|
SavedSection: ['tree', 'usageCount', 'category'],
|
|
173
200
|
PasswordResetToken: ['tokenHash', 'expiresAt', 'usedAt'],
|
|
174
201
|
MediaUsage: ['mediaId', 'documentId', 'fieldPath'],
|
|
175
|
-
}
|
|
176
|
-
const missing: string[] = []
|
|
202
|
+
}
|
|
203
|
+
const missing: string[] = []
|
|
177
204
|
|
|
178
205
|
for (const [model, fields] of Object.entries(requiredFields)) {
|
|
179
|
-
const body =
|
|
180
|
-
|
|
206
|
+
const body =
|
|
207
|
+
schemaContent.match(new RegExp(`model\\s+${model}\\s+\\{([\\s\\S]*?)\\n\\}`))?.[1] ?? ''
|
|
208
|
+
if (!body) continue
|
|
181
209
|
for (const field of fields) {
|
|
182
210
|
if (!new RegExp(`^\\s*${field}\\s+`, 'm').test(body)) {
|
|
183
|
-
missing.push(`${model}.${field}`)
|
|
211
|
+
missing.push(`${model}.${field}`)
|
|
184
212
|
}
|
|
185
213
|
}
|
|
186
214
|
}
|
|
187
215
|
|
|
188
|
-
return missing
|
|
216
|
+
return missing
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function detectsFlatMarketingPageModel(configContent: string): boolean {
|
|
220
|
+
const normalized = configContent.toLowerCase()
|
|
221
|
+
const hasPagesCollection =
|
|
222
|
+
/\bpages\b/.test(normalized) || /slug\s*:\s*['"]pages['"]/.test(normalized)
|
|
223
|
+
if (!hasPagesCollection) return false
|
|
224
|
+
|
|
225
|
+
const hasPageBuilderSignals = [
|
|
226
|
+
'pagebuilder',
|
|
227
|
+
'page-builder',
|
|
228
|
+
"type: 'blocks'",
|
|
229
|
+
'type: "blocks"',
|
|
230
|
+
'layout:',
|
|
231
|
+
'savedsections',
|
|
232
|
+
'pagetemplate',
|
|
233
|
+
].some((signal) => normalized.includes(signal.toLowerCase()))
|
|
234
|
+
|
|
235
|
+
if (hasPageBuilderSignals) return false
|
|
236
|
+
|
|
237
|
+
const flatMarketingSignals = [
|
|
238
|
+
'heroheadline',
|
|
239
|
+
'herosubheadline',
|
|
240
|
+
'herotitle',
|
|
241
|
+
'heroimage',
|
|
242
|
+
'bodycontent',
|
|
243
|
+
'ctabuttontext',
|
|
244
|
+
'ctabuttonurl',
|
|
245
|
+
'servicecards',
|
|
246
|
+
'testimonial',
|
|
247
|
+
'reviews',
|
|
248
|
+
]
|
|
249
|
+
|
|
250
|
+
const signalCount = flatMarketingSignals.filter((signal) => normalized.includes(signal)).length
|
|
251
|
+
return signalCount >= 3
|
|
189
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
|
+
}
|