├── all.md
├── www
├── README.md
├── test.ts
├── global.d.ts
├── docs
│ ├── coming-soon.md
│ ├── bridge
│ │ ├── examples
│ │ │ ├── basic.md
│ │ │ ├── medium.md
│ │ │ └── advanced.md
│ │ ├── socket.md
│ │ ├── adapters
│ │ │ ├── fastify.md
│ │ │ ├── http.md
│ │ │ └── express.md
│ │ ├── launch_server
│ │ │ ├── fastify.md
│ │ │ ├── node-http.md
│ │ │ ├── express.md
│ │ │ └── express copy 3.md
│ │ ├── automatic_documentation.md
│ │ ├── client_code.md
│ │ ├── handler.md
│ │ ├── server.md
│ │ ├── files.md
│ │ ├── server_calls.md
│ │ ├── middlewares.md
│ │ ├── routes.md
│ │ └── data_validation.md
│ ├── bridge-client
│ │ ├── dart
│ │ │ └── coming-soon.md
│ │ ├── kotlin
│ │ │ └── coming-soon.md
│ │ ├── python
│ │ │ └── coming-soon.md
│ │ ├── swift
│ │ │ └── coming-soon.md
│ │ ├── kotlin.md
│ │ ├── python.md
│ │ ├── swift.md
│ │ ├── dart.md
│ │ └── typescript
│ │ │ ├── fetch.md
│ │ │ └── how-to-use.md
│ ├── compilation.md
│ ├── documentation.md
│ ├── introduction.md
│ ├── bridge-studio.md
│ ├── examples
│ │ └── example.md
│ └── typescript-sdk.md
├── static
│ ├── img
│ │ ├── bg.png
│ │ ├── doc.png
│ │ ├── globe.png
│ │ ├── favicon.ico
│ │ ├── bg-lines.png
│ │ ├── dashboard.png
│ │ ├── logo_b.svg
│ │ ├── logo_w.svg
│ │ ├── logo_w_round.svg
│ │ ├── logo_b_round.svg
│ │ └── globe.svg
│ ├── favicon.png
│ ├── twitter.png
│ └── studio
│ │ ├── studio-header.png
│ │ ├── tests
│ │ └── bg-main.png
│ │ ├── dots.svg
│ │ ├── send.svg
│ │ ├── speed.svg
│ │ ├── fetch-danger.svg
│ │ ├── customcard.svg
│ │ ├── documentation-logo.svg
│ │ ├── receive.svg
│ │ ├── lights.svg
│ │ └── sdk-icon.svg
├── babel.config.js
├── src
│ ├── pages
│ │ ├── ok.tsx
│ │ ├── markdown-page.md
│ │ └── index.module.css
│ ├── components
│ │ ├── Layout.tsx
│ │ ├── HomepageFeatures
│ │ │ ├── styles.module.css
│ │ │ └── index.tsx
│ │ └── Newsletter.tsx
│ ├── analytics
│ │ └── mixpanel.ts
│ └── theme
│ │ └── Layout
│ │ └── index.js
├── tsconfig.json
├── .gitignore
├── blog
│ ├── authors.yml
│ └── trpc.mdx
├── docusaurus.preferredTheme.js
├── package.json
└── tailwind.config.js
├── examples
├── bridge-mongodb-boilerplate
│ ├── src
│ │ ├── models
│ │ │ ├── index.ts
│ │ │ └── user.ts
│ │ ├── config
│ │ │ ├── index.ts
│ │ │ └── api.ts
│ │ ├── routes.ts
│ │ ├── errorHandler.ts
│ │ └── index.ts
│ ├── bridge.config.json
│ ├── .prettierignore
│ ├── sdk
│ │ ├── index.ts
│ │ ├── hey.ts
│ │ └── bridgeFetchMethod.ts
│ ├── .prettierrc.json
│ ├── JSONType.json
│ ├── nodemon.json
│ ├── .env.example
│ ├── .gitignore
│ ├── .eslintrc.js
│ ├── package.json
│ └── openapi.json
├── minimal-express
│ ├── bridge.config.json
│ ├── .prettierignore
│ ├── .gitignore
│ ├── sdk
│ │ ├── index.ts
│ │ ├── hello.ts
│ │ └── bridgeFetchMethod.ts
│ ├── .prettierrc.json
│ ├── JSONType.json
│ ├── index.ts
│ ├── package.json
│ └── openapi.json
├── minimal-http
│ ├── bridge.config.json
│ ├── .gitignore
│ ├── sdk
│ │ ├── index.ts
│ │ ├── hello.ts
│ │ └── bridgeFetchMethod.ts
│ ├── JSONType.json
│ ├── index.ts
│ ├── package.json
│ └── openapi.json
└── comparizon
│ ├── .gitignore
│ ├── express.ts
│ └── package.json
├── .prettierignore
├── packages
├── bridge
│ ├── source
│ │ ├── server
│ │ │ ├── adapters
│ │ │ │ ├── serverless.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── express.ts
│ │ │ ├── index.ts
│ │ │ └── http-transormers
│ │ │ │ ├── index.ts
│ │ │ │ ├── query-json.ts
│ │ │ │ ├── body-json.ts
│ │ │ │ └── formidable-async.ts
│ │ ├── routes
│ │ │ ├── index.ts
│ │ │ ├── convert.ts
│ │ │ ├── method.ts
│ │ │ └── types.ts
│ │ ├── utilities
│ │ │ ├── index.ts
│ │ │ ├── apply.ts
│ │ │ ├── dirExists.ts
│ │ │ ├── formidable.ts
│ │ │ └── types.ts
│ │ ├── core
│ │ │ ├── handlers
│ │ │ │ ├── index.ts
│ │ │ │ ├── resolver.ts
│ │ │ │ ├── middleware.ts
│ │ │ │ ├── file-validator.ts
│ │ │ │ ├── data-validator.ts
│ │ │ │ └── bridge.ts
│ │ │ ├── index.ts
│ │ │ └── handler.ts
│ │ ├── error
│ │ │ ├── listener.ts
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ └── bridge.ts
│ ├── .gitignore
│ ├── package.json
│ └── test.ts
├── bridge-compile
│ ├── .gitignore
│ ├── .prettierignore
│ ├── README.md
│ ├── bin
│ │ ├── utils
│ │ │ ├── sleep.ts
│ │ │ ├── index.ts
│ │ │ ├── methods.ts
│ │ │ ├── run-command.ts
│ │ │ ├── fsAsync.ts
│ │ │ └── statusCode.ts
│ │ ├── sdk-compilers
│ │ │ ├── index.ts
│ │ │ ├── typescript
│ │ │ │ ├── compilers
│ │ │ │ │ ├── index-import-file-compiler.ts
│ │ │ │ │ ├── fetch-file-compiler.ts
│ │ │ │ │ └── handler-file-compiler.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── json-type-to-ts-interface.ts
│ │ │ │ └── write-handlers-file.ts
│ │ │ └── utils.ts
│ │ └── parser
│ │ │ ├── ts-parser
│ │ │ ├── utils.ts
│ │ │ ├── recursive-checker.ts
│ │ │ └── index.ts
│ │ │ ├── remove-added-code.ts
│ │ │ ├── extract-zip.ts
│ │ │ └── find-source-file.ts
│ ├── .prettierrc.json
│ └── package.json
├── bridge-studio
│ ├── .gitignore
│ ├── README.md
│ ├── sdk
│ │ ├── hello.ts
│ │ ├── user
│ │ │ ├── logout.ts
│ │ │ ├── signinWithPassword.ts
│ │ │ ├── deleteMyAccount.ts
│ │ │ ├── updateMyPassword.ts
│ │ │ ├── isEmailInUse.ts
│ │ │ ├── refreshToken.ts
│ │ │ ├── updateForgottenPassword.ts
│ │ │ └── getMe.ts
│ │ ├── confirmation
│ │ │ └── getCodeByEmail.ts
│ │ ├── deploy
│ │ │ ├── typescript-sdk
│ │ │ │ └── get.ts
│ │ │ └── getLast.ts
│ │ ├── github
│ │ │ ├── getMyConnectedAccounts.ts
│ │ │ ├── getReposWithTS.ts
│ │ │ └── subscribeRepoToBridge.ts
│ │ ├── project
│ │ │ ├── createProjectFromCLI.ts
│ │ │ ├── getFromCLI.ts
│ │ │ ├── get.ts
│ │ │ ├── update.ts
│ │ │ ├── compileWithCommandLine.ts
│ │ │ ├── getMine.ts
│ │ │ └── reCompile.ts
│ │ ├── bridgeFetchMethod.ts
│ │ └── index.ts
│ └── package.json
├── create-bridge-app
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ └── bin
│ │ ├── renameSync.ts
│ │ └── index.ts
├── fetch-bridge-sdk
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ └── bin
│ │ └── index.ts
└── bridge-react-query
│ ├── README.md
│ ├── .gitignore
│ ├── package.json
│ └── source
│ └── index.ts
├── .prettierrc.json
├── .vscode
├── extensions.json
└── settings.json
├── nodemon.json
├── .gitignore
├── .eslintrc.js
└── LICENSE
/all.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/www/README.md:
--------------------------------------------------------------------------------
1 | Docusaurus
2 |
--------------------------------------------------------------------------------
/www/test.ts:
--------------------------------------------------------------------------------
1 | import { API } from 'sdk';
2 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/src/models/index.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | coverage
3 | dist
4 | build
5 | public
--------------------------------------------------------------------------------
/packages/bridge/source/server/adapters/serverless.ts:
--------------------------------------------------------------------------------
1 | // Coming soon
2 |
--------------------------------------------------------------------------------
/packages/bridge/source/server/index.ts:
--------------------------------------------------------------------------------
1 | export * from './adapters';
2 |
--------------------------------------------------------------------------------
/www/global.d.ts:
--------------------------------------------------------------------------------
1 | declare module '@docusaurus/plugin-content-docs/client';
2 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/src/config/index.ts:
--------------------------------------------------------------------------------
1 | export * from './api';
2 |
--------------------------------------------------------------------------------
/examples/minimal-express/bridge.config.json:
--------------------------------------------------------------------------------
1 | { "serverUrl": "http://localhost:8080" }
2 |
--------------------------------------------------------------------------------
/examples/minimal-http/bridge.config.json:
--------------------------------------------------------------------------------
1 | { "serverUrl": "http://localhost:8080" }
2 |
--------------------------------------------------------------------------------
/examples/comparizon/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /dist
3 | package-lock.json
4 | pnpm-lock.yaml
--------------------------------------------------------------------------------
/examples/minimal-express/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | coverage
3 | dist
4 | build
5 | public
--------------------------------------------------------------------------------
/examples/minimal-http/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /dist
3 | package-lock.json
4 | pnpm-lock.yaml
--------------------------------------------------------------------------------
/packages/bridge-compile/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /dist
3 | package-lock.json
4 | pnpm-lock.yaml
--------------------------------------------------------------------------------
/packages/bridge-compile/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | coverage
3 | dist
4 | build
5 | public
--------------------------------------------------------------------------------
/packages/bridge-studio/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /dist
3 | package-lock.json
4 | pnpm-lock.yaml
--------------------------------------------------------------------------------
/packages/bridge/source/routes/index.ts:
--------------------------------------------------------------------------------
1 | export * from './types';
2 | export * from './convert';
3 |
--------------------------------------------------------------------------------
/www/docs/coming-soon.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Coming Soon'
3 | ---
4 |
5 | # Coming Soon
6 |
--------------------------------------------------------------------------------
/www/static/img/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridge-codes/bridge/HEAD/www/static/img/bg.png
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/bridge.config.json:
--------------------------------------------------------------------------------
1 | { "serverUrl": "http://localhost:8080" }
2 |
--------------------------------------------------------------------------------
/examples/minimal-express/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /dist
3 | package-lock.json
4 | pnpm-lock.yaml
--------------------------------------------------------------------------------
/packages/create-bridge-app/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /dist
3 | package-lock.json
4 | pnpm-lock.yaml
--------------------------------------------------------------------------------
/packages/fetch-bridge-sdk/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /dist
3 | package-lock.json
4 | pnpm-lock.yaml
--------------------------------------------------------------------------------
/www/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridge-codes/bridge/HEAD/www/static/favicon.png
--------------------------------------------------------------------------------
/www/static/img/doc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridge-codes/bridge/HEAD/www/static/img/doc.png
--------------------------------------------------------------------------------
/www/static/img/globe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridge-codes/bridge/HEAD/www/static/img/globe.png
--------------------------------------------------------------------------------
/www/static/twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridge-codes/bridge/HEAD/www/static/twitter.png
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | coverage
3 | dist
4 | build
5 | public
--------------------------------------------------------------------------------
/www/static/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridge-codes/bridge/HEAD/www/static/img/favicon.ico
--------------------------------------------------------------------------------
/packages/bridge-react-query/README.md:
--------------------------------------------------------------------------------
1 | # Bridge React Query
2 |
3 | Bridge between react-query and bridge-sdk
4 |
--------------------------------------------------------------------------------
/packages/bridge/source/server/adapters/index.ts:
--------------------------------------------------------------------------------
1 | export * from './express';
2 | export * from './node-http';
3 |
--------------------------------------------------------------------------------
/www/docs/bridge/examples/basic.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Basic Example'
3 | ---
4 |
5 | # Basic Example
6 |
--------------------------------------------------------------------------------
/www/docs/bridge/examples/medium.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Medium Example'
3 | ---
4 |
5 | # Medium Example
6 |
--------------------------------------------------------------------------------
/www/docs/bridge/socket.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Socket'
3 | ---
4 |
5 | # Socket
6 |
7 | Coming soon...
8 |
--------------------------------------------------------------------------------
/www/static/img/bg-lines.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridge-codes/bridge/HEAD/www/static/img/bg-lines.png
--------------------------------------------------------------------------------
/www/static/img/dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridge-codes/bridge/HEAD/www/static/img/dashboard.png
--------------------------------------------------------------------------------
/examples/minimal-express/sdk/index.ts:
--------------------------------------------------------------------------------
1 | import hello from './/hello';
2 |
3 | export const API = { hello: hello };
4 |
--------------------------------------------------------------------------------
/examples/minimal-http/sdk/index.ts:
--------------------------------------------------------------------------------
1 | import hello from './/hello';
2 |
3 | export const API = { hello: hello };
4 |
--------------------------------------------------------------------------------
/www/docs/bridge-client/dart/coming-soon.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Coming Soon'
3 | ---
4 |
5 | # Coming Soon
6 |
--------------------------------------------------------------------------------
/www/docs/bridge-client/kotlin/coming-soon.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Coming Soon'
3 | ---
4 |
5 | # Coming Soon
6 |
--------------------------------------------------------------------------------
/www/docs/bridge-client/python/coming-soon.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Coming Soon'
3 | ---
4 |
5 | # Coming Soon
6 |
--------------------------------------------------------------------------------
/www/docs/bridge-client/swift/coming-soon.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Coming Soon'
3 | ---
4 |
5 | # Coming Soon
6 |
--------------------------------------------------------------------------------
/www/docs/bridge/examples/advanced.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Advanced Example'
3 | ---
4 |
5 | # Advanced Example
6 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/sdk/index.ts:
--------------------------------------------------------------------------------
1 | import hey from './/hey';
2 |
3 | export const API = { hey: hey };
4 |
--------------------------------------------------------------------------------
/www/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
3 | };
4 |
--------------------------------------------------------------------------------
/www/docs/bridge/adapters/fastify.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Fastify'
3 | ---
4 |
5 | # Fastify
6 |
7 | Coming soon...
8 |
--------------------------------------------------------------------------------
/packages/bridge-studio/README.md:
--------------------------------------------------------------------------------
1 | # Bridge Studio
2 |
3 | Compile a completely typed sdk of your Bridge project with one command.
--------------------------------------------------------------------------------
/www/src/pages/ok.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export default function Page() {
4 | return(
)
5 | }
6 |
--------------------------------------------------------------------------------
/www/static/studio/studio-header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridge-codes/bridge/HEAD/www/static/studio/studio-header.png
--------------------------------------------------------------------------------
/www/static/studio/tests/bg-main.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bridge-codes/bridge/HEAD/www/static/studio/tests/bg-main.png
--------------------------------------------------------------------------------
/packages/bridge-compile/README.md:
--------------------------------------------------------------------------------
1 | # Bridge Studio
2 |
3 | Compile a completely typed sdk of your Bridge project with one command.
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "printWidth": 100,
4 | "trailingComma": "all",
5 | "endOfLine": "auto"
6 | }
7 |
--------------------------------------------------------------------------------
/www/docs/bridge/launch_server/fastify.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'With Fastify'
3 | ---
4 |
5 | # With Fastify
6 |
7 | Coming soon...
8 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/utils/sleep.ts:
--------------------------------------------------------------------------------
1 | export const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
2 | //
3 |
--------------------------------------------------------------------------------
/examples/minimal-express/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "printWidth": 100,
4 | "trailingComma": "all",
5 | "endOfLine": "auto"
6 | }
7 |
--------------------------------------------------------------------------------
/packages/bridge/source/server/http-transormers/index.ts:
--------------------------------------------------------------------------------
1 | export * from './body-json';
2 | export * from './query-json';
3 | export * from './formidable-async';
4 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/src/routes.ts:
--------------------------------------------------------------------------------
1 | import { handler } from 'bridge';
2 |
3 | export default {
4 | hey: handler({ resolve: () => 'hey' }),
5 | };
6 |
--------------------------------------------------------------------------------
/packages/bridge-compile/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "singleQuote": true,
4 | "printWidth": 120,
5 | "trailingComma": "es5",
6 | "endOfLine": "auto"
7 | }
8 |
--------------------------------------------------------------------------------
/packages/bridge/source/utilities/index.ts:
--------------------------------------------------------------------------------
1 | export * from './types';
2 | export * from './apply';
3 | export * from './formidable';
4 | export * from './dirExists';
5 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "printWidth": 125,
4 | "trailingComma": "es5",
5 | "endOfLine": "auto"
6 | }
7 |
--------------------------------------------------------------------------------
/www/src/pages/markdown-page.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Markdown page example
3 | ---
4 |
5 | # Markdown page example
6 |
7 | You don't need React to write simple standalone pages.
8 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/sdk-compilers/index.ts:
--------------------------------------------------------------------------------
1 | // REFACTO WITH CLASS AND INHERITANCE
2 | import compileTypescriptSDK from './typescript';
3 |
4 | export { compileTypescriptSDK };
5 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './fsAsync';
2 | export * from './sleep';
3 | export * from './run-command';
4 | export * from './statusCode';
5 | export * from './methods';
6 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "yzhang.markdown-all-in-one",
4 | "esbenp.prettier-vscode",
5 | "dbaeumer.vscode-eslint",
6 | "bungcip.better-toml"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/packages/bridge/source/core/handlers/index.ts:
--------------------------------------------------------------------------------
1 | export * from './bridge';
2 | export * from './data-validator';
3 | export * from './file-validator';
4 | export * from './middleware';
5 | export * from './resolver';
6 |
--------------------------------------------------------------------------------
/www/src/components/Layout.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export const Layout = (props) => {
4 | console.log("layout")
5 | return (
6 | {props.children}
7 | )
8 | }
9 |
--------------------------------------------------------------------------------
/www/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | // This file is not used in compilation. It is here just for a nice editor experience.
3 | "extends": "@tsconfig/docusaurus/tsconfig.json",
4 | "compilerOptions": {
5 | "baseUrl": "."
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/www/src/components/HomepageFeatures/styles.module.css:
--------------------------------------------------------------------------------
1 | .features {
2 | display: flex;
3 | align-items: center;
4 | padding: 2rem 0;
5 | width: 100%;
6 | }
7 |
8 | .featureSvg {
9 | height: 200px;
10 | width: 200px;
11 | }
12 |
--------------------------------------------------------------------------------
/www/static/studio/dots.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/utils/methods.ts:
--------------------------------------------------------------------------------
1 | export const methodConvertor = {
2 | GET_BRIDGE_METHOD: 'get',
3 | POST_BRIDGE_METHOD: 'post',
4 | PATCH_BRIDGE_METHOD: 'patch',
5 | PUT_BRIDGE_METHOD: 'put',
6 | DELETE_BRIDGE_METHOD: 'delete',
7 | } as const;
8 |
--------------------------------------------------------------------------------
/www/docs/bridge-client/kotlin.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Kotlin (Coming Soon)'
3 | ---
4 |
5 | # Coming Soon
6 |
7 | If you would like your client SDK to be available in a specific language sooner or want to contribute, please contact us [on discord](https://discord.gg/yxjrwm7Bfr).
--------------------------------------------------------------------------------
/www/docs/bridge-client/python.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Python (Coming Soon)'
3 | ---
4 |
5 | # Coming Soon
6 |
7 | If you would like your client SDK to be available in a specific language sooner or want to contribute, please contact us [on discord](https://discord.gg/yxjrwm7Bfr).
--------------------------------------------------------------------------------
/www/docs/bridge-client/swift.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Swift (Coming Soon)'
3 | ---
4 |
5 | # Coming Soon
6 |
7 | If you would like your client SDK to be available in a specific language sooner or want to contribute, please contact us [on discord](https://discord.gg/yxjrwm7Bfr).
--------------------------------------------------------------------------------
/packages/bridge/source/error/listener.ts:
--------------------------------------------------------------------------------
1 | export type ErrorHandler = (p: {
2 | error: { status: number; data?: any; name: string };
3 | path: string;
4 | }) => void;
5 |
6 | type OnError = (p: T) => T;
7 |
8 | export const onError: OnError = (p) => p;
9 |
--------------------------------------------------------------------------------
/packages/bridge/source/index.ts:
--------------------------------------------------------------------------------
1 | export { handler } from './core';
2 | export { httpError, onError, StatusCode, isBridgeError as isError } from './error';
3 | export { apply } from './utilities';
4 | export { initBridge } from './bridge';
5 | export { method } from './routes/method';
6 |
--------------------------------------------------------------------------------
/www/docs/bridge-client/dart.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Dart (Coming Soon)'
3 | ---
4 |
5 | # Coming Soon
6 |
7 | If you would like your client SDK to be available in a specific language sooner or want to contribute, please contact us [on discord](https://discord.gg/yxjrwm7Bfr).
8 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/parser/ts-parser/utils.ts:
--------------------------------------------------------------------------------
1 | import { Type } from 'typescript';
2 |
3 | export function isArrayWithPos(type: Type) {
4 | return type
5 | .getProperties()
6 | .map((p) => p.escapedName)
7 | .some((p) => String(p).startsWith('__@iterator'));
8 | }
9 |
--------------------------------------------------------------------------------
/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "restartable": "rs",
3 | "ignore": [".git", "dist/", "coverage/"],
4 | "watch": ["Lib", "Example"],
5 | "execMap": {
6 | "ts": "node -r ts-node/register"
7 | },
8 | "env": {
9 | "NODE_ENV": "development"
10 | },
11 | "ext": "js,json,ts"
12 | }
13 |
--------------------------------------------------------------------------------
/examples/minimal-http/JSONType.json:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "hello": {
4 | "object": {
5 | "returnBridgeType": {
6 | "data": { "optional": false, "primitive": "string" },
7 | "error": { "union": [] }
8 | }
9 | }
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/src/models/user.ts:
--------------------------------------------------------------------------------
1 | import { Schema } from 'bridge-mongo';
2 |
3 | const userSchema = new Schema(
4 | {
5 | username: { type: String, required: true, unique: true },
6 | age: Number,
7 | password: String,
8 | },
9 | { timestamps: true }
10 | );
11 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/JSONType.json:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "hey": {
4 | "object": {
5 | "returnBridgeType": {
6 | "data": { "optional": false, "primitive": "string" },
7 | "error": { "union": [] }
8 | }
9 | }
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "restartable": "rs",
3 | "ignore": [".git", "dist/", "coverage/"],
4 | "watch": ["src"],
5 | "execMap": {
6 | "ts": "node -r ts-node/register"
7 | },
8 | "env": {
9 | "NODE_ENV": "test"
10 | },
11 | "ext": "js,json,ts"
12 | }
13 |
--------------------------------------------------------------------------------
/www/src/analytics/mixpanel.ts:
--------------------------------------------------------------------------------
1 | import mixpanel from "mixpanel-browser"
2 |
3 | export const track = (name: string, data: any) => {
4 | if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') {
5 | // dev code
6 | } else {
7 | // production code
8 | mixpanel.track(name, data)
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/examples/minimal-http/index.ts:
--------------------------------------------------------------------------------
1 | import { handler, initBridge } from 'bridge';
2 |
3 | const port = 8080;
4 | const routes = { hello: handler({ resolve: () => 'hello' }) };
5 |
6 | const httpServer = initBridge({ routes }).HTTPServer();
7 |
8 | httpServer.listen(port, () => {
9 | console.log(`Listening on port ${port}`);
10 | });
11 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/src/errorHandler.ts:
--------------------------------------------------------------------------------
1 | import { onError } from 'bridge';
2 |
3 | export default onError(({ error, path }) => {
4 | console.log(path, error);
5 | if (error.name === 'Internal server error') {
6 | console.error(path, error);
7 | // Send to bug reporting
8 | } else {
9 | // Normal http errors
10 | }
11 | });
12 |
--------------------------------------------------------------------------------
/examples/minimal-express/JSONType.json:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "hello": {
4 | "object": {
5 | "returnBridgeType": {
6 | "data": {
7 | "optional": false,
8 | "primitive": "string",
9 | "value": "hello"
10 | },
11 | "error": { "union": [] }
12 | }
13 | }
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/packages/bridge/source/core/handlers/resolver.ts:
--------------------------------------------------------------------------------
1 | import { AbstractHandler, Handler, HandlerParams } from '../handler';
2 |
3 | export class Resolver extends AbstractHandler {
4 | public isResolver = true;
5 |
6 | constructor(private resolve: (p: HandlerParams) => any) {
7 | super();
8 | }
9 |
10 | public handle: Handler['handle'] = async (data) => this.resolve(data);
11 | }
12 |
--------------------------------------------------------------------------------
/www/docs/bridge/automatic_documentation.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Documentation Generation'
3 | ---
4 |
5 | # Documentation Generation
6 |
7 | Bridge App allows you to easily create a comprehensive online documentation for your code without any extra effort. Simply join our **[Discord community](https://discord.gg/yxjrwm7Bfr)** to learn more and join the **[Beta](https://discord.gg/yxjrwm7Bfr)**!
8 |
--------------------------------------------------------------------------------
/www/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | /node_modules
3 |
4 | package-lock.json
5 | pnpm-lock.yaml
6 |
7 | # Production
8 | /build
9 |
10 | # Generated files
11 | .docusaurus
12 | .cache-loader
13 |
14 | # Misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
25 | .vercel
26 |
--------------------------------------------------------------------------------
/www/docs/bridge/client_code.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Client Code Generation'
3 | ---
4 |
5 | # Client Code Generation
6 |
7 | Bridge App allows you to easily create a fully typed client code for any frontend langauge with minimal effort. No extra metadata is required. Simply join our **[Discord community](https://discord.gg/yxjrwm7Bfr)** to learn more and join the **[Beta](https://discord.gg/yxjrwm7Bfr)**!
8 |
--------------------------------------------------------------------------------
/examples/minimal-express/index.ts:
--------------------------------------------------------------------------------
1 | import { handler, initBridge } from 'bridge';
2 | import express from 'express';
3 |
4 | const port = 8080;
5 | const routes = { hello: handler({ resolve: () => 'hello' as const }) };
6 |
7 | const app = express();
8 |
9 | app.use('', initBridge({ routes }).expressMiddleware());
10 |
11 | app.listen(port, () => {
12 | console.log(`Listening on port ${port}`);
13 | });
14 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "typescript.tsdk": "node_modules/typescript/lib",
3 | "editor.formatOnSave": true,
4 | // Auto-fix issues with ESLint when you save code changes
5 | "editor.codeActionsOnSave": {
6 | "source.fixAll.eslint": "explicit"
7 | },
8 | "workbench.colorCustomizations": {
9 | "titleBar.activeBackground": "#291b25",
10 | "titleBar.inactiveBackground": "#2a242a"
11 | }
12 | }
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/.env.example:
--------------------------------------------------------------------------------
1 | # ENV EXAMPLE
2 |
3 | ENV=example
4 |
5 | # Project name
6 | PROJECT_NAME=Bridge MongoDB Boilerplate
7 |
8 | # Port number
9 | PORT=8080
10 |
11 | # Mongo DB
12 | MONGODB_URL=mongodb+srv://user:example@user.mongodb.net/example
13 |
14 | # ACCESS TOKEN
15 | JWT_EXPIRATION_TIME=8m
16 | ACCESS_TOKEN_KEY=lygfdYGYnkdgfkuygNOUBYFGiytufd
17 | REFRESH_TOKEN_KEY=KUYgbdjhfbkdsypmioq678sd
--------------------------------------------------------------------------------
/examples/minimal-http/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "minimal-http",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "start": "node ./dist/index.js",
6 | "build": "tsc",
7 | "dev": "ts-node ./index.ts"
8 | },
9 | "dependencies": {
10 | "bridge": "^2.0.45"
11 | },
12 | "devDependencies": {
13 | "@types/node": "^18.11.16",
14 | "ts-node": "^10.9.1",
15 | "typescript": "^4.9.4"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/parser/remove-added-code.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 |
3 | export async function removeAddedCode(absolutePath: string, addedCode: string) {
4 | try {
5 | const data = fs.readFileSync(absolutePath, 'utf-8');
6 | const newData = data.replace(addedCode, '');
7 |
8 | fs.writeFileSync(absolutePath, newData, 'utf-8');
9 | } catch (error) {
10 | console.error(`Error: ${error}`);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/packages/bridge/source/utilities/apply.ts:
--------------------------------------------------------------------------------
1 | import { BridgeHandler } from '../core';
2 | import { UnionToArray } from './types';
3 |
4 | // transform an array into an array as const
5 | type Apply = Record>, T extends Array>(
6 | ...args: T
7 | ) => B extends string ? UnionToArray : UnionToArray;
8 |
9 | export const apply: Apply = (...args) => args as any;
10 |
--------------------------------------------------------------------------------
/examples/comparizon/express.ts:
--------------------------------------------------------------------------------
1 | import express from 'express';
2 |
3 | const port = 8080;
4 |
5 | const app = express();
6 |
7 | app.post('/user', (req, res) => {
8 | const user = req.body;
9 |
10 | if (!user) {
11 | return res.status(400).json({ error: 'No user provided' });
12 | }
13 |
14 | return res.status(201).json(user);
15 | });
16 |
17 | app.listen(port, () => {
18 | console.log(`Listening on port ${port}`);
19 | });
20 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/utils/run-command.ts:
--------------------------------------------------------------------------------
1 | import { exec } from 'child_process';
2 |
3 | export async function runAsyncCommand(command: string): Promise<{ stdout: string; stderr: string }> {
4 | return new Promise((resolve, reject) => {
5 | exec(command, (error, stdout, stderr) => {
6 | if (error) {
7 | reject(error);
8 | } else {
9 | resolve({ stdout, stderr });
10 | }
11 | });
12 | });
13 | }
14 |
--------------------------------------------------------------------------------
/packages/bridge/source/utilities/dirExists.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 |
3 | export function directoryExists(path: string): boolean {
4 | try {
5 | return fs.statSync(path).isDirectory();
6 | } catch (err: any) {
7 | if (err.code === 'ENOENT') {
8 | // The directory does not exist
9 | return false;
10 | } else {
11 | // Something else went wrong
12 | console.error(err);
13 | return false;
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/packages/bridge/source/server/adapters/express.ts:
--------------------------------------------------------------------------------
1 | import { BridgeRoutes } from '../../routes';
2 | import { ErrorHandler } from '../../error';
3 | import type * as express from 'express';
4 |
5 | import { createHttpHandler } from './node-http';
6 |
7 | export const createExpressMiddleware = (
8 | routes: BridgeRoutes,
9 | config?: { errorHandler?: ErrorHandler; formidable?: any; logs?: boolean },
10 | ): express.Handler => createHttpHandler(routes, config);
11 |
--------------------------------------------------------------------------------
/packages/fetch-bridge-sdk/README.md:
--------------------------------------------------------------------------------
1 | # Fetch Bridge SDK
2 |
3 | You can fetch your bridge project sdk with the following commands:
4 |
5 | ```bash
6 | npx fetch-bridge-sdk@latest {username}/{project}
7 | # or
8 | yarn fetch-bridge-sdk {username}/{project}
9 | # or
10 | pnpm fetch-bridge-sdk {username}/{project}
11 | ```
12 |
13 | If you haven't set up a Bridge project or linked it to the Bridge Studio, please visit our website for instructions: https://bridge.codes.
--------------------------------------------------------------------------------
/www/docs/bridge/adapters/http.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'HTTP'
3 | ---
4 |
5 | # HTTP
6 |
7 | **Example**
8 |
9 | ```ts twoslash title='server.ts'
10 | import { initBridge, handler } from 'bridge';
11 |
12 | const hello = handler({
13 | resolve: () => 'hello',
14 | });
15 |
16 | const bridge = initBridge({ routes: { hello } });
17 |
18 | const port = 8080;
19 |
20 | bridge.HTTPServer().listen(port, () => {
21 | `Listening on port ${port}`;
22 | });
23 | ```
24 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/parser/extract-zip.ts:
--------------------------------------------------------------------------------
1 | import AdmZip from 'adm-zip';
2 | import * as os from 'os';
3 |
4 | export const extractZipFromBufferAndGetPath = (zipBuffer: Buffer): string => {
5 | const zipFolder = new AdmZip(zipBuffer);
6 |
7 | const folderName = zipFolder.getEntries()[0].entryName;
8 |
9 | console.log(folderName);
10 |
11 | const tmpDir = os.tmpdir();
12 |
13 | zipFolder.extractAllTo(tmpDir, true);
14 |
15 | return `${tmpDir}/${folderName}`;
16 | };
17 |
--------------------------------------------------------------------------------
/www/src/pages/index.module.css:
--------------------------------------------------------------------------------
1 | /**
2 | * CSS files with the .module.css suffix will be treated as CSS modules
3 | * and scoped locally.
4 | */
5 |
6 | .heroBanner {
7 | padding: 4rem 0;
8 | text-align: center;
9 | position: relative;
10 | overflow: hidden;
11 | }
12 |
13 | @media screen and (max-width: 996px) {
14 | .heroBanner {
15 | padding: 2rem;
16 | }
17 | }
18 |
19 | .buttons {
20 | display: flex;
21 | align-items: center;
22 | justify-content: center;
23 | }
24 |
--------------------------------------------------------------------------------
/www/docs/bridge/launch_server/node-http.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'With Node HTTP'
3 | ---
4 |
5 | # With Node HTTP
6 |
7 | ## Example
8 |
9 |
10 | ```ts twoslash title='server.ts'
11 | import { initBridge, handler } from 'bridge';
12 |
13 | const hello = handler({
14 | resolve: () => 'hello',
15 | });
16 |
17 | const bridge = initBridge({ routes: { hello } });
18 |
19 | const port = 8080;
20 |
21 | bridge.HTTPServer().listen(port, () => {
22 | `Listening on port ${port}`;
23 | });
24 | ```
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /dist
2 | /node_modules
3 |
4 | # Logs
5 | logs
6 | *.log
7 | npm-debug.log*
8 | pnpm-debug.log*
9 | yarn-debug.log*
10 | yarn-error.log*
11 | lerna-debug.log*
12 |
13 | # OS
14 | .DS_Store
15 |
16 | # Tests
17 | /coverage
18 | /.nyc_output
19 |
20 | # IDEs and editors
21 | /.idea
22 | .project
23 | .classpath
24 | .c9/
25 | *.launch
26 | .settings/
27 | *.sublime-workspace
28 |
29 | # IDE - VSCode
30 | .vscode/*
31 | !.vscode/settings.json
32 | !.vscode/tasks.json
33 | !.vscode/launch.json
34 | !.vscode/extensions.json
35 | .vercel
36 |
--------------------------------------------------------------------------------
/www/static/img/logo_b.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/www/static/img/logo_w.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/examples/minimal-express/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "minimal-express",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "start": "node ./dist/index.js",
6 | "build": "tsc",
7 | "dev": "ts-node ./index.ts"
8 | },
9 | "dependencies": {
10 | "axios": "^1.4.0",
11 | "bridge": "^2.0.45",
12 | "express": "^4.18.2",
13 | "form-data": "^4.0.0"
14 | },
15 | "devDependencies": {
16 | "@types/express": "^4.17.15",
17 | "@types/node": "^18.11.16",
18 | "ts-node": "^10.9.1",
19 | "typescript": "^4.9.4"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/packages/bridge/.gitignore:
--------------------------------------------------------------------------------
1 | /dist
2 | /node_modules
3 | pnpm-lock.yaml
4 |
5 | # Logs
6 | logs
7 | *.log
8 | npm-debug.log*
9 | pnpm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 | lerna-debug.log*
13 |
14 | # OS
15 | .DS_Store
16 |
17 | # Tests
18 | /coverage
19 | /.nyc_output
20 |
21 | # IDEs and editors
22 | /.idea
23 | .project
24 | .classpath
25 | .c9/
26 | *.launch
27 | .settings/
28 | *.sublime-workspace
29 |
30 | # IDE - VSCode
31 | .vscode/*
32 | !.vscode/settings.json
33 | !.vscode/tasks.json
34 | !.vscode/launch.json
35 | !.vscode/extensions.json
--------------------------------------------------------------------------------
/www/docs/bridge/adapters/express.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Express'
3 | ---
4 |
5 | # Express
6 |
7 | **Example**
8 |
9 | ```ts twoslash title='server.ts'
10 | import { initBridge, handler } from 'bridge';
11 | import express from 'express';
12 |
13 | const hello = handler({
14 | resolve: () => 'hello',
15 | });
16 |
17 | const bridge = initBridge({ routes: { hello } });
18 |
19 | const port = 8080;
20 |
21 | const app = express();
22 |
23 | app.use('', bridge.expressMiddleware());
24 |
25 | app.listen(port, () => {
26 | `Listening on port ${port}`;
27 | });
28 | ```
29 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/.gitignore:
--------------------------------------------------------------------------------
1 | /dist
2 | /node_modules
3 |
4 | # Logs
5 | logs
6 | *.log
7 | npm-debug.log*
8 | pnpm-debug.log*
9 | yarn-debug.log*
10 | yarn-error.log*
11 | lerna-debug.log*
12 |
13 | # OS
14 | .DS_Store
15 |
16 | # Tests
17 | /coverage
18 | /.nyc_output
19 |
20 | # IDEs and editors
21 | /.idea
22 | .project
23 | .classpath
24 | .c9/
25 | *.launch
26 | .settings/
27 | *.sublime-workspace
28 |
29 | # IDE - VSCode
30 | .vscode/*
31 | !.vscode/settings.json
32 | !.vscode/tasks.json
33 | !.vscode/launch.json
34 | !.vscode/extensions.json
35 | .vercel
36 |
--------------------------------------------------------------------------------
/examples/comparizon/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "comparizon",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "node ./dist/index.js",
8 | "build": "tsc",
9 | "dev": "ts-node ./index.ts"
10 | },
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "bridge": "^2.0.66",
15 | "express": "^4.18.2"
16 | },
17 | "devDependencies": {
18 | "@types/express": "^4.17.17",
19 | "@types/node": "^20.3.1",
20 | "ts-node": "^10.9.1",
21 | "typescript": "^5.1.3"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/hello.ts:
--------------------------------------------------------------------------------
1 | import Fetch from './bridgeFetchMethod';
2 |
3 | export default async (): Promise<
4 | | { data: string; error: null }
5 | | {
6 | data: null;
7 | error:
8 | | { name: 'Axios Error'; status: 400; data: any }
9 | | { name: 'Internal Server Error'; status: 500 };
10 | }
11 | > => {
12 | const res = await Fetch({ method: 'POST', path: '/hello' });
13 |
14 | if (res.error && typeof res.error.status === 'number')
15 | return { data: null, error: res.error };
16 | else return { data: res, error: null };
17 | };
18 |
--------------------------------------------------------------------------------
/packages/bridge/source/server/http-transormers/query-json.ts:
--------------------------------------------------------------------------------
1 | export const getJSONQueryFromURL = (queryUrl: string): Record => {
2 | const queryJSON: Record = {};
3 | try {
4 | if (!queryUrl) return queryJSON;
5 |
6 | const queries = queryUrl.replace('?', '&').split('&');
7 |
8 | queries.forEach((query: string) => {
9 | const [key, value] = query.split('=');
10 | queryJSON[key] = value;
11 | });
12 |
13 | return queryJSON;
14 | } catch (err) {
15 | console.error(err);
16 | return queryJSON;
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/packages/bridge-react-query/.gitignore:
--------------------------------------------------------------------------------
1 | /dist
2 | /node_modules
3 | pnpm-lock.yaml
4 |
5 | # Logs
6 | logs
7 | *.log
8 | npm-debug.log*
9 | pnpm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 | lerna-debug.log*
13 |
14 | # OS
15 | .DS_Store
16 |
17 | # Tests
18 | /coverage
19 | /.nyc_output
20 |
21 | # IDEs and editors
22 | /.idea
23 | .project
24 | .classpath
25 | .c9/
26 | *.launch
27 | .settings/
28 | *.sublime-workspace
29 |
30 | # IDE - VSCode
31 | .vscode/*
32 | !.vscode/settings.json
33 | !.vscode/tasks.json
34 | !.vscode/launch.json
35 | !.vscode/extensions.json
36 |
37 | sdk
--------------------------------------------------------------------------------
/examples/minimal-http/sdk/hello.ts:
--------------------------------------------------------------------------------
1 | import Fetch from './bridgeFetchMethod';
2 |
3 | export default async (): Promise<
4 | | { data: string; error: undefined }
5 | | {
6 | data: undefined;
7 | error:
8 | | { name: 'Axios Error'; status: 400; data: any }
9 | | { name: 'Internal Server Error'; status: 500 };
10 | }
11 | > => {
12 | const res = await Fetch({ method: 'POST', path: '/hello' });
13 |
14 | if (res.error && typeof res.error.status === 'number')
15 | return { data: undefined, error: res.error };
16 | else return { data: res, error: undefined };
17 | };
18 |
--------------------------------------------------------------------------------
/examples/minimal-express/sdk/hello.ts:
--------------------------------------------------------------------------------
1 | import Fetch from './bridgeFetchMethod';
2 |
3 | export default async (): Promise<
4 | | { data: 'hello'; error: undefined }
5 | | {
6 | data: undefined;
7 | error:
8 | | { name: 'Axios Error'; status: 400; data: any }
9 | | { name: 'Internal Server Error'; status: 500 };
10 | }
11 | > => {
12 | const res = await Fetch({ method: 'POST', path: '/hello' });
13 |
14 | if (res.error && typeof res.error.status === 'number')
15 | return { data: undefined, error: res.error };
16 | else return { data: res, error: undefined };
17 | };
18 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/sdk/hey.ts:
--------------------------------------------------------------------------------
1 | import Fetch from './bridgeFetchMethod';
2 |
3 | export default async (): Promise<
4 | | { data: string; error: undefined }
5 | | {
6 | data: undefined;
7 | error:
8 | | { name: 'Axios Error'; status: 400; data: any }
9 | | { name: 'Internal Server Error'; status: 500 };
10 | }
11 | > => {
12 | const res = await Fetch({ method: 'POST', path: '/hey' });
13 |
14 | if (res.error && typeof res.error.status === 'number')
15 | return { data: undefined, error: res.error };
16 | else return { data: res, error: undefined };
17 | };
18 |
--------------------------------------------------------------------------------
/packages/bridge/source/core/index.ts:
--------------------------------------------------------------------------------
1 | import { CreateHandler } from './types';
2 | import { BridgeHandler } from './handlers';
3 |
4 | // This is a BridgeHandler
5 | export const handler: CreateHandler = (routeParams) => {
6 | return new BridgeHandler({
7 | bodySchema: routeParams.body,
8 | querySchema: routeParams.query,
9 | headersSchema: routeParams.headers,
10 | filesConfig: routeParams.files,
11 | middlewares: routeParams.middlewares,
12 | resolve: routeParams.resolve,
13 | });
14 | };
15 |
16 | export * from './types';
17 | export * from './handlers';
18 | export * from './handler';
19 |
--------------------------------------------------------------------------------
/www/static/img/logo_w_round.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/utils/fsAsync.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 |
3 | export const writeFileAsync = (filePath: string, content: string) => {
4 | return new Promise(function (resolve, reject) {
5 | fs.writeFile(filePath, content, function (err) {
6 | if (err) reject(err);
7 | else resolve({ success: true });
8 | });
9 | });
10 | };
11 |
12 | export const mkdirAsync = (folderPath: string) => {
13 | return new Promise(function (resolve, reject) {
14 | fs.mkdir(folderPath, function (err) {
15 | if (err) reject(err);
16 | else resolve({ success: true });
17 | });
18 | });
19 | };
20 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/src/config/api.ts:
--------------------------------------------------------------------------------
1 | import dotenv from 'dotenv';
2 | import path from 'path';
3 |
4 | if (!process.env.MONGODB_URI) dotenv.config({ path: path.join('.env.example') });
5 |
6 | export const api = {
7 | env: process.env.ENV,
8 | projectName: process.env.PROJECT_NAME,
9 | port: parseInt(process.env.PORT || '') || 8080,
10 | jwt: {
11 | expirationTime: process.env.JWT_EXPIRATION_TIME || '8m',
12 | accessTokenKey: process.env.ACCESS_TOKEN_KEY || '',
13 | refreshTokenKey: process.env.REFRESH_TOKEN_KEY || '',
14 | },
15 | mongodb: {
16 | url: process.env.MONGODB_URI,
17 | },
18 | };
19 |
--------------------------------------------------------------------------------
/packages/bridge/source/server/http-transormers/body-json.ts:
--------------------------------------------------------------------------------
1 | import { IncomingMessage } from 'http';
2 |
3 | export const getJSONDataFromRequestStream = (request: IncomingMessage): Promise =>
4 | new Promise((resolve) => {
5 | if (typeof (request as any).body === 'object') resolve((request as any).body);
6 | const chunks: any[] = [];
7 | request.on('data', (chunk) => {
8 | chunks.push(chunk);
9 | });
10 | request.on('end', () => {
11 | try {
12 | resolve(JSON.parse(Buffer.concat(chunks).toString()));
13 | } catch (err) {
14 | resolve(JSON.parse('{}'));
15 | }
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/www/blog/authors.yml:
--------------------------------------------------------------------------------
1 | endi:
2 | name: Endilie Yacop Sucipto
3 | title: Maintainer of Docusaurus
4 | url: https://github.com/endiliey
5 | image_url: https://github.com/endiliey.png
6 |
7 | yangshun:
8 | name: Yangshun Tay
9 | title: Front End Engineer @ Facebook
10 | url: https://github.com/yangshun
11 | image_url: https://github.com/yangshun.png
12 |
13 | slorber:
14 | name: Sébastien Lorber
15 | title: Docusaurus maintainer
16 | url: https://sebastienlorber.com
17 | image_url: https://github.com/slorber.png
18 |
19 | raul:
20 | name: Raul Mihaila
21 | title: Bridge team
22 | image_url: https://avatars.githubusercontent.com/u/67507353?s=40&v=4
23 |
--------------------------------------------------------------------------------
/www/docs/compilation.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Compilation 🚀'
3 | ---
4 |
5 | # Compilation
6 |
7 | Use the following command line to compile your Bridge project:
8 |
9 | ```bash title='terminal'
10 | npx bridge-compile@latest
11 | # or
12 | pnpx bridge-compile@latest
13 | ```
14 |
15 | This command line generates 3 things:
16 | - JSONType.json file
17 | - openapi.json file
18 | - sdk folder
19 |
20 | The JSONType file contains all the types of your project compiled by Bridge. This file was the input to create the openapi specification and to generate the typescript sdk folder. You can develop your own compiler using this file as an input to generate sdk in other languages.
--------------------------------------------------------------------------------
/www/static/img/logo_b_round.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/packages/bridge/source/server/http-transormers/formidable-async.ts:
--------------------------------------------------------------------------------
1 | import { FormidableFile } from '../../utilities';
2 | import { IncomingMessage } from 'http';
3 |
4 | export const formidableAsyncParseFiles = async (
5 | req: IncomingMessage,
6 | formidable: any,
7 | ): Promise<{
8 | [file: string]: FormidableFile | FormidableFile[];
9 | }> => {
10 | let form = formidable({ multiples: true });
11 |
12 | return new Promise((resolve, reject) => {
13 | form.parse(req, function (error: any, fields: any, files: any) {
14 | if (error) {
15 | reject(error);
16 | return;
17 | }
18 |
19 | resolve(files);
20 | });
21 | });
22 | };
23 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/user/logout.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | body: { all: false | true };
5 | headers: { refreshtoken: string };
6 | }): Promise<
7 | | { data: any; error: null }
8 | | {
9 | data: null;
10 | error:
11 | | { name: 'Axios Error'; status: 400; data: any }
12 | | { name: 'Internal Server Error'; status: 500 };
13 | }
14 | > => {
15 | const res = await Fetch({ ...data, method: 'POST', path: '/user/logout' });
16 |
17 | if (res.error && typeof res.error.status === 'number')
18 | return { data: null, error: res.error };
19 | else return { data: res, error: null };
20 | };
21 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/user/signinWithPassword.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | body: { email: string; password: string };
5 | }): Promise<
6 | | { data: any; error: null }
7 | | {
8 | data: null;
9 | error:
10 | | { name: 'Axios Error'; status: 400; data: any }
11 | | { name: 'Internal Server Error'; status: 500 };
12 | }
13 | > => {
14 | const res = await Fetch({
15 | ...data,
16 | method: 'POST',
17 | path: '/user/signinWithPassword',
18 | });
19 |
20 | if (res.error && typeof res.error.status === 'number')
21 | return { data: null, error: res.error };
22 | else return { data: res, error: null };
23 | };
24 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | parserOptions: {
4 | project: 'tsconfig.json',
5 | sourceType: 'module',
6 | },
7 | plugins: ['@typescript-eslint/eslint-plugin'],
8 | extends: ['plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'],
9 | root: true,
10 | env: {
11 | node: true,
12 | jest: true,
13 | },
14 | ignorePatterns: ['.eslintrc.js', 'generated.ts', 'fetchSDK.js'],
15 | rules: {
16 | '@typescript-eslint/interface-name-prefix': 'off',
17 | '@typescript-eslint/explicit-function-return-type': 'off',
18 | '@typescript-eslint/explicit-module-boundary-types': 'off',
19 | '@typescript-eslint/no-explicit-any': 'off',
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/user/deleteMyAccount.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | body: { password: string };
5 | headers: { refreshtoken: string };
6 | }): Promise<
7 | | { data: any; error: null }
8 | | {
9 | data: null;
10 | error:
11 | | { name: 'Axios Error'; status: 400; data: any }
12 | | { name: 'Internal Server Error'; status: 500 };
13 | }
14 | > => {
15 | const res = await Fetch({
16 | ...data,
17 | method: 'POST',
18 | path: '/user/deleteMyAccount',
19 | });
20 |
21 | if (res.error && typeof res.error.status === 'number')
22 | return { data: null, error: res.error };
23 | else return { data: res, error: null };
24 | };
25 |
--------------------------------------------------------------------------------
/packages/bridge/source/error/index.ts:
--------------------------------------------------------------------------------
1 | import { ErrorStatus } from './status';
2 |
3 | interface Error {
4 | name: string;
5 | status: number;
6 | data?: any;
7 | }
8 |
9 | export const isBridgeError = (object: any): object is { error: Error } =>
10 | typeof object === 'object' &&
11 | typeof object.error === 'object' &&
12 | typeof object.error.name === 'string' &&
13 | typeof object.error.status === 'number';
14 |
15 | export const httpError = (
16 | status: Status,
17 | name: Name,
18 | data?: Data,
19 | ): { error: { name: Name; data?: any; status: Status } } => {
20 | return { error: { status, name, data } };
21 | };
22 |
23 | export * from './listener';
24 | export * from './status';
25 |
--------------------------------------------------------------------------------
/www/docs/bridge/launch_server/express.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'With Express'
3 | ---
4 |
5 | # With Express
6 |
7 | ## Install [express](https://www.npmjs.com/package/express)
8 |
9 | ```bash title=terminal
10 | npm i express
11 | npm i --save-dev @types/express
12 | ```
13 |
14 | ## Example
15 |
16 | ```ts twoslash title='server.ts'
17 | import { initBridge, handler } from 'bridge';
18 | import express from 'express';
19 |
20 | const hello = handler({
21 | resolve: () => 'hello',
22 | });
23 |
24 | const bridge = initBridge({ routes: { hello } });
25 |
26 | const port = 8080;
27 |
28 | const app = express();
29 |
30 | app.use('', bridge.expressMiddleware());
31 |
32 | app.listen(port, () => {
33 | `Listening on port ${port}`;
34 | });
35 | ```
36 |
37 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/user/updateMyPassword.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | body: { oldPassword: string; newPassword: string };
5 | headers: { refreshtoken: string };
6 | }): Promise<
7 | | { data: any; error: null }
8 | | {
9 | data: null;
10 | error:
11 | | { name: 'Axios Error'; status: 400; data: any }
12 | | { name: 'Internal Server Error'; status: 500 };
13 | }
14 | > => {
15 | const res = await Fetch({
16 | ...data,
17 | method: 'POST',
18 | path: '/user/updateMyPassword',
19 | });
20 |
21 | if (res.error && typeof res.error.status === 'number')
22 | return { data: null, error: res.error };
23 | else return { data: res, error: null };
24 | };
25 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | parserOptions: {
4 | project: 'tsconfig.json',
5 | sourceType: 'module',
6 | },
7 | plugins: ['@typescript-eslint/eslint-plugin'],
8 | extends: ['plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended'],
9 | root: true,
10 | env: {
11 | node: true,
12 | jest: true,
13 | },
14 | ignorePatterns: ['.eslintrc.js', 'generated.ts', 'fetchSDK.js'],
15 | rules: {
16 | '@typescript-eslint/interface-name-prefix': 'off',
17 | '@typescript-eslint/explicit-function-return-type': 'off',
18 | '@typescript-eslint/explicit-module-boundary-types': 'off',
19 | '@typescript-eslint/no-explicit-any': 'off',
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/user/isEmailInUse.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | query: { email: string };
5 | }): Promise<
6 | | { data: { exists: false | true }; error: null }
7 | | {
8 | data: null;
9 | error:
10 | | { name: 'Query schema validation error'; status: 422; data: any }
11 | | { name: 'Axios Error'; status: 400; data: any }
12 | | { name: 'Internal Server Error'; status: 500 };
13 | }
14 | > => {
15 | const res = await Fetch({
16 | ...data,
17 | method: 'POST',
18 | path: '/user/isEmailInUse',
19 | });
20 |
21 | if (res.error && typeof res.error.status === 'number')
22 | return { data: null, error: res.error };
23 | else return { data: res, error: null };
24 | };
25 |
--------------------------------------------------------------------------------
/packages/bridge/source/core/handlers/middleware.ts:
--------------------------------------------------------------------------------
1 | import { Handler, AbstractHandler } from '../handler';
2 | import { isBridgeError } from '../../error';
3 |
4 | export class MiddelwaresHandler extends AbstractHandler {
5 | constructor(private handlers: ReadonlyArray) {
6 | super();
7 | }
8 |
9 | public handle: Handler['handle'] = async (data) => {
10 | // All the middlewares are executed simultaneously
11 | const results = await Promise.all(this.handlers.map(async (handler) => handler.handle(data)));
12 |
13 | // If one middleware returns an error, we directly return the error to the client
14 | for (const result of results) if (isBridgeError(result)) return result;
15 |
16 | return super.handle({ ...data, middlewares: Object.assign({}, ...results) });
17 | };
18 | }
19 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/confirmation/getCodeByEmail.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | query: { email: string };
5 | }): Promise<
6 | | { data: 'Code sent by email'; error: null }
7 | | {
8 | data: null;
9 | error:
10 | | { name: 'Query schema validation error'; status: 422; data: any }
11 | | { name: 'Axios Error'; status: 400; data: any }
12 | | { name: 'Internal Server Error'; status: 500 };
13 | }
14 | > => {
15 | const res = await Fetch({
16 | ...data,
17 | method: 'POST',
18 | path: '/confirmation/getCodeByEmail',
19 | });
20 |
21 | if (res.error && typeof res.error.status === 'number')
22 | return { data: null, error: res.error };
23 | else return { data: res, error: null };
24 | };
25 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/src/index.ts:
--------------------------------------------------------------------------------
1 | import { initBridge } from 'bridge';
2 | import express from 'express';
3 | import morgan from 'morgan';
4 | import helmet from 'helmet';
5 | import cors from 'cors';
6 | import { api } from './config';
7 | import routes from './routes';
8 | import errorHandler from './errorHandler';
9 |
10 | const app = express();
11 |
12 | app.enable('trust proxy');
13 | app.use(express.static('public'));
14 | app.use(cors());
15 | app.use(morgan('dev'));
16 | app.use(helmet());
17 |
18 | app.get('/', (req, res) => res.send(`Welcome on ${api.projectName}, mode: ${api.env}`));
19 |
20 | const bridge = initBridge({ routes, errorHandler });
21 |
22 | app.use('', bridge.expressMiddleware());
23 |
24 | app.listen(api.port, () => {
25 | console.log(`Listening on port ${api.port}`);
26 | });
27 |
--------------------------------------------------------------------------------
/packages/bridge/source/core/handlers/file-validator.ts:
--------------------------------------------------------------------------------
1 | import { AbstractHandler, Handler } from '../handler';
2 | import { httpError, StatusCode } from '../../error';
3 |
4 | export type FilesConfig = 'any' | ReadonlyArray;
5 |
6 | export class FileValidator extends AbstractHandler {
7 | constructor(private config: FilesConfig) {
8 | super();
9 | }
10 |
11 | public handle: Handler['handle'] = async (data) => {
12 | const missingFiles: string[] = [];
13 |
14 | // req.body contains the files
15 | if (this.config !== 'any')
16 | for (const name of this.config) if (!data.files[name]) missingFiles.push(name);
17 |
18 | if (missingFiles.length > 0)
19 | return httpError(StatusCode.BAD_REQUEST, 'Files schema validation error', {
20 | missingFiles,
21 | });
22 |
23 | return super.handle(data);
24 | };
25 | }
26 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/deploy/typescript-sdk/get.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | query: { project: string; owner: string };
5 | }): Promise<
6 | | { data: string; error: null }
7 | | {
8 | data: null;
9 | error:
10 | | { name: 'Document not found'; data?: any; status: 404 }
11 | | { name: 'Query schema validation error'; status: 422; data: any }
12 | | { name: 'Axios Error'; status: 400; data: any }
13 | | { name: 'Internal Server Error'; status: 500 };
14 | }
15 | > => {
16 | const res = await Fetch({
17 | ...data,
18 | method: 'GET',
19 | path: '/deploy/typescript-sdk',
20 | });
21 |
22 | if (res.error && typeof res.error.status === 'number')
23 | return { data: null, error: res.error };
24 | else return { data: res, error: null };
25 | };
26 |
--------------------------------------------------------------------------------
/www/docs/bridge-client/typescript/fetch.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Fetch your Client SDK'
3 | ---
4 |
5 | # Fetch your Client SDK
6 |
7 | Refer to the [Bridge Studio documentation](../../bridge-studio.md) to learn how to deploy your Bridge API and retrieve your client SDK from Bridge Studio.
8 |
9 | **To deploy your project on Bridge Studio:**
10 | ```bash title='terminal'
11 | npx bridge-studio@latest
12 | ```
13 |
14 | **To fetch the latest typescript client sdk:**
15 | ```bash title='terminal'
16 | npx fetch-bridge-sdk@latest {username}{projectName}
17 | ```
18 |
19 | If you do not have `axios` and `form-data` installed in your project, the command line will automatically install them for you.
20 |
21 | The upcoming version of the command line will allow you to select your preferred HTTP client library, either axios or fetch, and the required packages will be automatically installed if they are not already present in your project.
--------------------------------------------------------------------------------
/www/docs/documentation.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'OpenAPI Documentation'
3 | ---
4 |
5 | # Browse OpenAPI documentation
6 |
7 | After compiling your Bridge project, you can browse the openapi specification generated easily with ExpressJS.
8 |
9 |
10 | ```ts title='server.ts' showLineNumbers
11 | import { handler, initBridge } from 'bridge';
12 | import express from 'express';
13 | import swaggerUi from 'swagger-ui-express';
14 |
15 | const openApiDocumentation = require('./openapi.json');
16 |
17 | const routes = {
18 | hello: handler({
19 | resolve: () => 'Hello World',
20 | }),
21 | };
22 |
23 | const port = 8080;
24 | const app = express();
25 | const bridge = initBridge({ routes });
26 |
27 | app.use('', bridge.expressMiddleware());
28 |
29 | app.use('/docs', swaggerUi.serve, swaggerUi.setup(openApiDocumentation));
30 |
31 | app.listen(port, () => {
32 | console.log(`Listening on port ${port}`);
33 | });
34 | ```
35 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bridge-mongodb-boilerplate",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "build": "tsc",
8 | "start": "node ./dist/src/index.js",
9 | "dev": "clear && nodemon --config nodemon.json ./src/index.ts"
10 | },
11 | "keywords": [],
12 | "author": "Bridge Team ",
13 | "license": "MIT",
14 | "dependencies": {
15 | "bridge": "^2.0.46",
16 | "bridge-mongo": "^1.0.13",
17 | "cors": "^2.8.5",
18 | "dotenv": "^16.0.3",
19 | "express": "^4.18.2",
20 | "helmet": "^6.0.1",
21 | "morgan": "^1.10.0"
22 | },
23 | "devDependencies": {
24 | "@types/cors": "^2.8.13",
25 | "@types/express": "^4.17.17",
26 | "@types/morgan": "^1.9.4",
27 | "@types/node": "^18.14.0",
28 | "nodemon": "^2.0.20",
29 | "ts-node": "^10.9.1",
30 | "typescript": "^4.9.5"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/packages/bridge-react-query/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bridge-react-query",
3 | "version": "1.0.8",
4 | "description": "Bridge between react-query and bridge-sdk",
5 | "author": "Bridge Team ",
6 | "license": "MIT",
7 | "main": "dist/source/index.js",
8 | "types": "dist/source/index.d.ts",
9 | "bugs": "https://github.com/bridge-codes/bridge/issues",
10 | "homepage": "https://bridge.codes",
11 | "files": [
12 | "/dist"
13 | ],
14 | "scripts": {
15 | "build": "tsc",
16 | "publish-minor": "tsc && npm version patch && npm publish"
17 | },
18 | "repository": {
19 | "type": "git",
20 | "url": "git+https://github.com/bridge-codes/bridge.git",
21 | "directory": "packages/bridge-react-query"
22 | },
23 | "keywords": [
24 | "bridge",
25 | "sdk",
26 | "react-query",
27 | "typescript"
28 | ],
29 | "dependencies": {
30 | "@tanstack/react-query": "^4.23.0"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/user/refreshToken.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | headers: { refreshtoken: string };
5 | }): Promise<
6 | | { data: string; error: null }
7 | | {
8 | data: null;
9 | error:
10 | | { name: 'Wrong permission'; data?: any; status: 401 }
11 | | { name: 'Invalid token'; data?: any; status: 401 }
12 | | { name: 'Wrong refreshToken'; data?: any; status: 401 }
13 | | { name: 'Headers schema validation error'; status: 422; data: any }
14 | | { name: 'Axios Error'; status: 400; data: any }
15 | | { name: 'Internal Server Error'; status: 500 };
16 | }
17 | > => {
18 | const res = await Fetch({
19 | ...data,
20 | method: 'POST',
21 | path: '/user/refreshToken',
22 | });
23 |
24 | if (res.error && typeof res.error.status === 'number')
25 | return { data: null, error: res.error };
26 | else return { data: res, error: null };
27 | };
28 |
--------------------------------------------------------------------------------
/www/static/img/globe.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/packages/create-bridge-app/README.md:
--------------------------------------------------------------------------------
1 | # Create Bridge App
2 |
3 | The easiest way to get started with Bridge is by using `create-bridge-app`. This CLI tool enables you to quickly start building a new Bridge application, with everything set up for you.
4 |
5 | ### Interactive
6 |
7 | You can create a new project interactively by running:
8 |
9 | ```bash
10 | npx create-bridge-app@latest
11 | # or
12 | yarn create bridge-app
13 | # or
14 | pnpm create bridge-app
15 | ```
16 |
17 | You will be asked for the name of your project.
18 |
19 | ### Why use Create Bridge App?
20 |
21 | `create-bridge-app` allows you to create a new Bridge app within seconds. It is officially maintained by the creators of Bridge, and includes a number of benefits:
22 |
23 | - **Interactive Experience**: Running `npx create-bridge-app@latest` (with no arguments) launches an interactive experience that guides you through setting up a project.
24 | - **Zero Dependencies**: Initializing a project is as quick as one second. Create Bridge App has zero dependencies.
--------------------------------------------------------------------------------
/packages/bridge/source/core/handler.ts:
--------------------------------------------------------------------------------
1 | type AnyObject = Record;
2 |
3 | /**
4 | * This is the real data received by the client
5 | */
6 | export interface HandlerParams {
7 | body: AnyObject;
8 | query: AnyObject;
9 | headers: AnyObject;
10 | files: AnyObject;
11 | middlewares: AnyObject;
12 | }
13 |
14 | export interface Handler {
15 | setNext(handler: Handler): Handler;
16 |
17 | handle: (p: HandlerParams) => any;
18 |
19 | getNextHandler: () => Handler | undefined;
20 | }
21 |
22 | export abstract class AbstractHandler implements Handler {
23 | protected nextHandler: Handler | undefined;
24 |
25 | public setNext(handler: Handler): Handler {
26 | this.nextHandler = handler;
27 |
28 | return handler;
29 | }
30 |
31 | public async handle(data: HandlerParams) {
32 | if (this.nextHandler) return this.nextHandler.handle(data);
33 | return data;
34 | }
35 |
36 | public getNextHandler = () => this.nextHandler;
37 | }
38 |
39 | export class FirstHandler extends AbstractHandler {}
40 |
--------------------------------------------------------------------------------
/packages/create-bridge-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "create-bridge-app",
3 | "version": "1.0.35",
4 | "description": "Create Bridge-powered Express app with one command",
5 | "author": "Bridge Team ",
6 | "license": "MIT",
7 | "bin": {
8 | "create-bridge-app": "./dist/index.js"
9 | },
10 | "bugs": "https://github.com/bridge-codes/bridge/issues",
11 | "homepage": "https://bridge.codes",
12 | "files": [
13 | "/dist"
14 | ],
15 | "scripts": {
16 | "build": "tsc",
17 | "publish-minor": "tsc && npm version patch && npm publish"
18 | },
19 | "repository": {
20 | "type": "git",
21 | "url": "git+https://github.com/bridge-codes/bridge.git",
22 | "directory": "packages/create-bridge-app"
23 | },
24 | "devDependencies": {
25 | "@types/prettier": "^2.7.1",
26 | "@types/prompts": "^2.4.2",
27 | "ts-node": "^10.9.1",
28 | "typescript": "^4.9.4"
29 | },
30 | "dependencies": {
31 | "prettier": "^2.8.1",
32 | "prompts": "^2.4.2"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/deploy/getLast.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | query: { project: string; owner: string };
5 | }): Promise<
6 | | {
7 | data: {
8 | project: { createdAt: Date; name: string } & { _id: string };
9 | createdAt: Date;
10 | owner: { createdAt: Date; name: string } & { _id: string };
11 | _id: string;
12 | };
13 | error: null;
14 | }
15 | | {
16 | data: null;
17 | error:
18 | | { name: 'Document not found'; data?: any; status: 404 }
19 | | { name: 'Query schema validation error'; status: 422; data: any }
20 | | { name: 'Axios Error'; status: 400; data: any }
21 | | { name: 'Internal Server Error'; status: 500 };
22 | }
23 | > => {
24 | const res = await Fetch({ ...data, method: 'POST', path: '/deploy/getLast' });
25 |
26 | if (res.error && typeof res.error.status === 'number')
27 | return { data: null, error: res.error };
28 | else return { data: res, error: null };
29 | };
30 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/sdk-compilers/typescript/compilers/index-import-file-compiler.ts:
--------------------------------------------------------------------------------
1 | import { BridgeRoutesTree } from '../../utils';
2 |
3 | export const getIndexTSFileContent = (
4 | root: BridgeRoutesTree,
5 | path: string[] = []
6 | ): { importsString: string; exportAPIStringObject: string } => {
7 | let exportAPIStringObject = '{';
8 | let importsString = '';
9 |
10 | for (const [key, value] of Object.entries(root)) {
11 | if (value === 'handler') {
12 | importsString += `import ${path.join('').replaceAll('-', '')}${key} from "./${path.join('/')}/${key}";\n`;
13 | exportAPIStringObject += `${key}: ${path.join('').replaceAll('-', '')}${key},`;
14 | } else {
15 | exportAPIStringObject += `${key.replaceAll('-', '')}:`;
16 | const res = getIndexTSFileContent(value, [...path, key]);
17 | importsString += res.importsString;
18 | exportAPIStringObject += res.exportAPIStringObject;
19 | }
20 | }
21 |
22 | exportAPIStringObject += '},';
23 |
24 | return { importsString, exportAPIStringObject };
25 | };
26 |
--------------------------------------------------------------------------------
/www/docs/bridge/launch_server/express copy 3.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'With Express'
3 | ---
4 |
5 | # Launch your server
6 |
7 | ## With HTTP
8 |
9 | **Example**
10 |
11 | ```ts twoslash title='server.ts'
12 | import { initBridge, handler } from 'bridge';
13 |
14 | const hello = handler({
15 | resolve: () => 'hello',
16 | });
17 |
18 | const bridge = initBridge({ routes: { hello } });
19 |
20 | const port = 8080;
21 |
22 | bridge.HTTPServer().listen(port, () => {
23 | `Listening on port ${port}`;
24 | });
25 | ```
26 |
27 | ## With Express
28 |
29 | **Example**
30 |
31 | ```ts twoslash title='server.ts'
32 | import { initBridge, handler } from 'bridge';
33 | import express from 'express';
34 |
35 | const hello = handler({
36 | resolve: () => 'hello',
37 | });
38 |
39 | const bridge = initBridge({ routes: { hello } });
40 |
41 | const port = 8080;
42 |
43 | const app = express();
44 |
45 | app.use('', bridge.expressMiddleware());
46 |
47 | app.listen(port, () => {
48 | `Listening on port ${port}`;
49 | });
50 | ```
51 |
52 | ## With Fastify
53 |
54 | Coming soon...
55 |
--------------------------------------------------------------------------------
/packages/fetch-bridge-sdk/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fetch-bridge-sdk",
3 | "version": "1.0.12",
4 | "description": "Fetch Bridge SDK with one command",
5 | "author": "Bridge Team ",
6 | "bin": {
7 | "fetch-bridge-sdk": "./dist/index.js"
8 | },
9 | "files": [
10 | "/dist"
11 | ],
12 | "scripts": {
13 | "build": "tsc",
14 | "publish-minor": "tsc && npm version patch && npm publish"
15 | },
16 | "license": "MIT",
17 | "bugs": "https://github.com/bridge-codes/bridge/issues",
18 | "homepage": "https://bridge.codes",
19 | "repository": {
20 | "type": "git",
21 | "url": "git+https://github.com/bridge-codes/bridge.git",
22 | "directory": "packages/fetch-bridge-sdk"
23 | },
24 | "dependencies": {
25 | "adm-zip": "^0.5.10",
26 | "axios": "^1.2.3",
27 | "form-data": "^4.0.0",
28 | "minimist": "^1.2.7",
29 | "prompts": "^2.4.2"
30 | },
31 | "devDependencies": {
32 | "@types/adm-zip": "^0.5.0",
33 | "@types/prompts": "^2.4.2",
34 | "ts-node": "^10.9.1",
35 | "typescript": "^4.9.4"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/www/src/theme/Layout/index.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from 'react';
2 | import Layout from '@theme-original/Layout';
3 | import mixpanel from 'mixpanel-browser';
4 | import { useLocation } from '@docusaurus/router';
5 | import { inject } from "@vercel/analytics"
6 |
7 | import { Analytics } from '@vercel/analytics/react';
8 | export default function LayoutWrapper(props) {
9 | if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') {
10 | // dev code
11 | } else {
12 | // production code
13 | mixpanel.init('0c100fcfe97943ac4ded12a1d1a8cc7f');
14 | }
15 |
16 | const location = useLocation()
17 | // useEffect(() => {
18 | // if (location.pathname.includes('docs')) {
19 | // const element = document.getElementsByClassName("navbar")
20 | // for (let navItem of element) {
21 | // navItem.style.background = "#111111"
22 | // navItem.style.borderBottom = "solid 1px #272727"
23 | // }
24 | // }
25 | // }, [location])
26 |
27 | return (
28 | <>
29 |
30 |
31 | >
32 | );
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/packages/bridge/source/bridge.ts:
--------------------------------------------------------------------------------
1 | import { BridgeRoutes } from './routes';
2 | import { ErrorHandler } from './error';
3 | import { RoutesToBridgeType } from './routes';
4 | import type * as express from 'express';
5 | import { createHttpHandler } from './server/adapters/node-http';
6 | import http from 'http';
7 |
8 | class Bridge {
9 | public bridgeType!: RoutesToBridgeType;
10 |
11 | constructor(
12 | public routes: Routes,
13 | private config: { errorHandler?: ErrorHandler; formidable?: any; logs?: boolean },
14 | ) {}
15 |
16 | public expressMiddleware = (): express.Handler => createHttpHandler(this.routes, this.config);
17 |
18 | public HTTPServer = () => http.createServer(createHttpHandler(this.routes, this.config));
19 | }
20 |
21 | export const initBridge = ({
22 | routes,
23 | errorHandler,
24 | formidable,
25 | logs,
26 | }: {
27 | routes: Routes;
28 | formidable?: any;
29 | errorHandler?: ErrorHandler;
30 | logs?: boolean;
31 | }): Bridge => new Bridge(routes, { formidable, errorHandler, logs });
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Bridge
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/www/static/studio/send.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/www/static/studio/speed.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/www/docs/bridge/handler.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Handler'
3 | ---
4 |
5 | # Handler
6 |
7 | The `handler` is the core concept of Bridge. This function helps you create endpoints and middlewares for your Bridge server.
8 |
9 | ## Resolve Function
10 |
11 | The `resolve` function is the only required parameter of a handler. You can either return a json object, a string or a number with the resolve function. If the function returns void, the client will receive an empty object in response.
12 |
13 | ```ts
14 | import { handler } from 'bridge';
15 |
16 | // Returns the string "Hello World" with an http status code 200
17 | const handler1 = handler({
18 | resolve: () => 'Hello World',
19 | });
20 |
21 | // Returns the number 42 with an http status code 200
22 | const handler2 = handler({
23 | resolve: () => 42,
24 | });
25 |
26 | // Returns the json { name: "John", age: 42 } with an http status code 200
27 | const handler3 = handler({
28 | resolve: () => ({ name: 'John', age: 42 }),
29 | });
30 |
31 | // Returns the empty json {} with an http status code 200
32 | const handler3 = handler({
33 | resolve: () => {
34 | console.log('hello');
35 | },
36 | });
37 | ```
38 |
--------------------------------------------------------------------------------
/www/docusaurus.preferredTheme.js:
--------------------------------------------------------------------------------
1 | import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
2 |
3 | const darkTheme = 'dark';
4 | const lightTheme = 'light';
5 |
6 | // if (!window.location.pathname.includes('docs')) {
7 | // console.log("yes")
8 | // document.querySelector('.navbar').classList.add('navbarE');
9 | // // document.navbar?.style.setProperty('position', 'sticky')
10 | // }
11 |
12 | // if (window.location.pathname.includes('docs')) {
13 | // document.querySelector('.header').style.backgroundColor = '#F7F7F7';
14 | // }
15 |
16 | if (ExecutionEnvironment.canUseDOM) {
17 | const mediaMatch = window.matchMedia('(prefers-color-scheme: dark)');
18 | const htmlElement = document.querySelector('html');
19 |
20 | const setInitialTheme = () => {
21 | const newTheme = mediaMatch.matches ? darkTheme : darkTheme;
22 | htmlElement?.setAttribute('data-theme', newTheme);
23 | };
24 | setInitialTheme();
25 |
26 | const colorSchemeChangeListener = (e) => {
27 | const newTheme = e.matches ? darkTheme : lightTheme;
28 | htmlElement?.setAttribute('data-theme', newTheme);
29 | };
30 | mediaMatch.addEventListener('change', colorSchemeChangeListener);
31 |
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/www/static/studio/fetch-danger.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/user/updateForgottenPassword.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | body: { email: string; password: string };
5 | query: { code: string };
6 | }): Promise<
7 | | { data: { refreshToken: string; accessToken: string }; error: null }
8 | | {
9 | data: null;
10 | error:
11 | | { name: 'Expired code'; data?: any; status: 401 }
12 | | { name: 'Invalid code'; data?: any; status: 401 }
13 | | {
14 | name: 'user not found' | 'admin not found';
15 | data?: any;
16 | status: 404;
17 | }
18 | | { name: 'Body schema validation error'; status: 422; data: any }
19 | | { name: 'Query schema validation error'; status: 422; data: any }
20 | | { name: 'Axios Error'; status: 400; data: any }
21 | | { name: 'Internal Server Error'; status: 500 };
22 | }
23 | > => {
24 | const res = await Fetch({
25 | ...data,
26 | method: 'POST',
27 | path: '/user/updateForgottenPassword',
28 | });
29 |
30 | if (res.error && typeof res.error.status === 'number')
31 | return { data: null, error: res.error };
32 | else return { data: res, error: null };
33 | };
34 |
--------------------------------------------------------------------------------
/packages/bridge/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bridge",
3 | "version": "2.0.73",
4 | "description": "Bridge is a Typescript Node.js framework that provides an easy and scalable way to create REST APIs while generating the client code.",
5 | "author": "Bridge Team ",
6 | "license": "MIT",
7 | "main": "dist/source/index.js",
8 | "types": "dist/source/index.d.ts",
9 | "bugs": "https://github.com/bridge-codes/bridge/issues",
10 | "homepage": "https://bridge.codes",
11 | "files": [
12 | "/dist"
13 | ],
14 | "scripts": {
15 | "build": "tsc",
16 | "publish-minor": "tsc && npm version patch && npm publish"
17 | },
18 | "repository": {
19 | "type": "git",
20 | "url": "git+https://github.com/bridge-codes/bridge.git",
21 | "directory": "packages/bridge"
22 | },
23 | "keywords": [
24 | "express",
25 | "http",
26 | "api",
27 | "sdk",
28 | "typescript",
29 | "generation",
30 | "type",
31 | "node",
32 | "framework",
33 | "rest"
34 | ],
35 | "devDependencies": {
36 | "@types/adm-zip": "^0.5.0",
37 | "@types/express": "^4.17.17",
38 | "@types/node": "^20.2.5",
39 | "nodemon": "^2.0.22",
40 | "ts-node": "^10.9.1",
41 | "typescript": "^5.1.3"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/www/docs/bridge/server.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Launch your server'
3 | ---
4 |
5 | # Launch your server
6 |
7 | ## With Node HTTP
8 |
9 | ### Example
10 |
11 |
12 | ```ts twoslash title='server.ts'
13 | import { initBridge, handler } from 'bridge';
14 |
15 | const hello = handler({
16 | resolve: () => 'hello',
17 | });
18 |
19 | const bridge = initBridge({ routes: { hello } });
20 |
21 | const port = 8080;
22 |
23 | bridge.HTTPServer().listen(port, () => {
24 | `Listening on port ${port}`;
25 | });
26 | ```
27 |
28 | ## With Express
29 |
30 | ### Install [express](https://www.npmjs.com/package/express)
31 |
32 | ```bash title=terminal
33 | npm i express
34 | npm i --save-dev @types/express
35 | ```
36 |
37 | ### Example
38 |
39 | ```ts twoslash title='server.ts'
40 | import { initBridge, handler } from 'bridge';
41 | import express from 'express';
42 |
43 | const hello = handler({
44 | resolve: () => 'hello',
45 | });
46 |
47 | const bridge = initBridge({ routes: { hello } });
48 |
49 | const port = 8080;
50 |
51 | const app = express();
52 |
53 | app.use('', bridge.expressMiddleware());
54 |
55 | app.listen(port, () => {
56 | `Listening on port ${port}`;
57 | });
58 | ```
59 |
60 | ## With Fastify
61 |
62 | Coming soon...
63 |
64 | ## Lambda
65 |
66 | Coming soon...
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/github/getMyConnectedAccounts.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | headers: { token: string };
5 | }): Promise<
6 | | {
7 | data: {
8 | githubAccounts: Array<{
9 | id: string;
10 | name: string;
11 | avatar: string;
12 | createdAt: string;
13 | }>;
14 | };
15 | error: null;
16 | }
17 | | {
18 | data: null;
19 | error:
20 | | { name: 'Wrong permission'; data?: any; status: 401 }
21 | | { name: 'Expired token'; data?: any; status: 401 }
22 | | { name: 'Invalid token'; data?: any; status: 401 }
23 | | { status: 404; name: 'Document not found' }
24 | | { name: 'Headers schema validation error'; status: 422; data: any }
25 | | { name: 'Headers schema validation error'; status: 422; data: any }
26 | | { name: 'Axios Error'; status: 400; data: any }
27 | | { name: 'Internal Server Error'; status: 500 };
28 | }
29 | > => {
30 | const res = await Fetch({
31 | ...data,
32 | method: 'POST',
33 | path: '/github/getMyConnectedAccounts',
34 | });
35 |
36 | if (res.error && typeof res.error.status === 'number')
37 | return { data: null, error: res.error };
38 | else return { data: res, error: null };
39 | };
40 |
--------------------------------------------------------------------------------
/packages/create-bridge-app/bin/renameSync.ts:
--------------------------------------------------------------------------------
1 | import * as fs from 'fs';
2 | import * as util from 'util';
3 | import * as path from 'path';
4 |
5 | const readdir = util.promisify(fs.readdir);
6 | const mkdir = util.promisify(fs.mkdir);
7 | const rmdir = util.promisify(fs.rmdir);
8 | const readFile = util.promisify(fs.readFile);
9 | const writeFile = util.promisify(fs.writeFile);
10 |
11 | export async function copy(src: string, dest: string): Promise {
12 | const filenames = await readdir(src);
13 |
14 | await mkdir(dest);
15 |
16 | for (const filename of filenames) {
17 | const srcPath = path.join(src, filename);
18 | const destPath = path.join(dest, filename);
19 |
20 | const stat = await fs.promises.stat(srcPath);
21 |
22 | if (stat.isDirectory()) {
23 | await copy(srcPath, destPath);
24 | } else {
25 | const data = await readFile(srcPath);
26 | await writeFile(destPath, data);
27 | }
28 | }
29 | }
30 |
31 | // export async function renameFolder(oldPath: string, newPath: string): Promise {
32 | // try {
33 | // throw new Error('sd');
34 | // await fs.promises.rename(oldPath, newPath);
35 | // // console.log(`Successfully renamed '${oldPath}' to '${newPath}'`);
36 | // } catch (err: any) {
37 | // await copy(oldPath, newPath);
38 | // // await rmdir(oldPath);
39 | // }
40 | // }
41 |
--------------------------------------------------------------------------------
/www/src/components/Newsletter.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export const NewsLetter = (): JSX.Element => {
4 | return (
5 |
30 | );
31 | };
32 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/parser/find-source-file.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import path from 'path';
3 |
4 | /**
5 | *
6 | */
7 | export const findSourceFilePath = async (dir: string): Promise<{ sourceFilePath: string; addedCode: string }> => {
8 | let sourceFilePath: string = '';
9 | let addedCode: string = '';
10 |
11 | for (const file of fs.readdirSync(dir)) {
12 | const absolute = path.join(dir, file);
13 |
14 | if (fs.statSync(absolute).isDirectory()) {
15 | const { sourceFilePath: sourceFilePathInDir, addedCode: addedCodeInDir } = await findSourceFilePath(absolute);
16 | if (sourceFilePathInDir) return { sourceFilePath: sourceFilePathInDir, addedCode: addedCodeInDir };
17 | } else if (absolute.substring(absolute.length - 3) === '.ts') {
18 | const file = fs.readFileSync(absolute, 'utf8');
19 | const matches = file.match(/initBridge\((.*?)\)/);
20 |
21 | if (matches && matches?.length > 1 && matches[1].includes('routes')) {
22 | // console.log(matches[1]);
23 |
24 | addedCode = `\nconst bridgeGeneratedVariable = initBridge(${matches[1]});\ntype BridgeGenereatedType = typeof bridgeGeneratedVariable['bridgeType'];\n`;
25 |
26 | await fs.promises.appendFile(absolute, addedCode, 'utf-8');
27 |
28 | sourceFilePath = absolute;
29 | return { sourceFilePath, addedCode };
30 | }
31 | }
32 | }
33 |
34 | return { sourceFilePath, addedCode };
35 | };
36 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/utils/statusCode.ts:
--------------------------------------------------------------------------------
1 | export const descriptionOfStatusCode: any = {
2 | '400': 'BAD_REQUEST',
3 | '401': 'UNAUTHORIZED',
4 | '402': 'PAYMENT_REQUIRED',
5 | '403': 'FORBIDDEN',
6 | '404': 'NOT_FOUND',
7 | '405': 'METHOD_NOT_ALLOWED',
8 | '406': 'NOT_ACCEPTABLE',
9 | '407': 'PROXY_AUTHENTICATION_REQUIRED',
10 | '408': 'REQUEST_TIMEOUT',
11 | '409': 'CONFLICT',
12 | '410': 'GONE',
13 | '411': 'LENGTH_REQUIRED',
14 | '412': 'PRECONDITION_FAILED',
15 | '413': 'PAYLOAD_TOO_LARGE',
16 | '414': 'URI_TOO_LONG',
17 | '415': 'UNSUPORTED_MEDIA_TYPE',
18 | '416': 'RANGE_NOT_SATISFIABLE',
19 | '417': 'EXPECTATION_FAILED',
20 | '418': 'I_AM_A_TEAPOT',
21 | '419': 'MISDIRECTED_REQUEST',
22 | '422': 'UNPROCESSABLE_ENTITY',
23 | '423': 'LOCKED',
24 | '424': 'FAILED_DEPENDENCY',
25 | '425': 'TOO_EARLY',
26 | '426': 'UPGRADE_REQUIRED',
27 | '428': 'PRECONDITION_REQUIRED',
28 | '429': 'TOO_MANY_REQUEST',
29 | '431': 'REQUEST_HEADER_FIELDS_TOO_LARGE',
30 | '451': 'UNAVAILABLE_FOR_LEGAL_REASONS',
31 | '500': 'INTERNAL_SERVER_ERROR',
32 | '501': 'NOT_IMPLEMENTED',
33 | '502': 'BAD_GATEWAY',
34 | '503': 'SERVICE_UNAVAILABLE',
35 | '504': 'GATEWAY_TIMEOUT',
36 | '505': 'HTTP_VERSION_NOT_SUPPORTED',
37 | '506': 'VARIANT_ALSO_NEGOCIATES',
38 | '507': 'INSUFFICIENT_STORAGE',
39 | '508': 'LOOP_DETECTED',
40 | '510': 'NOT_EXTENTED',
41 | '511': 'NETWORK_AUTHENTICATION_REQUIRED',
42 | };
43 |
--------------------------------------------------------------------------------
/packages/bridge/source/routes/convert.ts:
--------------------------------------------------------------------------------
1 | import { BridgeRoutes, ServerRoutes, isBridgeRoutes } from './types';
2 | import { isBridgeHandler } from '../core';
3 | import { isBridgeMethod } from './method';
4 |
5 | const serverRoutes: ServerRoutes = {};
6 |
7 | export const convertBridgeRoutesToServerRoutes = (
8 | routes: BridgeRoutes,
9 | prefix: string,
10 | hasFormidable: boolean,
11 | ): ServerRoutes => {
12 | for (const [key, value] of Object.entries(routes)) {
13 | if (!value) continue;
14 | else if (isBridgeMethod(value)) {
15 | serverRoutes[`${prefix}/${key}`] = value.methods;
16 | Object.values(value.methods).forEach((handler) => {
17 | if (handler.config.filesConfig && !hasFormidable)
18 | throw new Error(
19 | `You need to install formidable and to give it to Bridge in order to use files.`,
20 | );
21 | });
22 | } else if (isBridgeHandler(value)) {
23 | serverRoutes[`${prefix}/${key}`] = { POST: value };
24 | if (value.config.filesConfig && !hasFormidable)
25 | throw new Error(
26 | `You need to install formidable and pass it to the initBridge function in order to use files.
27 | \nCheck the documentation: https://bridge.codes/docs/file \n`,
28 | );
29 | } else if (isBridgeRoutes(value))
30 | convertBridgeRoutesToServerRoutes(value, `${prefix}/${key}`, hasFormidable);
31 | }
32 |
33 | return serverRoutes;
34 | };
35 |
--------------------------------------------------------------------------------
/packages/bridge-studio/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bridge-studio",
3 | "version": "1.0.9",
4 | "description": "Compile the sdk of your Bridge project with one command",
5 | "author": "Bridge Team ",
6 | "bin": {
7 | "bridge-studio": "./dist/bin/index.js"
8 | },
9 | "files": [
10 | "/dist"
11 | ],
12 | "scripts": {
13 | "build": "tsc",
14 | "publish-minor": "tsc && npm version patch && npm publish"
15 | },
16 | "keywords": [
17 | "sdk",
18 | "compilation",
19 | "bridge",
20 | "typescript"
21 | ],
22 | "license": "MIT",
23 | "bugs": "https://github.com/bridge-codes/bridge/issues",
24 | "homepage": "https://bridge.codes",
25 | "repository": {
26 | "type": "git",
27 | "url": "git+https://github.com/bridge-codes/bridge.git",
28 | "directory": "packages/fetch-bridge-sdk"
29 | },
30 | "dependencies": {
31 | "adm-zip": "^0.5.10",
32 | "axios": "^1.2.5",
33 | "bridge": "^2.0.39",
34 | "chalk": "^5.2.0",
35 | "cli-spinners": "^2.7.0",
36 | "colors": "^1.4.0",
37 | "express": "^4.18.2",
38 | "form-data": "^4.0.0",
39 | "ora": "^3.4.0",
40 | "prettier": "^2.8.3",
41 | "prompts": "^2.4.2",
42 | "zod": "^3.20.2"
43 | },
44 | "devDependencies": {
45 | "@types/prettier": "^2.7.2",
46 | "@types/adm-zip": "^0.5.0",
47 | "@types/express": "^4.17.16",
48 | "@types/ora": "^3.2.0",
49 | "@types/prompts": "^2.4.2"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/sdk-compilers/typescript/index.ts:
--------------------------------------------------------------------------------
1 | import { JSONTypeI } from '../../types';
2 | import { mkdirAsync, writeFileAsync } from '../../utils';
3 | import { writeHandlersFilesAndFolders } from './write-handlers-file';
4 | import getFetchFileContent from './compilers/fetch-file-compiler';
5 | import { getIndexTSFileContent } from './compilers/index-import-file-compiler';
6 | import prettier from 'prettier';
7 | import AdmZip from 'adm-zip';
8 | import fs from 'fs';
9 | import os from 'os';
10 |
11 | export default async (JSONType: JSONTypeI, serverUrl: string): Promise => {
12 | const sdkTempPath = `${os.tmpdir()}/ts-sdk-${new Date().getTime()}`;
13 |
14 | await mkdirAsync(sdkTempPath);
15 |
16 | const [routesTree] = await Promise.all([
17 | writeHandlersFilesAndFolders(JSONType, sdkTempPath, {}),
18 | writeFileAsync(`${sdkTempPath}/bridgeFetchMethod.ts`, getFetchFileContent(serverUrl)),
19 | ]);
20 |
21 | const { importsString, exportAPIStringObject } = getIndexTSFileContent(routesTree);
22 |
23 | await writeFileAsync(
24 | `${sdkTempPath}/index.ts`,
25 | prettier.format(`${importsString}\nexport const API = ${exportAPIStringObject.slice(0, -1)}`, {
26 | parser: 'typescript',
27 | singleQuote: true,
28 | })
29 | );
30 |
31 | const zip = new AdmZip();
32 | zip.addLocalFolder(sdkTempPath);
33 |
34 | const buffer = await zip.toBufferPromise();
35 |
36 | fs.rm(sdkTempPath, { recursive: true }, () => {});
37 |
38 | return buffer;
39 | };
40 |
--------------------------------------------------------------------------------
/packages/bridge/source/routes/method.ts:
--------------------------------------------------------------------------------
1 | import { BridgeHandler } from '../core';
2 |
3 | export class BridgeMethod<
4 | BHGet extends BridgeHandler | null,
5 | BHPost extends BridgeHandler | null,
6 | BHPatch extends BridgeHandler | null,
7 | BHPut extends BridgeHandler | null,
8 | BHDelete extends BridgeHandler | null,
9 | > {
10 | public isBridgeMethodObject = true;
11 | public type!: {
12 | getBridgeMehthodSDK: BHGet;
13 | postBridgeMehthodSDK: BHPost;
14 | patchBridgeMehthodSDK: BHPatch;
15 | putBridgeMehthodSDK: BHPut;
16 | deleteBridgeMehthodSDK: BHDelete;
17 | };
18 |
19 | constructor(
20 | public methods: {
21 | GET?: BHGet;
22 | POST?: BHPost;
23 | PATCH?: BHPatch;
24 | PUT?: BHPut;
25 | DELETE?: BHDelete;
26 | },
27 | ) {
28 | if (methods.GET?.config.bodySchema) throw Error("You can't have a body with a GET endpoint");
29 | }
30 | }
31 |
32 | export const isBridgeMethod = (obj: any): obj is BridgeMethod =>
33 | typeof obj === 'object' && obj.isBridgeMethodObject === true;
34 |
35 | export const method = <
36 | BHGet extends BridgeHandler | null = null,
37 | BHPost extends BridgeHandler | null = null,
38 | BHPatch extends BridgeHandler | null = null,
39 | BHPut extends BridgeHandler | null = null,
40 | BHDelete extends BridgeHandler | null = null,
41 | >(p: {
42 | GET?: BHGet;
43 | POST?: BHPost;
44 | PATCH?: BHPatch;
45 | PUT?: BHPut;
46 | DELETE?: BHDelete;
47 | }) => new BridgeMethod(p);
48 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/github/getReposWithTS.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | body: { repoName?: string; perPage?: number; connectedAccountName: string };
5 | headers: { token: string };
6 | }): Promise<
7 | | {
8 | data: Array<{
9 | id: number;
10 | name: string;
11 | full_name: string;
12 | visibility: string;
13 | owner: string;
14 | createdAt: string;
15 | updatedAt: string;
16 | }>;
17 | error: null;
18 | }
19 | | {
20 | data: null;
21 | error:
22 | | { name: 'Wrong permission'; data?: any; status: 401 }
23 | | { name: 'Expired token'; data?: any; status: 401 }
24 | | { name: 'Invalid token'; data?: any; status: 401 }
25 | | { status: 404; name: 'Document not found' }
26 | | { name: 'Headers schema validation error'; status: 422; data: any }
27 | | { name: 'Body schema validation error'; status: 422; data: any }
28 | | { name: 'Headers schema validation error'; status: 422; data: any }
29 | | { name: 'Axios Error'; status: 400; data: any }
30 | | { name: 'Internal Server Error'; status: 500 };
31 | }
32 | > => {
33 | const res = await Fetch({
34 | ...data,
35 | method: 'POST',
36 | path: '/github/getReposWithTS',
37 | });
38 |
39 | if (res.error && typeof res.error.status === 'number')
40 | return { data: null, error: res.error };
41 | else return { data: res, error: null };
42 | };
43 |
--------------------------------------------------------------------------------
/packages/bridge-compile/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bridge-compile",
3 | "version": "1.0.30",
4 | "description": "Compile the sdk of your Bridge project with one command locally",
5 | "author": "Bridge Team ",
6 | "bin": {
7 | "bridge-compile": "./dist/index.js"
8 | },
9 | "files": [
10 | "/dist"
11 | ],
12 | "scripts": {
13 | "build": "tsc",
14 | "publish-minor": "tsc && npm version patch && npm publish"
15 | },
16 | "keywords": [
17 | "sdk",
18 | "compilation",
19 | "bridge",
20 | "typescript"
21 | ],
22 | "license": "MIT",
23 | "bugs": "https://github.com/bridge-codes/bridge/issues",
24 | "homepage": "https://bridge.codes",
25 | "repository": {
26 | "type": "git",
27 | "url": "git+https://github.com/bridge-codes/bridge.git",
28 | "directory": "packages/bridge-compile"
29 | },
30 | "dependencies": {
31 | "adm-zip": "^0.5.10",
32 | "axios": "^1.2.5",
33 | "bridge": "^2.0.39",
34 | "chalk": "^5.2.0",
35 | "cli-spinners": "^2.7.0",
36 | "colors": "^1.4.0",
37 | "express": "^4.18.2",
38 | "form-data": "^4.0.0",
39 | "minimist": "^1.2.8",
40 | "ora": "^3.4.0",
41 | "prettier": "^2.8.3",
42 | "prompts": "^2.4.2",
43 | "typescript": "^4.9.4",
44 | "zod": "^3.20.2"
45 | },
46 | "devDependencies": {
47 | "@types/adm-zip": "^0.5.0",
48 | "@types/express": "^4.17.16",
49 | "@types/ora": "^3.2.0",
50 | "@types/prettier": "^2.7.2",
51 | "@types/prompts": "^2.4.2"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/packages/fetch-bridge-sdk/bin/index.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | import axios from 'axios';
3 | import AdmZip from 'adm-zip';
4 | import { execSync } from 'child_process';
5 | import fs from 'fs';
6 |
7 | var argv = require('minimist')(process.argv.slice(2));
8 |
9 | const launch = async () => {
10 | const serverUrl = argv._[0];
11 |
12 | if (!serverUrl.includes('/')) {
13 | console.error(
14 | 'You have to give the server url as parameter, example: npx fetch-bridge-sdk@latest http://localhost:8080',
15 | );
16 | process.exit(1);
17 | }
18 |
19 | const directory = 'sdk';
20 |
21 | const { data } = await axios({
22 | method: 'get',
23 | url: `${serverUrl}/sdk`,
24 | responseType: 'arraybuffer',
25 | });
26 |
27 | const zipFolder = new AdmZip(data);
28 | zipFolder.extractAllTo(directory, true);
29 |
30 | const packageJSON = JSON.parse(fs.readFileSync('./package.json', 'utf-8'));
31 |
32 | let pnpmLock: boolean;
33 | try {
34 | fs.readFileSync('./pnpm-lock.yaml', 'utf-8');
35 | pnpmLock = true;
36 | } catch (e) {
37 | pnpmLock = false;
38 | }
39 |
40 | const installCommand = pnpmLock ? 'pnpm i' : 'npm i';
41 |
42 | if (!packageJSON) throw new Error('package.json not found.');
43 |
44 | if (!packageJSON.dependencies.axios)
45 | execSync(`echo Installing axios`) && execSync(`${installCommand} axios`);
46 | if (!packageJSON.dependencies['form-data'])
47 | execSync(`echo Installing form-data`) && execSync(`${installCommand} form-data`);
48 | };
49 |
50 | launch();
51 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/project/createProjectFromCLI.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | query: { serverUrl: string; projectName: string };
5 | headers: { token: string };
6 | }): Promise<
7 | | {
8 | data: {
9 | owner: string;
10 | name: string;
11 | serverUrl: string;
12 | provider: 'cli';
13 | subscribedLanguages: Array<'typescript'>;
14 | pendingCompilation: false;
15 | lastCompilationSuccess: true;
16 | } & { _id: string; createdAt: Date; updatedAt: Date };
17 | error: null;
18 | }
19 | | {
20 | data: null;
21 | error:
22 | | { name: 'Wrong permission'; data?: any; status: 401 }
23 | | { name: 'Invalid token'; data?: any; status: 401 }
24 | | { status: 409; name: 'Already exists'; data?: any }
25 | | { name: 'Headers schema validation error'; status: 422; data: any }
26 | | { name: 'Headers schema validation error'; status: 422; data: any }
27 | | { name: 'Query schema validation error'; status: 422; data: any }
28 | | { name: 'Axios Error'; status: 400; data: any }
29 | | { name: 'Internal Server Error'; status: 500 };
30 | }
31 | > => {
32 | const res = await Fetch({
33 | ...data,
34 | method: 'POST',
35 | path: '/project/createProjectFromCLI',
36 | });
37 |
38 | if (res.error && typeof res.error.status === 'number')
39 | return { data: null, error: res.error };
40 | else return { data: res, error: null };
41 | };
42 |
--------------------------------------------------------------------------------
/packages/bridge/test.ts:
--------------------------------------------------------------------------------
1 | // import { handler, apply, httpError } from './source';
2 | // import { BridgeHandler } from './source/core';
3 | // import { z } from 'zod';
4 |
5 | // const middleware = handler({
6 | // resolve: () => ({ status: 200, res: 'Hello, world!' }),
7 | // });
8 |
9 | // const middleware2 = handler({
10 | // body: z.object({ last: z.string() }),
11 | // resolve: ({ body }) => {
12 | // if (body.last === 'last') return httpError(400, 'last is not allowed');
13 | // return { brooo: 'brooo' };
14 | // },
15 | // });
16 |
17 | // const query = handler({
18 | // middlewares: [middleware, middleware2] as const,
19 | // body: z.object({ name: z.string() }),
20 | // resolve: (data) => {},
21 | // });
22 |
23 | // type TEST = readonly [
24 | // BridgeHandler<
25 | // () => {
26 | // brooo: string;
27 | // },
28 | // never
29 | // >,
30 | // BridgeHandler<
31 | // () => {
32 | // status: number;
33 | // body: string;
34 | // },
35 | // never
36 | // >,
37 | // ];
38 |
39 | // export type UnionToIntersection = (U extends any ? (k: U) => void : never) extends (
40 | // k: infer I,
41 | // ) => void
42 | // ? I
43 | // : never;
44 |
45 | // // Generic type to get the intersection of return types of an array of BridgeHandler
46 | // type UnionOfResolveReturnTypes>> =
47 | // T extends ReadonlyArray> ? ReturnType : never;
48 |
49 | // type Result = UnionToIntersection>;
50 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/sdk-compilers/typescript/json-type-to-ts-interface.ts:
--------------------------------------------------------------------------------
1 | import { JSONTypeI } from '../../types';
2 |
3 | export const JSONTypeToTSInterface = (JSONType: JSONTypeI): string => {
4 | // HAVE TO FIX
5 | if (Object.values(JSONType).length === 0) return '{}';
6 | if ('primitive' in JSONType)
7 | return JSONType.value && JSONType.primitive !== 'nested'
8 | ? JSONType.primitive === 'string'
9 | ? `"${JSONType.value.toString()}"`
10 | : JSONType.value.toString()
11 | : ['unrecognized', 'nested'].includes(JSONType.primitive)
12 | ? 'any'
13 | : JSONType.primitive;
14 |
15 | if ('array' in JSONType) return `Array<${JSONTypeToTSInterface(JSONType.array)}>`;
16 |
17 | if ('record' in JSONType)
18 | return `Record<${JSONTypeToTSInterface(JSONType.record.key)}, ${JSONTypeToTSInterface(JSONType.record.value)}>`;
19 |
20 | if ('union' in JSONType && JSONType.union.length > 0)
21 | return '(' + JSONType.union.map((elem) => JSONTypeToTSInterface(elem)).join(' | ') + ')';
22 |
23 | if ('intersection' in JSONType && JSONType.intersection.length > 0)
24 | return '(' + JSONType.intersection.map((elem) => JSONTypeToTSInterface(elem)).join(' & ') + ')';
25 |
26 | if ('arrayWithPos' in JSONType)
27 | return '[' + JSONType.arrayWithPos.map((elem) => JSONTypeToTSInterface(elem)).join(', ') + ']';
28 | else if ('object' in JSONType)
29 | return (
30 | '{' +
31 | Object.entries(JSONType.object)
32 | .map(([key, value]) => `"${key}"${value.optional ? '?' : ''}: ${JSONTypeToTSInterface(value)}`)
33 | .join(';') +
34 | '}'
35 | );
36 |
37 | return 'any';
38 | };
39 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/user/getMe.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | headers: { token: string };
5 | }): Promise<
6 | | {
7 | data: {
8 | github?: {
9 | id: string;
10 | accessToken: string;
11 | refreshToken: string;
12 | lastUpdate: Date;
13 | username: string;
14 | profileUrl: string;
15 | accountCreation: Date;
16 | public_repos_nbr: number;
17 | followers: number;
18 | };
19 | createdAt: Date;
20 | lastConnexionDate: Date;
21 | name: string;
22 | username: string;
23 | email: string;
24 | language: 'english' | 'french';
25 | twitter_username?: string;
26 | avatar?: string;
27 | } & { _id: string };
28 | error: null;
29 | }
30 | | {
31 | data: null;
32 | error:
33 | | { name: 'Wrong permission'; data?: any; status: 401 }
34 | | { name: 'Expired token'; data?: any; status: 401 }
35 | | { name: 'Invalid token'; data?: any; status: 401 }
36 | | { status: 404; name: 'Document not found' }
37 | | { name: 'Headers schema validation error'; status: 422; data: any }
38 | | { name: 'Headers schema validation error'; status: 422; data: any }
39 | | { name: 'Axios Error'; status: 400; data: any }
40 | | { name: 'Internal Server Error'; status: 500 };
41 | }
42 | > => {
43 | const res = await Fetch({ ...data, method: 'POST', path: '/user/getMe' });
44 |
45 | if (res.error && typeof res.error.status === 'number')
46 | return { data: null, error: res.error };
47 | else return { data: res, error: null };
48 | };
49 |
--------------------------------------------------------------------------------
/www/docs/bridge/files.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Files'
3 | ---
4 |
5 | # Files
6 |
7 | Bridge integrates seamlessly with `formidable` to receive and handle files on your server. Simply install `formidable` and pass it to `initBridge` to enable this feature. You can use the `apply` function in Bridge to specify the names of specific files you want your client to send, or use "any" to accept any file.
8 |
9 | ## Install [formidable](https://www.npmjs.com/package/formidable)
10 |
11 |
12 | ``` bash title='terminal'
13 | npm i formidable
14 | npm i --save-dev formidable
15 | ```
16 |
17 | ## Example
18 |
19 | ```ts twoslash title='server.ts'
20 | import { initBridge, handler, apply } from 'bridge';
21 | import formidable from 'formidable';
22 |
23 | const sendAnyFiles = handler({
24 | files: 'any',
25 | resolve: ({ files }) => {
26 | // ^?
27 | console.log(files);
28 | return { success: true };
29 | },
30 | });
31 |
32 | const sendSpecificFiles = handler({
33 | files: apply('profilePicture', 'coverPicture'),
34 | resolve: ({ files }) => {
35 | // ^?
36 | console.log(files);
37 | return { success: true };
38 | },
39 | });
40 |
41 | const routes = {
42 | sendAnyFiles,
43 | sendSpecificFiles,
44 | };
45 |
46 | const bridge = initBridge({ routes, formidable });
47 | ```
48 |
49 | ## Error Example
50 |
51 | "If the user submits files with incorrect names, Bridge will respond with a 400 Bad Request error, denoted as "Files schema validation error". Here is an example:
52 |
53 | ```json
54 | {
55 | "error": {
56 | "status": 400,
57 | "name": "Files schema validation error",
58 | "data": {
59 | "missingFiles": ["profilePicture"]
60 | }
61 | }
62 | }
63 | ```
64 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/parser/ts-parser/recursive-checker.ts:
--------------------------------------------------------------------------------
1 | import ts from 'typescript';
2 | import { utilityTypes } from '../../types';
3 | import { isArrayWithPos } from './utils';
4 |
5 | export const isTypeDepthGreaterThan = (
6 | checker: ts.TypeChecker,
7 | type: ts.Type,
8 | node: ts.Node,
9 | maxDepth: number,
10 | depth = 0
11 | ): boolean => {
12 | try {
13 | if (depth > maxDepth) return true;
14 |
15 | if (checker.typeToString(type) === 'ObjectId') return false;
16 |
17 | if (type.isUnionOrIntersection())
18 | for (const t of type.types) {
19 | if (isTypeDepthGreaterThan(checker, t, node, maxDepth, depth + 1)) return true;
20 | }
21 |
22 | if (
23 | !utilityTypes.includes((type.aliasSymbol?.name || '') as any) &&
24 | (type.isClassOrInterface() || ['__type', '__object'].includes(type.symbol?.name as any))
25 | )
26 | for (const property of type.getProperties()) {
27 | const valueType = checker.getTypeOfSymbolAtLocation(property, node);
28 | if (isTypeDepthGreaterThan(checker, valueType, node, maxDepth, depth + 1)) return true;
29 | }
30 |
31 | if (
32 | type.symbol?.name === 'Array' &&
33 | isTypeDepthGreaterThan(checker, checker.getTypeArguments(type as any)?.[0], node, maxDepth, depth + 1)
34 | )
35 | return true;
36 |
37 | if (isArrayWithPos(type) && type.symbol?.name !== 'Array' && checker.typeToString(type) !== 'string')
38 | for (const t of (type as any).resolvedTypeArguments || [])
39 | if (isTypeDepthGreaterThan(checker, t, node, maxDepth, depth + 1)) return true;
40 |
41 | return false;
42 | } catch (err) {
43 | console.error(err);
44 | return true;
45 | }
46 | };
47 |
--------------------------------------------------------------------------------
/examples/minimal-http/openapi.json:
--------------------------------------------------------------------------------
1 | {
2 | "openapi": "3.0.0",
3 | "info": { "title": "minimal-http", "version": "Bridge: 1.0.0" },
4 | "paths": {
5 | "/hello": {
6 | "post": {
7 | "parameters": [],
8 | "responses": {
9 | "200": {
10 | "description": "Success",
11 | "content": {
12 | "application/json": { "schema": { "type": "string" } }
13 | }
14 | },
15 | "400": {
16 | "description": "BAD_REQUEST",
17 | "content": {
18 | "application/json": {
19 | "schema": {
20 | "type": "object",
21 | "required": ["name", "status", "data"],
22 | "properties": {
23 | "name": { "enum": ["Axios Error"], "type": "string" },
24 | "status": { "enum": [400], "type": "number" },
25 | "data": {}
26 | }
27 | }
28 | }
29 | }
30 | },
31 | "500": {
32 | "description": "INTERNAL_SERVER_ERROR",
33 | "content": {
34 | "application/json": {
35 | "schema": {
36 | "type": "object",
37 | "required": ["name", "status"],
38 | "properties": {
39 | "name": {
40 | "enum": ["Internal Server Error"],
41 | "type": "string"
42 | },
43 | "status": { "enum": [500], "type": "number" }
44 | }
45 | }
46 | }
47 | }
48 | }
49 | }
50 | }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/openapi.json:
--------------------------------------------------------------------------------
1 | {
2 | "openapi": "3.0.0",
3 | "info": { "title": "bridge-mongodb-boilerplate", "version": "Bridge: 1.0.0" },
4 | "paths": {
5 | "/hey": {
6 | "post": {
7 | "parameters": [],
8 | "responses": {
9 | "200": {
10 | "description": "Success",
11 | "content": {
12 | "application/json": { "schema": { "type": "string" } }
13 | }
14 | },
15 | "400": {
16 | "description": "BAD_REQUEST",
17 | "content": {
18 | "application/json": {
19 | "schema": {
20 | "type": "object",
21 | "required": ["name", "status", "data"],
22 | "properties": {
23 | "name": { "enum": ["Axios Error"], "type": "string" },
24 | "status": { "enum": [400], "type": "number" },
25 | "data": {}
26 | }
27 | }
28 | }
29 | }
30 | },
31 | "500": {
32 | "description": "INTERNAL_SERVER_ERROR",
33 | "content": {
34 | "application/json": {
35 | "schema": {
36 | "type": "object",
37 | "required": ["name", "status"],
38 | "properties": {
39 | "name": {
40 | "enum": ["Internal Server Error"],
41 | "type": "string"
42 | },
43 | "status": { "enum": [500], "type": "number" }
44 | }
45 | }
46 | }
47 | }
48 | }
49 | }
50 | }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/www/static/studio/customcard.svg:
--------------------------------------------------------------------------------
1 |
29 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/project/getFromCLI.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | query: { _id: string };
5 | headers: { token: string };
6 | }): Promise<
7 | | {
8 | data: {
9 | createdAt: Date;
10 | name: string;
11 | owner: string;
12 | serverUrl: string;
13 | provider: 'github' | 'gitlab' | 'cli';
14 | subscribedLanguages: Array<'python' | 'javascript' | 'typescript'>;
15 | lastCompilationSuccess: false | true;
16 | pendingCompilation: false | true;
17 | githubRepo?: {
18 | id: number;
19 | name: string;
20 | owner: string;
21 | full_name: string;
22 | visibility: 'private' | 'public';
23 | createdAt: Date;
24 | };
25 | } & { _id: string };
26 | error: null;
27 | }
28 | | {
29 | data: null;
30 | error:
31 | | { name: 'Wrong permission'; data?: any; status: 401 }
32 | | { name: 'Invalid token'; data?: any; status: 401 }
33 | | { status: 404; name: 'Document not found' }
34 | | { name: 'Headers schema validation error'; status: 422; data: any }
35 | | { name: 'Headers schema validation error'; status: 422; data: any }
36 | | { name: 'Query schema validation error'; status: 422; data: any }
37 | | { name: 'Axios Error'; status: 400; data: any }
38 | | { name: 'Internal Server Error'; status: 500 };
39 | }
40 | > => {
41 | const res = await Fetch({
42 | ...data,
43 | method: 'POST',
44 | path: '/project/getFromCLI',
45 | });
46 |
47 | if (res.error && typeof res.error.status === 'number')
48 | return { data: null, error: res.error };
49 | else return { data: res, error: null };
50 | };
51 |
--------------------------------------------------------------------------------
/examples/minimal-express/openapi.json:
--------------------------------------------------------------------------------
1 | {
2 | "openapi": "3.0.0",
3 | "info": { "title": "minimal-express", "version": "Bridge: 1.0.0" },
4 | "paths": {
5 | "/hello": {
6 | "post": {
7 | "parameters": [],
8 | "responses": {
9 | "200": {
10 | "description": "Success",
11 | "content": {
12 | "application/json": {
13 | "schema": { "enum": ["hello"], "type": "string" }
14 | }
15 | }
16 | },
17 | "400": {
18 | "description": "BAD_REQUEST",
19 | "content": {
20 | "application/json": {
21 | "schema": {
22 | "type": "object",
23 | "required": ["name", "status", "data"],
24 | "properties": {
25 | "name": { "enum": ["Axios Error"], "type": "string" },
26 | "status": { "enum": [400], "type": "number" },
27 | "data": {}
28 | }
29 | }
30 | }
31 | }
32 | },
33 | "500": {
34 | "description": "INTERNAL_SERVER_ERROR",
35 | "content": {
36 | "application/json": {
37 | "schema": {
38 | "type": "object",
39 | "required": ["name", "status"],
40 | "properties": {
41 | "name": {
42 | "enum": ["Internal Server Error"],
43 | "type": "string"
44 | },
45 | "status": { "enum": [500], "type": "number" }
46 | }
47 | }
48 | }
49 | }
50 | }
51 | }
52 | }
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/project/get.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | query: { _id: string };
5 | headers: { token: string };
6 | }): Promise<
7 | | {
8 | data: {
9 | createdAt: Date;
10 | name: string;
11 | owner: string;
12 | serverUrl: string;
13 | provider: 'github' | 'gitlab' | 'cli';
14 | subscribedLanguages: Array<'python' | 'javascript' | 'typescript'>;
15 | lastCompilationSuccess: false | true;
16 | pendingCompilation: false | true;
17 | githubRepo?: {
18 | id: number;
19 | name: string;
20 | owner: string;
21 | full_name: string;
22 | visibility: 'private' | 'public';
23 | createdAt: Date;
24 | };
25 | } & { _id: string };
26 | error: null;
27 | }
28 | | {
29 | data: null;
30 | error:
31 | | { name: 'Wrong permission'; data?: any; status: 401 }
32 | | { name: 'Expired token'; data?: any; status: 401 }
33 | | { name: 'Invalid token'; data?: any; status: 401 }
34 | | { status: 404; name: 'Document not found' }
35 | | { name: 'Headers schema validation error'; status: 422; data: any }
36 | | { name: 'Headers schema validation error'; status: 422; data: any }
37 | | { name: 'Query schema validation error'; status: 422; data: any }
38 | | { name: 'Axios Error'; status: 400; data: any }
39 | | { name: 'Internal Server Error'; status: 500 };
40 | }
41 | > => {
42 | const res = await Fetch({ ...data, method: 'POST', path: '/project/get' });
43 |
44 | if (res.error && typeof res.error.status === 'number')
45 | return { data: null, error: res.error };
46 | else return { data: res, error: null };
47 | };
48 |
--------------------------------------------------------------------------------
/www/docs/bridge-client/typescript/how-to-use.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'How to use your SDK'
3 | ---
4 |
5 | # SDK in the client code
6 |
7 | ## Import API from sdk
8 |
9 | The Typescript client SDK exports an API constant which can be easily imported into your code and used to access every endpoint of the Bridge API.
10 |
11 | ## Example
12 |
13 | ```ts twoslash title='client.ts' live
14 |
15 | const API = {
16 | user: {
17 | getMe: async (p: {
18 | headers: { token: string }
19 | }): Promise<
20 | | {
21 | data: {
22 | _id: string
23 | username: string;
24 | email: string;
25 | age: number;
26 | language: 'english' | 'french';
27 | avatar?: string;
28 | createdAt: Date;
29 | };
30 | error: undefined;
31 | }
32 | | {
33 | data: undefined;
34 | error:
35 | | { name: 'Wrong permission'; data?: any; status: 401 }
36 | | { status: 404; name: 'User not found' }
37 | | { name: 'Headers schema validation error'; status: 422; data: any }
38 | | { name: 'Axios Error'; status: 400; data: any }
39 | | { name: 'Internal Server Error'; status: 500 };
40 | }
41 | > => '' as any
42 | }
43 | }
44 |
45 | // ---cut---
46 |
47 | async () => {
48 |
49 | const { data, error } = await API.user.getMe({
50 | headers: { token: 'secretToken' }
51 | })
52 |
53 | if (data) console.log(data)
54 | // ^?
55 |
56 |
57 | if (error) {
58 | switch (error.name) {
59 | case "User not found":
60 | //...
61 | break;
62 | }
63 |
64 | console.log(error)
65 | // ^?
66 | }
67 | }
68 | ```
69 |
70 | Please visit https://bridge.codes/studio for more information.
--------------------------------------------------------------------------------
/examples/minimal-express/sdk/bridgeFetchMethod.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import FormData from 'form-data';
3 |
4 | export const serverUrl = 'http://localhost:8080';
5 |
6 | interface FETCH {
7 | method: 'GET' | 'POST' | 'PATCH' | 'DELETE' | 'PUT';
8 | path: string;
9 | body?: Record;
10 | query?: Record;
11 | headers?: Record;
12 | file?: Record;
13 | }
14 |
15 | const getQueryUrl = (query: FETCH['query']): string => {
16 | if (!query || !Object.values(query).some((val) => val)) return '';
17 |
18 | return Object.entries(query)
19 | .filter(([_, value]) => value !== undefined)
20 | .map(([key, value]) => `${key}=${value}`)
21 | .join('&');
22 | };
23 |
24 | export default async ({ path, method, body, query, headers, file }: FETCH) => {
25 | let completeUrl = serverUrl + path;
26 | if (query && Object.keys(query).length > 0)
27 | completeUrl += '?' + getQueryUrl(query);
28 |
29 | const config: any = { url: completeUrl, method };
30 |
31 | if (headers) config.headers = headers;
32 | if (body) config.data = body;
33 | else if (file) {
34 | const formData = new FormData();
35 | Object.entries(file).forEach(([name, f]) => formData.append(name, f));
36 | config.data = formData;
37 | config.headers = {
38 | ...config.headers,
39 | 'Content-Type': 'multipart/form-data',
40 | };
41 | }
42 |
43 | return axios(config)
44 | .then((res) => res.data)
45 | .catch((err) => {
46 | if (
47 | err.response &&
48 | err.response.data &&
49 | 'error' in err.response.data &&
50 | 'status' in err.response.data.error
51 | )
52 | return err.response.data;
53 |
54 | return {
55 | error: {
56 | name: 'Axios Error',
57 | status: 400,
58 | data: err,
59 | },
60 | };
61 | });
62 | };
63 |
--------------------------------------------------------------------------------
/examples/minimal-http/sdk/bridgeFetchMethod.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import FormData from 'form-data';
3 |
4 | export const serverUrl = 'http://localhost:8080';
5 |
6 | interface FETCH {
7 | method: 'GET' | 'POST' | 'PATCH' | 'DELETE' | 'PUT';
8 | path: string;
9 | body?: Record;
10 | query?: Record;
11 | headers?: Record;
12 | file?: Record;
13 | }
14 |
15 | const getQueryUrl = (query: FETCH['query']): string => {
16 | if (!query || !Object.values(query).some((val) => val)) return '';
17 |
18 | return Object.entries(query)
19 | .filter(([_, value]) => value !== undefined)
20 | .map(([key, value]) => `${key}=${value}`)
21 | .join('&');
22 | };
23 |
24 | export default async ({ path, method, body, query, headers, file }: FETCH) => {
25 | let completeUrl = serverUrl + path;
26 | if (query && Object.keys(query).length > 0)
27 | completeUrl += '?' + getQueryUrl(query);
28 |
29 | const config: any = { url: completeUrl, method };
30 |
31 | if (headers) config.headers = headers;
32 | if (body) config.data = body;
33 | else if (file) {
34 | const formData = new FormData();
35 | Object.entries(file).forEach(([name, f]) => formData.append(name, f));
36 | config.data = formData;
37 | config.headers = {
38 | ...config.headers,
39 | 'Content-Type': 'multipart/form-data',
40 | };
41 | }
42 |
43 | return axios(config)
44 | .then((res) => res.data)
45 | .catch((err) => {
46 | if (
47 | err.response &&
48 | err.response.data &&
49 | 'error' in err.response.data &&
50 | 'status' in err.response.data.error
51 | )
52 | return err.response.data;
53 |
54 | return {
55 | error: {
56 | name: 'Axios Error',
57 | status: 400,
58 | data: err,
59 | },
60 | };
61 | });
62 | };
63 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/bridgeFetchMethod.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import FormData from 'form-data';
3 |
4 | export const serverUrl = 'https://api-prod.bridge.codes';
5 |
6 | interface FETCH {
7 | method: 'GET' | 'POST' | 'PATCH' | 'DELETE' | 'PUT';
8 | path: string;
9 | body?: Record;
10 | query?: Record;
11 | headers?: Record;
12 | file?: Record;
13 | }
14 |
15 | const getQueryUrl = (query: FETCH['query']): string => {
16 | if (!query || !Object.values(query).some((val) => val)) return '';
17 |
18 | return Object.entries(query)
19 | .filter(([_, value]) => value)
20 | .map(([key, value]) => `${key}=${value}`)
21 | .join('&');
22 | };
23 |
24 | export default async ({ path, method, body, query, headers, file }: FETCH) => {
25 | let completeUrl = serverUrl + path;
26 | if (query && Object.keys(query).length > 0) completeUrl += '?' + getQueryUrl(query);
27 |
28 | const config: any = { url: completeUrl, method };
29 |
30 | if (headers) config.headers = headers;
31 | if (body) config.data = body;
32 | else if (file) {
33 | const formData = new FormData();
34 | Object.entries(file).forEach(([name, f]) => formData.append(name, f));
35 | config.data = formData;
36 | config.headers = {
37 | ...config.headers,
38 | 'Content-Type': 'multipart/form-data',
39 | };
40 | }
41 |
42 | return axios(config)
43 | .then((res) => res.data)
44 | .catch((err) => {
45 | console.error(err);
46 | if (
47 | err.response &&
48 | err.response.data &&
49 | err.response.data.error &&
50 | err.response.data.error.status
51 | )
52 | return err.response.data;
53 |
54 | return {
55 | error: {
56 | name: 'Axios Error',
57 | status: 400,
58 | data: err,
59 | },
60 | };
61 | });
62 | };
63 |
--------------------------------------------------------------------------------
/examples/bridge-mongodb-boilerplate/sdk/bridgeFetchMethod.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import FormData from 'form-data';
3 |
4 | export const serverUrl = 'http://localhost:8080';
5 |
6 | interface FETCH {
7 | method: 'GET' | 'POST' | 'PATCH' | 'DELETE' | 'PUT';
8 | path: string;
9 | body?: Record;
10 | query?: Record;
11 | headers?: Record;
12 | file?: Record;
13 | }
14 |
15 | const getQueryUrl = (query: FETCH['query']): string => {
16 | if (!query || !Object.values(query).some((val) => val)) return '';
17 |
18 | return Object.entries(query)
19 | .filter(([_, value]) => value !== undefined)
20 | .map(([key, value]) => `${key}=${value}`)
21 | .join('&');
22 | };
23 |
24 | export default async ({ path, method, body, query, headers, file }: FETCH) => {
25 | let completeUrl = serverUrl + path;
26 | if (query && Object.keys(query).length > 0)
27 | completeUrl += '?' + getQueryUrl(query);
28 |
29 | const config: any = { url: completeUrl, method };
30 |
31 | if (headers) config.headers = headers;
32 | if (body) config.data = body;
33 | else if (file) {
34 | const formData = new FormData();
35 | Object.entries(file).forEach(([name, f]) => formData.append(name, f));
36 | config.data = formData;
37 | config.headers = {
38 | ...config.headers,
39 | 'Content-Type': 'multipart/form-data',
40 | };
41 | }
42 |
43 | return axios(config)
44 | .then((res) => res.data)
45 | .catch((err) => {
46 | if (
47 | err.response &&
48 | err.response.data &&
49 | 'error' in err.response.data &&
50 | 'status' in err.response.data.error
51 | )
52 | return err.response.data;
53 |
54 | return {
55 | error: {
56 | name: 'Axios Error',
57 | status: 400,
58 | data: err,
59 | },
60 | };
61 | });
62 | };
63 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/project/update.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | body: { name: string; serverUrl: string };
5 | query: { _id: string };
6 | headers: { token: string };
7 | }): Promise<
8 | | {
9 | data: {
10 | createdAt: Date;
11 | name: string;
12 | owner: string;
13 | serverUrl: string;
14 | provider: 'github' | 'gitlab' | 'cli';
15 | subscribedLanguages: Array<'python' | 'javascript' | 'typescript'>;
16 | lastCompilationSuccess: false | true;
17 | pendingCompilation: false | true;
18 | githubRepo?: {
19 | id: number;
20 | name: string;
21 | owner: string;
22 | full_name: string;
23 | visibility: 'private' | 'public';
24 | createdAt: Date;
25 | };
26 | } & { _id: string };
27 | error: null;
28 | }
29 | | {
30 | data: null;
31 | error:
32 | | { name: 'Wrong permission'; data?: any; status: 401 }
33 | | { name: 'Expired token'; data?: any; status: 401 }
34 | | { name: 'Invalid token'; data?: any; status: 401 }
35 | | { name: 'Headers schema validation error'; status: 422; data: any }
36 | | { status: 404; name: 'Document not found' }
37 | | { name: 'Body schema validation error'; status: 422; data: any }
38 | | { name: 'Headers schema validation error'; status: 422; data: any }
39 | | { name: 'Query schema validation error'; status: 422; data: any }
40 | | { name: 'Axios Error'; status: 400; data: any }
41 | | { name: 'Internal Server Error'; status: 500 };
42 | }
43 | > => {
44 | const res = await Fetch({ ...data, method: 'POST', path: '/project/update' });
45 |
46 | if (res.error && typeof res.error.status === 'number')
47 | return { data: null, error: res.error };
48 | else return { data: res, error: null };
49 | };
50 |
--------------------------------------------------------------------------------
/www/docs/introduction.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Introduction'
3 | ---
4 |
5 | # Introduction
6 |
7 | Welcome to the Bridge documentation!
8 |
9 | Bridge is the most straightforward yet powerful framework for creating simple or complex APIs using the full power of TypeScript, even for developers with little experience. Give it a try and see how easy it is to build your dream API!
10 |
11 | If you have any questions about anything related to Bridge or if you want to discuss with us and the community, you are welcome to join our **[discord](https://discord.gg/yxjrwm7Bfr)**.
12 |
13 | ## Our Mission
14 |
15 | Our mission at Bridge is to revolutionize the way developers build and integrate APIs. Through our open-source project and SAAS platform, we aim to provide the best developer experience ever by simplifying the process of developing and integrating APIs, and helping developers create value faster. We believe that developers deserve tools that are easy to use, efficient, and powerful, and we are committed to helping our clients achieve their goals and succeed in the digital world by providing innovative solutions that reduce development time and increase value creation.
16 |
17 | ## Chat with us!
18 |
19 | We are dedicated to creating a fantastic project that offers the best developer experience possible, and we would love for you to be a part of it! Please join our **[Discord Community](https://discord.gg/yxjrwm7Bfr)** and chat with us about your thoughts on Bridge and ask us any questions. We are always happy to have a discussion with you!
20 |
21 |
26 |
--------------------------------------------------------------------------------
/www/static/studio/documentation-logo.svg:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/www/docs/bridge-studio.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Bridge Studio'
3 | ---
4 |
5 | # Bridge Studio
6 |
7 | 
8 |
9 |
10 | ## Connecting your Bridge API to Bridge Studio
11 |
12 |
13 | ### Using the CLI
14 |
15 | ```bash title='terminal'
16 | npx bridge-studio@latest
17 | # or
18 | pnpx bridge-studio@latest
19 | ```
20 |
21 | You'll be redirected to the [github login](https://github.com/login/oauth/authorize?client_id=Iv1.61c158472b4a85b9). Sign in with your GitHub account, then copy and paste the secretToken on the Studio Bridge page.
22 |
23 | This command-line tool will generate a `bridge.config.json` file for you. To keep your secret token private, consider adding this file to your `.gitignore` before publishing to GitHub.
24 |
25 | If you didn't have a Studio Bridge account, this process will create one for you. You can log in to your profile to view and manage your projects at https://studio.bridge.codes.
26 |
27 | ### Using the plateform
28 |
29 | Connect to https://studio.bridge.codes using your GitHub account to import a project from your GitHub repository. The project will be linked to your repository. To recompile the client SDK, simply click the "Recompile" button on the platform.
30 |
31 | ## Fetch your client SDK
32 |
33 | ```bash title='terminal'
34 | npx fetch-bridge-sdk@latest {username}/{projectName}
35 | ```
36 |
37 | If you do not have `axios` and `form-data` installed in your project, the command line will automatically install them for you.
38 |
39 | The upcoming version of the command line will allow you to select your preferred HTTP client library, either axios or fetch, and the required packages will be automatically installed if they are not already present in your project.
40 |
41 |
42 | ## Access your generated documentation
43 |
44 | You'll be able to access your complete generated documentation on https://studio.bridge.codes soon.
45 |
46 | Please visit https://bridge.codes/studio for more information.
--------------------------------------------------------------------------------
/packages/bridge/source/utilities/formidable.ts:
--------------------------------------------------------------------------------
1 | export interface FormidableFile {
2 | /**
3 | * The size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'`
4 | * event), this property says how many bytes of the file have been written to disk yet.
5 | */
6 | size: number;
7 |
8 | /**
9 | * The path this file is being written to. You can modify this in the `'fileBegin'` event in case
10 | * you are unhappy with the way formidable generates a temporary path for your files.
11 | */
12 | filepath: string;
13 |
14 | /**
15 | * The name this file had according to the uploading client.
16 | */
17 | originalFilename: string | null;
18 |
19 | /**
20 | * Calculated based on options provided
21 | */
22 | newFilename: string;
23 |
24 | /**
25 | * The mime type of this file, according to the uploading client.
26 | */
27 | mimetype: string | null;
28 |
29 | /**
30 | * A Date object (or `null`) containing the time this file was last written to. Mostly here for
31 | * compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/).
32 | */
33 | mtime?: Date | null | undefined;
34 |
35 | hashAlgorithm: false | 'sha1' | 'md5' | 'sha256';
36 |
37 | /**
38 | * If `options.hashAlgorithm` calculation was set, you can read the hex digest out of this var
39 | * (at the end it will be a string).
40 | */
41 | hash?: string | null;
42 |
43 | /**
44 | * This method returns a JSON-representation of the file, allowing you to JSON.stringify() the
45 | * file which is useful for logging and responding to requests.
46 | *
47 | * @link https://github.com/node-formidable/formidable#filetojson
48 | */
49 | toJSON(): FileJSON;
50 |
51 | toString(): string;
52 | }
53 |
54 | interface FileJSON
55 | extends Pick {
56 | length: number;
57 | mimetype: string | null;
58 | mtime: Date | null;
59 | }
60 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/sdk-compilers/typescript/compilers/fetch-file-compiler.ts:
--------------------------------------------------------------------------------
1 | import prettier from 'prettier';
2 |
3 | export default (serverUrl: string) =>
4 | prettier.format(
5 | `import axios from 'axios';
6 | import FormData from 'form-data';
7 |
8 | export const serverUrl = '${serverUrl.replace(/\/$/, '')}';
9 |
10 | interface FETCH {
11 | method: 'GET' | 'POST' | 'PATCH' | 'DELETE' | 'PUT';
12 | path: string;
13 | body?: Record;
14 | query?: Record;
15 | headers?: Record;
16 | file?: Record;
17 | }
18 |
19 | const getQueryUrl = (query: FETCH["query"]): string => {
20 | if (!query || !Object.values(query).some((val) => val)) return "";
21 |
22 | return Object.entries(query)
23 | .filter(([_, value]) => value !== undefined)
24 | .map(([key, value]) => \`\${key}=\${value}\`)
25 | .join("&");
26 | };
27 |
28 | export default async ({ path, method, body, query, headers, file }: FETCH) => {
29 | let completeUrl = serverUrl + path;
30 | if (query && Object.keys(query).length > 0) completeUrl += '?' + getQueryUrl(query)
31 |
32 | const config: any = { url: completeUrl, method };
33 |
34 | if (headers) config.headers = headers;
35 | if (body) config.data = body;
36 | else if (file) {
37 | const formData = new FormData();
38 | Object.entries(file).forEach(([name, f]) => formData.append(name, f));
39 | config.data = formData;
40 | config.headers = { ...config.headers, 'Content-Type': 'multipart/form-data' };
41 | }
42 |
43 | return axios(config)
44 | .then((res) => res.data)
45 | .catch((err) => {
46 | if (err.response && err.response.data && 'error' in err.response.data && 'status' in err.response.data.error)
47 | return err.response.data;
48 |
49 | return {
50 | error: {
51 | name: 'Axios Error',
52 | status: 400,
53 | data: err,
54 | },
55 | };
56 | });
57 | };`,
58 | { parser: 'typescript', singleQuote: true }
59 | );
60 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/project/compileWithCommandLine.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | query: { serverUrl: string; projectName: string; projectId: string };
5 | headers: { token: string };
6 | file: { projectZipBuffer: File | Buffer };
7 | }): Promise<
8 | | {
9 | data: {
10 | project: {
11 | createdAt: Date;
12 | name: string;
13 | owner: string;
14 | serverUrl: string;
15 | provider: 'github' | 'gitlab' | 'cli';
16 | subscribedLanguages: Array<'python' | 'javascript' | 'typescript'>;
17 | lastCompilationSuccess: false | true;
18 | pendingCompilation: false | true;
19 | githubRepo?: {
20 | id: number;
21 | name: string;
22 | owner: string;
23 | full_name: string;
24 | visibility: 'private' | 'public';
25 | createdAt: Date;
26 | };
27 | } & { _id: string };
28 | user: { username: string } & { _id: string };
29 | };
30 | error: null;
31 | }
32 | | {
33 | data: null;
34 | error:
35 | | { name: 'Wrong permission'; data?: any; status: 401 }
36 | | { name: 'Invalid token'; data?: any; status: 401 }
37 | | { status: 404; name: 'Document not found' }
38 | | { name: 'Headers schema validation error'; status: 422; data: any }
39 | | { name: 'Headers schema validation error'; status: 422; data: any }
40 | | { name: 'Query schema validation error'; status: 422; data: any }
41 | | { name: 'Axios Error'; status: 400; data: any }
42 | | { name: 'Internal Server Error'; status: 500 };
43 | }
44 | > => {
45 | const res = await Fetch({
46 | ...data,
47 | method: 'POST',
48 | path: '/project/compileWithCommandLine',
49 | });
50 |
51 | if (res.error && typeof res.error.status === 'number')
52 | return { data: null, error: res.error };
53 | else return { data: res, error: null };
54 | };
55 |
--------------------------------------------------------------------------------
/www/docs/examples/example.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Example'
3 | ---
4 |
5 | # Example
6 |
7 | ```ts twoslash title='server.ts' showLineNumbers
8 | import { initBridge, handler, onError, StatusCode, httpError, apply } from 'bridge';
9 | import express from 'express';
10 | // You can also use Yup or Superstruct for data validation
11 | import z from 'zod';
12 |
13 | const port = 8080;
14 |
15 | // A middleware is also a handler
16 | const authMiddleware = handler({
17 | headers: z.object({ token: z.string().min(5) }),
18 | resolve: ({ headers }) => {
19 | // ^?
20 | if (headers.token !== 'private_token') return httpError(StatusCode.UNAUTHORIZED, 'Wrong token');
21 | else return { firstName: 'John', name: 'Doe', age: 21 };
22 | },
23 | });
24 |
25 | // A handler can be used as an endpoint
26 | const updateUser = handler({
27 | middlewares: apply(authMiddleware),
28 | body: z.object({ age: z.number() }),
29 | resolve: (data) => {
30 | // ^?
31 | const user = data.middlewares;
32 | user.age = data.body.age;
33 | return user;
34 | },
35 | });
36 |
37 | // You can have multiple endpoints for the same route with different methods with the method function
38 | const routes = {
39 | hey: handler({ resolve: () => 'hey' }), // POST /hey
40 | hello: handler({
41 | query: z.object({ name: z.string().optional() }),
42 | resolve: ({ query }) => `Hello ${query.name}`,
43 | }), // POST /hello
44 | user: {
45 | update: updateUser, // POST /user/update
46 | },
47 | };
48 |
49 | const errorHandler = onError(({ error, path }) => {
50 | // The error object can be modified here before it is sent to the client
51 | if (error.name === 'Internal server error') console.log(path, error); // Send to bug reporting
52 | else console.log(path, error.status, error.name);
53 | });
54 |
55 | // It is also possible to use HTTP Server
56 | const app = express();
57 |
58 | app.use('', initBridge({ routes, errorHandler }).expressMiddleware());
59 |
60 | app.listen(port, () => {
61 | console.log(`Listening on port ${port}`);
62 | });
63 | ```
64 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/project/getMine.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | query: { limit?: string; skip?: string };
5 | headers: { token: string };
6 | }): Promise<
7 | | {
8 | data: {
9 | data: Array<
10 | {
11 | createdAt: Date;
12 | name: string;
13 | owner: string;
14 | serverUrl: string;
15 | provider: 'github' | 'gitlab' | 'cli';
16 | subscribedLanguages: Array<'python' | 'javascript' | 'typescript'>;
17 | lastCompilationSuccess: false | true;
18 | pendingCompilation: false | true;
19 | githubRepo?: {
20 | id: number;
21 | name: string;
22 | owner: string;
23 | full_name: string;
24 | visibility: 'private' | 'public';
25 | createdAt: Date;
26 | };
27 | } & { _id: string }
28 | >;
29 | total: number;
30 | skip: number;
31 | limit: number;
32 | };
33 | error: null;
34 | }
35 | | {
36 | data: null;
37 | error:
38 | | { name: 'Wrong permission'; data?: any; status: 401 }
39 | | { name: 'Expired token'; data?: any; status: 401 }
40 | | { name: 'Invalid token'; data?: any; status: 401 }
41 | | { name: 'Headers schema validation error'; status: 422; data: any }
42 | | { name: 'Query schema validation error'; status: 422; data: any }
43 | | { name: 'Headers schema validation error'; status: 422; data: any }
44 | | { name: 'Query schema validation error'; status: 422; data: any }
45 | | { name: 'Axios Error'; status: 400; data: any }
46 | | { name: 'Internal Server Error'; status: 500 };
47 | }
48 | > => {
49 | const res = await Fetch({
50 | ...data,
51 | method: 'POST',
52 | path: '/project/getMine',
53 | });
54 |
55 | if (res.error && typeof res.error.status === 'number')
56 | return { data: null, error: res.error };
57 | else return { data: res, error: null };
58 | };
59 |
--------------------------------------------------------------------------------
/www/docs/bridge/server_calls.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Server Side Calls'
3 | ---
4 |
5 | # Server Side Calls
6 |
7 | You can directly access the resolve function of any handler. Its type will be inferred automatically.
8 |
9 | ## Example
10 |
11 | ```ts twoslash
12 | import { handler, httpError } from 'bridge';
13 | import z from 'zod';
14 |
15 | const users: Record = {
16 | '1': {
17 | firstName: 'John',
18 | lastName: 'Doe',
19 | },
20 | };
21 |
22 | const getMyIdWithToken = handler({
23 | headers: z.object({ token: z.string() }),
24 | resolve: ({ headers }) => {
25 | if (headers.token === 'token') return { id: '1' };
26 | else return httpError(400, 'Wrong token');
27 | },
28 | });
29 |
30 | const getProfileWithToken = handler({
31 | headers: z.object({ token: z.string() }),
32 | resolve: ({ headers }) => {
33 | const res = getMyIdWithToken.resolve({ headers });
34 | // ^?
35 | if ('error' in res) return res;
36 | return users[res.id];
37 | },
38 | });
39 | ```
40 |
41 | This example shows two handlers that can be used as endpoints and called separately. `getProfileWithToken` uses the resolve function of `getMyIdWithToken`.
42 |
43 | :::caution
44 | The above example doesn't make much sense, it would be more logical to use getMyIdWithToken as a middleware for getProfileWithToken. This would make the code shorter and clearer. Here is the revised code:
45 | :::
46 |
47 | ```ts twoslash
48 | import { handler, httpError, apply } from 'bridge';
49 | import z from 'zod';
50 |
51 | const users: Record = {
52 | '1': {
53 | firstName: 'John',
54 | lastName: 'Doe',
55 | },
56 | };
57 |
58 | const getMyIdWithToken = handler({
59 | headers: z.object({ token: z.string() }),
60 | resolve: ({ headers }) => {
61 | if (headers.token === 'token') return { id: '1' };
62 | else return httpError(400, 'Wrong token');
63 | },
64 | });
65 |
66 | const getProfileWithToken = handler({
67 | middlewares: apply(getMyIdWithToken),
68 | resolve: ({ middlewares }) => users[middlewares.id],
69 | });
70 | ```
71 |
--------------------------------------------------------------------------------
/www/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "www",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "docusaurus": "docusaurus",
7 | "start": "docusaurus start",
8 | "build": "docusaurus build",
9 | "swizzle": "docusaurus swizzle",
10 | "deploy": "docusaurus deploy",
11 | "clear": "docusaurus clear",
12 | "serve": "docusaurus serve",
13 | "write-translations": "docusaurus write-translations",
14 | "write-heading-ids": "docusaurus write-heading-ids",
15 | "typecheck": "tsc"
16 | },
17 | "directories": {
18 | "sdk": "sdk"
19 | },
20 | "dependencies": {
21 | "@docusaurus/core": "2.2.0",
22 | "@docusaurus/plugin-google-analytics": "^2.2.0",
23 | "@docusaurus/plugin-sitemap": "^2.3.1",
24 | "@docusaurus/preset-classic": "2.2.0",
25 | "@heroicons/react": "^2.0.13",
26 | "@mdx-js/react": "^1.6.22",
27 | "@tailwindcss/line-clamp": "^0.4.2",
28 | "@vercel/analytics": "^0.1.8",
29 | "autoprefixer": "^10.4.13",
30 | "axios": "^1.3.2",
31 | "bridge": "^2.0.42",
32 | "bridge-react-query": "^1.0.8",
33 | "clsx": "^1.2.1",
34 | "docusaurus-preset-shiki-twoslash": "^1.1.38",
35 | "form-data": "^4.0.0",
36 | "formidable": "^2.1.1",
37 | "mixpanel-browser": "^2.45.0",
38 | "postcss": "^8.4.20",
39 | "prism-react-renderer": "^1.3.5",
40 | "react": "^17.0.2",
41 | "react-dom": "^17.0.2",
42 | "react-syntax-highlighter": "^15.5.0",
43 | "superstruct": "^1.0.3",
44 | "tailwindcss": "^3.2.4",
45 | "yup": "^0.32.11",
46 | "zod": "^3.20.2"
47 | },
48 | "devDependencies": {
49 | "@docusaurus/module-type-aliases": "2.2.0",
50 | "@tsconfig/docusaurus": "^1.0.5",
51 | "@types/formidable": "^2.0.5",
52 | "@types/yup": "^0.32.0",
53 | "typescript": "^4.7.4"
54 | },
55 | "browserslist": {
56 | "production": [
57 | ">0.5%",
58 | "not dead",
59 | "not op_mini all"
60 | ],
61 | "development": [
62 | "last 1 chrome version",
63 | "last 1 firefox version",
64 | "last 1 safari version"
65 | ]
66 | },
67 | "engines": {
68 | "node": ">=16.14"
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/sdk-compilers/typescript/write-handlers-file.ts:
--------------------------------------------------------------------------------
1 | import { writeFileAsync, mkdirAsync } from '../../utils';
2 | import { JSONTypeI } from '../../types';
3 | import { BridgeRoutesTree, isHandler } from '../utils';
4 | import { getHandlerTSFileContent } from './compilers/handler-file-compiler';
5 |
6 | const handlerNameToMethod: Record = {
7 | GET_BRIDGE_METHOD: 'GET',
8 | POST_BRIDGE_METHOD: 'POST',
9 | PATCH_BRIDGE_METHOD: 'PATCH',
10 | PUT_BRIDGE_METHOD: 'PUT',
11 | DELETE_BRIDGE_METHOD: 'DELETE',
12 | };
13 |
14 | const handlerNameToFunctionName: Record = {
15 | GET_BRIDGE_METHOD: 'get',
16 | POST_BRIDGE_METHOD: 'post',
17 | PATCH_BRIDGE_METHOD: 'patch',
18 | PUT_BRIDGE_METHOD: 'put',
19 | DELETE_BRIDGE_METHOD: 'delete',
20 | };
21 |
22 | export const writeHandlersFilesAndFolders = async (
23 | JSONType: JSONTypeI,
24 | filePath: string,
25 | routesTree: BridgeRoutesTree,
26 | pathArray: string[] = []
27 | ): Promise => {
28 | if (!('object' in JSONType)) return routesTree;
29 |
30 | const promises: Promise[] = [];
31 |
32 | for (const [key, value] of Object.entries(JSONType.object)) {
33 | if (!('object' in value)) return routesTree;
34 |
35 | if (isHandler(value)) {
36 | const method = handlerNameToMethod[key] || 'POST';
37 | const newKey = handlerNameToFunctionName[key] || key;
38 | const newPathArray = newKey !== key ? [...pathArray] : [...pathArray, newKey];
39 |
40 | promises.push(
41 | writeFileAsync(
42 | `${filePath}/${newKey}.ts`,
43 | getHandlerTSFileContent(value, newPathArray, pathArray.length, method)
44 | )
45 | );
46 | routesTree[newKey] = 'handler';
47 | } else {
48 | promises.push(
49 | mkdirAsync(`${filePath}/${key}`).then(async () => {
50 | routesTree[key] = await writeHandlersFilesAndFolders(value, `${filePath}/${key}`, {}, [...pathArray, key]);
51 | })
52 | );
53 | }
54 | }
55 |
56 | await Promise.all(promises);
57 |
58 | return routesTree;
59 | };
60 |
--------------------------------------------------------------------------------
/www/static/studio/receive.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/www/src/components/HomepageFeatures/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import clsx from 'clsx';
3 | import styles from './styles.module.css';
4 |
5 | type FeatureItem = {
6 | title: string;
7 | Svg: React.ComponentType>;
8 | description: JSX.Element;
9 | };
10 |
11 | const FeatureList: FeatureItem[] = [
12 | {
13 | title: 'Easy to Use',
14 | Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default,
15 | description: (
16 | <>
17 | Docusaurus was designed from the ground up to be easily installed and
18 | used to get your website up and running quickly.
19 | >
20 | ),
21 | },
22 | {
23 | title: 'Focus on What Matters',
24 | Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default,
25 | description: (
26 | <>
27 | Docusaurus lets you focus on your docs, and we'll do the chores. Go
28 | ahead and move your docs into the docs directory.
29 | >
30 | ),
31 | },
32 | {
33 | title: 'Powered by React',
34 | Svg: require('@site/static/img/undraw_docusaurus_react.svg').default,
35 | description: (
36 | <>
37 | Extend or customize your website layout by reusing React. Docusaurus can
38 | be extended while reusing the same header and footer.
39 | >
40 | ),
41 | },
42 | ];
43 |
44 | function Feature({title, Svg, description}: FeatureItem) {
45 | return (
46 |
47 |
48 |
49 |
50 |
51 |
{title}
52 |
{description}
53 |
54 |
55 | );
56 | }
57 |
58 | export default function HomepageFeatures(): JSX.Element {
59 | return (
60 |
61 |
62 |
63 | {FeatureList.map((props, idx) => (
64 |
65 | ))}
66 |
67 |
68 |
69 | );
70 | }
71 |
--------------------------------------------------------------------------------
/packages/bridge-react-query/source/index.ts:
--------------------------------------------------------------------------------
1 | import {
2 | UseMutationOptions,
3 | useQuery,
4 | useMutation,
5 | UseQueryOptions,
6 | QueryKey,
7 | QueryFunction,
8 | MutationFunction,
9 | } from '@tanstack/react-query';
10 |
11 | const useBridgeQuery = (
12 | queryKey: TQueryKey,
13 | queryFn: QueryFunction<
14 | | { data: Exclude; error: undefined }
15 | | { data: undefined; error: Exclude },
16 | TQueryKey
17 | >,
18 | options?: Omit<
19 | UseQueryOptions<
20 | | { data: Exclude; error: undefined }
21 | | { data: undefined; error: Exclude },
22 | Exclude,
23 | Exclude,
24 | TQueryKey
25 | >,
26 | 'queryKey' | 'queryFn' | 'initialData'
27 | > & {
28 | initialData?: () => undefined;
29 | },
30 | ) =>
31 | useQuery(
32 | queryKey,
33 | async (context) => {
34 | const { data, error } = await queryFn(context);
35 | if (error) throw error;
36 | return data as any;
37 | },
38 | options,
39 | );
40 |
41 | const useBridgeMutation = (
42 | mutationFn: MutationFunction<
43 | { data: TData; error: undefined } | { data: undefined; error: TError },
44 | TVariables
45 | >,
46 | options?: Omit<
47 | UseMutationOptions, Exclude, TVariables, TContext>,
48 | 'mutationFn'
49 | >,
50 | ) =>
51 | useMutation(async (input: TVariables) => {
52 | const { data, error } = await mutationFn(input);
53 | if (error) throw error;
54 | return data as Exclude;
55 | }, options);
56 |
57 | export * from '@tanstack/react-query';
58 | export { useBridgeQuery, useBridgeMutation };
59 |
60 | type rs = { error: undefined; data: { yo: true } } | { error: { name: 'sdf' }; data: undefined };
61 |
62 | const req = async (): Promise => ({} as any);
63 |
64 | useBridgeQuery(['d'], () => req(), {
65 | onError: (error) => {},
66 | });
67 |
68 | useBridgeMutation(req, {
69 | onError: (error) => {},
70 | });
71 |
--------------------------------------------------------------------------------
/packages/bridge-compile/bin/parser/ts-parser/index.ts:
--------------------------------------------------------------------------------
1 | import ts from 'typescript';
2 | import { JSONTypeI } from '../../types';
3 | import { createJSONType } from './create-json-type';
4 | import { cleanJSONType } from '../transform-json-type';
5 |
6 | /**
7 | *
8 | * WARNING:
9 | * This is not at all the best way to extract the type of the bridge project
10 | * If all the parameters of the initBridge function are not declared outside any closure,
11 | * the code wont work
12 | *
13 | * TO-DO
14 | * - [ ] Find with ts AST where is the initBridge call and extract the type from there
15 | */
16 | export default (sourceFilePath: string): JSONTypeI => {
17 | try {
18 | const program: ts.Program = ts.createProgram([sourceFilePath], {
19 | // allowJs: true,
20 | target: ts.ScriptTarget.ESNext,
21 | module: ts.ModuleKind.CommonJS,
22 | declaration: true,
23 | declarationMap: true,
24 | sourceMap: true,
25 | strict: true,
26 | noErrorTruncation: true,
27 | forceConsistentCasingInFileNames: true,
28 | skipLibCheck: true,
29 | emitDecoratorMetadata: true,
30 | experimentalDecorators: true,
31 | esModuleInterop: true,
32 | allowSyntheticDefaultImports: true,
33 | resolveJsonModule: true,
34 | moduleResolution: 2,
35 | });
36 |
37 | const checker: ts.TypeChecker = program.getTypeChecker();
38 |
39 | const sourceFile = program.getSourceFile(sourceFilePath);
40 | if (!sourceFile) throw new Error('Program failed to laod sourceFile');
41 |
42 | let BridgeGenereatedTypeNode: ts.Node = null as any;
43 |
44 | ts.forEachChild(sourceFile, (node) => {
45 | if (ts.isTypeAliasDeclaration(node) && node.name.escapedText === 'BridgeGenereatedType')
46 | BridgeGenereatedTypeNode = node;
47 | });
48 |
49 | if (!BridgeGenereatedTypeNode) throw new Error('TS Node not found');
50 |
51 | const JSONType = cleanJSONType(
52 | createJSONType(checker, checker.getTypeAtLocation(BridgeGenereatedTypeNode), BridgeGenereatedTypeNode)
53 | );
54 |
55 | return JSONType;
56 | } catch (err) {
57 | console.error(err);
58 | return { primitive: 'unrecognized', value: `Error in program load` };
59 | }
60 | };
61 |
--------------------------------------------------------------------------------
/packages/bridge-studio/sdk/project/reCompile.ts:
--------------------------------------------------------------------------------
1 | import Fetch from '../bridgeFetchMethod';
2 |
3 | export default async (data: {
4 | query: { projectId: string };
5 | headers: { token: string };
6 | }): Promise<
7 | | {
8 | data: {
9 | createdAt: Date;
10 | name: string;
11 | owner: string;
12 | serverUrl: string;
13 | provider: 'github' | 'gitlab' | 'cli';
14 | subscribedLanguages: Array<'python' | 'javascript' | 'typescript'>;
15 | lastCompilationSuccess: false | true;
16 | pendingCompilation: false | true;
17 | githubRepo?: {
18 | id: number;
19 | name: string;
20 | owner: string;
21 | full_name: string;
22 | visibility: 'private' | 'public';
23 | createdAt: Date;
24 | };
25 | } & { _id: string };
26 | error: null;
27 | }
28 | | {
29 | data: null;
30 | error:
31 | | { name: 'Wrong permission'; data?: any; status: 401 }
32 | | { name: 'Expired token'; data?: any; status: 401 }
33 | | { name: 'Invalid token'; data?: any; status: 401 }
34 | | { status: 404; name: 'Document not found' }
35 | | { name: 'Headers schema validation error'; status: 422; data: any }
36 | | { name: 'User not connected with github'; data?: any; status: 401 }
37 | | {
38 | name: 'Undefined in result of github.getRepoZip';
39 | data?: any;
40 | status: 500;
41 | }
42 | | {
43 | name: 'Project not connected to github or gitlab';
44 | data?: any;
45 | status: 401;
46 | }
47 | | { name: 'Headers schema validation error'; status: 422; data: any }
48 | | { name: 'Query schema validation error'; status: 422; data: any }
49 | | { name: 'Axios Error'; status: 400; data: any }
50 | | { name: 'Internal Server Error'; status: 500 };
51 | }
52 | > => {
53 | const res = await Fetch({
54 | ...data,
55 | method: 'POST',
56 | path: '/project/reCompile',
57 | });
58 |
59 | if (res.error && typeof res.error.status === 'number')
60 | return { data: null, error: res.error };
61 | else return { data: res, error: null };
62 | };
63 |
--------------------------------------------------------------------------------
/www/tailwind.config.js:
--------------------------------------------------------------------------------
1 | // tailwind.config.js
2 | /** @type {import('tailwindcss').Config} */
3 | module.exports = {
4 | content: [
5 | //
6 | './src/**/*.{js,jsx,ts,tsx,md,mdx}',
7 | './docs/**/*.{js,jsx,ts,tsx,md,mdx}',
8 | ],
9 | theme: {
10 | extend: {
11 | colors: {
12 | primary: {
13 | dark: 'var(--ifm-color-primary-dark)',
14 | darker: 'var(--ifm-color-primary-darker)',
15 | darkest: 'var(--ifm-color-primary-darkest)',
16 | DEFAULT: 'var(--ifm-color-primary)',
17 | light: 'var(--ifm-color-primary-light)',
18 | lighter: 'var(--ifm-color-primary-lighter)',
19 | lightest: 'var(--ifm-color-primary-lightest)',
20 | },
21 | t: {
22 | main: '#A175FF',
23 | },
24 | },
25 | },
26 | backgroundImage: (theme) => ({
27 | grad: 'linear-gradient(76.03deg, rgba(10, 117, 255, 0) 0%, rgba(255, 117, 255, 0.5) 19.01%, rgba(120, 117, 255, 0) 45.83%, rgba(120, 117, 255, 0.4) 73.44%, rgba(120, 117, 255, 0.25) 100%)',
28 | "grad-yellow-green": 'linear-gradient(263.08deg, #75E0A2 0%, rgba(117, 224, 162, 0.25) 21.88%, rgba(117, 224, 162, 0.9) 42.71%, rgba(244, 248, 92, 0.3) 65.1%, rgba(244, 248, 92, 0.9) 84.38%, rgba(244, 248, 92, 0.25) 100%)',
29 | grad2:
30 | 'linear-gradient(76.03deg, rgba(120, 117, 255, 0) 0%, rgba(120, 117, 255, 0.5) 19.01%, rgba(120, 117, 255, 0) 45.83%, rgba(120, 117, 255, 0.4) 73.44%, rgba(120, 117, 255, 0.25) 100%)',
31 | "grad-blue-green": "linear-gradient(253.54deg, #59F7C8 0%, rgba(94, 233, 202, 0.5) 17.71%, rgba(99, 220, 204, 0.9) 34.37%, rgba(105, 200, 207, 0.3) 51.04%, rgba(112, 182, 209, 0.6) 68.23%, rgba(116, 170, 211, 0.3) 84.9%, rgba(120, 158, 213, 0) 91.67%, rgba(125, 144, 215, 0.75) 100%)",
32 | 'gradient-conic': 'conic-gradient(var(--tw-gradient-stops))',
33 | }),
34 | keyframes: {
35 | disco: {
36 | '0%': { transform: 'translateY(-50%) rotate(0deg)' },
37 | '100%': { transform: 'translateY(-50%) rotate(360deg)' },
38 | },
39 | },
40 | animation: {
41 | disco: 'disco 1.5s linear infinite',
42 | },
43 | },
44 | darkMode: ['class', '[data-theme="dark"]'],
45 | plugins: [require('@tailwindcss/line-clamp')],
46 | };
47 |
--------------------------------------------------------------------------------
/packages/create-bridge-app/bin/index.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | import os from 'os';
4 | import path from 'path';
5 | import prompts from 'prompts';
6 | import fs from 'fs';
7 | import { execSync } from 'child_process';
8 | import { copy } from './renameSync';
9 |
10 | const launch = async () => {
11 | const slugRegex = /^[a-zA-Z0-9-]+$/;
12 |
13 | const { projectName } = await prompts({
14 | type: 'text',
15 | name: 'projectName',
16 | message: `What's your project's name?`,
17 | validate: (text) =>
18 | slugRegex.test(text) ? true : 'You can only use alphanumeric characters and -',
19 | });
20 |
21 | if (fs.existsSync(`./${projectName}`)) {
22 | const { override } = await prompts({
23 | type: 'confirm',
24 | name: 'override',
25 | message: `A folder in ./${projectName} already exists. Do you want to override it?`,
26 | });
27 |
28 | if (!override) process.exit(1);
29 | fs.rmSync(`./${projectName}`, { recursive: true });
30 | }
31 |
32 | const { template } = await prompts({
33 | type: 'select',
34 | choices: [
35 | { title: 'minimal-express', value: 'minimal-express' },
36 | { title: 'minimal-http', value: 'minimal-http' },
37 | ],
38 | name: 'template',
39 | message: `Which template do you want to use?`,
40 | validate: (text) =>
41 | slugRegex.test(text) ? true : 'You can only use alphanumeric characters and -',
42 | });
43 |
44 | const tempRepoPath = path.join(os.tmpdir(), 'bridgeRepoTemp');
45 |
46 | execSync(`git clone https://github.com/bridge-codes/bridge.git ${tempRepoPath} -q`);
47 |
48 | await copy(path.join(tempRepoPath, path.join('examples', template)), projectName);
49 |
50 | const packageJSONPath = path.join(projectName, 'package.json');
51 | fs.readFile(packageJSONPath, 'utf-8', (err, data) => {
52 | if (err) {
53 | console.error(err);
54 | process.exit(1);
55 | }
56 |
57 | const regexStr = `"name": "${template}",`;
58 | const result = data.replace(new RegExp(regexStr, 'g'), `"name": "${projectName}",`);
59 |
60 | fs.writeFile(packageJSONPath, result, 'utf8', function (err) {
61 | if (err) return console.log(err);
62 | });
63 | });
64 |
65 | fs.rmSync(tempRepoPath, { recursive: true });
66 | };
67 |
68 | launch();
69 |
--------------------------------------------------------------------------------
/www/docs/typescript-sdk.md:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_label: 'Typescript SDK'
3 | ---
4 |
5 | # Typescript SDK
6 |
7 | ## Fetch your Client SDK
8 |
9 | You can simply download the typescript client code with the following command line:
10 |
11 | ```bash title='terminal'
12 | npx fetch-bridge-sdk $serverUrl
13 | ```
14 |
15 | If you do not have axios and form-data installed in your project, the command line will automatically install them for you.
16 |
17 | The upcoming version of the command line will allow you to select your preferred HTTP client library, either axios or fetch, and the required packages will be automatically installed if they are not already present in your project.
18 |
19 |
20 | ## Use it in the frontend
21 |
22 | The Typescript client SDK exports an API constant which can be easily imported into your code and used to access every endpoint of the Bridge API.
23 |
24 | ### Example
25 |
26 | ```ts twoslash title='client.ts' live
27 |
28 | const API = {
29 | user: {
30 | getMe: async (p: {
31 | headers: { token: string }
32 | }): Promise<
33 | | {
34 | data: {
35 | _id: string
36 | username: string;
37 | email: string;
38 | age: number;
39 | language: 'english' | 'french';
40 | avatar?: string;
41 | createdAt: Date;
42 | };
43 | error: undefined;
44 | }
45 | | {
46 | data: undefined;
47 | error:
48 | | { name: 'Wrong permission'; data?: any; status: 401 }
49 | | { status: 404; name: 'User not found' }
50 | | { name: 'Headers schema validation error'; status: 422; data: any }
51 | | { name: 'Axios Error'; status: 400; data: any }
52 | | { name: 'Internal Server Error'; status: 500 };
53 | }
54 | > => '' as any
55 | }
56 | }
57 |
58 | // ---cut---
59 | // import { API } from './api'
60 |
61 | async () => {
62 |
63 | const { data, error } = await API.user.getMe({
64 | headers: { token: 'secretToken' }
65 | })
66 |
67 | if (data) console.log(data)
68 | // ^?
69 |
70 |
71 | if (error) {
72 | switch (error.name) {
73 | case "User not found":
74 | //...
75 | break;
76 | }
77 |
78 | console.log(error)
79 | // ^?
80 | }
81 | }
82 | ```
--------------------------------------------------------------------------------
/packages/bridge/source/core/handlers/data-validator.ts:
--------------------------------------------------------------------------------
1 | // This code was strongly inspired from @trpc/server
2 |
3 | import { httpError, StatusCode } from '../../error';
4 | import { AbstractHandler, Handler } from '../handler';
5 |
6 | type YupParser = { validateSync: (input: unknown) => T };
7 | type SuperstructParser = { create: (input: unknown) => T };
8 | type ZodParser = { parse: (input: any) => T };
9 |
10 | export type DataParser = YupParser | ZodParser | SuperstructParser;
11 |
12 | export type InferDataParser = Val extends DataParser
13 | ? Output
14 | : any;
15 |
16 | export const isZodParser = (parser: any): parser is ZodParser =>
17 | typeof parser?.safeParse === 'function';
18 |
19 | /**
20 | * This handler is used to validate data from the body, the
21 | */
22 | export class DataValidator