@shaferllc/keel 0.82.0 → 0.83.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.
Files changed (150) hide show
  1. package/README.md +2 -2
  2. package/dist/billing/billable.d.ts +2 -3
  3. package/dist/billing/billable.js +2 -3
  4. package/dist/billing/billing.config.stub +1 -1
  5. package/dist/billing/builder.d.ts +2 -2
  6. package/dist/billing/builder.js +2 -2
  7. package/dist/billing/provider.d.ts +1 -1
  8. package/dist/billing/provider.js +2 -2
  9. package/dist/billing/subscription-item.d.ts +0 -1
  10. package/dist/billing/subscription-item.js +0 -1
  11. package/dist/core/decorators.d.ts +5 -7
  12. package/dist/core/decorators.js +5 -7
  13. package/dist/core/exceptions.d.ts +2 -3
  14. package/dist/core/exceptions.js +2 -3
  15. package/dist/core/model-query.d.ts +1 -1
  16. package/dist/core/model-query.js +1 -1
  17. package/dist/core/request-logger.d.ts +2 -2
  18. package/dist/core/request-logger.js +2 -2
  19. package/dist/core/request.js +1 -1
  20. package/dist/core/testing.d.ts +3 -3
  21. package/dist/core/testing.js +3 -3
  22. package/dist/db/d1-http.d.ts +34 -0
  23. package/dist/db/d1-http.js +61 -0
  24. package/dist/db/libsql.d.ts +13 -3
  25. package/dist/teams/models.js +51 -5
  26. package/docs/ai-manifest.json +23 -2
  27. package/docs/billing.md +5 -6
  28. package/docs/changelog.md +106 -21
  29. package/docs/database.md +5 -522
  30. package/docs/decorators.md +2 -6
  31. package/docs/errors.md +1 -1
  32. package/docs/hooks.md +1 -3
  33. package/docs/logger.md +2 -2
  34. package/docs/models.md +5 -2
  35. package/docs/orm.md +57 -0
  36. package/docs/packages.md +3 -3
  37. package/docs/providers.md +6 -6
  38. package/docs/query-builder.md +533 -0
  39. package/docs/request-response.md +2 -2
  40. package/docs/starter-kits.md +88 -0
  41. package/docs/testing.md +1 -2
  42. package/docs/validation.md +1 -2
  43. package/llms-full.txt +5301 -5126
  44. package/llms.txt +4 -1
  45. package/package.json +7 -2
  46. package/templates/api/.env.example +12 -0
  47. package/templates/api/app/Controllers/PostController.ts +37 -0
  48. package/templates/api/app/Http/Kernel.ts +13 -0
  49. package/templates/api/app/Http/Middleware/requestLogger.ts +8 -0
  50. package/templates/api/app/Models/Post.ts +12 -0
  51. package/templates/api/app/Providers/AppServiceProvider.ts +8 -0
  52. package/templates/api/app/Providers/DatabaseServiceProvider.ts +52 -0
  53. package/templates/api/bin/keel.ts +15 -0
  54. package/templates/api/bootstrap/app.ts +24 -0
  55. package/templates/api/bootstrap/providers.edge.ts +14 -0
  56. package/templates/api/bootstrap/providers.ts +7 -0
  57. package/templates/api/config/app.ts +10 -0
  58. package/templates/api/config/database.ts +42 -0
  59. package/templates/api/database/migrations/0001_create_posts.ts +20 -0
  60. package/templates/api/package.json +30 -0
  61. package/templates/api/routes/web.ts +12 -0
  62. package/templates/api/tests/posts.test.ts +30 -0
  63. package/templates/api/tsconfig.json +16 -0
  64. package/templates/api/worker.ts +33 -0
  65. package/templates/api/wrangler.jsonc +22 -0
  66. package/templates/app/.env.example +12 -0
  67. package/templates/app/app/Controllers/AuthController.ts +117 -0
  68. package/templates/app/app/Controllers/DashboardController.ts +37 -0
  69. package/templates/app/app/Controllers/HomeController.ts +10 -0
  70. package/templates/app/app/Http/Kernel.ts +21 -0
  71. package/templates/app/app/Http/Middleware/requestLogger.ts +8 -0
  72. package/templates/app/app/Models/User.ts +15 -0
  73. package/templates/app/app/Providers/AppServiceProvider.ts +12 -0
  74. package/templates/app/app/Providers/DatabaseServiceProvider.ts +52 -0
  75. package/templates/app/bin/keel.ts +15 -0
  76. package/templates/app/bootstrap/app.ts +24 -0
  77. package/templates/app/bootstrap/providers.edge.ts +15 -0
  78. package/templates/app/bootstrap/providers.ts +18 -0
  79. package/templates/app/config/app.ts +10 -0
  80. package/templates/app/config/database.ts +42 -0
  81. package/templates/app/database/migrations/0001_create_users.ts +21 -0
  82. package/templates/app/package.json +35 -0
  83. package/templates/app/public/.gitkeep +2 -0
  84. package/templates/app/resources/css/app.css +1 -0
  85. package/templates/app/resources/views/auth/forgot.tsx +30 -0
  86. package/templates/app/resources/views/auth/login.tsx +24 -0
  87. package/templates/app/resources/views/auth/register.tsx +24 -0
  88. package/templates/app/resources/views/auth/two-factor.tsx +22 -0
  89. package/templates/app/resources/views/dashboard.tsx +20 -0
  90. package/templates/app/resources/views/layout.tsx +15 -0
  91. package/templates/app/resources/views/welcome.tsx +29 -0
  92. package/templates/app/routes/web.ts +35 -0
  93. package/templates/app/tests/auth.test.ts +47 -0
  94. package/templates/app/tsconfig.json +31 -0
  95. package/templates/app/worker.ts +33 -0
  96. package/templates/app/wrangler.jsonc +25 -0
  97. package/templates/minimal/.env.example +8 -0
  98. package/templates/minimal/app/Controllers/HomeController.ts +14 -0
  99. package/templates/minimal/app/Http/Kernel.ts +22 -0
  100. package/templates/minimal/app/Http/Middleware/requestLogger.ts +8 -0
  101. package/templates/minimal/app/Providers/AppServiceProvider.ts +8 -0
  102. package/templates/minimal/bin/keel.ts +15 -0
  103. package/templates/minimal/bootstrap/app.ts +24 -0
  104. package/templates/minimal/bootstrap/providers.ts +6 -0
  105. package/templates/minimal/config/app.ts +10 -0
  106. package/templates/minimal/package.json +29 -0
  107. package/templates/minimal/public/.gitkeep +2 -0
  108. package/templates/minimal/resources/css/app.css +1 -0
  109. package/templates/minimal/resources/views/layout.tsx +15 -0
  110. package/templates/minimal/resources/views/welcome.tsx +15 -0
  111. package/templates/minimal/routes/web.ts +13 -0
  112. package/templates/minimal/tsconfig.json +18 -0
  113. package/templates/minimal/worker.ts +23 -0
  114. package/templates/minimal/wrangler.jsonc +10 -0
  115. package/templates/saas/.env.example +12 -0
  116. package/templates/saas/app/Controllers/AuthController.ts +125 -0
  117. package/templates/saas/app/Controllers/DashboardController.ts +37 -0
  118. package/templates/saas/app/Controllers/HomeController.ts +10 -0
  119. package/templates/saas/app/Controllers/TeamController.ts +88 -0
  120. package/templates/saas/app/Http/Kernel.ts +27 -0
  121. package/templates/saas/app/Http/Middleware/requestLogger.ts +8 -0
  122. package/templates/saas/app/Models/Project.ts +20 -0
  123. package/templates/saas/app/Models/User.ts +15 -0
  124. package/templates/saas/app/Providers/AppServiceProvider.ts +12 -0
  125. package/templates/saas/app/Providers/DatabaseServiceProvider.ts +52 -0
  126. package/templates/saas/bin/keel.ts +15 -0
  127. package/templates/saas/bootstrap/app.ts +24 -0
  128. package/templates/saas/bootstrap/providers.edge.ts +18 -0
  129. package/templates/saas/bootstrap/providers.ts +22 -0
  130. package/templates/saas/config/app.ts +10 -0
  131. package/templates/saas/config/database.ts +42 -0
  132. package/templates/saas/database/migrations/0001_create_users.ts +21 -0
  133. package/templates/saas/database/migrations/0002_create_projects.ts +20 -0
  134. package/templates/saas/package.json +35 -0
  135. package/templates/saas/public/.gitkeep +2 -0
  136. package/templates/saas/resources/css/app.css +1 -0
  137. package/templates/saas/resources/views/auth/forgot.tsx +30 -0
  138. package/templates/saas/resources/views/auth/login.tsx +24 -0
  139. package/templates/saas/resources/views/auth/register.tsx +24 -0
  140. package/templates/saas/resources/views/auth/two-factor.tsx +22 -0
  141. package/templates/saas/resources/views/dashboard.tsx +20 -0
  142. package/templates/saas/resources/views/layout.tsx +15 -0
  143. package/templates/saas/resources/views/teams/index.tsx +85 -0
  144. package/templates/saas/resources/views/welcome.tsx +29 -0
  145. package/templates/saas/routes/web.ts +44 -0
  146. package/templates/saas/tests/auth.test.ts +47 -0
  147. package/templates/saas/tests/teams.test.ts +27 -0
  148. package/templates/saas/tsconfig.json +31 -0
  149. package/templates/saas/worker.ts +33 -0
  150. package/templates/saas/wrangler.jsonc +25 -0
@@ -0,0 +1,47 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+
4
+ import { HttpKernel, testClient } from "@shaferllc/keel/core";
5
+
6
+ import { createApplication } from "../bootstrap/app.js";
7
+
8
+ /**
9
+ * These hit the real routes through the real kernel. A starter that ships no tests
10
+ * teaches that tests are optional — and auth is the last place you want that.
11
+ */
12
+ test("a visitor can register and land in their personal team", async () => {
13
+ const app = await createApplication();
14
+ const client = testClient(app.make(HttpKernel));
15
+
16
+ (await client.get("/login")).assertOk();
17
+
18
+ const registered = await client.form("/register", {
19
+ name: "Ada",
20
+ email: `ada+${crypto.randomUUID()}@example.com`,
21
+ password: "correct horse battery",
22
+ });
23
+
24
+ // A redirect means the session was set and the personal team exists.
25
+ assert.equal(registered.status, 302);
26
+ });
27
+
28
+ test("the dashboard turns guests away", async () => {
29
+ const app = await createApplication();
30
+ const client = testClient(app.make(HttpKernel));
31
+
32
+ const response = await client.get("/dashboard");
33
+
34
+ assert.equal(response.status, 302, "a guest is redirected, not shown the page");
35
+ });
36
+
37
+ test("a wrong password says nothing about whether the account exists", async () => {
38
+ const app = await createApplication();
39
+ const client = testClient(app.make(HttpKernel));
40
+
41
+ const response = await client.form("/login", {
42
+ email: "nobody@example.com",
43
+ password: "wrong",
44
+ });
45
+
46
+ assert.equal(response.status, 401);
47
+ });
@@ -0,0 +1,27 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+
4
+ import { HttpKernel, testClient } from "@shaferllc/keel/core";
5
+
6
+ import { createApplication } from "../bootstrap/app.js";
7
+
8
+ test("registering creates a personal team and lands on it", async () => {
9
+ const app = await createApplication();
10
+ const client = testClient(app.make(HttpKernel));
11
+
12
+ const registered = await client.form("/register", {
13
+ name: "Ada",
14
+ email: `ada+${crypto.randomUUID()}@example.com`,
15
+ password: "correct horse battery",
16
+ });
17
+
18
+ // Redirected to /teams — the personal team exists, so tenant queries can run.
19
+ assert.equal(registered.status, 302);
20
+ });
21
+
22
+ test("teams turn guests away", async () => {
23
+ const app = await createApplication();
24
+ const client = testClient(app.make(HttpKernel));
25
+
26
+ assert.equal((await client.get("/teams")).status, 302);
27
+ });
@@ -0,0 +1,31 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "lib": [
7
+ "ES2022"
8
+ ],
9
+ "types": [
10
+ "node"
11
+ ],
12
+ "strict": true,
13
+ "noUncheckedIndexedAccess": true,
14
+ "esModuleInterop": true,
15
+ "skipLibCheck": true,
16
+ "resolveJsonModule": true,
17
+ "noEmit": true,
18
+ "jsx": "react-jsx",
19
+ "jsxImportSource": "hono/jsx"
20
+ },
21
+ "include": [
22
+ "app",
23
+ "bootstrap",
24
+ "config",
25
+ "routes",
26
+ "database",
27
+ "resources",
28
+ "bin",
29
+ "tests"
30
+ ]
31
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The Cloudflare Workers entry. `wrangler dev` / `wrangler deploy` use this.
3
+ *
4
+ * D1's binding only exists inside a request, so the connection is wired here, before
5
+ * the app boots — and the app is built once, then reused.
6
+ *
7
+ * Note the provider list: `edgeProviders`, not the Node one. See providers.edge.ts.
8
+ */
9
+
10
+ import { setConnection, HttpKernel } from "@shaferllc/keel/core";
11
+ import { d1Connection, type D1Like } from "@shaferllc/keel/db/d1";
12
+
13
+ import { createApplication } from "./bootstrap/app.js";
14
+ import { edgeProviders } from "./bootstrap/providers.edge.js";
15
+
16
+ interface Env {
17
+ DB: D1Like;
18
+ }
19
+
20
+ let handler: { fetch: (request: Request, env: unknown) => Response | Promise<Response> } | undefined;
21
+
22
+ export default {
23
+ async fetch(request: Request, env: Env): Promise<Response> {
24
+ if (!handler) {
25
+ setConnection(d1Connection(env.DB), "sqlite");
26
+
27
+ const app = await createApplication(edgeProviders);
28
+ handler = app.make(HttpKernel).build();
29
+ }
30
+
31
+ return handler.fetch(request, env);
32
+ },
33
+ };
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "node_modules/wrangler/config-schema.json",
3
+ "name": "__APP_NAME__",
4
+ "main": "worker.ts",
5
+ "compatibility_date": "2025-01-01",
6
+ // AsyncLocalStorage — Keel carries the request, the open transaction, and the
7
+ // current team in it. Without this flag they have nowhere to live.
8
+ "compatibility_flags": ["nodejs_compat"],
9
+
10
+ // The compiled stylesheet. Cloudflare serves these; the Worker never sees them.
11
+ "assets": { "directory": "./public" },
12
+
13
+ "d1_databases": [
14
+ {
15
+ "binding": "DB",
16
+ "database_name": "__APP_NAME__",
17
+ // Create one: wrangler d1 create __APP_NAME__ — then paste the id here.
18
+ "database_id": ""
19
+ }
20
+ ],
21
+
22
+ "vars": {
23
+ "DB_CONNECTION": "d1"
24
+ }
25
+ }