31 | Wabe powered{' '} 32 | 33 | ShipMySaaS 34 | {' '} 35 | ! 36 |
37 |38 | Wabe is powered by{' '} 39 | 40 | Bun 41 | {' '} 42 | ! 43 |
44 |├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── ci.yml │ ├── conventional-pr.yml │ └── release.yml ├── .gitignore ├── .npmignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── biome.json ├── bun.lock ├── lefthook.yml ├── package.json ├── packages ├── wabe-build │ ├── README.md │ ├── package.json │ ├── src │ │ ├── bunVersion.ts │ │ ├── index.ts │ │ └── tscVersion.ts │ └── tsconfig.json ├── wabe-buns3 │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.test.ts │ │ ├── index.ts │ │ └── utils.ts │ └── tsconfig.json ├── wabe-documentation │ ├── .gitignore │ ├── README.md │ ├── components │ │ ├── blog │ │ │ ├── footerArticle.tsx │ │ │ ├── header.tsx │ │ │ └── listBlogArticles.tsx │ │ ├── index.tsx │ │ ├── landing │ │ │ ├── callToAction.tsx │ │ │ ├── example.tsx │ │ │ ├── features.tsx │ │ │ ├── footer.tsx │ │ │ ├── hero.tsx │ │ │ └── presentation.tsx │ │ └── utils.ts │ ├── docs │ │ ├── documentation │ │ │ ├── ai │ │ │ │ └── index.md │ │ │ ├── authentication │ │ │ │ ├── customMethods.md │ │ │ │ ├── defaultMethods.md │ │ │ │ ├── emailPasswordSRP.md │ │ │ │ ├── interact.md │ │ │ │ ├── oauth.md │ │ │ │ ├── resetPassword.md │ │ │ │ ├── roles.md │ │ │ │ ├── sessions.md │ │ │ │ └── twoFactor.md │ │ │ ├── codegen.md │ │ │ ├── cron │ │ │ │ └── index.md │ │ │ ├── database │ │ │ │ └── index.md │ │ │ ├── email │ │ │ │ └── index.md │ │ │ ├── file │ │ │ │ └── index.md │ │ │ ├── graphql │ │ │ │ └── api.md │ │ │ ├── hooks.md │ │ │ ├── index.md │ │ │ ├── payment │ │ │ │ └── index.md │ │ │ ├── public │ │ │ │ ├── auth.webp │ │ │ │ ├── copy.webp │ │ │ │ ├── cover2.webp │ │ │ │ ├── database.webp │ │ │ │ ├── email.webp │ │ │ │ ├── favicon.ico │ │ │ │ ├── github.webp │ │ │ │ ├── graphql.webp │ │ │ │ ├── graphqlPlayground.webp │ │ │ │ ├── graphqlPlayground2.webp │ │ │ │ ├── hooks.webp │ │ │ │ ├── logo.webp │ │ │ │ ├── payment.webp │ │ │ │ ├── permissions.webp │ │ │ │ ├── robots.txt │ │ │ │ └── sitemap.xml │ │ │ ├── rootKey.md │ │ │ ├── routes.md │ │ │ ├── schema │ │ │ │ ├── classes.md │ │ │ │ ├── enums.md │ │ │ │ ├── resolvers.md │ │ │ │ └── scalars.md │ │ │ ├── security │ │ │ │ └── index.md │ │ │ └── wabe │ │ │ │ ├── concepts.md │ │ │ │ ├── motivations.md │ │ │ │ └── start.md │ │ ├── index.mdx │ │ └── public │ │ │ ├── assets │ │ │ ├── appleTouchIcon.png │ │ │ ├── auth.webp │ │ │ ├── bun.svg │ │ │ ├── code.webp │ │ │ ├── copy.webp │ │ │ ├── cover.png │ │ │ ├── database.webp │ │ │ ├── email.webp │ │ │ ├── favicon.ico │ │ │ ├── github.svg │ │ │ ├── google.svg │ │ │ ├── graphql.svg │ │ │ ├── graphql.webp │ │ │ ├── graphqlPlayground.webp │ │ │ ├── graphqlPlayground2.webp │ │ │ ├── hooks.webp │ │ │ ├── logo.png │ │ │ ├── logoWithoutBackground.webp │ │ │ ├── logoXWhite.png │ │ │ ├── mongodb.svg │ │ │ ├── payment.webp │ │ │ ├── permissions.webp │ │ │ ├── resend.svg │ │ │ ├── robots.txt │ │ │ ├── schema.webp │ │ │ ├── sitemap.xml │ │ │ └── stripe.svg │ │ │ ├── robots.txt │ │ │ ├── scripts │ │ │ └── data.js │ │ │ └── sitemap.xml │ ├── package.json │ ├── postcss.config.js │ ├── rspress.config.ts │ ├── styles │ │ └── index.css │ ├── tailwind.config.js │ └── tsconfig.json ├── wabe-mistralai │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.test.ts │ │ └── index.ts │ └── tsconfig.json ├── wabe-mongodb-launcher │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── wabe-mongodb │ ├── .gitignore │ ├── README.md │ ├── bunfig.toml │ ├── package.json │ ├── src │ │ ├── index.test.ts │ │ └── index.ts │ ├── tsconfig.json │ └── utils │ │ ├── preload.ts │ │ └── testHelper.ts ├── wabe-openai │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.test.ts │ │ └── index.ts │ └── tsconfig.json ├── wabe-pluralize │ ├── package.json │ ├── src │ │ ├── index.test.ts │ │ └── index.ts │ └── tsconfig.json ├── wabe-postgres-launcher │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── wabe-postgres │ ├── .gitignore │ ├── README.md │ ├── bunfig.toml │ ├── package.json │ ├── src │ │ ├── index.test.ts │ │ └── index.ts │ ├── tsconfig.json │ └── utils │ │ ├── preload.ts │ │ └── testHelper.ts ├── wabe-resend │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.test.ts │ │ └── index.ts │ └── tsconfig.json ├── wabe-stripe │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.test.ts │ │ └── index.ts │ └── tsconfig.json └── wabe │ ├── README.md │ ├── bunfig.toml │ ├── dev │ └── index.ts │ ├── generated │ ├── schema.graphql │ └── wabe.ts │ ├── package.json │ ├── src │ ├── ai │ │ ├── AIController.test.ts │ │ ├── AIController.ts │ │ ├── index.ts │ │ └── interface.ts │ ├── authentication │ │ ├── OTP.test.ts │ │ ├── OTP.ts │ │ ├── Session.test.ts │ │ ├── Session.ts │ │ ├── defaultAuthentication.ts │ │ ├── index.ts │ │ ├── interface.ts │ │ ├── oauth │ │ │ ├── GitHub.test.ts │ │ │ ├── GitHub.ts │ │ │ ├── Google.test.ts │ │ │ ├── Google.ts │ │ │ ├── Oauth2Client.test.ts │ │ │ ├── Oauth2Client.ts │ │ │ ├── index.ts │ │ │ ├── utils.test.ts │ │ │ └── utils.ts │ │ ├── providers │ │ │ ├── EmailOTP.test.ts │ │ │ ├── EmailOTP.ts │ │ │ ├── EmailPassword.test.ts │ │ │ ├── EmailPassword.ts │ │ │ ├── EmailPasswordSRP.test.ts │ │ │ ├── EmailPasswordSRP.ts │ │ │ ├── GitHub.ts │ │ │ ├── Google.ts │ │ │ ├── OAuth.test.ts │ │ │ ├── OAuth.ts │ │ │ ├── PhonePassword.test.ts │ │ │ ├── PhonePassword.ts │ │ │ └── index.ts │ │ ├── resolvers │ │ │ ├── refreshResolver.test.ts │ │ │ ├── refreshResolver.ts │ │ │ ├── signInWithResolver.test.ts │ │ │ ├── signInWithResolver.ts │ │ │ ├── signOutResolver.test.ts │ │ │ ├── signOutResolver.ts │ │ │ ├── signUpWithResolver.test.ts │ │ │ ├── signUpWithResolver.ts │ │ │ ├── verifyChallenge.test.ts │ │ │ └── verifyChallenge.ts │ │ ├── roles.test.ts │ │ ├── roles.ts │ │ ├── utils.test.ts │ │ └── utils.ts │ ├── cache │ │ ├── InMemoryCache.test.ts │ │ └── InMemoryCache.ts │ ├── cron │ │ ├── index.test.ts │ │ └── index.ts │ ├── database │ │ ├── DatabaseController.test.ts │ │ ├── DatabaseController.ts │ │ ├── index.test.ts │ │ ├── index.ts │ │ └── interface.ts │ ├── email │ │ ├── DevAdapter.ts │ │ ├── EmailController.test.ts │ │ ├── EmailController.ts │ │ ├── index.ts │ │ ├── interface.ts │ │ └── templates │ │ │ └── sendOtpCode.ts │ ├── files │ │ ├── FileController.ts │ │ ├── FileDevAdapter.ts │ │ ├── hookDeleteFile.ts │ │ ├── hookReadFile.ts │ │ ├── hookUploadFile.ts │ │ ├── index.test.ts │ │ ├── index.ts │ │ └── interface.ts │ ├── graphql │ │ ├── GraphQLSchema.test.ts │ │ ├── GraphQLSchema.ts │ │ ├── index.ts │ │ ├── parseGraphqlSchema.ts │ │ ├── parser.test.ts │ │ ├── parser.ts │ │ ├── pointerAndRelationFunction.ts │ │ ├── resolvers.ts │ │ ├── tests │ │ │ ├── aggregation.test.ts │ │ │ ├── e2e.test.ts │ │ │ └── scalars.test.ts │ │ └── types.ts │ ├── hooks │ │ ├── HookObject.test.ts │ │ ├── HookObject.ts │ │ ├── authentication.test.ts │ │ ├── authentication.ts │ │ ├── defaultFields.test.ts │ │ ├── defaultFields.ts │ │ ├── deleteSession.test.ts │ │ ├── deleteSession.ts │ │ ├── index.test.ts │ │ ├── index.ts │ │ ├── permissions.test.ts │ │ ├── permissions.ts │ │ ├── protected.test.ts │ │ ├── protected.ts │ │ ├── searchableFields.test.ts │ │ ├── searchableFields.ts │ │ ├── session.test.ts │ │ ├── session.ts │ │ ├── setEmail.test.ts │ │ ├── setEmail.ts │ │ ├── setupAcl.test.ts │ │ └── setupAcl.ts │ ├── index.ts │ ├── payment │ │ ├── DevAdapter.ts │ │ ├── PaymentController.test.ts │ │ ├── PaymentController.ts │ │ ├── index.ts │ │ └── interface.ts │ ├── schema │ │ ├── Schema.test.ts │ │ ├── Schema.ts │ │ ├── defaultResolvers.ts │ │ ├── index.ts │ │ └── resolvers │ │ │ ├── meResolver.test.ts │ │ │ ├── meResolver.ts │ │ │ ├── newFile.ts │ │ │ ├── resetPassword.test.ts │ │ │ ├── resetPassword.ts │ │ │ ├── sendEmail.test.ts │ │ │ ├── sendEmail.ts │ │ │ ├── sendOtpCode.test.ts │ │ │ └── sendOtpCode.ts │ ├── security.test.ts │ ├── server │ │ ├── defaultHandlers.ts │ │ ├── generateCodegen.ts │ │ ├── index.test.ts │ │ ├── index.ts │ │ ├── interface.ts │ │ └── routes │ │ │ ├── authHandler.ts │ │ │ └── index.ts │ └── utils │ │ ├── export.ts │ │ ├── helper.ts │ │ ├── index.test.ts │ │ ├── index.ts │ │ ├── preload.ts │ │ └── testHelper.ts │ └── tsconfig.json └── tsconfig.json /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Additional context** 20 | Add any other context about the problem here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | ## **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | ## **Additional context** 17 | Add any other context or screenshots about the feature request here (code example). 18 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci checks 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | branches: 7 | - '**' 8 | types: [opened, synchronize, reopened, unlabeled] 9 | paths: 10 | - '**' 11 | 12 | concurrency: 13 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | test: 18 | timeout-minutes: 10 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - name: Set up Docker Buildx 24 | uses: docker/setup-buildx-action@v3 25 | - name: Install Docker 26 | run: sudo apt-get update && sudo apt-get install -y docker-ce-cli 27 | 28 | - uses: oven-sh/setup-bun@v2 29 | with: 30 | bun-version: latest 31 | 32 | - run: bun install 33 | - run: bun run build 34 | - run: bun ci 35 | -------------------------------------------------------------------------------- /.github/workflows/conventional-pr.yml: -------------------------------------------------------------------------------- 1 | name: 'Conventional PR' 2 | 3 | on: 4 | pull_request: 5 | types: 6 | - opened 7 | - edited 8 | - synchronize 9 | 10 | permissions: 11 | pull-requests: read 12 | 13 | jobs: 14 | main: 15 | name: Validate PR title 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: amannn/action-semantic-pull-request@v5 19 | with: 20 | requireScope: true 21 | env: 22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | /.next/ 4 | /out/ 5 | /build 6 | .DS_Store 7 | *.pem 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | .env.local 12 | .env.development.local 13 | .env.test.local 14 | .env.production.local 15 | .vercel 16 | **/*.trace 17 | **/*.zip 18 | **/*.tar.gz 19 | **/*.tgz 20 | **/*.log 21 | package-lock.json 22 | **/*.bun 23 | .zed 24 | 25 | 26 | cache 27 | bucket 28 | .nuxt 29 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | logs 2 | .cache 3 | node_modules/ 4 | .npm 5 | .env 6 | .env.development.local 7 | .env.test.local 8 | .env.production.local 9 | .env.local 10 | 11 | cache 12 | build 13 | lib 14 | src 15 | tests 16 | test 17 | CONTRIBUTING.md 18 | CODE_OF_CONDUCT.md 19 | CHANGELOG.md 20 | tsconfig.json 21 | .git 22 | bun.lockb 23 | dev 24 | fixtures 25 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 2 | 3 | Contributions are welcome! Here's how you can help: 4 | 5 | - **Report a bug**: If you find a bug, please open an issue. 6 | - **Request a feature**: If you have an idea for a feature, please open an issue. 7 | - **Create a pull request**: If you can fix a bug or implement a feature, please create a pull request (I promise a quick review). 8 | - **Use Wabe**: The best way to contribute is to use Wabe for your backend. 9 | 10 | Note: Each code contribution must be tested either by an existing test or a new one. 11 | 12 | ## Note about new PR 13 | 14 | First of all, thank you for taking the time to improve Wabe. Wabe has a great test coverage, to keep this code quality, please add tests that cover your changes 🙂. 15 | 16 | ## Requirement 17 | 18 | Wabe supports two types of databases: MongoDB and PostgreSQL. Since PostgreSQL is faster, it is the one we use in our tests. To run the tests, you need to have Docker installed and running on your machine. The launch scripts will take care of downloading the PostgreSQL image and creating a container before running the tests. More information can be found in the `wabe-postgres-launcher` or `wabe-mongodb-launcher` packages. 19 | 20 | ## Install 21 | 22 | Wabe uses Bun, so you need the latest version of Bun. You can see [here](https://bun.sh/docs/installation) if Bun is not installed on your machine. 23 | 24 | Wabe uses a monorepo organization, all the packages are under the `packages` directory. 25 | 26 | Once you have cloned the repository you can run the following command at the root of the project. 27 | 28 | ```sh 29 | bun install 30 | ``` 31 | 32 | You can run the tests in all packages by running the following commands at the root repository: 33 | 34 | ```sh 35 | cd packages/wabe 36 | bun dev # Run server and create all codegen 37 | 38 | bun test # Run test on wabe package 39 | # or 40 | bun ci # Run lint + test on package 41 | ``` 42 | 43 | ## Pre-commit 44 | 45 | Before any commit a pre-commit command that will run on your machine to ensure that the code is correctly formatted and the lint is respected. If you have any error of formatting during the pre-commit you can simply run the following command (at the root of the repository): 46 | 47 | Wabe repository also uses the conventional commits to ensure consistence and facilitate the release. Your PRs and your commits need to follow this convention. You can see here to see more information about [Conventional commits](https://www.conventionalcommits.org/en/v1.0.0/). 48 | 49 | ```sh 50 | bun format 51 | ``` 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
4 | 5 |15 | The SaaS boilerplate with NextJS focus on quality, efficiency and 16 | security to build powerful SaaS applications. 17 |
18 | 19 |11 | Read the latest news and updates from the team. 12 |
13 |31 | Wabe powered{' '} 32 | 33 | ShipMySaaS 34 | {' '} 35 | ! 36 |
37 |38 | Wabe is powered by{' '} 39 | 40 | Bun 41 | {' '} 42 | ! 43 |
44 |24 | Skip the hassle of backend development and focus on what truly 25 | matters your product. With just a few lines of code, get instant 26 | access to a powerful, scalable, and secure{' '} 27 | backend. 28 |
29 |53 | 💡 Stop wasting time. Get started in seconds and scale 54 | effortlessly! 55 |
56 |