mycelia-kernel-plugin 1.2.0 → 1.4.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 +89 -6
- package/bin/cli.js +769 -3
- package/package.json +15 -5
- package/src/angular/builders.js +37 -0
- package/src/angular/helpers.js +102 -0
- package/src/angular/index.js +189 -0
- package/src/angular/services.js +32 -0
- package/src/builder/dependency-graph.js +65 -9
- package/src/builder/hook-processor.js +26 -4
- package/src/builder/utils.js +78 -22
- package/src/core/facet.js +16 -3
- package/src/index.js +18 -0
- package/src/manager/facet-manager.js +10 -2
- package/src/qwik/builders.js +39 -0
- package/src/qwik/index.js +178 -0
- package/src/qwik/listeners.js +96 -0
- package/src/qwik/queues.js +87 -0
- package/src/qwik/signals.js +32 -0
- package/src/react/README.md +3 -0
- package/src/solid/README.md +69 -0
- package/src/solid/index.js +387 -0
- 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/utils/instrumentation.js +204 -0
- package/src/utils/use-base.js +205 -30
- 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/bin/cli.js
CHANGED
|
@@ -62,8 +62,28 @@ 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 if (args[0] === 'angular') {
|
|
78
|
+
const projectName = args[1] || 'my-angular-app';
|
|
79
|
+
initAngularProject(projectName);
|
|
80
|
+
} else if (args[0] === 'qwik') {
|
|
81
|
+
const projectName = args[1] || 'my-qwik-app';
|
|
82
|
+
initQwikProject(projectName);
|
|
83
|
+
} else {
|
|
84
|
+
const projectName = args[0];
|
|
85
|
+
initProject(projectName);
|
|
86
|
+
}
|
|
67
87
|
}
|
|
68
88
|
|
|
69
89
|
/**
|
|
@@ -368,6 +388,742 @@ main().catch(console.error);
|
|
|
368
388
|
console.log(` npm start`);
|
|
369
389
|
}
|
|
370
390
|
|
|
391
|
+
/**
|
|
392
|
+
* Initialize a React project with Mycelia bindings
|
|
393
|
+
*/
|
|
394
|
+
function initReactProject(projectName) {
|
|
395
|
+
const projectDir = projectName;
|
|
396
|
+
|
|
397
|
+
if (existsSync(projectDir)) {
|
|
398
|
+
console.error(`Error: Directory already exists: ${projectDir}`);
|
|
399
|
+
process.exit(1);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
console.log(`Creating React project: ${projectName}...`);
|
|
403
|
+
|
|
404
|
+
// Create directory structure
|
|
405
|
+
mkdirSync(projectDir, { recursive: true });
|
|
406
|
+
mkdirSync(join(projectDir, 'src'), { recursive: true });
|
|
407
|
+
mkdirSync(join(projectDir, 'src/hooks'), { recursive: true });
|
|
408
|
+
mkdirSync(join(projectDir, 'src/components'), { recursive: true });
|
|
409
|
+
|
|
410
|
+
// Create package.json
|
|
411
|
+
const packageJson = {
|
|
412
|
+
name: projectName,
|
|
413
|
+
version: '1.0.0',
|
|
414
|
+
type: 'module',
|
|
415
|
+
scripts: {
|
|
416
|
+
dev: 'vite',
|
|
417
|
+
build: 'vite build',
|
|
418
|
+
preview: 'vite preview'
|
|
419
|
+
},
|
|
420
|
+
dependencies: {
|
|
421
|
+
'mycelia-kernel-plugin': '^1.2.0',
|
|
422
|
+
'react': '^18.2.0',
|
|
423
|
+
'react-dom': '^18.2.0'
|
|
424
|
+
},
|
|
425
|
+
devDependencies: {
|
|
426
|
+
'@vitejs/plugin-react': '^4.2.0',
|
|
427
|
+
'vite': '^5.0.0'
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
writeFileSync(
|
|
432
|
+
join(projectDir, 'package.json'),
|
|
433
|
+
JSON.stringify(packageJson, null, 2),
|
|
434
|
+
'utf8'
|
|
435
|
+
);
|
|
436
|
+
|
|
437
|
+
// Create vite.config.js
|
|
438
|
+
const viteConfig = `import { defineConfig } from 'vite';
|
|
439
|
+
import react from '@vitejs/plugin-react';
|
|
440
|
+
|
|
441
|
+
export default defineConfig({
|
|
442
|
+
plugins: [react()],
|
|
443
|
+
});
|
|
444
|
+
`;
|
|
445
|
+
|
|
446
|
+
writeFileSync(join(projectDir, 'vite.config.js'), viteConfig, 'utf8');
|
|
447
|
+
|
|
448
|
+
// Create index.html
|
|
449
|
+
const indexHtml = `<!DOCTYPE html>
|
|
450
|
+
<html lang="en">
|
|
451
|
+
<head>
|
|
452
|
+
<meta charset="UTF-8" />
|
|
453
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
454
|
+
<title>${projectName}</title>
|
|
455
|
+
</head>
|
|
456
|
+
<body>
|
|
457
|
+
<div id="root"></div>
|
|
458
|
+
<script type="module" src="/src/main.jsx"></script>
|
|
459
|
+
</body>
|
|
460
|
+
</html>
|
|
461
|
+
`;
|
|
462
|
+
|
|
463
|
+
writeFileSync(join(projectDir, 'index.html'), indexHtml, 'utf8');
|
|
464
|
+
|
|
465
|
+
// Create main.jsx
|
|
466
|
+
const mainJsx = `import React from 'react';
|
|
467
|
+
import ReactDOM from 'react-dom/client';
|
|
468
|
+
import { MyceliaProvider } from 'mycelia-kernel-plugin/react';
|
|
469
|
+
import { useBase } from 'mycelia-kernel-plugin';
|
|
470
|
+
import App from './App.jsx';
|
|
471
|
+
|
|
472
|
+
const buildSystem = () =>
|
|
473
|
+
useBase('${projectName}')
|
|
474
|
+
.build();
|
|
475
|
+
|
|
476
|
+
ReactDOM.createRoot(document.getElementById('root')).render(
|
|
477
|
+
<React.StrictMode>
|
|
478
|
+
<MyceliaProvider build={buildSystem}>
|
|
479
|
+
<App />
|
|
480
|
+
</MyceliaProvider>
|
|
481
|
+
</React.StrictMode>
|
|
482
|
+
);
|
|
483
|
+
`;
|
|
484
|
+
|
|
485
|
+
writeFileSync(join(projectDir, 'src/main.jsx'), mainJsx, 'utf8');
|
|
486
|
+
|
|
487
|
+
// Create App.jsx
|
|
488
|
+
const appJsx = `import React from 'react';
|
|
489
|
+
import { useMycelia } from 'mycelia-kernel-plugin/react';
|
|
490
|
+
|
|
491
|
+
function App() {
|
|
492
|
+
const system = useMycelia();
|
|
493
|
+
|
|
494
|
+
return (
|
|
495
|
+
<div>
|
|
496
|
+
<h1>${projectName}</h1>
|
|
497
|
+
<p>System: {system?.name}</p>
|
|
498
|
+
</div>
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
export default App;
|
|
503
|
+
`;
|
|
504
|
+
|
|
505
|
+
writeFileSync(join(projectDir, 'src/App.jsx'), appJsx, 'utf8');
|
|
506
|
+
|
|
507
|
+
// Create README.md
|
|
508
|
+
const readme = `# ${projectName}
|
|
509
|
+
|
|
510
|
+
A React application built with Mycelia Plugin System.
|
|
511
|
+
|
|
512
|
+
## Getting Started
|
|
513
|
+
|
|
514
|
+
\`\`\`bash
|
|
515
|
+
npm install
|
|
516
|
+
npm run dev
|
|
517
|
+
\`\`\`
|
|
518
|
+
|
|
519
|
+
## Creating Plugins
|
|
520
|
+
|
|
521
|
+
Use the CLI to scaffold new plugins:
|
|
522
|
+
|
|
523
|
+
\`\`\`bash
|
|
524
|
+
npx mycelia-kernel-plugin create hook my-plugin
|
|
525
|
+
\`\`\`
|
|
526
|
+
|
|
527
|
+
## Structure
|
|
528
|
+
|
|
529
|
+
- \`src/hooks/\` - Plugin hooks
|
|
530
|
+
- \`src/components/\` - React components
|
|
531
|
+
- \`src/App.jsx\` - Main app component
|
|
532
|
+
- \`src/main.jsx\` - Entry point
|
|
533
|
+
`;
|
|
534
|
+
|
|
535
|
+
writeFileSync(join(projectDir, 'README.md'), readme, 'utf8');
|
|
536
|
+
|
|
537
|
+
// Create .gitignore
|
|
538
|
+
const gitignore = `node_modules/
|
|
539
|
+
dist/
|
|
540
|
+
*.log
|
|
541
|
+
.DS_Store
|
|
542
|
+
`;
|
|
543
|
+
|
|
544
|
+
writeFileSync(join(projectDir, '.gitignore'), gitignore, 'utf8');
|
|
545
|
+
|
|
546
|
+
console.log(`✅ React project created: ${projectDir}`);
|
|
547
|
+
console.log(`\nNext steps:`);
|
|
548
|
+
console.log(` cd ${projectDir}`);
|
|
549
|
+
console.log(` npm install`);
|
|
550
|
+
console.log(` npm run dev`);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Initialize a Vue project with Mycelia bindings
|
|
555
|
+
*/
|
|
556
|
+
function initVueProject(projectName) {
|
|
557
|
+
const projectDir = projectName;
|
|
558
|
+
|
|
559
|
+
if (existsSync(projectDir)) {
|
|
560
|
+
console.error(`Error: Directory already exists: ${projectDir}`);
|
|
561
|
+
process.exit(1);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
console.log(`Creating Vue project: ${projectName}...`);
|
|
565
|
+
|
|
566
|
+
// Create directory structure
|
|
567
|
+
mkdirSync(projectDir, { recursive: true });
|
|
568
|
+
mkdirSync(join(projectDir, 'src'), { recursive: true });
|
|
569
|
+
mkdirSync(join(projectDir, 'src/hooks'), { recursive: true });
|
|
570
|
+
mkdirSync(join(projectDir, 'src/components'), { recursive: true });
|
|
571
|
+
|
|
572
|
+
// Create package.json
|
|
573
|
+
const packageJson = {
|
|
574
|
+
name: projectName,
|
|
575
|
+
version: '1.0.0',
|
|
576
|
+
type: 'module',
|
|
577
|
+
scripts: {
|
|
578
|
+
dev: 'vite',
|
|
579
|
+
build: 'vite build',
|
|
580
|
+
preview: 'vite preview'
|
|
581
|
+
},
|
|
582
|
+
dependencies: {
|
|
583
|
+
'mycelia-kernel-plugin': '^1.2.0',
|
|
584
|
+
'vue': '^3.4.0'
|
|
585
|
+
},
|
|
586
|
+
devDependencies: {
|
|
587
|
+
'@vitejs/plugin-vue': '^5.0.0',
|
|
588
|
+
'vite': '^5.0.0'
|
|
589
|
+
}
|
|
590
|
+
};
|
|
591
|
+
|
|
592
|
+
writeFileSync(
|
|
593
|
+
join(projectDir, 'package.json'),
|
|
594
|
+
JSON.stringify(packageJson, null, 2),
|
|
595
|
+
'utf8'
|
|
596
|
+
);
|
|
597
|
+
|
|
598
|
+
// Create vite.config.js
|
|
599
|
+
const viteConfig = `import { defineConfig } from 'vite';
|
|
600
|
+
import vue from '@vitejs/plugin-vue';
|
|
601
|
+
|
|
602
|
+
export default defineConfig({
|
|
603
|
+
plugins: [vue()],
|
|
604
|
+
});
|
|
605
|
+
`;
|
|
606
|
+
|
|
607
|
+
writeFileSync(join(projectDir, 'vite.config.js'), viteConfig, 'utf8');
|
|
608
|
+
|
|
609
|
+
// Create index.html
|
|
610
|
+
const indexHtml = `<!DOCTYPE html>
|
|
611
|
+
<html lang="en">
|
|
612
|
+
<head>
|
|
613
|
+
<meta charset="UTF-8" />
|
|
614
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
615
|
+
<title>${projectName}</title>
|
|
616
|
+
</head>
|
|
617
|
+
<body>
|
|
618
|
+
<div id="app"></div>
|
|
619
|
+
<script type="module" src="/src/main.js"></script>
|
|
620
|
+
</body>
|
|
621
|
+
</html>
|
|
622
|
+
`;
|
|
623
|
+
|
|
624
|
+
writeFileSync(join(projectDir, 'index.html'), indexHtml, 'utf8');
|
|
625
|
+
|
|
626
|
+
// Create main.js
|
|
627
|
+
const mainJs = `import { createApp } from 'vue';
|
|
628
|
+
import { MyceliaPlugin } from 'mycelia-kernel-plugin/vue';
|
|
629
|
+
import { useBase } from 'mycelia-kernel-plugin';
|
|
630
|
+
import App from './App.vue';
|
|
631
|
+
|
|
632
|
+
const buildSystem = () =>
|
|
633
|
+
useBase('${projectName}')
|
|
634
|
+
.build();
|
|
635
|
+
|
|
636
|
+
const app = createApp(App);
|
|
637
|
+
app.use(MyceliaPlugin, { build: buildSystem });
|
|
638
|
+
app.mount('#app');
|
|
639
|
+
`;
|
|
640
|
+
|
|
641
|
+
writeFileSync(join(projectDir, 'src/main.js'), mainJs, 'utf8');
|
|
642
|
+
|
|
643
|
+
// Create App.vue
|
|
644
|
+
const appVue = `<template>
|
|
645
|
+
<div>
|
|
646
|
+
<h1>${projectName}</h1>
|
|
647
|
+
<p>System: {{ system?.name }}</p>
|
|
648
|
+
</div>
|
|
649
|
+
</template>
|
|
650
|
+
|
|
651
|
+
<script setup>
|
|
652
|
+
import { useMycelia } from 'mycelia-kernel-plugin/vue';
|
|
653
|
+
|
|
654
|
+
const system = useMycelia();
|
|
655
|
+
</script>
|
|
656
|
+
`;
|
|
657
|
+
|
|
658
|
+
writeFileSync(join(projectDir, 'src/App.vue'), appVue, 'utf8');
|
|
659
|
+
|
|
660
|
+
// Create README.md
|
|
661
|
+
const readme = `# ${projectName}
|
|
662
|
+
|
|
663
|
+
A Vue 3 application built with Mycelia Plugin System.
|
|
664
|
+
|
|
665
|
+
## Getting Started
|
|
666
|
+
|
|
667
|
+
\`\`\`bash
|
|
668
|
+
npm install
|
|
669
|
+
npm run dev
|
|
670
|
+
\`\`\`
|
|
671
|
+
|
|
672
|
+
## Creating Plugins
|
|
673
|
+
|
|
674
|
+
Use the CLI to scaffold new plugins:
|
|
675
|
+
|
|
676
|
+
\`\`\`bash
|
|
677
|
+
npx mycelia-kernel-plugin create hook my-plugin
|
|
678
|
+
\`\`\`
|
|
679
|
+
|
|
680
|
+
## Structure
|
|
681
|
+
|
|
682
|
+
- \`src/hooks/\` - Plugin hooks
|
|
683
|
+
- \`src/components/\` - Vue components
|
|
684
|
+
- \`src/App.vue\` - Main app component
|
|
685
|
+
- \`src/main.js\` - Entry point
|
|
686
|
+
`;
|
|
687
|
+
|
|
688
|
+
writeFileSync(join(projectDir, 'README.md'), readme, 'utf8');
|
|
689
|
+
|
|
690
|
+
// Create .gitignore
|
|
691
|
+
const gitignore = `node_modules/
|
|
692
|
+
dist/
|
|
693
|
+
*.log
|
|
694
|
+
.DS_Store
|
|
695
|
+
`;
|
|
696
|
+
|
|
697
|
+
writeFileSync(join(projectDir, '.gitignore'), gitignore, 'utf8');
|
|
698
|
+
|
|
699
|
+
console.log(`✅ Vue project created: ${projectDir}`);
|
|
700
|
+
console.log(`\nNext steps:`);
|
|
701
|
+
console.log(` cd ${projectDir}`);
|
|
702
|
+
console.log(` npm install`);
|
|
703
|
+
console.log(` npm run dev`);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Initialize a Svelte project with Mycelia bindings
|
|
708
|
+
*/
|
|
709
|
+
function initSvelteProject(projectName) {
|
|
710
|
+
const projectDir = projectName;
|
|
711
|
+
|
|
712
|
+
if (existsSync(projectDir)) {
|
|
713
|
+
console.error(`Error: Directory already exists: ${projectDir}`);
|
|
714
|
+
process.exit(1);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
console.log(`Creating Svelte project: ${projectName}...`);
|
|
718
|
+
|
|
719
|
+
// Create directory structure
|
|
720
|
+
mkdirSync(projectDir, { recursive: true });
|
|
721
|
+
mkdirSync(join(projectDir, 'src'), { recursive: true });
|
|
722
|
+
mkdirSync(join(projectDir, 'src/hooks'), { recursive: true });
|
|
723
|
+
mkdirSync(join(projectDir, 'src/components'), { recursive: true });
|
|
724
|
+
|
|
725
|
+
// Create package.json
|
|
726
|
+
const packageJson = {
|
|
727
|
+
name: projectName,
|
|
728
|
+
version: '1.0.0',
|
|
729
|
+
type: 'module',
|
|
730
|
+
scripts: {
|
|
731
|
+
dev: 'vite dev',
|
|
732
|
+
build: 'vite build',
|
|
733
|
+
preview: 'vite preview'
|
|
734
|
+
},
|
|
735
|
+
dependencies: {
|
|
736
|
+
'mycelia-kernel-plugin': '^1.2.0',
|
|
737
|
+
'svelte': '^4.2.0'
|
|
738
|
+
},
|
|
739
|
+
devDependencies: {
|
|
740
|
+
'@sveltejs/vite-plugin-svelte': '^3.0.0',
|
|
741
|
+
'vite': '^5.0.0'
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
|
|
745
|
+
writeFileSync(
|
|
746
|
+
join(projectDir, 'package.json'),
|
|
747
|
+
JSON.stringify(packageJson, null, 2),
|
|
748
|
+
'utf8'
|
|
749
|
+
);
|
|
750
|
+
|
|
751
|
+
// Create vite.config.js
|
|
752
|
+
const viteConfig = `import { defineConfig } from 'vite';
|
|
753
|
+
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
|
754
|
+
|
|
755
|
+
export default defineConfig({
|
|
756
|
+
plugins: [svelte()],
|
|
757
|
+
});
|
|
758
|
+
`;
|
|
759
|
+
|
|
760
|
+
writeFileSync(join(projectDir, 'vite.config.js'), viteConfig, 'utf8');
|
|
761
|
+
|
|
762
|
+
// Create svelte.config.js
|
|
763
|
+
const svelteConfig = `import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
|
764
|
+
|
|
765
|
+
export default {
|
|
766
|
+
preprocess: vitePreprocess(),
|
|
767
|
+
};
|
|
768
|
+
`;
|
|
769
|
+
|
|
770
|
+
writeFileSync(join(projectDir, 'svelte.config.js'), svelteConfig, 'utf8');
|
|
771
|
+
|
|
772
|
+
// Create index.html
|
|
773
|
+
const indexHtml = `<!DOCTYPE html>
|
|
774
|
+
<html lang="en">
|
|
775
|
+
<head>
|
|
776
|
+
<meta charset="UTF-8" />
|
|
777
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
778
|
+
<title>${projectName}</title>
|
|
779
|
+
</head>
|
|
780
|
+
<body>
|
|
781
|
+
<div id="app"></div>
|
|
782
|
+
<script type="module" src="/src/main.js"></script>
|
|
783
|
+
</body>
|
|
784
|
+
</html>
|
|
785
|
+
`;
|
|
786
|
+
|
|
787
|
+
writeFileSync(join(projectDir, 'index.html'), indexHtml, 'utf8');
|
|
788
|
+
|
|
789
|
+
// Create main.js
|
|
790
|
+
const mainJs = `import App from './App.svelte';
|
|
791
|
+
|
|
792
|
+
const app = new App({
|
|
793
|
+
target: document.getElementById('app'),
|
|
794
|
+
});
|
|
795
|
+
|
|
796
|
+
export default app;
|
|
797
|
+
`;
|
|
798
|
+
|
|
799
|
+
writeFileSync(join(projectDir, 'src/main.js'), mainJs, 'utf8');
|
|
800
|
+
|
|
801
|
+
// Create App.svelte
|
|
802
|
+
const appSvelte = `<script>
|
|
803
|
+
import { onMount } from 'svelte';
|
|
804
|
+
import { setMyceliaSystem, useMycelia } from 'mycelia-kernel-plugin/svelte';
|
|
805
|
+
import { useBase } from 'mycelia-kernel-plugin';
|
|
806
|
+
|
|
807
|
+
let system;
|
|
808
|
+
|
|
809
|
+
onMount(async () => {
|
|
810
|
+
system = await useBase('${projectName}').build();
|
|
811
|
+
setMyceliaSystem(system);
|
|
812
|
+
});
|
|
813
|
+
|
|
814
|
+
const systemStore = useMycelia();
|
|
815
|
+
$: currentSystem = $systemStore;
|
|
816
|
+
</script>
|
|
817
|
+
|
|
818
|
+
<div>
|
|
819
|
+
<h1>${projectName}</h1>
|
|
820
|
+
{#if currentSystem}
|
|
821
|
+
<p>System: {currentSystem.name}</p>
|
|
822
|
+
{:else}
|
|
823
|
+
<p>Loading system...</p>
|
|
824
|
+
{/if}
|
|
825
|
+
</div>
|
|
826
|
+
`;
|
|
827
|
+
|
|
828
|
+
writeFileSync(join(projectDir, 'src/App.svelte'), appSvelte, 'utf8');
|
|
829
|
+
|
|
830
|
+
// Create README.md
|
|
831
|
+
const readme = `# ${projectName}
|
|
832
|
+
|
|
833
|
+
A Svelte application built with Mycelia Plugin System.
|
|
834
|
+
|
|
835
|
+
## Getting Started
|
|
836
|
+
|
|
837
|
+
\`\`\`bash
|
|
838
|
+
npm install
|
|
839
|
+
npm run dev
|
|
840
|
+
\`\`\`
|
|
841
|
+
|
|
842
|
+
## Creating Plugins
|
|
843
|
+
|
|
844
|
+
Use the CLI to scaffold new plugins:
|
|
845
|
+
|
|
846
|
+
\`\`\`bash
|
|
847
|
+
npx mycelia-kernel-plugin create hook my-plugin
|
|
848
|
+
\`\`\`
|
|
849
|
+
|
|
850
|
+
## Structure
|
|
851
|
+
|
|
852
|
+
- \`src/hooks/\` - Plugin hooks
|
|
853
|
+
- \`src/components/\` - Svelte components
|
|
854
|
+
- \`src/App.svelte\` - Main app component
|
|
855
|
+
- \`src/main.js\` - Entry point
|
|
856
|
+
`;
|
|
857
|
+
|
|
858
|
+
writeFileSync(join(projectDir, 'README.md'), readme, 'utf8');
|
|
859
|
+
|
|
860
|
+
// Create .gitignore
|
|
861
|
+
const gitignore = `node_modules/
|
|
862
|
+
dist/
|
|
863
|
+
*.log
|
|
864
|
+
.DS_Store
|
|
865
|
+
`;
|
|
866
|
+
|
|
867
|
+
writeFileSync(join(projectDir, '.gitignore'), gitignore, 'utf8');
|
|
868
|
+
|
|
869
|
+
console.log(`✅ Svelte project created: ${projectDir}`);
|
|
870
|
+
console.log(`\nNext steps:`);
|
|
871
|
+
console.log(` cd ${projectDir}`);
|
|
872
|
+
console.log(` npm install`);
|
|
873
|
+
console.log(` npm run dev`);
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* Initialize an Angular project with Mycelia bindings
|
|
878
|
+
*/
|
|
879
|
+
function initAngularProject(projectName) {
|
|
880
|
+
const projectDir = projectName;
|
|
881
|
+
|
|
882
|
+
if (existsSync(projectDir)) {
|
|
883
|
+
console.error(`Error: Directory already exists: ${projectDir}`);
|
|
884
|
+
process.exit(1);
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
console.log(`Creating Angular project: ${projectName}...`);
|
|
888
|
+
console.log(`\nNote: This creates a basic Angular project structure.`);
|
|
889
|
+
console.log(`You may need to run 'ng new' separately for a full Angular CLI setup.`);
|
|
890
|
+
|
|
891
|
+
// Create directory structure
|
|
892
|
+
mkdirSync(projectDir, { recursive: true });
|
|
893
|
+
mkdirSync(join(projectDir, 'src'), { recursive: true });
|
|
894
|
+
mkdirSync(join(projectDir, 'src/app'), { recursive: true });
|
|
895
|
+
mkdirSync(join(projectDir, 'src/app/services'), { recursive: true });
|
|
896
|
+
mkdirSync(join(projectDir, 'src/app/components'), { recursive: true });
|
|
897
|
+
mkdirSync(join(projectDir, 'src/mycelia'), { recursive: true });
|
|
898
|
+
|
|
899
|
+
// Create package.json
|
|
900
|
+
const packageJson = {
|
|
901
|
+
name: projectName,
|
|
902
|
+
version: '1.0.0',
|
|
903
|
+
type: 'module',
|
|
904
|
+
scripts: {
|
|
905
|
+
start: 'ng serve',
|
|
906
|
+
build: 'ng build',
|
|
907
|
+
test: 'ng test'
|
|
908
|
+
},
|
|
909
|
+
dependencies: {
|
|
910
|
+
'mycelia-kernel-plugin': '^1.3.0',
|
|
911
|
+
'@angular/core': '^17.0.0',
|
|
912
|
+
'@angular/common': '^17.0.0',
|
|
913
|
+
'rxjs': '^7.8.0'
|
|
914
|
+
},
|
|
915
|
+
devDependencies: {
|
|
916
|
+
'@angular/cli': '^17.0.0',
|
|
917
|
+
'@angular/compiler-cli': '^17.0.0',
|
|
918
|
+
'typescript': '^5.0.0'
|
|
919
|
+
}
|
|
920
|
+
};
|
|
921
|
+
|
|
922
|
+
writeFileSync(
|
|
923
|
+
join(projectDir, 'package.json'),
|
|
924
|
+
JSON.stringify(packageJson, null, 2),
|
|
925
|
+
'utf8'
|
|
926
|
+
);
|
|
927
|
+
|
|
928
|
+
// Create Mycelia service
|
|
929
|
+
const myceliaService = `import { Injectable } from '@angular/core';
|
|
930
|
+
import { BehaviorSubject, Observable } from 'rxjs';
|
|
931
|
+
import { createMyceliaService } from 'mycelia-kernel-plugin/angular';
|
|
932
|
+
import { buildSystem } from '../mycelia/system.builder.js';
|
|
933
|
+
|
|
934
|
+
@Injectable({ providedIn: 'root' })
|
|
935
|
+
export class MyceliaService {
|
|
936
|
+
private service = createMyceliaService(buildSystem);
|
|
937
|
+
|
|
938
|
+
get system$(): Observable<any> {
|
|
939
|
+
return this.service.system$;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
getSystem() {
|
|
943
|
+
return this.service.getSystem();
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
useFacet(kind: string) {
|
|
947
|
+
return this.service.useFacet(kind);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
useListener(eventName: string, handler: Function) {
|
|
951
|
+
return this.service.useListener(eventName, handler);
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
async dispose() {
|
|
955
|
+
await this.service.dispose();
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
`;
|
|
959
|
+
|
|
960
|
+
writeFileSync(join(projectDir, 'src/app/services/mycelia.service.ts'), myceliaService, 'utf8');
|
|
961
|
+
|
|
962
|
+
// Create system builder
|
|
963
|
+
const systemBuilder = `import { useBase } from 'mycelia-kernel-plugin';
|
|
964
|
+
import { useListeners } from 'mycelia-kernel-plugin';
|
|
965
|
+
|
|
966
|
+
export async function buildSystem() {
|
|
967
|
+
return useBase('${projectName}')
|
|
968
|
+
.use(useListeners)
|
|
969
|
+
.build();
|
|
970
|
+
}
|
|
971
|
+
`;
|
|
972
|
+
|
|
973
|
+
writeFileSync(join(projectDir, 'src/mycelia/system.builder.ts'), systemBuilder, 'utf8');
|
|
974
|
+
|
|
975
|
+
// Create README
|
|
976
|
+
const readme = `# ${projectName}
|
|
977
|
+
|
|
978
|
+
An Angular application built with Mycelia Plugin System.
|
|
979
|
+
|
|
980
|
+
## Getting Started
|
|
981
|
+
|
|
982
|
+
\`\`\`bash
|
|
983
|
+
npm install
|
|
984
|
+
ng serve
|
|
985
|
+
\`\`\`
|
|
986
|
+
|
|
987
|
+
## Structure
|
|
988
|
+
|
|
989
|
+
- \`src/app/services/\` - Angular services (including MyceliaService)
|
|
990
|
+
- \`src/app/components/\` - Angular components
|
|
991
|
+
- \`src/mycelia/\` - Mycelia plugin code (framework-agnostic)
|
|
992
|
+
`;
|
|
993
|
+
|
|
994
|
+
writeFileSync(join(projectDir, 'README.md'), readme, 'utf8');
|
|
995
|
+
|
|
996
|
+
console.log(`✅ Angular project created: ${projectDir}`);
|
|
997
|
+
console.log(`\nNext steps:`);
|
|
998
|
+
console.log(` cd ${projectDir}`);
|
|
999
|
+
console.log(` npm install`);
|
|
1000
|
+
console.log(` ng serve`);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
/**
|
|
1004
|
+
* Initialize a Qwik project with Mycelia bindings
|
|
1005
|
+
*/
|
|
1006
|
+
function initQwikProject(projectName) {
|
|
1007
|
+
const projectDir = projectName;
|
|
1008
|
+
|
|
1009
|
+
if (existsSync(projectDir)) {
|
|
1010
|
+
console.error(`Error: Directory already exists: ${projectDir}`);
|
|
1011
|
+
process.exit(1);
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
console.log(`Creating Qwik project: ${projectName}...`);
|
|
1015
|
+
|
|
1016
|
+
// Create directory structure
|
|
1017
|
+
mkdirSync(projectDir, { recursive: true });
|
|
1018
|
+
mkdirSync(join(projectDir, 'src'), { recursive: true });
|
|
1019
|
+
mkdirSync(join(projectDir, 'src/components'), { recursive: true });
|
|
1020
|
+
mkdirSync(join(projectDir, 'src/mycelia'), { recursive: true });
|
|
1021
|
+
|
|
1022
|
+
// Create package.json
|
|
1023
|
+
const packageJson = {
|
|
1024
|
+
name: projectName,
|
|
1025
|
+
version: '1.0.0',
|
|
1026
|
+
type: 'module',
|
|
1027
|
+
scripts: {
|
|
1028
|
+
dev: 'vite',
|
|
1029
|
+
build: 'vite build',
|
|
1030
|
+
preview: 'vite preview'
|
|
1031
|
+
},
|
|
1032
|
+
dependencies: {
|
|
1033
|
+
'mycelia-kernel-plugin': '^1.3.0',
|
|
1034
|
+
'@builder.io/qwik': '^1.0.0',
|
|
1035
|
+
'@builder.io/qwik-city': '^1.0.0'
|
|
1036
|
+
},
|
|
1037
|
+
devDependencies: {
|
|
1038
|
+
'vite': '^5.0.0',
|
|
1039
|
+
'@vitejs/plugin-qwik': '^1.0.0'
|
|
1040
|
+
}
|
|
1041
|
+
};
|
|
1042
|
+
|
|
1043
|
+
writeFileSync(
|
|
1044
|
+
join(projectDir, 'package.json'),
|
|
1045
|
+
JSON.stringify(packageJson, null, 2),
|
|
1046
|
+
'utf8'
|
|
1047
|
+
);
|
|
1048
|
+
|
|
1049
|
+
// Create App component
|
|
1050
|
+
const appComponent = `import { component$ } from '@builder.io/qwik';
|
|
1051
|
+
import { MyceliaProvider } from 'mycelia-kernel-plugin/qwik';
|
|
1052
|
+
import { buildSystem } from './mycelia/system.builder.js';
|
|
1053
|
+
import { TodoApp } from './components/TodoApp';
|
|
1054
|
+
|
|
1055
|
+
export default component$(() => {
|
|
1056
|
+
return (
|
|
1057
|
+
<MyceliaProvider build={buildSystem}>
|
|
1058
|
+
<TodoApp />
|
|
1059
|
+
</MyceliaProvider>
|
|
1060
|
+
);
|
|
1061
|
+
});
|
|
1062
|
+
`;
|
|
1063
|
+
|
|
1064
|
+
writeFileSync(join(projectDir, 'src/App.tsx'), appComponent, 'utf8');
|
|
1065
|
+
|
|
1066
|
+
// Create system builder
|
|
1067
|
+
const systemBuilder = `import { useBase } from 'mycelia-kernel-plugin';
|
|
1068
|
+
import { useListeners } from 'mycelia-kernel-plugin';
|
|
1069
|
+
|
|
1070
|
+
export async function buildSystem() {
|
|
1071
|
+
return useBase('${projectName}')
|
|
1072
|
+
.use(useListeners)
|
|
1073
|
+
.build();
|
|
1074
|
+
}
|
|
1075
|
+
`;
|
|
1076
|
+
|
|
1077
|
+
writeFileSync(join(projectDir, 'src/mycelia/system.builder.ts'), systemBuilder, 'utf8');
|
|
1078
|
+
|
|
1079
|
+
// Create example component
|
|
1080
|
+
const todoComponent = `import { component$ } from '@builder.io/qwik';
|
|
1081
|
+
import { useFacet, useListener } from 'mycelia-kernel-plugin/qwik';
|
|
1082
|
+
|
|
1083
|
+
export const TodoApp = component$(() => {
|
|
1084
|
+
const todos = useFacet('todos');
|
|
1085
|
+
useListener('todos:changed', (msg) => {
|
|
1086
|
+
console.log('Todos changed:', msg.body);
|
|
1087
|
+
});
|
|
1088
|
+
|
|
1089
|
+
return (
|
|
1090
|
+
<div>
|
|
1091
|
+
<h1>Todo App</h1>
|
|
1092
|
+
{todos.value && <p>Todos facet loaded</p>}
|
|
1093
|
+
</div>
|
|
1094
|
+
);
|
|
1095
|
+
});
|
|
1096
|
+
`;
|
|
1097
|
+
|
|
1098
|
+
writeFileSync(join(projectDir, 'src/components/TodoApp.tsx'), todoComponent, 'utf8');
|
|
1099
|
+
|
|
1100
|
+
// Create README
|
|
1101
|
+
const readme = `# ${projectName}
|
|
1102
|
+
|
|
1103
|
+
A Qwik application built with Mycelia Plugin System.
|
|
1104
|
+
|
|
1105
|
+
## Getting Started
|
|
1106
|
+
|
|
1107
|
+
\`\`\`bash
|
|
1108
|
+
npm install
|
|
1109
|
+
npm run dev
|
|
1110
|
+
\`\`\`
|
|
1111
|
+
|
|
1112
|
+
## Structure
|
|
1113
|
+
|
|
1114
|
+
- \`src/components/\` - Qwik components
|
|
1115
|
+
- \`src/mycelia/\` - Mycelia plugin code (framework-agnostic)
|
|
1116
|
+
`;
|
|
1117
|
+
|
|
1118
|
+
writeFileSync(join(projectDir, 'README.md'), readme, 'utf8');
|
|
1119
|
+
|
|
1120
|
+
console.log(`✅ Qwik project created: ${projectDir}`);
|
|
1121
|
+
console.log(`\nNext steps:`);
|
|
1122
|
+
console.log(` cd ${projectDir}`);
|
|
1123
|
+
console.log(` npm install`);
|
|
1124
|
+
console.log(` npm run dev`);
|
|
1125
|
+
}
|
|
1126
|
+
|
|
371
1127
|
/**
|
|
372
1128
|
* Show help message
|
|
373
1129
|
*/
|
|
@@ -381,13 +1137,23 @@ Usage:
|
|
|
381
1137
|
Commands:
|
|
382
1138
|
create hook <name> Create a new hook file
|
|
383
1139
|
create contract <name> Create a new contract file
|
|
384
|
-
init [name] Initialize a new project
|
|
1140
|
+
init [name] Initialize a new project (vanilla JS)
|
|
1141
|
+
init react [name] Initialize a React project with Mycelia bindings
|
|
1142
|
+
init vue [name] Initialize a Vue 3 project with Mycelia bindings
|
|
1143
|
+
init svelte [name] Initialize a Svelte project with Mycelia bindings
|
|
1144
|
+
init angular [name] Initialize an Angular project with Mycelia bindings
|
|
1145
|
+
init qwik [name] Initialize a Qwik project with Mycelia bindings
|
|
385
1146
|
help Show this help message
|
|
386
1147
|
|
|
387
1148
|
Examples:
|
|
388
1149
|
mycelia-kernel-plugin create hook database
|
|
389
1150
|
mycelia-kernel-plugin create contract database
|
|
390
1151
|
mycelia-kernel-plugin init my-app
|
|
1152
|
+
mycelia-kernel-plugin init react my-react-app
|
|
1153
|
+
mycelia-kernel-plugin init vue my-vue-app
|
|
1154
|
+
mycelia-kernel-plugin init svelte my-svelte-app
|
|
1155
|
+
mycelia-kernel-plugin init angular my-angular-app
|
|
1156
|
+
mycelia-kernel-plugin init qwik my-qwik-app
|
|
391
1157
|
|
|
392
1158
|
For more information, visit:
|
|
393
1159
|
https://github.com/lesfleursdelanuitdev/mycelia-kernel-plugin-system
|