Merge branch 'master' into revert-13160-revert-13128-feature/sql-query-aliasing
This commit is contained in:
commit
30bd1deb37
|
@ -0,0 +1,221 @@
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://www.budibase.com">
|
||||||
|
<img alt="Budibase" src="https://res.cloudinary.com/daog6scxm/image/upload/v1696515725/Branding/Assets/Symbol/RGB/Full%20Colour/Budibase_Symbol_RGB_FullColour_cbqvha_1_z5cwq2.svg" width="60" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<h1 align="center">
|
||||||
|
Budibase
|
||||||
|
</h1>
|
||||||
|
<h3 align="center">
|
||||||
|
자체 인프라에서 몇 분 만에 맞춤형 비즈니스 도구를 구축하세요.
|
||||||
|
</h3>
|
||||||
|
<p align="center">
|
||||||
|
Budibase는 개발자와 IT 전문가가 몇 분 만에 맞춤형 애플리케이션을 구축하고 자동화할 수 있는 오픈 소스 로우코드 플랫폼입니다.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 align="center">
|
||||||
|
🤖 🎨 🚀
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img alt="Budibase design ui" src="https://res.cloudinary.com/daog6scxm/image/upload/v1633524049/ui/design-ui-wide-mobile_gdaveq.jpg">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://github.com/Budibase/budibase/releases">
|
||||||
|
<img alt="GitHub all releases" src="https://img.shields.io/github/downloads/Budibase/budibase/total">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/Budibase/budibase/releases">
|
||||||
|
<img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Budibase/budibase">
|
||||||
|
</a>
|
||||||
|
<a href="https://twitter.com/intent/follow?screen_name=budibase">
|
||||||
|
<img src="https://img.shields.io/twitter/follow/budibase?style=social" alt="Follow @budibase" />
|
||||||
|
</a>
|
||||||
|
<img src="https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg" alt="Code of conduct" />
|
||||||
|
<a href="https://codecov.io/gh/Budibase/budibase">
|
||||||
|
<img src="https://codecov.io/gh/Budibase/budibase/graph/badge.svg?token=E8W2ZFXQOH"/>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 align="center">
|
||||||
|
<a href="https://docs.budibase.com/getting-started">소개</a>
|
||||||
|
<span> · </span>
|
||||||
|
<a href="https://docs.budibase.com">문서</a>
|
||||||
|
<span> · </span>
|
||||||
|
<a href="https://github.com/Budibase/budibase/discussions?discussions_q=category%3AIdeas">기능 요청</a>
|
||||||
|
<span> · </span>
|
||||||
|
<a href="https://github.com/Budibase/budibase/issues">버그 보고</a>
|
||||||
|
<span> · </span>
|
||||||
|
지원: <a href="https://github.com/Budibase/budibase/discussions">토론</a>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<br /><br />
|
||||||
|
## ✨ 특징
|
||||||
|
|
||||||
|
### "실제" 소프트웨어를 구축할 수 있습니다.
|
||||||
|
Budibase를 사용하면 고성능 단일 페이지 애플리케이션을 구축할 수 있습니다. 또한 반응형 디자인으로 제작하여 사용자에게 멋진 경험을 제공할 수 있습니다.
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
### 오픈 소스 및 확장성
|
||||||
|
Budibase는 오픈소스이며, GPL v3 라이선스에 따라 공개되어 있습니다. 이는 Budibase가 항상 당신 곁에 있다는 안도감을 줄 것입니다. 그리고 우리는 개발자 친화적인 환경을 제공하고 있기 때문에, 당신은 원하는 만큼 소스 코드를 포크하여 수정하거나 Budibase에 직접 기여할 수 있습니다.
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
### 기존 데이터 또는 처음부터 시작
|
||||||
|
Budibase를 사용하면 다음과 같은 여러 소스에서 데이터를 가져올 수 있습니다: MondoDB, CouchDB, PostgreSQL, MySQL, Airtable, S3, DynamoDB 또는 REST API.
|
||||||
|
|
||||||
|
또는 원하는 경우 외부 도구 없이도 Budibase를 사용하여 처음부터 시작하여 자체 애플리케이션을 구축할 수 있습니다.[데이터 소스 제안](https://github.com/Budibase/budibase/discussions?discussions_q=category%3AIdeas).
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img alt="Budibase data" src="https://res.cloudinary.com/daog6scxm/image/upload/v1636970242/Out%20of%20beta%20launch/data_n1tlhf.png">
|
||||||
|
</p>
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
### 강력한 내장 구성 요소로 애플리케이션을 설계하고 구축할 수 있습니다.
|
||||||
|
|
||||||
|
Budibase에는 아름답게 디자인된 강력한 컴포넌트들이 제공되며, 이를 사용하여 UI를 쉽게 구축할 수 있습니다. 또한, CSS를 통한 스타일링 옵션도 풍부하게 제공되어 보다 창의적인 표현도 가능하다.
|
||||||
|
[Request new component](https://github.com/Budibase/budibase/discussions?discussions_q=category%3AIdeas).
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img alt="Budibase design" src="https://res.cloudinary.com/daog6scxm/image/upload/v1636970243/Out%20of%20beta%20launch/design-like-a-pro_qhlfeu.gif">
|
||||||
|
</p>
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
### 프로세스를 자동화하고, 다른 도구와 연동하고, 웹훅으로 연결하세요!
|
||||||
|
워크플로우와 수동 프로세스를 자동화하여 시간을 절약하세요. 웹훅 이벤트 연결부터 이메일 자동화까지, Budibase에 수행할 작업을 지시하기만 하면 자동으로 처리됩니다. [새로운 자동화 만들기](https://github.com/Budibase/automations)또는[새로운 자동화를 요청할 수 있습니다](https://github.com/Budibase/budibase/discussions?discussions_q=category%3AIdeas).
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img alt="Budibase automations" src="https://res.cloudinary.com/daog6scxm/image/upload/v1636970486/Out%20of%20beta%20launch/automation_riro7u.png">
|
||||||
|
</p>
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
### 선호하는 도구
|
||||||
|
Budibase는 사용자의 선호도에 따라 애플리케이션을 구축할 수 있는 다양한 도구를 통합하고 있습니다.
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img alt="Budibase integrations" src="https://res.cloudinary.com/daog6scxm/image/upload/v1636970242/Out%20of%20beta%20launch/integrations_kc7dqt.png">
|
||||||
|
</p>
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
### 관리자의 천국
|
||||||
|
Budibase는 어떤 규모의 프로젝트에도 유연하게 대응할 수 있으며, Budibase를 사용하면 개인 또는 조직의 서버에서 자체 호스팅하고 사용자, 온보딩, SMTP, 앱, 그룹, 테마 등을 한꺼번에 관리할 수 있습니다. 또한, 사용자나 그룹에 앱 포털을 제공하고 그룹 관리자에게 사용자 관리를 맡길 수도 있다.
|
||||||
|
- 프로모션 비디오: https://youtu.be/xoljVpty_Kw
|
||||||
|
|
||||||
|
<br /><br /><br />
|
||||||
|
|
||||||
|
## 🏁 시작
|
||||||
|
|
||||||
|
Docker, Kubernetes 또는 Digital Ocean을 사용하여 자체 인프라에서 Budibase를 호스팅하거나, 걱정 없이 빠르게 애플리케이션을 구축하려는 경우 클라우드에서 Budibase를 사용할 수 있습니다.
|
||||||
|
|
||||||
|
### [Budibase 셀프 호스팅으로 시작하기](https://docs.budibase.com/docs/hosting-methods)
|
||||||
|
|
||||||
|
- [Docker - single ARM compatible image](https://docs.budibase.com/docs/docker)
|
||||||
|
- [Docker Compose](https://docs.budibase.com/docs/docker-compose)
|
||||||
|
- [Kubernetes](https://docs.budibase.com/docs/kubernetes-k8s)
|
||||||
|
- [Digital Ocean](https://docs.budibase.com/docs/digitalocean)
|
||||||
|
- [Portainer](https://docs.budibase.com/docs/portainer)
|
||||||
|
|
||||||
|
|
||||||
|
### [클라우드에서 Budibase 시작하기](https://budibase.com)
|
||||||
|
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
## 🎓 Budibase 알아보기
|
||||||
|
|
||||||
|
문서 [documentacion de Budibase](https://docs.budibase.com/docs).
|
||||||
|
<br />
|
||||||
|
|
||||||
|
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
## 💬 커뮤니티
|
||||||
|
|
||||||
|
질문하고, 다른 사람을 돕고, 다른 Budibase 사용자와 즐거운 대화를 나눌 수 있는 Budibase 커뮤니티에 여러분을 초대합니다.
|
||||||
|
[깃허브 토론](https://github.com/Budibase/budibase/discussions)
|
||||||
|
<br /><br /><br />
|
||||||
|
|
||||||
|
|
||||||
|
## ❗ 행동강령
|
||||||
|
|
||||||
|
Budibase 는 모든 계층의 사람들을 환영하고 상호 존중하는 환경을 제공하는 데 특별한 주의를 기울이고 있습니다. 저희는 커뮤니티에도 같은 기대를 가지고 있습니다.
|
||||||
|
[**행동 강령**](https://github.com/Budibase/budibase/blob/HEAD/.github/CODE_OF_CONDUCT.md).
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
|
||||||
|
## 🙌 Contribuir en Budibase
|
||||||
|
|
||||||
|
버그 신고부터 코드의 버그 수정에 이르기까지 모든 기여를 감사하고 환영합니다. 새로운 기능을 구현하거나 API를 변경할 계획이 있다면 [여기에 새 메시지](https://github.com/Budibase/budibase/issues),
|
||||||
|
이렇게 하면 여러분의 노력이 헛되지 않도록 보장할 수 있습니다.
|
||||||
|
|
||||||
|
여기에는 다음을 위해 Budibase 환경을 설정하는 방법에 대한 지침이 나와 있습니다. [여기를 클릭하세요](https://github.com/Budibase/budibase/tree/HEAD/docs/CONTRIBUTING.md).
|
||||||
|
|
||||||
|
### 어디서부터 시작해야 할지 혼란스러우신가요?
|
||||||
|
이곳은 기여를 시작하기에 최적의 장소입니다! [First time issues project](https://github.com/Budibase/budibase/projects/22).
|
||||||
|
|
||||||
|
### 리포지토리 구성
|
||||||
|
|
||||||
|
Budibase는 Lerna에서 관리하는 단일 리포지토리입니다. Lerna는 변경 사항이 있을 때마다 이를 동기화하여 Budibase 패키지를 빌드하고 게시합니다. 크게 보면 이러한 패키지가 Budibase를 구성하는 패키지입니다:
|
||||||
|
|
||||||
|
- [packages/builder](https://github.com/Budibase/budibase/tree/HEAD/packages/builder) - budibase builder 클라이언트 측의 svelte 애플리케이션 코드가 포함되어 있습니다.
|
||||||
|
|
||||||
|
- [packages/client](https://github.com/Budibase/budibase/tree/HEAD/packages/client) - budibase builder 클라이언트 측의 svelte 애플리케이션 코드가 포함되어 있습니다.
|
||||||
|
|
||||||
|
- [packages/server](https://github.com/Budibase/budibase/tree/HEAD/packages/server) - Budibase의 서버 부분입니다. 이 Koa 애플리케이션은 빌더에게 Budibase 애플리케이션을 생성하는 데 필요한 것을 제공하는 역할을 합니다. 또한 데이터베이스 및 파일 저장소와 상호 작용할 수 있는 API를 제공합니다.
|
||||||
|
|
||||||
|
자세한 내용은 다음 문서를 참조하세요. [CONTRIBUTING.md](https://github.com/Budibase/budibase/blob/HEAD/docs/CONTRIBUTING.md)
|
||||||
|
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
|
||||||
|
## 📝 라이선스
|
||||||
|
|
||||||
|
Budibase는 오픈 소스이며, 라이선스는 다음과 같습니다 [GPL v3](https://www.gnu.org/licenses/gpl-3.0.en.html). 클라이언트 및 컴포넌트 라이브러리는 다음과 같이 라이선스가 부여됩니다. [MPL](https://directory.fsf.org/wiki/License:MPL-2.0) - 이렇게 하면 빌드한 애플리케이션에 원하는 대로 라이선스를 부여할 수 있습니다.
|
||||||
|
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
## ⭐ 스타 수의 역사
|
||||||
|
|
||||||
|
[![Stargazers over time](https://starchart.cc/Budibase/budibase.svg)](https://starchart.cc/Budibase/budibase)
|
||||||
|
|
||||||
|
빌더 업데이트 중 문제가 발생하는 경우 [여기](https://github.com/Budibase/budibase/blob/HEAD/docs/CONTRIBUTING.md#troubleshooting) 를 참고하여 환경을 정리해 주세요.
|
||||||
|
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
## Contributors ✨
|
||||||
|
|
||||||
|
훌륭한 여러분께 감사할 따름입니다. ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
||||||
|
|
||||||
|
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
<!-- markdownlint-disable -->
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td align="center"><a href="http://martinmck.com"><img src="https://avatars1.githubusercontent.com/u/11256663?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Martin McKeaveney</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=shogunpurple" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=shogunpurple" title="Documentation">📖</a> <a href="https://github.com/Budibase/budibase/commits?author=shogunpurple" title="Tests">⚠️</a> <a href="#infra-shogunpurple" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||||
|
<td align="center"><a href="http://www.michaeldrury.co.uk/"><img src="https://avatars2.githubusercontent.com/u/4407001?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Drury</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=mike12345567" title="Documentation">📖</a> <a href="https://github.com/Budibase/budibase/commits?author=mike12345567" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=mike12345567" title="Tests">⚠️</a> <a href="#infra-mike12345567" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/aptkingston"><img src="https://avatars3.githubusercontent.com/u/9075550?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andrew Kingston</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=aptkingston" title="Documentation">📖</a> <a href="https://github.com/Budibase/budibase/commits?author=aptkingston" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=aptkingston" title="Tests">⚠️</a> <a href="#design-aptkingston" title="Design">🎨</a></td>
|
||||||
|
<td align="center"><a href="https://budibase.com/"><img src="https://avatars3.githubusercontent.com/u/3524181?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Shanks</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=mjashanks" title="Documentation">📖</a> <a href="https://github.com/Budibase/budibase/commits?author=mjashanks" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=mjashanks" title="Tests">⚠️</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/kevmodrome"><img src="https://avatars3.githubusercontent.com/u/534488?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kevin Åberg Kultalahti</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=kevmodrome" title="Documentation">📖</a> <a href="https://github.com/Budibase/budibase/commits?author=kevmodrome" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=kevmodrome" title="Tests">⚠️</a></td>
|
||||||
|
<td align="center"><a href="https://www.budibase.com/"><img src="https://avatars2.githubusercontent.com/u/49767913?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Joe</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=joebudi" title="Documentation">📖</a> <a href="https://github.com/Budibase/budibase/commits?author=joebudi" title="Code">💻</a> <a href="#content-joebudi" title="Content">🖋</a> <a href="#design-joebudi" title="Design">🎨</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/Rory-Powell"><img src="https://avatars.githubusercontent.com/u/8755148?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rory Powell</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=Rory-Powell" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=Rory-Powell" title="Documentation">📖</a> <a href="https://github.com/Budibase/budibase/commits?author=Rory-Powell" title="Tests">⚠️</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center"><a href="https://github.com/PClmnt"><img src="https://avatars.githubusercontent.com/u/5665926?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Peter Clement</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=PClmnt" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=PClmnt" title="Documentation">📖</a> <a href="https://github.com/Budibase/budibase/commits?author=PClmnt" title="Tests">⚠️</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/Conor-Mack"><img src="https://avatars1.githubusercontent.com/u/36074859?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Conor_Mack</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=Conor-Mack" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=Conor-Mack" title="Tests">⚠️</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/pngwn"><img src="https://avatars1.githubusercontent.com/u/12937446?v=4?s=100" width="100px;" alt=""/><br /><sub><b>pngwn</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=pngwn" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=pngwn" title="Tests">⚠️</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/HugoLd"><img src="https://avatars0.githubusercontent.com/u/26521848?v=4?s=100" width="100px;" alt=""/><br /><sub><b>HugoLd</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=HugoLd" title="Code">💻</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/victoriasloan"><img src="https://avatars.githubusercontent.com/u/9913651?v=4?s=100" width="100px;" alt=""/><br /><sub><b>victoriasloan</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=victoriasloan" title="Code">💻</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/yashank09"><img src="https://avatars.githubusercontent.com/u/37672190?v=4?s=100" width="100px;" alt=""/><br /><sub><b>yashank09</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=yashank09" title="Code">💻</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/SOVLOOKUP"><img src="https://avatars.githubusercontent.com/u/53158137?v=4?s=100" width="100px;" alt=""/><br /><sub><b>SOVLOOKUP</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=SOVLOOKUP" title="Code">💻</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/seoulaja"><img src="https://avatars.githubusercontent.com/u/15101654?v=4?s=100" width="100px;" alt=""/><br /><sub><b>seoulaja</b></sub></a><br /><a href="#translation-seoulaja" title="Translation">🌍</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/mslourens"><img src="https://avatars.githubusercontent.com/u/1907152?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Maurits Lourens</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=mslourens" title="Tests">⚠️</a> <a href="https://github.com/Budibase/budibase/commits?author=mslourens" title="Code">💻</a></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- markdownlint-restore -->
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
|
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||||
|
|
||||||
|
이 프로젝트는 다음 사양을 따릅니다. [all-contributors](https://github.com/all-contributors/all-contributors).
|
||||||
|
모든 종류의 기여를 환영합니다!
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "2.20.13",
|
"version": "2.20.14",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*",
|
"packages/*",
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
Document,
|
Document,
|
||||||
isDocument,
|
isDocument,
|
||||||
RowResponse,
|
RowResponse,
|
||||||
|
RowValue,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { getCouchInfo } from "./connections"
|
import { getCouchInfo } from "./connections"
|
||||||
import { directCouchUrlCall } from "./utils"
|
import { directCouchUrlCall } from "./utils"
|
||||||
|
@ -221,7 +222,7 @@ export class DatabaseImpl implements Database {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async allDocs<T extends Document>(
|
async allDocs<T extends Document | RowValue>(
|
||||||
params: DatabaseQueryOpts
|
params: DatabaseQueryOpts
|
||||||
): Promise<AllDocsResponse<T>> {
|
): Promise<AllDocsResponse<T>> {
|
||||||
return this.performCall(db => {
|
return this.performCall(db => {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import {
|
import {
|
||||||
DocumentScope,
|
|
||||||
DocumentDestroyResponse,
|
DocumentDestroyResponse,
|
||||||
DocumentInsertResponse,
|
DocumentInsertResponse,
|
||||||
DocumentBulkResponse,
|
DocumentBulkResponse,
|
||||||
|
@ -13,6 +12,7 @@ import {
|
||||||
DatabasePutOpts,
|
DatabasePutOpts,
|
||||||
DatabaseQueryOpts,
|
DatabaseQueryOpts,
|
||||||
Document,
|
Document,
|
||||||
|
RowValue,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import tracer from "dd-trace"
|
import tracer from "dd-trace"
|
||||||
import { Writable } from "stream"
|
import { Writable } from "stream"
|
||||||
|
@ -79,7 +79,7 @@ export class DDInstrumentedDatabase implements Database {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
allDocs<T extends Document>(
|
allDocs<T extends Document | RowValue>(
|
||||||
params: DatabaseQueryOpts
|
params: DatabaseQueryOpts
|
||||||
): Promise<AllDocsResponse<T>> {
|
): Promise<AllDocsResponse<T>> {
|
||||||
return tracer.trace("db.allDocs", span => {
|
return tracer.trace("db.allDocs", span => {
|
||||||
|
|
|
@ -15,10 +15,14 @@ import {
|
||||||
FieldType,
|
FieldType,
|
||||||
RelationshipFieldMetadata,
|
RelationshipFieldMetadata,
|
||||||
SourceName,
|
SourceName,
|
||||||
|
UpdateDatasourceRequest,
|
||||||
UpdateDatasourceResponse,
|
UpdateDatasourceResponse,
|
||||||
UserCtx,
|
UserCtx,
|
||||||
VerifyDatasourceRequest,
|
VerifyDatasourceRequest,
|
||||||
VerifyDatasourceResponse,
|
VerifyDatasourceResponse,
|
||||||
|
Table,
|
||||||
|
RowValue,
|
||||||
|
DynamicVariable,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import sdk from "../../sdk"
|
import sdk from "../../sdk"
|
||||||
import { builderSocket } from "../../websockets"
|
import { builderSocket } from "../../websockets"
|
||||||
|
@ -90,8 +94,10 @@ async function invalidateVariables(
|
||||||
existingDatasource: Datasource,
|
existingDatasource: Datasource,
|
||||||
updatedDatasource: Datasource
|
updatedDatasource: Datasource
|
||||||
) {
|
) {
|
||||||
const existingVariables: any = existingDatasource.config?.dynamicVariables
|
const existingVariables: DynamicVariable[] =
|
||||||
const updatedVariables: any = updatedDatasource.config?.dynamicVariables
|
existingDatasource.config?.dynamicVariables || []
|
||||||
|
const updatedVariables: DynamicVariable[] =
|
||||||
|
updatedDatasource.config?.dynamicVariables || []
|
||||||
const toInvalidate = []
|
const toInvalidate = []
|
||||||
|
|
||||||
if (!existingVariables) {
|
if (!existingVariables) {
|
||||||
|
@ -103,9 +109,9 @@ async function invalidateVariables(
|
||||||
toInvalidate.push(...existingVariables)
|
toInvalidate.push(...existingVariables)
|
||||||
} else {
|
} else {
|
||||||
// invaldate changed / removed
|
// invaldate changed / removed
|
||||||
existingVariables.forEach((existing: any) => {
|
existingVariables.forEach(existing => {
|
||||||
const unchanged = updatedVariables.find(
|
const unchanged = updatedVariables.find(
|
||||||
(updated: any) =>
|
updated =>
|
||||||
existing.name === updated.name &&
|
existing.name === updated.name &&
|
||||||
existing.queryId === updated.queryId &&
|
existing.queryId === updated.queryId &&
|
||||||
existing.value === updated.value
|
existing.value === updated.value
|
||||||
|
@ -118,24 +124,32 @@ async function invalidateVariables(
|
||||||
await invalidateDynamicVariables(toInvalidate)
|
await invalidateDynamicVariables(toInvalidate)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function update(ctx: UserCtx<any, UpdateDatasourceResponse>) {
|
export async function update(
|
||||||
|
ctx: UserCtx<UpdateDatasourceRequest, UpdateDatasourceResponse>
|
||||||
|
) {
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
const datasourceId = ctx.params.datasourceId
|
const datasourceId = ctx.params.datasourceId
|
||||||
const baseDatasource = await sdk.datasources.get(datasourceId)
|
const baseDatasource = await sdk.datasources.get(datasourceId)
|
||||||
const auth = baseDatasource.config?.auth
|
|
||||||
await invalidateVariables(baseDatasource, ctx.request.body)
|
await invalidateVariables(baseDatasource, ctx.request.body)
|
||||||
|
|
||||||
const isBudibaseSource =
|
const isBudibaseSource =
|
||||||
baseDatasource.type === dbCore.BUDIBASE_DATASOURCE_TYPE
|
baseDatasource.type === dbCore.BUDIBASE_DATASOURCE_TYPE
|
||||||
|
|
||||||
const dataSourceBody = isBudibaseSource
|
const dataSourceBody: Datasource = isBudibaseSource
|
||||||
? { name: ctx.request.body?.name }
|
? {
|
||||||
|
name: ctx.request.body?.name,
|
||||||
|
type: dbCore.BUDIBASE_DATASOURCE_TYPE,
|
||||||
|
source: SourceName.BUDIBASE,
|
||||||
|
}
|
||||||
: ctx.request.body
|
: ctx.request.body
|
||||||
|
|
||||||
let datasource: Datasource = {
|
let datasource: Datasource = {
|
||||||
...baseDatasource,
|
...baseDatasource,
|
||||||
...sdk.datasources.mergeConfigs(dataSourceBody, baseDatasource),
|
...sdk.datasources.mergeConfigs(dataSourceBody, baseDatasource),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this block is specific to GSheets, if no auth set, set it back
|
||||||
|
const auth = baseDatasource.config?.auth
|
||||||
if (auth && !ctx.request.body.auth) {
|
if (auth && !ctx.request.body.auth) {
|
||||||
// don't strip auth config from DB
|
// don't strip auth config from DB
|
||||||
datasource.config!.auth = auth
|
datasource.config!.auth = auth
|
||||||
|
@ -204,7 +218,7 @@ async function destroyInternalTablesBySourceId(datasourceId: string) {
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
|
|
||||||
// Get all internal tables
|
// Get all internal tables
|
||||||
const internalTables = await db.allDocs(
|
const internalTables = await db.allDocs<Table>(
|
||||||
getTableParams(null, {
|
getTableParams(null, {
|
||||||
include_docs: true,
|
include_docs: true,
|
||||||
})
|
})
|
||||||
|
@ -212,8 +226,8 @@ async function destroyInternalTablesBySourceId(datasourceId: string) {
|
||||||
|
|
||||||
// Filter by datasource and return the docs.
|
// Filter by datasource and return the docs.
|
||||||
const datasourceTableDocs = internalTables.rows.reduce(
|
const datasourceTableDocs = internalTables.rows.reduce(
|
||||||
(acc: any, table: any) => {
|
(acc: Table[], table) => {
|
||||||
if (table.doc.sourceId == datasourceId) {
|
if (table.doc?.sourceId == datasourceId) {
|
||||||
acc.push(table.doc)
|
acc.push(table.doc)
|
||||||
}
|
}
|
||||||
return acc
|
return acc
|
||||||
|
@ -254,9 +268,9 @@ export async function destroy(ctx: UserCtx) {
|
||||||
if (datasource.type === dbCore.BUDIBASE_DATASOURCE_TYPE) {
|
if (datasource.type === dbCore.BUDIBASE_DATASOURCE_TYPE) {
|
||||||
await destroyInternalTablesBySourceId(datasourceId)
|
await destroyInternalTablesBySourceId(datasourceId)
|
||||||
} else {
|
} else {
|
||||||
const queries = await db.allDocs(getQueryParams(datasourceId))
|
const queries = await db.allDocs<RowValue>(getQueryParams(datasourceId))
|
||||||
await db.bulkDocs(
|
await db.bulkDocs(
|
||||||
queries.rows.map((row: any) => ({
|
queries.rows.map(row => ({
|
||||||
_id: row.id,
|
_id: row.id,
|
||||||
_rev: row.value.rev,
|
_rev: row.value.rev,
|
||||||
_deleted: true,
|
_deleted: true,
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
import { getDefinition, getDefinitions } from "../../integrations"
|
import { getDefinition, getDefinitions } from "../../integrations"
|
||||||
import { SourceName, UserCtx } from "@budibase/types"
|
import { SourceName, UserCtx } from "@budibase/types"
|
||||||
|
|
||||||
const DISABLED_EXTERNAL_INTEGRATIONS = [SourceName.AIRTABLE]
|
const DISABLED_EXTERNAL_INTEGRATIONS = [
|
||||||
|
SourceName.AIRTABLE,
|
||||||
|
SourceName.BUDIBASE,
|
||||||
|
]
|
||||||
|
|
||||||
export async function fetch(ctx: UserCtx) {
|
export async function fetch(ctx: UserCtx) {
|
||||||
const definitions = await getDefinitions()
|
const definitions = await getDefinitions()
|
||||||
|
|
|
@ -189,11 +189,12 @@ export async function fetchEnrichedRow(ctx: UserCtx) {
|
||||||
const tableId = utils.getTableId(ctx)
|
const tableId = utils.getTableId(ctx)
|
||||||
const rowId = ctx.params.rowId as string
|
const rowId = ctx.params.rowId as string
|
||||||
// need table to work out where links go in row, as well as the link docs
|
// need table to work out where links go in row, as well as the link docs
|
||||||
const [table, row, links] = await Promise.all([
|
const [table, links] = await Promise.all([
|
||||||
sdk.tables.getTable(tableId),
|
sdk.tables.getTable(tableId),
|
||||||
utils.findRow(ctx, tableId, rowId),
|
|
||||||
linkRows.getLinkDocuments({ tableId, rowId, fieldName }),
|
linkRows.getLinkDocuments({ tableId, rowId, fieldName }),
|
||||||
])
|
])
|
||||||
|
let row = await utils.findRow(ctx, tableId, rowId)
|
||||||
|
row = await outputProcessing(table, row)
|
||||||
const linkVals = links as LinkDocumentValue[]
|
const linkVals = links as LinkDocumentValue[]
|
||||||
|
|
||||||
// look up the actual rows based on the ids
|
// look up the actual rows based on the ids
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import {
|
import {
|
||||||
DEFAULT_BB_DATASOURCE_ID,
|
DEFAULT_BB_DATASOURCE_ID,
|
||||||
DEFAULT_INVENTORY_TABLE_ID,
|
|
||||||
DEFAULT_EMPLOYEE_TABLE_ID,
|
DEFAULT_EMPLOYEE_TABLE_ID,
|
||||||
DEFAULT_EXPENSES_TABLE_ID,
|
DEFAULT_EXPENSES_TABLE_ID,
|
||||||
|
DEFAULT_INVENTORY_TABLE_ID,
|
||||||
DEFAULT_JOBS_TABLE_ID,
|
DEFAULT_JOBS_TABLE_ID,
|
||||||
} from "../../constants"
|
} from "../../constants"
|
||||||
import { importToRows } from "../../api/controllers/table/utils"
|
import { importToRows } from "../../api/controllers/table/utils"
|
||||||
|
@ -15,19 +15,21 @@ import { expensesImport } from "./expensesImport"
|
||||||
import { db as dbCore } from "@budibase/backend-core"
|
import { db as dbCore } from "@budibase/backend-core"
|
||||||
import {
|
import {
|
||||||
AutoFieldSubType,
|
AutoFieldSubType,
|
||||||
|
Datasource,
|
||||||
FieldType,
|
FieldType,
|
||||||
RelationshipType,
|
RelationshipType,
|
||||||
Row,
|
Row,
|
||||||
|
SourceName,
|
||||||
Table,
|
Table,
|
||||||
TableSchema,
|
TableSchema,
|
||||||
TableSourceType,
|
TableSourceType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
const defaultDatasource = {
|
const defaultDatasource: Datasource = {
|
||||||
_id: DEFAULT_BB_DATASOURCE_ID,
|
_id: DEFAULT_BB_DATASOURCE_ID,
|
||||||
type: dbCore.BUDIBASE_DATASOURCE_TYPE,
|
type: dbCore.BUDIBASE_DATASOURCE_TYPE,
|
||||||
name: "Sample Data",
|
name: "Sample Data",
|
||||||
source: "BUDIBASE",
|
source: SourceName.BUDIBASE,
|
||||||
config: {},
|
config: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
import newid from "./newid"
|
import newid from "./newid"
|
||||||
import { db as dbCore } from "@budibase/backend-core"
|
import { db as dbCore } from "@budibase/backend-core"
|
||||||
import {
|
import {
|
||||||
FieldType,
|
DatabaseQueryOpts,
|
||||||
|
Datasource,
|
||||||
DocumentType,
|
DocumentType,
|
||||||
FieldSchema,
|
FieldSchema,
|
||||||
RelationshipFieldMetadata,
|
FieldType,
|
||||||
VirtualDocumentType,
|
|
||||||
INTERNAL_TABLE_SOURCE_ID,
|
INTERNAL_TABLE_SOURCE_ID,
|
||||||
DatabaseQueryOpts,
|
RelationshipFieldMetadata,
|
||||||
|
SourceName,
|
||||||
|
VirtualDocumentType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export { DocumentType, VirtualDocumentType } from "@budibase/types"
|
export { DocumentType, VirtualDocumentType } from "@budibase/types"
|
||||||
|
@ -20,11 +22,11 @@ export const enum AppStatus {
|
||||||
DEPLOYED = "published",
|
DEPLOYED = "published",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BudibaseInternalDB = {
|
export const BudibaseInternalDB: Datasource = {
|
||||||
_id: INTERNAL_TABLE_SOURCE_ID,
|
_id: INTERNAL_TABLE_SOURCE_ID,
|
||||||
type: dbCore.BUDIBASE_DATASOURCE_TYPE,
|
type: dbCore.BUDIBASE_DATASOURCE_TYPE,
|
||||||
name: "Budibase DB",
|
name: "Budibase DB",
|
||||||
source: "BUDIBASE",
|
source: SourceName.BUDIBASE,
|
||||||
config: {},
|
config: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ const DEFINITIONS: Record<SourceName, Integration | undefined> = {
|
||||||
[SourceName.REDIS]: redis.schema,
|
[SourceName.REDIS]: redis.schema,
|
||||||
[SourceName.SNOWFLAKE]: snowflake.schema,
|
[SourceName.SNOWFLAKE]: snowflake.schema,
|
||||||
[SourceName.ORACLE]: undefined,
|
[SourceName.ORACLE]: undefined,
|
||||||
|
[SourceName.BUDIBASE]: undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
const INTEGRATIONS: Record<SourceName, any> = {
|
const INTEGRATIONS: Record<SourceName, any> = {
|
||||||
|
@ -56,6 +57,7 @@ const INTEGRATIONS: Record<SourceName, any> = {
|
||||||
[SourceName.REDIS]: redis.integration,
|
[SourceName.REDIS]: redis.integration,
|
||||||
[SourceName.SNOWFLAKE]: snowflake.integration,
|
[SourceName.SNOWFLAKE]: snowflake.integration,
|
||||||
[SourceName.ORACLE]: undefined,
|
[SourceName.ORACLE]: undefined,
|
||||||
|
[SourceName.BUDIBASE]: undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
// optionally add oracle integration if the oracle binary can be installed
|
// optionally add oracle integration if the oracle binary can be installed
|
||||||
|
|
|
@ -85,7 +85,9 @@ async function getImportableDocuments(db: Database) {
|
||||||
const docPromises = []
|
const docPromises = []
|
||||||
for (let docType of DocumentTypesToImport) {
|
for (let docType of DocumentTypesToImport) {
|
||||||
docPromises.push(
|
docPromises.push(
|
||||||
db.allDocs(dbCore.getDocParams(docType, null, { include_docs: true }))
|
db.allDocs<Document>(
|
||||||
|
dbCore.getDocParams(docType, null, { include_docs: true })
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// map the responses to the document itself
|
// map the responses to the document itself
|
||||||
|
|
|
@ -229,7 +229,7 @@ export async function removeSecretSingle(datasource: Datasource) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mergeConfigs(update: Datasource, old: Datasource) {
|
export function mergeConfigs(update: Datasource, old: Datasource) {
|
||||||
if (!update.config) {
|
if (!update.config || !old.config) {
|
||||||
return update
|
return update
|
||||||
}
|
}
|
||||||
// specific to REST datasources, fix the auth configs again if required
|
// specific to REST datasources, fix the auth configs again if required
|
||||||
|
|
|
@ -38,6 +38,7 @@ async function initRoutes(app: Koa) {
|
||||||
|
|
||||||
// api routes
|
// api routes
|
||||||
app.use(api.router.routes())
|
app.use(api.router.routes())
|
||||||
|
app.use(api.router.allowedMethods())
|
||||||
}
|
}
|
||||||
|
|
||||||
async function initPro() {
|
async function initPro() {
|
||||||
|
|
|
@ -32,9 +32,7 @@ export interface FetchDatasourceInfoResponse {
|
||||||
tableNames: string[]
|
tableNames: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateDatasourceRequest extends Datasource {
|
export interface UpdateDatasourceRequest extends Datasource {}
|
||||||
datasource: Datasource
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BuildSchemaFromSourceRequest {
|
export interface BuildSchemaFromSourceRequest {
|
||||||
tablesFilter?: string[]
|
tablesFilter?: string[]
|
||||||
|
|
|
@ -6,6 +6,9 @@ export interface Datasource extends Document {
|
||||||
type: string
|
type: string
|
||||||
name?: string
|
name?: string
|
||||||
source: SourceName
|
source: SourceName
|
||||||
|
// this is a googlesheets specific property which
|
||||||
|
// can be found in the GSheets schema - pertains to SSO creds
|
||||||
|
auth?: { type: string }
|
||||||
// the config is defined by the schema
|
// the config is defined by the schema
|
||||||
config?: Record<string, any>
|
config?: Record<string, any>
|
||||||
plus?: boolean
|
plus?: boolean
|
||||||
|
@ -36,6 +39,12 @@ export interface RestAuthConfig {
|
||||||
config: RestBasicAuthConfig | RestBearerAuthConfig
|
config: RestBasicAuthConfig | RestBearerAuthConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DynamicVariable {
|
||||||
|
name: string
|
||||||
|
queryId: string
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface RestConfig {
|
export interface RestConfig {
|
||||||
url: string
|
url: string
|
||||||
rejectUnauthorized: boolean
|
rejectUnauthorized: boolean
|
||||||
|
@ -47,11 +56,5 @@ export interface RestConfig {
|
||||||
staticVariables: {
|
staticVariables: {
|
||||||
[key: string]: string
|
[key: string]: string
|
||||||
}
|
}
|
||||||
dynamicVariables: [
|
dynamicVariables: DynamicVariable[]
|
||||||
{
|
|
||||||
name: string
|
|
||||||
queryId: string
|
|
||||||
value: string
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,15 +5,15 @@ export interface RowValue {
|
||||||
deleted: boolean
|
deleted: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RowResponse<T extends Document> {
|
export interface RowResponse<T extends Document | RowValue> {
|
||||||
id: string
|
id: string
|
||||||
key: string
|
key: string
|
||||||
error: string
|
error: string
|
||||||
value: T | RowValue
|
value: T
|
||||||
doc?: T
|
doc?: T
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AllDocsResponse<T extends Document> {
|
export interface AllDocsResponse<T extends Document | RowValue> {
|
||||||
offset: number
|
offset: number
|
||||||
total_rows: number
|
total_rows: number
|
||||||
rows: RowResponse<T>[]
|
rows: RowResponse<T>[]
|
||||||
|
|
|
@ -57,6 +57,7 @@ export enum SourceName {
|
||||||
FIRESTORE = "FIRESTORE",
|
FIRESTORE = "FIRESTORE",
|
||||||
REDIS = "REDIS",
|
REDIS = "REDIS",
|
||||||
SNOWFLAKE = "SNOWFLAKE",
|
SNOWFLAKE = "SNOWFLAKE",
|
||||||
|
BUDIBASE = "BUDIBASE",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum IncludeRelationship {
|
export enum IncludeRelationship {
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
import type Nano from "@budibase/nano"
|
import type Nano from "@budibase/nano"
|
||||||
import { AllDocsResponse, AnyDocument, Document, ViewTemplateOpts } from "../"
|
import {
|
||||||
|
AllDocsResponse,
|
||||||
|
AnyDocument,
|
||||||
|
Document,
|
||||||
|
RowValue,
|
||||||
|
ViewTemplateOpts,
|
||||||
|
} from "../"
|
||||||
import { Writable } from "stream"
|
import { Writable } from "stream"
|
||||||
|
|
||||||
export enum SearchIndex {
|
export enum SearchIndex {
|
||||||
|
@ -135,7 +141,7 @@ export interface Database {
|
||||||
opts?: DatabasePutOpts
|
opts?: DatabasePutOpts
|
||||||
): Promise<Nano.DocumentInsertResponse>
|
): Promise<Nano.DocumentInsertResponse>
|
||||||
bulkDocs(documents: AnyDocument[]): Promise<Nano.DocumentBulkResponse[]>
|
bulkDocs(documents: AnyDocument[]): Promise<Nano.DocumentBulkResponse[]>
|
||||||
allDocs<T extends Document>(
|
allDocs<T extends Document | RowValue>(
|
||||||
params: DatabaseQueryOpts
|
params: DatabaseQueryOpts
|
||||||
): Promise<AllDocsResponse<T>>
|
): Promise<AllDocsResponse<T>>
|
||||||
query<T extends Document>(
|
query<T extends Document>(
|
||||||
|
|
Loading…
Reference in New Issue