@stonecrop/nuxt 0.7.3 → 0.7.5
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/README.md +105 -1
- package/bin/init.mjs +104 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +84 -5
- package/package.json +25 -10
- package/src/cli/detect.ts +125 -0
- package/src/cli/index.ts +184 -0
- package/src/cli/installers/casl.ts +51 -0
- package/src/cli/installers/doctypes.ts +206 -0
- package/src/cli/installers/frontend.ts +68 -0
- package/src/cli/installers/grafserv.ts +308 -0
- package/src/cli/installers/graphql-client.ts +36 -0
- package/src/cli/installers/index.ts +10 -0
- package/src/cli/installers/rockfoil.ts +51 -0
- package/src/cli/prompts.ts +204 -0
- package/src/cli/utils/config.ts +260 -0
- package/src/cli/utils/index.ts +15 -0
- package/src/cli/utils/package.ts +128 -0
- package/src/cli/utils/plugin.ts +107 -0
- package/templates/Example.json +85 -0
- package/templates/example-table.json +60 -0
- package/templates/plugins.ts +81 -0
- package/templates/resolvers.ts +256 -0
- package/templates/schema.graphql +129 -0
package/src/cli/index.ts
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stonecrop Nuxt CLI - Main Installer
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates the installation of Stonecrop features into a Nuxt project.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import consola from 'consola'
|
|
8
|
+
import { detectFeatures, getInstalledSummary } from './detect'
|
|
9
|
+
import { promptFeatures, type SelectedFeatures } from './prompts'
|
|
10
|
+
import { installFrontend } from './installers/frontend'
|
|
11
|
+
import { installGrafserv } from './installers/grafserv'
|
|
12
|
+
import { installGraphqlClient } from './installers/graphql-client'
|
|
13
|
+
import { installCasl } from './installers/casl'
|
|
14
|
+
import { installRockfoil } from './installers/rockfoil'
|
|
15
|
+
import { installDoctypes } from './installers/doctypes'
|
|
16
|
+
import { getInstallCommand } from './utils/package'
|
|
17
|
+
|
|
18
|
+
export interface InstallerOptions {
|
|
19
|
+
/** Working directory (defaults to current directory) */
|
|
20
|
+
cwd: string
|
|
21
|
+
/** Pre-selected features from CLI flags */
|
|
22
|
+
features?: Partial<SelectedFeatures>
|
|
23
|
+
/** Skip confirmation prompts */
|
|
24
|
+
skipConfirm?: boolean
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Main installer entry point
|
|
29
|
+
*/
|
|
30
|
+
export async function runInstaller(options: InstallerOptions): Promise<void> {
|
|
31
|
+
const { cwd, features: preselectedFeatures = {}, skipConfirm = false } = options
|
|
32
|
+
|
|
33
|
+
consola.box('🌱 Stonecrop Nuxt Installer')
|
|
34
|
+
console.log()
|
|
35
|
+
|
|
36
|
+
// Detect existing setup
|
|
37
|
+
consola.start('Detecting existing setup...')
|
|
38
|
+
const detected = await detectFeatures(cwd)
|
|
39
|
+
|
|
40
|
+
if (!detected.isNuxtProject) {
|
|
41
|
+
consola.error('This does not appear to be a Nuxt project.')
|
|
42
|
+
consola.info('Please run this command in a directory with nuxt.config.ts and Nuxt in package.json.')
|
|
43
|
+
process.exit(1)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
consola.success('Nuxt project detected')
|
|
47
|
+
|
|
48
|
+
// Show what's already installed
|
|
49
|
+
const installed = getInstalledSummary(detected)
|
|
50
|
+
if (installed.length > 0) {
|
|
51
|
+
console.log()
|
|
52
|
+
consola.info('Already installed:')
|
|
53
|
+
for (const item of installed) {
|
|
54
|
+
consola.info(` ✓ ${item}`)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
console.log()
|
|
59
|
+
|
|
60
|
+
// Prompt for features to install
|
|
61
|
+
const selectedFeatures = await promptFeatures({
|
|
62
|
+
preselected: preselectedFeatures,
|
|
63
|
+
detected,
|
|
64
|
+
skipConfirm,
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
if (!selectedFeatures) {
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
console.log()
|
|
72
|
+
consola.start('Installing selected features...')
|
|
73
|
+
console.log()
|
|
74
|
+
|
|
75
|
+
// Track installation results
|
|
76
|
+
const results: { feature: string; success: boolean }[] = []
|
|
77
|
+
|
|
78
|
+
// Install frontend module
|
|
79
|
+
if (selectedFeatures.frontend) {
|
|
80
|
+
const success = await installFrontend({ cwd })
|
|
81
|
+
results.push({ feature: '@stonecrop/nuxt', success })
|
|
82
|
+
console.log()
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Install GraphQL client
|
|
86
|
+
if (selectedFeatures.graphqlClient) {
|
|
87
|
+
const success = await installGraphqlClient({ cwd })
|
|
88
|
+
results.push({ feature: '@stonecrop/graphql-client', success })
|
|
89
|
+
console.log()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Install GraphQL server
|
|
93
|
+
if (selectedFeatures.graphql) {
|
|
94
|
+
const success = await installGrafserv({ cwd })
|
|
95
|
+
results.push({ feature: '@stonecrop/nuxt-grafserv', success })
|
|
96
|
+
console.log()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Install CASL middleware
|
|
100
|
+
if (selectedFeatures.casl) {
|
|
101
|
+
const success = await installCasl({ cwd })
|
|
102
|
+
results.push({ feature: '@stonecrop/casl-middleware', success })
|
|
103
|
+
console.log()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Install Rockfoil middleware
|
|
107
|
+
if (selectedFeatures.rockfoil) {
|
|
108
|
+
const success = await installRockfoil({ cwd })
|
|
109
|
+
results.push({ feature: '@stonecrop/rockfoil', success })
|
|
110
|
+
console.log()
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Install sample doctypes
|
|
114
|
+
if (selectedFeatures.doctypes) {
|
|
115
|
+
const success = await installDoctypes({ cwd })
|
|
116
|
+
results.push({ feature: 'Sample doctypes', success })
|
|
117
|
+
console.log()
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Summary
|
|
121
|
+
const successCount = results.filter(r => r.success).length
|
|
122
|
+
const failCount = results.filter(r => !r.success).length
|
|
123
|
+
|
|
124
|
+
console.log()
|
|
125
|
+
if (failCount === 0) {
|
|
126
|
+
consola.success(`Successfully installed ${successCount} feature(s)`)
|
|
127
|
+
} else {
|
|
128
|
+
consola.warn(`Installed ${successCount} feature(s), ${failCount} failed`)
|
|
129
|
+
for (const result of results.filter(r => !r.success)) {
|
|
130
|
+
consola.error(` ✗ ${result.feature}`)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Next steps
|
|
135
|
+
console.log()
|
|
136
|
+
consola.box('Next Steps')
|
|
137
|
+
console.log()
|
|
138
|
+
|
|
139
|
+
const installCmd = getInstallCommand(cwd)
|
|
140
|
+
consola.info(`1. Install dependencies:`)
|
|
141
|
+
consola.info(` ${installCmd}`)
|
|
142
|
+
console.log()
|
|
143
|
+
|
|
144
|
+
let stepNum = 2
|
|
145
|
+
|
|
146
|
+
if (selectedFeatures.graphql) {
|
|
147
|
+
consola.info(`${stepNum}. Update your GraphQL schema and resolvers:`)
|
|
148
|
+
consola.info(` - server/schema.graphql`)
|
|
149
|
+
consola.info(` - server/resolvers.ts`)
|
|
150
|
+
console.log()
|
|
151
|
+
stepNum++
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (selectedFeatures.rockfoil) {
|
|
155
|
+
consola.info(`${stepNum}. Configure Rockfoil:`)
|
|
156
|
+
consola.info(` - Set DATABASE_URL environment variable`)
|
|
157
|
+
consola.info(` - Configure the Rockfoil plugin options in nuxt.config.ts`)
|
|
158
|
+
console.log()
|
|
159
|
+
stepNum++
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (selectedFeatures.doctypes) {
|
|
163
|
+
consola.info(`${stepNum}. Customize your doctypes:`)
|
|
164
|
+
consola.info(` - doctypes/Example.json`)
|
|
165
|
+
consola.info(` - doctypes/example-table.json`)
|
|
166
|
+
console.log()
|
|
167
|
+
stepNum++
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
consola.info(`Start development server:`)
|
|
171
|
+
consola.info(` pnpm dev`)
|
|
172
|
+
console.log()
|
|
173
|
+
|
|
174
|
+
if (selectedFeatures.graphql) {
|
|
175
|
+
consola.info(`Access GraphiQL:`)
|
|
176
|
+
consola.info(` http://localhost:3000/graphql/`)
|
|
177
|
+
consola.info(` (Make sure to restart your dev server if it's already running)`)
|
|
178
|
+
console.log()
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Re-export types for external use
|
|
183
|
+
export type { SelectedFeatures } from './prompts'
|
|
184
|
+
export type { DetectedFeatures } from './detect'
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CASL middleware installer
|
|
3
|
+
* Installs @stonecrop/casl-middleware and updates nuxt.config.ts
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import consola from 'consola'
|
|
7
|
+
|
|
8
|
+
import { updateNuxtConfig } from '../utils/config'
|
|
9
|
+
import { addDependencies } from '../utils/package'
|
|
10
|
+
import { addPluginToGrafservConfig } from '../utils/plugin'
|
|
11
|
+
|
|
12
|
+
export interface CaslInstallerOptions {
|
|
13
|
+
cwd: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Install the @stonecrop/casl-middleware authorization package
|
|
18
|
+
*/
|
|
19
|
+
export async function installCasl(options: CaslInstallerOptions): Promise<boolean> {
|
|
20
|
+
const { cwd } = options
|
|
21
|
+
|
|
22
|
+
consola.start('Installing @stonecrop/casl-middleware authorization...')
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
// Add dependencies - use latest published version
|
|
26
|
+
await addDependencies(cwd, {
|
|
27
|
+
'@stonecrop/casl-middleware': 'latest',
|
|
28
|
+
'@casl/ability': '^6.7.3',
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
// Add import to nuxt.config.ts
|
|
32
|
+
await updateNuxtConfig(cwd, {
|
|
33
|
+
import: "import { pglCaslPlugin } from '@stonecrop/casl-middleware'",
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
// Add plugin to grafserv preset configuration
|
|
37
|
+
const pluginAdded = await addPluginToGrafservConfig(cwd, 'pglCaslPlugin')
|
|
38
|
+
|
|
39
|
+
if (pluginAdded) {
|
|
40
|
+
consola.success('@stonecrop/casl-middleware installed and configured successfully')
|
|
41
|
+
} else {
|
|
42
|
+
consola.success('@stonecrop/casl-middleware installed successfully')
|
|
43
|
+
consola.info('Add pglCaslPlugin to your grafserv preset plugins array manually')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return true
|
|
47
|
+
} catch (error) {
|
|
48
|
+
consola.error('Failed to install @stonecrop/casl-middleware:', error)
|
|
49
|
+
return false
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sample doctypes installer
|
|
3
|
+
* Scaffolds example doctype JSON files
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { existsSync } from 'node:fs'
|
|
7
|
+
import { mkdir, writeFile, readFile } from 'node:fs/promises'
|
|
8
|
+
import { join, dirname } from 'pathe'
|
|
9
|
+
import { fileURLToPath } from 'node:url'
|
|
10
|
+
import consola from 'consola'
|
|
11
|
+
|
|
12
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
13
|
+
|
|
14
|
+
export interface DoctypesInstallerOptions {
|
|
15
|
+
cwd: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Install sample doctype files
|
|
20
|
+
*/
|
|
21
|
+
export async function installDoctypes(options: DoctypesInstallerOptions): Promise<boolean> {
|
|
22
|
+
const { cwd } = options
|
|
23
|
+
|
|
24
|
+
consola.start('Scaffolding sample doctypes...')
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const doctypesDir = join(cwd, 'doctypes')
|
|
28
|
+
|
|
29
|
+
// Create doctypes directory if it doesn't exist
|
|
30
|
+
if (!existsSync(doctypesDir)) {
|
|
31
|
+
await mkdir(doctypesDir, { recursive: true })
|
|
32
|
+
consola.info('Created doctypes/ directory')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Scaffold Example.json (form doctype)
|
|
36
|
+
const examplePath = join(doctypesDir, 'Example.json')
|
|
37
|
+
if (!existsSync(examplePath)) {
|
|
38
|
+
const exampleTemplate = await loadTemplate('Example.json')
|
|
39
|
+
await writeFile(examplePath, exampleTemplate, 'utf-8')
|
|
40
|
+
consola.info('Created doctypes/Example.json')
|
|
41
|
+
} else {
|
|
42
|
+
consola.info('doctypes/Example.json already exists, skipping')
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Scaffold example-table.json (table doctype)
|
|
46
|
+
const tableExamplePath = join(doctypesDir, 'example-table.json')
|
|
47
|
+
if (!existsSync(tableExamplePath)) {
|
|
48
|
+
const tableTemplate = await loadTemplate('example-table.json')
|
|
49
|
+
await writeFile(tableExamplePath, tableTemplate, 'utf-8')
|
|
50
|
+
consola.info('Created doctypes/example-table.json')
|
|
51
|
+
} else {
|
|
52
|
+
consola.info('doctypes/example-table.json already exists, skipping')
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
consola.success('Sample doctypes created successfully')
|
|
56
|
+
return true
|
|
57
|
+
} catch (error) {
|
|
58
|
+
consola.error('Failed to scaffold doctypes:', error)
|
|
59
|
+
return false
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Load a template file
|
|
65
|
+
*/
|
|
66
|
+
async function loadTemplate(filename: string): Promise<string> {
|
|
67
|
+
// Try to load from templates directory
|
|
68
|
+
const templatePath = join(__dirname, '..', '..', '..', 'templates', filename)
|
|
69
|
+
|
|
70
|
+
if (existsSync(templatePath)) {
|
|
71
|
+
return readFile(templatePath, 'utf-8')
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Fallback to inline templates
|
|
75
|
+
return getInlineTemplate(filename)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Get inline template content as fallback
|
|
80
|
+
*/
|
|
81
|
+
function getInlineTemplate(filename: string): string {
|
|
82
|
+
const templates: Record<string, string> = {
|
|
83
|
+
'Example.json': JSON.stringify(
|
|
84
|
+
{
|
|
85
|
+
name: 'Example',
|
|
86
|
+
slug: 'example/:id',
|
|
87
|
+
tableName: 'examples',
|
|
88
|
+
fields: [
|
|
89
|
+
{
|
|
90
|
+
fieldname: 'id',
|
|
91
|
+
fieldtype: 'Data',
|
|
92
|
+
label: 'ID',
|
|
93
|
+
readOnly: true,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
fieldname: 'title',
|
|
97
|
+
fieldtype: 'Data',
|
|
98
|
+
label: 'Title',
|
|
99
|
+
required: true,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
fieldname: 'description',
|
|
103
|
+
fieldtype: 'Text',
|
|
104
|
+
label: 'Description',
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
fieldname: 'status',
|
|
108
|
+
fieldtype: 'Select',
|
|
109
|
+
label: 'Status',
|
|
110
|
+
options: ['Draft', 'Active', 'Archived'],
|
|
111
|
+
default: 'Draft',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
fieldname: 'priority',
|
|
115
|
+
fieldtype: 'Select',
|
|
116
|
+
label: 'Priority',
|
|
117
|
+
options: ['Low', 'Medium', 'High'],
|
|
118
|
+
default: 'Medium',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
fieldname: 'createdAt',
|
|
122
|
+
fieldtype: 'Datetime',
|
|
123
|
+
label: 'Created At',
|
|
124
|
+
readOnly: true,
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
fieldname: 'updatedAt',
|
|
128
|
+
fieldtype: 'Datetime',
|
|
129
|
+
label: 'Updated At',
|
|
130
|
+
readOnly: true,
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
workflow: {
|
|
134
|
+
states: ['Draft', 'Active', 'Archived'],
|
|
135
|
+
actions: {
|
|
136
|
+
activate: {
|
|
137
|
+
label: 'Activate',
|
|
138
|
+
handler: 'activate_example',
|
|
139
|
+
allowedStates: ['Draft'],
|
|
140
|
+
confirm: true,
|
|
141
|
+
},
|
|
142
|
+
archive: {
|
|
143
|
+
label: 'Archive',
|
|
144
|
+
handler: 'archive_example',
|
|
145
|
+
allowedStates: ['Active'],
|
|
146
|
+
confirm: true,
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
null,
|
|
152
|
+
'\t'
|
|
153
|
+
),
|
|
154
|
+
'example-table.json': JSON.stringify(
|
|
155
|
+
{
|
|
156
|
+
name: 'Example',
|
|
157
|
+
slug: 'example',
|
|
158
|
+
tableName: 'examples',
|
|
159
|
+
schema: [
|
|
160
|
+
{
|
|
161
|
+
component: 'ATable',
|
|
162
|
+
columns: [
|
|
163
|
+
{
|
|
164
|
+
name: 'id',
|
|
165
|
+
label: 'ID',
|
|
166
|
+
fieldtype: 'Data',
|
|
167
|
+
width: '8ch',
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
name: 'title',
|
|
171
|
+
label: 'Title',
|
|
172
|
+
fieldtype: 'Data',
|
|
173
|
+
width: '20ch',
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
name: 'status',
|
|
177
|
+
label: 'Status',
|
|
178
|
+
fieldtype: 'Data',
|
|
179
|
+
width: '10ch',
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
name: 'priority',
|
|
183
|
+
label: 'Priority',
|
|
184
|
+
fieldtype: 'Data',
|
|
185
|
+
width: '10ch',
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
name: 'createdAt',
|
|
189
|
+
label: 'Created',
|
|
190
|
+
fieldtype: 'Datetime',
|
|
191
|
+
width: '18ch',
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
config: {
|
|
195
|
+
view: 'list',
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
},
|
|
200
|
+
null,
|
|
201
|
+
'\t'
|
|
202
|
+
),
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return templates[filename] || '{}'
|
|
206
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frontend module installer
|
|
3
|
+
* Installs @stonecrop/nuxt and configures nuxt.config.ts
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import consola from 'consola'
|
|
7
|
+
import { addDependencies } from '../utils/package'
|
|
8
|
+
import { updateNuxtConfig } from '../utils/config'
|
|
9
|
+
|
|
10
|
+
export interface FrontendInstallerOptions {
|
|
11
|
+
cwd: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Install the @stonecrop/nuxt frontend module
|
|
16
|
+
*/
|
|
17
|
+
export async function installFrontend(options: FrontendInstallerOptions): Promise<boolean> {
|
|
18
|
+
const { cwd } = options
|
|
19
|
+
|
|
20
|
+
consola.start('Installing @stonecrop/nuxt frontend module...')
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
// Add @stonecrop/nuxt and its required peer dependencies
|
|
24
|
+
// These packages are imported by the Nuxt module and need to be available at runtime
|
|
25
|
+
await addDependencies(cwd, {
|
|
26
|
+
'@stonecrop/nuxt': 'latest',
|
|
27
|
+
'@stonecrop/aform': 'latest',
|
|
28
|
+
'@stonecrop/atable': 'latest',
|
|
29
|
+
'@stonecrop/stonecrop': 'latest',
|
|
30
|
+
'@stonecrop/node-editor': 'latest',
|
|
31
|
+
'@stonecrop/schema': 'latest',
|
|
32
|
+
'@stonecrop/utilities': 'latest',
|
|
33
|
+
pinia: '^3.0.4',
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
// Update nuxt.config.ts with module and Nitro configuration
|
|
37
|
+
await updateNuxtConfig(cwd, {
|
|
38
|
+
module: "'@stonecrop/nuxt'",
|
|
39
|
+
moduleOptions: {
|
|
40
|
+
key: 'stonecrop',
|
|
41
|
+
value: `{
|
|
42
|
+
// Enable DocBuilder for visual schema editing
|
|
43
|
+
docbuilder: false,
|
|
44
|
+
}`,
|
|
45
|
+
},
|
|
46
|
+
// Add Nitro configuration to handle CSS imports in Stonecrop packages
|
|
47
|
+
// This is required because the packages use vite-plugin-lib-inject-css which adds
|
|
48
|
+
// CSS imports to the JavaScript bundles. Node.js ESM loader doesn't understand .css files,
|
|
49
|
+
// so we need Nitro to bundle these packages (allowing Vite to process the CSS)
|
|
50
|
+
nitroConfig: {
|
|
51
|
+
externalsInline: [
|
|
52
|
+
'@stonecrop/aform',
|
|
53
|
+
'@stonecrop/atable',
|
|
54
|
+
'@stonecrop/stonecrop',
|
|
55
|
+
'@stonecrop/node-editor',
|
|
56
|
+
'@stonecrop/utilities',
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
consola.success('@stonecrop/nuxt installed successfully')
|
|
62
|
+
consola.info('Added Nitro configuration for CSS handling')
|
|
63
|
+
return true
|
|
64
|
+
} catch (error) {
|
|
65
|
+
consola.error('Failed to install @stonecrop/nuxt:', error)
|
|
66
|
+
return false
|
|
67
|
+
}
|
|
68
|
+
}
|