@ultrst-armada/krnl 1.0.2 → 1.0.3
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 +12 -8
- package/packages/cli/dist/bin/krnl.cjs +793 -330
- package/packages/cli/dist/bin/krnl.js +50 -65
- package/packages/cli/dist/chunk-6SHSECXR.js +1628 -0
- package/packages/cli/dist/index.cjs +746 -262
- 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 +2905 -139
- package/packages/core/dist/index.d.cts +611 -27
- package/packages/core/dist/index.d.ts +611 -27
- package/packages/core/dist/index.js +2897 -139
- package/packages/core/package.json +14 -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,98 @@ 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};
|
|
607
|
-
`
|
|
608
|
-
);
|
|
609
|
-
fs4.writeFileSync(
|
|
610
|
-
path6.join(bEntityDir, "orchestrations", "DefaultFlow.ts"),
|
|
611
|
-
`export function configureDefaultFlow(entity: any) {
|
|
612
|
-
return entity.flow("defaultFlow")
|
|
613
|
-
.register({ visibility: "public" });
|
|
614
|
-
}
|
|
905
|
+
export default ${name}FunctionalityOrchestration;
|
|
615
906
|
`
|
|
616
907
|
);
|
|
617
908
|
fs4.writeFileSync(
|
|
618
|
-
|
|
619
|
-
`import { describe, it, expect } from
|
|
620
|
-
import { ${name} } from
|
|
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
|
+
var asyncHooks = globalThis.process?.getBuiltinModule?.("node:async_hooks");
|
|
669
934
|
var KrnlPackageReconciler = class {
|
|
670
935
|
/**
|
|
671
936
|
* Scans all manifest.json files across backend and frontend and reconciles root package.json.
|
|
@@ -713,7 +978,7 @@ var KrnlPackageReconciler = class {
|
|
|
713
978
|
}
|
|
714
979
|
resolvedDevDeps[pkg] = versions[versions.length - 1];
|
|
715
980
|
}
|
|
716
|
-
const pkgJsonPath =
|
|
981
|
+
const pkgJsonPath = path6.join(projectRoot, "package.json");
|
|
717
982
|
let updated = false;
|
|
718
983
|
if (fs5.existsSync(pkgJsonPath)) {
|
|
719
984
|
const pkgContent = JSON.parse(fs5.readFileSync(pkgJsonPath, "utf8"));
|
|
@@ -751,12 +1016,15 @@ var KrnlPackageReconciler = class {
|
|
|
751
1016
|
*/
|
|
752
1017
|
static findManifests(projectRoot) {
|
|
753
1018
|
const searchDirs = [
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
1019
|
+
path6.join(projectRoot, "krnl", "backend", "services"),
|
|
1020
|
+
path6.join(projectRoot, "krnl", "backend", "libraries"),
|
|
1021
|
+
path6.join(projectRoot, "krnl", "backend", "functionalities"),
|
|
1022
|
+
path6.join(projectRoot, "krnl", "frontend", "libraries"),
|
|
1023
|
+
path6.join(projectRoot, "krnl", "frontend", "functionalities"),
|
|
1024
|
+
path6.join(projectRoot, "src", "backend", "services"),
|
|
1025
|
+
path6.join(projectRoot, "src", "services"),
|
|
1026
|
+
path6.join(projectRoot, "src", "functionalities"),
|
|
1027
|
+
path6.join(projectRoot, "src", "libraries")
|
|
760
1028
|
];
|
|
761
1029
|
const found = [];
|
|
762
1030
|
for (const dir of searchDirs) {
|
|
@@ -771,7 +1039,7 @@ var KrnlPackageReconciler = class {
|
|
|
771
1039
|
const entries = fs5.readdirSync(dir, { withFileTypes: true });
|
|
772
1040
|
for (const entry of entries) {
|
|
773
1041
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === ".git") continue;
|
|
774
|
-
const full =
|
|
1042
|
+
const full = path6.join(dir, entry.name);
|
|
775
1043
|
if (entry.isDirectory()) {
|
|
776
1044
|
this.scanRecursive(full, found);
|
|
777
1045
|
} else if (entry.isFile() && entry.name === "manifest.json") {
|
|
@@ -784,16 +1052,40 @@ var KrnlPackageReconciler = class {
|
|
|
784
1052
|
};
|
|
785
1053
|
|
|
786
1054
|
// src/commands/generators/functionalityGenerator.ts
|
|
787
|
-
function generateFunctionality(name, projectRoot) {
|
|
1055
|
+
function generateFunctionality(name, projectRoot, parentServiceOrOptions) {
|
|
788
1056
|
const { backend, frontend } = getPlaneRoots(projectRoot);
|
|
789
|
-
const
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
1057
|
+
const options = typeof parentServiceOrOptions === "string" ? { parentService: parentServiceOrOptions } : parentServiceOrOptions || {};
|
|
1058
|
+
let targetService = options.parentService;
|
|
1059
|
+
if (!targetService) {
|
|
1060
|
+
const servicesDir = path7.join(backend, "services");
|
|
1061
|
+
if (fs6.existsSync(servicesDir)) {
|
|
1062
|
+
const existing = fs6.readdirSync(servicesDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
1063
|
+
if (existing.length === 1) {
|
|
1064
|
+
targetService = existing[0].name;
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
const bFuncDir = targetService ? path7.join(backend, "services", targetService, "functionalities", name) : path7.join(backend, "functionalities", name);
|
|
1069
|
+
fs6.mkdirSync(path7.join(bFuncDir, "main_function"), { recursive: true });
|
|
1070
|
+
fs6.mkdirSync(path7.join(bFuncDir, "helper_functions"), { recursive: true });
|
|
1071
|
+
fs6.mkdirSync(path7.join(bFuncDir, "events"), { recursive: true });
|
|
1072
|
+
fs6.mkdirSync(path7.join(bFuncDir, "tests"), { recursive: true });
|
|
1073
|
+
if (options.withState) {
|
|
1074
|
+
fs6.mkdirSync(path7.join(bFuncDir, "state_data"), { recursive: true });
|
|
1075
|
+
fs6.writeFileSync(
|
|
1076
|
+
path7.join(bFuncDir, "state_data", "state.ts"),
|
|
1077
|
+
`export interface ${name}State {
|
|
1078
|
+
executionCount: number;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
export const initialState: ${name}State = {
|
|
1082
|
+
executionCount: 0
|
|
1083
|
+
};
|
|
1084
|
+
`
|
|
1085
|
+
);
|
|
1086
|
+
}
|
|
795
1087
|
fs6.writeFileSync(
|
|
796
|
-
|
|
1088
|
+
path7.join(bFuncDir, `${name}Atom.ts`),
|
|
797
1089
|
`export interface ${name}Input {
|
|
798
1090
|
payload?: string;
|
|
799
1091
|
}
|
|
@@ -805,10 +1097,11 @@ export interface ${name}Output {
|
|
|
805
1097
|
`
|
|
806
1098
|
);
|
|
807
1099
|
fs6.writeFileSync(
|
|
808
|
-
|
|
1100
|
+
path7.join(bFuncDir, "manifest.json"),
|
|
809
1101
|
JSON.stringify(
|
|
810
1102
|
{
|
|
811
1103
|
name,
|
|
1104
|
+
service: targetService || void 0,
|
|
812
1105
|
description: `${name} quad-unit functionality`,
|
|
813
1106
|
dependencies: {}
|
|
814
1107
|
},
|
|
@@ -817,10 +1110,10 @@ export interface ${name}Output {
|
|
|
817
1110
|
)
|
|
818
1111
|
);
|
|
819
1112
|
fs6.writeFileSync(
|
|
820
|
-
|
|
1113
|
+
path7.join(bFuncDir, "main_function", "logic.ts"),
|
|
821
1114
|
`import type { ${name}Input, ${name}Output } from "../${name}Atom.js";
|
|
822
1115
|
|
|
823
|
-
export const main = async (input: ${name}Input,
|
|
1116
|
+
export const main = async (input: ${name}Input, context: any): Promise<${name}Output> => {
|
|
824
1117
|
return {
|
|
825
1118
|
success: true,
|
|
826
1119
|
timestamp: Date.now()
|
|
@@ -829,24 +1122,13 @@ export const main = async (input: ${name}Input, { state }: any): Promise<${name}
|
|
|
829
1122
|
`
|
|
830
1123
|
);
|
|
831
1124
|
fs6.writeFileSync(
|
|
832
|
-
|
|
1125
|
+
path7.join(bFuncDir, "main_function", "lifecycle.ts"),
|
|
833
1126
|
`export async function onMount() {}
|
|
834
1127
|
export async function onTeardown() {}
|
|
835
1128
|
`
|
|
836
1129
|
);
|
|
837
1130
|
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"),
|
|
1131
|
+
path7.join(bFuncDir, "helper_functions", "helper.ts"),
|
|
850
1132
|
`/**
|
|
851
1133
|
* @role component
|
|
852
1134
|
*/
|
|
@@ -856,7 +1138,7 @@ export function exampleHelper(): boolean {
|
|
|
856
1138
|
`
|
|
857
1139
|
);
|
|
858
1140
|
fs6.writeFileSync(
|
|
859
|
-
|
|
1141
|
+
path7.join(bFuncDir, "events", "events.ts"),
|
|
860
1142
|
`/**
|
|
861
1143
|
* @role component
|
|
862
1144
|
*/
|
|
@@ -866,7 +1148,7 @@ export interface ${name}CompletedEvent {
|
|
|
866
1148
|
`
|
|
867
1149
|
);
|
|
868
1150
|
fs6.writeFileSync(
|
|
869
|
-
|
|
1151
|
+
path7.join(bFuncDir, "tests", `${name}.test.ts`),
|
|
870
1152
|
`import { describe, it, expect } from "vitest";
|
|
871
1153
|
|
|
872
1154
|
describe("${name} functionality", () => {
|
|
@@ -876,10 +1158,10 @@ describe("${name} functionality", () => {
|
|
|
876
1158
|
});
|
|
877
1159
|
`
|
|
878
1160
|
);
|
|
879
|
-
const fFuncDir =
|
|
880
|
-
fs6.mkdirSync(
|
|
1161
|
+
const fFuncDir = path7.join(frontend, "functionalities", name);
|
|
1162
|
+
fs6.mkdirSync(path7.join(fFuncDir, "tests"), { recursive: true });
|
|
881
1163
|
fs6.writeFileSync(
|
|
882
|
-
|
|
1164
|
+
path7.join(fFuncDir, `${name}0.tsx`),
|
|
883
1165
|
`import React from "react";
|
|
884
1166
|
|
|
885
1167
|
export const ${name}0: React.FC = () => {
|
|
@@ -894,11 +1176,11 @@ export default ${name}0;
|
|
|
894
1176
|
`
|
|
895
1177
|
);
|
|
896
1178
|
fs6.writeFileSync(
|
|
897
|
-
|
|
1179
|
+
path7.join(fFuncDir, "manifest.json"),
|
|
898
1180
|
JSON.stringify({ name: `${name}UI`, dependencies: {} }, null, 2)
|
|
899
1181
|
);
|
|
900
1182
|
fs6.writeFileSync(
|
|
901
|
-
|
|
1183
|
+
path7.join(fFuncDir, "tests", `${name}0.test.tsx`),
|
|
902
1184
|
`import { describe, it, expect } from "vitest";
|
|
903
1185
|
|
|
904
1186
|
describe("${name}0 Component", () => {
|
|
@@ -909,20 +1191,33 @@ describe("${name}0 Component", () => {
|
|
|
909
1191
|
`
|
|
910
1192
|
);
|
|
911
1193
|
KrnlPackageReconciler.reconcile(projectRoot, true);
|
|
912
|
-
console.log(`\u2705 Created Backend Functionality
|
|
913
|
-
console.log(`\u2705 Created Frontend Functionality:
|
|
1194
|
+
console.log(`\u2705 Created Backend Functionality: ${path7.relative(projectRoot, bFuncDir)}/`);
|
|
1195
|
+
console.log(`\u2705 Created Frontend Functionality: ${path7.relative(projectRoot, fFuncDir)}/`);
|
|
914
1196
|
}
|
|
915
1197
|
|
|
916
1198
|
// src/commands/generators/libraryGenerator.ts
|
|
917
1199
|
var fs7 = __toESM(require("fs"), 1);
|
|
918
|
-
var
|
|
919
|
-
function generateLibrary(name, projectRoot) {
|
|
1200
|
+
var path8 = __toESM(require("path"), 1);
|
|
1201
|
+
function generateLibrary(name, projectRoot, parentService) {
|
|
920
1202
|
const { backend, frontend } = getPlaneRoots(projectRoot);
|
|
921
1203
|
const conceptName = name.endsWith("Concepts") ? name : `${name}Concepts`;
|
|
922
|
-
|
|
923
|
-
|
|
1204
|
+
let targetService = parentService;
|
|
1205
|
+
if (!targetService) {
|
|
1206
|
+
const servicesDir = path8.join(backend, "services");
|
|
1207
|
+
if (fs7.existsSync(servicesDir)) {
|
|
1208
|
+
const existing = fs7.readdirSync(servicesDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
1209
|
+
if (existing.length === 1) {
|
|
1210
|
+
targetService = existing[0].name;
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
if (!targetService) {
|
|
1215
|
+
targetService = "App";
|
|
1216
|
+
}
|
|
1217
|
+
const bLibDir = path8.join(backend, "services", targetService, "libraries", conceptName);
|
|
1218
|
+
fs7.mkdirSync(path8.join(bLibDir, "tests"), { recursive: true });
|
|
924
1219
|
fs7.writeFileSync(
|
|
925
|
-
|
|
1220
|
+
path8.join(bLibDir, "definitions.ts"),
|
|
926
1221
|
`/**
|
|
927
1222
|
* @file definitions.ts
|
|
928
1223
|
* @role component
|
|
@@ -933,7 +1228,7 @@ export interface ${conceptName}Options {
|
|
|
933
1228
|
`
|
|
934
1229
|
);
|
|
935
1230
|
fs7.writeFileSync(
|
|
936
|
-
|
|
1231
|
+
path8.join(bLibDir, "functions.ts"),
|
|
937
1232
|
`/**
|
|
938
1233
|
* @file functions.ts
|
|
939
1234
|
* @role component
|
|
@@ -946,31 +1241,38 @@ export function ${name.toLowerCase()}Transform<T>(data: T, _opts?: ${conceptName
|
|
|
946
1241
|
`
|
|
947
1242
|
);
|
|
948
1243
|
fs7.writeFileSync(
|
|
949
|
-
|
|
950
|
-
|
|
1244
|
+
path8.join(bLibDir, "index.ts"),
|
|
1245
|
+
`export * from "./definitions.js";
|
|
1246
|
+
export * from "./functions.js";
|
|
1247
|
+
`
|
|
1248
|
+
);
|
|
1249
|
+
fs7.writeFileSync(
|
|
1250
|
+
path8.join(bLibDir, "manifest.json"),
|
|
1251
|
+
JSON.stringify({ name: conceptName, service: targetService, dependencies: {} }, null, 2)
|
|
951
1252
|
);
|
|
952
1253
|
fs7.writeFileSync(
|
|
953
|
-
|
|
1254
|
+
path8.join(bLibDir, "tests", `${conceptName}.test.ts`),
|
|
954
1255
|
`import { describe, it, expect } from "vitest";
|
|
1256
|
+
import { ${name.toLowerCase()}Transform } from "../functions.js";
|
|
955
1257
|
|
|
956
1258
|
describe("${conceptName}", () => {
|
|
957
1259
|
it("runs correctly", () => {
|
|
958
|
-
expect(
|
|
1260
|
+
expect(${name.toLowerCase()}Transform(42)).toBe(42);
|
|
959
1261
|
});
|
|
960
1262
|
});
|
|
961
1263
|
`
|
|
962
1264
|
);
|
|
963
|
-
const fLibDir =
|
|
964
|
-
fs7.mkdirSync(
|
|
1265
|
+
const fLibDir = path8.join(frontend, "libraries", conceptName);
|
|
1266
|
+
fs7.mkdirSync(path8.join(fLibDir, "tests"), { recursive: true });
|
|
965
1267
|
fs7.writeFileSync(
|
|
966
|
-
|
|
1268
|
+
path8.join(fLibDir, "definitions.ts"),
|
|
967
1269
|
`export interface ${name}Props {
|
|
968
1270
|
label?: string;
|
|
969
1271
|
}
|
|
970
1272
|
`
|
|
971
1273
|
);
|
|
972
1274
|
fs7.writeFileSync(
|
|
973
|
-
|
|
1275
|
+
path8.join(fLibDir, "components.tsx"),
|
|
974
1276
|
`import React from "react";
|
|
975
1277
|
import type { ${name}Props } from "./definitions.js";
|
|
976
1278
|
import "./styles.css";
|
|
@@ -981,18 +1283,18 @@ export const ${name}: React.FC<${name}Props> = ({ label = "${name}" }) => {
|
|
|
981
1283
|
`
|
|
982
1284
|
);
|
|
983
1285
|
fs7.writeFileSync(
|
|
984
|
-
|
|
1286
|
+
path8.join(fLibDir, "styles.css"),
|
|
985
1287
|
`.krnl-${name.toLowerCase()} {
|
|
986
1288
|
font-family: inherit;
|
|
987
1289
|
}
|
|
988
1290
|
`
|
|
989
1291
|
);
|
|
990
1292
|
fs7.writeFileSync(
|
|
991
|
-
|
|
1293
|
+
path8.join(fLibDir, "manifest.json"),
|
|
992
1294
|
JSON.stringify({ name: `${conceptName}UI`, dependencies: {} }, null, 2)
|
|
993
1295
|
);
|
|
994
1296
|
fs7.writeFileSync(
|
|
995
|
-
|
|
1297
|
+
path8.join(fLibDir, "tests", `${name}.test.tsx`),
|
|
996
1298
|
`import { describe, it, expect } from "vitest";
|
|
997
1299
|
|
|
998
1300
|
describe("${name} UI Concept", () => {
|
|
@@ -1003,82 +1305,165 @@ describe("${name} UI Concept", () => {
|
|
|
1003
1305
|
`
|
|
1004
1306
|
);
|
|
1005
1307
|
KrnlPackageReconciler.reconcile(projectRoot, true);
|
|
1006
|
-
console.log(`\u2705 Created
|
|
1007
|
-
console.log(`\u2705 Created Frontend Concept Library:
|
|
1308
|
+
console.log(`\u2705 Created Service-Owned Library: ${path8.relative(projectRoot, bLibDir)}/ (Owner: ${targetService})`);
|
|
1309
|
+
console.log(`\u2705 Created Frontend Concept Library: ${path8.relative(projectRoot, fLibDir)}/`);
|
|
1008
1310
|
}
|
|
1009
|
-
|
|
1311
|
+
|
|
1312
|
+
// src/commands/generators/serviceGenerator.ts
|
|
1313
|
+
var fs8 = __toESM(require("fs"), 1);
|
|
1314
|
+
var path9 = __toESM(require("path"), 1);
|
|
1315
|
+
function generateService(name, projectRoot, defaultFrontend) {
|
|
1316
|
+
const frontendReference = defaultFrontend?.component ? {
|
|
1317
|
+
component: defaultFrontend.component,
|
|
1318
|
+
...defaultFrontend.package ? { package: defaultFrontend.package } : {},
|
|
1319
|
+
...defaultFrontend.export ? { export: defaultFrontend.export } : {},
|
|
1320
|
+
relationship: defaultFrontend.relationship ?? "recommended"
|
|
1321
|
+
} : void 0;
|
|
1322
|
+
const frontendConfig = frontendReference ? JSON.stringify(frontendReference, null, 2).replace(/\n/g, "\n ") : void 0;
|
|
1010
1323
|
const { backend } = getPlaneRoots(projectRoot);
|
|
1011
|
-
const
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
)
|
|
1324
|
+
const serviceDir = path9.join(backend, "services", name);
|
|
1325
|
+
const funcsDir = path9.join(serviceDir, "functionalities");
|
|
1326
|
+
const orchsDir = path9.join(serviceDir, "orchestrations");
|
|
1327
|
+
const libsDir = path9.join(serviceDir, "libraries");
|
|
1328
|
+
const testsDir = path9.join(serviceDir, "tests");
|
|
1329
|
+
fs8.mkdirSync(funcsDir, { recursive: true });
|
|
1330
|
+
fs8.mkdirSync(orchsDir, { recursive: true });
|
|
1331
|
+
fs8.mkdirSync(libsDir, { recursive: true });
|
|
1332
|
+
fs8.mkdirSync(testsDir, { recursive: true });
|
|
1333
|
+
const conceptName = `${name}Concepts`;
|
|
1334
|
+
const defaultLibDir = path9.join(libsDir, conceptName);
|
|
1335
|
+
fs8.mkdirSync(path9.join(defaultLibDir, "tests"), { recursive: true });
|
|
1336
|
+
fs8.writeFileSync(
|
|
1337
|
+
path9.join(defaultLibDir, "definitions.ts"),
|
|
1338
|
+
`/**
|
|
1339
|
+
* @file definitions.ts
|
|
1340
|
+
* @role component
|
|
1341
|
+
*/
|
|
1342
|
+
export interface ${name}Options {
|
|
1343
|
+
enabled?: boolean;
|
|
1344
|
+
}
|
|
1345
|
+
`
|
|
1025
1346
|
);
|
|
1026
|
-
|
|
1027
|
-
path9.join(
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1347
|
+
fs8.writeFileSync(
|
|
1348
|
+
path9.join(defaultLibDir, "functions.ts"),
|
|
1349
|
+
`/**
|
|
1350
|
+
* @file functions.ts
|
|
1351
|
+
* @role component
|
|
1352
|
+
*/
|
|
1353
|
+
import type { ${name}Options } from "./definitions.js";
|
|
1354
|
+
|
|
1355
|
+
export function format${name}Name(input: string, _opts?: ${name}Options): string {
|
|
1356
|
+
return "${name}: " + input;
|
|
1034
1357
|
}
|
|
1035
|
-
export default register;
|
|
1036
1358
|
`
|
|
1037
1359
|
);
|
|
1038
|
-
|
|
1360
|
+
fs8.writeFileSync(
|
|
1361
|
+
path9.join(defaultLibDir, "index.ts"),
|
|
1362
|
+
`export * from "./definitions.js";
|
|
1363
|
+
export * from "./functions.js";
|
|
1364
|
+
`
|
|
1365
|
+
);
|
|
1366
|
+
fs8.writeFileSync(
|
|
1367
|
+
path9.join(defaultLibDir, "manifest.json"),
|
|
1368
|
+
JSON.stringify({ name: conceptName, description: `${name} service-owned library`, dependencies: {} }, null, 2)
|
|
1369
|
+
);
|
|
1370
|
+
fs8.writeFileSync(
|
|
1371
|
+
path9.join(defaultLibDir, "tests", `${conceptName}.test.ts`),
|
|
1372
|
+
`import { describe, it, expect } from "vitest";
|
|
1373
|
+
import { format${name}Name } from "../functions.js";
|
|
1374
|
+
|
|
1375
|
+
describe("${conceptName}", () => {
|
|
1376
|
+
it("formats name correctly", () => {
|
|
1377
|
+
expect(format${name}Name("test")).toContain("${name}");
|
|
1378
|
+
});
|
|
1379
|
+
});
|
|
1380
|
+
`
|
|
1381
|
+
);
|
|
1382
|
+
const frontendProperty = frontendConfig ? ` defaultFrontend: ${frontendConfig},
|
|
1383
|
+
` : "";
|
|
1384
|
+
fs8.writeFileSync(
|
|
1385
|
+
path9.join(serviceDir, `${name}ServiceFacade.ts`),
|
|
1386
|
+
`import { ServiceFacade } from "@ultrst-armada/krnl-core";
|
|
1387
|
+
import * as ${name.toLowerCase()}Concepts from "./libraries/${conceptName}/index.js";
|
|
1388
|
+
|
|
1389
|
+
export const ${name}ServiceFacade = new ServiceFacade({
|
|
1390
|
+
id: "${name.toLowerCase()}.service",
|
|
1391
|
+
name: "${name}Service",
|
|
1392
|
+
version: "1.0.0",
|
|
1393
|
+
description: "${name} service facade",
|
|
1394
|
+
${frontendProperty} libraries: {
|
|
1395
|
+
${conceptName}: ${name.toLowerCase()}Concepts,
|
|
1396
|
+
},
|
|
1397
|
+
});
|
|
1398
|
+
|
|
1399
|
+
export default ${name}ServiceFacade;
|
|
1400
|
+
`
|
|
1401
|
+
);
|
|
1402
|
+
fs8.writeFileSync(
|
|
1403
|
+
path9.join(testsDir, `${name}ServiceFacade.test.ts`),
|
|
1404
|
+
`import { describe, it, expect } from "vitest";
|
|
1405
|
+
import { ${name}ServiceFacade } from "../${name}ServiceFacade.js";
|
|
1406
|
+
|
|
1407
|
+
describe("${name}ServiceFacade", () => {
|
|
1408
|
+
it("initializes and exposes service-owned library", () => {
|
|
1409
|
+
expect(${name}ServiceFacade.id).toBe("${name.toLowerCase()}.service");
|
|
1410
|
+
expect(${name}ServiceFacade.libraries.${conceptName}).toBeDefined();
|
|
1411
|
+
expect(typeof ${name}ServiceFacade.libraries.${conceptName}.format${name}Name).toBe("function");
|
|
1412
|
+
});
|
|
1413
|
+
});
|
|
1414
|
+
`
|
|
1415
|
+
);
|
|
1416
|
+
KrnlPackageReconciler.reconcile(projectRoot, true);
|
|
1417
|
+
console.log(`\u2705 Created Service: ${path9.relative(projectRoot, serviceDir)}/`);
|
|
1039
1418
|
}
|
|
1040
1419
|
|
|
1041
1420
|
// src/commands/generate.ts
|
|
1042
|
-
async function runGenerate(type, name,
|
|
1421
|
+
async function runGenerate(type, name, parentService, projectRoot = process.cwd(), options = {}) {
|
|
1043
1422
|
if (!name) {
|
|
1044
|
-
console.error(
|
|
1423
|
+
console.error(
|
|
1424
|
+
"\u274C Error: Resource name is required. Usage: krnl generate <service|orchestration|functionality|library> <Name> [parentService]"
|
|
1425
|
+
);
|
|
1045
1426
|
process.exit(1);
|
|
1046
1427
|
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1428
|
+
const normalizedType = type.toLowerCase().replace(/[-_]/g, "");
|
|
1429
|
+
switch (normalizedType) {
|
|
1430
|
+
case "service":
|
|
1431
|
+
generateService(name, projectRoot, options.defaultFrontend);
|
|
1432
|
+
break;
|
|
1433
|
+
case "functionalityorchestration":
|
|
1434
|
+
case "orchestration":
|
|
1435
|
+
generateFunctionalityOrchestration(name, projectRoot);
|
|
1050
1436
|
break;
|
|
1051
1437
|
case "functionality":
|
|
1052
|
-
generateFunctionality(name, projectRoot);
|
|
1438
|
+
generateFunctionality(name, projectRoot, parentService);
|
|
1053
1439
|
break;
|
|
1054
1440
|
case "library":
|
|
1055
|
-
generateLibrary(name, projectRoot);
|
|
1056
|
-
break;
|
|
1057
|
-
case "subapp":
|
|
1058
|
-
generateSubApp(name, projectRoot);
|
|
1441
|
+
generateLibrary(name, projectRoot, parentService);
|
|
1059
1442
|
break;
|
|
1060
1443
|
default:
|
|
1061
|
-
console.error(
|
|
1444
|
+
console.error(
|
|
1445
|
+
`\u274C Unknown resource type "${type}". Valid types: service, orchestration, functionality, library`
|
|
1446
|
+
);
|
|
1062
1447
|
process.exit(1);
|
|
1063
1448
|
}
|
|
1064
1449
|
}
|
|
1065
1450
|
|
|
1066
1451
|
// src/commands/watch.ts
|
|
1067
|
-
var
|
|
1452
|
+
var fs9 = __toESM(require("fs"), 1);
|
|
1068
1453
|
var path10 = __toESM(require("path"), 1);
|
|
1069
1454
|
function generateMagneticDeclarations(projectRoot = process.cwd()) {
|
|
1070
1455
|
const { results: functionalities, libDirs } = scanDirectory(projectRoot);
|
|
1071
1456
|
let dtsContent = `// Automatically generated by Krnl Magnetic Watcher. Do not edit manually.
|
|
1072
1457
|
|
|
1073
1458
|
`;
|
|
1074
|
-
dtsContent += `import {
|
|
1459
|
+
dtsContent += `import { Orchestration } from '@ultrst-armada/krnl-core';
|
|
1075
1460
|
|
|
1076
1461
|
`;
|
|
1077
1462
|
const globalDeclarations = [];
|
|
1078
1463
|
for (const func of functionalities) {
|
|
1079
1464
|
const helpersDir = path10.join(func.funcPath, "helper_functions");
|
|
1080
|
-
if (
|
|
1081
|
-
const files =
|
|
1465
|
+
if (fs9.existsSync(helpersDir)) {
|
|
1466
|
+
const files = fs9.readdirSync(helpersDir);
|
|
1082
1467
|
for (const file of files) {
|
|
1083
1468
|
if (file.endsWith(".js") || file.endsWith(".ts")) {
|
|
1084
1469
|
const filePath = path10.join(helpersDir, file);
|
|
@@ -1095,8 +1480,8 @@ function generateMagneticDeclarations(projectRoot = process.cwd()) {
|
|
|
1095
1480
|
}
|
|
1096
1481
|
}
|
|
1097
1482
|
const eventsDir = path10.join(func.funcPath, "events");
|
|
1098
|
-
if (
|
|
1099
|
-
const files =
|
|
1483
|
+
if (fs9.existsSync(eventsDir)) {
|
|
1484
|
+
const files = fs9.readdirSync(eventsDir);
|
|
1100
1485
|
for (const file of files) {
|
|
1101
1486
|
if (file.endsWith(".js") || file.endsWith(".ts")) {
|
|
1102
1487
|
const filePath = path10.join(eventsDir, file);
|
|
@@ -1123,12 +1508,12 @@ ${Array.from(new Set(globalDeclarations)).join("\n")}
|
|
|
1123
1508
|
`;
|
|
1124
1509
|
}
|
|
1125
1510
|
const outPath = path10.join(projectRoot, "krnl-magnetic.d.ts");
|
|
1126
|
-
|
|
1511
|
+
fs9.writeFileSync(outPath, dtsContent);
|
|
1127
1512
|
console.log(`[Krnl Watch] Updated ambient declarations: ${outPath}`);
|
|
1128
1513
|
}
|
|
1129
1514
|
function scanLibFiles(dir, projectRoot, decls) {
|
|
1130
|
-
if (!
|
|
1131
|
-
for (const entry of
|
|
1515
|
+
if (!fs9.existsSync(dir)) return;
|
|
1516
|
+
for (const entry of fs9.readdirSync(dir, { withFileTypes: true })) {
|
|
1132
1517
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
1133
1518
|
const full = path10.join(dir, entry.name);
|
|
1134
1519
|
if (entry.isDirectory()) {
|
|
@@ -1143,14 +1528,14 @@ function scanLibFiles(dir, projectRoot, decls) {
|
|
|
1143
1528
|
}
|
|
1144
1529
|
}
|
|
1145
1530
|
function scanDirectory(dir, results = [], libDirs = []) {
|
|
1146
|
-
if (!
|
|
1147
|
-
const list =
|
|
1531
|
+
if (!fs9.existsSync(dir)) return { results, libDirs };
|
|
1532
|
+
const list = fs9.readdirSync(dir, { withFileTypes: true });
|
|
1148
1533
|
for (const entry of list) {
|
|
1149
1534
|
if (entry.isDirectory()) {
|
|
1150
1535
|
if (entry.name === "node_modules" || entry.name === "dist" || entry.name === ".git") continue;
|
|
1151
1536
|
const fullPath = path10.join(dir, entry.name);
|
|
1152
1537
|
if (entry.name === "functionalities") {
|
|
1153
|
-
const funcs =
|
|
1538
|
+
const funcs = fs9.readdirSync(fullPath, { withFileTypes: true });
|
|
1154
1539
|
for (const f of funcs) {
|
|
1155
1540
|
if (f.isDirectory()) results.push({ funcPath: path10.join(fullPath, f.name), funcName: f.name });
|
|
1156
1541
|
}
|
|
@@ -1164,7 +1549,7 @@ function scanDirectory(dir, results = [], libDirs = []) {
|
|
|
1164
1549
|
return { results, libDirs };
|
|
1165
1550
|
}
|
|
1166
1551
|
function parseExports(filePath, defaultName) {
|
|
1167
|
-
const content =
|
|
1552
|
+
const content = fs9.readFileSync(filePath, "utf8");
|
|
1168
1553
|
const named = [];
|
|
1169
1554
|
let hasDefault = false;
|
|
1170
1555
|
const namedRegex = /export\s+(?:const|let|var|function|class|async\s+function)\s+([a-zA-Z0-9_$]+)/g;
|
|
@@ -1177,9 +1562,108 @@ function parseExports(filePath, defaultName) {
|
|
|
1177
1562
|
}
|
|
1178
1563
|
return { named, hasDefault };
|
|
1179
1564
|
}
|
|
1565
|
+
|
|
1566
|
+
// src/commands/build.ts
|
|
1567
|
+
var path11 = __toESM(require("path"), 1);
|
|
1568
|
+
var fs10 = __toESM(require("fs"), 1);
|
|
1569
|
+
var import_child_process = require("child_process");
|
|
1570
|
+
async function runBuild(projectRoot = process.cwd(), options = {}) {
|
|
1571
|
+
KrnlPackageReconciler.reconcile(projectRoot, true);
|
|
1572
|
+
const target = options.service || options.orchestration;
|
|
1573
|
+
if (target) {
|
|
1574
|
+
console.log(`\u{1F3D7}\uFE0F [Krnl Build] Target service/orchestration variant: "${target}"`);
|
|
1575
|
+
} else if (options.all) {
|
|
1576
|
+
console.log(`\u{1F3D7}\uFE0F [Krnl Build] Combined multi-service build`);
|
|
1577
|
+
}
|
|
1578
|
+
console.log("\u{1F50D} [Krnl Build] Running AST & layer purity validation...");
|
|
1579
|
+
const valid = await runValidate(projectRoot);
|
|
1580
|
+
if (!valid) {
|
|
1581
|
+
console.error("\u274C [Krnl Build] Build aborted due to validation errors.");
|
|
1582
|
+
return { success: false, error: "Validation failed" };
|
|
1583
|
+
}
|
|
1584
|
+
generateMagneticDeclarations(projectRoot);
|
|
1585
|
+
const tsConfigPath = path11.join(projectRoot, "tsconfig.json");
|
|
1586
|
+
if (fs10.existsSync(tsConfigPath)) {
|
|
1587
|
+
console.log("\u{1F3D7}\uFE0F [Krnl Build] Compiling TypeScript source files to dist/...");
|
|
1588
|
+
const localTsc = path11.join(projectRoot, "node_modules", ".bin", "tsc");
|
|
1589
|
+
const tscCmd = fs10.existsSync(localTsc) ? localTsc : "tsc";
|
|
1590
|
+
try {
|
|
1591
|
+
(0, import_child_process.execSync)(`${tscCmd} -p tsconfig.json`, { cwd: projectRoot, stdio: "inherit" });
|
|
1592
|
+
} catch (err) {
|
|
1593
|
+
console.error("\u274C [Krnl Build] TypeScript compilation failed.");
|
|
1594
|
+
return { success: false, error: "TypeScript compilation failed" };
|
|
1595
|
+
}
|
|
1596
|
+
} else {
|
|
1597
|
+
console.log("\u2139\uFE0F [Krnl Build] No tsconfig.json found; skipping TypeScript compiler invocation.");
|
|
1598
|
+
}
|
|
1599
|
+
console.log("\u2705 [Krnl Build] Project validation, declaration generation, and compilation completed successfully.");
|
|
1600
|
+
return { success: true };
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
// src/commands/dev.ts
|
|
1604
|
+
var http = __toESM(require("http"), 1);
|
|
1605
|
+
var path12 = __toESM(require("path"), 1);
|
|
1606
|
+
var fs11 = __toESM(require("fs"), 1);
|
|
1607
|
+
async function runDev(projectRoot = process.cwd(), options = {}) {
|
|
1608
|
+
const port = options.port ?? 8080;
|
|
1609
|
+
KrnlPackageReconciler.reconcile(projectRoot, true);
|
|
1610
|
+
generateMagneticDeclarations(projectRoot);
|
|
1611
|
+
if (options.dryRun) {
|
|
1612
|
+
console.log(`\u26A1 [Krnl Dev] Development environment verified on port ${port} (--dry-run).`);
|
|
1613
|
+
return {
|
|
1614
|
+
port,
|
|
1615
|
+
close: async () => {
|
|
1616
|
+
}
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
1619
|
+
const server = http.createServer((req, res) => {
|
|
1620
|
+
res.setHeader("Content-Type", "application/json");
|
|
1621
|
+
const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
|
|
1622
|
+
if (url.pathname === "/" || url.pathname === "/health") {
|
|
1623
|
+
res.writeHead(200);
|
|
1624
|
+
res.end(JSON.stringify({ status: "ok", service: "krnl-dev", port, uptime: process.uptime() }));
|
|
1625
|
+
return;
|
|
1626
|
+
}
|
|
1627
|
+
if (url.pathname === "/manifest") {
|
|
1628
|
+
const pkgPath = path12.join(projectRoot, "package.json");
|
|
1629
|
+
const pkg = fs11.existsSync(pkgPath) ? JSON.parse(fs11.readFileSync(pkgPath, "utf8")) : {};
|
|
1630
|
+
res.writeHead(200);
|
|
1631
|
+
res.end(JSON.stringify({ name: pkg.name || "krnl-app", version: pkg.version || "1.0.0" }));
|
|
1632
|
+
return;
|
|
1633
|
+
}
|
|
1634
|
+
res.writeHead(404);
|
|
1635
|
+
res.end(JSON.stringify({ error: "Route not found" }));
|
|
1636
|
+
});
|
|
1637
|
+
await new Promise((resolve2, reject) => {
|
|
1638
|
+
server.listen(port, () => resolve2());
|
|
1639
|
+
server.on("error", reject);
|
|
1640
|
+
});
|
|
1641
|
+
console.log(`\u26A1 [Krnl Dev] Development server listening on http://localhost:${port}`);
|
|
1642
|
+
const watcher = fs11.watch(projectRoot, { recursive: true }, (_evt, filename) => {
|
|
1643
|
+
if (filename && (filename.endsWith(".ts") || filename.endsWith(".js")) && !filename.includes("krnl-magnetic.d.ts")) {
|
|
1644
|
+
try {
|
|
1645
|
+
generateMagneticDeclarations(projectRoot);
|
|
1646
|
+
} catch {
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
if (filename && filename.endsWith("manifest.json")) {
|
|
1650
|
+
try {
|
|
1651
|
+
KrnlPackageReconciler.reconcile(projectRoot, true);
|
|
1652
|
+
} catch {
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
});
|
|
1656
|
+
const close = async () => {
|
|
1657
|
+
watcher.close();
|
|
1658
|
+
await new Promise((resolve2) => server.close(() => resolve2()));
|
|
1659
|
+
};
|
|
1660
|
+
return { server, close, port };
|
|
1661
|
+
}
|
|
1180
1662
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1181
1663
|
0 && (module.exports = {
|
|
1182
1664
|
generateMagneticDeclarations,
|
|
1665
|
+
runBuild,
|
|
1666
|
+
runDev,
|
|
1183
1667
|
runGenerate,
|
|
1184
1668
|
runValidate
|
|
1185
1669
|
});
|