create-slotkit-app 0.1.3 → 0.1.7
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 +13 -16
- package/dist/index.js +125 -47
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
- **Quick Setup**: Create a new SlotKit project in seconds
|
|
16
16
|
- **Vite Integration**: Uses Vite for fast development and building
|
|
17
17
|
- **TypeScript Support**: Full TypeScript configuration included
|
|
18
|
-
- **Plugin System Ready**: Pre-configured plugin directory structure
|
|
18
|
+
- **Plugin System Ready**: Pre-configured plugin directory structure with a default helloworld plugin
|
|
19
|
+
- **Auto Import Generation**: `slotkit generate-imports` runs automatically before `pnpm dev` and `pnpm build`
|
|
19
20
|
- **Zero Configuration**: Works out of the box with sensible defaults
|
|
20
21
|
|
|
21
22
|
### Installation
|
|
@@ -59,14 +60,8 @@ cd my-slotkit-app
|
|
|
59
60
|
# Install dependencies
|
|
60
61
|
pnpm install
|
|
61
62
|
|
|
62
|
-
#
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
# Generate plugin import mappings
|
|
66
|
-
slotkit generate-imports
|
|
67
|
-
|
|
68
|
-
# Start development server
|
|
69
|
-
slotkit dev
|
|
63
|
+
# Start development server (generate-imports runs automatically)
|
|
64
|
+
pnpm dev
|
|
70
65
|
```
|
|
71
66
|
|
|
72
67
|
### What Gets Created
|
|
@@ -81,7 +76,8 @@ my-slotkit-app/
|
|
|
81
76
|
│ │ ├── AppLayout.tsx # Layout with Slot components
|
|
82
77
|
│ │ └── AppLayout.css # Layout styles
|
|
83
78
|
│ └── main.tsx # Entry point
|
|
84
|
-
├── plugins/
|
|
79
|
+
├── plugins/
|
|
80
|
+
│ └── helloworld/ # Default sample plugin
|
|
85
81
|
├── slotkit.config.ts # SlotKit configuration
|
|
86
82
|
├── vite.config.ts # Vite configuration
|
|
87
83
|
├── package.json # Project dependencies
|
|
@@ -98,8 +94,9 @@ The generated project includes:
|
|
|
98
94
|
- `sidebar` slot
|
|
99
95
|
- `content` slot
|
|
100
96
|
- `footer` slot
|
|
101
|
-
3. **slotkit.config.ts**: Basic configuration pointing to `./plugins`
|
|
102
|
-
4. **
|
|
97
|
+
3. **slotkit.config.ts**: Basic configuration pointing to `./plugins`
|
|
98
|
+
4. **helloworld plugin**: Located at `plugins/helloworld/` as a ready-to-run example
|
|
99
|
+
5. **vite.config.ts**: Vite configuration with plugin directory access
|
|
103
100
|
|
|
104
101
|
### Creating Plugins
|
|
105
102
|
|
|
@@ -122,10 +119,10 @@ slotkit disable my-plugin
|
|
|
122
119
|
|
|
123
120
|
### Next Steps
|
|
124
121
|
|
|
125
|
-
1.
|
|
126
|
-
2.
|
|
127
|
-
3.
|
|
128
|
-
4.
|
|
122
|
+
1. Install dependencies: `pnpm install`
|
|
123
|
+
2. Start the dev server: `pnpm dev` (runs `slotkit generate-imports` automatically)
|
|
124
|
+
3. Create additional plugins: `slotkit create-plugin my-plugin --slots content`
|
|
125
|
+
4. Whenever you create/modify plugins outside the dev flow, run `pnpm slotkit generate-imports`
|
|
129
126
|
|
|
130
127
|
### Configuration
|
|
131
128
|
|
package/dist/index.js
CHANGED
|
@@ -56,27 +56,37 @@ function createSlotKitFiles(projectDir) {
|
|
|
56
56
|
// Create App.tsx (replaces Vite's default)
|
|
57
57
|
const appTsx = `import React, { useEffect, useState } from 'react'
|
|
58
58
|
import { AppLayout } from './app/AppLayout'
|
|
59
|
-
import { pluginRegistry, pluginLoader } from '@slotkitjs/core'
|
|
59
|
+
import { pluginRegistry, pluginLoader, setPluginImportFunctions } from '@slotkitjs/core'
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
// Import generated plugin import mappings
|
|
62
|
+
// This file is generated by 'slotkit generate-imports'
|
|
63
|
+
import * as pluginImports from './core/plugin/loader/plugin-imports.generated'
|
|
64
|
+
|
|
65
|
+
// Initialize plugin import mappings
|
|
66
|
+
if (pluginImports.getPluginImport && pluginImports.getAvailablePluginIds) {
|
|
67
|
+
setPluginImportFunctions({
|
|
68
|
+
getPluginImport: (pluginId: string) => {
|
|
69
|
+
const importFn = pluginImports.getPluginImport(pluginId)
|
|
70
|
+
if (!importFn) return undefined
|
|
71
|
+
return () => Promise.resolve(importFn())
|
|
72
|
+
},
|
|
73
|
+
getAvailablePluginIds: pluginImports.getAvailablePluginIds,
|
|
74
|
+
getAllPluginManifests: pluginImports.getAllPluginManifests,
|
|
75
|
+
getPluginManifest: pluginImports.getPluginManifest
|
|
76
|
+
})
|
|
77
|
+
} else {
|
|
78
|
+
console.warn('[WARN] Plugin import functions not found in generated file')
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Load all plugins
|
|
64
82
|
const loadPlugins = async () => {
|
|
65
83
|
try {
|
|
66
|
-
console.log('[INFO] Starting to load plugins...')
|
|
67
|
-
|
|
68
|
-
// Load all plugins using plugin loader
|
|
69
84
|
const plugins = await pluginLoader.loadAllPlugins()
|
|
70
|
-
|
|
71
|
-
// Register all plugins to registry
|
|
85
|
+
|
|
72
86
|
plugins.forEach(plugin => {
|
|
73
87
|
pluginRegistry.register(plugin)
|
|
74
|
-
console.log(\`[INFO] Plugin "\${plugin.name}" registered to slots:\`, plugin.slots)
|
|
75
88
|
})
|
|
76
|
-
|
|
77
|
-
console.log('[OK] Plugin loading completed!')
|
|
78
|
-
console.log(\`[INFO] Total \${plugins.length} plugins loaded\`)
|
|
79
|
-
|
|
89
|
+
|
|
80
90
|
return plugins
|
|
81
91
|
} catch (error) {
|
|
82
92
|
console.error('[ERROR] Failed to load plugins:', error)
|
|
@@ -89,41 +99,43 @@ const App: React.FC = () => {
|
|
|
89
99
|
const [loadedPlugins, setLoadedPlugins] = useState<any[]>([])
|
|
90
100
|
|
|
91
101
|
useEffect(() => {
|
|
92
|
-
loadPlugins()
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
102
|
+
loadPlugins()
|
|
103
|
+
.then((plugins) => {
|
|
104
|
+
setPluginsLoaded(true)
|
|
105
|
+
setLoadedPlugins(plugins)
|
|
106
|
+
})
|
|
107
|
+
.catch((error) => {
|
|
108
|
+
console.error('[ERROR] Failed to load plugins:', error)
|
|
109
|
+
})
|
|
98
110
|
}, [])
|
|
99
111
|
|
|
100
112
|
return (
|
|
101
113
|
<div className="app">
|
|
102
114
|
<AppLayout />
|
|
103
|
-
|
|
115
|
+
|
|
104
116
|
{/* Plugin loading status indicator */}
|
|
105
|
-
<div style={{
|
|
106
|
-
position: 'fixed',
|
|
107
|
-
top: '10px',
|
|
108
|
-
right: '10px',
|
|
109
|
-
background: pluginsLoaded ? '#e8f5e8' : '#fff3cd',
|
|
110
|
-
padding: '10px',
|
|
117
|
+
<div style={{
|
|
118
|
+
position: 'fixed',
|
|
119
|
+
top: '10px',
|
|
120
|
+
right: '10px',
|
|
121
|
+
background: pluginsLoaded ? '#e8f5e8' : '#fff3cd',
|
|
122
|
+
padding: '10px',
|
|
111
123
|
borderRadius: '4px',
|
|
112
124
|
fontSize: '12px',
|
|
113
|
-
border:
|
|
125
|
+
border: pluginsLoaded ? '1px solid #4caf50' : '1px solid #ffc107',
|
|
114
126
|
zIndex: 1000
|
|
115
127
|
}}>
|
|
116
128
|
{pluginsLoaded ? '[OK] Plugins loaded' : '[INFO] Loading plugins...'}
|
|
117
129
|
</div>
|
|
118
|
-
|
|
130
|
+
|
|
119
131
|
{/* Loaded plugins list */}
|
|
120
132
|
{loadedPlugins.length > 0 && (
|
|
121
|
-
<div style={{
|
|
122
|
-
position: 'fixed',
|
|
123
|
-
top: '50px',
|
|
124
|
-
right: '10px',
|
|
125
|
-
background: '#f3e5f5',
|
|
126
|
-
padding: '10px',
|
|
133
|
+
<div style={{
|
|
134
|
+
position: 'fixed',
|
|
135
|
+
top: '50px',
|
|
136
|
+
right: '10px',
|
|
137
|
+
background: '#f3e5f5',
|
|
138
|
+
padding: '10px',
|
|
127
139
|
borderRadius: '4px',
|
|
128
140
|
fontSize: '11px',
|
|
129
141
|
border: '1px solid #9c27b0',
|
|
@@ -256,8 +268,73 @@ export default defineConfig({
|
|
|
256
268
|
})
|
|
257
269
|
`;
|
|
258
270
|
writeFileSync(join(projectDir, 'slotkit.config.ts'), slotkitConfig, 'utf-8');
|
|
259
|
-
// Create plugins directory
|
|
260
|
-
|
|
271
|
+
// Create plugins directory and default hello-world plugin
|
|
272
|
+
const pluginsDir = join(projectDir, 'plugins');
|
|
273
|
+
mkdirSync(pluginsDir, { recursive: true });
|
|
274
|
+
const helloWorldDir = join(pluginsDir, 'helloworld');
|
|
275
|
+
const helloWorldSrcDir = join(helloWorldDir, 'src');
|
|
276
|
+
mkdirSync(helloWorldSrcDir, { recursive: true });
|
|
277
|
+
const helloWorldManifest = `{
|
|
278
|
+
"id": "helloworld",
|
|
279
|
+
"name": "Hello-world Plugin",
|
|
280
|
+
"version": "1.0.0",
|
|
281
|
+
"description": "A built-in hello-world plugin",
|
|
282
|
+
"author": "SlotKit Team",
|
|
283
|
+
"entry": "./src/index.tsx",
|
|
284
|
+
"slots": [
|
|
285
|
+
"content"
|
|
286
|
+
],
|
|
287
|
+
"enabled": true
|
|
288
|
+
}`;
|
|
289
|
+
writeFileSync(join(helloWorldDir, 'manifest.json'), helloWorldManifest + '\n', 'utf-8');
|
|
290
|
+
const helloWorldPackageJson = `{
|
|
291
|
+
"name": "plugin-helloworld",
|
|
292
|
+
"version": "1.0.0",
|
|
293
|
+
"main": "src/index.tsx",
|
|
294
|
+
"private": true
|
|
295
|
+
}`;
|
|
296
|
+
writeFileSync(join(helloWorldDir, 'package.json'), helloWorldPackageJson + '\n', 'utf-8');
|
|
297
|
+
const helloWorldTsconfig = `{
|
|
298
|
+
"extends": "../../tsconfig.json",
|
|
299
|
+
"compilerOptions": {
|
|
300
|
+
"jsx": "react-jsx"
|
|
301
|
+
},
|
|
302
|
+
"include": [
|
|
303
|
+
"src/**/*"
|
|
304
|
+
]
|
|
305
|
+
}`;
|
|
306
|
+
writeFileSync(join(helloWorldDir, 'tsconfig.json'), helloWorldTsconfig + '\n', 'utf-8');
|
|
307
|
+
const helloWorldIndexTsx = `import React from 'react'
|
|
308
|
+
|
|
309
|
+
const HelloWorldComponent: React.FC = () => {
|
|
310
|
+
return (
|
|
311
|
+
<div
|
|
312
|
+
style={{
|
|
313
|
+
padding: '1rem',
|
|
314
|
+
background: '#f5f5f5',
|
|
315
|
+
border: '1px solid #ddd',
|
|
316
|
+
borderRadius: '8px',
|
|
317
|
+
margin: '0.5rem 0'
|
|
318
|
+
}}
|
|
319
|
+
>
|
|
320
|
+
<h3>Hello-world Plugin</h3>
|
|
321
|
+
<p>This is the default hello-world plugin generated by create-slotkit-app.</p>
|
|
322
|
+
</div>
|
|
323
|
+
)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const helloworldPlugin = {
|
|
327
|
+
id: 'helloworld',
|
|
328
|
+
name: 'Hello-world Plugin',
|
|
329
|
+
version: '1.0.0',
|
|
330
|
+
component: HelloWorldComponent,
|
|
331
|
+
slots: ['content']
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export { helloworldPlugin }
|
|
335
|
+
export default helloworldPlugin
|
|
336
|
+
`;
|
|
337
|
+
writeFileSync(join(helloWorldSrcDir, 'index.tsx'), helloWorldIndexTsx, 'utf-8');
|
|
261
338
|
// Create or update vite.config.ts with SlotKit-specific configuration
|
|
262
339
|
const viteConfigPath = join(projectDir, 'vite.config.ts');
|
|
263
340
|
const viteConfigJsPath = join(projectDir, 'vite.config.js');
|
|
@@ -379,13 +456,14 @@ program
|
|
|
379
456
|
// Ensure @vitejs/plugin-react is in devDependencies
|
|
380
457
|
packageJson.devDependencies['@vitejs/plugin-react'] = packageJson.devDependencies['@vitejs/plugin-react'] || '^5.0.4';
|
|
381
458
|
}
|
|
382
|
-
//
|
|
383
|
-
packageJson.scripts
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
459
|
+
// Ensure scripts object exists
|
|
460
|
+
if (!packageJson.scripts) {
|
|
461
|
+
packageJson.scripts = {};
|
|
462
|
+
}
|
|
463
|
+
packageJson.scripts.dev = 'slotkit generate-imports && slotkit dev';
|
|
464
|
+
packageJson.scripts.build = 'slotkit generate-imports && slotkit build';
|
|
465
|
+
packageJson.scripts.preview = packageJson.scripts.preview || 'slotkit preview';
|
|
466
|
+
packageJson.scripts['generate-imports'] = packageJson.scripts['generate-imports'] || 'slotkit generate-imports';
|
|
389
467
|
writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n', 'utf-8');
|
|
390
468
|
}
|
|
391
469
|
// Step 3: Create SlotKit-specific files
|
|
@@ -404,9 +482,9 @@ program
|
|
|
404
482
|
console.log('\n[INFO] Next steps:');
|
|
405
483
|
console.log(` cd ${projectName}`);
|
|
406
484
|
console.log(' pnpm install');
|
|
407
|
-
console.log('
|
|
408
|
-
console.log(' slotkit
|
|
409
|
-
console.log(' slotkit
|
|
485
|
+
console.log(' pnpm dev');
|
|
486
|
+
console.log(' # Optional: pnpm slotkit create-plugin <name> --slots <slots>');
|
|
487
|
+
console.log(' # predev/prebuild will automatically run slotkit generate-imports');
|
|
410
488
|
}
|
|
411
489
|
catch (error) {
|
|
412
490
|
console.error('[ERROR] Failed to create project:', error.message);
|