ebade 0.4.0 → 0.4.1

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/cli/scaffold.js CHANGED
@@ -13,6 +13,7 @@ import yaml from "yaml";
13
13
  import ora from "ora";
14
14
  import prompts from "prompts";
15
15
  import chokidar from "chokidar";
16
+ import { execSync } from "child_process";
16
17
 
17
18
  // ============================================
18
19
  // ANSI Renk Kodları (Terminal çıktısı için)
@@ -39,7 +40,7 @@ ${colors.magenta} ██╔══╝ ${colors.cyan}██╔══██╗$
39
40
  ${colors.magenta} ███████╗${colors.cyan}██████╔╝${colors.magenta}██║ ██║${colors.cyan}██████╔╝${colors.magenta}███████╗
40
41
  ${colors.magenta} ╚══════╝${colors.cyan}╚═════╝ ${colors.magenta}╚═╝ ╚═╝${colors.cyan}╚═════╝ ${colors.magenta}╚══════╝${colors.reset}
41
42
 
42
- ${colors.dim}✨ Agent-First Framework ${colors.yellow}v0.1.0${colors.reset}
43
+ ${colors.dim}✨ Agent-First Framework ${colors.yellow}v0.4.1${colors.reset}
43
44
  `;
44
45
 
45
46
  const log = {
@@ -47,6 +48,8 @@ const log = {
47
48
  success: (msg) => console.log(`${colors.green}✓${colors.reset} ${msg}`),
48
49
  warn: (msg) => console.log(`${colors.yellow}⚠${colors.reset} ${msg}`),
49
50
  file: (msg) => console.log(`${colors.cyan} →${colors.reset} ${msg}`),
51
+ verify: (msg) => console.log(`${colors.yellow} 🔍${colors.reset} ${msg}`),
52
+ error: (msg) => console.log(`${colors.red} ✘${colors.reset} ${msg}`),
50
53
  section: (msg) =>
51
54
  console.log(`\n${colors.bright}${colors.magenta}▸ ${msg}${colors.reset}`),
52
55
  };
@@ -657,7 +660,7 @@ function ensureDir(dir) {
657
660
  // ============================================
658
661
  // Main Scaffold Function
659
662
  // ============================================
660
- function scaffold(ebadePath, outputDir) {
663
+ async function scaffold(ebadePath, outputDir) {
661
664
  const startTime = Date.now();
662
665
  const stats = {
663
666
  pages: 0,
@@ -872,6 +875,10 @@ function scaffold(ebadePath, outputDir) {
872
875
  fs.copyFileSync(ebadePath, path.join(projectDir, "project.ebade.yaml"));
873
876
  log.file("project.ebade.yaml (for agent reference)");
874
877
 
878
+ // ========== Summary ==========
879
+ // ========== Verify Output ==========
880
+ const verificationResult = await verifyOutput(projectDir, config);
881
+
875
882
  // ========== Summary ==========
876
883
  const duration = ((Date.now() - startTime) / 1000).toFixed(1);
877
884
 
@@ -897,8 +904,16 @@ ${colors.green} │${colors.reset} ${colors.cyan}📊 Token Savings:${
897
904
  ${colors.green} │${colors.reset} ${colors.cyan}⏱ Completed in:${
898
905
  colors.reset
899
906
  } ${String(duration + "s").padEnd(18)} ${colors.green}│${colors.reset}
907
+ ${colors.green} ├${"─".repeat(41)}┤${colors.reset}
908
+ ${colors.green} │${colors.reset} ${colors.yellow}🔍 Integrity:${
909
+ colors.reset
910
+ } ${(verificationResult.passed ? "PASSED" : "ISSUES FOUND").padEnd(
911
+ 18
912
+ )} ${colors.green}│${colors.reset}
900
913
  ${colors.green} └${"─".repeat(41)}┘${colors.reset}
901
914
 
915
+ ${verificationResult.report}
916
+
902
917
  ${colors.dim}Next steps:${colors.reset}
903
918
  ${colors.gray}1.${colors.reset} cd ${colors.cyan}${projectDir}${colors.reset}
904
919
  ${colors.gray}2.${colors.reset} npm install
@@ -911,6 +926,117 @@ ${colors.yellow}💡 Tip:${colors.reset} AI Agents can read ${
911
926
  `);
912
927
  }
913
928
 
929
+ /**
930
+ * ebade Output Verifier
931
+ * Performs a sanity check on the generated codebase.
932
+ */
933
+ async function verifyOutput(projectDir, config) {
934
+ log.section("Verifying output integrity");
935
+ const spinner = ora("Running ebade verification protocols...").start();
936
+
937
+ const results = {
938
+ structure: true,
939
+ syntax: true,
940
+ tests: true,
941
+ issues: [],
942
+ };
943
+
944
+ // 1. Structure Check
945
+ const requiredFiles = [
946
+ "package.json",
947
+ "tsconfig.json",
948
+ "app/layout.tsx",
949
+ "app/page.tsx",
950
+ "lib/utils.ts",
951
+ ];
952
+
953
+ for (const file of requiredFiles) {
954
+ if (!fs.existsSync(path.join(projectDir, file))) {
955
+ results.structure = false;
956
+ results.issues.push(`Missing core file: ${file}`);
957
+ }
958
+ }
959
+
960
+ // 2. Syntax Check (Lightweight)
961
+ // We check if exports match the intent in some key files
962
+ if (config.pages) {
963
+ config.pages.forEach((page) => {
964
+ const pagePath =
965
+ page.path === "/"
966
+ ? "app/page.tsx"
967
+ : `app${page.path.replace("[", "(").replace("]", ")")}/page.tsx`;
968
+ const fullPath = path.join(projectDir, pagePath);
969
+ if (fs.existsSync(fullPath)) {
970
+ const content = fs.readFileSync(fullPath, "utf-8");
971
+ const expectedExport = `export default function ${toPascalCase(
972
+ page.intent
973
+ )}Page()`;
974
+ if (!content.includes(expectedExport)) {
975
+ results.syntax = false;
976
+ results.issues.push(
977
+ `Syntax mismatch in ${pagePath}: Export name should be ${toPascalCase(
978
+ page.intent
979
+ )}Page`
980
+ );
981
+ }
982
+ }
983
+ });
984
+ }
985
+
986
+ // 3. Test Coverage Check
987
+ // Ensure every component has a matching test file
988
+ const components = fs
989
+ .readdirSync(path.join(projectDir, "components"))
990
+ .filter((f) => f.endsWith(".tsx") && !f.endsWith(".test.tsx"));
991
+ components.forEach((comp) => {
992
+ const testFile = comp.replace(".tsx", ".test.tsx");
993
+ if (!fs.existsSync(path.join(projectDir, "components", testFile))) {
994
+ results.tests = false;
995
+ results.issues.push(`Missing test for component: ${comp}`);
996
+ }
997
+ });
998
+
999
+ // 4. Semantic Integrity Check
1000
+ // Check if layout imports globals.css
1001
+ const layoutPath = path.join(projectDir, "app/layout.tsx");
1002
+ if (fs.existsSync(layoutPath)) {
1003
+ const content = fs.readFileSync(layoutPath, "utf-8");
1004
+ if (!content.includes('import "./globals.css"')) {
1005
+ results.issues.push(
1006
+ "Semantic Error: Root layout missing global styles import"
1007
+ );
1008
+ }
1009
+ }
1010
+
1011
+ // Check if home page has at least one intent-defined component
1012
+ const homePath = path.join(projectDir, "app/page.tsx");
1013
+ if (fs.existsSync(homePath) && config.pages?.[0]?.components?.length > 0) {
1014
+ const content = fs.readFileSync(homePath, "utf-8");
1015
+ const firstComp = toPascalCase(config.pages[0].components[0]);
1016
+ if (!content.includes(`<${firstComp} />`)) {
1017
+ results.issues.push(
1018
+ `Semantic Warning: Home page might be missing the ${firstComp} component`
1019
+ );
1020
+ }
1021
+ }
1022
+
1023
+ spinner.stop();
1024
+
1025
+ const passed = results.issues.length === 0;
1026
+
1027
+ let report = "";
1028
+ if (passed) {
1029
+ report = `${colors.green} ✓ All integrity checks passed! Code is production-ready.${colors.reset}`;
1030
+ } else {
1031
+ report = `${colors.red} ⚠ Verification found ${results.issues.length} issue(s):${colors.reset}\n`;
1032
+ results.issues.forEach((issue) => {
1033
+ report += ` ${colors.red}•${colors.reset} ${issue}\n`;
1034
+ });
1035
+ }
1036
+
1037
+ return { passed, report };
1038
+ }
1039
+
914
1040
  // ============================================
915
1041
  // CLI Entry Point
916
1042
  // ============================================
@@ -928,6 +1054,7 @@ ${colors.dim}Commands:${colors.reset}
928
1054
  init Create a new ebade project interactively
929
1055
  scaffold <file> [output] Scaffold a project from ebade file
930
1056
  dev <file> [output] Watch ebade file and re-scaffold on changes
1057
+ playground Open the ebade playground
931
1058
 
932
1059
  ${colors.dim}Examples:${colors.reset}
933
1060
  npx ebade init
@@ -1047,7 +1174,7 @@ ${colors.green}✓${colors.reset} Created ${colors.cyan}${ebadeFilePath}${colors
1047
1174
  `);
1048
1175
 
1049
1176
  if (response.autoScaffold) {
1050
- scaffold(ebadeFilePath, outputDir);
1177
+ await scaffold(ebadeFilePath, outputDir);
1051
1178
  } else {
1052
1179
  console.log(`
1053
1180
  ${colors.dim}Next steps:${colors.reset}
@@ -1060,7 +1187,7 @@ ${colors.dim}Next steps:${colors.reset}
1060
1187
  // ============================================
1061
1188
  // Dev Command (Watch Mode)
1062
1189
  // ============================================
1063
- function dev(ebadeFile, outputDir) {
1190
+ async function dev(ebadeFile, outputDir) {
1064
1191
  console.log(`
1065
1192
  ${LOGO}
1066
1193
  `);
@@ -1071,7 +1198,7 @@ ${LOGO}
1071
1198
  console.log(`${colors.dim}Press Ctrl+C to stop.${colors.reset}\n`);
1072
1199
 
1073
1200
  // Initial scaffold
1074
- scaffold(ebadeFile, outputDir);
1201
+ await scaffold(ebadeFile, outputDir);
1075
1202
 
1076
1203
  // Watch for changes
1077
1204
  const watcher = chokidar.watch(ebadeFile, {
@@ -1079,11 +1206,11 @@ ${LOGO}
1079
1206
  ignoreInitial: true,
1080
1207
  });
1081
1208
 
1082
- watcher.on("change", () => {
1209
+ watcher.on("change", async () => {
1083
1210
  console.log(
1084
1211
  `\n${colors.yellow}⚡ Change detected!${colors.reset} Re-scaffolding...\n`
1085
1212
  );
1086
- scaffold(ebadeFile, outputDir);
1213
+ await scaffold(ebadeFile, outputDir);
1087
1214
  });
1088
1215
 
1089
1216
  watcher.on("error", (error) => {
@@ -1127,7 +1254,21 @@ if (command === "init") {
1127
1254
  process.exit(1);
1128
1255
  }
1129
1256
 
1130
- scaffold(ebadeFile, outputDir);
1257
+ await scaffold(ebadeFile, outputDir);
1258
+ } else if (command === "playground") {
1259
+ console.log(`\n${colors.cyan}🌐 Opening ebade playground...${colors.reset}`);
1260
+ const url = "https://ebade.dev/playground";
1261
+ const start =
1262
+ process.platform === "darwin"
1263
+ ? "open"
1264
+ : process.platform === "win32"
1265
+ ? "start"
1266
+ : "xdg-open";
1267
+ try {
1268
+ execSync(`${start} ${url}`);
1269
+ } catch (e) {
1270
+ console.log(`\n${colors.yellow}Please open:${colors.reset} ${url}`);
1271
+ }
1131
1272
  } else if (command === "dev") {
1132
1273
  const ebadeFile = args[1];
1133
1274
  const outputDir = args[2] || "./output";
@@ -1149,7 +1290,7 @@ if (command === "init") {
1149
1290
  process.exit(1);
1150
1291
  }
1151
1292
 
1152
- dev(ebadeFile, outputDir);
1293
+ await dev(ebadeFile, outputDir);
1153
1294
  } else {
1154
1295
  console.error(
1155
1296
  `${colors.red}Error:${colors.reset} Unknown command: ${command}`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ebade",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "ebade - Agent-First Framework. The first framework designed for AI agents, readable by humans.",
5
5
  "type": "module",
6
6
  "main": "cli/scaffold.js",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ebade/mcp-server",
3
- "version": "0.4.0",
4
- "description": "MCP Server for ebade v0.3.1 - The Agent-First Framework",
3
+ "version": "0.4.1",
4
+ "description": "MCP Server for ebade v0.4.1 - The Agent-First Framework",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
@@ -2,7 +2,7 @@
2
2
  "name": "ebade",
3
3
  "displayName": "ebade - Agent-First Framework",
4
4
  "description": "Syntax highlighting and snippets for ebade (.ebade.yaml) files",
5
- "version": "0.4.0",
5
+ "version": "0.4.1",
6
6
  "publisher": "hasankemaldemirci",
7
7
  "icon": "images/icon.png",
8
8
  "engines": {