wabe 0.6.9 → 0.6.11

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 (162) hide show
  1. package/README.md +156 -50
  2. package/bucket/b.txt +1 -0
  3. package/dev/index.ts +215 -0
  4. package/dist/authentication/Session.d.ts +4 -1
  5. package/dist/authentication/interface.d.ts +16 -0
  6. package/dist/cron/index.d.ts +0 -1
  7. package/dist/database/DatabaseController.d.ts +41 -13
  8. package/dist/database/interface.d.ts +1 -0
  9. package/dist/email/DevAdapter.d.ts +0 -1
  10. package/dist/email/interface.d.ts +1 -1
  11. package/dist/graphql/resolvers.d.ts +4 -2
  12. package/dist/hooks/index.d.ts +8 -2
  13. package/dist/index.d.ts +0 -1
  14. package/dist/index.js +32144 -32058
  15. package/dist/schema/Schema.d.ts +2 -1
  16. package/dist/server/index.d.ts +4 -2
  17. package/dist/utils/crypto.d.ts +7 -0
  18. package/dist/utils/helper.d.ts +5 -1
  19. package/generated/schema.graphql +22 -14
  20. package/generated/wabe.ts +4 -4
  21. package/package.json +23 -23
  22. package/src/authentication/OTP.test.ts +69 -0
  23. package/src/authentication/OTP.ts +64 -0
  24. package/src/authentication/Session.test.ts +629 -0
  25. package/src/authentication/Session.ts +493 -0
  26. package/src/authentication/defaultAuthentication.ts +209 -0
  27. package/src/authentication/index.ts +3 -0
  28. package/src/authentication/interface.ts +155 -0
  29. package/src/authentication/oauth/GitHub.test.ts +91 -0
  30. package/src/authentication/oauth/GitHub.ts +121 -0
  31. package/src/authentication/oauth/Google.test.ts +91 -0
  32. package/src/authentication/oauth/Google.ts +101 -0
  33. package/src/authentication/oauth/Oauth2Client.test.ts +219 -0
  34. package/src/authentication/oauth/Oauth2Client.ts +135 -0
  35. package/src/authentication/oauth/index.ts +2 -0
  36. package/src/authentication/oauth/utils.test.ts +33 -0
  37. package/src/authentication/oauth/utils.ts +27 -0
  38. package/src/authentication/providers/EmailOTP.test.ts +127 -0
  39. package/src/authentication/providers/EmailOTP.ts +84 -0
  40. package/src/authentication/providers/EmailPassword.test.ts +176 -0
  41. package/src/authentication/providers/EmailPassword.ts +116 -0
  42. package/src/authentication/providers/EmailPasswordSRP.test.ts +208 -0
  43. package/src/authentication/providers/EmailPasswordSRP.ts +179 -0
  44. package/src/authentication/providers/GitHub.ts +24 -0
  45. package/src/authentication/providers/Google.ts +24 -0
  46. package/src/authentication/providers/OAuth.test.ts +185 -0
  47. package/src/authentication/providers/OAuth.ts +106 -0
  48. package/src/authentication/providers/PhonePassword.test.ts +176 -0
  49. package/src/authentication/providers/PhonePassword.ts +115 -0
  50. package/src/authentication/providers/QRCodeOTP.test.ts +77 -0
  51. package/src/authentication/providers/QRCodeOTP.ts +58 -0
  52. package/src/authentication/providers/index.ts +6 -0
  53. package/src/authentication/resolvers/refreshResolver.test.ts +30 -0
  54. package/src/authentication/resolvers/refreshResolver.ts +19 -0
  55. package/src/authentication/resolvers/signInWithResolver.inte.test.ts +59 -0
  56. package/src/authentication/resolvers/signInWithResolver.test.ts +293 -0
  57. package/src/authentication/resolvers/signInWithResolver.ts +92 -0
  58. package/src/authentication/resolvers/signOutResolver.test.ts +38 -0
  59. package/src/authentication/resolvers/signOutResolver.ts +18 -0
  60. package/src/authentication/resolvers/signUpWithResolver.test.ts +180 -0
  61. package/src/authentication/resolvers/signUpWithResolver.ts +65 -0
  62. package/src/authentication/resolvers/verifyChallenge.test.ts +133 -0
  63. package/src/authentication/resolvers/verifyChallenge.ts +62 -0
  64. package/src/authentication/roles.test.ts +49 -0
  65. package/src/authentication/roles.ts +40 -0
  66. package/src/authentication/utils.test.ts +97 -0
  67. package/src/authentication/utils.ts +39 -0
  68. package/src/cache/InMemoryCache.test.ts +62 -0
  69. package/src/cache/InMemoryCache.ts +45 -0
  70. package/src/cron/index.test.ts +17 -0
  71. package/src/cron/index.ts +43 -0
  72. package/src/database/DatabaseController.test.ts +613 -0
  73. package/src/database/DatabaseController.ts +1007 -0
  74. package/src/database/index.test.ts +1372 -0
  75. package/src/database/index.ts +9 -0
  76. package/src/database/interface.ts +302 -0
  77. package/src/email/DevAdapter.ts +7 -0
  78. package/src/email/EmailController.test.ts +29 -0
  79. package/src/email/EmailController.ts +13 -0
  80. package/src/email/index.ts +2 -0
  81. package/src/email/interface.ts +36 -0
  82. package/src/email/templates/sendOtpCode.ts +120 -0
  83. package/src/file/FileController.ts +28 -0
  84. package/src/file/FileDevAdapter.ts +51 -0
  85. package/src/file/hookDeleteFile.ts +25 -0
  86. package/src/file/hookReadFile.ts +66 -0
  87. package/src/file/hookUploadFile.ts +50 -0
  88. package/src/file/index.test.ts +932 -0
  89. package/src/file/index.ts +2 -0
  90. package/src/file/interface.ts +39 -0
  91. package/src/graphql/GraphQLSchema.test.ts +4408 -0
  92. package/src/graphql/GraphQLSchema.ts +880 -0
  93. package/src/graphql/index.ts +2 -0
  94. package/src/graphql/parseGraphqlSchema.ts +85 -0
  95. package/src/graphql/parser.test.ts +203 -0
  96. package/src/graphql/parser.ts +542 -0
  97. package/src/graphql/pointerAndRelationFunction.ts +191 -0
  98. package/src/graphql/resolvers.ts +442 -0
  99. package/src/graphql/tests/aggregation.test.ts +1115 -0
  100. package/src/graphql/tests/e2e.test.ts +590 -0
  101. package/src/graphql/tests/scalars.test.ts +250 -0
  102. package/src/graphql/types.ts +227 -0
  103. package/src/hooks/HookObject.test.ts +122 -0
  104. package/src/hooks/HookObject.ts +165 -0
  105. package/src/hooks/authentication.ts +67 -0
  106. package/src/hooks/createUser.test.ts +77 -0
  107. package/src/hooks/createUser.ts +10 -0
  108. package/src/hooks/defaultFields.test.ts +176 -0
  109. package/src/hooks/defaultFields.ts +32 -0
  110. package/src/hooks/deleteSession.test.ts +181 -0
  111. package/src/hooks/deleteSession.ts +20 -0
  112. package/src/hooks/hashFieldHook.test.ts +152 -0
  113. package/src/hooks/hashFieldHook.ts +89 -0
  114. package/src/hooks/index.test.ts +258 -0
  115. package/src/hooks/index.ts +414 -0
  116. package/src/hooks/permissions.test.ts +412 -0
  117. package/src/hooks/permissions.ts +93 -0
  118. package/src/hooks/protected.test.ts +551 -0
  119. package/src/hooks/protected.ts +60 -0
  120. package/src/hooks/searchableFields.test.ts +147 -0
  121. package/src/hooks/searchableFields.ts +86 -0
  122. package/src/hooks/session.test.ts +134 -0
  123. package/src/hooks/session.ts +76 -0
  124. package/src/hooks/setEmail.test.ts +216 -0
  125. package/src/hooks/setEmail.ts +33 -0
  126. package/src/hooks/setupAcl.test.ts +618 -0
  127. package/src/hooks/setupAcl.ts +25 -0
  128. package/src/index.ts +9 -0
  129. package/src/schema/Schema.test.ts +482 -0
  130. package/src/schema/Schema.ts +757 -0
  131. package/src/schema/defaultResolvers.ts +93 -0
  132. package/src/schema/index.ts +1 -0
  133. package/src/schema/resolvers/meResolver.test.ts +62 -0
  134. package/src/schema/resolvers/meResolver.ts +10 -0
  135. package/src/schema/resolvers/resetPassword.test.ts +341 -0
  136. package/src/schema/resolvers/resetPassword.ts +63 -0
  137. package/src/schema/resolvers/sendEmail.test.ts +118 -0
  138. package/src/schema/resolvers/sendEmail.ts +21 -0
  139. package/src/schema/resolvers/sendOtpCode.test.ts +141 -0
  140. package/src/schema/resolvers/sendOtpCode.ts +52 -0
  141. package/src/security.test.ts +3434 -0
  142. package/src/server/defaultSessionHandler.test.ts +62 -0
  143. package/src/server/defaultSessionHandler.ts +105 -0
  144. package/src/server/generateCodegen.ts +433 -0
  145. package/src/server/index.test.ts +532 -0
  146. package/src/server/index.ts +334 -0
  147. package/src/server/interface.ts +11 -0
  148. package/src/server/routes/authHandler.ts +169 -0
  149. package/src/server/routes/index.ts +39 -0
  150. package/src/utils/crypto.test.ts +41 -0
  151. package/src/utils/crypto.ts +105 -0
  152. package/src/utils/export.ts +11 -0
  153. package/src/utils/helper.ts +204 -0
  154. package/src/utils/index.test.ts +11 -0
  155. package/src/utils/index.ts +189 -0
  156. package/src/utils/preload.ts +8 -0
  157. package/src/utils/testHelper.ts +116 -0
  158. package/tsconfig.json +32 -0
  159. package/bunfig.toml +0 -4
  160. package/dist/ai/index.d.ts +0 -1
  161. package/dist/ai/interface.d.ts +0 -9
  162. /package/dist/server/{defaultHandlers.d.ts → defaultSessionHandler.d.ts} +0 -0
package/README.md CHANGED
@@ -1,75 +1,181 @@
1
1
  <p align="center">
2
- <a href="https://wabe.dev"><img src="https://wabe.dev/assets/logo.png" alt="Wabe logo" height=170></a>
2
+ <h1 align="center">Wabe</h1>
3
+ <p align="center">🚀 A fully open-source <strong>Firebase alternative</strong> built in TypeScript</p>
3
4
  </p>
4
5
 
5
- <div align="center">
6
- <a href="https://wabe.dev">Documentation</a>
7
- </div>
6
+ <p align="center">
7
+ <a href="https://github.com/palixir/wabe"><img src="https://img.shields.io/github/stars/palixir/wabe?style=flat-square" /></a>
8
+ <a href="https://www.npmjs.com/package/wabe"><img src="https://img.shields.io/npm/v/wabe?style=flat-square" /></a>
9
+ <a href="./LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-green?style=flat-square" /></a>
10
+ </p>
11
+
12
+ ---
13
+
14
+ Wabe is a modern, batteries-included backend-as-a-service designed for developers who want the flexibility of self-hosting with the ease of Firebase.
15
+
16
+ You define your models → Wabe instantly generates:
17
+
18
+ - a **secure GraphQL API**
19
+ - **auth**, **permissions**, **hooks**, **emails**, **files**, and more
20
+ - a fully extensible backend written in clean TypeScript
21
+
22
+ No vendor lock-in. No hidden limits.
23
+ Host it anywhere.
24
+
25
+ 📚 **Documentation:** [https://palixir.github.io/wabe](https://palixir.github.io/wabe)
8
26
 
9
- ## What is Wabe?
27
+ ---
10
28
 
11
- Wabe is an open-source backend as a service that allows you to create your own fully customizable backend in just a few minutes. It handles database access, automatic GraphQL API generation, authentication with various methods (classic or OAuth), permissions, security, emails, and more for you.
29
+ # Features
12
30
 
13
- It requires Bun or Node > 24.7.
31
+ | Feature | Description |
32
+ | ------------------------- | ---------------------------------------------------------------------------------------- |
33
+ | 🔐 Authentication | Email/password, OTP, OAuth (Google, GitHub), password reset, email verification |
34
+ | 🔑 Permissions | Fine-grained access control at collection, object, and field levels with secure defaults |
35
+ | ⚡ Auto-generated GraphQL | Fully typed CRUD GraphQL API generated from your schema, ready for production |
36
+ | 🔄 Hooks | Custom logic before/after create, update, delete, and read operations |
37
+ | 📨 Email providers | Resend (official adapter) or custom adapters |
38
+ | 🗄️ Database adapters | MongoDB, PostgreSQL (official), or your own adapter |
39
+ | 📦 Modular architecture | Replaceable and extensible modules: auth, storage, email, database, permissions |
40
+ | 🌍 Self-host anywhere | Docker, Node, Bun, Fly.io, Render, Railway, Hetzner, Raspberry Pi |
14
41
 
15
- ## Install
42
+ ---
16
43
 
17
- ```sh
18
- bun install wabe # On bun
19
- npm install wabe # On npm
20
- yarn add wabe # On yarn
44
+ # 🚀 Quickstart
45
+
46
+ ### 1. Install
47
+
48
+ ```bash
49
+ npm install wabe
50
+ # or
51
+ bun add wabe
21
52
  ```
22
53
 
23
- ## Basic example
54
+ ### 2. Create your schema and start your server
24
55
 
25
56
  ```ts
26
- import { Wabe } from "wabe";
27
- import { MongoAdapter } from "wabe-mongodb";
57
+ import { Wabe } from 'wabe'
58
+ import { MongoAdapter } from 'wabe-mongodb'
28
59
 
29
60
  const run = async () => {
30
- // Ensure your database is running before run the file
31
-
32
- const wabe = new Wabe({
33
- isProduction: process.env.NODE_ENV === "production",
34
- // Root key example (must be long minimal 64 characters, you can generate it online)
35
- rootKey:
36
- "0uwFvUxM$ceFuF1aEtTtZMa7DUN2NZudqgY5ve5W*QCyb58cwMj9JeoaV@d#%29v&aJzswuudVU1%nAT+rxS0Bh&OkgBYc0PH18*",
37
- database: {
38
- adapter: new MongoAdapter({
39
- databaseName: "WabeApp",
40
- databaseUrl: "mongodb://127.0.0.1:27045",
41
- }),
42
- },
43
- port: 3001,
44
- });
45
-
46
- await wabe.start();
47
- };
48
-
49
- await run();
61
+ const wabe = new Wabe({
62
+ isProduction: process.env.NODE_ENV === 'production',
63
+ // Root key example (must be long minimal 64 characters, you can generate it online)
64
+ rootKey:
65
+ '0uwFvUxM$ceFuF1aEtTtZMa7DUN2NZudqgY5ve5W*QCyb58cwMj9JeoaV@d#%29v&aJzswuudVU1%nAT+rxS0Bh&OkgBYc0PH18*',
66
+ database: {
67
+ adapter: new MongoAdapter({
68
+ databaseName: 'WabeApp',
69
+ databaseUrl: 'mongodb://127.0.0.1:27045',
70
+ }),
71
+ },
72
+ schema: {
73
+ classes: [
74
+ {
75
+ name: 'User',
76
+ description: 'User class',
77
+ fields: {
78
+ name: {
79
+ type: 'String',
80
+ },
81
+ age: {
82
+ type: 'Int',
83
+ },
84
+ email: {
85
+ type: 'Email',
86
+ required: true,
87
+ },
88
+ },
89
+ },
90
+ ],
91
+ },
92
+ port: 3000,
93
+ })
94
+
95
+ await wabe.start()
96
+ }
97
+
98
+ await run()
99
+ ```
100
+
101
+ ### 3. Query your API
102
+
103
+ ```graphql
104
+ mutation createUser {
105
+ createUser(input: { fields: { name: "Wabe", email: "mybackend@wabe.com", age: 10 } }) {
106
+ user {
107
+ id
108
+ name
109
+ }
110
+ }
111
+ }
50
112
  ```
51
113
 
52
- ## Features
114
+ # 🧩 Official Templates
115
+
116
+ Wabe comes with a set of official templates to help you bootstrap projects instantly:
117
+
118
+ | Template | Stack | Description | Status |
119
+ | ---------------------- | -------------- | --------------------------------- | -------------- |
120
+ | **wabe-starter** | Wabe + Node | Minimal starter backend | 🟡 Coming soon |
121
+ | **wabe-next-template** | Next.js + Wabe | Authentication + CRUD boilerplate | 🟡 Coming soon |
122
+ | **wabe-saas-kit** | Wabe + Wobe | SaaS starter kit with Stripe | 🟡 Coming soon |
123
+
124
+ More templates are added regularly based on community needs.
125
+
126
+ ---
127
+
128
+ # 🌱 Ecosystem
129
+
130
+ ### **Wobe — Full-stack web framework**
131
+
132
+ Wobe is a lightweight, TypeScript-first full-stack framework designed to pair naturally with Wabe.
133
+ For a seamless frontend + backend developer experience:
134
+
135
+ 👉 https://github.com/palixir/wobe
136
+
137
+ ### **GraphQL Server (coming soon)**
138
+
139
+ A modern, type-safe GraphQL server designed as a companion to Wabe.
140
+ Optimized for DX, performance, and full extensibility.
141
+
142
+ ---
143
+
144
+ # 🗺️ Roadmap
145
+
146
+ - [x] PostgreSQL adapter
147
+ - [ ] Admin dashboard UI
148
+ - [x] File storage adapters (S3, Cloudflare R2, etc.)
149
+ - [ ] CLI (`wabe init`, `wabe generate`)
150
+ - [ ] SaaS starter kit
151
+ - [ ] Improved documentation
152
+
153
+ ---
154
+
155
+ # 🤝 Contributing
156
+
157
+ Contributions are welcome!
158
+ Before opening a PR, check the `CONTRIBUTING.md` and join the community.
159
+
160
+ ---
53
161
 
54
- - **Authentication**: Secure and scalable authentication for your applications.
55
- - **Permissions**: Granular permissions control to secure your resources.
56
- - **Database**: A powerful, scalable database to store and manage you data.
57
- - **GraphQL API**: A flexible and powerful GraphQL API (following GraphQL Relay standard) to interact with your data.
58
- - **Hooks**: Powerful hooks system to execute custom actions before or after database requests.
59
- - **Email**: Send emails with your favorite provider with very simple integration.
162
+ # ❤️ Sponsors
60
163
 
61
- ## Contributing
164
+ Wabe is 100% open-source and maintained in my free time.
165
+ If you want to support development:
62
166
 
63
- Contributions are always welcome! If you have an idea for something that should be added, modified, or removed, please don't hesitate to create a pull request (I promise a quick review).
167
+ 👉 **GitHub Sponsors:** https://github.com/sponsors/coratgerl
64
168
 
65
- You can also create an issue to propose your ideas or report a bug.
169
+ **Sponsors receive:**
66
170
 
67
- Of course, you can also use Wabe for your backend; that is the better contribution at this day ❤️.
171
+ - Access to a complete, fully tested boilerplate with an admin dashboard to manage users (Vite, Tailwind, Playwright, Wabe, Bun, GraphQL, etc.)
172
+ - Your name featured in the `README.md`
68
173
 
69
- If you like the project don't forget to share it.
174
+ Your support helps keep Wabe sustainable and actively maintained, and allows me to continue creating new projects in my free time to help developers have solid backends with minimal effort.
70
175
 
71
- More information on the [Contribution guide](https://github.com/palixir/wabe/blob/main/CONTRIBUTING.md)
176
+ ---
72
177
 
73
- ## License
178
+ # ⭐ Show your support
74
179
 
75
- Distributed under the Apache License 2.0 [License](https://github.com/palixir/wabe/blob/main/LICENSE).
180
+ If you like the project, please consider starring the repository:
181
+ ⭐ → It helps more than you think.
package/bucket/b.txt ADDED
@@ -0,0 +1 @@
1
+ b
package/dev/index.ts ADDED
@@ -0,0 +1,215 @@
1
+ import {
2
+ RoleEnum,
3
+ type WabeSchemaWhereTypes,
4
+ type WabeSchemaEnums,
5
+ type WabeSchemaScalars,
6
+ type WabeSchemaTypes,
7
+ } from '../generated/wabe'
8
+ import { getDatabaseAdapter } from '../src/utils/testHelper'
9
+ import { Wabe } from '../src/server'
10
+ import { FileDevAdapter } from '../src'
11
+ import { runDatabase } from 'wabe-mongodb-launcher'
12
+
13
+ const run = async () => {
14
+ await runDatabase()
15
+
16
+ const wabe = new Wabe<{
17
+ types: WabeSchemaTypes
18
+ scalars: WabeSchemaScalars
19
+ enums: WabeSchemaEnums
20
+ where: WabeSchemaWhereTypes
21
+ }>({
22
+ isProduction: false,
23
+ codegen: {
24
+ enabled: true,
25
+ path: `${import.meta.dirname}/../generated/`,
26
+ },
27
+ rootKey: 'dev',
28
+ authentication: {
29
+ session: {
30
+ cookieSession: true,
31
+ jwtSecret: 'dev',
32
+ jwtTokenFields: {
33
+ id: true,
34
+ },
35
+ },
36
+ roles: ['Admin', 'Client'],
37
+ successRedirectPath: 'https://palixir.github.io/wabe/',
38
+ failureRedirectPath: 'https://palixir.github.io/wabe/',
39
+ },
40
+ database: {
41
+ // @ts-expect-error
42
+ adapter: await getDatabaseAdapter('Wabe'),
43
+ },
44
+ file: {
45
+ adapter: new FileDevAdapter(),
46
+ },
47
+ port: 3001,
48
+ schema: {
49
+ classes: [
50
+ {
51
+ name: 'User',
52
+ description: 'User class',
53
+ fields: {
54
+ name: {
55
+ type: 'String',
56
+ },
57
+ age: {
58
+ type: 'Int',
59
+ },
60
+ email: {
61
+ type: 'Email',
62
+ required: true,
63
+ },
64
+ },
65
+ },
66
+ {
67
+ name: 'Post',
68
+ fields: {
69
+ name: { type: 'String', required: true },
70
+ test2: { type: 'RoleEnum' },
71
+ test3: { type: 'Relation', class: 'User', required: true },
72
+ test4: { type: 'Pointer', class: 'User', required: true },
73
+ experiences: {
74
+ type: 'Array',
75
+ typeValue: 'Object',
76
+ object: {
77
+ name: 'Experience',
78
+ required: true,
79
+ fields: {
80
+ jobTitle: {
81
+ type: 'String',
82
+ required: true,
83
+ },
84
+ companyName: {
85
+ type: 'String',
86
+ required: true,
87
+ },
88
+ startDate: {
89
+ type: 'String',
90
+ required: true,
91
+ },
92
+ endDate: {
93
+ type: 'String',
94
+ required: true,
95
+ },
96
+ achievements: {
97
+ type: 'Array',
98
+ typeValue: 'String',
99
+ },
100
+ },
101
+ },
102
+ },
103
+ },
104
+ permissions: {
105
+ create: {
106
+ requireAuthentication: true,
107
+ authorizedRoles: [RoleEnum.Admin],
108
+ },
109
+ },
110
+ },
111
+ ],
112
+ resolvers: {
113
+ queries: {
114
+ helloWorld: {
115
+ type: 'String',
116
+ description: 'Hello world description',
117
+ args: {
118
+ name: {
119
+ type: 'String',
120
+ required: true,
121
+ },
122
+ },
123
+ resolve: () => 'Hello World',
124
+ },
125
+ },
126
+ mutations: {
127
+ createMutation: {
128
+ type: 'Boolean',
129
+ required: true,
130
+ args: {
131
+ input: {
132
+ name: {
133
+ type: 'Int',
134
+ required: true,
135
+ },
136
+ },
137
+ },
138
+ resolve: () => true,
139
+ },
140
+ customMutation: {
141
+ type: 'Int',
142
+ args: {
143
+ input: {
144
+ a: {
145
+ type: 'Int',
146
+ required: true,
147
+ },
148
+ b: {
149
+ type: 'Int',
150
+ required: true,
151
+ },
152
+ },
153
+ },
154
+ resolve: (_: any, args: any) => args.input.a + args.input.b,
155
+ },
156
+ secondCustomMutation: {
157
+ type: 'Int',
158
+ args: {
159
+ input: {
160
+ sum: {
161
+ type: 'Object',
162
+ object: {
163
+ name: 'Sum',
164
+ fields: {
165
+ a: {
166
+ type: 'Int',
167
+ required: true,
168
+ },
169
+ b: {
170
+ type: 'Int',
171
+ required: true,
172
+ },
173
+ },
174
+ },
175
+ },
176
+ },
177
+ },
178
+ resolve: (_: any, args: any) => args.input.sum.a + args.input.sum.b,
179
+ },
180
+ },
181
+ },
182
+ },
183
+ })
184
+
185
+ // For select test
186
+ // const res = await wabe.controllers.database.getObjects({
187
+ // className: 'Post',
188
+ // context: {} as any,
189
+ // select: {
190
+ // name: true,
191
+ // test3: {
192
+ // age: true,
193
+ // role: {
194
+ // id: true,
195
+ // },
196
+ // },
197
+ // test4: {
198
+ // name: true,
199
+ // },
200
+ // },
201
+ // where: {
202
+ // name: {
203
+ // equalTo: 'test',
204
+ // },
205
+ // },
206
+ // })
207
+
208
+ // res[0]?.test3[0].role?.id
209
+
210
+ await wabe.start()
211
+ }
212
+
213
+ run().catch((err) => {
214
+ console.error(err)
215
+ })
@@ -8,7 +8,10 @@ export declare class Session {
8
8
  getAccessTokenExpireAt(config: WabeConfig<DevWabeTypes>);
9
9
  _getRefreshTokenExpiresInMs(config: WabeConfig<DevWabeTypes>);
10
10
  getRefreshTokenExpireAt(config: WabeConfig<DevWabeTypes>);
11
- meFromAccessToken(accessToken: string, context: WabeContext<DevWabeTypes>): Promise<{
11
+ meFromAccessToken({ accessToken, csrfToken }: {
12
+ accessToken: string;
13
+ csrfToken: string;
14
+ }, context: WabeContext<DevWabeTypes>): Promise<{
12
15
  sessionId: string | null;
13
16
  user: User | null;
14
17
  accessToken: string | null;
@@ -101,6 +101,22 @@ export interface SessionConfig<T extends WabeTypes> {
101
101
  */
102
102
  jwtSecret: string;
103
103
  /**
104
+ * Optional audience to embed and verify in JWTs
105
+ */
106
+ jwtAudience?: string;
107
+ /**
108
+ * Optional issuer to embed and verify in JWTs
109
+ */
110
+ jwtIssuer?: string;
111
+ /**
112
+ * Secret dedicated to CSRF token HMAC (defaults to jwtSecret)
113
+ */
114
+ csrfSecret?: string;
115
+ /**
116
+ * Secret used to encrypt session tokens at rest (defaults to jwtSecret)
117
+ */
118
+ tokenSecret?: string;
119
+ /**
104
120
  * A selection of fields to include in the JWT token in the "user" fields
105
121
  */
106
122
  jwtTokenFields?: SelectType<T, "User", keyof T["types"]["User"]>;
@@ -13,7 +13,6 @@ export declare enum CronExpressions {
13
13
  EVERY_HOUR = "0 0 * * * *",
14
14
  EVERY_DAY_AT_MIDNIGHT = "0 0 0 * * *",
15
15
  EVERY_WEEK = "0 0 0 * * 0",
16
- EVERY_MONTH = "0 0 0 1 * *",
17
16
  EVERY_YEAR = "0 0 0 1 1 *",
18
17
  WEEKDAYS_MORNING = "0 0 7 * * 1-5",
19
18
  WEEKENDS_EVENING = "0 0 19 * * 6-7",
@@ -1,4 +1,5 @@
1
1
  import type { WabeTypes } from "../..";
2
+ import { OperationType } from "../hooks";
2
3
  import type { SchemaInterface } from "../schema";
3
4
  import type { WabeContext } from "../server/interface";
4
5
  import type { CountOptions, CreateObjectOptions, CreateObjectsOptions, DatabaseAdapter, DeleteObjectOptions, DeleteObjectsOptions, GetObjectOptions, GetObjectsOptions, OutputType, UpdateObjectOptions, UpdateObjectsOptions, WhereType } from "./interface";
@@ -7,32 +8,59 @@ type SelectWithObject = Record<string, object | boolean>;
7
8
  export declare class DatabaseController<T extends WabeTypes> {
8
9
  adapter: DatabaseAdapter<T>;
9
10
  constructor(adapter: DatabaseAdapter<T>);
11
+ /**
12
+ * Get a class definition from the schema by name (case-insensitive)
13
+ */
14
+ _getClass(className: string | keyof T["types"], context: WabeContext<T>);
15
+ /**
16
+ * Get field type and target class information
17
+ */
18
+ _getFieldType(originClassName: string, fieldName: string, context: WabeContext<T>): {
19
+ type: string;
20
+ class?: string;
21
+ } | undefined;
10
22
  _getSelectMinusPointersAndRelations({ className, context, select }: {
11
23
  className: keyof T["types"];
12
24
  context: WabeContext<T>;
13
25
  select?: SelectWithObject;
14
26
  }): {
15
- // We associated the fieldName with a className and a select object
16
27
  pointers: Record<string, {
17
28
  className: string;
18
29
  select: Select;
19
30
  }>;
20
31
  selectWithoutPointers: Select;
21
32
  };
22
- _isRelationField({ pointerField, currentClassName, context, originClassName }: {
23
- pointerField: string;
24
- originClassName: string;
25
- context: WabeContext<T>;
26
- currentClassName?: string;
27
- });
28
- _isPointerField({ pointerField, currentClassName, context, originClassName }: {
29
- originClassName: string;
30
- context: WabeContext<T>;
31
- pointerField: string;
32
- currentClassName?: string;
33
- });
33
+ _isFieldOfType(originClassName: string, pointerField: string, expectedType: "Pointer" | "Relation", context: WabeContext<T>, currentClassName?: string): boolean;
34
34
  _getWhereObjectWithPointerOrRelation<U extends keyof T["types"]>(className: U, where: WhereType<T, U>, context: WabeContext<T>);
35
35
  _buildWhereWithACL<K extends keyof T["types"]>(where: WhereType<T, K>, context: WabeContext<T>, operation: "write" | "read"): WhereType<T, K>;
36
+ /**
37
+ * Private helper to load a single object for hooks (skips hooks to avoid recursion)
38
+ */
39
+ _loadObjectForHooks(className: keyof T["types"], context: WabeContext<T>): unknown;
40
+ /**
41
+ * Private helper to load multiple objects for hooks (skips hooks to avoid recursion)
42
+ */
43
+ _loadObjectsForHooks(className: keyof T["types"], context: WabeContext<T>): unknown;
44
+ /**
45
+ * Generic executor for single object operations (create, update, delete, read)
46
+ * Encapsulates the hook lifecycle: Init -> Before -> Adapter -> After
47
+ */
48
+ _executeSingleOperationWithHooks<
49
+ K extends keyof T["types"],
50
+ U extends keyof T["types"][K]
51
+ >({ operationTypeBefore, operationTypeAfter, className, context, data, select, id, adapterCallback, inputObject }: {
52
+ operationTypeBefore: OperationType;
53
+ operationTypeAfter: OperationType;
54
+ className: K;
55
+ context: WabeContext<T>;
56
+ data?: any;
57
+ select?: Select;
58
+ id?: string;
59
+ inputObject?: OutputType<T, K, U>;
60
+ adapterCallback: (newData: any) => Promise<OutputType<T, K, U> | {
61
+ id: string;
62
+ } | null>;
63
+ });
36
64
  _getFinalObjectWithPointerAndRelation({ pointers, context, originClassName, object, _skipHooks }: {
37
65
  originClassName: string;
38
66
  pointers: Record<string, {
@@ -28,6 +28,7 @@ type WhereScalar<T> = {
28
28
  notIn?: T[];
29
29
  contains?: T;
30
30
  notContains?: T;
31
+ exists?: boolean;
31
32
  };
32
33
  type WhereObject<T> = { [P in keyof T] : IsScalar<T[P]> extends false ? WhereObject<Partial<T[P]>> : WhereScalar<T[P]> };
33
34
  type WhereAggregation<
@@ -1,5 +1,4 @@
1
1
  import type { EmailAdapter } from "./interface";
2
2
  export declare class EmailDevAdapter implements EmailAdapter {
3
- // biome-ignore lint/suspicious/useAwait: false
4
3
  send();
5
4
  }
@@ -10,7 +10,7 @@ export interface EmailSendOptions {
10
10
  from: string;
11
11
  to: Array<string>;
12
12
  subject: string;
13
- node?: React.ReactNode;
13
+ node?: any;
14
14
  html?: string;
15
15
  text?: string;
16
16
  }
@@ -1,6 +1,8 @@
1
- import type { SelectionSetNode } from "graphql";
1
+ import type { SelectionSetNode, FragmentDefinitionNode } from "graphql";
2
2
  import type { WabeContext } from "../server/interface";
3
- export declare const extractFieldsFromSetNode: (selectionSet: SelectionSetNode, className: string) => Record<string, any>;
3
+ export declare const extractFieldsFromSetNode: (selectionSet: SelectionSetNode, className: string, fragments?: Record<string, FragmentDefinitionNode>, options?: {
4
+ ignoreClassField?: boolean;
5
+ }) => Record<string, any>;
4
6
  export declare const getFieldsOfClassName: ({ fields, className, context }: {
5
7
  fields: string[];
6
8
  className: string;
@@ -1,4 +1,4 @@
1
- import type { MutationData, OutputType, Select } from "../database";
1
+ import type { MutationData, OutputType, Select, WhereType } from "../database";
2
2
  import type { WabeTypes } from "../server";
3
3
  import type { WabeContext } from "../server/interface";
4
4
  import type { DevWabeTypes } from "../utils/helper";
@@ -30,16 +30,22 @@ export declare const _findHooksByPriority: unknown;
30
30
  export declare const initializeHook: <
31
31
  T extends WabeTypes,
32
32
  K extends keyof T["types"]
33
- >({ className, newData, context, select }: {
33
+ >({ className, newData, context, select, objectLoader, objectsLoader }: {
34
34
  className: K;
35
35
  newData?: MutationData<DevWabeTypes, any, any>;
36
36
  select: Select;
37
37
  context: WabeContext<any>;
38
+ objectLoader?: (id: string) => Promise<OutputType<DevWabeTypes, any, any> | null>;
39
+ objectsLoader?: (opts: {
40
+ where?: WhereType<DevWabeTypes, any>;
41
+ ids: string[];
42
+ }) => Promise<OutputType<DevWabeTypes, any, any>[]>;
38
43
  }) => {
39
44
  runOnSingleObject: (options: {
40
45
  operationType: OperationType;
41
46
  id?: string;
42
47
  originalObject?: OutputType<DevWabeTypes, any, any>;
48
+ object?: OutputType<DevWabeTypes, any, any>;
43
49
  }) => Promise<MutationData<T, K, any>>;
44
50
  };
45
51
  export declare const getDefaultHooks: () => Hook<any, any>[];
package/dist/index.d.ts CHANGED
@@ -5,6 +5,5 @@ export * from "./database";
5
5
  export * from "./authentication";
6
6
  export * from "./file";
7
7
  export * from "./email";
8
- export * from "./ai";
9
8
  export * from "./utils/export";
10
9
  export * from "./cron";