@zenithbuild/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/.eslintignore +15 -0
  2. package/.gitattributes +2 -0
  3. package/.github/ISSUE_TEMPLATE/compiler-errors-for-invalid-state-declarations.md +25 -0
  4. package/.github/ISSUE_TEMPLATE/new_ticket.yaml +34 -0
  5. package/.github/pull_request_template.md +15 -0
  6. package/.github/workflows/discord-changelog.yml +141 -0
  7. package/.github/workflows/discord-notify.yml +242 -0
  8. package/.github/workflows/discord-version.yml +195 -0
  9. package/.prettierignore +13 -0
  10. package/.prettierrc +21 -0
  11. package/.zen.d.ts +15 -0
  12. package/LICENSE +21 -0
  13. package/README.md +55 -0
  14. package/app/components/Button.zen +46 -0
  15. package/app/components/Link.zen +11 -0
  16. package/app/favicon.ico +0 -0
  17. package/app/layouts/Main.zen +59 -0
  18. package/app/pages/about.zen +23 -0
  19. package/app/pages/blog/[id].zen +53 -0
  20. package/app/pages/blog/index.zen +32 -0
  21. package/app/pages/dynamic-dx.zen +712 -0
  22. package/app/pages/dynamic-primitives.zen +453 -0
  23. package/app/pages/index.zen +154 -0
  24. package/app/pages/navigation-demo.zen +229 -0
  25. package/app/pages/posts/[...slug].zen +61 -0
  26. package/app/pages/primitives-demo.zen +273 -0
  27. package/assets/logos/0E3B5DDD-605C-4839-BB2E-DFCA8ADC9604.PNG +0 -0
  28. package/assets/logos/760971E5-79A1-44F9-90B9-925DF30F4278.PNG +0 -0
  29. package/assets/logos/8A06ED80-9ED2-4689-BCBD-13B2E95EE8E4.JPG +0 -0
  30. package/assets/logos/C691FF58-ED13-4E8D-B6A3-02E835849340.PNG +0 -0
  31. package/assets/logos/C691FF58-ED13-4E8D-B6A3-02E835849340.svg +601 -0
  32. package/assets/logos/README.md +54 -0
  33. package/assets/logos/zen.icns +0 -0
  34. package/bun.lock +39 -0
  35. package/compiler/README.md +380 -0
  36. package/compiler/errors/compilerError.ts +24 -0
  37. package/compiler/finalize/finalizeOutput.ts +163 -0
  38. package/compiler/finalize/generateFinalBundle.ts +82 -0
  39. package/compiler/index.ts +44 -0
  40. package/compiler/ir/types.ts +83 -0
  41. package/compiler/legacy/binding.ts +254 -0
  42. package/compiler/legacy/bindings.ts +338 -0
  43. package/compiler/legacy/component-process.ts +1208 -0
  44. package/compiler/legacy/component.ts +301 -0
  45. package/compiler/legacy/event.ts +50 -0
  46. package/compiler/legacy/expression.ts +1149 -0
  47. package/compiler/legacy/mutation.ts +280 -0
  48. package/compiler/legacy/parse.ts +299 -0
  49. package/compiler/legacy/split.ts +608 -0
  50. package/compiler/legacy/types.ts +32 -0
  51. package/compiler/output/types.ts +34 -0
  52. package/compiler/parse/detectMapExpressions.ts +102 -0
  53. package/compiler/parse/parseScript.ts +22 -0
  54. package/compiler/parse/parseTemplate.ts +425 -0
  55. package/compiler/parse/parseZenFile.ts +66 -0
  56. package/compiler/parse/trackLoopContext.ts +82 -0
  57. package/compiler/runtime/dataExposure.ts +291 -0
  58. package/compiler/runtime/generateDOM.ts +144 -0
  59. package/compiler/runtime/generateHydrationBundle.ts +383 -0
  60. package/compiler/runtime/hydration.ts +309 -0
  61. package/compiler/runtime/navigation.ts +432 -0
  62. package/compiler/runtime/thinRuntime.ts +160 -0
  63. package/compiler/runtime/transformIR.ts +256 -0
  64. package/compiler/runtime/wrapExpression.ts +84 -0
  65. package/compiler/runtime/wrapExpressionWithLoop.ts +77 -0
  66. package/compiler/spa-build.ts +1000 -0
  67. package/compiler/test/validate-test.ts +104 -0
  68. package/compiler/transform/generateBindings.ts +47 -0
  69. package/compiler/transform/generateHTML.ts +28 -0
  70. package/compiler/transform/transformNode.ts +126 -0
  71. package/compiler/transform/transformTemplate.ts +38 -0
  72. package/compiler/validate/validateExpressions.ts +168 -0
  73. package/core/index.ts +135 -0
  74. package/core/lifecycle/index.ts +49 -0
  75. package/core/lifecycle/zen-mount.ts +182 -0
  76. package/core/lifecycle/zen-unmount.ts +88 -0
  77. package/core/reactivity/index.ts +54 -0
  78. package/core/reactivity/tracking.ts +167 -0
  79. package/core/reactivity/zen-batch.ts +57 -0
  80. package/core/reactivity/zen-effect.ts +139 -0
  81. package/core/reactivity/zen-memo.ts +146 -0
  82. package/core/reactivity/zen-ref.ts +52 -0
  83. package/core/reactivity/zen-signal.ts +121 -0
  84. package/core/reactivity/zen-state.ts +180 -0
  85. package/core/reactivity/zen-untrack.ts +44 -0
  86. package/docs/COMMENTS.md +111 -0
  87. package/docs/COMMITS.md +36 -0
  88. package/docs/CONTRIBUTING.md +116 -0
  89. package/docs/STYLEGUIDE.md +62 -0
  90. package/package.json +44 -0
  91. package/router/index.ts +76 -0
  92. package/router/manifest.ts +314 -0
  93. package/router/navigation/ZenLink.zen +231 -0
  94. package/router/navigation/index.ts +78 -0
  95. package/router/navigation/zen-link.ts +584 -0
  96. package/router/runtime.ts +458 -0
  97. package/router/types.ts +168 -0
  98. package/runtime/build.ts +17 -0
  99. package/runtime/serve.ts +93 -0
  100. package/scripts/webhook-proxy.ts +213 -0
  101. package/tsconfig.json +28 -0
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Zenith Development Server
3
+ *
4
+ * SPA-compatible server that:
5
+ * - Serves static assets directly (js, css, ico, images)
6
+ * - Serves index.html for all other routes (SPA fallback)
7
+ *
8
+ * This enables client-side routing to work on:
9
+ * - Direct URL entry
10
+ * - Hard refresh
11
+ * - Back/forward navigation
12
+ */
13
+
14
+ import { serve } from "bun"
15
+ import path from "path"
16
+
17
+ const distDir = path.resolve(import.meta.dir, "..", "app", "dist")
18
+
19
+ // File extensions that should be served as static assets
20
+ const STATIC_EXTENSIONS = new Set([
21
+ ".js",
22
+ ".css",
23
+ ".ico",
24
+ ".png",
25
+ ".jpg",
26
+ ".jpeg",
27
+ ".gif",
28
+ ".svg",
29
+ ".webp",
30
+ ".woff",
31
+ ".woff2",
32
+ ".ttf",
33
+ ".eot",
34
+ ".json",
35
+ ".map"
36
+ ])
37
+
38
+ serve({
39
+ port: 3000,
40
+
41
+ async fetch(req) {
42
+ const url = new URL(req.url)
43
+ const pathname = url.pathname
44
+
45
+ // Get file extension
46
+ const ext = path.extname(pathname).toLowerCase()
47
+
48
+ // Check if this is a static asset request
49
+ if (STATIC_EXTENSIONS.has(ext)) {
50
+ const filePath = path.join(distDir, pathname)
51
+ const file = Bun.file(filePath)
52
+
53
+ // Check if file exists
54
+ if (await file.exists()) {
55
+ return new Response(file)
56
+ }
57
+
58
+ // Static file not found
59
+ return new Response("Not found", { status: 404 })
60
+ }
61
+
62
+ // For all other routes, serve index.html (SPA fallback)
63
+ const indexPath = path.join(distDir, "index.html")
64
+ const indexFile = Bun.file(indexPath)
65
+
66
+ if (await indexFile.exists()) {
67
+ return new Response(indexFile, {
68
+ headers: {
69
+ "Content-Type": "text/html; charset=utf-8"
70
+ }
71
+ })
72
+ }
73
+
74
+ // No index.html found - likely need to run build first
75
+ return new Response(
76
+ `<html>
77
+ <head><title>Zenith - Build Required</title></head>
78
+ <body style="font-family: system-ui; padding: 2rem; text-align: center;">
79
+ <h1>Build Required</h1>
80
+ <p>Run <code>bun runtime/build.ts</code> first to compile the pages.</p>
81
+ </body>
82
+ </html>`,
83
+ {
84
+ status: 500,
85
+ headers: { "Content-Type": "text/html; charset=utf-8" }
86
+ }
87
+ )
88
+ }
89
+ })
90
+
91
+ console.log("šŸš€ Zenith dev server running at http://localhost:3000")
92
+ console.log(" SPA mode: All routes serve index.html")
93
+
@@ -0,0 +1,213 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * GitHub to Discord Webhook Proxy
4
+ *
5
+ * This server receives GitHub webhook events and formats them for Discord.
6
+ *
7
+ * Usage:
8
+ * 1. Add DISCORD_WEBHOOK_URL to .env file (or export as environment variable)
9
+ * 2. Run: bun scripts/webhook-proxy.ts
10
+ * 3. Point GitHub webhook to: http://your-server:3001/webhook
11
+ *
12
+ * Note: Bun automatically loads .env files from the project root
13
+ */
14
+
15
+ import { serve } from "bun";
16
+
17
+ const DISCORD_WEBHOOK_URL = process.env.DISCORD_WEBHOOK_URL;
18
+
19
+ if (!DISCORD_WEBHOOK_URL) {
20
+ console.error("āŒ Error: DISCORD_WEBHOOK_URL environment variable is required");
21
+ console.error(" Set it in .env file: DISCORD_WEBHOOK_URL='https://discord.com/api/webhooks/...'");
22
+ console.error(" Or export it: export DISCORD_WEBHOOK_URL='https://discord.com/api/webhooks/...'");
23
+ process.exit(1);
24
+ }
25
+
26
+ const PORT = process.env.PORT || 3001;
27
+
28
+ interface GitHubIssueEvent {
29
+ action: string;
30
+ issue: {
31
+ number: number;
32
+ title: string;
33
+ body: string;
34
+ html_url: string;
35
+ state: string;
36
+ labels: Array<{ name: string; color: string }>;
37
+ user: {
38
+ login: string;
39
+ avatar_url: string;
40
+ };
41
+ };
42
+ repository: {
43
+ name: string;
44
+ full_name: string;
45
+ html_url: string;
46
+ };
47
+ }
48
+
49
+ function formatIssueForDiscord(event: GitHubIssueEvent): any {
50
+ const { issue, repository, action } = event;
51
+
52
+ // Determine color based on action
53
+ let color = 0x3498db; // Blue (default)
54
+ if (action === "opened") color = 0x2ecc71; // Green
55
+ if (action === "closed") color = 0xe74c3c; // Red
56
+ if (action === "reopened") color = 0xf39c12; // Orange
57
+
58
+ // Format labels
59
+ const labels = issue.labels.map(l => `\`${l.name}\``).join(" ") || "*No labels*";
60
+
61
+ // Truncate body if too long
62
+ let description = issue.body || "*No description*";
63
+ if (description.length > 1000) {
64
+ description = description.substring(0, 1000) + "...";
65
+ }
66
+
67
+ // Format action text
68
+ const actionText: Record<string, string> = {
69
+ opened: "šŸ“ New Issue Created",
70
+ closed: "āœ… Issue Closed",
71
+ reopened: "šŸ”„ Issue Reopened",
72
+ edited: "āœļø Issue Edited",
73
+ assigned: "šŸ‘¤ Issue Assigned",
74
+ unassigned: "šŸ‘¤ Issue Unassigned",
75
+ labeled: "šŸ·ļø Label Added",
76
+ unlabeled: "šŸ·ļø Label Removed",
77
+ };
78
+
79
+ const title = actionText[action] || `šŸ“‹ Issue ${action}`;
80
+
81
+ return {
82
+ embeds: [
83
+ {
84
+ title: title,
85
+ description: `**${issue.title}**`,
86
+ url: issue.html_url,
87
+ color: color,
88
+ fields: [
89
+ {
90
+ name: "Issue #",
91
+ value: `#${issue.number}`,
92
+ inline: true,
93
+ },
94
+ {
95
+ name: "State",
96
+ value: issue.state,
97
+ inline: true,
98
+ },
99
+ {
100
+ name: "Labels",
101
+ value: labels,
102
+ inline: false,
103
+ },
104
+ {
105
+ name: "Description",
106
+ value: description,
107
+ inline: false,
108
+ },
109
+ ],
110
+ author: {
111
+ name: issue.user.login,
112
+ icon_url: issue.user.avatar_url,
113
+ },
114
+ footer: {
115
+ text: repository.full_name,
116
+ },
117
+ timestamp: new Date().toISOString(),
118
+ },
119
+ ],
120
+ };
121
+ }
122
+
123
+ async function sendToDiscord(payload: any): Promise<Response> {
124
+ const response = await fetch(DISCORD_WEBHOOK_URL!, {
125
+ method: "POST",
126
+ headers: {
127
+ "Content-Type": "application/json",
128
+ },
129
+ body: JSON.stringify(payload),
130
+ });
131
+
132
+ if (!response.ok) {
133
+ const text = await response.text();
134
+ throw new Error(`Discord webhook failed: ${response.status} ${text}`);
135
+ }
136
+
137
+ return response;
138
+ }
139
+
140
+ serve({
141
+ port: PORT,
142
+ async fetch(req) {
143
+ const url = new URL(req.url);
144
+
145
+ // Health check endpoint
146
+ if (url.pathname === "/health") {
147
+ return new Response(JSON.stringify({ status: "ok" }), {
148
+ headers: { "Content-Type": "application/json" },
149
+ });
150
+ }
151
+
152
+ // Webhook endpoint
153
+ if (url.pathname === "/webhook" && req.method === "POST") {
154
+ try {
155
+ const githubEvent = req.headers.get("x-github-event");
156
+ const signature = req.headers.get("x-hub-signature-256");
157
+
158
+ if (!githubEvent) {
159
+ return new Response(
160
+ JSON.stringify({ error: "Missing x-github-event header" }),
161
+ { status: 400, headers: { "Content-Type": "application/json" } }
162
+ );
163
+ }
164
+
165
+ // Only process issue events
166
+ if (githubEvent !== "issues" && githubEvent !== "issue_comment") {
167
+ return new Response(
168
+ JSON.stringify({ message: `Ignoring event: ${githubEvent}` }),
169
+ { status: 200, headers: { "Content-Type": "application/json" } }
170
+ );
171
+ }
172
+
173
+ const body = await req.json();
174
+
175
+ // Format for Discord
176
+ let discordPayload;
177
+ if (githubEvent === "issues") {
178
+ discordPayload = formatIssueForDiscord(body as GitHubIssueEvent);
179
+ } else {
180
+ // Handle issue comments if needed
181
+ return new Response(
182
+ JSON.stringify({ message: "Issue comments not yet implemented" }),
183
+ { status: 200, headers: { "Content-Type": "application/json" } }
184
+ );
185
+ }
186
+
187
+ // Send to Discord
188
+ await sendToDiscord(discordPayload);
189
+
190
+ console.log(`āœ… Sent ${githubEvent} event to Discord: ${body.issue?.title || "N/A"}`);
191
+
192
+ return new Response(
193
+ JSON.stringify({ success: true, event: githubEvent }),
194
+ { status: 200, headers: { "Content-Type": "application/json" } }
195
+ );
196
+ } catch (error: any) {
197
+ console.error("āŒ Error processing webhook:", error);
198
+ return new Response(
199
+ JSON.stringify({ error: error.message }),
200
+ { status: 500, headers: { "Content-Type": "application/json" } }
201
+ );
202
+ }
203
+ }
204
+
205
+ return new Response("Not Found", { status: 404 });
206
+ },
207
+ });
208
+
209
+ console.log(`šŸš€ GitHub to Discord webhook proxy running on port ${PORT}`);
210
+ console.log(`šŸ“” Webhook endpoint: http://localhost:${PORT}/webhook`);
211
+ console.log(`šŸ’š Health check: http://localhost:${PORT}/health`);
212
+ console.log(`\nāš ļø Make sure to set DISCORD_WEBHOOK_URL environment variable`);
213
+
package/tsconfig.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "compilerOptions": {
3
+ // Environment setup & latest features
4
+ "lib": [
5
+ "DOM",
6
+ "ESNext"
7
+ ],
8
+ "target": "ESNext",
9
+ "module": "ESNext",
10
+ "moduleDetection": "force",
11
+ "allowJs": true,
12
+ // Bundler mode
13
+ "moduleResolution": "bundler",
14
+ "allowImportingTsExtensions": true,
15
+ "verbatimModuleSyntax": true,
16
+ "noEmit": true,
17
+ // Best practices
18
+ "strict": true,
19
+ "skipLibCheck": true,
20
+ "noFallthroughCasesInSwitch": true,
21
+ "noUncheckedIndexedAccess": true,
22
+ "noImplicitOverride": true,
23
+ // Some stricter flags (disabled by default)
24
+ "noUnusedLocals": false,
25
+ "noUnusedParameters": false,
26
+ "noPropertyAccessFromIndexSignature": false
27
+ }
28
+ }