bertui 1.1.0 → 1.1.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.
@@ -1,16 +1,36 @@
1
+ // bertui/src/config/defaultConfig.js
2
+ // Default configuration used when bertui.config.js is not present
3
+
1
4
  export const defaultConfig = {
5
+ // Site information (used for sitemap generation)
6
+ siteName: "BertUI App",
7
+ baseUrl: "http://localhost:3000", // Default to localhost
8
+
9
+ // HTML Meta Tags (SEO)
2
10
  meta: {
3
- title: "BertUI App",
4
- description: "Built with BertUI - Lightning fast React development",
5
- keywords: "react, bun, bertui",
11
+ title: "BertUI - Lightning Fast React",
12
+ description: "Build lightning-fast React applications with file-based routing powered by Bun",
13
+ keywords: "react, bun, bertui, fast, file-based routing",
6
14
  author: "Pease Ernest",
7
- ogImage: "/og-image.png",
8
- themeColor: "#f30606ff",
9
- lang: "en"
15
+ themeColor: "#667eea",
16
+ lang: "en",
17
+
18
+ // Open Graph for social sharing
19
+ ogTitle: "BertUI - Lightning Fast React Framework",
20
+ ogDescription: "Build lightning-fast React apps with zero config",
21
+ ogImage: "/og-image.png"
10
22
  },
23
+
24
+ // App Shell Configuration
11
25
  appShell: {
12
26
  loading: true,
13
27
  loadingText: "Loading...",
14
28
  backgroundColor: "#ffffff"
29
+ },
30
+
31
+ // robots.txt Configuration
32
+ robots: {
33
+ disallow: [], // No paths blocked by default
34
+ crawlDelay: null // No crawl delay by default
15
35
  }
16
36
  };
@@ -1,4 +1,4 @@
1
- // src/config/loadConfig.js
1
+ // src/config/loadConfig.js - COMPLETE CORRECTED VERSION
2
2
  import { join } from 'path';
3
3
  import { existsSync } from 'fs';
4
4
  import { defaultConfig } from './defaultConfig.js';
@@ -13,6 +13,13 @@ export async function loadConfig(root) {
13
13
  const userConfig = await import(configPath);
14
14
  logger.success('Loaded bertui.config.js');
15
15
 
16
+ // DEBUG: Show what we loaded
17
+ logger.info(`📋 Config loaded: ${JSON.stringify({
18
+ hasSiteName: !!(userConfig.default?.siteName || userConfig.siteName),
19
+ hasBaseUrl: !!(userConfig.default?.baseUrl || userConfig.baseUrl),
20
+ hasRobots: !!(userConfig.default?.robots || userConfig.robots)
21
+ })}`);
22
+
16
23
  // Merge user config with defaults
17
24
  return mergeConfig(defaultConfig, userConfig.default || userConfig);
18
25
  } catch (error) {
@@ -26,8 +33,17 @@ export async function loadConfig(root) {
26
33
  }
27
34
 
28
35
  function mergeConfig(defaults, user) {
29
- return {
30
- meta: { ...defaults.meta, ...(user.meta || {}) },
31
- appShell: { ...defaults.appShell, ...(user.appShell || {}) }
32
- };
36
+ // Start with user config (so user values override defaults)
37
+ const merged = { ...user };
38
+
39
+ // Deep merge for nested objects
40
+ merged.meta = { ...defaults.meta, ...(user.meta || {}) };
41
+ merged.appShell = { ...defaults.appShell, ...(user.appShell || {}) };
42
+ merged.robots = { ...defaults.robots, ...(user.robots || {}) };
43
+
44
+ // Ensure we have required top-level fields
45
+ if (!merged.siteName) merged.siteName = defaults.siteName;
46
+ if (!merged.baseUrl) merged.baseUrl = defaults.baseUrl;
47
+
48
+ return merged;
33
49
  }
@@ -0,0 +1,61 @@
1
+ // bertui/src/utils/meta-extractor.js
2
+ export function extractMetaFromSource(code) {
3
+ try {
4
+ if (!code.includes('export const meta')) {
5
+ return null;
6
+ }
7
+
8
+ const metaStart = code.indexOf('export const meta = {');
9
+ if (metaStart === -1) return null;
10
+
11
+ let braceCount = 0;
12
+ let inString = false;
13
+ let stringChar = '';
14
+ let metaEnd = -1;
15
+
16
+ for (let i = metaStart + 'export const meta = {'.length; i < code.length; i++) {
17
+ const char = code[i];
18
+ const prevChar = i > 0 ? code[i - 1] : '';
19
+
20
+ if (!inString && (char === '"' || char === "'" || char === '`')) {
21
+ inString = true;
22
+ stringChar = char;
23
+ } else if (inString && char === stringChar && prevChar !== '\\') {
24
+ inString = false;
25
+ }
26
+
27
+ if (!inString) {
28
+ if (char === '{') braceCount++;
29
+ if (char === '}') {
30
+ if (braceCount === 0) {
31
+ metaEnd = i;
32
+ break;
33
+ }
34
+ braceCount--;
35
+ }
36
+ }
37
+ }
38
+
39
+ if (metaEnd === -1) return null;
40
+
41
+ const metaString = code.substring(metaStart + 'export const meta = {'.length - 1, metaEnd + 1);
42
+ const meta = {};
43
+ const pairs = metaString.match(/(\w+)\s*:\s*(['"`][^'"`]*['"`])/g) || [];
44
+
45
+ pairs.forEach(pair => {
46
+ const colonIndex = pair.indexOf(':');
47
+ if (colonIndex === -1) return;
48
+
49
+ const key = pair.substring(0, colonIndex).trim();
50
+ const value = pair.substring(colonIndex + 1).trim().slice(1, -1);
51
+
52
+ if (key && value) {
53
+ meta[key] = value;
54
+ }
55
+ });
56
+
57
+ return Object.keys(meta).length > 0 ? meta : null;
58
+ } catch (error) {
59
+ return null;
60
+ }
61
+ }
@@ -0,0 +1,80 @@
1
+ // bertui/types/config.d.ts
2
+ declare module 'bertui/config' {
3
+ /**
4
+ * BertUI Configuration
5
+ */
6
+ export interface BertuiConfig {
7
+ /** Site name for SEO */
8
+ siteName?: string;
9
+
10
+ /** Base URL for sitemap generation (e.g., "https://example.com") */
11
+ baseUrl?: string;
12
+
13
+ /** HTML meta tags configuration */
14
+ meta?: {
15
+ /** Page title */
16
+ title?: string;
17
+ /** Meta description */
18
+ description?: string;
19
+ /** Meta keywords */
20
+ keywords?: string;
21
+ /** Author name */
22
+ author?: string;
23
+ /** Open Graph image URL */
24
+ ogImage?: string;
25
+ /** Open Graph title */
26
+ ogTitle?: string;
27
+ /** Open Graph description */
28
+ ogDescription?: string;
29
+ /** Theme color */
30
+ themeColor?: string;
31
+ /** Language code (e.g., "en") */
32
+ lang?: string;
33
+ };
34
+
35
+ /** App shell configuration */
36
+ appShell?: {
37
+ /** Show loading indicator */
38
+ loading?: boolean;
39
+ /** Loading text */
40
+ loadingText?: string;
41
+ /** Background color */
42
+ backgroundColor?: string;
43
+ };
44
+
45
+ /** robots.txt configuration */
46
+ robots?: {
47
+ /** Paths to disallow in robots.txt */
48
+ disallow?: string[];
49
+ /** Crawl delay in seconds */
50
+ crawlDelay?: number;
51
+ };
52
+ }
53
+
54
+ /**
55
+ * Page meta configuration (exported from page files)
56
+ */
57
+ export interface PageMeta {
58
+ title?: string;
59
+ description?: string;
60
+ keywords?: string;
61
+ author?: string;
62
+ ogTitle?: string;
63
+ ogDescription?: string;
64
+ ogImage?: string;
65
+ themeColor?: string;
66
+ lang?: string;
67
+ publishedDate?: string;
68
+ updatedDate?: string;
69
+ }
70
+
71
+ /**
72
+ * Default BertUI configuration
73
+ */
74
+ export const defaultConfig: BertuiConfig;
75
+
76
+ /**
77
+ * Load BertUI configuration from bertui.config.js
78
+ */
79
+ export function loadConfig(root: string): Promise<BertuiConfig>;
80
+ }
@@ -0,0 +1,116 @@
1
+ // bertui/types/index.d.ts
2
+
3
+ declare namespace React {
4
+ type ReactNode = any;
5
+ }
6
+
7
+ declare global {
8
+ namespace JSX {
9
+ type Element = any;
10
+ interface IntrinsicElements {
11
+ [elemName: string]: any;
12
+ }
13
+ }
14
+ }
15
+ declare module 'bertui' {
16
+ import { BertuiConfig } from 'bertui/config';
17
+
18
+ /**
19
+ * Logger utility
20
+ */
21
+ export interface Logger {
22
+ info(message: string): void;
23
+ success(message: string): void;
24
+ warn(message: string): void;
25
+ error(message: string): void;
26
+ debug(message: string): void;
27
+ bigLog(message: string, options?: { color?: string }): void;
28
+ table(data: any[]): void;
29
+ }
30
+
31
+ /**
32
+ * Build options
33
+ */
34
+ export interface BuildOptions {
35
+ /** Project root directory */
36
+ root?: string;
37
+ }
38
+
39
+ /**
40
+ * Dev server options
41
+ */
42
+ export interface DevOptions {
43
+ /** Server port */
44
+ port?: number;
45
+ /** Project root directory */
46
+ root?: string;
47
+ }
48
+
49
+ /**
50
+ * Compile options
51
+ */
52
+ export interface CompileOptions {
53
+ /** Project root directory */
54
+ root?: string;
55
+ }
56
+
57
+ /**
58
+ * Logger instance
59
+ */
60
+ export const logger: Logger;
61
+
62
+ /**
63
+ * Default configuration
64
+ */
65
+ export const defaultConfig: BertuiConfig;
66
+
67
+ /**
68
+ * Load configuration
69
+ */
70
+ export function loadConfig(root: string): Promise<BertuiConfig>;
71
+
72
+ /**
73
+ * Start development server
74
+ */
75
+ export function startDev(options?: DevOptions): Promise<void>;
76
+
77
+ /**
78
+ * Build for production
79
+ */
80
+ export function buildProduction(options?: BuildOptions): Promise<void>;
81
+
82
+ /**
83
+ * Compile project
84
+ */
85
+ export function compileProject(root: string): Promise<{
86
+ outDir: string;
87
+ stats: { files: number; skipped: number };
88
+ routes: any[];
89
+ }>;
90
+
91
+ /**
92
+ * CLI program
93
+ */
94
+ export function program(): void;
95
+
96
+ /**
97
+ * BertUI version
98
+ */
99
+ export const version: string;
100
+ }
101
+
102
+ // Global declarations for Server Islands
103
+ declare global {
104
+ /**
105
+ * Mark a page component as a Server Island (SSG)
106
+ * Add this export to any page to enable static generation:
107
+ *
108
+ * @example
109
+ * ```tsx
110
+ * export const render = "server";
111
+ * ```
112
+ */
113
+ export const render: "server" | "client";
114
+ }
115
+
116
+ export {};
@@ -0,0 +1,13 @@
1
+ // bertui/types/react.d.ts
2
+ import React from 'react';
3
+
4
+ declare global {
5
+ namespace JSX {
6
+ interface IntrinsicElements {
7
+ [elemName: string]: React.DetailedHTMLProps<
8
+ React.HTMLAttributes<HTMLElement>,
9
+ HTMLElement
10
+ >;
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,79 @@
1
+ // bertui/types/router.d.ts
2
+ declare module 'bertui/router' {
3
+ import { ReactNode, ComponentType } from 'react';
4
+
5
+ /**
6
+ * Route parameter object
7
+ */
8
+ export interface RouteParams {
9
+ [key: string]: string;
10
+ }
11
+
12
+ /**
13
+ * Router context value
14
+ */
15
+ export interface RouterContext {
16
+ /** Current active route */
17
+ currentRoute: Route | null;
18
+ /** Dynamic route parameters */
19
+ params: RouteParams;
20
+ /** Navigate to a new path */
21
+ navigate: (path: string) => void;
22
+ /** Current pathname */
23
+ pathname: string;
24
+ /** Whether running in SSR mode */
25
+ isSSR?: boolean;
26
+ }
27
+
28
+ /**
29
+ * Route configuration object
30
+ */
31
+ export interface Route {
32
+ /** Route path (e.g., "/", "/blog", "/user/:id") */
33
+ path: string;
34
+ /** React component to render */
35
+ component: ComponentType<{ params?: RouteParams }>;
36
+ /** Route type: "static" or "dynamic" */
37
+ type: 'static' | 'dynamic';
38
+ }
39
+
40
+ /**
41
+ * Router component props
42
+ */
43
+ export interface RouterProps {
44
+ /** Array of route configurations */
45
+ routes: Route[];
46
+ /** Initial path for SSR */
47
+ initialPath?: string;
48
+ }
49
+
50
+ /**
51
+ * Link component props
52
+ */
53
+ export interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
54
+ /** Destination path */
55
+ to: string;
56
+ /** Link content */
57
+ children: ReactNode;
58
+ }
59
+
60
+ /**
61
+ * Router component for client-side routing
62
+ */
63
+ export const Router: ComponentType<RouterProps>;
64
+
65
+ /**
66
+ * Link component for navigation
67
+ */
68
+ export const Link: ComponentType<LinkProps>;
69
+
70
+ /**
71
+ * Hook to access router context
72
+ */
73
+ export function useRouter(): RouterContext;
74
+
75
+ /**
76
+ * Exported routes configuration
77
+ */
78
+ export const routes: Route[];
79
+ }