mycelia-kernel-plugin 1.2.0 → 1.3.0
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 +47 -5
- package/bin/cli.js +508 -3
- package/package.json +7 -4
- package/src/svelte/builders.js +43 -0
- package/src/svelte/index.js +183 -0
- package/src/svelte/listeners.js +96 -0
- package/src/svelte/queues.js +114 -0
- package/src/svelte/stores.js +36 -0
- package/src/vue/builders.js +40 -0
- package/src/vue/composables.js +37 -0
- package/src/vue/index.js +252 -0
- package/src/vue/listeners.js +78 -0
- package/src/vue/queues.js +113 -0
package/README.md
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# Mycelia Plugin System
|
|
2
2
|
|
|
3
|
-
A sophisticated,
|
|
3
|
+
A sophisticated, **framework-agnostic** plugin system with transaction safety, lifecycle management, and official bindings for React and Vue 3.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
Mycelia Plugin System is a standalone plugin architecture extracted from [Mycelia Kernel](https://github.com/lesfleursdelanuitdev/mycelia-kernel). It provides:
|
|
7
|
+
Mycelia Plugin System is a **framework-agnostic**, standalone plugin architecture extracted from [Mycelia Kernel](https://github.com/lesfleursdelanuitdev/mycelia-kernel). It provides:
|
|
8
8
|
|
|
9
|
+
- **Framework-agnostic** - Write domain logic once, use it with React, Vue, or any framework. Plugins are completely independent of UI frameworks
|
|
9
10
|
- **Hook-based composition** - Extend systems without modification
|
|
10
11
|
- **Dependency resolution** - Automatic topological sorting
|
|
11
12
|
- **Transaction safety** - Atomic installation with rollback
|
|
@@ -14,9 +15,21 @@ Mycelia Plugin System is a standalone plugin architecture extracted from [Myceli
|
|
|
14
15
|
- **Facet contracts** - Runtime validation of plugin interfaces
|
|
15
16
|
- **Standalone mode** - Works without message system or other dependencies
|
|
16
17
|
- **Built-in hooks** - Ships with `useListeners` for event-driven architectures (see [Simple Event System Example](#simple-event-system-example)), plus `useQueue` and `useSpeak`
|
|
18
|
+
- **Framework bindings** - Official bindings for [React](#react-bindings), [Vue 3](#vue-bindings), and [Svelte](#svelte-bindings) with more coming soon
|
|
17
19
|
|
|
18
20
|
**Facets** are the concrete runtime capabilities produced by hooks and attached to the system.
|
|
19
21
|
|
|
22
|
+
### Framework Integration
|
|
23
|
+
|
|
24
|
+
The system is designed to be framework-agnostic. Your domain logic lives in Mycelia plugins, which can be used with any framework:
|
|
25
|
+
|
|
26
|
+
- **React** - Use `MyceliaProvider` and React hooks (`useFacet`, `useListener`)
|
|
27
|
+
- **Vue 3** - Use `MyceliaPlugin` and Vue composables (`useFacet`, `useListener`)
|
|
28
|
+
- **Svelte** - Use `setMyceliaSystem` and Svelte stores (`useFacet`, `useListener`)
|
|
29
|
+
- **Vanilla JS/Node.js** - Use the system directly without any framework bindings
|
|
30
|
+
|
|
31
|
+
See the [React Todo App](./examples/react-todo/README.md), [Vue Todo App](./examples/vue-todo/README.md), and [Svelte Todo App](./examples/svelte-todo/README.md) examples - they all use the **exact same plugin code**, demonstrating true framework independence.
|
|
32
|
+
|
|
20
33
|
## Quick Start
|
|
21
34
|
|
|
22
35
|
### Using useBase (Recommended)
|
|
@@ -285,7 +298,9 @@ Comprehensive documentation is available in the [`docs/`](./docs/) directory:
|
|
|
285
298
|
- **[Getting Started Guide](./docs/getting-started/README.md)** - Quick start with examples
|
|
286
299
|
- **[Hooks and Facets Overview](./docs/core-concepts/HOOKS-AND-FACETS-OVERVIEW.md)** - Core concepts
|
|
287
300
|
- **[Built-in Hooks](./docs/hooks/README.md)** - Documentation for `useListeners`, `useQueue`, and `useSpeak`
|
|
288
|
-
- **[React Bindings](./docs/react/README.md)** - React integration utilities
|
|
301
|
+
- **[React Bindings](./docs/react/README.md)** - React integration utilities (`MyceliaProvider`, `useFacet`, `useListener`)
|
|
302
|
+
- **[Vue Bindings](./docs/vue/README.md)** - Vue 3 integration utilities (`MyceliaPlugin`, `useFacet`, `useListener`) ⭐
|
|
303
|
+
- **[Svelte Bindings](./docs/svelte/README.md)** - Svelte integration utilities (`setMyceliaSystem`, `useFacet`, `useListener`) ⭐
|
|
289
304
|
- **[Standalone Plugin System](./docs/standalone/STANDALONE-PLUGIN-SYSTEM.md)** - Complete usage guide
|
|
290
305
|
- **[Documentation Index](./docs/README.md)** - Full documentation index
|
|
291
306
|
|
|
@@ -298,11 +313,28 @@ See the `examples/` directory for:
|
|
|
298
313
|
- Contract validation
|
|
299
314
|
- Hot reloading
|
|
300
315
|
- useBase fluent API
|
|
301
|
-
|
|
316
|
+
|
|
317
|
+
### Framework Integration Examples
|
|
318
|
+
|
|
319
|
+
- **[React Todo App](./examples/react-todo/README.md)** – A real-world example showing:
|
|
302
320
|
- Domain logic as a Mycelia facet (`useTodos` hook)
|
|
303
321
|
- Event-driven state synchronization (`todos:changed` events)
|
|
304
322
|
- React bindings (`MyceliaProvider`, `useFacet`, `useListener`)
|
|
305
323
|
|
|
324
|
+
- **[Vue Todo App](./examples/vue-todo/README.md)** ⭐ – A complete Vue 3 example demonstrating:
|
|
325
|
+
- **Framework-agnostic plugins** - Uses the same shared plugin code as the React example
|
|
326
|
+
- Event-driven state synchronization (`todos:changed` events)
|
|
327
|
+
- Vue 3 bindings (`MyceliaPlugin`, `useFacet`, `useListener`)
|
|
328
|
+
- Composition API integration with reactive state management
|
|
329
|
+
|
|
330
|
+
- **[Svelte Todo App](./examples/svelte-todo/README.md)** ⭐ – A complete Svelte example demonstrating:
|
|
331
|
+
- **Framework-agnostic plugins** - Uses the same shared plugin code as React and Vue examples
|
|
332
|
+
- Event-driven state synchronization (`todos:changed` events)
|
|
333
|
+
- Svelte bindings (`setMyceliaSystem`, `useFacet`, `useListener`)
|
|
334
|
+
- Store-based reactivity with automatic subscription
|
|
335
|
+
|
|
336
|
+
All three examples use the **exact same Mycelia plugin code** from `examples/todo-shared/`, proving that plugins are truly framework-independent. Write your domain logic once, use it everywhere!
|
|
337
|
+
|
|
306
338
|
## CLI Tool
|
|
307
339
|
|
|
308
340
|
The package includes a CLI tool for scaffolding hooks, contracts, and projects:
|
|
@@ -314,14 +346,24 @@ npx mycelia-kernel-plugin create hook database
|
|
|
314
346
|
# Create a new contract
|
|
315
347
|
npx mycelia-kernel-plugin create contract database
|
|
316
348
|
|
|
317
|
-
# Initialize a new project
|
|
349
|
+
# Initialize a new project (vanilla JS)
|
|
318
350
|
npx mycelia-kernel-plugin init my-app
|
|
351
|
+
|
|
352
|
+
# Initialize a React project with Mycelia bindings
|
|
353
|
+
npx mycelia-kernel-plugin init react my-react-app
|
|
354
|
+
|
|
355
|
+
# Initialize a Vue 3 project with Mycelia bindings
|
|
356
|
+
npx mycelia-kernel-plugin init vue my-vue-app
|
|
357
|
+
|
|
358
|
+
# Initialize a Svelte project with Mycelia bindings
|
|
359
|
+
npx mycelia-kernel-plugin init svelte my-svelte-app
|
|
319
360
|
```
|
|
320
361
|
|
|
321
362
|
Or install globally:
|
|
322
363
|
```bash
|
|
323
364
|
npm install -g mycelia-kernel-plugin
|
|
324
365
|
mycelia-kernel-plugin create hook database
|
|
366
|
+
mycelia-kernel-plugin init react my-react-app
|
|
325
367
|
```
|
|
326
368
|
|
|
327
369
|
## Testing
|
package/bin/cli.js
CHANGED
|
@@ -62,8 +62,22 @@ function handleCreate(args) {
|
|
|
62
62
|
* Handle 'init' command
|
|
63
63
|
*/
|
|
64
64
|
function handleInit(args) {
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
if (args.length === 0) {
|
|
66
|
+
const projectName = 'my-plugin-system';
|
|
67
|
+
initProject(projectName);
|
|
68
|
+
} else if (args[0] === 'react') {
|
|
69
|
+
const projectName = args[1] || 'my-react-app';
|
|
70
|
+
initReactProject(projectName);
|
|
71
|
+
} else if (args[0] === 'vue') {
|
|
72
|
+
const projectName = args[1] || 'my-vue-app';
|
|
73
|
+
initVueProject(projectName);
|
|
74
|
+
} else if (args[0] === 'svelte') {
|
|
75
|
+
const projectName = args[1] || 'my-svelte-app';
|
|
76
|
+
initSvelteProject(projectName);
|
|
77
|
+
} else {
|
|
78
|
+
const projectName = args[0];
|
|
79
|
+
initProject(projectName);
|
|
80
|
+
}
|
|
67
81
|
}
|
|
68
82
|
|
|
69
83
|
/**
|
|
@@ -368,6 +382,491 @@ main().catch(console.error);
|
|
|
368
382
|
console.log(` npm start`);
|
|
369
383
|
}
|
|
370
384
|
|
|
385
|
+
/**
|
|
386
|
+
* Initialize a React project with Mycelia bindings
|
|
387
|
+
*/
|
|
388
|
+
function initReactProject(projectName) {
|
|
389
|
+
const projectDir = projectName;
|
|
390
|
+
|
|
391
|
+
if (existsSync(projectDir)) {
|
|
392
|
+
console.error(`Error: Directory already exists: ${projectDir}`);
|
|
393
|
+
process.exit(1);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
console.log(`Creating React project: ${projectName}...`);
|
|
397
|
+
|
|
398
|
+
// Create directory structure
|
|
399
|
+
mkdirSync(projectDir, { recursive: true });
|
|
400
|
+
mkdirSync(join(projectDir, 'src'), { recursive: true });
|
|
401
|
+
mkdirSync(join(projectDir, 'src/hooks'), { recursive: true });
|
|
402
|
+
mkdirSync(join(projectDir, 'src/components'), { recursive: true });
|
|
403
|
+
|
|
404
|
+
// Create package.json
|
|
405
|
+
const packageJson = {
|
|
406
|
+
name: projectName,
|
|
407
|
+
version: '1.0.0',
|
|
408
|
+
type: 'module',
|
|
409
|
+
scripts: {
|
|
410
|
+
dev: 'vite',
|
|
411
|
+
build: 'vite build',
|
|
412
|
+
preview: 'vite preview'
|
|
413
|
+
},
|
|
414
|
+
dependencies: {
|
|
415
|
+
'mycelia-kernel-plugin': '^1.2.0',
|
|
416
|
+
'react': '^18.2.0',
|
|
417
|
+
'react-dom': '^18.2.0'
|
|
418
|
+
},
|
|
419
|
+
devDependencies: {
|
|
420
|
+
'@vitejs/plugin-react': '^4.2.0',
|
|
421
|
+
'vite': '^5.0.0'
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
writeFileSync(
|
|
426
|
+
join(projectDir, 'package.json'),
|
|
427
|
+
JSON.stringify(packageJson, null, 2),
|
|
428
|
+
'utf8'
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
// Create vite.config.js
|
|
432
|
+
const viteConfig = `import { defineConfig } from 'vite';
|
|
433
|
+
import react from '@vitejs/plugin-react';
|
|
434
|
+
|
|
435
|
+
export default defineConfig({
|
|
436
|
+
plugins: [react()],
|
|
437
|
+
});
|
|
438
|
+
`;
|
|
439
|
+
|
|
440
|
+
writeFileSync(join(projectDir, 'vite.config.js'), viteConfig, 'utf8');
|
|
441
|
+
|
|
442
|
+
// Create index.html
|
|
443
|
+
const indexHtml = `<!DOCTYPE html>
|
|
444
|
+
<html lang="en">
|
|
445
|
+
<head>
|
|
446
|
+
<meta charset="UTF-8" />
|
|
447
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
448
|
+
<title>${projectName}</title>
|
|
449
|
+
</head>
|
|
450
|
+
<body>
|
|
451
|
+
<div id="root"></div>
|
|
452
|
+
<script type="module" src="/src/main.jsx"></script>
|
|
453
|
+
</body>
|
|
454
|
+
</html>
|
|
455
|
+
`;
|
|
456
|
+
|
|
457
|
+
writeFileSync(join(projectDir, 'index.html'), indexHtml, 'utf8');
|
|
458
|
+
|
|
459
|
+
// Create main.jsx
|
|
460
|
+
const mainJsx = `import React from 'react';
|
|
461
|
+
import ReactDOM from 'react-dom/client';
|
|
462
|
+
import { MyceliaProvider } from 'mycelia-kernel-plugin/react';
|
|
463
|
+
import { useBase } from 'mycelia-kernel-plugin';
|
|
464
|
+
import App from './App.jsx';
|
|
465
|
+
|
|
466
|
+
const buildSystem = () =>
|
|
467
|
+
useBase('${projectName}')
|
|
468
|
+
.build();
|
|
469
|
+
|
|
470
|
+
ReactDOM.createRoot(document.getElementById('root')).render(
|
|
471
|
+
<React.StrictMode>
|
|
472
|
+
<MyceliaProvider build={buildSystem}>
|
|
473
|
+
<App />
|
|
474
|
+
</MyceliaProvider>
|
|
475
|
+
</React.StrictMode>
|
|
476
|
+
);
|
|
477
|
+
`;
|
|
478
|
+
|
|
479
|
+
writeFileSync(join(projectDir, 'src/main.jsx'), mainJsx, 'utf8');
|
|
480
|
+
|
|
481
|
+
// Create App.jsx
|
|
482
|
+
const appJsx = `import React from 'react';
|
|
483
|
+
import { useMycelia } from 'mycelia-kernel-plugin/react';
|
|
484
|
+
|
|
485
|
+
function App() {
|
|
486
|
+
const system = useMycelia();
|
|
487
|
+
|
|
488
|
+
return (
|
|
489
|
+
<div>
|
|
490
|
+
<h1>${projectName}</h1>
|
|
491
|
+
<p>System: {system?.name}</p>
|
|
492
|
+
</div>
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
export default App;
|
|
497
|
+
`;
|
|
498
|
+
|
|
499
|
+
writeFileSync(join(projectDir, 'src/App.jsx'), appJsx, 'utf8');
|
|
500
|
+
|
|
501
|
+
// Create README.md
|
|
502
|
+
const readme = `# ${projectName}
|
|
503
|
+
|
|
504
|
+
A React application built with Mycelia Plugin System.
|
|
505
|
+
|
|
506
|
+
## Getting Started
|
|
507
|
+
|
|
508
|
+
\`\`\`bash
|
|
509
|
+
npm install
|
|
510
|
+
npm run dev
|
|
511
|
+
\`\`\`
|
|
512
|
+
|
|
513
|
+
## Creating Plugins
|
|
514
|
+
|
|
515
|
+
Use the CLI to scaffold new plugins:
|
|
516
|
+
|
|
517
|
+
\`\`\`bash
|
|
518
|
+
npx mycelia-kernel-plugin create hook my-plugin
|
|
519
|
+
\`\`\`
|
|
520
|
+
|
|
521
|
+
## Structure
|
|
522
|
+
|
|
523
|
+
- \`src/hooks/\` - Plugin hooks
|
|
524
|
+
- \`src/components/\` - React components
|
|
525
|
+
- \`src/App.jsx\` - Main app component
|
|
526
|
+
- \`src/main.jsx\` - Entry point
|
|
527
|
+
`;
|
|
528
|
+
|
|
529
|
+
writeFileSync(join(projectDir, 'README.md'), readme, 'utf8');
|
|
530
|
+
|
|
531
|
+
// Create .gitignore
|
|
532
|
+
const gitignore = `node_modules/
|
|
533
|
+
dist/
|
|
534
|
+
*.log
|
|
535
|
+
.DS_Store
|
|
536
|
+
`;
|
|
537
|
+
|
|
538
|
+
writeFileSync(join(projectDir, '.gitignore'), gitignore, 'utf8');
|
|
539
|
+
|
|
540
|
+
console.log(`✅ React project created: ${projectDir}`);
|
|
541
|
+
console.log(`\nNext steps:`);
|
|
542
|
+
console.log(` cd ${projectDir}`);
|
|
543
|
+
console.log(` npm install`);
|
|
544
|
+
console.log(` npm run dev`);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* Initialize a Vue project with Mycelia bindings
|
|
549
|
+
*/
|
|
550
|
+
function initVueProject(projectName) {
|
|
551
|
+
const projectDir = projectName;
|
|
552
|
+
|
|
553
|
+
if (existsSync(projectDir)) {
|
|
554
|
+
console.error(`Error: Directory already exists: ${projectDir}`);
|
|
555
|
+
process.exit(1);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
console.log(`Creating Vue project: ${projectName}...`);
|
|
559
|
+
|
|
560
|
+
// Create directory structure
|
|
561
|
+
mkdirSync(projectDir, { recursive: true });
|
|
562
|
+
mkdirSync(join(projectDir, 'src'), { recursive: true });
|
|
563
|
+
mkdirSync(join(projectDir, 'src/hooks'), { recursive: true });
|
|
564
|
+
mkdirSync(join(projectDir, 'src/components'), { recursive: true });
|
|
565
|
+
|
|
566
|
+
// Create package.json
|
|
567
|
+
const packageJson = {
|
|
568
|
+
name: projectName,
|
|
569
|
+
version: '1.0.0',
|
|
570
|
+
type: 'module',
|
|
571
|
+
scripts: {
|
|
572
|
+
dev: 'vite',
|
|
573
|
+
build: 'vite build',
|
|
574
|
+
preview: 'vite preview'
|
|
575
|
+
},
|
|
576
|
+
dependencies: {
|
|
577
|
+
'mycelia-kernel-plugin': '^1.2.0',
|
|
578
|
+
'vue': '^3.4.0'
|
|
579
|
+
},
|
|
580
|
+
devDependencies: {
|
|
581
|
+
'@vitejs/plugin-vue': '^5.0.0',
|
|
582
|
+
'vite': '^5.0.0'
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
writeFileSync(
|
|
587
|
+
join(projectDir, 'package.json'),
|
|
588
|
+
JSON.stringify(packageJson, null, 2),
|
|
589
|
+
'utf8'
|
|
590
|
+
);
|
|
591
|
+
|
|
592
|
+
// Create vite.config.js
|
|
593
|
+
const viteConfig = `import { defineConfig } from 'vite';
|
|
594
|
+
import vue from '@vitejs/plugin-vue';
|
|
595
|
+
|
|
596
|
+
export default defineConfig({
|
|
597
|
+
plugins: [vue()],
|
|
598
|
+
});
|
|
599
|
+
`;
|
|
600
|
+
|
|
601
|
+
writeFileSync(join(projectDir, 'vite.config.js'), viteConfig, 'utf8');
|
|
602
|
+
|
|
603
|
+
// Create index.html
|
|
604
|
+
const indexHtml = `<!DOCTYPE html>
|
|
605
|
+
<html lang="en">
|
|
606
|
+
<head>
|
|
607
|
+
<meta charset="UTF-8" />
|
|
608
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
609
|
+
<title>${projectName}</title>
|
|
610
|
+
</head>
|
|
611
|
+
<body>
|
|
612
|
+
<div id="app"></div>
|
|
613
|
+
<script type="module" src="/src/main.js"></script>
|
|
614
|
+
</body>
|
|
615
|
+
</html>
|
|
616
|
+
`;
|
|
617
|
+
|
|
618
|
+
writeFileSync(join(projectDir, 'index.html'), indexHtml, 'utf8');
|
|
619
|
+
|
|
620
|
+
// Create main.js
|
|
621
|
+
const mainJs = `import { createApp } from 'vue';
|
|
622
|
+
import { MyceliaPlugin } from 'mycelia-kernel-plugin/vue';
|
|
623
|
+
import { useBase } from 'mycelia-kernel-plugin';
|
|
624
|
+
import App from './App.vue';
|
|
625
|
+
|
|
626
|
+
const buildSystem = () =>
|
|
627
|
+
useBase('${projectName}')
|
|
628
|
+
.build();
|
|
629
|
+
|
|
630
|
+
const app = createApp(App);
|
|
631
|
+
app.use(MyceliaPlugin, { build: buildSystem });
|
|
632
|
+
app.mount('#app');
|
|
633
|
+
`;
|
|
634
|
+
|
|
635
|
+
writeFileSync(join(projectDir, 'src/main.js'), mainJs, 'utf8');
|
|
636
|
+
|
|
637
|
+
// Create App.vue
|
|
638
|
+
const appVue = `<template>
|
|
639
|
+
<div>
|
|
640
|
+
<h1>${projectName}</h1>
|
|
641
|
+
<p>System: {{ system?.name }}</p>
|
|
642
|
+
</div>
|
|
643
|
+
</template>
|
|
644
|
+
|
|
645
|
+
<script setup>
|
|
646
|
+
import { useMycelia } from 'mycelia-kernel-plugin/vue';
|
|
647
|
+
|
|
648
|
+
const system = useMycelia();
|
|
649
|
+
</script>
|
|
650
|
+
`;
|
|
651
|
+
|
|
652
|
+
writeFileSync(join(projectDir, 'src/App.vue'), appVue, 'utf8');
|
|
653
|
+
|
|
654
|
+
// Create README.md
|
|
655
|
+
const readme = `# ${projectName}
|
|
656
|
+
|
|
657
|
+
A Vue 3 application built with Mycelia Plugin System.
|
|
658
|
+
|
|
659
|
+
## Getting Started
|
|
660
|
+
|
|
661
|
+
\`\`\`bash
|
|
662
|
+
npm install
|
|
663
|
+
npm run dev
|
|
664
|
+
\`\`\`
|
|
665
|
+
|
|
666
|
+
## Creating Plugins
|
|
667
|
+
|
|
668
|
+
Use the CLI to scaffold new plugins:
|
|
669
|
+
|
|
670
|
+
\`\`\`bash
|
|
671
|
+
npx mycelia-kernel-plugin create hook my-plugin
|
|
672
|
+
\`\`\`
|
|
673
|
+
|
|
674
|
+
## Structure
|
|
675
|
+
|
|
676
|
+
- \`src/hooks/\` - Plugin hooks
|
|
677
|
+
- \`src/components/\` - Vue components
|
|
678
|
+
- \`src/App.vue\` - Main app component
|
|
679
|
+
- \`src/main.js\` - Entry point
|
|
680
|
+
`;
|
|
681
|
+
|
|
682
|
+
writeFileSync(join(projectDir, 'README.md'), readme, 'utf8');
|
|
683
|
+
|
|
684
|
+
// Create .gitignore
|
|
685
|
+
const gitignore = `node_modules/
|
|
686
|
+
dist/
|
|
687
|
+
*.log
|
|
688
|
+
.DS_Store
|
|
689
|
+
`;
|
|
690
|
+
|
|
691
|
+
writeFileSync(join(projectDir, '.gitignore'), gitignore, 'utf8');
|
|
692
|
+
|
|
693
|
+
console.log(`✅ Vue project created: ${projectDir}`);
|
|
694
|
+
console.log(`\nNext steps:`);
|
|
695
|
+
console.log(` cd ${projectDir}`);
|
|
696
|
+
console.log(` npm install`);
|
|
697
|
+
console.log(` npm run dev`);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* Initialize a Svelte project with Mycelia bindings
|
|
702
|
+
*/
|
|
703
|
+
function initSvelteProject(projectName) {
|
|
704
|
+
const projectDir = projectName;
|
|
705
|
+
|
|
706
|
+
if (existsSync(projectDir)) {
|
|
707
|
+
console.error(`Error: Directory already exists: ${projectDir}`);
|
|
708
|
+
process.exit(1);
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
console.log(`Creating Svelte project: ${projectName}...`);
|
|
712
|
+
|
|
713
|
+
// Create directory structure
|
|
714
|
+
mkdirSync(projectDir, { recursive: true });
|
|
715
|
+
mkdirSync(join(projectDir, 'src'), { recursive: true });
|
|
716
|
+
mkdirSync(join(projectDir, 'src/hooks'), { recursive: true });
|
|
717
|
+
mkdirSync(join(projectDir, 'src/components'), { recursive: true });
|
|
718
|
+
|
|
719
|
+
// Create package.json
|
|
720
|
+
const packageJson = {
|
|
721
|
+
name: projectName,
|
|
722
|
+
version: '1.0.0',
|
|
723
|
+
type: 'module',
|
|
724
|
+
scripts: {
|
|
725
|
+
dev: 'vite dev',
|
|
726
|
+
build: 'vite build',
|
|
727
|
+
preview: 'vite preview'
|
|
728
|
+
},
|
|
729
|
+
dependencies: {
|
|
730
|
+
'mycelia-kernel-plugin': '^1.2.0',
|
|
731
|
+
'svelte': '^4.2.0'
|
|
732
|
+
},
|
|
733
|
+
devDependencies: {
|
|
734
|
+
'@sveltejs/vite-plugin-svelte': '^3.0.0',
|
|
735
|
+
'vite': '^5.0.0'
|
|
736
|
+
}
|
|
737
|
+
};
|
|
738
|
+
|
|
739
|
+
writeFileSync(
|
|
740
|
+
join(projectDir, 'package.json'),
|
|
741
|
+
JSON.stringify(packageJson, null, 2),
|
|
742
|
+
'utf8'
|
|
743
|
+
);
|
|
744
|
+
|
|
745
|
+
// Create vite.config.js
|
|
746
|
+
const viteConfig = `import { defineConfig } from 'vite';
|
|
747
|
+
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
|
748
|
+
|
|
749
|
+
export default defineConfig({
|
|
750
|
+
plugins: [svelte()],
|
|
751
|
+
});
|
|
752
|
+
`;
|
|
753
|
+
|
|
754
|
+
writeFileSync(join(projectDir, 'vite.config.js'), viteConfig, 'utf8');
|
|
755
|
+
|
|
756
|
+
// Create svelte.config.js
|
|
757
|
+
const svelteConfig = `import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
|
758
|
+
|
|
759
|
+
export default {
|
|
760
|
+
preprocess: vitePreprocess(),
|
|
761
|
+
};
|
|
762
|
+
`;
|
|
763
|
+
|
|
764
|
+
writeFileSync(join(projectDir, 'svelte.config.js'), svelteConfig, 'utf8');
|
|
765
|
+
|
|
766
|
+
// Create index.html
|
|
767
|
+
const indexHtml = `<!DOCTYPE html>
|
|
768
|
+
<html lang="en">
|
|
769
|
+
<head>
|
|
770
|
+
<meta charset="UTF-8" />
|
|
771
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
772
|
+
<title>${projectName}</title>
|
|
773
|
+
</head>
|
|
774
|
+
<body>
|
|
775
|
+
<div id="app"></div>
|
|
776
|
+
<script type="module" src="/src/main.js"></script>
|
|
777
|
+
</body>
|
|
778
|
+
</html>
|
|
779
|
+
`;
|
|
780
|
+
|
|
781
|
+
writeFileSync(join(projectDir, 'index.html'), indexHtml, 'utf8');
|
|
782
|
+
|
|
783
|
+
// Create main.js
|
|
784
|
+
const mainJs = `import App from './App.svelte';
|
|
785
|
+
|
|
786
|
+
const app = new App({
|
|
787
|
+
target: document.getElementById('app'),
|
|
788
|
+
});
|
|
789
|
+
|
|
790
|
+
export default app;
|
|
791
|
+
`;
|
|
792
|
+
|
|
793
|
+
writeFileSync(join(projectDir, 'src/main.js'), mainJs, 'utf8');
|
|
794
|
+
|
|
795
|
+
// Create App.svelte
|
|
796
|
+
const appSvelte = `<script>
|
|
797
|
+
import { onMount } from 'svelte';
|
|
798
|
+
import { setMyceliaSystem, useMycelia } from 'mycelia-kernel-plugin/svelte';
|
|
799
|
+
import { useBase } from 'mycelia-kernel-plugin';
|
|
800
|
+
|
|
801
|
+
let system;
|
|
802
|
+
|
|
803
|
+
onMount(async () => {
|
|
804
|
+
system = await useBase('${projectName}').build();
|
|
805
|
+
setMyceliaSystem(system);
|
|
806
|
+
});
|
|
807
|
+
|
|
808
|
+
const systemStore = useMycelia();
|
|
809
|
+
$: currentSystem = $systemStore;
|
|
810
|
+
</script>
|
|
811
|
+
|
|
812
|
+
<div>
|
|
813
|
+
<h1>${projectName}</h1>
|
|
814
|
+
{#if currentSystem}
|
|
815
|
+
<p>System: {currentSystem.name}</p>
|
|
816
|
+
{:else}
|
|
817
|
+
<p>Loading system...</p>
|
|
818
|
+
{/if}
|
|
819
|
+
</div>
|
|
820
|
+
`;
|
|
821
|
+
|
|
822
|
+
writeFileSync(join(projectDir, 'src/App.svelte'), appSvelte, 'utf8');
|
|
823
|
+
|
|
824
|
+
// Create README.md
|
|
825
|
+
const readme = `# ${projectName}
|
|
826
|
+
|
|
827
|
+
A Svelte application built with Mycelia Plugin System.
|
|
828
|
+
|
|
829
|
+
## Getting Started
|
|
830
|
+
|
|
831
|
+
\`\`\`bash
|
|
832
|
+
npm install
|
|
833
|
+
npm run dev
|
|
834
|
+
\`\`\`
|
|
835
|
+
|
|
836
|
+
## Creating Plugins
|
|
837
|
+
|
|
838
|
+
Use the CLI to scaffold new plugins:
|
|
839
|
+
|
|
840
|
+
\`\`\`bash
|
|
841
|
+
npx mycelia-kernel-plugin create hook my-plugin
|
|
842
|
+
\`\`\`
|
|
843
|
+
|
|
844
|
+
## Structure
|
|
845
|
+
|
|
846
|
+
- \`src/hooks/\` - Plugin hooks
|
|
847
|
+
- \`src/components/\` - Svelte components
|
|
848
|
+
- \`src/App.svelte\` - Main app component
|
|
849
|
+
- \`src/main.js\` - Entry point
|
|
850
|
+
`;
|
|
851
|
+
|
|
852
|
+
writeFileSync(join(projectDir, 'README.md'), readme, 'utf8');
|
|
853
|
+
|
|
854
|
+
// Create .gitignore
|
|
855
|
+
const gitignore = `node_modules/
|
|
856
|
+
dist/
|
|
857
|
+
*.log
|
|
858
|
+
.DS_Store
|
|
859
|
+
`;
|
|
860
|
+
|
|
861
|
+
writeFileSync(join(projectDir, '.gitignore'), gitignore, 'utf8');
|
|
862
|
+
|
|
863
|
+
console.log(`✅ Svelte project created: ${projectDir}`);
|
|
864
|
+
console.log(`\nNext steps:`);
|
|
865
|
+
console.log(` cd ${projectDir}`);
|
|
866
|
+
console.log(` npm install`);
|
|
867
|
+
console.log(` npm run dev`);
|
|
868
|
+
}
|
|
869
|
+
|
|
371
870
|
/**
|
|
372
871
|
* Show help message
|
|
373
872
|
*/
|
|
@@ -381,13 +880,19 @@ Usage:
|
|
|
381
880
|
Commands:
|
|
382
881
|
create hook <name> Create a new hook file
|
|
383
882
|
create contract <name> Create a new contract file
|
|
384
|
-
init [name] Initialize a new project
|
|
883
|
+
init [name] Initialize a new project (vanilla JS)
|
|
884
|
+
init react [name] Initialize a React project with Mycelia bindings
|
|
885
|
+
init vue [name] Initialize a Vue 3 project with Mycelia bindings
|
|
886
|
+
init svelte [name] Initialize a Svelte project with Mycelia bindings
|
|
385
887
|
help Show this help message
|
|
386
888
|
|
|
387
889
|
Examples:
|
|
388
890
|
mycelia-kernel-plugin create hook database
|
|
389
891
|
mycelia-kernel-plugin create contract database
|
|
390
892
|
mycelia-kernel-plugin init my-app
|
|
893
|
+
mycelia-kernel-plugin init react my-react-app
|
|
894
|
+
mycelia-kernel-plugin init vue my-vue-app
|
|
895
|
+
mycelia-kernel-plugin init svelte my-svelte-app
|
|
391
896
|
|
|
392
897
|
For more information, visit:
|
|
393
898
|
https://github.com/lesfleursdelanuitdev/mycelia-kernel-plugin-system
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mycelia-kernel-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "A sophisticated, dependency-aware plugin system with transaction safety and lifecycle management",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -35,7 +35,9 @@
|
|
|
35
35
|
"./system": "./src/system/index.js",
|
|
36
36
|
"./contract": "./src/contract/index.js",
|
|
37
37
|
"./contract/contracts": "./src/contract/contracts/index.js",
|
|
38
|
-
"./react": "./src/react/index.js"
|
|
38
|
+
"./react": "./src/react/index.js",
|
|
39
|
+
"./vue": "./src/vue/index.js",
|
|
40
|
+
"./svelte": "./src/svelte/index.js"
|
|
39
41
|
},
|
|
40
42
|
"files": [
|
|
41
43
|
"src/",
|
|
@@ -52,7 +54,9 @@
|
|
|
52
54
|
"test:coverage": "vitest run --coverage"
|
|
53
55
|
},
|
|
54
56
|
"peerDependencies": {
|
|
55
|
-
"react": ">=16.8.0"
|
|
57
|
+
"react": ">=16.8.0",
|
|
58
|
+
"vue": ">=3.0.0",
|
|
59
|
+
"svelte": ">=3.0.0"
|
|
56
60
|
},
|
|
57
61
|
"devDependencies": {
|
|
58
62
|
"@eslint/js": "^9.36.0",
|
|
@@ -64,4 +68,3 @@
|
|
|
64
68
|
"node": ">=18.0.0"
|
|
65
69
|
}
|
|
66
70
|
}
|
|
67
|
-
|