@shaferllc/keel 0.83.1 → 0.83.3
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/README.md +4 -1
- package/dist/gates/index.d.ts +10 -0
- package/dist/gates/index.js +9 -0
- package/dist/gates/models.d.ts +42 -0
- package/dist/gates/models.js +76 -0
- package/dist/gates/provider.d.ts +10 -0
- package/dist/gates/provider.js +13 -0
- package/dist/hosting/cloudflare.d.ts +43 -0
- package/dist/hosting/cloudflare.js +66 -0
- package/dist/hosting/dump.d.ts +7 -0
- package/dist/hosting/dump.js +58 -0
- package/dist/hosting/hostname.d.ts +7 -0
- package/dist/hosting/hostname.js +25 -0
- package/dist/hosting/index.d.ts +14 -0
- package/dist/hosting/index.js +12 -0
- package/dist/hosting/secrets.d.ts +15 -0
- package/dist/hosting/secrets.js +27 -0
- package/docs/ai-manifest.json +20 -13
- package/docs/billing.md +40 -0
- package/docs/changelog.md +31 -0
- package/docs/cors.md +28 -0
- package/docs/examples/billing.ts +128 -0
- package/docs/examples/cors.ts +29 -0
- package/docs/examples/gates.ts +30 -0
- package/docs/examples/hono.ts +29 -0
- package/docs/examples/openapi.ts +35 -0
- package/docs/examples/orm.ts +30 -0
- package/docs/examples/packages.ts +26 -0
- package/docs/examples/query-builder.ts +118 -0
- package/docs/examples/security.ts +31 -0
- package/docs/examples/social-auth.ts +76 -0
- package/docs/examples/starter-kits.ts +14 -0
- package/docs/examples/watch.ts +10 -0
- package/docs/gates.md +75 -0
- package/docs/orm.md +39 -0
- package/docs/starter-kits.md +14 -0
- package/docs/watch.md +1 -1
- package/llms-full.txt +203 -1
- package/llms.txt +14 -1
- package/package.json +9 -1
package/docs/gates.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Gates
|
|
2
|
+
|
|
3
|
+
Keel Gates is a **signup gate** for private alpha / waitlist apps: an email
|
|
4
|
+
allowlist, invite codes with use limits and expiry, and a single check that
|
|
5
|
+
answers "may this person register?". It ships as `@shaferllc/keel/gates`.
|
|
6
|
+
|
|
7
|
+
This is **not** authorization (`can` / policies in [authorization](./authorization.md))
|
|
8
|
+
and **not** team invitations ([teams](./teams.md)). Those answer different
|
|
9
|
+
questions. Gates answers only: *is this email allowed to create an account?*
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
// bootstrap/providers.ts
|
|
15
|
+
import { GatesServiceProvider } from "@shaferllc/keel/gates";
|
|
16
|
+
|
|
17
|
+
export const providers = [AppServiceProvider, GatesServiceProvider];
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Then migrate — the provider contributes `invite_codes` and `email_allowlist`
|
|
21
|
+
tables (`CREATE TABLE IF NOT EXISTS`, so existing apps stay safe):
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
keel migrate
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Checking registration
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { canRegister, redeemInvite } from "@shaferllc/keel/gates";
|
|
31
|
+
|
|
32
|
+
const gate = await canRegister(email, inviteCode);
|
|
33
|
+
if (!gate.ok) {
|
|
34
|
+
return json({ error: gate.reason }, 403);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// …create the user…
|
|
38
|
+
|
|
39
|
+
if (gate.via === "code" && gate.invite) {
|
|
40
|
+
await redeemInvite(gate.invite); // increments uses
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`canRegister` returns:
|
|
45
|
+
|
|
46
|
+
| Result | Meaning |
|
|
47
|
+
|--------|---------|
|
|
48
|
+
| `{ ok: true, via: "allowlist" }` | Email is on `email_allowlist` |
|
|
49
|
+
| `{ ok: true, via: "code", invite }` | Valid invite code (not expired, uses left) |
|
|
50
|
+
| `{ ok: false, reason }` | Rejected — show `reason` to the user |
|
|
51
|
+
|
|
52
|
+
Allowlist wins over codes: if the email is allowlisted, the code is ignored.
|
|
53
|
+
|
|
54
|
+
## Managing codes and allowlist
|
|
55
|
+
|
|
56
|
+
The models are ordinary Keel models — create rows from an admin UI or a seeder:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { InviteCode, EmailAllowlist } from "@shaferllc/keel/gates";
|
|
60
|
+
|
|
61
|
+
await InviteCode.create({
|
|
62
|
+
code: "ALPHA-42",
|
|
63
|
+
max_uses: 10,
|
|
64
|
+
uses: 0,
|
|
65
|
+
expires_at: null,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
await EmailAllowlist.create({ email: "ada@example.com" });
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Related
|
|
72
|
+
|
|
73
|
+
- [Accounts](./accounts.md) — register / login flows that call `canRegister` first
|
|
74
|
+
- [Teams](./teams.md) — invitations *into* a team, after the user already exists
|
|
75
|
+
- [Authorization](./authorization.md) — ability checks once they're signed in
|
package/docs/orm.md
CHANGED
|
@@ -55,3 +55,42 @@ The ORM is deliberately small — enough for CRUD, relationships, and the common
|
|
|
55
55
|
query shapes without an ORM dependency. For a gnarly one-off report, reach for
|
|
56
56
|
the [query builder](./query-builder.md) or a raw `connection().select(sql)`; the
|
|
57
57
|
model layer never gets in the way.
|
|
58
|
+
|
|
59
|
+
## A worked example
|
|
60
|
+
|
|
61
|
+
A blog with authors and posts — enough to see CRUD, a relation, and eager loading
|
|
62
|
+
together:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import { Model } from "@shaferllc/keel/core";
|
|
66
|
+
|
|
67
|
+
class Post extends Model {
|
|
68
|
+
static table = "posts";
|
|
69
|
+
static fillable = ["title", "body"];
|
|
70
|
+
declare id: number;
|
|
71
|
+
declare title: string;
|
|
72
|
+
declare user_id: number;
|
|
73
|
+
|
|
74
|
+
author() { return this.belongsTo(User); }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
class User extends Model {
|
|
78
|
+
static table = "users";
|
|
79
|
+
declare id: number;
|
|
80
|
+
declare email: string;
|
|
81
|
+
|
|
82
|
+
posts() { return this.hasMany(Post); }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const ada = await User.create({ email: "ada@example.com" });
|
|
86
|
+
await ada.posts().create({ title: "Notes on engines", body: "…" });
|
|
87
|
+
|
|
88
|
+
const withPosts = await User.with("posts").where("id", ada.id).first();
|
|
89
|
+
for (const post of (withPosts as User & { posts: Post[] }).posts) {
|
|
90
|
+
console.log(post.title);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
For the full surface — casts, soft deletes, scopes, polymorphic relations —
|
|
95
|
+
see [Models](./models.md).
|
|
96
|
+
|
package/docs/starter-kits.md
CHANGED
|
@@ -14,6 +14,20 @@ to finish.
|
|
|
14
14
|
| `app` *(default)* | Full-stack: views, sessions, register/login, password reset, two-factor. |
|
|
15
15
|
| `saas` | `app` plus teams, roles, invitations, billing, and multi-tenancy. |
|
|
16
16
|
|
|
17
|
+
## Pick a kit
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm create keeljs@latest my-app # app (default)
|
|
21
|
+
npm create keeljs@latest my-api -- --preset api
|
|
22
|
+
npm create keeljs@latest my-saas -- --preset saas
|
|
23
|
+
npm create keeljs@latest bare -- --preset minimal
|
|
24
|
+
cd my-app && npm install && npm run dev
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Then open `http://localhost:3000`. The SaaS kit already has a team switcher,
|
|
28
|
+
invites, and a billing stub wired through [teams](./teams.md) and
|
|
29
|
+
[billing](./billing.md) — start by editing `app/Models` and `routes/web.ts`.
|
|
30
|
+
|
|
17
31
|
## Every database, Cloudflare first
|
|
18
32
|
|
|
19
33
|
Each kit ships with all four drivers wired. Switching is `DB_CONNECTION` and nothing
|
package/docs/watch.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Watch
|
|
2
2
|
|
|
3
|
-
Keel Watch is a debug dashboard
|
|
3
|
+
Keel Watch is a debug dashboard for Keel apps. It records the requests,
|
|
4
4
|
queries, exceptions, logs, jobs, mail, notifications, cache lookups, events, and
|
|
5
5
|
scheduled tasks flowing through your app, and shows them in a single-page UI at
|
|
6
6
|
`/watch`, with every request linked to the queries and logs it produced.
|
package/llms-full.txt
CHANGED
|
@@ -5764,6 +5764,46 @@ resolveBillableUsing(async (customerId) => {
|
|
|
5764
5764
|
});
|
|
5765
5765
|
```
|
|
5766
5766
|
|
|
5767
|
+
## A complete flow
|
|
5768
|
+
|
|
5769
|
+
From "user signs up" to "they're subscribed", with the fake gateway for tests:
|
|
5770
|
+
|
|
5771
|
+
```ts
|
|
5772
|
+
import { Model } from "@shaferllc/keel/core";
|
|
5773
|
+
import {
|
|
5774
|
+
Billable,
|
|
5775
|
+
BillingManager,
|
|
5776
|
+
FakeGateway,
|
|
5777
|
+
setBilling,
|
|
5778
|
+
} from "@shaferllc/keel/billing";
|
|
5779
|
+
|
|
5780
|
+
class User extends Billable(Model) {
|
|
5781
|
+
static table = "users";
|
|
5782
|
+
declare email: string;
|
|
5783
|
+
}
|
|
5784
|
+
|
|
5785
|
+
// In a test bootstrap:
|
|
5786
|
+
const fake = new FakeGateway();
|
|
5787
|
+
const manager = new BillingManager({
|
|
5788
|
+
default: "fake",
|
|
5789
|
+
currency: "usd",
|
|
5790
|
+
billableModel: "User",
|
|
5791
|
+
webhook: { path: "billing/webhook" },
|
|
5792
|
+
gateways: { stripe: { key: "", webhookSecret: "" }, paddle: { key: "", webhookSecret: "" }, fake: {} },
|
|
5793
|
+
});
|
|
5794
|
+
manager.register("fake", () => fake);
|
|
5795
|
+
setBilling(manager);
|
|
5796
|
+
|
|
5797
|
+
const user = await User.create({ email: "ada@example.com" });
|
|
5798
|
+
await user.newSubscription("default", "price_pro").trialDays(14).create();
|
|
5799
|
+
|
|
5800
|
+
await user.subscribed(); // true
|
|
5801
|
+
fake.calls.some((c) => c.method === "createSubscription"); // true
|
|
5802
|
+
```
|
|
5803
|
+
|
|
5804
|
+
In production you skip the fake manager — `BillingServiceProvider` wires the
|
|
5805
|
+
real gateway from `config/billing.ts` and `.env`.
|
|
5806
|
+
|
|
5767
5807
|
## Gateway differences
|
|
5768
5808
|
|
|
5769
5809
|
| Concern | Stripe | Paddle |
|
|
@@ -7611,6 +7651,34 @@ router.group(() => { /* … */ }).use(cors({ origin: ["https://app.example.com"]
|
|
|
7611
7651
|
With no options, `cors()` reflects the caller's origin — convenient in
|
|
7612
7652
|
development. **Lock it down in production** with an explicit allowlist.
|
|
7613
7653
|
|
|
7654
|
+
## A production API group
|
|
7655
|
+
|
|
7656
|
+
Typical setup for a JSON API served from `api.example.com` and called from a
|
|
7657
|
+
SPA on `app.example.com`:
|
|
7658
|
+
|
|
7659
|
+
```ts
|
|
7660
|
+
// app/Http/Kernel.ts
|
|
7661
|
+
import { cors } from "@shaferllc/keel/core";
|
|
7662
|
+
|
|
7663
|
+
this.use(
|
|
7664
|
+
cors({
|
|
7665
|
+
origin: ["https://app.example.com"],
|
|
7666
|
+
credentials: true, // cookies / Authorization
|
|
7667
|
+
exposeHeaders: ["X-Request-Id"],
|
|
7668
|
+
}),
|
|
7669
|
+
);
|
|
7670
|
+
```
|
|
7671
|
+
|
|
7672
|
+
During local development, allow any localhost port with a predicate:
|
|
7673
|
+
|
|
7674
|
+
```ts
|
|
7675
|
+
cors({
|
|
7676
|
+
origin: (origin) =>
|
|
7677
|
+
origin.startsWith("http://localhost:") || origin === "https://app.example.com",
|
|
7678
|
+
credentials: true,
|
|
7679
|
+
});
|
|
7680
|
+
```
|
|
7681
|
+
|
|
7614
7682
|
## Options
|
|
7615
7683
|
|
|
7616
7684
|
```ts
|
|
@@ -9361,6 +9429,88 @@ definition function.
|
|
|
9361
9429
|
|
|
9362
9430
|
|
|
9363
9431
|
|
|
9432
|
+
---
|
|
9433
|
+
|
|
9434
|
+
<!-- source: docs/gates.md -->
|
|
9435
|
+
|
|
9436
|
+
# Gates
|
|
9437
|
+
|
|
9438
|
+
Keel Gates is a **signup gate** for private alpha / waitlist apps: an email
|
|
9439
|
+
allowlist, invite codes with use limits and expiry, and a single check that
|
|
9440
|
+
answers "may this person register?". It ships as `@shaferllc/keel/gates`.
|
|
9441
|
+
|
|
9442
|
+
This is **not** authorization (`can` / policies in [authorization](./authorization.md))
|
|
9443
|
+
and **not** team invitations ([teams](./teams.md)). Those answer different
|
|
9444
|
+
questions. Gates answers only: *is this email allowed to create an account?*
|
|
9445
|
+
|
|
9446
|
+
## Install
|
|
9447
|
+
|
|
9448
|
+
```ts
|
|
9449
|
+
// bootstrap/providers.ts
|
|
9450
|
+
import { GatesServiceProvider } from "@shaferllc/keel/gates";
|
|
9451
|
+
|
|
9452
|
+
export const providers = [AppServiceProvider, GatesServiceProvider];
|
|
9453
|
+
```
|
|
9454
|
+
|
|
9455
|
+
Then migrate — the provider contributes `invite_codes` and `email_allowlist`
|
|
9456
|
+
tables (`CREATE TABLE IF NOT EXISTS`, so existing apps stay safe):
|
|
9457
|
+
|
|
9458
|
+
```bash
|
|
9459
|
+
keel migrate
|
|
9460
|
+
```
|
|
9461
|
+
|
|
9462
|
+
## Checking registration
|
|
9463
|
+
|
|
9464
|
+
```ts
|
|
9465
|
+
import { canRegister, redeemInvite } from "@shaferllc/keel/gates";
|
|
9466
|
+
|
|
9467
|
+
const gate = await canRegister(email, inviteCode);
|
|
9468
|
+
if (!gate.ok) {
|
|
9469
|
+
return json({ error: gate.reason }, 403);
|
|
9470
|
+
}
|
|
9471
|
+
|
|
9472
|
+
// …create the user…
|
|
9473
|
+
|
|
9474
|
+
if (gate.via === "code" && gate.invite) {
|
|
9475
|
+
await redeemInvite(gate.invite); // increments uses
|
|
9476
|
+
}
|
|
9477
|
+
```
|
|
9478
|
+
|
|
9479
|
+
`canRegister` returns:
|
|
9480
|
+
|
|
9481
|
+
| Result | Meaning |
|
|
9482
|
+
|--------|---------|
|
|
9483
|
+
| `{ ok: true, via: "allowlist" }` | Email is on `email_allowlist` |
|
|
9484
|
+
| `{ ok: true, via: "code", invite }` | Valid invite code (not expired, uses left) |
|
|
9485
|
+
| `{ ok: false, reason }` | Rejected — show `reason` to the user |
|
|
9486
|
+
|
|
9487
|
+
Allowlist wins over codes: if the email is allowlisted, the code is ignored.
|
|
9488
|
+
|
|
9489
|
+
## Managing codes and allowlist
|
|
9490
|
+
|
|
9491
|
+
The models are ordinary Keel models — create rows from an admin UI or a seeder:
|
|
9492
|
+
|
|
9493
|
+
```ts
|
|
9494
|
+
import { InviteCode, EmailAllowlist } from "@shaferllc/keel/gates";
|
|
9495
|
+
|
|
9496
|
+
await InviteCode.create({
|
|
9497
|
+
code: "ALPHA-42",
|
|
9498
|
+
max_uses: 10,
|
|
9499
|
+
uses: 0,
|
|
9500
|
+
expires_at: null,
|
|
9501
|
+
});
|
|
9502
|
+
|
|
9503
|
+
await EmailAllowlist.create({ email: "ada@example.com" });
|
|
9504
|
+
```
|
|
9505
|
+
|
|
9506
|
+
## Related
|
|
9507
|
+
|
|
9508
|
+
- [Accounts](./accounts.md) — register / login flows that call `canRegister` first
|
|
9509
|
+
- [Teams](./teams.md) — invitations *into* a team, after the user already exists
|
|
9510
|
+
- [Authorization](./authorization.md) — ability checks once they're signed in
|
|
9511
|
+
|
|
9512
|
+
|
|
9513
|
+
|
|
9364
9514
|
---
|
|
9365
9515
|
|
|
9366
9516
|
<!-- source: docs/hashing.md -->
|
|
@@ -14934,6 +15084,44 @@ query shapes without an ORM dependency. For a gnarly one-off report, reach for
|
|
|
14934
15084
|
the [query builder](./query-builder.md) or a raw `connection().select(sql)`; the
|
|
14935
15085
|
model layer never gets in the way.
|
|
14936
15086
|
|
|
15087
|
+
## A worked example
|
|
15088
|
+
|
|
15089
|
+
A blog with authors and posts — enough to see CRUD, a relation, and eager loading
|
|
15090
|
+
together:
|
|
15091
|
+
|
|
15092
|
+
```ts
|
|
15093
|
+
import { Model } from "@shaferllc/keel/core";
|
|
15094
|
+
|
|
15095
|
+
class Post extends Model {
|
|
15096
|
+
static table = "posts";
|
|
15097
|
+
static fillable = ["title", "body"];
|
|
15098
|
+
declare id: number;
|
|
15099
|
+
declare title: string;
|
|
15100
|
+
declare user_id: number;
|
|
15101
|
+
|
|
15102
|
+
author() { return this.belongsTo(User); }
|
|
15103
|
+
}
|
|
15104
|
+
|
|
15105
|
+
class User extends Model {
|
|
15106
|
+
static table = "users";
|
|
15107
|
+
declare id: number;
|
|
15108
|
+
declare email: string;
|
|
15109
|
+
|
|
15110
|
+
posts() { return this.hasMany(Post); }
|
|
15111
|
+
}
|
|
15112
|
+
|
|
15113
|
+
const ada = await User.create({ email: "ada@example.com" });
|
|
15114
|
+
await ada.posts().create({ title: "Notes on engines", body: "…" });
|
|
15115
|
+
|
|
15116
|
+
const withPosts = await User.with("posts").where("id", ada.id).first();
|
|
15117
|
+
for (const post of (withPosts as User & { posts: Post[] }).posts) {
|
|
15118
|
+
console.log(post.title);
|
|
15119
|
+
}
|
|
15120
|
+
```
|
|
15121
|
+
|
|
15122
|
+
For the full surface — casts, soft deletes, scopes, polymorphic relations —
|
|
15123
|
+
see [Models](./models.md).
|
|
15124
|
+
|
|
14937
15125
|
|
|
14938
15126
|
|
|
14939
15127
|
---
|
|
@@ -17630,6 +17818,20 @@ to finish.
|
|
|
17630
17818
|
| `app` *(default)* | Full-stack: views, sessions, register/login, password reset, two-factor. |
|
|
17631
17819
|
| `saas` | `app` plus teams, roles, invitations, billing, and multi-tenancy. |
|
|
17632
17820
|
|
|
17821
|
+
## Pick a kit
|
|
17822
|
+
|
|
17823
|
+
```bash
|
|
17824
|
+
npm create keeljs@latest my-app # app (default)
|
|
17825
|
+
npm create keeljs@latest my-api -- --preset api
|
|
17826
|
+
npm create keeljs@latest my-saas -- --preset saas
|
|
17827
|
+
npm create keeljs@latest bare -- --preset minimal
|
|
17828
|
+
cd my-app && npm install && npm run dev
|
|
17829
|
+
```
|
|
17830
|
+
|
|
17831
|
+
Then open `http://localhost:3000`. The SaaS kit already has a team switcher,
|
|
17832
|
+
invites, and a billing stub wired through [teams](./teams.md) and
|
|
17833
|
+
[billing](./billing.md) — start by editing `app/Models` and `routes/web.ts`.
|
|
17834
|
+
|
|
17633
17835
|
## Every database, Cloudflare first
|
|
17634
17836
|
|
|
17635
17837
|
Each kit ships with all four drivers wired. Switching is `DB_CONNECTION` and nothing
|
|
@@ -21244,7 +21446,7 @@ Vite's `manifest.json`, as produced by the build. You rarely touch it directly
|
|
|
21244
21446
|
|
|
21245
21447
|
# Watch
|
|
21246
21448
|
|
|
21247
|
-
Keel Watch is a debug dashboard
|
|
21449
|
+
Keel Watch is a debug dashboard for Keel apps. It records the requests,
|
|
21248
21450
|
queries, exceptions, logs, jobs, mail, notifications, cache lookups, events, and
|
|
21249
21451
|
scheduled tasks flowing through your app, and shows them in a single-page UI at
|
|
21250
21452
|
`/watch`, with every request linked to the queries and logs it produced.
|
package/llms.txt
CHANGED
|
@@ -30,6 +30,7 @@ Userland imports everything from `@shaferllc/keel/core`.
|
|
|
30
30
|
- [Errors & Exceptions](https://github.com/shaferllc/keel/blob/main/docs/errors.md): Throw an exception anywhere — a handler, middleware, or a service deep in the container — and Keel's HTTP kernel turns it into the right response.
|
|
31
31
|
- [Events](https://github.com/shaferllc/keel/blob/main/docs/events.md): A tiny event emitter for decoupling — fire an event in one place, handle it in another.
|
|
32
32
|
- [Factories & Seeders](https://github.com/shaferllc/keel/blob/main/docs/factories.md): Populate the database with realistic fixtures for tests and demos.
|
|
33
|
+
- [Gates](https://github.com/shaferllc/keel/blob/main/docs/gates.md): Keel Gates is a signup gate for private alpha / waitlist apps: an email allowlist, invite codes with use limits and expiry, and a single check that answers "may this person register?".
|
|
33
34
|
- [Getting Started](https://github.com/shaferllc/keel/blob/main/docs/getting-started.md): Keel is a house framework for Node.js — a small, legible MVC layer over Hono.
|
|
34
35
|
- [Hashing & Encryption](https://github.com/shaferllc/keel/blob/main/docs/hashing.md): Password hashing and value encryption, both built on the Web Crypto API — so they run identically on Node and the edge, with no native bindings (no bcrypt to compile).
|
|
35
36
|
- [Health Checks](https://github.com/shaferllc/keel/blob/main/docs/health.md): Two endpoints, answering the two questions an orchestrator — Kubernetes, Fly, Railway, a load balancer — actually asks:
|
|
@@ -72,7 +73,7 @@ Userland imports everything from `@shaferllc/keel/core`.
|
|
|
72
73
|
- [Validation](https://github.com/shaferllc/keel/blob/main/docs/validation.md): validate() parses request input against a schema and returns typed data.
|
|
73
74
|
- [Views](https://github.com/shaferllc/keel/blob/main/docs/views.md): Keel renders HTML with Hono JSX — type-safe components that run identically on Node and on Cloudflare Workers (no filesystem templating, so it ports anywhere).
|
|
74
75
|
- [Vite](https://github.com/shaferllc/keel/blob/main/docs/vite.md): Wire a modern frontend build — bundling, hashed filenames, hot module reload — to Keel's server-rendered HTML, the way modern full-stack frameworks do.
|
|
75
|
-
- [Watch](https://github.com/shaferllc/keel/blob/main/docs/watch.md): Keel Watch is a debug dashboard
|
|
76
|
+
- [Watch](https://github.com/shaferllc/keel/blob/main/docs/watch.md): Keel Watch is a debug dashboard for Keel apps.
|
|
76
77
|
|
|
77
78
|
## Examples
|
|
78
79
|
|
|
@@ -82,6 +83,7 @@ Every topic has a runnable, type-checked example:
|
|
|
82
83
|
- [API Resources example](https://github.com/shaferllc/keel/blob/main/docs/examples/api-resources.ts)
|
|
83
84
|
- [Authentication example](https://github.com/shaferllc/keel/blob/main/docs/examples/authentication.ts)
|
|
84
85
|
- [Authorization example](https://github.com/shaferllc/keel/blob/main/docs/examples/authorization.ts)
|
|
86
|
+
- [Billing example](https://github.com/shaferllc/keel/blob/main/docs/examples/billing.ts)
|
|
85
87
|
- [Broadcasting example](https://github.com/shaferllc/keel/blob/main/docs/examples/broadcasting.ts)
|
|
86
88
|
- [Service Broker example](https://github.com/shaferllc/keel/blob/main/docs/examples/broker.ts)
|
|
87
89
|
- [Cache example](https://github.com/shaferllc/keel/blob/main/docs/examples/cache.ts)
|
|
@@ -89,15 +91,18 @@ Every topic has a runnable, type-checked example:
|
|
|
89
91
|
- [The Console example](https://github.com/shaferllc/keel/blob/main/docs/examples/console.ts)
|
|
90
92
|
- [The Service Container example](https://github.com/shaferllc/keel/blob/main/docs/examples/container.ts)
|
|
91
93
|
- [Controllers example](https://github.com/shaferllc/keel/blob/main/docs/examples/controllers.ts)
|
|
94
|
+
- [CORS example](https://github.com/shaferllc/keel/blob/main/docs/examples/cors.ts)
|
|
92
95
|
- [Database example](https://github.com/shaferllc/keel/blob/main/docs/examples/database.ts)
|
|
93
96
|
- [Debugging example](https://github.com/shaferllc/keel/blob/main/docs/examples/debugging.ts)
|
|
94
97
|
- [Request Decorators example](https://github.com/shaferllc/keel/blob/main/docs/examples/decorators.ts)
|
|
95
98
|
- [Errors & Exceptions example](https://github.com/shaferllc/keel/blob/main/docs/examples/errors.ts)
|
|
96
99
|
- [Events example](https://github.com/shaferllc/keel/blob/main/docs/examples/events.ts)
|
|
97
100
|
- [Factories & Seeders example](https://github.com/shaferllc/keel/blob/main/docs/examples/factories.ts)
|
|
101
|
+
- [Gates example](https://github.com/shaferllc/keel/blob/main/docs/examples/gates.ts)
|
|
98
102
|
- [Hashing & Encryption example](https://github.com/shaferllc/keel/blob/main/docs/examples/hashing.ts)
|
|
99
103
|
- [Health Checks example](https://github.com/shaferllc/keel/blob/main/docs/examples/health.ts)
|
|
100
104
|
- [Helpers example](https://github.com/shaferllc/keel/blob/main/docs/examples/helpers.ts)
|
|
105
|
+
- [Built on Hono example](https://github.com/shaferllc/keel/blob/main/docs/examples/hono.ts)
|
|
101
106
|
- [Lifecycle Hooks example](https://github.com/shaferllc/keel/blob/main/docs/examples/hooks.ts)
|
|
102
107
|
- [Internationalization example](https://github.com/shaferllc/keel/blob/main/docs/examples/i18n.ts)
|
|
103
108
|
- [Inertia example](https://github.com/shaferllc/keel/blob/main/docs/examples/inertia.ts)
|
|
@@ -108,15 +113,22 @@ Every topic has a runnable, type-checked example:
|
|
|
108
113
|
- [Migrations example](https://github.com/shaferllc/keel/blob/main/docs/examples/migrations.ts)
|
|
109
114
|
- [Models example](https://github.com/shaferllc/keel/blob/main/docs/examples/models.ts)
|
|
110
115
|
- [Notifications example](https://github.com/shaferllc/keel/blob/main/docs/examples/notification.ts)
|
|
116
|
+
- [OpenAPI example](https://github.com/shaferllc/keel/blob/main/docs/examples/openapi.ts)
|
|
117
|
+
- [ORM example](https://github.com/shaferllc/keel/blob/main/docs/examples/orm.ts)
|
|
118
|
+
- [Packages example](https://github.com/shaferllc/keel/blob/main/docs/examples/packages.ts)
|
|
111
119
|
- [Pages example](https://github.com/shaferllc/keel/blob/main/docs/examples/pages.ts)
|
|
112
120
|
- [Service Providers example](https://github.com/shaferllc/keel/blob/main/docs/examples/providers.ts)
|
|
121
|
+
- [Query Builder example](https://github.com/shaferllc/keel/blob/main/docs/examples/query-builder.ts)
|
|
113
122
|
- [Queues & Jobs example](https://github.com/shaferllc/keel/blob/main/docs/examples/queues.ts)
|
|
114
123
|
- [Rate Limiting example](https://github.com/shaferllc/keel/blob/main/docs/examples/rate-limiting.ts)
|
|
115
124
|
- [Redis example](https://github.com/shaferllc/keel/blob/main/docs/examples/redis.ts)
|
|
116
125
|
- [Request & Response example](https://github.com/shaferllc/keel/blob/main/docs/examples/request-response.ts)
|
|
117
126
|
- [Routing example](https://github.com/shaferllc/keel/blob/main/docs/examples/routing.ts)
|
|
118
127
|
- [Task Scheduling example](https://github.com/shaferllc/keel/blob/main/docs/examples/scheduling.ts)
|
|
128
|
+
- [Securing SSR apps example](https://github.com/shaferllc/keel/blob/main/docs/examples/security.ts)
|
|
119
129
|
- [Sessions example](https://github.com/shaferllc/keel/blob/main/docs/examples/sessions.ts)
|
|
130
|
+
- [Social authentication example](https://github.com/shaferllc/keel/blob/main/docs/examples/social-auth.ts)
|
|
131
|
+
- [Starter kits example](https://github.com/shaferllc/keel/blob/main/docs/examples/starter-kits.ts)
|
|
120
132
|
- [Static Files example](https://github.com/shaferllc/keel/blob/main/docs/examples/static-files.ts)
|
|
121
133
|
- [Storage example](https://github.com/shaferllc/keel/blob/main/docs/examples/storage.ts)
|
|
122
134
|
- [Teams example](https://github.com/shaferllc/keel/blob/main/docs/examples/teams.ts)
|
|
@@ -128,6 +140,7 @@ Every topic has a runnable, type-checked example:
|
|
|
128
140
|
- [Validation example](https://github.com/shaferllc/keel/blob/main/docs/examples/validation.ts)
|
|
129
141
|
- [Views example](https://github.com/shaferllc/keel/blob/main/docs/examples/views.tsx)
|
|
130
142
|
- [Vite example](https://github.com/shaferllc/keel/blob/main/docs/examples/vite.ts)
|
|
143
|
+
- [Watch example](https://github.com/shaferllc/keel/blob/main/docs/examples/watch.ts)
|
|
131
144
|
|
|
132
145
|
## Optional
|
|
133
146
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shaferllc/keel",
|
|
3
|
-
"version": "0.83.
|
|
3
|
+
"version": "0.83.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The house framework for Node.js — a service container, providers, routing, JSX views, and a code-generating console.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -77,6 +77,14 @@
|
|
|
77
77
|
"types": "./dist/billing/index.d.ts",
|
|
78
78
|
"import": "./dist/billing/index.js"
|
|
79
79
|
},
|
|
80
|
+
"./gates": {
|
|
81
|
+
"types": "./dist/gates/index.d.ts",
|
|
82
|
+
"import": "./dist/gates/index.js"
|
|
83
|
+
},
|
|
84
|
+
"./hosting": {
|
|
85
|
+
"types": "./dist/hosting/index.d.ts",
|
|
86
|
+
"import": "./dist/hosting/index.js"
|
|
87
|
+
},
|
|
80
88
|
"./cli": {
|
|
81
89
|
"types": "./dist/core/cli/index.d.ts",
|
|
82
90
|
"import": "./dist/core/cli/index.js"
|