@zenithbuild/core 0.1.0 ā 0.3.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/LICENSE +1 -1
- package/README.md +24 -40
- package/bin/zen-build.ts +2 -0
- package/bin/zen-dev.ts +2 -0
- package/bin/zen-preview.ts +2 -0
- package/bin/zenith.ts +2 -0
- package/cli/commands/add.ts +37 -0
- package/cli/commands/build.ts +37 -0
- package/cli/commands/create.ts +702 -0
- package/cli/commands/dev.ts +197 -0
- package/cli/commands/index.ts +112 -0
- package/cli/commands/preview.ts +62 -0
- package/cli/commands/remove.ts +33 -0
- package/cli/index.ts +10 -0
- package/cli/main.ts +101 -0
- package/cli/utils/branding.ts +153 -0
- package/cli/utils/logger.ts +40 -0
- package/cli/utils/plugin-manager.ts +114 -0
- package/cli/utils/project.ts +71 -0
- package/compiler/build-analyzer.ts +122 -0
- package/compiler/discovery/layouts.ts +61 -0
- package/compiler/index.ts +40 -24
- package/compiler/ir/types.ts +1 -0
- package/compiler/parse/parseScript.ts +29 -5
- package/compiler/parse/parseTemplate.ts +96 -58
- package/compiler/parse/scriptAnalysis.ts +77 -0
- package/compiler/runtime/dataExposure.ts +49 -31
- package/compiler/runtime/generateDOM.ts +18 -17
- package/compiler/runtime/generateHydrationBundle.ts +24 -5
- package/compiler/runtime/transformIR.ts +140 -49
- package/compiler/runtime/wrapExpressionWithLoop.ts +11 -11
- package/compiler/spa-build.ts +70 -153
- package/compiler/ssg-build.ts +412 -0
- package/compiler/transform/layoutProcessor.ts +132 -0
- package/compiler/transform/transformNode.ts +19 -19
- package/dist/cli.js +11648 -0
- package/dist/zen-build.js +11659 -0
- package/dist/zen-dev.js +11659 -0
- package/dist/zen-preview.js +11659 -0
- package/dist/zenith.js +11659 -0
- package/package.json +22 -2
- package/runtime/bundle-generator.ts +416 -0
- package/runtime/client-runtime.ts +532 -0
- package/.eslintignore +0 -15
- package/.gitattributes +0 -2
- package/.github/ISSUE_TEMPLATE/compiler-errors-for-invalid-state-declarations.md +0 -25
- package/.github/ISSUE_TEMPLATE/new_ticket.yaml +0 -34
- package/.github/pull_request_template.md +0 -15
- package/.github/workflows/discord-changelog.yml +0 -141
- package/.github/workflows/discord-notify.yml +0 -242
- package/.github/workflows/discord-version.yml +0 -195
- package/.prettierignore +0 -13
- package/.prettierrc +0 -21
- package/.zen.d.ts +0 -15
- package/app/components/Button.zen +0 -46
- package/app/components/Link.zen +0 -11
- package/app/favicon.ico +0 -0
- package/app/layouts/Main.zen +0 -59
- package/app/pages/about.zen +0 -23
- package/app/pages/blog/[id].zen +0 -53
- package/app/pages/blog/index.zen +0 -32
- package/app/pages/dynamic-dx.zen +0 -712
- package/app/pages/dynamic-primitives.zen +0 -453
- package/app/pages/index.zen +0 -154
- package/app/pages/navigation-demo.zen +0 -229
- package/app/pages/posts/[...slug].zen +0 -61
- package/app/pages/primitives-demo.zen +0 -273
- 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 +0 -601
- package/assets/logos/README.md +0 -54
- package/assets/logos/zen.icns +0 -0
- package/bun.lock +0 -39
- package/compiler/legacy/binding.ts +0 -254
- package/compiler/legacy/bindings.ts +0 -338
- package/compiler/legacy/component-process.ts +0 -1208
- package/compiler/legacy/component.ts +0 -301
- package/compiler/legacy/event.ts +0 -50
- package/compiler/legacy/expression.ts +0 -1149
- package/compiler/legacy/mutation.ts +0 -280
- package/compiler/legacy/parse.ts +0 -299
- package/compiler/legacy/split.ts +0 -608
- package/compiler/legacy/types.ts +0 -32
- package/docs/COMMENTS.md +0 -111
- package/docs/COMMITS.md +0 -36
- package/docs/CONTRIBUTING.md +0 -116
- package/docs/STYLEGUIDE.md +0 -62
- package/scripts/webhook-proxy.ts +0 -213
package/docs/COMMENTS.md
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
# Conventional Comments
|
|
2
|
-
|
|
3
|
-
Zenith uses [Conventional Comments](https://conventionalcomments.org/) to provide clear, actionable feedback in pull requests.
|
|
4
|
-
|
|
5
|
-
## Format
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
<label> [decorations]: <subject>
|
|
9
|
-
|
|
10
|
-
[discussion]
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## š« Quick Reference
|
|
14
|
-
### Labels
|
|
15
|
-
|
|
16
|
-
| Label | Description | Example Use Case |
|
|
17
|
-
|--------------|------------------------------------------------------|-------------------------------------------|
|
|
18
|
-
| **praise** | Highlight something positive | Great implementation, well-documented code |
|
|
19
|
-
| **nitpick** | Minor suggestions that don't require changes | Variable naming, minor style preferences |
|
|
20
|
-
| **suggestion** | Propose improvements to consider | Alternative approaches, optimizations |
|
|
21
|
-
| **issue** | Highlight problems that need to be resolved | Bugs, errors, critical problems |
|
|
22
|
-
| **question** | Ask for clarification or explanation | Understanding intent, approach questions |
|
|
23
|
-
| **thought** | Share ideas or considerations for the future | Architectural thoughts, future improvements |
|
|
24
|
-
| **chore** | Simple tasks like formatting or typos | Missing semicolons, typos, formatting |
|
|
25
|
-
|
|
26
|
-
### Decorations
|
|
27
|
-
|
|
28
|
-
| Decoration | Meaning |
|
|
29
|
-
|-------------------|------------------------------------------------------|
|
|
30
|
-
| **(non-blocking)** | Optional feedback - PR can merge without addressing |
|
|
31
|
-
| **(blocking)** | Must be addressed before merge |
|
|
32
|
-
| **(if-minor)** | Address only if it's a quick fix |
|
|
33
|
-
|
|
34
|
-
## Examples
|
|
35
|
-
|
|
36
|
-
### Praise
|
|
37
|
-
```
|
|
38
|
-
praise: Excellent error handling here!
|
|
39
|
-
|
|
40
|
-
This covers all the edge cases I was worried about.
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### Nitpick (non-blocking)
|
|
44
|
-
```
|
|
45
|
-
nitpick (non-blocking): Consider renaming `temp` to `processedData`
|
|
46
|
-
|
|
47
|
-
While `temp` works, a more descriptive name might help future maintainers.
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### Suggestion
|
|
51
|
-
```
|
|
52
|
-
suggestion: We could use a Map instead of an Object here for better performance
|
|
53
|
-
|
|
54
|
-
Since we're doing frequent lookups, a Map would give us O(1) access time
|
|
55
|
-
and better memory characteristics for this use case.
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### Issue (blocking)
|
|
59
|
-
```
|
|
60
|
-
issue (blocking): This will throw when `items` is undefined
|
|
61
|
-
|
|
62
|
-
We need to add a null/undefined check before calling `.map()` on line 42.
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### Question
|
|
66
|
-
```
|
|
67
|
-
question: Why are we processing this data twice?
|
|
68
|
-
|
|
69
|
-
I see similar logic on lines 15 and 78. Is there a reason we can't
|
|
70
|
-
consolidate these operations?
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### Thought
|
|
74
|
-
```
|
|
75
|
-
thought: This might be a good candidate for a custom hook in the future
|
|
76
|
-
|
|
77
|
-
Not for this PR, but as we add more components with similar behavior,
|
|
78
|
-
extracting this pattern could be valuable.
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Chore
|
|
82
|
-
```
|
|
83
|
-
chore (if-minor): Missing semicolon on line 23
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
## Best Practices
|
|
87
|
-
|
|
88
|
-
1. **Be specific** - Reference line numbers or code sections
|
|
89
|
-
2. **Be kind** - Remember there's a human on the other side
|
|
90
|
-
3. **Be clear** - Explain the "why" behind your feedback
|
|
91
|
-
4. **Use blocking sparingly** - Only for issues that truly need resolution
|
|
92
|
-
5. **Praise good work** - Positive feedback is valuable!
|
|
93
|
-
|
|
94
|
-
## Quick Tips for Reviewers
|
|
95
|
-
|
|
96
|
-
- Start with **praise** for good work
|
|
97
|
-
- Use **suggestion** for most feedback (not blocking unless critical)
|
|
98
|
-
- Reserve **issue (blocking)** for bugs or critical problems
|
|
99
|
-
- Use **question** when you don't understand something
|
|
100
|
-
- Mark style preferences as **nitpick (non-blocking)**
|
|
101
|
-
|
|
102
|
-
## Quick Tips for Authors
|
|
103
|
-
|
|
104
|
-
- Don't take **nitpicks** personally - they're optional
|
|
105
|
-
- Ask for clarification on unclear **questions** or **suggestions**
|
|
106
|
-
- Address all **blocking** comments before requesting re-review
|
|
107
|
-
- Thank reviewers for their time and feedback
|
|
108
|
-
|
|
109
|
-
---
|
|
110
|
-
|
|
111
|
-
**Remember**: The goal is constructive collaboration, not perfection. Use these conventions to make reviews clearer and more productive for everyone.
|
package/docs/COMMITS.md
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
## TL;DR
|
|
2
|
-
***If you find that this is tanking your productivity just use `feat` or `fix` and always apply `!` if pushing breaking changes***
|
|
3
|
-
|
|
4
|
-
## Why bother with conventional commits?
|
|
5
|
-
- _The most important reason for us is to simplify/automate SemVer and our Release strategy_
|
|
6
|
-
- For this reason, please prefix all commits with one of the below [Prefixes](#prefixes)
|
|
7
|
-
|
|
8
|
-
## How does this relate to SemVer?
|
|
9
|
-
- `fix` type commits should be translated to `PATCH` releases.
|
|
10
|
-
- `feat` type commits should be translated to `MINOR` releases.
|
|
11
|
-
- Commits with `BREAKING CHANGE` or `!` (e.g. `feat!: extend parser`) in the commits, regardless of type, should be translated to `MAJOR` releases.
|
|
12
|
-
|
|
13
|
-
## Prefixes
|
|
14
|
-
| Commit Prefix | SemVer Equivalent | Example |
|
|
15
|
-
| --------------- | ----------------- | ------------------------------------ |
|
|
16
|
-
| fix: | PATCH - 0.0.n | fix: html not recognizing state |
|
|
17
|
-
| feat: | MINOR - 0.n.0 | feat: phase 2 event loop |
|
|
18
|
-
| fix!: | MAJOR - n.0.0 | fix!: html not recognizing state |
|
|
19
|
-
| feat!: | MAJOR - n.0.0 | feat!: phase 2 event loop |
|
|
20
|
-
| BREAKING CHANGE | MAJOR - n.0.0 | fix: BREAKING CHANGE component state |
|
|
21
|
-
| BREAKING-CHANGE | MAJOR - n.0.0 | feat: BREAKING-CHANGE build phase 2 |
|
|
22
|
-
| docs: | CHANGELOG | ... |
|
|
23
|
-
| chore: | CHANGELOG | ... |
|
|
24
|
-
| style: | CHANGELOG | ... |
|
|
25
|
-
| test: | CHANGELOG | ... |
|
|
26
|
-
| refactor: | CHANGELOG | ... |
|
|
27
|
-
|
|
28
|
-
### Glossary
|
|
29
|
-
|
|
30
|
-
- `feat:` - New features
|
|
31
|
-
- `fix:` - Bug fixes
|
|
32
|
-
- `docs:` - Documentation changes
|
|
33
|
-
- `style:` - Code style changes (formatting, no logic change)
|
|
34
|
-
- `refactor:` - Code refactoring
|
|
35
|
-
- `test:` - Adding or updating tests
|
|
36
|
-
- `chore:` - Maintenance tasks
|
package/docs/CONTRIBUTING.md
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
# š« Contributing to Zenith
|
|
2
|
-
## š Prerequisites
|
|
3
|
-
|
|
4
|
-
> Before you begin, join the [Discord Server](https://discord.gg/T85bBj8T3n) and **ensure you have the following installed**:
|
|
5
|
-
|
|
6
|
-
- **[Bun](https://bun.sh/)** (v1.0 or later) - Zenith uses Bun as its JavaScript runtime and package manager
|
|
7
|
-
- **[Git](https://git-scm.com/)** - For version control
|
|
8
|
-
|
|
9
|
-
### Installation
|
|
10
|
-
|
|
11
|
-
1. **Clone the repository (no fork)**
|
|
12
|
-
```ts
|
|
13
|
-
git clone https://github.com/judahbsullivan/zenith.js.git
|
|
14
|
-
cd zenith
|
|
15
|
-
```
|
|
16
|
-
2. **Install dependencies**
|
|
17
|
-
```ts
|
|
18
|
-
bun install
|
|
19
|
-
```
|
|
20
|
-
3. **Build the application** (required first)
|
|
21
|
-
```ts
|
|
22
|
-
bun run build
|
|
23
|
-
```
|
|
24
|
-
This compiles `.zen` files from `app/pages/` into `app/dist/`.
|
|
25
|
-
|
|
26
|
-
4. **Run the development server**
|
|
27
|
-
```ts
|
|
28
|
-
bun run dev
|
|
29
|
-
|
|
30
|
-
> **Important**: Use `bun run <script>` to execute npm scripts from package.json. The command `bun build` (without `run`) invokes Bun's built-in bundler, which won't specify our entrypoints by default.
|
|
31
|
-
|
|
32
|
-
## šæ Branching Strategy
|
|
33
|
-
### Option 1: Issue-Driven Development (Preferred)
|
|
34
|
-
|
|
35
|
-
1. **Create or find an issue** on GitHub that describes the work you want to do
|
|
36
|
-
2. **Create a branch from the issue** directly on GitHub
|
|
37
|
-
- Branch name format: `{issue-number}-{short-description}`
|
|
38
|
-
- Example: `33-contributing-md`
|
|
39
|
-
3. **Pull the branch** to your local machine
|
|
40
|
-
```ts
|
|
41
|
-
git fetch origin
|
|
42
|
-
git checkout 33-contributing-md
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### Option 2: Feature/Fix Branch
|
|
46
|
-
|
|
47
|
-
If you're working on something without an existing issue:
|
|
48
|
-
|
|
49
|
-
1. **Branch from `main`**
|
|
50
|
-
```ts
|
|
51
|
-
git checkout main
|
|
52
|
-
git pull origin main
|
|
53
|
-
git checkout -b {prefix}/{short-description}
|
|
54
|
-
```
|
|
55
|
-
2. **Use appropriate prefix subfolder** based on the type of change:
|
|
56
|
-
- `feat/` for new features ā MINOR version bump (0.n.0)
|
|
57
|
-
- `fix/` for bug fixes ā PATCH version bump (0.0.n)
|
|
58
|
-
- `docs/` for documentation changes
|
|
59
|
-
- `refactor/` for code refactoring
|
|
60
|
-
- `test/` for adding or updating tests
|
|
61
|
-
- `chore/` for maintenance tasks
|
|
62
|
-
|
|
63
|
-
Example: `feat/reactive-state` or `fix/router-navigation`
|
|
64
|
-
|
|
65
|
-
## š Commit Strategy
|
|
66
|
-
> Zenith follows [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) for consistent versioning and changelog generation.
|
|
67
|
-
|
|
68
|
-
### Commit Message Format
|
|
69
|
-
|
|
70
|
-
```ts
|
|
71
|
-
<type>[optional scope]: <description>
|
|
72
|
-
[optional body]
|
|
73
|
-
[optional footer(s)]
|
|
74
|
-
```
|
|
75
|
-
### Quick Reference
|
|
76
|
-
|
|
77
|
-
| Prefix | SemVer Impact | Example |
|
|
78
|
-
|----------|---------------|----------------------------------|
|
|
79
|
-
| `fix:` | PATCH (0.0.n) | `fix: html not recognizing state` |
|
|
80
|
-
| `feat:` | MINOR (0.n.0) | `feat: add reactive state system` |
|
|
81
|
-
| `feat!:` | MAJOR (n.0.0) | `feat!: change compiler API` |
|
|
82
|
-
| `fix!:` | MAJOR (n.0.0) | `fix!: remove deprecated methods` |
|
|
83
|
-
|
|
84
|
-
**Breaking Changes**: Use `!` after the type or include `BREAKING CHANGE:` in the footer.
|
|
85
|
-
|
|
86
|
-
**š For complete details, see [COMMITS.md](COMMITS.md)**
|
|
87
|
-
|
|
88
|
-
## š¬ Pull Request Comment Strategy
|
|
89
|
-
> Zenith uses [Conventional Comments](https://conventionalcomments.org/) for clear, actionable PR feedback.
|
|
90
|
-
|
|
91
|
-
### Comment Format
|
|
92
|
-
```ts
|
|
93
|
-
<label> [decorations]: <subject>
|
|
94
|
-
[discussion]
|
|
95
|
-
```
|
|
96
|
-
### Examples
|
|
97
|
-
```ts
|
|
98
|
-
suggestion (non-blocking): Consider using a more descriptive variable name
|
|
99
|
-
This would improve readability for future maintainers.
|
|
100
|
-
```
|
|
101
|
-
```ts
|
|
102
|
-
issue (blocking): This function will throw an error when input is null
|
|
103
|
-
We need to add null checking before processing.
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
**š For complete details, see [COMMENTS.md](COMMENTS.md)**
|
|
107
|
-
|
|
108
|
-
## ā Questions?
|
|
109
|
-
- Check existing [Issues](https://github.com/judahbsullivan/zenith/issues)
|
|
110
|
-
- Review [README.md](../README.md) for project overview
|
|
111
|
-
- Reach out to maintainers in your PR, Issue or [Discord!](https://discord.gg/T85bBj8T3n)
|
|
112
|
-
|
|
113
|
-
---
|
|
114
|
-
|
|
115
|
-
**Remember**: Contributing should be enjoyable! Don't hesitate to ask questions if anything is unclear.
|
|
116
|
-
|
package/docs/STYLEGUIDE.md
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# Style Guide
|
|
2
|
-
## Code Style
|
|
3
|
-
- TypeScript only
|
|
4
|
-
- No implicit any
|
|
5
|
-
- Prefer explicit return types for public APIs
|
|
6
|
-
- Avoid magic strings
|
|
7
|
-
## Architectural Rules
|
|
8
|
-
- Compiler decisions > runtime decisions
|
|
9
|
-
- HTML is the source of truth
|
|
10
|
-
- Navigation controls rendering, not components
|
|
11
|
-
- Layouts persist unless explicitly changed
|
|
12
|
-
## Naming Conventions
|
|
13
|
-
- camelCase for variables
|
|
14
|
-
- PascalCase for components
|
|
15
|
-
- kebab-case for files where appropriate
|
|
16
|
-
- `.zenith` for user-facing components
|
|
17
|
-
## API Design Rules
|
|
18
|
-
- No developer flags for runtime behavior
|
|
19
|
-
- Behavior inferred via static analysis
|
|
20
|
-
- Fail loudly at compile time
|
|
21
|
-
## What to Avoid
|
|
22
|
-
- Implicit global state
|
|
23
|
-
- Hidden hydration logic
|
|
24
|
-
- Runtime heuristics
|
|
25
|
-
- JSX-only APIs
|
|
26
|
-
## Guiding Question
|
|
27
|
-
> "Can the compiler decide this instead?"
|
|
28
|
-
If yes ā move it out of runtime.
|
|
29
|
-
|
|
30
|
-
## šÆ Development Philosophy
|
|
31
|
-
|
|
32
|
-
- **Simplicity over complexity** - Zenith aims to be intuitive and straightforward
|
|
33
|
-
- **HTML-first** - HTML is the source of truth
|
|
34
|
-
- **Consistency** - Follow established patterns in the codebase
|
|
35
|
-
- **Iteration speed** - Don't let perfect be the enemy of good
|
|
36
|
-
|
|
37
|
-
## š§Ŗ Testing Your Changes
|
|
38
|
-
|
|
39
|
-
Before submitting a PR:
|
|
40
|
-
|
|
41
|
-
1. **Build the application** to compile your changes:
|
|
42
|
-
```bash
|
|
43
|
-
bun run build
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
2. **Run the dev server** and verify your changes work:
|
|
47
|
-
```bash
|
|
48
|
-
bun run dev
|
|
49
|
-
```
|
|
50
|
-
Visit `http://localhost:3000` to test.
|
|
51
|
-
|
|
52
|
-
3. **Format your code**:
|
|
53
|
-
```bash
|
|
54
|
-
bun run format
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
4. **Check formatting** (optional):
|
|
58
|
-
```bash
|
|
59
|
-
bun run format:check
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
> **Note**: Use `bun run <script>` for npm scripts. Plain `bun build` invokes Bun's bundler, not the project build script.
|
package/scripts/webhook-proxy.ts
DELETED
|
@@ -1,213 +0,0 @@
|
|
|
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
|
-
|