zyket 1.1.4 → 1.1.6
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/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +8 -0
- package/plugin/skills/generate/SKILL.md +33 -0
- package/plugin/skills/generate/components/event.md +47 -0
- package/plugin/skills/generate/components/extension.md +78 -0
- package/plugin/skills/generate/components/guard.md +44 -0
- package/plugin/skills/generate/components/handler.md +48 -0
- package/plugin/skills/generate/components/middleware.md +52 -0
- package/plugin/skills/generate/components/route.md +62 -0
- package/plugin/skills/generate/components/scheduler.md +60 -0
- package/plugin/skills/generate/components/service.md +66 -0
- package/plugin/skills/generate/components/worker.md +53 -0
- package/plugin/skills/generate/rules.md +29 -0
- package/src/services/express/Express.js +1 -1
- package/.claude/settings.json +0 -3
- package/.claude-plugin/marketplace.json +0 -16
- package/claude-plugin/.claude-plugin/commands/event.md +0 -29
- package/claude-plugin/.claude-plugin/commands/guard.md +0 -37
- package/claude-plugin/.claude-plugin/commands/handler.md +0 -37
- package/claude-plugin/.claude-plugin/commands/middleware.md +0 -28
- package/claude-plugin/.claude-plugin/commands/model.md +0 -40
- package/claude-plugin/.claude-plugin/commands/route.md +0 -42
- package/claude-plugin/.claude-plugin/commands/schedule.md +0 -38
- package/claude-plugin/.claude-plugin/commands/service.md +0 -59
- package/claude-plugin/.claude-plugin/commands/worker.md +0 -39
- package/claude-plugin/.claude-plugin/plugin.json +0 -133
- package/claude-plugin/.claude-plugin/skills/auth.md +0 -128
- package/claude-plugin/.claude-plugin/skills/database.md +0 -132
- package/claude-plugin/.claude-plugin/skills/events.md +0 -63
- package/claude-plugin/.claude-plugin/skills/extensions.md +0 -75
- package/claude-plugin/.claude-plugin/skills/middlewares.md +0 -97
- package/claude-plugin/.claude-plugin/skills/overview.md +0 -109
- package/claude-plugin/.claude-plugin/skills/routes.md +0 -141
- package/claude-plugin/.claude-plugin/skills/scheduler.md +0 -60
- package/claude-plugin/.claude-plugin/skills/services.md +0 -152
- package/claude-plugin/.claude-plugin/skills/socketio.md +0 -110
- package/claude-plugin/.claude-plugin/skills/workers.md +0 -88
- package/claude-plugin/README.md +0 -54
package/package.json
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: generate
|
|
3
|
+
description: Generate Zyket framework components — handlers, guards, routes, middlewares, services, events, schedulers, workers, and extensions. Use when the user wants to create or scaffold any Zyket component.
|
|
4
|
+
allowed-tools: Read, Write, Grep, Glob, Bash
|
|
5
|
+
argument-hint: [component-type] [name]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Zyket Component Generator
|
|
9
|
+
|
|
10
|
+
Generate a **$ARGUMENTS** component for the Zyket framework.
|
|
11
|
+
|
|
12
|
+
## Instructions
|
|
13
|
+
|
|
14
|
+
1. Parse `$ARGUMENTS` — first word is the component type, remaining words form the name.
|
|
15
|
+
2. Read the matching component reference from [components/](components/) to get the exact pattern.
|
|
16
|
+
3. Read the [rules.md](rules.md) file for conventions that apply to all components.
|
|
17
|
+
4. Before writing, read the actual base class from the project's `node_modules/zyket/` or framework source to confirm the API hasn't changed.
|
|
18
|
+
5. Create the target directory if it doesn't exist.
|
|
19
|
+
6. Write the component file following the reference pattern exactly.
|
|
20
|
+
|
|
21
|
+
## Component Types
|
|
22
|
+
|
|
23
|
+
| Type | Reference | Location |
|
|
24
|
+
|------|-----------|----------|
|
|
25
|
+
| `handler` | [components/handler.md](components/handler.md) | `src/handlers/<name>.js` |
|
|
26
|
+
| `guard` | [components/guard.md](components/guard.md) | `src/guards/<name>.js` |
|
|
27
|
+
| `route` | [components/route.md](components/route.md) | `src/routes/<path>.js` |
|
|
28
|
+
| `middleware` | [components/middleware.md](components/middleware.md) | `src/middlewares/<name>.js` |
|
|
29
|
+
| `service` | [components/service.md](components/service.md) | Custom location |
|
|
30
|
+
| `event` | [components/event.md](components/event.md) | `src/events/<name>.js` |
|
|
31
|
+
| `scheduler` | [components/scheduler.md](components/scheduler.md) | `src/schedulers/<name>.js` |
|
|
32
|
+
| `worker` | [components/worker.md](components/worker.md) | `src/workers/<name>.js` |
|
|
33
|
+
| `extension` | [components/extension.md](components/extension.md) | Custom location |
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Event
|
|
2
|
+
|
|
3
|
+
Internal event handler. Enables decoupled pub/sub communication between components.
|
|
4
|
+
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
`src/events/<name>.js` — the filename becomes the **event name**.
|
|
8
|
+
|
|
9
|
+
## Base Class
|
|
10
|
+
|
|
11
|
+
`Event` from `zyket`
|
|
12
|
+
|
|
13
|
+
## Template
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
const { Event } = require("zyket");
|
|
17
|
+
|
|
18
|
+
module.exports = class extends Event {
|
|
19
|
+
async handle({ container, payload }) {
|
|
20
|
+
// Process the event payload
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Method Signature
|
|
26
|
+
|
|
27
|
+
| Param | Type | Description |
|
|
28
|
+
|-------|------|-------------|
|
|
29
|
+
| `container` | `ContainerBuilder` | DI service container |
|
|
30
|
+
| `payload` | `any` | Data passed when the event was emitted |
|
|
31
|
+
|
|
32
|
+
## Emitting Events
|
|
33
|
+
|
|
34
|
+
From any component with container access:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
// Synchronous-style (still returns promise)
|
|
38
|
+
container.get('events').emit('event-name', { key: "value" });
|
|
39
|
+
|
|
40
|
+
// Async with timeout (default 30s)
|
|
41
|
+
await container.get('events').emitAsync('event-name', { key: "value" }, 15000);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Requirements
|
|
45
|
+
|
|
46
|
+
- The `events` service must be enabled (`DISABLE_EVENTS` must not be `true`).
|
|
47
|
+
- The event name used in `emit()` must match a filename in `src/events/`.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Extension
|
|
2
|
+
|
|
3
|
+
Post-boot plugin with full container access. Integrates with booted services to add features like dashboards, file browsers, or third-party integrations.
|
|
4
|
+
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
No fixed location — extensions are manually registered in the Kernel constructor.
|
|
8
|
+
|
|
9
|
+
## Base Class
|
|
10
|
+
|
|
11
|
+
`Extension` from `zyket`
|
|
12
|
+
|
|
13
|
+
## Template
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
const { Extension } = require("zyket");
|
|
17
|
+
|
|
18
|
+
module.exports = class MyExtension extends Extension {
|
|
19
|
+
constructor(options = {}) {
|
|
20
|
+
super("MyExtension"); // extension display name
|
|
21
|
+
// Store any configuration options
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async load(container) {
|
|
25
|
+
// Runs after all services have booted
|
|
26
|
+
// Full access to every service via container
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Registration
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
const { Kernel } = require("zyket");
|
|
35
|
+
const MyExtension = require("./extensions/MyExtension");
|
|
36
|
+
|
|
37
|
+
const kernel = new Kernel({
|
|
38
|
+
extensions: [new MyExtension({ path: "/my-ext" })]
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Method Signature
|
|
43
|
+
|
|
44
|
+
| Param | Type | Description |
|
|
45
|
+
|-------|------|-------------|
|
|
46
|
+
| `container` | `ContainerBuilder` | DI service container with all booted services |
|
|
47
|
+
|
|
48
|
+
## Common Patterns
|
|
49
|
+
|
|
50
|
+
### Registering additional routes
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
async load(container) {
|
|
54
|
+
const express = container.get('express');
|
|
55
|
+
express.registerRoutes([new MyRoute("/custom-path")]);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Registering a raw Express handler
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
async load(container) {
|
|
63
|
+
const express = container.get('express');
|
|
64
|
+
express.regiterRawAllRoutes("/webhook", (req, res) => {
|
|
65
|
+
res.send("OK");
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Checking service availability
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
async load(container) {
|
|
74
|
+
if (!container.has('s3')) {
|
|
75
|
+
return container.get('logger').warn('MyExtension: s3 service not found, skipping');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Guard
|
|
2
|
+
|
|
3
|
+
Socket.IO guard. Protects handlers and connections by running validation logic before they execute.
|
|
4
|
+
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
`src/guards/<name>.js` — the filename becomes the **guard name** referenced in handlers.
|
|
8
|
+
|
|
9
|
+
## Base Class
|
|
10
|
+
|
|
11
|
+
`Guard` from `zyket`
|
|
12
|
+
|
|
13
|
+
## Template
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
const { Guard } = require("zyket");
|
|
17
|
+
|
|
18
|
+
module.exports = class extends Guard {
|
|
19
|
+
async handle({ container, socket, io }) {
|
|
20
|
+
// Throw an error to block the event or connection
|
|
21
|
+
// If this method completes without throwing, the guard passes
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Method Signature
|
|
27
|
+
|
|
28
|
+
| Param | Type | Description |
|
|
29
|
+
|-------|------|-------------|
|
|
30
|
+
| `container` | `ContainerBuilder` | DI service container |
|
|
31
|
+
| `socket` | `Socket` | The connected socket |
|
|
32
|
+
| `io` | `Server` | Socket.IO server instance |
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
Reference guards by filename (without `.js`) in a handler's `guards` array:
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
// src/handlers/send-message.js
|
|
40
|
+
module.exports = class extends Handler {
|
|
41
|
+
guards = ["auth"]; // references src/guards/auth.js
|
|
42
|
+
async handle({ container, socket, data, io }) { }
|
|
43
|
+
}
|
|
44
|
+
```
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Handler
|
|
2
|
+
|
|
3
|
+
Socket.IO event handler. Receives and responds to real-time WebSocket events.
|
|
4
|
+
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
`src/handlers/<name>.js` — the filename becomes the **event name** the client emits.
|
|
8
|
+
|
|
9
|
+
The special file `src/handlers/connection.js` runs when a new socket connects.
|
|
10
|
+
|
|
11
|
+
## Base Class
|
|
12
|
+
|
|
13
|
+
`Handler` from `zyket`
|
|
14
|
+
|
|
15
|
+
## Template
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
const { Handler } = require("zyket");
|
|
19
|
+
|
|
20
|
+
module.exports = class extends Handler {
|
|
21
|
+
// Optional: guard names that must pass before this handler runs
|
|
22
|
+
// guards = ["auth"];
|
|
23
|
+
|
|
24
|
+
async handle({ container, socket, data, io }) {
|
|
25
|
+
// data — payload sent by the client
|
|
26
|
+
// socket — the connected socket instance
|
|
27
|
+
// io — the Socket.IO server instance
|
|
28
|
+
// Return value is sent back via callback if the client provided one
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Method Signature
|
|
34
|
+
|
|
35
|
+
| Param | Type | Description |
|
|
36
|
+
|-------|------|-------------|
|
|
37
|
+
| `container` | `ContainerBuilder` | DI service container |
|
|
38
|
+
| `socket` | `Socket` | The connected socket |
|
|
39
|
+
| `data` | `any` | Payload from the client |
|
|
40
|
+
| `io` | `Server` | Socket.IO server instance |
|
|
41
|
+
|
|
42
|
+
## Guards
|
|
43
|
+
|
|
44
|
+
Set `guards` as an array of guard filenames (without `.js`). Guards run in order before the handler. If a guard throws, the handler is skipped and the error is returned to the client callback.
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
guards = ["auth", "rate-limit"];
|
|
48
|
+
```
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Middleware
|
|
2
|
+
|
|
3
|
+
HTTP middleware. Runs before route handlers to validate, transform, or block requests.
|
|
4
|
+
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
`src/middlewares/<name>.js`
|
|
8
|
+
|
|
9
|
+
Middlewares are **not auto-discovered**. They must be imported and attached to routes manually.
|
|
10
|
+
|
|
11
|
+
## Base Class
|
|
12
|
+
|
|
13
|
+
`Middleware` from `zyket`
|
|
14
|
+
|
|
15
|
+
## Template
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
const { Middleware } = require("zyket");
|
|
19
|
+
|
|
20
|
+
module.exports = class extends Middleware {
|
|
21
|
+
handle({ container, request, response, next }) {
|
|
22
|
+
// Call next() to pass control to the next middleware or route handler
|
|
23
|
+
// Or respond directly to block the request
|
|
24
|
+
next();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Method Signature
|
|
30
|
+
|
|
31
|
+
| Param | Type | Description |
|
|
32
|
+
|-------|------|-------------|
|
|
33
|
+
| `container` | `ContainerBuilder` | DI service container |
|
|
34
|
+
| `request` | `Request` | Express request object |
|
|
35
|
+
| `response` | `Response` | Express response object |
|
|
36
|
+
| `next` | `Function` | Call to continue the chain |
|
|
37
|
+
|
|
38
|
+
## Usage in Routes
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
const { Route } = require("zyket");
|
|
42
|
+
const AuthMiddleware = require("../middlewares/auth");
|
|
43
|
+
|
|
44
|
+
module.exports = class extends Route {
|
|
45
|
+
middlewares = {
|
|
46
|
+
get: [new AuthMiddleware()],
|
|
47
|
+
post: [new AuthMiddleware()]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async get({ container, request }) { }
|
|
51
|
+
}
|
|
52
|
+
```
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Route
|
|
2
|
+
|
|
3
|
+
HTTP endpoint. Handles REST API requests via Express.
|
|
4
|
+
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
`src/routes/<path>.js` — the file path maps to the **URL path**:
|
|
8
|
+
|
|
9
|
+
| File | URL |
|
|
10
|
+
|------|-----|
|
|
11
|
+
| `src/routes/index.js` | `/` |
|
|
12
|
+
| `src/routes/users.js` | `/users` |
|
|
13
|
+
| `src/routes/users/[id].js` | `/users/:id` |
|
|
14
|
+
| `src/routes/auth/login.js` | `/auth/login` |
|
|
15
|
+
|
|
16
|
+
- `index.js` maps to the parent directory path
|
|
17
|
+
- `[param]` in filenames becomes `:param` in the URL
|
|
18
|
+
- Nested folders create nested URL segments
|
|
19
|
+
|
|
20
|
+
## Base Class
|
|
21
|
+
|
|
22
|
+
`Route` from `zyket`
|
|
23
|
+
|
|
24
|
+
## Template
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
const { Route } = require("zyket");
|
|
28
|
+
|
|
29
|
+
module.exports = class extends Route {
|
|
30
|
+
// Optional: attach middlewares per HTTP method
|
|
31
|
+
// middlewares = {
|
|
32
|
+
// get: [new SomeMiddleware()],
|
|
33
|
+
// post: [new SomeMiddleware()]
|
|
34
|
+
// }
|
|
35
|
+
|
|
36
|
+
async get({ container, request, response }) {
|
|
37
|
+
return { data: "value" };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async post({ container, request, response }) {
|
|
41
|
+
const body = request.body;
|
|
42
|
+
return { status: 201, created: true };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Also available: put, delete
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Method Signature
|
|
50
|
+
|
|
51
|
+
| Param | Type | Description |
|
|
52
|
+
|-------|------|-------------|
|
|
53
|
+
| `container` | `ContainerBuilder` | DI service container |
|
|
54
|
+
| `request` | `Request` | Express request object |
|
|
55
|
+
| `response` | `Response` | Express response object |
|
|
56
|
+
|
|
57
|
+
## Return Values
|
|
58
|
+
|
|
59
|
+
- Return an **object** — the framework wraps it with `{ success: true, ...returnValue }` and sends as JSON.
|
|
60
|
+
- Set a `status` key to change the HTTP status code (defaults to `200`).
|
|
61
|
+
- Return a `RedirectResponse` to redirect: `return new RedirectResponse("/target-url")`.
|
|
62
|
+
- Return a `Buffer` to send a file download.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Scheduler
|
|
2
|
+
|
|
3
|
+
Cron job. Runs tasks on a recurring schedule using cron expressions.
|
|
4
|
+
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
`src/schedulers/<name>.js` — the filename becomes the **scheduler name**.
|
|
8
|
+
|
|
9
|
+
## Base Class
|
|
10
|
+
|
|
11
|
+
`Schedule` from `zyket`
|
|
12
|
+
|
|
13
|
+
## Template
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
const { Schedule } = require("zyket");
|
|
17
|
+
|
|
18
|
+
module.exports = class extends Schedule {
|
|
19
|
+
time = "*/5 * * * *"; // required: cron expression
|
|
20
|
+
|
|
21
|
+
async handle({ container }) {
|
|
22
|
+
// Runs on the cron schedule
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Properties
|
|
28
|
+
|
|
29
|
+
| Property | Type | Required | Description |
|
|
30
|
+
|----------|------|----------|-------------|
|
|
31
|
+
| `time` | `string` | Yes | Cron expression defining the schedule |
|
|
32
|
+
|
|
33
|
+
## Method Signature
|
|
34
|
+
|
|
35
|
+
| Param | Type | Description |
|
|
36
|
+
|-------|------|-------------|
|
|
37
|
+
| `container` | `ContainerBuilder` | DI service container |
|
|
38
|
+
|
|
39
|
+
## Cron Expression Reference
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
┌────────── minute (0-59)
|
|
43
|
+
│ ┌──────── hour (0-23)
|
|
44
|
+
│ │ ┌────── day of month (1-31)
|
|
45
|
+
│ │ │ ┌──── month (1-12)
|
|
46
|
+
│ │ │ │ ┌── day of week (0-7, 0 and 7 = Sunday)
|
|
47
|
+
│ │ │ │ │
|
|
48
|
+
* * * * *
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
| Expression | Meaning |
|
|
52
|
+
|------------|---------|
|
|
53
|
+
| `*/5 * * * *` | Every 5 minutes |
|
|
54
|
+
| `0 * * * *` | Every hour |
|
|
55
|
+
| `0 0 * * *` | Daily at midnight |
|
|
56
|
+
| `0 2 * * 0` | Sundays at 2 AM |
|
|
57
|
+
|
|
58
|
+
## Requirements
|
|
59
|
+
|
|
60
|
+
- The `scheduler` service must be enabled (`DISABLE_SCHEDULER` must not be `true`).
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Service
|
|
2
|
+
|
|
3
|
+
Custom service with dependency injection. Long-running components that provide shared functionality across the application.
|
|
4
|
+
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
No fixed location — services are manually registered in the Kernel constructor.
|
|
8
|
+
|
|
9
|
+
## Base Class
|
|
10
|
+
|
|
11
|
+
`Service` from `zyket`
|
|
12
|
+
|
|
13
|
+
## Template
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
const { Service } = require("zyket");
|
|
17
|
+
|
|
18
|
+
module.exports = class MyService extends Service {
|
|
19
|
+
#container;
|
|
20
|
+
|
|
21
|
+
constructor(container) {
|
|
22
|
+
super("my-service"); // name used with container.get()
|
|
23
|
+
this.#container = container;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async boot({ httpServer } = {}) {
|
|
27
|
+
// Called during kernel boot
|
|
28
|
+
// Initialize connections, load config, set up state
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Public API methods
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Registration
|
|
36
|
+
|
|
37
|
+
Services are registered in the Kernel constructor as a tuple: `[name, class, args]`.
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
const { Kernel } = require("zyket");
|
|
41
|
+
const MyService = require("./services/MyService");
|
|
42
|
+
|
|
43
|
+
const kernel = new Kernel({
|
|
44
|
+
services: [
|
|
45
|
+
["my-service", MyService, ["@service_container"]]
|
|
46
|
+
]
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Special Arguments
|
|
51
|
+
|
|
52
|
+
| Placeholder | Replaced With |
|
|
53
|
+
|------------|---------------|
|
|
54
|
+
| `"@service_container"` | The DI `ContainerBuilder` instance |
|
|
55
|
+
|
|
56
|
+
## Boot Signature
|
|
57
|
+
|
|
58
|
+
| Param | Type | Description |
|
|
59
|
+
|-------|------|-------------|
|
|
60
|
+
| `httpServer` | `http.Server` | The underlying HTTP server |
|
|
61
|
+
|
|
62
|
+
## Accessing From Other Components
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
const myService = container.get("my-service");
|
|
66
|
+
```
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Worker
|
|
2
|
+
|
|
3
|
+
BullMQ job processor. Processes background jobs from a named queue.
|
|
4
|
+
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
`src/workers/<name>.js` — the filename becomes the **worker name**.
|
|
8
|
+
|
|
9
|
+
## Base Class
|
|
10
|
+
|
|
11
|
+
`Worker` from `zyket`
|
|
12
|
+
|
|
13
|
+
## Template
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
const { Worker } = require("zyket");
|
|
17
|
+
|
|
18
|
+
module.exports = class extends Worker {
|
|
19
|
+
queueName = "my-queue"; // required: must match a queue in QUEUES env var
|
|
20
|
+
|
|
21
|
+
async handle({ container, job }) {
|
|
22
|
+
// job.data contains the job payload
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Properties
|
|
28
|
+
|
|
29
|
+
| Property | Type | Required | Description |
|
|
30
|
+
|----------|------|----------|-------------|
|
|
31
|
+
| `queueName` | `string` | Yes | Name of the BullMQ queue to process |
|
|
32
|
+
|
|
33
|
+
## Method Signature
|
|
34
|
+
|
|
35
|
+
| Param | Type | Description |
|
|
36
|
+
|-------|------|-------------|
|
|
37
|
+
| `container` | `ContainerBuilder` | DI service container |
|
|
38
|
+
| `job` | `Job` | BullMQ job instance |
|
|
39
|
+
|
|
40
|
+
## Adding Jobs to a Queue
|
|
41
|
+
|
|
42
|
+
From any component with container access:
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
const bull = container.get('bullmq');
|
|
46
|
+
await bull.queues['my-queue'].add('job-name', { key: "value" });
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Requirements
|
|
50
|
+
|
|
51
|
+
- `CACHE_URL` environment variable must be set (Redis connection).
|
|
52
|
+
- `QUEUES` environment variable must include the queue name.
|
|
53
|
+
- `DISABLE_BULLMQ` must not be `true`.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Zyket Generation Rules
|
|
2
|
+
|
|
3
|
+
These rules apply to **all** generated components.
|
|
4
|
+
|
|
5
|
+
## Module System
|
|
6
|
+
|
|
7
|
+
- Always use `module.exports =` — Zyket uses `require()` and validates with `prototype instanceof BaseClass`.
|
|
8
|
+
- Always import base classes from `zyket`: `const { Handler } = require("zyket");`
|
|
9
|
+
|
|
10
|
+
## Auto-Discovery
|
|
11
|
+
|
|
12
|
+
Handlers, guards, routes, events, schedulers, and workers are **auto-discovered** by the framework.
|
|
13
|
+
- The **filename** becomes the component's identity (event name, guard name, route path, etc.).
|
|
14
|
+
- Use **kebab-case** for filenames.
|
|
15
|
+
- Do **not** add constructor parameters to auto-discovered components — they receive only their name (derived from filename) via the base class constructor.
|
|
16
|
+
|
|
17
|
+
## Dependency Injection
|
|
18
|
+
|
|
19
|
+
- All component methods receive `{ container }` as part of their arguments.
|
|
20
|
+
- Access services via `container.get('service-name')`.
|
|
21
|
+
- Available default services: `logger`, `database`, `cache`, `s3`, `events`, `scheduler`, `bullmq`, `socketio`, `express`.
|
|
22
|
+
- Service availability depends on environment variables — check before using.
|
|
23
|
+
|
|
24
|
+
## Code Style
|
|
25
|
+
|
|
26
|
+
- Keep components focused — one responsibility per file.
|
|
27
|
+
- Don't add guards or middlewares unless the user explicitly asks for them.
|
|
28
|
+
- Don't add error handling that duplicates what the framework already provides.
|
|
29
|
+
- Don't add comments explaining obvious code.
|
|
@@ -71,6 +71,7 @@ module.exports = class Express extends Service {
|
|
|
71
71
|
async (req, res) => {
|
|
72
72
|
try {
|
|
73
73
|
const routeResponse = await route[methodName]({ container: this.#container, request: req, response: res });
|
|
74
|
+
if (routeResponse instanceof RedirectResponse) return res.redirect(routeResponse.url);
|
|
74
75
|
|
|
75
76
|
// Check if response is a buffer (file download)
|
|
76
77
|
if (Buffer.isBuffer(routeResponse)) {
|
|
@@ -126,7 +127,6 @@ module.exports = class Express extends Service {
|
|
|
126
127
|
async (req, res) => {
|
|
127
128
|
try {
|
|
128
129
|
const routeResponse = await route[methodName]({ container: this.#container, request: req, response: res });
|
|
129
|
-
|
|
130
130
|
if (routeResponse instanceof RedirectResponse) return res.redirect(routeResponse.url);
|
|
131
131
|
|
|
132
132
|
// Check if response is a buffer (file download)
|
package/.claude/settings.json
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "zyket",
|
|
3
|
-
"owner": {
|
|
4
|
-
"name": "PemaK"
|
|
5
|
-
},
|
|
6
|
-
"metadata": {
|
|
7
|
-
"description": "A collection of Claude plugins for building Zyket apps",
|
|
8
|
-
"version": "1.0.8"
|
|
9
|
-
},
|
|
10
|
-
"plugins": [
|
|
11
|
-
{
|
|
12
|
-
"name": "zyket",
|
|
13
|
-
"source": "./claude-plugin"
|
|
14
|
-
}
|
|
15
|
-
]
|
|
16
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# Create a Zyket Event
|
|
2
|
-
|
|
3
|
-
Create a new event file in the Zyket project.
|
|
4
|
-
|
|
5
|
-
## Instructions
|
|
6
|
-
|
|
7
|
-
Events live in `src/events/`. The filename (without `.js`) is the event name used in `emit()`.
|
|
8
|
-
|
|
9
|
-
### Template
|
|
10
|
-
|
|
11
|
-
```js
|
|
12
|
-
const { Event } = require("zyket");
|
|
13
|
-
|
|
14
|
-
module.exports = class $EventName$Event extends Event {
|
|
15
|
-
async handle({ container, payload }) {
|
|
16
|
-
container.get("logger").info("$EventName$ event fired", payload);
|
|
17
|
-
// Your event logic here
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
### Steps:
|
|
23
|
-
1. Create `src/events/$event-name$.js`.
|
|
24
|
-
2. Implement the handler logic based on the user's description.
|
|
25
|
-
3. Show the user how to emit it:
|
|
26
|
-
```js
|
|
27
|
-
container.get("events").emitAsync("$event-name$", { ...payload });
|
|
28
|
-
```
|
|
29
|
-
4. Remind the user to set `DISABLE_EVENTS=false` in `.env`.
|