@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.
- package/.eslintignore +15 -0
- package/.gitattributes +2 -0
- package/.github/ISSUE_TEMPLATE/compiler-errors-for-invalid-state-declarations.md +25 -0
- package/.github/ISSUE_TEMPLATE/new_ticket.yaml +34 -0
- package/.github/pull_request_template.md +15 -0
- package/.github/workflows/discord-changelog.yml +141 -0
- package/.github/workflows/discord-notify.yml +242 -0
- package/.github/workflows/discord-version.yml +195 -0
- package/.prettierignore +13 -0
- package/.prettierrc +21 -0
- package/.zen.d.ts +15 -0
- package/LICENSE +21 -0
- package/README.md +55 -0
- package/app/components/Button.zen +46 -0
- package/app/components/Link.zen +11 -0
- package/app/favicon.ico +0 -0
- package/app/layouts/Main.zen +59 -0
- package/app/pages/about.zen +23 -0
- package/app/pages/blog/[id].zen +53 -0
- package/app/pages/blog/index.zen +32 -0
- package/app/pages/dynamic-dx.zen +712 -0
- package/app/pages/dynamic-primitives.zen +453 -0
- package/app/pages/index.zen +154 -0
- package/app/pages/navigation-demo.zen +229 -0
- package/app/pages/posts/[...slug].zen +61 -0
- package/app/pages/primitives-demo.zen +273 -0
- package/assets/logos/0E3B5DDD-605C-4839-BB2E-DFCA8ADC9604.PNG +0 -0
- package/assets/logos/760971E5-79A1-44F9-90B9-925DF30F4278.PNG +0 -0
- package/assets/logos/8A06ED80-9ED2-4689-BCBD-13B2E95EE8E4.JPG +0 -0
- package/assets/logos/C691FF58-ED13-4E8D-B6A3-02E835849340.PNG +0 -0
- package/assets/logos/C691FF58-ED13-4E8D-B6A3-02E835849340.svg +601 -0
- package/assets/logos/README.md +54 -0
- package/assets/logos/zen.icns +0 -0
- package/bun.lock +39 -0
- package/compiler/README.md +380 -0
- package/compiler/errors/compilerError.ts +24 -0
- package/compiler/finalize/finalizeOutput.ts +163 -0
- package/compiler/finalize/generateFinalBundle.ts +82 -0
- package/compiler/index.ts +44 -0
- package/compiler/ir/types.ts +83 -0
- package/compiler/legacy/binding.ts +254 -0
- package/compiler/legacy/bindings.ts +338 -0
- package/compiler/legacy/component-process.ts +1208 -0
- package/compiler/legacy/component.ts +301 -0
- package/compiler/legacy/event.ts +50 -0
- package/compiler/legacy/expression.ts +1149 -0
- package/compiler/legacy/mutation.ts +280 -0
- package/compiler/legacy/parse.ts +299 -0
- package/compiler/legacy/split.ts +608 -0
- package/compiler/legacy/types.ts +32 -0
- package/compiler/output/types.ts +34 -0
- package/compiler/parse/detectMapExpressions.ts +102 -0
- package/compiler/parse/parseScript.ts +22 -0
- package/compiler/parse/parseTemplate.ts +425 -0
- package/compiler/parse/parseZenFile.ts +66 -0
- package/compiler/parse/trackLoopContext.ts +82 -0
- package/compiler/runtime/dataExposure.ts +291 -0
- package/compiler/runtime/generateDOM.ts +144 -0
- package/compiler/runtime/generateHydrationBundle.ts +383 -0
- package/compiler/runtime/hydration.ts +309 -0
- package/compiler/runtime/navigation.ts +432 -0
- package/compiler/runtime/thinRuntime.ts +160 -0
- package/compiler/runtime/transformIR.ts +256 -0
- package/compiler/runtime/wrapExpression.ts +84 -0
- package/compiler/runtime/wrapExpressionWithLoop.ts +77 -0
- package/compiler/spa-build.ts +1000 -0
- package/compiler/test/validate-test.ts +104 -0
- package/compiler/transform/generateBindings.ts +47 -0
- package/compiler/transform/generateHTML.ts +28 -0
- package/compiler/transform/transformNode.ts +126 -0
- package/compiler/transform/transformTemplate.ts +38 -0
- package/compiler/validate/validateExpressions.ts +168 -0
- package/core/index.ts +135 -0
- package/core/lifecycle/index.ts +49 -0
- package/core/lifecycle/zen-mount.ts +182 -0
- package/core/lifecycle/zen-unmount.ts +88 -0
- package/core/reactivity/index.ts +54 -0
- package/core/reactivity/tracking.ts +167 -0
- package/core/reactivity/zen-batch.ts +57 -0
- package/core/reactivity/zen-effect.ts +139 -0
- package/core/reactivity/zen-memo.ts +146 -0
- package/core/reactivity/zen-ref.ts +52 -0
- package/core/reactivity/zen-signal.ts +121 -0
- package/core/reactivity/zen-state.ts +180 -0
- package/core/reactivity/zen-untrack.ts +44 -0
- package/docs/COMMENTS.md +111 -0
- package/docs/COMMITS.md +36 -0
- package/docs/CONTRIBUTING.md +116 -0
- package/docs/STYLEGUIDE.md +62 -0
- package/package.json +44 -0
- package/router/index.ts +76 -0
- package/router/manifest.ts +314 -0
- package/router/navigation/ZenLink.zen +231 -0
- package/router/navigation/index.ts +78 -0
- package/router/navigation/zen-link.ts +584 -0
- package/router/runtime.ts +458 -0
- package/router/types.ts +168 -0
- package/runtime/build.ts +17 -0
- package/runtime/serve.ts +93 -0
- package/scripts/webhook-proxy.ts +213 -0
- package/tsconfig.json +28 -0
package/runtime/serve.ts
ADDED
|
@@ -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
|
+
}
|