@ultrst-armada/krnl 1.0.2 → 1.0.4
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 +67 -65
- package/package.json +15 -8
- package/packages/cli/dist/bin/krnl.cjs +808 -331
- package/packages/cli/dist/bin/krnl.js +50 -65
- package/packages/cli/dist/chunk-GHWYEAPD.js +1642 -0
- package/packages/cli/dist/index.cjs +761 -263
- package/packages/cli/dist/index.d.cts +45 -2
- package/packages/cli/dist/index.d.ts +45 -2
- package/packages/cli/dist/index.js +5 -1
- package/packages/cli/package.json +17 -10
- package/packages/core/dist/index.cjs +2912 -140
- package/packages/core/dist/index.d.cts +614 -27
- package/packages/core/dist/index.d.ts +614 -27
- package/packages/core/dist/index.js +2903 -140
- package/packages/core/package.json +15 -6
- package/packages/create-krnl/dist/index.cjs +102 -65
- package/packages/create-krnl/dist/index.js +102 -65
- package/packages/create-krnl/package.json +5 -3
- package/packages/eslint-plugin/dist/index.cjs +17 -55
- package/packages/eslint-plugin/dist/index.d.cts +8 -43
- package/packages/eslint-plugin/dist/index.d.ts +8 -43
- package/packages/eslint-plugin/dist/index.js +17 -55
- package/packages/eslint-plugin/package.json +5 -4
- package/packages/validate/dist/index.cjs +378 -85
- package/packages/validate/dist/index.d.cts +11 -1
- package/packages/validate/dist/index.d.ts +11 -1
- package/packages/validate/dist/index.js +375 -82
- package/packages/validate/package.json +14 -7
- package/packages/cli/dist/K_ENT_Entity-PQ5MURQY-ZG6FZXXX.js +0 -13
- package/packages/cli/dist/K_LIB_Krnl_Aiko_Client-OPZAVZCW-K4CRQYA5.js +0 -8
- package/packages/cli/dist/K_LIB_Krnl_Ep_Tools-ROOE2TQF-LNPXZYOE.js +0 -110
- package/packages/cli/dist/K_LIB_Krnl_Frontend_Builder-2ZDUH6PF-3ALZPNX4.js +0 -11
- package/packages/cli/dist/K_LIB_Krnl_Frontend_Generator-UYNRNX2X-PJTICYSW.js +0 -11
- package/packages/cli/dist/K_LIB_Krnl_Registry_Client-NXV6D2QW-M5TYU55O.js +0 -8
- package/packages/cli/dist/K_LIB_Krnl_SubApp_Engine-7HR5HWW2-H6STOXRK.js +0 -20
- package/packages/cli/dist/K_LIB_Krnl_SubApp_Registry-7XYGDKJK-XPJXSF7D.js +0 -19
- package/packages/cli/dist/K_LIB_Krnl_SubApp_Worker_Host-CQVTGGG7-CUYGTWOW.js +0 -7
- package/packages/cli/dist/K_LIB_Krnl_System_App_Adapter-M6FJKLGU-VR6T4N6J.js +0 -17
- package/packages/cli/dist/K_LIB_Krnl_System_Base_Functionality_APIs-ZZUZ6ZG5-RLJ4QWDP.js +0 -58
- package/packages/cli/dist/K_LIB_Krnl_System_Magnetic_Loader-XBQO2KXF-BOQGUASC.js +0 -22
- package/packages/cli/dist/K_LIB_Krnl_System_Unified_Http_Adapter-RCEGP3OG-XJI7KIT5.js +0 -8
- package/packages/cli/dist/K_LIB_Krnl_Telemetry-77FRZ3KV-K5VCWAFW.js +0 -9
- package/packages/cli/dist/chunk-3TRM6CYL.js +0 -152
- package/packages/cli/dist/chunk-5JDK35TG.js +0 -3872
- package/packages/cli/dist/chunk-63PTK33I.js +0 -997
- package/packages/cli/dist/chunk-6NIKAMUZ.js +0 -82
- package/packages/cli/dist/chunk-BOXWWXQG.js +0 -400
- package/packages/cli/dist/chunk-EEKLK7QJ.js +0 -565
- package/packages/cli/dist/chunk-EG7T2IAD.js +0 -107
- package/packages/cli/dist/chunk-ESTKOQ7T.js +0 -1146
- package/packages/cli/dist/chunk-F5EHXE2O.js +0 -1036
- package/packages/cli/dist/chunk-F65ANSQG.js +0 -269
- package/packages/cli/dist/chunk-FDNCADFE.js +0 -71
- package/packages/cli/dist/chunk-FZ6X7PHR.js +0 -1146
- package/packages/cli/dist/chunk-GDLRMDAN.js +0 -127
- package/packages/cli/dist/chunk-HWMTCMOS.js +0 -656
- package/packages/cli/dist/chunk-I74QIQOD.js +0 -5536
- package/packages/cli/dist/chunk-JTLSTO25.js +0 -71
- package/packages/cli/dist/chunk-JULBBJ27.js +0 -1033
- package/packages/cli/dist/chunk-OHVMVRBP.js +0 -117
- package/packages/cli/dist/chunk-P2PCLEKX.js +0 -666
- package/packages/cli/dist/chunk-PJQIUOX2.js +0 -7767
- package/packages/cli/dist/chunk-PPOF3DJW.js +0 -471
- package/packages/cli/dist/chunk-Q45257P6.js +0 -173
- package/packages/cli/dist/chunk-QNROWGBI.js +0 -1036
- package/packages/cli/dist/chunk-RJNYUXZD.js +0 -977
- package/packages/cli/dist/chunk-SRTOPJ5W.js +0 -104
- package/packages/cli/dist/chunk-TCEX3MPS.js +0 -702
- package/packages/cli/dist/chunk-TNOAJO2J.js +0 -675
- package/packages/cli/dist/chunk-UR2SUCSF.js +0 -701
- package/packages/cli/dist/chunk-X5LOIFM7.js +0 -68
- package/packages/cli/dist/chunk-XIRFOO3H.js +0 -589
- package/packages/cli/dist/chunk-ZAAV3JXQ.js +0 -809
- package/packages/core/dist/K_ENT_Entity-4MB7CU4A.js +0 -12
- package/packages/core/dist/K_ENT_Entity-DEJGIDGH.js +0 -12
- package/packages/core/dist/K_ENT_Entity-FXZO5UZ2.js +0 -12
- package/packages/core/dist/K_ENT_Entity-HDSCXC5F.js +0 -12
- package/packages/core/dist/K_ENT_Entity-JILABHLW.js +0 -12
- package/packages/core/dist/K_ENT_Entity-PQ5MURQY.js +0 -13
- package/packages/core/dist/K_ENT_Entity-ROAKDIHW.js +0 -12
- package/packages/core/dist/K_ENT_Entity-TBVFSKDV.js +0 -12
- package/packages/core/dist/K_ENT_Entity-ZFLKG3JO.js +0 -12
- package/packages/core/dist/K_LIB_Krnl_Aiko_Client-OPZAVZCW.js +0 -8
- package/packages/core/dist/K_LIB_Krnl_Ep_Tools-ROOE2TQF.js +0 -110
- package/packages/core/dist/K_LIB_Krnl_Frontend_Builder-2ZDUH6PF.js +0 -9
- package/packages/core/dist/K_LIB_Krnl_Frontend_Generator-UYNRNX2X.js +0 -9
- package/packages/core/dist/K_LIB_Krnl_Registry_Client-NXV6D2QW.js +0 -8
- package/packages/core/dist/K_LIB_Krnl_SubApp_Engine-7HR5HWW2.js +0 -20
- package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-4C6GBQAG.js +0 -18
- package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-6V23A6F6.js +0 -18
- package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-7XYGDKJK.js +0 -19
- package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-DYLLC5G2.js +0 -18
- package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-F4FOFAUP.js +0 -18
- package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-FBOXXMI3.js +0 -18
- package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-Q73BWLNP.js +0 -18
- package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-QM2C4MVA.js +0 -18
- package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-QUGI6SMP.js +0 -18
- package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-RGMTBHNP.js +0 -18
- package/packages/core/dist/K_LIB_Krnl_SubApp_Registry-RWR7UNDW.js +0 -18
- package/packages/core/dist/K_LIB_Krnl_SubApp_Worker_Host-CQVTGGG7.js +0 -7
- package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-32MFJJ5Z.js +0 -17
- package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-4J4CEWRY.js +0 -17
- package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-A366YHF2.js +0 -17
- package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-LK4LYJHI.js +0 -17
- package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-M6FJKLGU.js +0 -17
- package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-NW3K63II.js +0 -17
- package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-QDHTI5ZV.js +0 -17
- package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-VHCT6VIW.js +0 -17
- package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-WBRKF24R.js +0 -17
- package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-XKYQYT6Q.js +0 -17
- package/packages/core/dist/K_LIB_Krnl_System_App_Adapter-Z2PWZYDZ.js +0 -17
- package/packages/core/dist/K_LIB_Krnl_System_Base_Functionality_APIs-ZZUZ6ZG5.js +0 -58
- package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-2EZU7QF4.js +0 -21
- package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-6G3AQNAV.js +0 -21
- package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-B2NZMQUG.js +0 -21
- package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-C2RABMZP.js +0 -21
- package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-HHE3NZ4F.js +0 -21
- package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-LHFGR6WK.js +0 -21
- package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-M74BLM3N.js +0 -21
- package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-PT6ZA6EA.js +0 -21
- package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-SP52V3CX.js +0 -21
- package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-XBQO2KXF.js +0 -22
- package/packages/core/dist/K_LIB_Krnl_System_Magnetic_Loader-YNSEUHJJ.js +0 -21
- package/packages/core/dist/K_LIB_Krnl_System_Unified_Http_Adapter-M6SBHIVA.js +0 -8
- package/packages/core/dist/K_LIB_Krnl_System_Unified_Http_Adapter-RCEGP3OG.js +0 -8
- package/packages/core/dist/K_LIB_Krnl_Telemetry-77FRZ3KV.js +0 -9
- package/packages/core/dist/chunk-33L2J7V7.js +0 -82
- package/packages/core/dist/chunk-3ES4K2ZP.js +0 -817
- package/packages/core/dist/chunk-3SMHVVLL.js +0 -82
- package/packages/core/dist/chunk-3UEZ7JQA.js +0 -4877
- package/packages/core/dist/chunk-3XIE6KBD.js +0 -4877
- package/packages/core/dist/chunk-46ZLCML6.js +0 -107
- package/packages/core/dist/chunk-4UEL3DWJ.js +0 -107
- package/packages/core/dist/chunk-54GWZ5PC.js +0 -82
- package/packages/core/dist/chunk-6QCYRS5L.js +0 -127
- package/packages/core/dist/chunk-6ULMHNXR.js +0 -104
- package/packages/core/dist/chunk-7WUETJEV.js +0 -117
- package/packages/core/dist/chunk-A5KRAYDB.js +0 -107
- package/packages/core/dist/chunk-ANEAZ3PO.js +0 -107
- package/packages/core/dist/chunk-BE76RL6F.js +0 -82
- package/packages/core/dist/chunk-CIARVYDO.js +0 -107
- package/packages/core/dist/chunk-CR2ANE62.js +0 -107
- package/packages/core/dist/chunk-DI27MOR7.js +0 -173
- package/packages/core/dist/chunk-E6RLFHM5.js +0 -596
- package/packages/core/dist/chunk-EELAPMNV.js +0 -4877
- package/packages/core/dist/chunk-ENZ2RQVJ.js +0 -107
- package/packages/core/dist/chunk-F2U6CX4F.js +0 -4877
- package/packages/core/dist/chunk-FKG64OHL.js +0 -82
- package/packages/core/dist/chunk-FYAZJYM5.js +0 -772
- package/packages/core/dist/chunk-G4NP4RDQ.js +0 -82
- package/packages/core/dist/chunk-GADIRLRS.js +0 -473
- package/packages/core/dist/chunk-GR6CSLQJ.js +0 -772
- package/packages/core/dist/chunk-HDS7AT6O.js +0 -772
- package/packages/core/dist/chunk-HIMEZUU2.js +0 -71
- package/packages/core/dist/chunk-IB4UHG5I.js +0 -596
- package/packages/core/dist/chunk-J7ZYNVRS.js +0 -772
- package/packages/core/dist/chunk-JVLZU4K7.js +0 -604
- package/packages/core/dist/chunk-JYXXI7Q3.js +0 -82
- package/packages/core/dist/chunk-K54K2KZW.js +0 -192
- package/packages/core/dist/chunk-K6VHLBNH.js +0 -3316
- package/packages/core/dist/chunk-KCBP7ZYA.js +0 -596
- package/packages/core/dist/chunk-KFQGP6VL.js +0 -33
- package/packages/core/dist/chunk-KIUEUI7K.js +0 -82
- package/packages/core/dist/chunk-LB67NIZP.js +0 -949
- package/packages/core/dist/chunk-LDTYFUNW.js +0 -596
- package/packages/core/dist/chunk-MLVWARD4.js +0 -596
- package/packages/core/dist/chunk-MPYVXHKO.js +0 -2777
- package/packages/core/dist/chunk-MRQ3MITU.js +0 -772
- package/packages/core/dist/chunk-MVUN7I7O.js +0 -107
- package/packages/core/dist/chunk-NDDOIRW7.js +0 -596
- package/packages/core/dist/chunk-O3KDB5MH.js +0 -3330
- package/packages/core/dist/chunk-OEINUDSE.js +0 -400
- package/packages/core/dist/chunk-OPDENPT4.js +0 -4877
- package/packages/core/dist/chunk-P6XEM2LA.js +0 -429
- package/packages/core/dist/chunk-QKMRSQV4.js +0 -82
- package/packages/core/dist/chunk-R6CCWALL.js +0 -4877
- package/packages/core/dist/chunk-RAMMOO73.js +0 -774
- package/packages/core/dist/chunk-S3FTZFG6.js +0 -772
- package/packages/core/dist/chunk-T2ZVN434.js +0 -4877
- package/packages/core/dist/chunk-TFHLDMIA.js +0 -107
- package/packages/core/dist/chunk-TI3QUCIJ.js +0 -107
- package/packages/core/dist/chunk-TR2BAIGI.js +0 -107
- package/packages/core/dist/chunk-UGVVJKC6.js +0 -4877
- package/packages/core/dist/chunk-V2DX7YIU.js +0 -984
- package/packages/core/dist/chunk-W4IHYUYD.js +0 -772
- package/packages/core/dist/chunk-W6WBG5OY.js +0 -4877
- package/packages/core/dist/chunk-WN3M7O7H.js +0 -3312
- package/packages/core/dist/chunk-WR3NCU7U.js +0 -4877
- package/packages/core/dist/chunk-XC6B6L27.js +0 -82
- package/packages/core/dist/chunk-XNSE64ZY.js +0 -3316
- package/packages/core/dist/chunk-XROES2WN.js +0 -634
- package/packages/core/dist/chunk-XSCKNRCZ.js +0 -5020
- package/packages/core/dist/chunk-XVABPAUZ.js +0 -82
- package/packages/core/dist/chunk-YOBCB5C5.js +0 -596
- package/packages/core/dist/chunk-YUK6Q563.js +0 -666
- package/packages/core/dist/chunk-YXGL3ZEU.js +0 -1030
- package/packages/core/dist/chunk-ZINJ5OUX.js +0 -596
- package/packages/core/dist/chunk-ZPFD4BIQ.js +0 -604
- package/packages/core/dist/chunk-ZQZBFG6F.js +0 -4826
- package/packages/core/dist/chunk-ZZFRJGXM.js +0 -4877
- package/packages/create-krnl/dist/K_ENT_Entity-PQ5MURQY-R2OH4VXE.js +0 -14
- package/packages/create-krnl/dist/K_LIB_Krnl_Aiko_Client-OPZAVZCW-AZM5HF4M.js +0 -9
- package/packages/create-krnl/dist/K_LIB_Krnl_Ep_Tools-ROOE2TQF-X5N6SV2S.js +0 -111
- package/packages/create-krnl/dist/K_LIB_Krnl_Frontend_Builder-2ZDUH6PF-5PFHF4JU.js +0 -12
- package/packages/create-krnl/dist/K_LIB_Krnl_Frontend_Generator-UYNRNX2X-ED33OQPH.js +0 -12
- package/packages/create-krnl/dist/K_LIB_Krnl_Registry_Client-NXV6D2QW-YGQLVR4P.js +0 -9
- package/packages/create-krnl/dist/K_LIB_Krnl_SubApp_Engine-7HR5HWW2-VM7CTU2L.js +0 -21
- package/packages/create-krnl/dist/K_LIB_Krnl_SubApp_Registry-7XYGDKJK-Y2GQFJ7I.js +0 -21
- package/packages/create-krnl/dist/K_LIB_Krnl_SubApp_Worker_Host-CQVTGGG7-L3JQWO54.js +0 -8
- package/packages/create-krnl/dist/K_LIB_Krnl_System_App_Adapter-M6FJKLGU-KQARASPR.js +0 -19
- package/packages/create-krnl/dist/K_LIB_Krnl_System_Base_Functionality_APIs-ZZUZ6ZG5-OF3IGLVL.js +0 -59
- package/packages/create-krnl/dist/K_LIB_Krnl_System_Magnetic_Loader-XBQO2KXF-JOLHKOEX.js +0 -24
- package/packages/create-krnl/dist/K_LIB_Krnl_System_Unified_Http_Adapter-RCEGP3OG-L46LSHKQ.js +0 -10
- package/packages/create-krnl/dist/K_LIB_Krnl_Telemetry-77FRZ3KV-4JUPRR3X.js +0 -10
- package/packages/create-krnl/dist/chunk-3TRM6CYL.js +0 -152
- package/packages/create-krnl/dist/chunk-3URCB3QS.js +0 -127
- package/packages/create-krnl/dist/chunk-5JDK35TG.js +0 -3872
- package/packages/create-krnl/dist/chunk-A2XAXDOW.js +0 -812
- package/packages/create-krnl/dist/chunk-AN6TMQHG.js +0 -1033
- package/packages/create-krnl/dist/chunk-BOXWWXQG.js +0 -400
- package/packages/create-krnl/dist/chunk-BPTBREBG.js +0 -38
- package/packages/create-krnl/dist/chunk-FDNCADFE.js +0 -71
- package/packages/create-krnl/dist/chunk-JTLSTO25.js +0 -71
- package/packages/create-krnl/dist/chunk-M3NCUIPL.js +0 -107
- package/packages/create-krnl/dist/chunk-N2EONSOC.js +0 -7769
- package/packages/create-krnl/dist/chunk-OHVMVRBP.js +0 -117
- package/packages/create-krnl/dist/chunk-Q45257P6.js +0 -173
- package/packages/create-krnl/dist/chunk-QGM4M3NI.js +0 -37
- package/packages/create-krnl/dist/chunk-RJNYUXZD.js +0 -977
- package/packages/create-krnl/dist/chunk-SRTOPJ5W.js +0 -104
- package/packages/create-krnl/dist/chunk-UPBIGEC3.js +0 -666
- package/packages/create-krnl/dist/chunk-V2DB7UD7.js +0 -82
- package/packages/create-krnl/dist/chunk-WMHLIUI6.js +0 -3644
- package/packages/create-krnl/dist/chunk-XIRFOO3H.js +0 -589
- package/packages/create-krnl/dist/chunk-Y2CEEVZP.js +0 -5536
- package/packages/create-krnl/dist/main-DXUMPBND.js +0 -2217
- package/packages/create-krnl/dist/wrapper-SDF2VKX3.js +0 -31
|
@@ -31,6 +31,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
generateMagneticDeclarations: () => generateMagneticDeclarations,
|
|
34
|
+
runBuild: () => runBuild,
|
|
35
|
+
runDev: () => runDev,
|
|
34
36
|
runGenerate: () => runGenerate,
|
|
35
37
|
runValidate: () => runValidate
|
|
36
38
|
});
|
|
@@ -38,20 +40,20 @@ module.exports = __toCommonJS(index_exports);
|
|
|
38
40
|
|
|
39
41
|
// ../validate/dist/index.js
|
|
40
42
|
var fs2 = __toESM(require("fs"), 1);
|
|
41
|
-
var
|
|
43
|
+
var path3 = __toESM(require("path"), 1);
|
|
42
44
|
var import_ts_morph = require("ts-morph");
|
|
43
45
|
var path = __toESM(require("path"), 1);
|
|
44
46
|
var import_ts_morph2 = require("ts-morph");
|
|
45
|
-
var path2 = __toESM(require("path"), 1);
|
|
46
47
|
var import_ts_morph3 = require("ts-morph");
|
|
47
48
|
var fs = __toESM(require("fs"), 1);
|
|
48
|
-
var
|
|
49
|
+
var path2 = __toESM(require("path"), 1);
|
|
49
50
|
var import_ts_morph4 = require("ts-morph");
|
|
51
|
+
var import_ts_morph5 = require("ts-morph");
|
|
50
52
|
function checkFileLimits(sf, options) {
|
|
51
53
|
const errors = [];
|
|
52
54
|
const warnings = [];
|
|
53
55
|
const filePath = sf.getFilePath();
|
|
54
|
-
const sourceText = sf.
|
|
56
|
+
const sourceText = sf.getFullText();
|
|
55
57
|
const lines = sourceText.split("\n");
|
|
56
58
|
if (lines.length > options.maxFileLineLimit) {
|
|
57
59
|
errors.push({
|
|
@@ -162,7 +164,7 @@ function checkComponentRules(sf) {
|
|
|
162
164
|
ruleId: "krnl/helper-purity",
|
|
163
165
|
filePath,
|
|
164
166
|
line: decl.getStartLineNumber(),
|
|
165
|
-
message: `Helper functions (Layer 1) cannot directly import I/O modules ('${spec}'). Delegate to Layer 0 libraries or
|
|
167
|
+
message: `Helper functions (Layer 1) cannot directly import I/O modules ('${spec}'). Delegate to Layer 0 libraries or ServiceFacade context.`,
|
|
166
168
|
severity: "error"
|
|
167
169
|
});
|
|
168
170
|
}
|
|
@@ -170,12 +172,11 @@ function checkComponentRules(sf) {
|
|
|
170
172
|
}
|
|
171
173
|
return { errors, warnings };
|
|
172
174
|
}
|
|
173
|
-
function
|
|
175
|
+
function checkOrchestrationRules(sf) {
|
|
174
176
|
const errors = [];
|
|
175
177
|
const warnings = [];
|
|
176
178
|
const filePath = sf.getFilePath();
|
|
177
179
|
const sourceText = sf.getText();
|
|
178
|
-
const baseName = path2.basename(filePath);
|
|
179
180
|
const calls = sf.getDescendantsOfKind(import_ts_morph3.SyntaxKind.CallExpression);
|
|
180
181
|
for (const call of calls) {
|
|
181
182
|
const exprText = call.getExpression().getText();
|
|
@@ -184,7 +185,7 @@ function checkEntityRules(sf) {
|
|
|
184
185
|
ruleId: "krnl/no-polling",
|
|
185
186
|
filePath,
|
|
186
187
|
line: call.getStartLineNumber(),
|
|
187
|
-
message: `Prohibited use of 'setInterval'. Krnl applications must use reactive event streams
|
|
188
|
+
message: `Prohibited use of 'setInterval'. Krnl applications must use reactive event streams or triggers.`,
|
|
188
189
|
severity: "error"
|
|
189
190
|
});
|
|
190
191
|
}
|
|
@@ -193,65 +194,36 @@ function checkEntityRules(sf) {
|
|
|
193
194
|
const match = sourceText.match(/main\s*=\s*async\s*\([^,]+,\s*\{([^}]*)\}\s*\)/);
|
|
194
195
|
if (match) {
|
|
195
196
|
const destructured = match[1];
|
|
196
|
-
if (/\bsystem\b/.test(destructured)
|
|
197
|
+
if (/\bsystem\b/.test(destructured)) {
|
|
197
198
|
errors.push({
|
|
198
199
|
ruleId: "krnl/context-destructuring",
|
|
199
200
|
filePath,
|
|
200
|
-
message: `Functionality context parameter destructures 'system'. Functionality passes { state,
|
|
201
|
+
message: `Functionality context parameter destructures 'system'. Functionality passes { state, orchestration } or service context.`,
|
|
201
202
|
severity: "error"
|
|
202
203
|
});
|
|
203
204
|
}
|
|
204
205
|
}
|
|
205
206
|
}
|
|
206
|
-
const
|
|
207
|
+
const isOrchestrationClass = sf.getClasses().some((c) => {
|
|
207
208
|
const ext = c.getExtends();
|
|
208
|
-
return ext && (ext.getText().includes("
|
|
209
|
+
return ext && (ext.getText().includes("FunctionalityOrchestration") || ext.getText().includes("Orchestration") || ext.getText().includes("krnlOrchestrationBase"));
|
|
209
210
|
});
|
|
210
|
-
if (
|
|
211
|
+
if (isOrchestrationClass) {
|
|
211
212
|
for (const decl of sf.getImportDeclarations()) {
|
|
212
213
|
const spec = decl.getModuleSpecifierValue();
|
|
213
214
|
if (spec.includes("libraries/") || spec.includes("Concepts")) {
|
|
214
215
|
errors.push({
|
|
215
|
-
ruleId: "krnl/
|
|
216
|
+
ruleId: "krnl/orchestration-no-libraries",
|
|
216
217
|
filePath,
|
|
217
218
|
line: decl.getStartLineNumber(),
|
|
218
|
-
message: `
|
|
219
|
+
message: `FunctionalityOrchestration class violates Library Calling Invariant. FunctionalityOrchestrations must not call or import libraries directly ('${spec}'). Only functionalities are permitted to call shared libraries.`,
|
|
219
220
|
severity: "error"
|
|
220
221
|
});
|
|
221
222
|
}
|
|
222
223
|
}
|
|
223
|
-
let loadAllLine = -1;
|
|
224
|
-
const addLocalLines = [];
|
|
225
|
-
for (const call of calls) {
|
|
226
|
-
const txt = call.getText();
|
|
227
|
-
if (txt.includes("MagneticLoader.loadAll") || txt.includes("KrnlMagneticLoader.loadAll")) {
|
|
228
|
-
loadAllLine = call.getStartLineNumber();
|
|
229
|
-
} else if (txt.startsWith("this.addLocal(")) {
|
|
230
|
-
const hasUiSpec = txt.includes("uiSpec");
|
|
231
|
-
const idMatch = txt.match(/id\s*:\s*["']([^"']+)["']/);
|
|
232
|
-
addLocalLines.push({
|
|
233
|
-
line: call.getStartLineNumber(),
|
|
234
|
-
hasUiSpec,
|
|
235
|
-
id: idMatch ? idMatch[1] : "unknown"
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
if (loadAllLine !== -1) {
|
|
240
|
-
for (const al of addLocalLines) {
|
|
241
|
-
if (al.hasUiSpec && al.line > loadAllLine) {
|
|
242
|
-
errors.push({
|
|
243
|
-
ruleId: "krnl/boot-order",
|
|
244
|
-
filePath,
|
|
245
|
-
line: al.line,
|
|
246
|
-
message: `addLocal('${al.id}') with uiSpec at line ${al.line} appears AFTER loadAll() at line ${loadAllLine}. All addLocal() with UI must precede loadAll().`,
|
|
247
|
-
severity: "error"
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
224
|
for (const cls of sf.getClasses()) {
|
|
253
225
|
const ext = cls.getExtends();
|
|
254
|
-
if (ext && (ext.getText().includes("
|
|
226
|
+
if (ext && (ext.getText().includes("FunctionalityOrchestration") || ext.getText().includes("Orchestration") || ext.getText().includes("krnlOrchestrationBase"))) {
|
|
255
227
|
const loops = [
|
|
256
228
|
...cls.getDescendantsOfKind(import_ts_morph3.SyntaxKind.ForStatement),
|
|
257
229
|
...cls.getDescendantsOfKind(import_ts_morph3.SyntaxKind.ForOfStatement),
|
|
@@ -261,21 +233,34 @@ function checkEntityRules(sf) {
|
|
|
261
233
|
];
|
|
262
234
|
for (const loop of loops) {
|
|
263
235
|
errors.push({
|
|
264
|
-
ruleId: "krnl/
|
|
236
|
+
ruleId: "krnl/orchestration-purity",
|
|
265
237
|
filePath,
|
|
266
238
|
line: loop.getStartLineNumber(),
|
|
267
|
-
message: `
|
|
239
|
+
message: `FunctionalityOrchestration '${cls.getName() || "Anonymous"}' violates Orchestration Purity Law. Loops and procedural algorithms are prohibited inside orchestrations. Move logic to a functionality or a global library function.`,
|
|
268
240
|
severity: "error"
|
|
269
241
|
});
|
|
270
242
|
}
|
|
243
|
+
const allowedMethods = /* @__PURE__ */ new Set([
|
|
244
|
+
"flow",
|
|
245
|
+
"getFlow",
|
|
246
|
+
"listFlows",
|
|
247
|
+
"clearFlows",
|
|
248
|
+
"thenFunctionality",
|
|
249
|
+
"parallel",
|
|
250
|
+
"branch",
|
|
251
|
+
"fanOut",
|
|
252
|
+
"thenFunctionalityOrchestration",
|
|
253
|
+
"getSteps",
|
|
254
|
+
"assertServiceBoundary"
|
|
255
|
+
]);
|
|
271
256
|
for (const method of cls.getMethods()) {
|
|
272
257
|
const methodName = method.getName();
|
|
273
|
-
if (!
|
|
258
|
+
if (!allowedMethods.has(methodName)) {
|
|
274
259
|
errors.push({
|
|
275
|
-
ruleId: "krnl/
|
|
260
|
+
ruleId: "krnl/orchestration-purity",
|
|
276
261
|
filePath,
|
|
277
262
|
line: method.getStartLineNumber(),
|
|
278
|
-
message: `
|
|
263
|
+
message: `FunctionalityOrchestration '${cls.getName() || "Anonymous"}' defines custom method '${methodName}'. FunctionalityOrchestrations are purely declarative compositors. Define capabilities as functionalities or global library functions.`,
|
|
279
264
|
severity: "error"
|
|
280
265
|
});
|
|
281
266
|
}
|
|
@@ -284,7 +269,7 @@ function checkEntityRules(sf) {
|
|
|
284
269
|
}
|
|
285
270
|
for (const call of calls) {
|
|
286
271
|
const callText = call.getText();
|
|
287
|
-
if (callText.startsWith("this.
|
|
272
|
+
if (callText.startsWith("this.flow(") || callText.startsWith("orchestration.flow(")) {
|
|
288
273
|
let currentExpr = call;
|
|
289
274
|
const chainCalls = [];
|
|
290
275
|
while (currentExpr && import_ts_morph3.Node.isCallExpression(currentExpr)) {
|
|
@@ -301,14 +286,22 @@ function checkEntityRules(sf) {
|
|
|
301
286
|
}
|
|
302
287
|
let chainId = "orchestration";
|
|
303
288
|
for (const step of chainCalls) {
|
|
304
|
-
if (step.name === "
|
|
289
|
+
if (step.name === "flow") {
|
|
305
290
|
chainId = step.argText ? step.argText.replace(/['"]/g, "") : "orchestration";
|
|
306
291
|
} else if (step.name === "thenFunction") {
|
|
307
292
|
errors.push({
|
|
308
|
-
ruleId: "krnl/
|
|
293
|
+
ruleId: "krnl/orchestration-no-direct-library-calls",
|
|
294
|
+
filePath,
|
|
295
|
+
line: step.node.getStartLineNumber(),
|
|
296
|
+
message: `FunctionalityOrchestration flow '${chainId}' violates Orchestration Purity Law. Orchestrations cannot chain direct library functions via thenFunction(). Orchestrations must only sequence functionalities (thenFunctionality) and peer functionality orchestrations (thenFunctionalityOrchestration).`,
|
|
297
|
+
severity: "error"
|
|
298
|
+
});
|
|
299
|
+
} else if (step.name === "thenService") {
|
|
300
|
+
errors.push({
|
|
301
|
+
ruleId: "krnl/orchestration-no-external-services",
|
|
309
302
|
filePath,
|
|
310
303
|
line: step.node.getStartLineNumber(),
|
|
311
|
-
message: `
|
|
304
|
+
message: `FunctionalityOrchestration flow '${chainId}' violates Plane Isolation Law L1. A service-level FunctionalityOrchestration cannot compose external services. Use Skipo ServiceOrchestration at the application layer instead.`,
|
|
312
305
|
severity: "error"
|
|
313
306
|
});
|
|
314
307
|
}
|
|
@@ -322,9 +315,9 @@ function checkTopLevelPurity(sf) {
|
|
|
322
315
|
const errors = [];
|
|
323
316
|
const warnings = [];
|
|
324
317
|
const filePath = sf.getFilePath();
|
|
325
|
-
const baseName =
|
|
318
|
+
const baseName = path2.basename(filePath);
|
|
326
319
|
const isUiTopLevel = /^(App|main|index|_app|root)\.(tsx|jsx)$/i.test(baseName);
|
|
327
|
-
const isBackendTopLevel = /^(server|app)\.(ts|js)$/i.test(baseName) && !filePath.includes("/components/") && !filePath.includes("/
|
|
320
|
+
const isBackendTopLevel = /^(server|app|index)\.(ts|js)$/i.test(baseName) && !filePath.includes("/components/") && !filePath.includes("/orchestrations/") && !filePath.includes("/services/") && !filePath.includes("/libraries/");
|
|
328
321
|
if (isUiTopLevel) {
|
|
329
322
|
const jsxElements = sf.getDescendantsOfKind(import_ts_morph4.SyntaxKind.JsxOpeningElement);
|
|
330
323
|
const jsxSelfClosing = sf.getDescendantsOfKind(import_ts_morph4.SyntaxKind.JsxSelfClosingElement);
|
|
@@ -382,19 +375,56 @@ function checkTopLevelPurity(sf) {
|
|
|
382
375
|
return { errors, warnings };
|
|
383
376
|
}
|
|
384
377
|
function checkWorkspaceLayout(projectRoot, errors) {
|
|
385
|
-
const krnlDir =
|
|
386
|
-
const srcDir =
|
|
378
|
+
const krnlDir = path2.join(projectRoot, "krnl");
|
|
379
|
+
const srcDir = path2.join(projectRoot, "src");
|
|
387
380
|
const targetDir = fs.existsSync(krnlDir) ? krnlDir : fs.existsSync(srcDir) ? srcDir : null;
|
|
388
381
|
if (!targetDir) return;
|
|
389
|
-
const backendDir =
|
|
390
|
-
const frontendDir =
|
|
382
|
+
const backendDir = path2.join(targetDir, "backend");
|
|
383
|
+
const frontendDir = path2.join(targetDir, "frontend");
|
|
391
384
|
if (fs.existsSync(backendDir)) {
|
|
392
|
-
const
|
|
385
|
+
const bServices = path2.join(backendDir, "services");
|
|
386
|
+
if (fs.existsSync(bServices)) {
|
|
387
|
+
for (const sEntry of fs.readdirSync(bServices, { withFileTypes: true })) {
|
|
388
|
+
if (!sEntry.isDirectory()) continue;
|
|
389
|
+
const sDir = path2.join(bServices, sEntry.name);
|
|
390
|
+
const sLibs = path2.join(sDir, "libraries");
|
|
391
|
+
if (fs.existsSync(sLibs)) {
|
|
392
|
+
for (const entry of fs.readdirSync(sLibs, { withFileTypes: true })) {
|
|
393
|
+
if (!entry.isDirectory()) continue;
|
|
394
|
+
const libPath = path2.join(sLibs, entry.name);
|
|
395
|
+
if (!fs.existsSync(path2.join(libPath, "manifest.json"))) {
|
|
396
|
+
errors.push({
|
|
397
|
+
ruleId: "krnl/concept-manifest-required",
|
|
398
|
+
filePath: libPath,
|
|
399
|
+
message: `Service-owned concept library "${sEntry.name}/${entry.name}" is missing a manifest.json file.`,
|
|
400
|
+
severity: "error"
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
const sFuncs = path2.join(sDir, "functionalities");
|
|
406
|
+
if (fs.existsSync(sFuncs)) {
|
|
407
|
+
for (const entry of fs.readdirSync(sFuncs, { withFileTypes: true })) {
|
|
408
|
+
if (!entry.isDirectory()) continue;
|
|
409
|
+
const funcPath = path2.join(sFuncs, entry.name);
|
|
410
|
+
if (!fs.existsSync(path2.join(funcPath, "manifest.json"))) {
|
|
411
|
+
errors.push({
|
|
412
|
+
ruleId: "krnl/functionality-manifest-required",
|
|
413
|
+
filePath: funcPath,
|
|
414
|
+
message: `Service-owned functionality "${sEntry.name}/${entry.name}" is missing a manifest.json file.`,
|
|
415
|
+
severity: "error"
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
const bLibs = path2.join(backendDir, "libraries");
|
|
393
423
|
if (fs.existsSync(bLibs)) {
|
|
394
424
|
for (const entry of fs.readdirSync(bLibs, { withFileTypes: true })) {
|
|
395
425
|
if (!entry.isDirectory()) continue;
|
|
396
|
-
const libPath =
|
|
397
|
-
if (!fs.existsSync(
|
|
426
|
+
const libPath = path2.join(bLibs, entry.name);
|
|
427
|
+
if (!fs.existsSync(path2.join(libPath, "manifest.json"))) {
|
|
398
428
|
errors.push({
|
|
399
429
|
ruleId: "krnl/concept-manifest-required",
|
|
400
430
|
filePath: libPath,
|
|
@@ -404,12 +434,12 @@ function checkWorkspaceLayout(projectRoot, errors) {
|
|
|
404
434
|
}
|
|
405
435
|
}
|
|
406
436
|
}
|
|
407
|
-
const bFuncs =
|
|
437
|
+
const bFuncs = path2.join(backendDir, "functionalities");
|
|
408
438
|
if (fs.existsSync(bFuncs)) {
|
|
409
439
|
for (const entry of fs.readdirSync(bFuncs, { withFileTypes: true })) {
|
|
410
440
|
if (!entry.isDirectory()) continue;
|
|
411
|
-
const funcPath =
|
|
412
|
-
if (!fs.existsSync(
|
|
441
|
+
const funcPath = path2.join(bFuncs, entry.name);
|
|
442
|
+
if (!fs.existsSync(path2.join(funcPath, "manifest.json"))) {
|
|
413
443
|
errors.push({
|
|
414
444
|
ruleId: "krnl/functionality-manifest-required",
|
|
415
445
|
filePath: funcPath,
|
|
@@ -421,12 +451,12 @@ function checkWorkspaceLayout(projectRoot, errors) {
|
|
|
421
451
|
}
|
|
422
452
|
}
|
|
423
453
|
if (fs.existsSync(frontendDir)) {
|
|
424
|
-
const fLibs =
|
|
454
|
+
const fLibs = path2.join(frontendDir, "libraries");
|
|
425
455
|
if (fs.existsSync(fLibs)) {
|
|
426
456
|
for (const entry of fs.readdirSync(fLibs, { withFileTypes: true })) {
|
|
427
457
|
if (!entry.isDirectory()) continue;
|
|
428
|
-
const libPath =
|
|
429
|
-
if (!fs.existsSync(
|
|
458
|
+
const libPath = path2.join(fLibs, entry.name);
|
|
459
|
+
if (!fs.existsSync(path2.join(libPath, "manifest.json"))) {
|
|
430
460
|
errors.push({
|
|
431
461
|
ruleId: "krnl/frontend-concept-manifest-required",
|
|
432
462
|
filePath: libPath,
|
|
@@ -436,12 +466,12 @@ function checkWorkspaceLayout(projectRoot, errors) {
|
|
|
436
466
|
}
|
|
437
467
|
}
|
|
438
468
|
}
|
|
439
|
-
const fFuncs =
|
|
469
|
+
const fFuncs = path2.join(frontendDir, "functionalities");
|
|
440
470
|
if (fs.existsSync(fFuncs)) {
|
|
441
471
|
for (const entry of fs.readdirSync(fFuncs, { withFileTypes: true })) {
|
|
442
472
|
if (!entry.isDirectory()) continue;
|
|
443
|
-
const funcPath =
|
|
444
|
-
if (!fs.existsSync(
|
|
473
|
+
const funcPath = path2.join(fFuncs, entry.name);
|
|
474
|
+
if (!fs.existsSync(path2.join(funcPath, "manifest.json"))) {
|
|
445
475
|
errors.push({
|
|
446
476
|
ruleId: "krnl/frontend-functionality-manifest-required",
|
|
447
477
|
filePath: funcPath,
|
|
@@ -453,19 +483,258 @@ function checkWorkspaceLayout(projectRoot, errors) {
|
|
|
453
483
|
}
|
|
454
484
|
}
|
|
455
485
|
}
|
|
486
|
+
function checkServiceBoundaries(sf) {
|
|
487
|
+
const errors = [];
|
|
488
|
+
const warnings = [];
|
|
489
|
+
const filePath = sf.getFilePath().replace(/\\/g, "/");
|
|
490
|
+
const serviceMatch = filePath.match(/\/services\/([^/]+)\//);
|
|
491
|
+
if (!serviceMatch) {
|
|
492
|
+
return { errors, warnings };
|
|
493
|
+
}
|
|
494
|
+
const currentService = serviceMatch[1];
|
|
495
|
+
const imports = sf.getImportDeclarations();
|
|
496
|
+
for (const imp of imports) {
|
|
497
|
+
const spec = imp.getModuleSpecifierValue();
|
|
498
|
+
const crossServiceLibMatch = spec.match(/(?:^|\/|\.\.\/)services\/([^/]+)\/libraries\//) || spec.match(/\.\.\/(?:(?:\.\.\/)+)?([^/]+)\/libraries\//);
|
|
499
|
+
if (crossServiceLibMatch) {
|
|
500
|
+
const targetService = crossServiceLibMatch[1];
|
|
501
|
+
if (targetService !== currentService && targetService !== "." && targetService !== "..") {
|
|
502
|
+
errors.push({
|
|
503
|
+
ruleId: "krnl/no-cross-service-library-imports",
|
|
504
|
+
filePath,
|
|
505
|
+
line: imp.getStartLineNumber(),
|
|
506
|
+
message: `Cross-service library import forbidden: '${spec}'. Service '${currentService}' cannot import '${targetService}' libraries directly via filesystem. Access libraries through the '${targetService}' ServiceFacade (e.g. ${targetService}Facade.libraries).`,
|
|
507
|
+
severity: "error"
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return { errors, warnings };
|
|
513
|
+
}
|
|
514
|
+
var PRIMITIVE_AND_BUILTIN_TYPES = /* @__PURE__ */ new Set([
|
|
515
|
+
"string",
|
|
516
|
+
"number",
|
|
517
|
+
"boolean",
|
|
518
|
+
"symbol",
|
|
519
|
+
"bigint",
|
|
520
|
+
"void",
|
|
521
|
+
"undefined",
|
|
522
|
+
"null",
|
|
523
|
+
"never",
|
|
524
|
+
"unknown",
|
|
525
|
+
"any",
|
|
526
|
+
"object",
|
|
527
|
+
"Record",
|
|
528
|
+
"Array",
|
|
529
|
+
"ReadonlyArray",
|
|
530
|
+
"Map",
|
|
531
|
+
"Set",
|
|
532
|
+
"WeakMap",
|
|
533
|
+
"WeakSet",
|
|
534
|
+
"Promise",
|
|
535
|
+
"Date",
|
|
536
|
+
"RegExp",
|
|
537
|
+
"Error",
|
|
538
|
+
"Uint8Array",
|
|
539
|
+
"Int8Array",
|
|
540
|
+
"Uint16Array",
|
|
541
|
+
"Int16Array",
|
|
542
|
+
"Uint32Array",
|
|
543
|
+
"Int32Array",
|
|
544
|
+
"Float32Array",
|
|
545
|
+
"Float64Array",
|
|
546
|
+
"ArrayBuffer",
|
|
547
|
+
"Buffer",
|
|
548
|
+
"Iterable",
|
|
549
|
+
"AsyncIterable",
|
|
550
|
+
"Iterator",
|
|
551
|
+
"AsyncIterator",
|
|
552
|
+
"Partial",
|
|
553
|
+
"Required",
|
|
554
|
+
"Readonly",
|
|
555
|
+
"Pick",
|
|
556
|
+
"Omit",
|
|
557
|
+
"Exclude",
|
|
558
|
+
"Extract",
|
|
559
|
+
"NonNullable",
|
|
560
|
+
"Parameters",
|
|
561
|
+
"ConstructorParameters",
|
|
562
|
+
"ReturnType",
|
|
563
|
+
"InstanceType"
|
|
564
|
+
]);
|
|
565
|
+
function detectServiceContext(filePath) {
|
|
566
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
567
|
+
const match = normalized.match(/(?:^|\/)services\/([^/]+)\/libraries\/([^/]+)/);
|
|
568
|
+
if (match) {
|
|
569
|
+
return { serviceName: match[1], libraryName: match[2] };
|
|
570
|
+
}
|
|
571
|
+
return null;
|
|
572
|
+
}
|
|
573
|
+
function containsIdentifier(name, target) {
|
|
574
|
+
return name.toLowerCase().includes(target.toLowerCase());
|
|
575
|
+
}
|
|
576
|
+
function isCustomContextualType(typeName, serviceName, localTypes) {
|
|
577
|
+
if (PRIMITIVE_AND_BUILTIN_TYPES.has(typeName)) return false;
|
|
578
|
+
if (localTypes.has(typeName)) return true;
|
|
579
|
+
if (containsIdentifier(typeName, serviceName)) return true;
|
|
580
|
+
if (/^[A-Z][a-zA-Z0-9]+$/.test(typeName)) return true;
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
583
|
+
function hasContextualTypeReference(node, serviceName, localTypes) {
|
|
584
|
+
const typeRefs = node.getDescendantsOfKind(import_ts_morph5.SyntaxKind.TypeReference);
|
|
585
|
+
for (const ref of typeRefs) {
|
|
586
|
+
const text = ref.getTypeName().getText().trim();
|
|
587
|
+
if (isCustomContextualType(text, serviceName, localTypes)) {
|
|
588
|
+
return true;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
return false;
|
|
592
|
+
}
|
|
593
|
+
function checkScopedLibraryRules(sf) {
|
|
594
|
+
const errors = [];
|
|
595
|
+
const warnings = [];
|
|
596
|
+
const promotableAssets = [];
|
|
597
|
+
const filePath = sf.getFilePath().replace(/\\/g, "/");
|
|
598
|
+
const context = detectServiceContext(filePath);
|
|
599
|
+
if (!context) {
|
|
600
|
+
return { errors, warnings, promotableAssets };
|
|
601
|
+
}
|
|
602
|
+
const { serviceName, libraryName } = context;
|
|
603
|
+
const localTypes = /* @__PURE__ */ new Set();
|
|
604
|
+
sf.getInterfaces().forEach((i) => localTypes.add(i.getName()));
|
|
605
|
+
sf.getTypeAliases().forEach((t) => localTypes.add(t.getName()));
|
|
606
|
+
sf.getClasses().forEach((c) => {
|
|
607
|
+
const n = c.getName();
|
|
608
|
+
if (n) localTypes.add(n);
|
|
609
|
+
});
|
|
610
|
+
sf.getEnums().forEach((e) => localTypes.add(e.getName()));
|
|
611
|
+
const functions = sf.getFunctions();
|
|
612
|
+
for (const fn of functions) {
|
|
613
|
+
const fnName = fn.getName();
|
|
614
|
+
if (!fnName) continue;
|
|
615
|
+
const isContextual = hasContextualTypeReference(fn, serviceName, localTypes);
|
|
616
|
+
const hasServiceName = containsIdentifier(fnName, serviceName);
|
|
617
|
+
if (isContextual) {
|
|
618
|
+
if (!hasServiceName) {
|
|
619
|
+
errors.push({
|
|
620
|
+
ruleId: "krnl/service-library-asset-naming",
|
|
621
|
+
filePath,
|
|
622
|
+
line: fn.getStartLineNumber(),
|
|
623
|
+
message: `Service library asset '${fnName}' in service '${serviceName}' violates scoped library naming convention. Custom library asset identifiers must contain the owning service name ('${serviceName}'). Expected name containing '${serviceName}' (e.g. '${serviceName.toLowerCase()}${fnName[0].toUpperCase()}${fnName.slice(1)}'), or eliminate contextual custom type dependencies to make it a generic promotable utility.`,
|
|
624
|
+
severity: "error"
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
} else {
|
|
628
|
+
promotableAssets.push({
|
|
629
|
+
name: fnName,
|
|
630
|
+
kind: "function",
|
|
631
|
+
filePath,
|
|
632
|
+
scope: "service",
|
|
633
|
+
scopeName: serviceName,
|
|
634
|
+
target: "GutTS"
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
for (const stmt of sf.getVariableStatements()) {
|
|
639
|
+
for (const decl of stmt.getDeclarations()) {
|
|
640
|
+
const varName = decl.getName();
|
|
641
|
+
const init = decl.getInitializer();
|
|
642
|
+
const isFunction = init && (init.getKind() === import_ts_morph5.SyntaxKind.ArrowFunction || init.getKind() === import_ts_morph5.SyntaxKind.FunctionExpression);
|
|
643
|
+
if (isFunction) {
|
|
644
|
+
const isContextual = hasContextualTypeReference(decl, serviceName, localTypes);
|
|
645
|
+
const hasServiceName = containsIdentifier(varName, serviceName);
|
|
646
|
+
if (isContextual) {
|
|
647
|
+
if (!hasServiceName) {
|
|
648
|
+
errors.push({
|
|
649
|
+
ruleId: "krnl/service-library-asset-naming",
|
|
650
|
+
filePath,
|
|
651
|
+
line: decl.getStartLineNumber(),
|
|
652
|
+
message: `Service library asset '${varName}' in service '${serviceName}' violates scoped library naming convention. Custom library asset identifiers must contain the owning service name ('${serviceName}'). Expected name containing '${serviceName}', or eliminate contextual custom type dependencies to make it a generic promotable utility.`,
|
|
653
|
+
severity: "error"
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
} else {
|
|
657
|
+
promotableAssets.push({
|
|
658
|
+
name: varName,
|
|
659
|
+
kind: "function",
|
|
660
|
+
filePath,
|
|
661
|
+
scope: "service",
|
|
662
|
+
scopeName: serviceName,
|
|
663
|
+
target: "GutTS"
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
} else {
|
|
667
|
+
const isContextual = hasContextualTypeReference(decl, serviceName, localTypes);
|
|
668
|
+
const hasServiceName = containsIdentifier(varName, serviceName);
|
|
669
|
+
if (isContextual && !hasServiceName) {
|
|
670
|
+
errors.push({
|
|
671
|
+
ruleId: "krnl/service-library-asset-naming",
|
|
672
|
+
filePath,
|
|
673
|
+
line: decl.getStartLineNumber(),
|
|
674
|
+
message: `Service library asset '${varName}' in service '${serviceName}' violates scoped library naming convention. Custom library asset identifiers must contain the owning service name ('${serviceName}').`,
|
|
675
|
+
severity: "error"
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
for (const iface of sf.getInterfaces()) {
|
|
682
|
+
const name = iface.getName();
|
|
683
|
+
const hasServiceName = containsIdentifier(name, serviceName);
|
|
684
|
+
const hasProps = iface.getProperties().length > 0;
|
|
685
|
+
if (hasProps && !hasServiceName) {
|
|
686
|
+
errors.push({
|
|
687
|
+
ruleId: "krnl/service-library-asset-naming",
|
|
688
|
+
filePath,
|
|
689
|
+
line: iface.getStartLineNumber(),
|
|
690
|
+
message: `Service library interface '${name}' in service '${serviceName}' violates scoped library naming convention. Custom library asset identifiers must contain the owning service name ('${serviceName}'). Expected name like '${serviceName}${name}'.`,
|
|
691
|
+
severity: "error"
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
for (const t of sf.getTypeAliases()) {
|
|
696
|
+
const name = t.getName();
|
|
697
|
+
const hasServiceName = containsIdentifier(name, serviceName);
|
|
698
|
+
const isContextual = hasContextualTypeReference(t, serviceName, localTypes);
|
|
699
|
+
if (isContextual && !hasServiceName) {
|
|
700
|
+
errors.push({
|
|
701
|
+
ruleId: "krnl/service-library-asset-naming",
|
|
702
|
+
filePath,
|
|
703
|
+
line: t.getStartLineNumber(),
|
|
704
|
+
message: `Service library type alias '${name}' in service '${serviceName}' violates scoped library naming convention. Custom library asset identifiers must contain the owning service name ('${serviceName}'). Expected name like '${serviceName}${name}'.`,
|
|
705
|
+
severity: "error"
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
for (const cls of sf.getClasses()) {
|
|
710
|
+
const name = cls.getName();
|
|
711
|
+
if (!name) continue;
|
|
712
|
+
const hasServiceName = containsIdentifier(name, serviceName);
|
|
713
|
+
if (!hasServiceName) {
|
|
714
|
+
errors.push({
|
|
715
|
+
ruleId: "krnl/service-library-asset-naming",
|
|
716
|
+
filePath,
|
|
717
|
+
line: cls.getStartLineNumber(),
|
|
718
|
+
message: `Service library class '${name}' in service '${serviceName}' violates scoped library naming convention. Custom library asset identifiers must contain the owning service name ('${serviceName}'). Expected name like '${serviceName}${name}'.`,
|
|
719
|
+
severity: "error"
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
return { errors, warnings, promotableAssets };
|
|
724
|
+
}
|
|
456
725
|
var KrnlValidatorEngine = class {
|
|
457
726
|
project;
|
|
458
727
|
projectRoot;
|
|
459
728
|
limitOptions;
|
|
460
729
|
constructor(optionsOrRoot) {
|
|
461
730
|
const options = typeof optionsOrRoot === "string" ? { projectRoot: optionsOrRoot } : optionsOrRoot;
|
|
462
|
-
this.projectRoot =
|
|
731
|
+
this.projectRoot = path3.resolve(options.projectRoot || process.cwd());
|
|
463
732
|
this.limitOptions = {
|
|
464
733
|
maxFileLineLimit: options.maxFileLineLimit ?? 200,
|
|
465
734
|
maxMainLogicLimit: options.maxMainLogicLimit ?? 20,
|
|
466
735
|
maxHelperLineLimit: options.maxHelperLineLimit ?? 30
|
|
467
736
|
};
|
|
468
|
-
const tsConfigPath =
|
|
737
|
+
const tsConfigPath = path3.join(this.projectRoot, "tsconfig.json");
|
|
469
738
|
if (fs2.existsSync(tsConfigPath)) {
|
|
470
739
|
this.project = new import_ts_morph.Project({ tsConfigFilePath: tsConfigPath, skipAddingFilesFromTsConfig: true });
|
|
471
740
|
} else {
|
|
@@ -479,33 +748,55 @@ var KrnlValidatorEngine = class {
|
|
|
479
748
|
const files = this.collectSourceFiles(this.projectRoot);
|
|
480
749
|
const errors = [];
|
|
481
750
|
const warnings = [];
|
|
751
|
+
const promotableAssets = [];
|
|
482
752
|
checkWorkspaceLayout(this.projectRoot, errors);
|
|
483
753
|
for (const f of files) {
|
|
484
754
|
const sf = this.project.addSourceFileAtPath(f);
|
|
485
755
|
const fileReport = this.validateSourceFile(sf);
|
|
486
756
|
errors.push(...fileReport.errors);
|
|
487
757
|
warnings.push(...fileReport.warnings);
|
|
758
|
+
if (fileReport.promotableAssets) {
|
|
759
|
+
promotableAssets.push(...fileReport.promotableAssets);
|
|
760
|
+
}
|
|
488
761
|
}
|
|
489
762
|
return {
|
|
490
763
|
valid: errors.length === 0,
|
|
491
764
|
totalFiles: files.length,
|
|
492
765
|
errors,
|
|
493
|
-
warnings
|
|
766
|
+
warnings,
|
|
767
|
+
promotableAssets
|
|
494
768
|
};
|
|
495
769
|
}
|
|
496
770
|
validateSourceFile(sf) {
|
|
497
771
|
const filePath = sf.getFilePath();
|
|
498
|
-
const baseName =
|
|
772
|
+
const baseName = path3.basename(filePath);
|
|
499
773
|
if (baseName.includes("_pb.") || baseName.endsWith(".d.ts")) {
|
|
500
|
-
return { errors: [], warnings: [] };
|
|
774
|
+
return { errors: [], warnings: [], promotableAssets: [] };
|
|
501
775
|
}
|
|
502
776
|
const limits = checkFileLimits(sf, this.limitOptions);
|
|
503
777
|
const purity = checkTopLevelPurity(sf);
|
|
504
778
|
const components = checkComponentRules(sf);
|
|
505
|
-
const
|
|
779
|
+
const orchestration = checkOrchestrationRules(sf);
|
|
780
|
+
const boundaries = checkServiceBoundaries(sf);
|
|
781
|
+
const scopedLibraries = checkScopedLibraryRules(sf);
|
|
506
782
|
return {
|
|
507
|
-
errors: [
|
|
508
|
-
|
|
783
|
+
errors: [
|
|
784
|
+
...limits.errors,
|
|
785
|
+
...purity.errors,
|
|
786
|
+
...components.errors,
|
|
787
|
+
...orchestration.errors,
|
|
788
|
+
...boundaries.errors,
|
|
789
|
+
...scopedLibraries.errors
|
|
790
|
+
],
|
|
791
|
+
warnings: [
|
|
792
|
+
...limits.warnings,
|
|
793
|
+
...purity.warnings,
|
|
794
|
+
...components.warnings,
|
|
795
|
+
...orchestration.warnings,
|
|
796
|
+
...boundaries.warnings,
|
|
797
|
+
...scopedLibraries.warnings
|
|
798
|
+
],
|
|
799
|
+
promotableAssets: scopedLibraries.promotableAssets
|
|
509
800
|
};
|
|
510
801
|
}
|
|
511
802
|
collectSourceFiles(dir, collected = []) {
|
|
@@ -513,7 +804,7 @@ var KrnlValidatorEngine = class {
|
|
|
513
804
|
const entries = fs2.readdirSync(dir, { withFileTypes: true });
|
|
514
805
|
for (const entry of entries) {
|
|
515
806
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === ".git") continue;
|
|
516
|
-
const full =
|
|
807
|
+
const full = path3.join(dir, entry.name);
|
|
517
808
|
if (entry.isDirectory()) {
|
|
518
809
|
this.collectSourceFiles(full, collected);
|
|
519
810
|
} else if (entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".js") || entry.name.endsWith(".tsx") || entry.name.endsWith(".jsx"))) {
|
|
@@ -548,124 +839,112 @@ async function runValidate(projectRoot = process.cwd()) {
|
|
|
548
839
|
}
|
|
549
840
|
return false;
|
|
550
841
|
}
|
|
842
|
+
if (report.promotableAssets && report.promotableAssets.length > 0) {
|
|
843
|
+
console.log(`\u{1F4E6} [PROMOTABLE ASSETS] Detected ${report.promotableAssets.length} generic library asset(s) eligible for GutTS promotion:`);
|
|
844
|
+
for (const asset of report.promotableAssets) {
|
|
845
|
+
console.log(` \u2726 [${asset.scope}:${asset.scopeName}] ${asset.name} (${asset.kind}) -> ${asset.target}`);
|
|
846
|
+
}
|
|
847
|
+
console.log("");
|
|
848
|
+
}
|
|
551
849
|
console.log(`\u2705 [VALIDATION PASSED] ${report.totalFiles} source files verified clean against Krnl paradigms.
|
|
552
850
|
`);
|
|
553
851
|
return true;
|
|
554
852
|
}
|
|
555
853
|
|
|
556
|
-
// src/commands/generators/
|
|
854
|
+
// src/commands/generators/functionalityOrchestrationGenerator.ts
|
|
855
|
+
var path5 = __toESM(require("path"), 1);
|
|
557
856
|
var fs4 = __toESM(require("fs"), 1);
|
|
558
|
-
var path6 = __toESM(require("path"), 1);
|
|
559
857
|
|
|
560
858
|
// src/commands/generators/common.ts
|
|
561
859
|
var fs3 = __toESM(require("fs"), 1);
|
|
562
|
-
var
|
|
860
|
+
var path4 = __toESM(require("path"), 1);
|
|
563
861
|
function getPlaneRoots(projectRoot) {
|
|
564
|
-
const krnlRoot =
|
|
862
|
+
const krnlRoot = path4.join(projectRoot, "krnl");
|
|
565
863
|
if (fs3.existsSync(krnlRoot)) {
|
|
566
864
|
return {
|
|
567
|
-
backend:
|
|
568
|
-
frontend:
|
|
865
|
+
backend: path4.join(krnlRoot, "backend"),
|
|
866
|
+
frontend: path4.join(krnlRoot, "frontend"),
|
|
569
867
|
isKrnlDir: true
|
|
570
868
|
};
|
|
571
869
|
}
|
|
572
870
|
return {
|
|
573
|
-
backend:
|
|
574
|
-
frontend:
|
|
871
|
+
backend: path4.join(projectRoot, "src"),
|
|
872
|
+
frontend: path4.join(projectRoot, "src"),
|
|
575
873
|
isKrnlDir: false
|
|
576
874
|
};
|
|
577
875
|
}
|
|
578
876
|
|
|
579
|
-
// src/commands/generators/
|
|
580
|
-
function
|
|
581
|
-
const { backend
|
|
582
|
-
const
|
|
583
|
-
fs4.mkdirSync(
|
|
584
|
-
fs4.mkdirSync(path6.join(bEntityDir, "tests"), { recursive: true });
|
|
877
|
+
// src/commands/generators/functionalityOrchestrationGenerator.ts
|
|
878
|
+
function generateFunctionalityOrchestration(name, projectRoot) {
|
|
879
|
+
const { backend } = getPlaneRoots(projectRoot);
|
|
880
|
+
const orchDir = path5.join(backend, "orchestrations", name);
|
|
881
|
+
fs4.mkdirSync(path5.join(orchDir, "tests"), { recursive: true });
|
|
585
882
|
fs4.writeFileSync(
|
|
586
|
-
|
|
587
|
-
`import {
|
|
883
|
+
path5.join(orchDir, `${name}FunctionalityOrchestration.ts`),
|
|
884
|
+
`import { FunctionalityOrchestration } from '@ultrst-armada/krnl-core';
|
|
588
885
|
|
|
589
886
|
/**
|
|
590
|
-
* @role
|
|
887
|
+
* @role functionality-orchestration
|
|
888
|
+
* Declaratively composes functionalities within this service into named flows.
|
|
591
889
|
*/
|
|
592
|
-
export class ${name} extends
|
|
890
|
+
export class ${name}FunctionalityOrchestration extends FunctionalityOrchestration {
|
|
593
891
|
constructor() {
|
|
594
892
|
super({
|
|
595
|
-
id:
|
|
596
|
-
|
|
597
|
-
|
|
893
|
+
id: '${name}FunctionalityOrchestration',
|
|
894
|
+
name: '${name}',
|
|
895
|
+
version: '1.0.0',
|
|
896
|
+
description: '${name} declarative functionality orchestration flow',
|
|
598
897
|
});
|
|
599
|
-
}
|
|
600
898
|
|
|
601
|
-
|
|
602
|
-
|
|
899
|
+
this.flow('default')
|
|
900
|
+
.thenFunctionality('Execute${name}')
|
|
901
|
+
.register({ visibility: 'public' });
|
|
603
902
|
}
|
|
604
903
|
}
|
|
605
904
|
|
|
606
|
-
export default ${name};
|
|
905
|
+
export default ${name}FunctionalityOrchestration;
|
|
607
906
|
`
|
|
608
907
|
);
|
|
609
908
|
fs4.writeFileSync(
|
|
610
|
-
|
|
611
|
-
`
|
|
612
|
-
|
|
613
|
-
.register({ visibility: "public" });
|
|
614
|
-
}
|
|
615
|
-
`
|
|
616
|
-
);
|
|
617
|
-
fs4.writeFileSync(
|
|
618
|
-
path6.join(bEntityDir, "tests", `${name}.test.ts`),
|
|
619
|
-
`import { describe, it, expect } from "vitest";
|
|
620
|
-
import { ${name} } from "../${name}.js";
|
|
909
|
+
path5.join(orchDir, "tests", `${name}FunctionalityOrchestration.test.ts`),
|
|
910
|
+
`import { describe, it, expect } from 'vitest';
|
|
911
|
+
import { ${name}FunctionalityOrchestration } from '../${name}FunctionalityOrchestration.js';
|
|
621
912
|
|
|
622
|
-
describe(
|
|
623
|
-
it(
|
|
624
|
-
const
|
|
625
|
-
expect(
|
|
913
|
+
describe('${name}FunctionalityOrchestration', () => {
|
|
914
|
+
it('instantiates and configures declarative functionality flow correctly', () => {
|
|
915
|
+
const orchestration = new ${name}FunctionalityOrchestration();
|
|
916
|
+
expect(orchestration.id).toBe('${name}FunctionalityOrchestration');
|
|
917
|
+
expect(orchestration.getFlow('default')).toBeDefined();
|
|
918
|
+
expect(orchestration.getFlow('default')?.steps).toHaveLength(1);
|
|
626
919
|
});
|
|
627
920
|
});
|
|
628
921
|
`
|
|
629
922
|
);
|
|
630
|
-
|
|
631
|
-
fs4.mkdirSync(path6.join(fEntityDir, "tests"), { recursive: true });
|
|
632
|
-
fs4.writeFileSync(
|
|
633
|
-
path6.join(fEntityDir, `${name}0.tsx`),
|
|
634
|
-
`import React from "react";
|
|
635
|
-
|
|
636
|
-
export const ${name}0: React.FC = () => {
|
|
637
|
-
return (
|
|
638
|
-
<div className="krnl-entity-${name.toLowerCase()}">
|
|
639
|
-
<h2>${name} (Variant 0)</h2>
|
|
640
|
-
</div>
|
|
641
|
-
);
|
|
642
|
-
};
|
|
643
|
-
|
|
644
|
-
export default ${name}0;
|
|
645
|
-
`
|
|
646
|
-
);
|
|
647
|
-
fs4.writeFileSync(
|
|
648
|
-
path6.join(fEntityDir, "tests", `${name}0.test.tsx`),
|
|
649
|
-
`import { describe, it, expect } from "vitest";
|
|
650
|
-
|
|
651
|
-
describe("${name}0 Component", () => {
|
|
652
|
-
it("renders variant 0", () => {
|
|
653
|
-
expect(true).toBe(true);
|
|
654
|
-
});
|
|
655
|
-
});
|
|
656
|
-
`
|
|
657
|
-
);
|
|
658
|
-
console.log(`\u2705 Created Backend Entity Folder: krnl/backend/entities/${name}/`);
|
|
659
|
-
console.log(`\u2705 Created Frontend Entity Folder: krnl/frontend/entities/${name}/`);
|
|
923
|
+
console.log(`\u2705 Created FunctionalityOrchestration: krnl/backend/orchestrations/${name}/`);
|
|
660
924
|
}
|
|
661
925
|
|
|
662
926
|
// src/commands/generators/functionalityGenerator.ts
|
|
663
927
|
var fs6 = __toESM(require("fs"), 1);
|
|
664
|
-
var
|
|
928
|
+
var path7 = __toESM(require("path"), 1);
|
|
665
929
|
|
|
666
930
|
// ../core/dist/index.js
|
|
667
931
|
var fs5 = __toESM(require("fs"), 1);
|
|
668
|
-
var
|
|
932
|
+
var path6 = __toESM(require("path"), 1);
|
|
933
|
+
|
|
934
|
+
// ../../node_modules/.pnpm/@dinilmusick+gutts@0.1.0/node_modules/@dinilmusick/gutts/dist/json/json-parse.js
|
|
935
|
+
function parseJson(text) {
|
|
936
|
+
return JSON.parse(text);
|
|
937
|
+
}
|
|
938
|
+
function tryParseJson(text) {
|
|
939
|
+
try {
|
|
940
|
+
return parseJson(text);
|
|
941
|
+
} catch {
|
|
942
|
+
return void 0;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
// ../core/dist/index.js
|
|
947
|
+
var asyncHooks = globalThis.process?.getBuiltinModule?.("node:async_hooks");
|
|
669
948
|
var KrnlPackageReconciler = class {
|
|
670
949
|
/**
|
|
671
950
|
* Scans all manifest.json files across backend and frontend and reconciles root package.json.
|
|
@@ -677,7 +956,7 @@ var KrnlPackageReconciler = class {
|
|
|
677
956
|
for (const mPath of manifests) {
|
|
678
957
|
try {
|
|
679
958
|
const raw = fs5.readFileSync(mPath, "utf8");
|
|
680
|
-
const json =
|
|
959
|
+
const json = tryParseJson(raw) ?? {};
|
|
681
960
|
if (json.dependencies && typeof json.dependencies === "object") {
|
|
682
961
|
for (const [pkg, ver] of Object.entries(json.dependencies)) {
|
|
683
962
|
if (!aggregatedDeps[pkg]) aggregatedDeps[pkg] = [];
|
|
@@ -713,7 +992,7 @@ var KrnlPackageReconciler = class {
|
|
|
713
992
|
}
|
|
714
993
|
resolvedDevDeps[pkg] = versions[versions.length - 1];
|
|
715
994
|
}
|
|
716
|
-
const pkgJsonPath =
|
|
995
|
+
const pkgJsonPath = path6.join(projectRoot, "package.json");
|
|
717
996
|
let updated = false;
|
|
718
997
|
if (fs5.existsSync(pkgJsonPath)) {
|
|
719
998
|
const pkgContent = JSON.parse(fs5.readFileSync(pkgJsonPath, "utf8"));
|
|
@@ -751,12 +1030,15 @@ var KrnlPackageReconciler = class {
|
|
|
751
1030
|
*/
|
|
752
1031
|
static findManifests(projectRoot) {
|
|
753
1032
|
const searchDirs = [
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
1033
|
+
path6.join(projectRoot, "krnl", "backend", "services"),
|
|
1034
|
+
path6.join(projectRoot, "krnl", "backend", "libraries"),
|
|
1035
|
+
path6.join(projectRoot, "krnl", "backend", "functionalities"),
|
|
1036
|
+
path6.join(projectRoot, "krnl", "frontend", "libraries"),
|
|
1037
|
+
path6.join(projectRoot, "krnl", "frontend", "functionalities"),
|
|
1038
|
+
path6.join(projectRoot, "src", "backend", "services"),
|
|
1039
|
+
path6.join(projectRoot, "src", "services"),
|
|
1040
|
+
path6.join(projectRoot, "src", "functionalities"),
|
|
1041
|
+
path6.join(projectRoot, "src", "libraries")
|
|
760
1042
|
];
|
|
761
1043
|
const found = [];
|
|
762
1044
|
for (const dir of searchDirs) {
|
|
@@ -771,7 +1053,7 @@ var KrnlPackageReconciler = class {
|
|
|
771
1053
|
const entries = fs5.readdirSync(dir, { withFileTypes: true });
|
|
772
1054
|
for (const entry of entries) {
|
|
773
1055
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === ".git") continue;
|
|
774
|
-
const full =
|
|
1056
|
+
const full = path6.join(dir, entry.name);
|
|
775
1057
|
if (entry.isDirectory()) {
|
|
776
1058
|
this.scanRecursive(full, found);
|
|
777
1059
|
} else if (entry.isFile() && entry.name === "manifest.json") {
|
|
@@ -784,16 +1066,40 @@ var KrnlPackageReconciler = class {
|
|
|
784
1066
|
};
|
|
785
1067
|
|
|
786
1068
|
// src/commands/generators/functionalityGenerator.ts
|
|
787
|
-
function generateFunctionality(name, projectRoot) {
|
|
1069
|
+
function generateFunctionality(name, projectRoot, parentServiceOrOptions) {
|
|
788
1070
|
const { backend, frontend } = getPlaneRoots(projectRoot);
|
|
789
|
-
const
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
1071
|
+
const options = typeof parentServiceOrOptions === "string" ? { parentService: parentServiceOrOptions } : parentServiceOrOptions || {};
|
|
1072
|
+
let targetService = options.parentService;
|
|
1073
|
+
if (!targetService) {
|
|
1074
|
+
const servicesDir = path7.join(backend, "services");
|
|
1075
|
+
if (fs6.existsSync(servicesDir)) {
|
|
1076
|
+
const existing = fs6.readdirSync(servicesDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
1077
|
+
if (existing.length === 1) {
|
|
1078
|
+
targetService = existing[0].name;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
const bFuncDir = targetService ? path7.join(backend, "services", targetService, "functionalities", name) : path7.join(backend, "functionalities", name);
|
|
1083
|
+
fs6.mkdirSync(path7.join(bFuncDir, "main_function"), { recursive: true });
|
|
1084
|
+
fs6.mkdirSync(path7.join(bFuncDir, "helper_functions"), { recursive: true });
|
|
1085
|
+
fs6.mkdirSync(path7.join(bFuncDir, "events"), { recursive: true });
|
|
1086
|
+
fs6.mkdirSync(path7.join(bFuncDir, "tests"), { recursive: true });
|
|
1087
|
+
if (options.withState) {
|
|
1088
|
+
fs6.mkdirSync(path7.join(bFuncDir, "state_data"), { recursive: true });
|
|
1089
|
+
fs6.writeFileSync(
|
|
1090
|
+
path7.join(bFuncDir, "state_data", "state.ts"),
|
|
1091
|
+
`export interface ${name}State {
|
|
1092
|
+
executionCount: number;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
export const initialState: ${name}State = {
|
|
1096
|
+
executionCount: 0
|
|
1097
|
+
};
|
|
1098
|
+
`
|
|
1099
|
+
);
|
|
1100
|
+
}
|
|
795
1101
|
fs6.writeFileSync(
|
|
796
|
-
|
|
1102
|
+
path7.join(bFuncDir, `${name}Atom.ts`),
|
|
797
1103
|
`export interface ${name}Input {
|
|
798
1104
|
payload?: string;
|
|
799
1105
|
}
|
|
@@ -805,10 +1111,11 @@ export interface ${name}Output {
|
|
|
805
1111
|
`
|
|
806
1112
|
);
|
|
807
1113
|
fs6.writeFileSync(
|
|
808
|
-
|
|
1114
|
+
path7.join(bFuncDir, "manifest.json"),
|
|
809
1115
|
JSON.stringify(
|
|
810
1116
|
{
|
|
811
1117
|
name,
|
|
1118
|
+
service: targetService || void 0,
|
|
812
1119
|
description: `${name} quad-unit functionality`,
|
|
813
1120
|
dependencies: {}
|
|
814
1121
|
},
|
|
@@ -817,10 +1124,10 @@ export interface ${name}Output {
|
|
|
817
1124
|
)
|
|
818
1125
|
);
|
|
819
1126
|
fs6.writeFileSync(
|
|
820
|
-
|
|
1127
|
+
path7.join(bFuncDir, "main_function", "logic.ts"),
|
|
821
1128
|
`import type { ${name}Input, ${name}Output } from "../${name}Atom.js";
|
|
822
1129
|
|
|
823
|
-
export const main = async (input: ${name}Input,
|
|
1130
|
+
export const main = async (input: ${name}Input, context: any): Promise<${name}Output> => {
|
|
824
1131
|
return {
|
|
825
1132
|
success: true,
|
|
826
1133
|
timestamp: Date.now()
|
|
@@ -829,24 +1136,13 @@ export const main = async (input: ${name}Input, { state }: any): Promise<${name}
|
|
|
829
1136
|
`
|
|
830
1137
|
);
|
|
831
1138
|
fs6.writeFileSync(
|
|
832
|
-
|
|
1139
|
+
path7.join(bFuncDir, "main_function", "lifecycle.ts"),
|
|
833
1140
|
`export async function onMount() {}
|
|
834
1141
|
export async function onTeardown() {}
|
|
835
1142
|
`
|
|
836
1143
|
);
|
|
837
1144
|
fs6.writeFileSync(
|
|
838
|
-
|
|
839
|
-
`export interface ${name}State {
|
|
840
|
-
executionCount: number;
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
export const initialState: ${name}State = {
|
|
844
|
-
executionCount: 0
|
|
845
|
-
};
|
|
846
|
-
`
|
|
847
|
-
);
|
|
848
|
-
fs6.writeFileSync(
|
|
849
|
-
path8.join(bFuncDir, "helper_functions", "helper.ts"),
|
|
1145
|
+
path7.join(bFuncDir, "helper_functions", "helper.ts"),
|
|
850
1146
|
`/**
|
|
851
1147
|
* @role component
|
|
852
1148
|
*/
|
|
@@ -856,7 +1152,7 @@ export function exampleHelper(): boolean {
|
|
|
856
1152
|
`
|
|
857
1153
|
);
|
|
858
1154
|
fs6.writeFileSync(
|
|
859
|
-
|
|
1155
|
+
path7.join(bFuncDir, "events", "events.ts"),
|
|
860
1156
|
`/**
|
|
861
1157
|
* @role component
|
|
862
1158
|
*/
|
|
@@ -866,7 +1162,7 @@ export interface ${name}CompletedEvent {
|
|
|
866
1162
|
`
|
|
867
1163
|
);
|
|
868
1164
|
fs6.writeFileSync(
|
|
869
|
-
|
|
1165
|
+
path7.join(bFuncDir, "tests", `${name}.test.ts`),
|
|
870
1166
|
`import { describe, it, expect } from "vitest";
|
|
871
1167
|
|
|
872
1168
|
describe("${name} functionality", () => {
|
|
@@ -876,10 +1172,10 @@ describe("${name} functionality", () => {
|
|
|
876
1172
|
});
|
|
877
1173
|
`
|
|
878
1174
|
);
|
|
879
|
-
const fFuncDir =
|
|
880
|
-
fs6.mkdirSync(
|
|
1175
|
+
const fFuncDir = path7.join(frontend, "functionalities", name);
|
|
1176
|
+
fs6.mkdirSync(path7.join(fFuncDir, "tests"), { recursive: true });
|
|
881
1177
|
fs6.writeFileSync(
|
|
882
|
-
|
|
1178
|
+
path7.join(fFuncDir, `${name}0.tsx`),
|
|
883
1179
|
`import React from "react";
|
|
884
1180
|
|
|
885
1181
|
export const ${name}0: React.FC = () => {
|
|
@@ -894,11 +1190,11 @@ export default ${name}0;
|
|
|
894
1190
|
`
|
|
895
1191
|
);
|
|
896
1192
|
fs6.writeFileSync(
|
|
897
|
-
|
|
1193
|
+
path7.join(fFuncDir, "manifest.json"),
|
|
898
1194
|
JSON.stringify({ name: `${name}UI`, dependencies: {} }, null, 2)
|
|
899
1195
|
);
|
|
900
1196
|
fs6.writeFileSync(
|
|
901
|
-
|
|
1197
|
+
path7.join(fFuncDir, "tests", `${name}0.test.tsx`),
|
|
902
1198
|
`import { describe, it, expect } from "vitest";
|
|
903
1199
|
|
|
904
1200
|
describe("${name}0 Component", () => {
|
|
@@ -909,20 +1205,33 @@ describe("${name}0 Component", () => {
|
|
|
909
1205
|
`
|
|
910
1206
|
);
|
|
911
1207
|
KrnlPackageReconciler.reconcile(projectRoot, true);
|
|
912
|
-
console.log(`\u2705 Created Backend Functionality
|
|
913
|
-
console.log(`\u2705 Created Frontend Functionality:
|
|
1208
|
+
console.log(`\u2705 Created Backend Functionality: ${path7.relative(projectRoot, bFuncDir)}/`);
|
|
1209
|
+
console.log(`\u2705 Created Frontend Functionality: ${path7.relative(projectRoot, fFuncDir)}/`);
|
|
914
1210
|
}
|
|
915
1211
|
|
|
916
1212
|
// src/commands/generators/libraryGenerator.ts
|
|
917
1213
|
var fs7 = __toESM(require("fs"), 1);
|
|
918
|
-
var
|
|
919
|
-
function generateLibrary(name, projectRoot) {
|
|
1214
|
+
var path8 = __toESM(require("path"), 1);
|
|
1215
|
+
function generateLibrary(name, projectRoot, parentService) {
|
|
920
1216
|
const { backend, frontend } = getPlaneRoots(projectRoot);
|
|
921
1217
|
const conceptName = name.endsWith("Concepts") ? name : `${name}Concepts`;
|
|
922
|
-
|
|
923
|
-
|
|
1218
|
+
let targetService = parentService;
|
|
1219
|
+
if (!targetService) {
|
|
1220
|
+
const servicesDir = path8.join(backend, "services");
|
|
1221
|
+
if (fs7.existsSync(servicesDir)) {
|
|
1222
|
+
const existing = fs7.readdirSync(servicesDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
1223
|
+
if (existing.length === 1) {
|
|
1224
|
+
targetService = existing[0].name;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
if (!targetService) {
|
|
1229
|
+
targetService = "App";
|
|
1230
|
+
}
|
|
1231
|
+
const bLibDir = path8.join(backend, "services", targetService, "libraries", conceptName);
|
|
1232
|
+
fs7.mkdirSync(path8.join(bLibDir, "tests"), { recursive: true });
|
|
924
1233
|
fs7.writeFileSync(
|
|
925
|
-
|
|
1234
|
+
path8.join(bLibDir, "definitions.ts"),
|
|
926
1235
|
`/**
|
|
927
1236
|
* @file definitions.ts
|
|
928
1237
|
* @role component
|
|
@@ -933,7 +1242,7 @@ export interface ${conceptName}Options {
|
|
|
933
1242
|
`
|
|
934
1243
|
);
|
|
935
1244
|
fs7.writeFileSync(
|
|
936
|
-
|
|
1245
|
+
path8.join(bLibDir, "functions.ts"),
|
|
937
1246
|
`/**
|
|
938
1247
|
* @file functions.ts
|
|
939
1248
|
* @role component
|
|
@@ -946,31 +1255,38 @@ export function ${name.toLowerCase()}Transform<T>(data: T, _opts?: ${conceptName
|
|
|
946
1255
|
`
|
|
947
1256
|
);
|
|
948
1257
|
fs7.writeFileSync(
|
|
949
|
-
|
|
950
|
-
|
|
1258
|
+
path8.join(bLibDir, "index.ts"),
|
|
1259
|
+
`export * from "./definitions.js";
|
|
1260
|
+
export * from "./functions.js";
|
|
1261
|
+
`
|
|
1262
|
+
);
|
|
1263
|
+
fs7.writeFileSync(
|
|
1264
|
+
path8.join(bLibDir, "manifest.json"),
|
|
1265
|
+
JSON.stringify({ name: conceptName, service: targetService, dependencies: {} }, null, 2)
|
|
951
1266
|
);
|
|
952
1267
|
fs7.writeFileSync(
|
|
953
|
-
|
|
1268
|
+
path8.join(bLibDir, "tests", `${conceptName}.test.ts`),
|
|
954
1269
|
`import { describe, it, expect } from "vitest";
|
|
1270
|
+
import { ${name.toLowerCase()}Transform } from "../functions.js";
|
|
955
1271
|
|
|
956
1272
|
describe("${conceptName}", () => {
|
|
957
1273
|
it("runs correctly", () => {
|
|
958
|
-
expect(
|
|
1274
|
+
expect(${name.toLowerCase()}Transform(42)).toBe(42);
|
|
959
1275
|
});
|
|
960
1276
|
});
|
|
961
1277
|
`
|
|
962
1278
|
);
|
|
963
|
-
const fLibDir =
|
|
964
|
-
fs7.mkdirSync(
|
|
1279
|
+
const fLibDir = path8.join(frontend, "libraries", conceptName);
|
|
1280
|
+
fs7.mkdirSync(path8.join(fLibDir, "tests"), { recursive: true });
|
|
965
1281
|
fs7.writeFileSync(
|
|
966
|
-
|
|
1282
|
+
path8.join(fLibDir, "definitions.ts"),
|
|
967
1283
|
`export interface ${name}Props {
|
|
968
1284
|
label?: string;
|
|
969
1285
|
}
|
|
970
1286
|
`
|
|
971
1287
|
);
|
|
972
1288
|
fs7.writeFileSync(
|
|
973
|
-
|
|
1289
|
+
path8.join(fLibDir, "components.tsx"),
|
|
974
1290
|
`import React from "react";
|
|
975
1291
|
import type { ${name}Props } from "./definitions.js";
|
|
976
1292
|
import "./styles.css";
|
|
@@ -981,18 +1297,18 @@ export const ${name}: React.FC<${name}Props> = ({ label = "${name}" }) => {
|
|
|
981
1297
|
`
|
|
982
1298
|
);
|
|
983
1299
|
fs7.writeFileSync(
|
|
984
|
-
|
|
1300
|
+
path8.join(fLibDir, "styles.css"),
|
|
985
1301
|
`.krnl-${name.toLowerCase()} {
|
|
986
1302
|
font-family: inherit;
|
|
987
1303
|
}
|
|
988
1304
|
`
|
|
989
1305
|
);
|
|
990
1306
|
fs7.writeFileSync(
|
|
991
|
-
|
|
1307
|
+
path8.join(fLibDir, "manifest.json"),
|
|
992
1308
|
JSON.stringify({ name: `${conceptName}UI`, dependencies: {} }, null, 2)
|
|
993
1309
|
);
|
|
994
1310
|
fs7.writeFileSync(
|
|
995
|
-
|
|
1311
|
+
path8.join(fLibDir, "tests", `${name}.test.tsx`),
|
|
996
1312
|
`import { describe, it, expect } from "vitest";
|
|
997
1313
|
|
|
998
1314
|
describe("${name} UI Concept", () => {
|
|
@@ -1003,82 +1319,165 @@ describe("${name} UI Concept", () => {
|
|
|
1003
1319
|
`
|
|
1004
1320
|
);
|
|
1005
1321
|
KrnlPackageReconciler.reconcile(projectRoot, true);
|
|
1006
|
-
console.log(`\u2705 Created
|
|
1007
|
-
console.log(`\u2705 Created Frontend Concept Library:
|
|
1322
|
+
console.log(`\u2705 Created Service-Owned Library: ${path8.relative(projectRoot, bLibDir)}/ (Owner: ${targetService})`);
|
|
1323
|
+
console.log(`\u2705 Created Frontend Concept Library: ${path8.relative(projectRoot, fLibDir)}/`);
|
|
1008
1324
|
}
|
|
1009
|
-
|
|
1325
|
+
|
|
1326
|
+
// src/commands/generators/serviceGenerator.ts
|
|
1327
|
+
var fs8 = __toESM(require("fs"), 1);
|
|
1328
|
+
var path9 = __toESM(require("path"), 1);
|
|
1329
|
+
function generateService(name, projectRoot, defaultFrontend) {
|
|
1330
|
+
const frontendReference = defaultFrontend?.component ? {
|
|
1331
|
+
component: defaultFrontend.component,
|
|
1332
|
+
...defaultFrontend.package ? { package: defaultFrontend.package } : {},
|
|
1333
|
+
...defaultFrontend.export ? { export: defaultFrontend.export } : {},
|
|
1334
|
+
relationship: defaultFrontend.relationship ?? "recommended"
|
|
1335
|
+
} : void 0;
|
|
1336
|
+
const frontendConfig = frontendReference ? JSON.stringify(frontendReference, null, 2).replace(/\n/g, "\n ") : void 0;
|
|
1010
1337
|
const { backend } = getPlaneRoots(projectRoot);
|
|
1011
|
-
const
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
)
|
|
1338
|
+
const serviceDir = path9.join(backend, "services", name);
|
|
1339
|
+
const funcsDir = path9.join(serviceDir, "functionalities");
|
|
1340
|
+
const orchsDir = path9.join(serviceDir, "orchestrations");
|
|
1341
|
+
const libsDir = path9.join(serviceDir, "libraries");
|
|
1342
|
+
const testsDir = path9.join(serviceDir, "tests");
|
|
1343
|
+
fs8.mkdirSync(funcsDir, { recursive: true });
|
|
1344
|
+
fs8.mkdirSync(orchsDir, { recursive: true });
|
|
1345
|
+
fs8.mkdirSync(libsDir, { recursive: true });
|
|
1346
|
+
fs8.mkdirSync(testsDir, { recursive: true });
|
|
1347
|
+
const conceptName = `${name}Concepts`;
|
|
1348
|
+
const defaultLibDir = path9.join(libsDir, conceptName);
|
|
1349
|
+
fs8.mkdirSync(path9.join(defaultLibDir, "tests"), { recursive: true });
|
|
1350
|
+
fs8.writeFileSync(
|
|
1351
|
+
path9.join(defaultLibDir, "definitions.ts"),
|
|
1352
|
+
`/**
|
|
1353
|
+
* @file definitions.ts
|
|
1354
|
+
* @role component
|
|
1355
|
+
*/
|
|
1356
|
+
export interface ${name}Options {
|
|
1357
|
+
enabled?: boolean;
|
|
1358
|
+
}
|
|
1359
|
+
`
|
|
1025
1360
|
);
|
|
1026
|
-
|
|
1027
|
-
path9.join(
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1361
|
+
fs8.writeFileSync(
|
|
1362
|
+
path9.join(defaultLibDir, "functions.ts"),
|
|
1363
|
+
`/**
|
|
1364
|
+
* @file functions.ts
|
|
1365
|
+
* @role component
|
|
1366
|
+
*/
|
|
1367
|
+
import type { ${name}Options } from "./definitions.js";
|
|
1368
|
+
|
|
1369
|
+
export function format${name}Name(input: string, _opts?: ${name}Options): string {
|
|
1370
|
+
return "${name}: " + input;
|
|
1034
1371
|
}
|
|
1035
|
-
export default register;
|
|
1036
1372
|
`
|
|
1037
1373
|
);
|
|
1038
|
-
|
|
1374
|
+
fs8.writeFileSync(
|
|
1375
|
+
path9.join(defaultLibDir, "index.ts"),
|
|
1376
|
+
`export * from "./definitions.js";
|
|
1377
|
+
export * from "./functions.js";
|
|
1378
|
+
`
|
|
1379
|
+
);
|
|
1380
|
+
fs8.writeFileSync(
|
|
1381
|
+
path9.join(defaultLibDir, "manifest.json"),
|
|
1382
|
+
JSON.stringify({ name: conceptName, description: `${name} service-owned library`, dependencies: {} }, null, 2)
|
|
1383
|
+
);
|
|
1384
|
+
fs8.writeFileSync(
|
|
1385
|
+
path9.join(defaultLibDir, "tests", `${conceptName}.test.ts`),
|
|
1386
|
+
`import { describe, it, expect } from "vitest";
|
|
1387
|
+
import { format${name}Name } from "../functions.js";
|
|
1388
|
+
|
|
1389
|
+
describe("${conceptName}", () => {
|
|
1390
|
+
it("formats name correctly", () => {
|
|
1391
|
+
expect(format${name}Name("test")).toContain("${name}");
|
|
1392
|
+
});
|
|
1393
|
+
});
|
|
1394
|
+
`
|
|
1395
|
+
);
|
|
1396
|
+
const frontendProperty = frontendConfig ? ` defaultFrontend: ${frontendConfig},
|
|
1397
|
+
` : "";
|
|
1398
|
+
fs8.writeFileSync(
|
|
1399
|
+
path9.join(serviceDir, `${name}ServiceFacade.ts`),
|
|
1400
|
+
`import { ServiceFacade } from "@ultrst-armada/krnl-core";
|
|
1401
|
+
import * as ${name.toLowerCase()}Concepts from "./libraries/${conceptName}/index.js";
|
|
1402
|
+
|
|
1403
|
+
export const ${name}ServiceFacade = new ServiceFacade({
|
|
1404
|
+
id: "${name.toLowerCase()}.service",
|
|
1405
|
+
name: "${name}Service",
|
|
1406
|
+
version: "1.0.0",
|
|
1407
|
+
description: "${name} service facade",
|
|
1408
|
+
${frontendProperty} libraries: {
|
|
1409
|
+
${conceptName}: ${name.toLowerCase()}Concepts,
|
|
1410
|
+
},
|
|
1411
|
+
});
|
|
1412
|
+
|
|
1413
|
+
export default ${name}ServiceFacade;
|
|
1414
|
+
`
|
|
1415
|
+
);
|
|
1416
|
+
fs8.writeFileSync(
|
|
1417
|
+
path9.join(testsDir, `${name}ServiceFacade.test.ts`),
|
|
1418
|
+
`import { describe, it, expect } from "vitest";
|
|
1419
|
+
import { ${name}ServiceFacade } from "../${name}ServiceFacade.js";
|
|
1420
|
+
|
|
1421
|
+
describe("${name}ServiceFacade", () => {
|
|
1422
|
+
it("initializes and exposes service-owned library", () => {
|
|
1423
|
+
expect(${name}ServiceFacade.id).toBe("${name.toLowerCase()}.service");
|
|
1424
|
+
expect(${name}ServiceFacade.libraries.${conceptName}).toBeDefined();
|
|
1425
|
+
expect(typeof ${name}ServiceFacade.libraries.${conceptName}.format${name}Name).toBe("function");
|
|
1426
|
+
});
|
|
1427
|
+
});
|
|
1428
|
+
`
|
|
1429
|
+
);
|
|
1430
|
+
KrnlPackageReconciler.reconcile(projectRoot, true);
|
|
1431
|
+
console.log(`\u2705 Created Service: ${path9.relative(projectRoot, serviceDir)}/`);
|
|
1039
1432
|
}
|
|
1040
1433
|
|
|
1041
1434
|
// src/commands/generate.ts
|
|
1042
|
-
async function runGenerate(type, name,
|
|
1435
|
+
async function runGenerate(type, name, parentService, projectRoot = process.cwd(), options = {}) {
|
|
1043
1436
|
if (!name) {
|
|
1044
|
-
console.error(
|
|
1437
|
+
console.error(
|
|
1438
|
+
"\u274C Error: Resource name is required. Usage: krnl generate <service|orchestration|functionality|library> <Name> [parentService]"
|
|
1439
|
+
);
|
|
1045
1440
|
process.exit(1);
|
|
1046
1441
|
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1442
|
+
const normalizedType = type.toLowerCase().replace(/[-_]/g, "");
|
|
1443
|
+
switch (normalizedType) {
|
|
1444
|
+
case "service":
|
|
1445
|
+
generateService(name, projectRoot, options.defaultFrontend);
|
|
1446
|
+
break;
|
|
1447
|
+
case "functionalityorchestration":
|
|
1448
|
+
case "orchestration":
|
|
1449
|
+
generateFunctionalityOrchestration(name, projectRoot);
|
|
1050
1450
|
break;
|
|
1051
1451
|
case "functionality":
|
|
1052
|
-
generateFunctionality(name, projectRoot);
|
|
1452
|
+
generateFunctionality(name, projectRoot, parentService);
|
|
1053
1453
|
break;
|
|
1054
1454
|
case "library":
|
|
1055
|
-
generateLibrary(name, projectRoot);
|
|
1056
|
-
break;
|
|
1057
|
-
case "subapp":
|
|
1058
|
-
generateSubApp(name, projectRoot);
|
|
1455
|
+
generateLibrary(name, projectRoot, parentService);
|
|
1059
1456
|
break;
|
|
1060
1457
|
default:
|
|
1061
|
-
console.error(
|
|
1458
|
+
console.error(
|
|
1459
|
+
`\u274C Unknown resource type "${type}". Valid types: service, orchestration, functionality, library`
|
|
1460
|
+
);
|
|
1062
1461
|
process.exit(1);
|
|
1063
1462
|
}
|
|
1064
1463
|
}
|
|
1065
1464
|
|
|
1066
1465
|
// src/commands/watch.ts
|
|
1067
|
-
var
|
|
1466
|
+
var fs9 = __toESM(require("fs"), 1);
|
|
1068
1467
|
var path10 = __toESM(require("path"), 1);
|
|
1069
1468
|
function generateMagneticDeclarations(projectRoot = process.cwd()) {
|
|
1070
1469
|
const { results: functionalities, libDirs } = scanDirectory(projectRoot);
|
|
1071
1470
|
let dtsContent = `// Automatically generated by Krnl Magnetic Watcher. Do not edit manually.
|
|
1072
1471
|
|
|
1073
1472
|
`;
|
|
1074
|
-
dtsContent += `import {
|
|
1473
|
+
dtsContent += `import { Orchestration } from '@ultrst-armada/krnl-core';
|
|
1075
1474
|
|
|
1076
1475
|
`;
|
|
1077
1476
|
const globalDeclarations = [];
|
|
1078
1477
|
for (const func of functionalities) {
|
|
1079
1478
|
const helpersDir = path10.join(func.funcPath, "helper_functions");
|
|
1080
|
-
if (
|
|
1081
|
-
const files =
|
|
1479
|
+
if (fs9.existsSync(helpersDir)) {
|
|
1480
|
+
const files = fs9.readdirSync(helpersDir);
|
|
1082
1481
|
for (const file of files) {
|
|
1083
1482
|
if (file.endsWith(".js") || file.endsWith(".ts")) {
|
|
1084
1483
|
const filePath = path10.join(helpersDir, file);
|
|
@@ -1095,8 +1494,8 @@ function generateMagneticDeclarations(projectRoot = process.cwd()) {
|
|
|
1095
1494
|
}
|
|
1096
1495
|
}
|
|
1097
1496
|
const eventsDir = path10.join(func.funcPath, "events");
|
|
1098
|
-
if (
|
|
1099
|
-
const files =
|
|
1497
|
+
if (fs9.existsSync(eventsDir)) {
|
|
1498
|
+
const files = fs9.readdirSync(eventsDir);
|
|
1100
1499
|
for (const file of files) {
|
|
1101
1500
|
if (file.endsWith(".js") || file.endsWith(".ts")) {
|
|
1102
1501
|
const filePath = path10.join(eventsDir, file);
|
|
@@ -1123,12 +1522,12 @@ ${Array.from(new Set(globalDeclarations)).join("\n")}
|
|
|
1123
1522
|
`;
|
|
1124
1523
|
}
|
|
1125
1524
|
const outPath = path10.join(projectRoot, "krnl-magnetic.d.ts");
|
|
1126
|
-
|
|
1525
|
+
fs9.writeFileSync(outPath, dtsContent);
|
|
1127
1526
|
console.log(`[Krnl Watch] Updated ambient declarations: ${outPath}`);
|
|
1128
1527
|
}
|
|
1129
1528
|
function scanLibFiles(dir, projectRoot, decls) {
|
|
1130
|
-
if (!
|
|
1131
|
-
for (const entry of
|
|
1529
|
+
if (!fs9.existsSync(dir)) return;
|
|
1530
|
+
for (const entry of fs9.readdirSync(dir, { withFileTypes: true })) {
|
|
1132
1531
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
1133
1532
|
const full = path10.join(dir, entry.name);
|
|
1134
1533
|
if (entry.isDirectory()) {
|
|
@@ -1143,14 +1542,14 @@ function scanLibFiles(dir, projectRoot, decls) {
|
|
|
1143
1542
|
}
|
|
1144
1543
|
}
|
|
1145
1544
|
function scanDirectory(dir, results = [], libDirs = []) {
|
|
1146
|
-
if (!
|
|
1147
|
-
const list =
|
|
1545
|
+
if (!fs9.existsSync(dir)) return { results, libDirs };
|
|
1546
|
+
const list = fs9.readdirSync(dir, { withFileTypes: true });
|
|
1148
1547
|
for (const entry of list) {
|
|
1149
1548
|
if (entry.isDirectory()) {
|
|
1150
1549
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === ".git") continue;
|
|
1151
1550
|
const fullPath = path10.join(dir, entry.name);
|
|
1152
1551
|
if (entry.name === "functionalities") {
|
|
1153
|
-
const funcs =
|
|
1552
|
+
const funcs = fs9.readdirSync(fullPath, { withFileTypes: true });
|
|
1154
1553
|
for (const f of funcs) {
|
|
1155
1554
|
if (f.isDirectory()) results.push({ funcPath: path10.join(fullPath, f.name), funcName: f.name });
|
|
1156
1555
|
}
|
|
@@ -1164,7 +1563,7 @@ function scanDirectory(dir, results = [], libDirs = []) {
|
|
|
1164
1563
|
return { results, libDirs };
|
|
1165
1564
|
}
|
|
1166
1565
|
function parseExports(filePath, defaultName) {
|
|
1167
|
-
const content =
|
|
1566
|
+
const content = fs9.readFileSync(filePath, "utf8");
|
|
1168
1567
|
const named = [];
|
|
1169
1568
|
let hasDefault = false;
|
|
1170
1569
|
const namedRegex = /export\s+(?:const|let|var|function|class|async\s+function)\s+([a-zA-Z0-9_$]+)/g;
|
|
@@ -1177,9 +1576,108 @@ function parseExports(filePath, defaultName) {
|
|
|
1177
1576
|
}
|
|
1178
1577
|
return { named, hasDefault };
|
|
1179
1578
|
}
|
|
1579
|
+
|
|
1580
|
+
// src/commands/build.ts
|
|
1581
|
+
var path11 = __toESM(require("path"), 1);
|
|
1582
|
+
var fs10 = __toESM(require("fs"), 1);
|
|
1583
|
+
var import_child_process = require("child_process");
|
|
1584
|
+
async function runBuild(projectRoot = process.cwd(), options = {}) {
|
|
1585
|
+
KrnlPackageReconciler.reconcile(projectRoot, true);
|
|
1586
|
+
const target = options.service || options.orchestration;
|
|
1587
|
+
if (target) {
|
|
1588
|
+
console.log(`\u{1F3D7}\uFE0F [Krnl Build] Target service/orchestration variant: "${target}"`);
|
|
1589
|
+
} else if (options.all) {
|
|
1590
|
+
console.log(`\u{1F3D7}\uFE0F [Krnl Build] Combined multi-service build`);
|
|
1591
|
+
}
|
|
1592
|
+
console.log("\u{1F50D} [Krnl Build] Running AST & layer purity validation...");
|
|
1593
|
+
const valid = await runValidate(projectRoot);
|
|
1594
|
+
if (!valid) {
|
|
1595
|
+
console.error("\u274C [Krnl Build] Build aborted due to validation errors.");
|
|
1596
|
+
return { success: false, error: "Validation failed" };
|
|
1597
|
+
}
|
|
1598
|
+
generateMagneticDeclarations(projectRoot);
|
|
1599
|
+
const tsConfigPath = path11.join(projectRoot, "tsconfig.json");
|
|
1600
|
+
if (fs10.existsSync(tsConfigPath)) {
|
|
1601
|
+
console.log("\u{1F3D7}\uFE0F [Krnl Build] Compiling TypeScript source files to dist/...");
|
|
1602
|
+
const localTsc = path11.join(projectRoot, "node_modules", ".bin", "tsc");
|
|
1603
|
+
const tscCmd = fs10.existsSync(localTsc) ? localTsc : "tsc";
|
|
1604
|
+
try {
|
|
1605
|
+
(0, import_child_process.execSync)(`${tscCmd} -p tsconfig.json`, { cwd: projectRoot, stdio: "inherit" });
|
|
1606
|
+
} catch (err) {
|
|
1607
|
+
console.error("\u274C [Krnl Build] TypeScript compilation failed.");
|
|
1608
|
+
return { success: false, error: "TypeScript compilation failed" };
|
|
1609
|
+
}
|
|
1610
|
+
} else {
|
|
1611
|
+
console.log("\u2139\uFE0F [Krnl Build] No tsconfig.json found; skipping TypeScript compiler invocation.");
|
|
1612
|
+
}
|
|
1613
|
+
console.log("\u2705 [Krnl Build] Project validation, declaration generation, and compilation completed successfully.");
|
|
1614
|
+
return { success: true };
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
// src/commands/dev.ts
|
|
1618
|
+
var http = __toESM(require("http"), 1);
|
|
1619
|
+
var path12 = __toESM(require("path"), 1);
|
|
1620
|
+
var fs11 = __toESM(require("fs"), 1);
|
|
1621
|
+
async function runDev(projectRoot = process.cwd(), options = {}) {
|
|
1622
|
+
const port = options.port ?? 8080;
|
|
1623
|
+
KrnlPackageReconciler.reconcile(projectRoot, true);
|
|
1624
|
+
generateMagneticDeclarations(projectRoot);
|
|
1625
|
+
if (options.dryRun) {
|
|
1626
|
+
console.log(`\u26A1 [Krnl Dev] Development environment verified on port ${port} (--dry-run).`);
|
|
1627
|
+
return {
|
|
1628
|
+
port,
|
|
1629
|
+
close: async () => {
|
|
1630
|
+
}
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
const server = http.createServer((req, res) => {
|
|
1634
|
+
res.setHeader("Content-Type", "application/json");
|
|
1635
|
+
const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
|
|
1636
|
+
if (url.pathname === "/" || url.pathname === "/health") {
|
|
1637
|
+
res.writeHead(200);
|
|
1638
|
+
res.end(JSON.stringify({ status: "ok", service: "krnl-dev", port, uptime: process.uptime() }));
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1641
|
+
if (url.pathname === "/manifest") {
|
|
1642
|
+
const pkgPath = path12.join(projectRoot, "package.json");
|
|
1643
|
+
const pkg = fs11.existsSync(pkgPath) ? JSON.parse(fs11.readFileSync(pkgPath, "utf8")) : {};
|
|
1644
|
+
res.writeHead(200);
|
|
1645
|
+
res.end(JSON.stringify({ name: pkg.name || "krnl-app", version: pkg.version || "1.0.0" }));
|
|
1646
|
+
return;
|
|
1647
|
+
}
|
|
1648
|
+
res.writeHead(404);
|
|
1649
|
+
res.end(JSON.stringify({ error: "Route not found" }));
|
|
1650
|
+
});
|
|
1651
|
+
await new Promise((resolve2, reject) => {
|
|
1652
|
+
server.listen(port, () => resolve2());
|
|
1653
|
+
server.on("error", reject);
|
|
1654
|
+
});
|
|
1655
|
+
console.log(`\u26A1 [Krnl Dev] Development server listening on http://localhost:${port}`);
|
|
1656
|
+
const watcher = fs11.watch(projectRoot, { recursive: true }, (_evt, filename) => {
|
|
1657
|
+
if (filename && (filename.endsWith(".ts") || filename.endsWith(".js")) && !filename.includes("krnl-magnetic.d.ts")) {
|
|
1658
|
+
try {
|
|
1659
|
+
generateMagneticDeclarations(projectRoot);
|
|
1660
|
+
} catch {
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
if (filename && filename.endsWith("manifest.json")) {
|
|
1664
|
+
try {
|
|
1665
|
+
KrnlPackageReconciler.reconcile(projectRoot, true);
|
|
1666
|
+
} catch {
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
});
|
|
1670
|
+
const close = async () => {
|
|
1671
|
+
watcher.close();
|
|
1672
|
+
await new Promise((resolve2) => server.close(() => resolve2()));
|
|
1673
|
+
};
|
|
1674
|
+
return { server, close, port };
|
|
1675
|
+
}
|
|
1180
1676
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1181
1677
|
0 && (module.exports = {
|
|
1182
1678
|
generateMagneticDeclarations,
|
|
1679
|
+
runBuild,
|
|
1680
|
+
runDev,
|
|
1183
1681
|
runGenerate,
|
|
1184
1682
|
runValidate
|
|
1185
1683
|
});
|