mirror of
https://github.com/stefanpejcic/openpanel
synced 2025-06-26 18:28:26 +00:00
back
This commit is contained in:
1
packages/devtools-server/.gitignore
vendored
Normal file
1
packages/devtools-server/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.persist.json
|
||||
11
packages/devtools-server/.npmignore
Normal file
11
packages/devtools-server/.npmignore
Normal file
@@ -0,0 +1,11 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
test
|
||||
jest.config.js
|
||||
**/*.spec.ts
|
||||
**/*.spec.tsx
|
||||
**/*.test.ts
|
||||
**/*.test.tsx
|
||||
tsup.config.ts
|
||||
tsconfig.test.json
|
||||
tsconfig.declarations.json
|
||||
283
packages/devtools-server/CHANGELOG.md
Normal file
283
packages/devtools-server/CHANGELOG.md
Normal file
@@ -0,0 +1,283 @@
|
||||
# @refinedev/devtools-server
|
||||
|
||||
## 1.1.22
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5296](https://github.com/refinedev/refine/pull/5296) [`1b031a2c19`](https://github.com/refinedev/refine/commit/1b031a2c19126ec1c01a85ecfbc794dc82480776) Thanks [@aliemir](https://github.com/aliemir)! - Added error conditions on WS and HTTP servers to prevent crashing if ports are already in use. (Issue: #5215, #5294)
|
||||
|
||||
- Updated dependencies [[`00ac812347`](https://github.com/refinedev/refine/commit/00ac8123475748875df513a829684002677b5f43)]:
|
||||
- @refinedev/devtools-ui@1.1.15
|
||||
|
||||
## 1.1.21
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e29a3d37064`](https://github.com/refinedev/refine/commit/e29a3d37064500710dfa588ed5ca9074b93512c5)]:
|
||||
- @refinedev/devtools-ui@1.1.14
|
||||
|
||||
## 1.1.20
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5208](https://github.com/refinedev/refine/pull/5208) [`72f9f608f42`](https://github.com/refinedev/refine/commit/72f9f608f4205cf4f3266068326d029546cd9f88) Thanks [@BatuhanW](https://github.com/BatuhanW)! - chore: update feed URL from next to master branch.
|
||||
|
||||
- Updated dependencies [[`72f9f608f42`](https://github.com/refinedev/refine/commit/72f9f608f4205cf4f3266068326d029546cd9f88)]:
|
||||
- @refinedev/devtools-ui@1.1.13
|
||||
|
||||
## 1.1.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`be899901d0e`](https://github.com/refinedev/refine/commit/be899901d0ed7f9a336ab737b0b8a699f2e58ed3)]:
|
||||
- @refinedev/devtools-ui@1.1.12
|
||||
|
||||
## 1.1.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`be899901d0e`](https://github.com/refinedev/refine/commit/be899901d0ed7f9a336ab737b0b8a699f2e58ed3)]:
|
||||
- @refinedev/devtools-ui@1.1.11
|
||||
|
||||
## 1.1.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5149](https://github.com/refinedev/refine/pull/5149) [`2bd813f62bf`](https://github.com/refinedev/refine/commit/2bd813f62bf55eb1be55ffe5b2c1c7079d7a93f0) Thanks [@aliemir](https://github.com/aliemir)! - Add ability to force fetching the installed package versions
|
||||
|
||||
- [#5148](https://github.com/refinedev/refine/pull/5148) [`38f2a9b2e71`](https://github.com/refinedev/refine/commit/38f2a9b2e7149ad3d5e5c2780e05ddde0285ac3c) Thanks [@aliemir](https://github.com/aliemir)! - Use `node-fetch` to make feed requests to ensure older versions of Node.js are supported.
|
||||
|
||||
- Updated dependencies [[`2bd813f62bf`](https://github.com/refinedev/refine/commit/2bd813f62bf55eb1be55ffe5b2c1c7079d7a93f0)]:
|
||||
- @refinedev/devtools-ui@1.1.10
|
||||
|
||||
## 1.1.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5149](https://github.com/refinedev/refine/pull/5149) [`2bd813f62bf`](https://github.com/refinedev/refine/commit/2bd813f62bf55eb1be55ffe5b2c1c7079d7a93f0) Thanks [@aliemir](https://github.com/aliemir)! - Add ability to force fetching the installed package versions
|
||||
|
||||
- [#5148](https://github.com/refinedev/refine/pull/5148) [`38f2a9b2e71`](https://github.com/refinedev/refine/commit/38f2a9b2e7149ad3d5e5c2780e05ddde0285ac3c) Thanks [@aliemir](https://github.com/aliemir)! - Use `node-fetch` to make feed requests to ensure older versions of Node.js are supported.
|
||||
|
||||
- Updated dependencies [[`2bd813f62bf`](https://github.com/refinedev/refine/commit/2bd813f62bf55eb1be55ffe5b2c1c7079d7a93f0)]:
|
||||
- @refinedev/devtools-ui@1.1.9
|
||||
|
||||
## 1.1.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5144](https://github.com/refinedev/refine/pull/5144) [`be419eb31bc`](https://github.com/refinedev/refine/commit/be419eb31bc7b7a3934f39bcfcbaaa0b9db60be8) Thanks [@aliemir](https://github.com/aliemir)! - Updated auth flows and auth management to cover wider use cases.
|
||||
|
||||
## 1.1.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5144](https://github.com/refinedev/refine/pull/5144) [`be419eb31bc`](https://github.com/refinedev/refine/commit/be419eb31bc7b7a3934f39bcfcbaaa0b9db60be8) Thanks [@aliemir](https://github.com/aliemir)! - Updated auth flows and auth management to cover wider use cases.
|
||||
|
||||
## 1.1.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5140](https://github.com/refinedev/refine/pull/5140) [`78117485899`](https://github.com/refinedev/refine/commit/781174858992bb1d077069d2858a37b44344879e) Thanks [@aliemir](https://github.com/aliemir)! - Updated the devtools running log on terminal to a less attractive one.
|
||||
|
||||
## 1.1.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5140](https://github.com/refinedev/refine/pull/5140) [`78117485899`](https://github.com/refinedev/refine/commit/781174858992bb1d077069d2858a37b44344879e) Thanks [@aliemir](https://github.com/aliemir)! - Updated the devtools running log on terminal to a less attractive one.
|
||||
|
||||
## 1.1.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5082](https://github.com/refinedev/refine/pull/5082) [`61366ebd866`](https://github.com/refinedev/refine/commit/61366ebd86694328fe5a7f4dcf322db3c43bbc9d) Thanks [@aliemir](https://github.com/aliemir)! - Add `/open-in-editor/*` endpoint to server for opening files in vscode
|
||||
|
||||
- Updated dependencies [[`61366ebd866`](https://github.com/refinedev/refine/commit/61366ebd86694328fe5a7f4dcf322db3c43bbc9d)]:
|
||||
- @refinedev/devtools-ui@1.1.8
|
||||
|
||||
## 1.1.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5082](https://github.com/refinedev/refine/pull/5082) [`61366ebd866`](https://github.com/refinedev/refine/commit/61366ebd86694328fe5a7f4dcf322db3c43bbc9d) Thanks [@aliemir](https://github.com/aliemir)! - Add `/open-in-editor/*` endpoint to server for opening files in vscode
|
||||
|
||||
- Updated dependencies [[`61366ebd866`](https://github.com/refinedev/refine/commit/61366ebd86694328fe5a7f4dcf322db3c43bbc9d)]:
|
||||
- @refinedev/devtools-ui@1.1.7
|
||||
|
||||
## 1.1.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#26](https://github.com/TheRakeshPurohit/refine/pull/26) [`7533e541739`](https://github.com/refinedev/refine/commit/7533e541739faadffb763feef8739ac46f62bd17) Thanks [@pull](https://github.com/apps/pull)! - Fixed the issue with conflicting devtools port when `PORT` environment variable is set.
|
||||
|
||||
## 1.1.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5056](https://github.com/refinedev/refine/pull/5056) [`1fa531ebe89`](https://github.com/refinedev/refine/commit/1fa531ebe89bdab2af0dd57db121e2c0e72d44e8) Thanks [@aliemir](https://github.com/aliemir)! - Fixed the issue with conflicting devtools port when `PORT` environment variable is set.
|
||||
|
||||
## 1.1.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5056](https://github.com/refinedev/refine/pull/5056) [`1fa531ebe89`](https://github.com/refinedev/refine/commit/1fa531ebe89bdab2af0dd57db121e2c0e72d44e8) Thanks [@aliemir](https://github.com/aliemir)! - Fixed the issue with conflicting devtools port when `PORT` environment variable is set.
|
||||
|
||||
## 1.1.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5022](https://github.com/refinedev/refine/pull/5022) [`80513a4e42f`](https://github.com/refinedev/refine/commit/80513a4e42f8dda39e01157643594a9e4c32001b) Thanks [@BatuhanW](https://github.com/BatuhanW)! - chore: update README.md
|
||||
|
||||
- fix grammar errors.
|
||||
- make all README.md files consistent.
|
||||
- add code example code snippets.
|
||||
|
||||
- [#5020](https://github.com/refinedev/refine/pull/5020) [`20f5b6128d4`](https://github.com/refinedev/refine/commit/20f5b6128d4ae85904b9b0e2845c1bb2dcae1a44) Thanks [@aliemir](https://github.com/aliemir)! - Fixed the issue with the anchor tags in devtools feeds not opening in a new tab.
|
||||
|
||||
- Updated dependencies [[`80513a4e42f`](https://github.com/refinedev/refine/commit/80513a4e42f8dda39e01157643594a9e4c32001b), [`20f5b6128d4`](https://github.com/refinedev/refine/commit/20f5b6128d4ae85904b9b0e2845c1bb2dcae1a44)]:
|
||||
- @refinedev/devtools-shared@1.1.2
|
||||
- @refinedev/devtools-ui@1.1.6
|
||||
|
||||
## 1.1.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5022](https://github.com/refinedev/refine/pull/5022) [`80513a4e42f`](https://github.com/refinedev/refine/commit/80513a4e42f8dda39e01157643594a9e4c32001b) Thanks [@BatuhanW](https://github.com/BatuhanW)! - chore: update README.md
|
||||
|
||||
- fix grammar errors.
|
||||
- make all README.md files consistent.
|
||||
- add code example code snippets.
|
||||
|
||||
- [#5020](https://github.com/refinedev/refine/pull/5020) [`20f5b6128d4`](https://github.com/refinedev/refine/commit/20f5b6128d4ae85904b9b0e2845c1bb2dcae1a44) Thanks [@aliemir](https://github.com/aliemir)! - Fixed the issue with the anchor tags in devtools feeds not opening in a new tab.
|
||||
|
||||
- Updated dependencies [[`80513a4e42f`](https://github.com/refinedev/refine/commit/80513a4e42f8dda39e01157643594a9e4c32001b), [`20f5b6128d4`](https://github.com/refinedev/refine/commit/20f5b6128d4ae85904b9b0e2845c1bb2dcae1a44)]:
|
||||
- @refinedev/devtools-shared@1.1.1
|
||||
- @refinedev/devtools-ui@1.1.5
|
||||
|
||||
## 1.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5008](https://github.com/refinedev/refine/pull/5008) [`c8499114e55`](https://github.com/refinedev/refine/commit/c8499114e55968d8b440a8cd6eb2f29fbf3deb94) Thanks [@aliemir](https://github.com/aliemir)! - Fixing the versions of `@refinedev/devtools-ui` and `@refinedev/devtools-shared` dependencies to avoid breaking projects in mismatching releases.
|
||||
|
||||
- Updated dependencies [[`c8499114e55`](https://github.com/refinedev/refine/commit/c8499114e55968d8b440a8cd6eb2f29fbf3deb94), [`c8499114e55`](https://github.com/refinedev/refine/commit/c8499114e55968d8b440a8cd6eb2f29fbf3deb94), [`c8499114e55`](https://github.com/refinedev/refine/commit/c8499114e55968d8b440a8cd6eb2f29fbf3deb94), [`c8499114e55`](https://github.com/refinedev/refine/commit/c8499114e55968d8b440a8cd6eb2f29fbf3deb94)]:
|
||||
- @refinedev/devtools-ui@1.1.4
|
||||
|
||||
## 1.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#5008](https://github.com/refinedev/refine/pull/5008) [`c8499114e55`](https://github.com/refinedev/refine/commit/c8499114e55968d8b440a8cd6eb2f29fbf3deb94) Thanks [@aliemir](https://github.com/aliemir)! - Fixing the versions of `@refinedev/devtools-ui` and `@refinedev/devtools-shared` dependencies to avoid breaking projects in mismatching releases.
|
||||
|
||||
- Updated dependencies [[`c8499114e55`](https://github.com/refinedev/refine/commit/c8499114e55968d8b440a8cd6eb2f29fbf3deb94), [`c8499114e55`](https://github.com/refinedev/refine/commit/c8499114e55968d8b440a8cd6eb2f29fbf3deb94), [`c8499114e55`](https://github.com/refinedev/refine/commit/c8499114e55968d8b440a8cd6eb2f29fbf3deb94), [`c8499114e55`](https://github.com/refinedev/refine/commit/c8499114e55968d8b440a8cd6eb2f29fbf3deb94)]:
|
||||
- @refinedev/devtools-ui@1.1.3
|
||||
|
||||
## 1.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4995](https://github.com/refinedev/refine/pull/4995) [`ab01e8e32d8`](https://github.com/refinedev/refine/commit/ab01e8e32d8c1f141c4284b9c32727e905094082) Thanks [@omeraplak](https://github.com/omeraplak)! - Add Project ID warning and auto-fix action for broken projects
|
||||
|
||||
- [#4995](https://github.com/refinedev/refine/pull/4995) [`ab01e8e32d8`](https://github.com/refinedev/refine/commit/ab01e8e32d8c1f141c4284b9c32727e905094082) Thanks [@omeraplak](https://github.com/omeraplak)! - Fixed package descriptions and usage instructions
|
||||
|
||||
- Updated dependencies [[`ab01e8e32d8`](https://github.com/refinedev/refine/commit/ab01e8e32d8c1f141c4284b9c32727e905094082), [`ab01e8e32d8`](https://github.com/refinedev/refine/commit/ab01e8e32d8c1f141c4284b9c32727e905094082)]:
|
||||
- @refinedev/devtools-ui@1.1.2
|
||||
|
||||
## 1.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4995](https://github.com/refinedev/refine/pull/4995) [`ab01e8e32d8`](https://github.com/refinedev/refine/commit/ab01e8e32d8c1f141c4284b9c32727e905094082) Thanks [@omeraplak](https://github.com/omeraplak)! - Add Project ID warning and auto-fix action for broken projects
|
||||
|
||||
- [#4995](https://github.com/refinedev/refine/pull/4995) [`ab01e8e32d8`](https://github.com/refinedev/refine/commit/ab01e8e32d8c1f141c4284b9c32727e905094082) Thanks [@omeraplak](https://github.com/omeraplak)! - Fixed package descriptions and usage instructions
|
||||
|
||||
- Updated dependencies [[`ab01e8e32d8`](https://github.com/refinedev/refine/commit/ab01e8e32d8c1f141c4284b9c32727e905094082), [`ab01e8e32d8`](https://github.com/refinedev/refine/commit/ab01e8e32d8c1f141c4284b9c32727e905094082)]:
|
||||
- @refinedev/devtools-ui@1.1.1
|
||||
|
||||

|
||||
|
||||
## 1.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4976](https://github.com/refinedev/refine/pull/4976) [`ed026da4239`](https://github.com/refinedev/refine/commit/ed026da4239af5f15afa74fcb180f1086bce63cb) Thanks [@aliemir](https://github.com/aliemir)! - Updated dependency of `@refinedev/devtools-ui`
|
||||
|
||||
- Updated dependencies [[`ed026da4239`](https://github.com/refinedev/refine/commit/ed026da4239af5f15afa74fcb180f1086bce63cb), [`ed026da4239`](https://github.com/refinedev/refine/commit/ed026da4239af5f15afa74fcb180f1086bce63cb)]:
|
||||
- @refinedev/devtools-ui@1.0.2
|
||||
|
||||
## 1.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#4968](https://github.com/refinedev/refine/pull/4968) [`246b3cb6a00`](https://github.com/refinedev/refine/commit/246b3cb6a0000a5b70557d31940cb69113e0397b) Thanks [@aliemir](https://github.com/aliemir)! - Fix feed content url with main github branch
|
||||
|
||||
- Updated dependencies [[`246b3cb6a00`](https://github.com/refinedev/refine/commit/246b3cb6a0000a5b70557d31940cb69113e0397b)]:
|
||||
- @refinedev/devtools-ui@1.0.1
|
||||
|
||||
## 1.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
- [#4960](https://github.com/refinedev/refine/pull/4960) [`d8e464fa2c4`](https://github.com/refinedev/refine/commit/d8e464fa2c461d0fd60050cf18247758ecdc42e3) Thanks [@aliemir](https://github.com/aliemir)! - Initial beta release of refine devtools.🎉
|
||||
|
||||
We're releasing refine devtools in beta. refine devtools is designed to help you debug and develop your refine apps. It will be a collection of features including monitoring queries and mutations, testing out inferencer generated codes, adding and updating refine packages from the UI and more. 🤯
|
||||
|
||||
## Usage
|
||||
|
||||
Install the dependencies using your package manager.
|
||||
|
||||
```bash
|
||||
npm i @refinedev/devtools@next @refinedev/cli@next @refinedev/core@next
|
||||
```
|
||||
|
||||
Add `<DevtoolsProvider />` and `<DevtoolsPanel />` components to your app:
|
||||
|
||||
You'll need to wrap your app with `<DevtoolsProvider />` component and add `<DevtoolsPanel />` component to your app to access the devtools UI.
|
||||
|
||||
```tsx
|
||||
import { DevtoolsPanel, DevtoolsProvider } from "@refinedev/devtools";
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<DevtoolsProvider>
|
||||
<Refine
|
||||
// ...
|
||||
>
|
||||
{/* ... */}
|
||||
</Refine>
|
||||
<DevtoolsPanel />
|
||||
</DevtoolsProvider>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
Then you're good to go 🙌, `<DevtoolsProvider />` will tell refine to connect to the devtools server and track your queries and mutations. `<DevtoolsPanel />` will render the devtools UI in your app.
|
||||
|
||||
note: Devtools only works in development mode and have no overhead on production builds. You don't need to do anything special to exclude DevTools from your bundle.
|
||||
|
||||
Devtools is integrated with `@refinedev/cli` and it will be started automatically in development mode if you have `@refinedev/devtools` installed.
|
||||
|
||||
If you want to start devtools manually or have a custom dev script, you can run `refine devtools` in your project directory or add the following scripts to your `package.json`:
|
||||
|
||||
```js
|
||||
{
|
||||
"scripts": {
|
||||
// If you have not customized the start script.
|
||||
"start": "refine dev", // The devtools server runs automatically; you don't need to do anything.
|
||||
|
||||
// If you have customized the start script.
|
||||
"start": "my-custom-dev-script & refine devtools" // Run the devtools server manually.
|
||||
|
||||
// other scripts
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If you don't have `@refinedev/cli` installed already, you can follow the [installation guide](https://refine.dev/docs/packages/documentation/cli/#how-to-add-to-an-existing-project) to add it to your project.
|
||||
|
||||
These commands will start the devtools server. If you want to access the devtools UI outside of your app without depending on the `<DevtoolsPanel />` component, you can go to `http://localhost:5001` in your browser. 🚀
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`d8e464fa2c4`](https://github.com/refinedev/refine/commit/d8e464fa2c461d0fd60050cf18247758ecdc42e3)]:
|
||||
- @refinedev/devtools-shared@1.0.0
|
||||
- @refinedev/devtools-ui@1.0.0
|
||||
13
packages/devtools-server/FEED.md
Normal file
13
packages/devtools-server/FEED.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Feed
|
||||
|
||||
---section
|
||||
title: refine devtools is now in beta!
|
||||
author: Ali Emir Şen
|
||||
cover: https://refine.ams3.cdn.digitaloceanspaces.com/devtools/first-feed-cover.png
|
||||
date: 2023-09-19T15:14:00.000Z
|
||||
featured: true
|
||||
avatar: https://avatars.githubusercontent.com/u/11361964
|
||||
|
||||
---
|
||||
|
||||
We've released the first beta version of the refine devtools. Feel free to reach us out for any feedback or bug reports. We're looking forward to hearing from you! Check out or [GitHub](https://github.com/refinedev/refine) and [Discord](https://discord.gg/refine) channel.
|
||||
21
packages/devtools-server/LICENSE
Normal file
21
packages/devtools-server/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Refine Dev Corporation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
37
packages/devtools-server/README.md
Normal file
37
packages/devtools-server/README.md
Normal file
@@ -0,0 +1,37 @@
|
||||
<div align="center" style="margin: 30px;">
|
||||
<a href="https://refine.dev">
|
||||
<img alt="refine logo" src="https://refine.ams3.cdn.digitaloceanspaces.com/readme/refine-readme-banner.png">
|
||||
</a>
|
||||
</div>
|
||||
<br/>
|
||||
<div align="center">refine is an open-source, headless React framework for developers building enterprise web applications.
|
||||
|
||||
It eliminates repetitive tasks in CRUD operations and provides industry-standard solutions for critical project components like **authentication**, **access control**, **routing**, **networking**, **state management**, and **i18n**.
|
||||
|
||||
</div>
|
||||
<br/>
|
||||
|
||||
<div align="center">
|
||||
<sub>Created by <a href="https://refine.dev">refine</a></sub>
|
||||
</div>
|
||||
|
||||
## About
|
||||
|
||||
[refine](https://refine.dev/) is **headless by design**, offering unlimited styling and customization options. Moreover, refine ships with ready-made integrations for [Ant Design](https://ant.design/), [Material UI](https://mui.com/material-ui/getting-started/overview/), [Mantine](https://mantine.dev/), and [Chakra UI](https://chakra-ui.com/) for convenience.
|
||||
|
||||
refine has connectors for 15+ backend services, including REST API, [GraphQL](https://graphql.org/), and popular services like [Airtable](https://www.airtable.com/), [Strapi](https://strapi.io/), [Supabase](https://supabase.com/), [Firebase](https://firebase.google.com/), and [Directus](https://directus.io/)
|
||||
|
||||
[Refer to documentation for more info about refine→](https://refine.dev/docs/)
|
||||
[Step up to refine tutorials →](https://refine.dev/docs/tutorial/introduction/index/)
|
||||
|
||||
## Documentation
|
||||
|
||||
This package is an internal package and a part of the `@refinedev/devtools` package.
|
||||
|
||||
For more detailed information an usage, refer to the [refine devtools documentation](https://refine.dev/docs/packages/devtools)
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
npm install @refinedev/devtools
|
||||
```
|
||||
15
packages/devtools-server/jest.config.js
Normal file
15
packages/devtools-server/jest.config.js
Normal file
@@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
preset: "ts-jest",
|
||||
rootDir: "./",
|
||||
displayName: "react-hook-form",
|
||||
testPathIgnorePatterns: ["<rootDir>/node_modules/", "<rootDir>/dist/"],
|
||||
testEnvironment: "jsdom",
|
||||
transform: {
|
||||
"^.+\\.tsx?$": [
|
||||
"ts-jest",
|
||||
{
|
||||
tsconfig: "<rootDir>/tsconfig.test.json",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
92
packages/devtools-server/package.json
Normal file
92
packages/devtools-server/package.json
Normal file
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"name": "@refinedev/devtools-server",
|
||||
"private": false,
|
||||
"description": "refine devtools offers a set of features from monitoring to quickly prototyping a UI.",
|
||||
"author": "refine",
|
||||
"version": "1.1.22",
|
||||
"license": "MIT",
|
||||
"module": "dist/esm/index.js",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"files": [
|
||||
"dist",
|
||||
"src"
|
||||
],
|
||||
"bin": {
|
||||
"refine-devtools": "./dist/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"scripts": {
|
||||
"start:client": "vite build --watch --force --config src/client/vite.config.ts",
|
||||
"build:client": "NODE_ENV=production tsc && vite build --config src/client/vite.config.ts",
|
||||
"start:server": "node dist/cli.js",
|
||||
"start": "npm run start:client & tsup --watch --format esm,cjs,iife --legacy-output",
|
||||
"build": "npm run build:client && tsup --format esm,cjs,iife --minify --legacy-output",
|
||||
"test": "jest --passWithNoTests --runInBand",
|
||||
"prepare": "npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"error-stack-parser": "^2.1.4",
|
||||
"express": "^4.18.2",
|
||||
"@refinedev/devtools-ui": "1.1.15",
|
||||
"@refinedev/devtools-shared": "1.1.2",
|
||||
"@ory/client": "^1.1.25",
|
||||
"http-proxy-middleware": "^2.0.6",
|
||||
"boxen": "^5.1.2",
|
||||
"chalk": "^4.1.2",
|
||||
"dedent": "^0.7.0",
|
||||
"ws": "^8.13.0",
|
||||
"lodash": "^4.17.21",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"execa": "^5.1.1",
|
||||
"gray-matter": "^4.0.3",
|
||||
"fs-extra": "^10.1.0",
|
||||
"marked": "^4.3.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"globby": "^11.1.0",
|
||||
"sanitize-html": "^2.11.0",
|
||||
"preferred-pm": "^3.0.3",
|
||||
"body-parser": "^1.20.2",
|
||||
"jscodeshift": "0.13.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^17.0.0 || ^18.0.0",
|
||||
"@types/react": "^17.0.0 || ^18.0.0",
|
||||
"@types/react-dom": "^17.0.0 || ^18.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/jest-dom": "^5.16.4",
|
||||
"@esbuild-plugins/node-resolve": "^0.1.4",
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
"@types/jest": "^29.2.4",
|
||||
"@types/ws": "^8.5.5",
|
||||
"@types/dedent": "^0.7.0",
|
||||
"@types/jscodeshift": "^0.11.5",
|
||||
"jest": "^29.3.1",
|
||||
"jest-environment-jsdom": "^29.3.1",
|
||||
"react-router-dom": "^6.8.1",
|
||||
"ts-jest": "^29.0.3",
|
||||
"tslib": "^2.3.1",
|
||||
"tsup": "^6.7.0",
|
||||
"@vitejs/plugin-react": "^4.0.0",
|
||||
"vite": "^4.3.1",
|
||||
"typescript": "^4.7.4",
|
||||
"esbuild-copy-static-files": "^0.1.0",
|
||||
"@types/sanitize-html": "^2.9.0",
|
||||
"@types/marked": "^5.0.1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/refinedev/refine.git",
|
||||
"directory": "packages/devtools"
|
||||
},
|
||||
"gitHead": "829f5a516f98c06f666d6be3e6e6099c75c07719",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
4
packages/devtools-server/src/cli.ts
Normal file
4
packages/devtools-server/src/cli.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env node
|
||||
import { server } from "./index";
|
||||
|
||||
server();
|
||||
31
packages/devtools-server/src/client/index.html
Normal file
31
packages/devtools-server/src/client/index.html
Normal file
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' fill='none' viewBox='0 0 40 40'%3E%3Cpath fill='%231D1E30' fill-rule='evenodd' d='M23.9975 12.3333c0 2.2092-1.7909 4-4 4-2.2091 0-4-1.7908-4-4 0-2.2091 1.7909-4 4-4 2.2091 0 4 1.7909 4 4Z' clip-rule='evenodd'/%3E%3Cpath fill='%231D1E30' fill-rule='evenodd' d='M13.7975 12.2c0-3.4242 2.7758-6.2 6.2-6.2 3.4242 0 6.2 2.7758 6.2 6.2v15.6c0 3.4242-2.7758 6.2-6.2 6.2-3.4242 0-6.2-2.7758-6.2-6.2V12.2Zm6.2-5.2c-2.8719 0-5.2 2.3281-5.2 5.2v15.6c0 2.8719 2.3281 5.2 5.2 5.2s5.2-2.3281 5.2-5.2V12.2c0-2.8719-2.3281-5.2-5.2-5.2Z' clip-rule='evenodd'/%3E%3Cpath fill='%231D1E30' fill-rule='evenodd' d='M15.5279 1.0557a9.9998 9.9998 0 0 1 8.9442 0l10 5C37.86 7.7497 40 11.2123 40 15v10c0 3.7877-2.14 7.2504-5.5279 8.9443l-10 5a10 10 0 0 1-8.9442 0l-10-5C2.14 32.2504 0 28.7877 0 25V15c0-3.7877 2.14-7.2504 5.5279-8.9443l10-5Zm.4472.8945a8.9999 8.9999 0 0 1 8.0498 0l10 5C37.074 8.4747 39 11.591 39 15v10c0 3.4089-1.926 6.5253-4.9751 8.0498l-10 5a8.9997 8.9997 0 0 1-8.0498 0l-10-5C2.926 31.5253 1 28.4089 1 25V15c0-3.4089 1.926-6.5253 4.975-8.0498l10.0001-5Z' clip-rule='evenodd'/%3E%3Cpath fill='%231D1E30' fill-rule='evenodd' d='M15.9751 1.9502a8.9999 8.9999 0 0 1 8.0498 0l10 5C37.074 8.4747 39 11.591 39 15v10c0 3.4089-1.926 6.5253-4.9751 8.0498l-10 5a8.9997 8.9997 0 0 1-8.0498 0l-10-5C2.926 31.5253 1 28.4089 1 25V15c0-3.4089 1.926-6.5253 4.975-8.0498l10.0001-5ZM19.9975 6c-3.4242 0-6.2 2.7758-6.2 6.2v15.6c0 3.4242 2.7758 6.2 6.2 6.2 3.4242 0 6.2-2.7758 6.2-6.2V12.2c0-3.4242-2.7758-6.2-6.2-6.2Z' clip-rule='evenodd'/%3E%3Cpath fill='url(%23paint0_linear_504_1891)' fill-rule='evenodd' d='M23.9975 12.3333c0 2.2092-1.7909 4-4 4-2.2091 0-4-1.7908-4-4 0-2.2091 1.7909-4 4-4 2.2091 0 4 1.7909 4 4Z' clip-rule='evenodd'/%3E%3Cpath fill='url(%23paint1_linear_504_1891)' fill-rule='evenodd' d='M13.7975 12.2c0-3.4242 2.7758-6.2 6.2-6.2 3.4242 0 6.2 2.7758 6.2 6.2v15.6c0 3.4242-2.7758 6.2-6.2 6.2-3.4242 0-6.2-2.7758-6.2-6.2V12.2Zm6.2-5.2c-2.8719 0-5.2 2.3281-5.2 5.2v15.6c0 2.8719 2.3281 5.2 5.2 5.2s5.2-2.3281 5.2-5.2V12.2c0-2.8719-2.3281-5.2-5.2-5.2Z' clip-rule='evenodd'/%3E%3Cpath fill='url(%23paint2_linear_504_1891)' fill-rule='evenodd' d='M15.5279 1.0557a9.9998 9.9998 0 0 1 8.9442 0l10 5C37.86 7.7497 40 11.2123 40 15v10c0 3.7877-2.14 7.2504-5.5279 8.9443l-10 5a10 10 0 0 1-8.9442 0l-10-5C2.14 32.2504 0 28.7877 0 25V15c0-3.7877 2.14-7.2504 5.5279-8.9443l10-5Zm.4472.8945a8.9999 8.9999 0 0 1 8.0498 0l10 5C37.074 8.4747 39 11.591 39 15v10c0 3.4089-1.926 6.5253-4.9751 8.0498l-10 5a8.9997 8.9997 0 0 1-8.0498 0l-10-5C2.926 31.5253 1 28.4089 1 25V15c0-3.4089 1.926-6.5253 4.975-8.0498l10.0001-5Z' clip-rule='evenodd'/%3E%3Cpath fill='url(%23paint3_radial_504_1891)' fill-rule='evenodd' d='M15.9751 1.9502a8.9999 8.9999 0 0 1 8.0498 0l10 5C37.074 8.4747 39 11.591 39 15v10c0 3.4089-1.926 6.5253-4.9751 8.0498l-10 5a8.9997 8.9997 0 0 1-8.0498 0l-10-5C2.926 31.5253 1 28.4089 1 25V15c0-3.4089 1.926-6.5253 4.975-8.0498l10.0001-5ZM19.9975 6c-3.4242 0-6.2 2.7758-6.2 6.2v15.6c0 3.4242 2.7758 6.2 6.2 6.2 3.4242 0 6.2-2.7758 6.2-6.2V12.2c0-3.4242-2.7758-6.2-6.2-6.2Z' clip-rule='evenodd'/%3E%3Cdefs%3E%3ClinearGradient id='paint0_linear_504_1891' x1='20' x2='20' y1='8.5' y2='16.5' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%2347EBEB'/%3E%3Cstop offset='1' stop-color='%2347EBEB' stop-opacity='.5'/%3E%3C/linearGradient%3E%3ClinearGradient id='paint1_linear_504_1891' x1='20' x2='20' y1='6' y2='34' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%2347EBEB'/%3E%3Cstop offset='1' stop-color='%2347EBEB' stop-opacity='.5'/%3E%3C/linearGradient%3E%3ClinearGradient id='paint2_linear_504_1891' x1='20' x2='20' y1='0' y2='40' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%2347EBEB'/%3E%3Cstop offset='.5' stop-color='%2347EBEB' stop-opacity='.5'/%3E%3Cstop offset='1' stop-color='%2347EBEB' stop-opacity='.5'/%3E%3C/linearGradient%3E%3CradialGradient id='paint3_radial_504_1891' cx='0' cy='0' r='1' gradientTransform='matrix(0 40 -40 0 20 0)' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%2347EBEB' stop-opacity='0'/%3E%3Cstop offset='.5' stop-color='%2347EBEB' stop-opacity='.25'/%3E%3Cstop offset='1' stop-color='%2347EBEB' stop-opacity='.5'/%3E%3C/radialGradient%3E%3C/defs%3E%3C/svg%3E" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="description" content="Web site created using refine" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<!-- <link rel="manifest" href="/manifest.json" /> -->
|
||||
<title>refine devtools</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="./index.tsx"></script>
|
||||
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
--></body>
|
||||
</html>
|
||||
10
packages/devtools-server/src/client/index.tsx
Normal file
10
packages/devtools-server/src/client/index.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import { renderDevTools } from "@refinedev/devtools-ui";
|
||||
import "@refinedev/devtools-ui/style.css";
|
||||
|
||||
const container = document.getElementById("root");
|
||||
|
||||
if (container) {
|
||||
renderDevTools(container);
|
||||
} else {
|
||||
throw new Error("Could not find root element");
|
||||
}
|
||||
11
packages/devtools-server/src/client/vite.config.ts
Normal file
11
packages/devtools-server/src/client/vite.config.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
root: "src/client",
|
||||
build: {
|
||||
emptyOutDir: true,
|
||||
outDir: "../../dist/client",
|
||||
},
|
||||
});
|
||||
12
packages/devtools-server/src/constants.ts
Normal file
12
packages/devtools-server/src/constants.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export const DEFAULT_WS_PORT = 5002;
|
||||
export const DEFAULT_SERVER_PORT = 5001;
|
||||
|
||||
export const WS_PORT = DEFAULT_WS_PORT;
|
||||
export const SERVER_PORT = DEFAULT_SERVER_PORT;
|
||||
|
||||
export const REFINE_API_URL = __DEVELOPMENT__
|
||||
? "https://develop.cloud.refine.dev"
|
||||
: "https://cloud2.refine.dev";
|
||||
|
||||
export const FEED_MD_URL =
|
||||
"https://raw.githubusercontent.com/refinedev/refine/master/packages/devtools-server/FEED.md";
|
||||
34
packages/devtools-server/src/create-db.ts
Normal file
34
packages/devtools-server/src/create-db.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import {
|
||||
DevtoolsEvent,
|
||||
DevtoolsEventPayloads,
|
||||
} from "@refinedev/devtools-shared";
|
||||
import type { WebSocket } from "ws";
|
||||
|
||||
export type Activity =
|
||||
DevtoolsEventPayloads[DevtoolsEvent.DEVTOOLS_ACTIVITY_UPDATE]["updatedActivities"][number];
|
||||
|
||||
export type Data = {
|
||||
connectedApp: null | string;
|
||||
clientWs: null | WebSocket;
|
||||
devtoolsWsClients: WebSocket[];
|
||||
appWsClients: WebSocket[];
|
||||
activities: Activity[];
|
||||
packages: string[];
|
||||
};
|
||||
|
||||
const defaultData: Data = {
|
||||
connectedApp: null,
|
||||
clientWs: null,
|
||||
// connections
|
||||
devtoolsWsClients: [],
|
||||
appWsClients: [],
|
||||
// data
|
||||
activities: [],
|
||||
packages: [],
|
||||
};
|
||||
|
||||
export const createDb = (): Data => {
|
||||
return {
|
||||
...defaultData,
|
||||
};
|
||||
};
|
||||
1
packages/devtools-server/src/define.d.ts
vendored
Normal file
1
packages/devtools-server/src/define.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
declare const __DEVELOPMENT__: boolean;
|
||||
68
packages/devtools-server/src/feed/get-feed.ts
Normal file
68
packages/devtools-server/src/feed/get-feed.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import fetch from "node-fetch";
|
||||
import matter from "gray-matter";
|
||||
import { marked } from "marked";
|
||||
import sanitizeHtml from "sanitize-html";
|
||||
|
||||
import { Feed, FeedSection } from "@refinedev/devtools-shared";
|
||||
|
||||
import { FEED_MD_URL } from "src/constants";
|
||||
|
||||
const splitSections = (feed: string) => {
|
||||
const sections = feed.split("---section");
|
||||
|
||||
return sections.slice(1).map((section) => `---section${section}`);
|
||||
};
|
||||
|
||||
const contentToHtml = (content: string) => {
|
||||
const renderer = new marked.Renderer();
|
||||
renderer.link = function (...args) {
|
||||
const out = marked.Renderer.prototype.link.apply(this, args);
|
||||
return out.replace(
|
||||
/^<a/,
|
||||
'<a target="_blank" rel="noopener noreferrer"',
|
||||
);
|
||||
};
|
||||
|
||||
const html = marked(content, {
|
||||
renderer,
|
||||
});
|
||||
|
||||
return sanitizeHtml(html, {
|
||||
allowedTags: sanitizeHtml.defaults.allowedTags.concat(["img"]),
|
||||
allowedAttributes: {
|
||||
...sanitizeHtml.defaults.allowedAttributes,
|
||||
img: ["src"],
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const parseSection = (section: string): FeedSection => {
|
||||
const parsed = matter(section.replace("---section", "---"));
|
||||
|
||||
return {
|
||||
...parsed.data,
|
||||
content: contentToHtml(parsed.content),
|
||||
} as FeedSection;
|
||||
};
|
||||
|
||||
const fetchFeed = async () => {
|
||||
try {
|
||||
const response = await fetch(FEED_MD_URL);
|
||||
|
||||
return response.text();
|
||||
} catch (_) {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
export const getFeed = async (): Promise<Feed> => {
|
||||
try {
|
||||
const rawContent = await fetchFeed();
|
||||
const rawSections = splitSections(rawContent);
|
||||
const sections = rawSections.map(parseSection);
|
||||
|
||||
return sections;
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
133
packages/devtools-server/src/index.ts
Normal file
133
packages/devtools-server/src/index.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
import express from "express";
|
||||
|
||||
import { cyanBright, bold } from "chalk";
|
||||
|
||||
import { DevtoolsEvent, receive, send } from "@refinedev/devtools-shared";
|
||||
|
||||
import { serveClient } from "./serve-client";
|
||||
import { serveWs } from "./serve-ws";
|
||||
import { reloadOnChange } from "./reload-on-change";
|
||||
import { setupServer } from "./setup-server";
|
||||
import { Activity, createDb } from "./create-db";
|
||||
import { serveApi } from "./serve-api";
|
||||
import { SERVER_PORT } from "./constants";
|
||||
import { serveProxy } from "./serve-proxy";
|
||||
import { serveOpenInEditor } from "./serve-open-in-editor";
|
||||
|
||||
type Options = {
|
||||
projectPath?: string;
|
||||
};
|
||||
|
||||
export const server = async ({ projectPath = process.cwd() }: Options = {}) => {
|
||||
const app = express();
|
||||
const ws = serveWs();
|
||||
|
||||
const db = createDb();
|
||||
|
||||
ws.on("connection", (client) => {
|
||||
// Initialize development client
|
||||
receive(client as any, DevtoolsEvent.DEVTOOLS_INIT, (data) => {
|
||||
if (db.connectedApp) {
|
||||
// send client the devtools client url if already connected
|
||||
send(client as any, DevtoolsEvent.DEVTOOLS_ALREADY_CONNECTED, {
|
||||
url: db.connectedApp,
|
||||
});
|
||||
} else {
|
||||
db.connectedApp = data.url;
|
||||
db.clientWs = client;
|
||||
|
||||
ws.clients.forEach((c) => {
|
||||
send(c as any, DevtoolsEvent.DEVTOOLS_CONNECTED_APP, {
|
||||
url: db.connectedApp,
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
receive(client as any, DevtoolsEvent.ACTIVITY, (data) => {
|
||||
// match by identifier, if identifier is same, update data instead of pushing
|
||||
const index = db.activities.findIndex(
|
||||
(activity) => activity.identifier === data.identifier,
|
||||
);
|
||||
|
||||
const record: Activity = {
|
||||
...data,
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
};
|
||||
|
||||
if (index > -1) {
|
||||
record.createdAt = db.activities[index].createdAt;
|
||||
|
||||
db.activities[index] = record;
|
||||
} else {
|
||||
db.activities.push(record);
|
||||
}
|
||||
|
||||
ws.clients.forEach((c) => {
|
||||
send(c as any, DevtoolsEvent.DEVTOOLS_ACTIVITY_UPDATE, {
|
||||
updatedActivities: [record],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
receive(
|
||||
client as any,
|
||||
DevtoolsEvent.DEVTOOLS_HIGHLIGHT_IN_MONITOR,
|
||||
({ name }) => {
|
||||
ws.clients.forEach((c) => {
|
||||
send(
|
||||
c as any,
|
||||
DevtoolsEvent.DEVTOOLS_HIGHLIGHT_IN_MONITOR_ACTION,
|
||||
{
|
||||
name,
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
receive(client as any, DevtoolsEvent.DEVTOOLS_LOGIN_SUCCESS, () => {
|
||||
ws.clients.forEach((c) => {
|
||||
send(c as any, DevtoolsEvent.DEVTOOLS_RELOAD_AFTER_LOGIN, {});
|
||||
});
|
||||
});
|
||||
|
||||
// close connected app if client disconnects
|
||||
client.on("close", (_, reason) => {
|
||||
if (__DEVELOPMENT__) {
|
||||
console.log("Client disconnected", ws.clients.size);
|
||||
}
|
||||
|
||||
if (db.clientWs) {
|
||||
if (!ws.clients.has(db.clientWs)) {
|
||||
db.clientWs = null;
|
||||
db.connectedApp = null;
|
||||
|
||||
db.activities = [];
|
||||
|
||||
ws.clients.forEach((c) => {
|
||||
send(
|
||||
c as any,
|
||||
DevtoolsEvent.DEVTOOLS_DISCONNECTED_APP,
|
||||
{
|
||||
url: db.connectedApp,
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (__DEVELOPMENT__) {
|
||||
console.log("Client connected", ws.clients.size);
|
||||
}
|
||||
});
|
||||
|
||||
reloadOnChange(ws);
|
||||
serveClient(app);
|
||||
setupServer(app);
|
||||
serveApi(app, db);
|
||||
serveProxy(app);
|
||||
serveOpenInEditor(app, projectPath);
|
||||
};
|
||||
28
packages/devtools-server/src/packages/get-all-packages.ts
Normal file
28
packages/devtools-server/src/packages/get-all-packages.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { PackageType } from "@refinedev/devtools-shared";
|
||||
import { getInstalledPackageData } from "./get-installed-package-data";
|
||||
import { getPackagesFromPackageJSON } from "./get-packages-from-package-json";
|
||||
import { getChangelog } from "./get-changelog";
|
||||
import { getDocumentation } from "./get-documentation";
|
||||
|
||||
export const getAllPackages = async (projectPath?: string) => {
|
||||
try {
|
||||
const refinePackages = await getPackagesFromPackageJSON(projectPath);
|
||||
const installedVersions = await Promise.all(
|
||||
refinePackages.map(async (packageName) => {
|
||||
const currentInfo = await getInstalledPackageData(packageName);
|
||||
|
||||
return {
|
||||
name: packageName,
|
||||
currentVersion: currentInfo?.version,
|
||||
description: currentInfo?.description,
|
||||
changelog: getChangelog(packageName),
|
||||
documentation: getDocumentation(packageName),
|
||||
} as PackageType;
|
||||
}),
|
||||
);
|
||||
|
||||
return installedVersions;
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
513
packages/devtools-server/src/packages/get-available-packages.ts
Normal file
513
packages/devtools-server/src/packages/get-available-packages.ts
Normal file
@@ -0,0 +1,513 @@
|
||||
import { AvailablePackageType } from "@refinedev/devtools-shared";
|
||||
import dedent from "dedent";
|
||||
import { getPackagesFromPackageJSON } from "./get-packages-from-package-json";
|
||||
|
||||
export const AVAILABLE_PACKAGES: AvailablePackageType[] = [
|
||||
{
|
||||
name: "@refinedev/ably",
|
||||
description: "Ably integration for refine",
|
||||
install: `npm install @refinedev/ably`,
|
||||
usage: dedent(
|
||||
`
|
||||
import { liveProvider, Ably } from "@refinedev/ably";
|
||||
|
||||
export const ablyClient = new Ably.Realtime("YOUR_API_TOKEN");
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Refine
|
||||
liveProvider={liveProvider(ablyClient)}
|
||||
/* ... */
|
||||
>
|
||||
{/* ... */}
|
||||
</Refine>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/airtable",
|
||||
description: "Airtable integration for refine",
|
||||
install: `npm install @refinedev/airtable`,
|
||||
usage: dedent(
|
||||
`
|
||||
import dataProvider from "@refinedev/airtable";
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Refine
|
||||
dataProvider={dataProvider("API_KEY", "BASE_ID")}
|
||||
/* ... */
|
||||
>
|
||||
{/* ... */}
|
||||
</Refine>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/antd",
|
||||
description: "Ant Design integration for refine",
|
||||
install: `npm install @refinedev/antd antd`,
|
||||
usage: dedent(
|
||||
`
|
||||
import { ThemedLayoutV2 } from "@refinedev/antd";
|
||||
|
||||
import "@refinedev/antd/dist/reset.css";
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Refine
|
||||
/* ... */
|
||||
>
|
||||
<ThemedLayoutV2>
|
||||
{/* ... */}
|
||||
</ThemedLayoutV2>
|
||||
</Refine>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/appwrite",
|
||||
description: "Appwrite integration for refine",
|
||||
install: `npm install @refinedev/appwrite`,
|
||||
usage: dedent(
|
||||
`
|
||||
import { dataProvider, liveProvider, Account, Appwrite, Storage } from "@refinedev/appwrite";
|
||||
|
||||
const appwriteClient = new Appwrite();
|
||||
appwriteClient.setEndpoint("API_URL").setProject("PROJECT_ID");
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Refine
|
||||
dataProvider={dataProvider(appwriteClient, { databaseId: "default" })}
|
||||
liveProvider={liveProvider(appwriteClient, { databaseId: "default" })}
|
||||
/* ... */
|
||||
>
|
||||
<ThemedLayout>
|
||||
{/* ... */}
|
||||
</ThemedLayout>
|
||||
</Refine>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/chakra-ui",
|
||||
description: "Chakra UI integration for refine",
|
||||
install: `npm install @refinedev/chakra-ui @chakra-ui/react @emotion/react @emotion/styled framer-motion`,
|
||||
usage: dedent(
|
||||
`
|
||||
import { ThemedLayoutV2 } from "@refinedev/chakra-ui";
|
||||
import { ChakraProvider } from "@chakra-ui/react";
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<ChakraProvider>
|
||||
<Refine
|
||||
/* ... */
|
||||
>
|
||||
<ThemedLayoutV2>
|
||||
{/* ... */}
|
||||
</ThemedLayoutV2>
|
||||
</Refine>
|
||||
</ChakraProvider>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/graphql",
|
||||
description: "GraphQL integration for refine",
|
||||
install: `npm install @refinedev/graphql`,
|
||||
usage: dedent(
|
||||
`
|
||||
import dataProvider, { GraphQLClient } from "@refinedev/graphql";
|
||||
|
||||
const client = new GraphQLClient("YOUR_API_URL");
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Refine
|
||||
dataProvider={dataProvider(client)}
|
||||
/* ... */
|
||||
>
|
||||
{/* ... */}
|
||||
</Refine>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/hasura",
|
||||
description: "GraphQL integration for refine",
|
||||
install: `npm install @refinedev/hasura`,
|
||||
usage: dedent(
|
||||
`
|
||||
import dataProvider, { GraphQLClient } from "@refinedev/hasura";
|
||||
|
||||
const client = new GraphQLClient("HASURA_API_URL", {
|
||||
headers: {
|
||||
"x-hasura-role": "public",
|
||||
},
|
||||
});
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Refine
|
||||
dataProvider={dataProvider(client)}
|
||||
/* ... */
|
||||
>
|
||||
{/* ... */}
|
||||
</Refine>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/inferencer",
|
||||
description: "Auto generate views based on your APIs with refine",
|
||||
install: `npm install @refinedev/inferencer`,
|
||||
usage: dedent(
|
||||
`
|
||||
import { AntdInferencer } from "@refinedev/inferencer/antd";
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Refine
|
||||
/* ... */
|
||||
>
|
||||
<AntdInferencer action="list" resource="posts" />
|
||||
</Refine>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/kbar",
|
||||
description: "Command palette integration with kbar for refine",
|
||||
install: `npm install @refinedev/kbar`,
|
||||
usage: dedent(
|
||||
`
|
||||
import { RefineKbar, RefineKbarProvider } from "@refinedev/kbar";
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<RefineKbarProvider>
|
||||
<Refine
|
||||
/* ... */
|
||||
>
|
||||
<RefineKbar />
|
||||
</Refine>
|
||||
</RefineKbarProvider>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/mantine",
|
||||
description: "Mantine UI integration for refine",
|
||||
install: `npm install @refinedev/mantine @refinedev/react-table @mantine/core @mantine/hooks @mantine/form @mantine/notifications @emotion/react @tabler/icons`,
|
||||
usage: dedent(
|
||||
`
|
||||
import { ThemedLayoutV2 } from "@refinedev/mantine";
|
||||
import { MantineProvider } from "@mantine/core";
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<MantineProvider>
|
||||
<Refine
|
||||
/* ... */
|
||||
>
|
||||
<ThemedLayoutV2>
|
||||
{/* ... */}
|
||||
</ThemedLayoutV2>
|
||||
</Refine>
|
||||
</MantineProvider>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/medusa",
|
||||
description: "Medusa store integration for refine",
|
||||
install: `npm install @refinedev/medusa`,
|
||||
usage: dedent(
|
||||
`
|
||||
import dataProvider, { authProvider } from "@refinedev/medusa";
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Refine
|
||||
dataProvider={dataProvider("API_URL")}
|
||||
authProvider={authProvider("API_URL")}
|
||||
/* ... */
|
||||
>
|
||||
{/* ... */}
|
||||
</Refine>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/mui",
|
||||
description: "Material UI integration for refine",
|
||||
install: `npm install @refinedev/mui @refinedev/react-hook-form @mui/material @mui/lab @mui/x-data-grid @emotion/react @emotion/styled react-hook-form`,
|
||||
usage: dedent(
|
||||
`
|
||||
import { ThemedLayoutV2 } from "@refinedev/mui";
|
||||
|
||||
import CssBaseline from "@mui/material/CssBaseline";
|
||||
import GlobalStyles from "@mui/material/GlobalStyles";
|
||||
import { ThemeProvider } from "@mui/material/styles";
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<ThemeProvider>
|
||||
<CssBaseline />
|
||||
<GlobalStyles styles={{ html: { WebkitFontSmoothing: "auto" } }} />
|
||||
<Refine
|
||||
/* ... */
|
||||
>
|
||||
<ThemedLayoutV2>
|
||||
{/* ... */}
|
||||
</ThemedLayoutV2>
|
||||
</Refine>
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/nestjs-query",
|
||||
description: "NestJS Query data provider integration for refine",
|
||||
install: `npm install @refinedev/nestjs-query graphql-ws`,
|
||||
usage: dedent(
|
||||
`
|
||||
import dataProvider, {
|
||||
GraphQLClient,
|
||||
liveProvider,
|
||||
} from "@refinedev/nestjs-query";
|
||||
|
||||
import { createClient } from "graphql-ws";
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Refine
|
||||
dataProvider={dataProvider(new GraphQLClient( "API_URL" ))}
|
||||
liveProvider={liveProvider(createClient({ url: "WS_URL" }))}
|
||||
/* ... */
|
||||
>
|
||||
{/* ... */}
|
||||
</Refine>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/nestjsx-crud",
|
||||
description: "NestJSX CRUD data provider integration for refine",
|
||||
install: `npm install @refinedev/nestjsx-crud`,
|
||||
usage: dedent(
|
||||
`
|
||||
import dataProvider from "@refinedev/nestjsx-crud";
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Refine
|
||||
dataProvider={dataProvider("API_URL")}
|
||||
/* ... */
|
||||
>
|
||||
{/* ... */}
|
||||
</Refine>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/react-hook-form",
|
||||
description: "React Hook Form integration for refine",
|
||||
install: `npm install @refinedev/react-hook-form react-hook-form`,
|
||||
usage: dedent(
|
||||
`
|
||||
import { useForm } from "@refinedev/react-hook-form";
|
||||
|
||||
const EditPost = () => {
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState,
|
||||
refineCore,
|
||||
} = useForm({
|
||||
refineCoreProps: {
|
||||
resource: "posts",
|
||||
id: "1",
|
||||
},
|
||||
});
|
||||
|
||||
return /* ... */
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/react-table",
|
||||
description: "Tanstack React Table integration for refine",
|
||||
install: `npm install @refinedev/react-table @tanstack/react-table`,
|
||||
usage: dedent(
|
||||
`
|
||||
import { useTable } from "@refinedev/react-table";
|
||||
|
||||
import { ColumnDef, flexRender } from "@tanstack/react-table";
|
||||
|
||||
const EditPost = () => {
|
||||
const columns = React.useMemo<ColumnDef<IPost>[]>(
|
||||
() => [
|
||||
{
|
||||
id: "id",
|
||||
header: "ID",
|
||||
accessorKey: "id",
|
||||
},
|
||||
{
|
||||
id: "title",
|
||||
header: "Title",
|
||||
accessorKey: "title",
|
||||
meta: {
|
||||
filterOperator: "contains",
|
||||
},
|
||||
},
|
||||
], []);
|
||||
|
||||
const tableInstance = useTable({
|
||||
columns,
|
||||
refineCoreProps: {
|
||||
resource: "posts",
|
||||
}
|
||||
});
|
||||
|
||||
return /* ... */
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/simple-rest",
|
||||
description: "Data provider integration for REST APIs with refine",
|
||||
install: `npm install @refinedev/simple-rest`,
|
||||
usage: dedent(
|
||||
`
|
||||
import dataProvider from "@refinedev/simple-rest";
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Refine
|
||||
dataProvider={dataProvider("API_URL")}
|
||||
/* ... */
|
||||
>
|
||||
{/* ... */}
|
||||
</Refine>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/supabase",
|
||||
description:
|
||||
"Data provider and live provider integrations for Supabase with refine",
|
||||
install: `npm install @refinedev/supabase`,
|
||||
usage: dedent(
|
||||
`
|
||||
import { dataProvider, liveProvider, createClient } from "@refinedev/supabase";
|
||||
|
||||
const supabaseClient = createClient("SUPABASE_URL", "SUPABASE_KEY");
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Refine
|
||||
dataProvider={dataProvider(supabaseClient)}
|
||||
liveProvider={liveProvider(supabaseClient)}
|
||||
/* ... */
|
||||
>
|
||||
{/* ... */}
|
||||
</Refine>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/strapi",
|
||||
description: "Strapi integration of refine",
|
||||
install: `npm install @refinedev/strapi axios`,
|
||||
usage: dedent(
|
||||
`
|
||||
import { DataProvider, AuthHelper } from "@refinedev/strapi";
|
||||
|
||||
const axiosInstance = axios.create();
|
||||
const strapiAuthHelper = AuthHelper("API_URL");
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Refine
|
||||
dataProvider={DataProvider("API_URL", axiosInstance)}
|
||||
/* ... */
|
||||
>
|
||||
{/* ... */}
|
||||
</Refine>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "@refinedev/strapi-v4",
|
||||
description: "StrapiV4 integration of refine",
|
||||
install: `npm install @refinedev/strapi-v4 axios`,
|
||||
usage: dedent(
|
||||
`
|
||||
import { DataProvider, AuthHelper } from "@refinedev/strapi-v4";
|
||||
|
||||
const axiosInstance = axios.create();
|
||||
const strapiAuthHelper = AuthHelper("API_URL");
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Refine
|
||||
dataProvider={DataProvider("API_URL", axiosInstance)}
|
||||
/* ... */
|
||||
>
|
||||
{/* ... */}
|
||||
</Refine>
|
||||
);
|
||||
};
|
||||
`.trim(),
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
export const getAvailablePackages = async (projectPath?: string) => {
|
||||
const installedRefinePackages = await getPackagesFromPackageJSON(
|
||||
projectPath,
|
||||
);
|
||||
|
||||
return AVAILABLE_PACKAGES.filter(
|
||||
(p) => !installedRefinePackages.includes(p.name),
|
||||
);
|
||||
};
|
||||
3
packages/devtools-server/src/packages/get-changelog.ts
Normal file
3
packages/devtools-server/src/packages/get-changelog.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const getChangelog = (packageName: string) => {
|
||||
return packageName.replace("@refinedev/", "https://c.refine.dev/");
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
export const getDocumentation = (packageName: string) => {
|
||||
return "https://refine.dev/docs/api-reference/general-concepts/";
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
import fs from "fs";
|
||||
import { getInstalledPackageJSONPath } from "./get-installed-package-json-path";
|
||||
|
||||
export const getInstalledPackageData = async (packageName: string) => {
|
||||
try {
|
||||
const packagePath = await getInstalledPackageJSONPath(packageName);
|
||||
|
||||
if (!packagePath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const parsed = JSON.parse(
|
||||
fs.readFileSync(packagePath, { encoding: "utf-8" }),
|
||||
);
|
||||
|
||||
return {
|
||||
name: parsed.name,
|
||||
version: parsed.version,
|
||||
description: parsed.description,
|
||||
};
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
import path from "path";
|
||||
import globby from "globby";
|
||||
|
||||
export const getInstalledPackageJSONPath = async (packageName: string) => {
|
||||
try {
|
||||
const filesFromGlobbySearch = await globby(
|
||||
`node_modules/${packageName}/package.json`,
|
||||
{
|
||||
onlyFiles: true,
|
||||
},
|
||||
);
|
||||
|
||||
let fileFromModule: string | null = null;
|
||||
|
||||
try {
|
||||
const pkgJsonPath = require.resolve(
|
||||
path.join(packageName, "package.json"),
|
||||
);
|
||||
if (pkgJsonPath) {
|
||||
fileFromModule = pkgJsonPath;
|
||||
}
|
||||
} catch (err) {
|
||||
//
|
||||
}
|
||||
|
||||
return (
|
||||
[
|
||||
...filesFromGlobbySearch,
|
||||
...(fileFromModule ? [fileFromModule] : []),
|
||||
][0] ?? null
|
||||
);
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
import execa from "execa";
|
||||
|
||||
export const getLatestPackageData = async (
|
||||
packageName: string,
|
||||
): Promise<{ name: string; version?: string }> => {
|
||||
try {
|
||||
const { stdout } = await execa("npm", [
|
||||
"view",
|
||||
packageName,
|
||||
"name",
|
||||
"version",
|
||||
"--json",
|
||||
]);
|
||||
const parsed = JSON.parse(stdout);
|
||||
|
||||
return parsed;
|
||||
} catch (e) {
|
||||
return { name: packageName };
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
import path from "path";
|
||||
import { readJSON } from "fs-extra";
|
||||
|
||||
export const getPackagesFromPackageJSON = async (
|
||||
projectPath: string = process.cwd(),
|
||||
) => {
|
||||
const packageJson = await readJSON(path.join(projectPath, "package.json"), {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
|
||||
const refinePackages = Object.keys(packageJson.dependencies).filter(
|
||||
(packageName) => packageName.startsWith("@refinedev/"),
|
||||
);
|
||||
|
||||
return refinePackages;
|
||||
};
|
||||
22
packages/devtools-server/src/packages/update-package.ts
Normal file
22
packages/devtools-server/src/packages/update-package.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import preferredPM from "preferred-pm";
|
||||
import execa from "execa";
|
||||
|
||||
export const updatePackage = async (
|
||||
packages: string[],
|
||||
projectPath: string = process.cwd(),
|
||||
) => {
|
||||
try {
|
||||
const { name: pm } = (await preferredPM(projectPath)) ?? {
|
||||
name: "npm",
|
||||
};
|
||||
|
||||
const { failed } = await execa(pm ?? "npm", [
|
||||
"install",
|
||||
...packages.map((p) => `${p}@latest`),
|
||||
]);
|
||||
|
||||
return !failed;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
import { readJSON } from "fs-extra";
|
||||
import path from "path";
|
||||
|
||||
export const getProjectIdFromPackageJson = async (
|
||||
projectPath = process.cwd(),
|
||||
) => {
|
||||
try {
|
||||
const packageJson = await readJSON(
|
||||
path.join(projectPath, "package.json"),
|
||||
{
|
||||
encoding: "utf-8",
|
||||
},
|
||||
);
|
||||
|
||||
const projectId = packageJson?.refine?.projectId as string;
|
||||
|
||||
if (projectId) {
|
||||
return projectId;
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
import execa from "execa";
|
||||
|
||||
export const setProjectIdToPackageJson = async (
|
||||
projectId: string,
|
||||
projectPath = process.cwd(),
|
||||
) => {
|
||||
try {
|
||||
execa.sync("npm", ["pkg", "set", `refine.projectId=${projectId}`], {
|
||||
cwd: projectPath,
|
||||
});
|
||||
return true;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
import execa from "execa";
|
||||
import path from "path";
|
||||
|
||||
export const setProjectIdToRefineComponent = async (
|
||||
projectId: string,
|
||||
projectPath = process.cwd(),
|
||||
) => {
|
||||
try {
|
||||
const jscodeshiftExecutable = require.resolve(".bin/jscodeshift");
|
||||
|
||||
const execution = execa.sync(
|
||||
jscodeshiftExecutable,
|
||||
[
|
||||
"./",
|
||||
"--extensions=ts,tsx,js,jsx",
|
||||
"--parser=tsx",
|
||||
`--transform=${path.resolve(
|
||||
path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"src",
|
||||
"project-id",
|
||||
"transform.ts",
|
||||
),
|
||||
)}`,
|
||||
`--ignore-pattern=**/.cache/**`,
|
||||
`--ignore-pattern=**/node_modules/**`,
|
||||
`--ignore-pattern=**/build/**`,
|
||||
`--ignore-pattern=**/dist/**`,
|
||||
`--ignore-pattern=**/.next/**`,
|
||||
`--__projectId=${projectId}`,
|
||||
],
|
||||
{
|
||||
cwd: projectPath,
|
||||
timeout: 1000 * 10,
|
||||
},
|
||||
);
|
||||
|
||||
if (execution.stderr) {
|
||||
console.error(execution.stderr);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
return;
|
||||
};
|
||||
92
packages/devtools-server/src/project-id/transform.ts
Normal file
92
packages/devtools-server/src/project-id/transform.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { namedTypes } from "ast-types";
|
||||
import {
|
||||
API,
|
||||
ASTPath,
|
||||
Collection,
|
||||
FileInfo,
|
||||
JSCodeshift,
|
||||
Options,
|
||||
} from "jscodeshift";
|
||||
|
||||
export const parser = "tsx";
|
||||
|
||||
const transformRefineOptions = (
|
||||
j: JSCodeshift,
|
||||
root: Collection<any>,
|
||||
projectId: string,
|
||||
) => {
|
||||
const refineElements: Array<ASTPath<namedTypes.JSXElement>> = [];
|
||||
|
||||
root.findJSXElements("Refine").forEach((path) => {
|
||||
refineElements.push(path);
|
||||
});
|
||||
|
||||
for (const path of refineElements) {
|
||||
const props = path.node.openingElement.attributes;
|
||||
|
||||
const optionsProp: any = props?.find(
|
||||
(attribute) =>
|
||||
attribute.type === "JSXAttribute" &&
|
||||
attribute.name.name === "options",
|
||||
);
|
||||
if (!optionsProp) {
|
||||
path.node.openingElement.attributes?.push(
|
||||
j.jsxAttribute(
|
||||
j.jsxIdentifier("options"),
|
||||
j.jsxExpressionContainer(
|
||||
j.objectExpression([
|
||||
j.objectProperty(
|
||||
j.identifier("projectId"),
|
||||
j.stringLiteral(projectId),
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// for options={optionsProp}
|
||||
if (!optionsProp?.value.expression.properties) {
|
||||
break;
|
||||
}
|
||||
|
||||
// for options has already projectId
|
||||
const hasProjectId = optionsProp?.value.expression.properties.find(
|
||||
(p: any) => {
|
||||
if (p.type === "ObjectProperty") {
|
||||
return p.key.name === "projectId";
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
);
|
||||
|
||||
if (hasProjectId) break;
|
||||
|
||||
optionsProp?.value.expression.properties.push(
|
||||
j.objectProperty(
|
||||
j.identifier("projectId"),
|
||||
j.stringLiteral(projectId),
|
||||
),
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return root;
|
||||
};
|
||||
|
||||
export default function transformer(
|
||||
file: FileInfo,
|
||||
api: API,
|
||||
options: Options,
|
||||
) {
|
||||
const j = api.jscodeshift;
|
||||
const source = j(file.source);
|
||||
|
||||
transformRefineOptions(j, source, options.__projectId);
|
||||
|
||||
return source.toSource();
|
||||
}
|
||||
18
packages/devtools-server/src/project-id/update-project-id.ts
Normal file
18
packages/devtools-server/src/project-id/update-project-id.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { setProjectIdToPackageJson } from "./set-project-id-to-package-json";
|
||||
import { setProjectIdToRefineComponent } from "./set-project-id-to-refine-component";
|
||||
|
||||
export const updateProjectId = async (
|
||||
projectId: string,
|
||||
projectPath = process.cwd(),
|
||||
) => {
|
||||
try {
|
||||
await Promise.all([
|
||||
setProjectIdToPackageJson(projectId, projectPath),
|
||||
setProjectIdToRefineComponent(projectId, projectPath),
|
||||
]);
|
||||
|
||||
return true;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
32
packages/devtools-server/src/reload-on-change.ts
Normal file
32
packages/devtools-server/src/reload-on-change.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { debounce } from "lodash";
|
||||
import { DevtoolsEvent, send } from "@refinedev/devtools-shared";
|
||||
|
||||
import type { Server } from "ws";
|
||||
import { OPEN } from "ws";
|
||||
|
||||
export const reloadOnChange = __DEVELOPMENT__
|
||||
? (ws: Server) => {
|
||||
const reloadEmitter = debounce(() => {
|
||||
setTimeout(() => {
|
||||
ws.clients.forEach((client) => {
|
||||
if (client.readyState === OPEN) {
|
||||
console.log("Reloading connected client...");
|
||||
send(client as any, DevtoolsEvent.RELOAD, {});
|
||||
}
|
||||
});
|
||||
}, 800);
|
||||
}, 1000);
|
||||
|
||||
const watcher = fs.watch(
|
||||
path.resolve(__dirname, "client"),
|
||||
{ recursive: true },
|
||||
reloadEmitter,
|
||||
);
|
||||
|
||||
process.on("SIGTERM", () => {
|
||||
watcher.close();
|
||||
});
|
||||
}
|
||||
: () => 0;
|
||||
169
packages/devtools-server/src/serve-api.ts
Normal file
169
packages/devtools-server/src/serve-api.ts
Normal file
@@ -0,0 +1,169 @@
|
||||
import type { Express } from "express";
|
||||
import { json } from "express";
|
||||
import uniq from "lodash/uniq";
|
||||
import {
|
||||
AvailablePackageType,
|
||||
Feed,
|
||||
PackageType,
|
||||
} from "@refinedev/devtools-shared";
|
||||
|
||||
import { Data } from "./create-db";
|
||||
import { getFeed } from "./feed/get-feed";
|
||||
import { getAllPackages } from "./packages/get-all-packages";
|
||||
import { getAvailablePackages } from "./packages/get-available-packages";
|
||||
import { updatePackage } from "./packages/update-package";
|
||||
import { getLatestPackageData } from "./packages/get-latest-package-data";
|
||||
import { getProjectIdFromPackageJson } from "./project-id/get-project-id-from-package-json";
|
||||
import { updateProjectId } from "./project-id/update-project-id";
|
||||
|
||||
export const serveApi = (app: Express, db: Data) => {
|
||||
app.use("/api", json());
|
||||
|
||||
app.get("/api/connected-app", (_, res) => {
|
||||
res.json({ url: db.connectedApp });
|
||||
});
|
||||
|
||||
app.get("/api/activities", (req, res) => {
|
||||
const { offset = 0, limit = db.activities.length } = req.query;
|
||||
|
||||
res.setHeader("x-total-count", db.activities.length);
|
||||
|
||||
res.json({
|
||||
data: db.activities.slice(Number(offset), Number(limit)),
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/api/activities/reset", (_, res) => {
|
||||
db.activities = [];
|
||||
res.json({ success: true });
|
||||
});
|
||||
|
||||
app.get("/api/unique-trace-items", (req, res) => {
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
res.header(
|
||||
"Access-Control-Allow-Headers",
|
||||
"Origin, X-Requested-With, Content-Type, Accept",
|
||||
);
|
||||
|
||||
const traceItems = db.activities.flatMap(
|
||||
(activity) =>
|
||||
activity.trace?.map((t) => t.function).filter(Boolean) ?? [],
|
||||
) as string[];
|
||||
const uniqueTraceItems = uniq(traceItems);
|
||||
|
||||
res.setHeader("x-total-count", uniqueTraceItems.length);
|
||||
|
||||
res.json({ data: uniqueTraceItems });
|
||||
});
|
||||
|
||||
let cachedInstalledPackages: PackageType[] | null = null;
|
||||
app.get("/api/installed-packages", async (req, res) => {
|
||||
const { force } = req.query ?? {};
|
||||
|
||||
if (!cachedInstalledPackages || force) {
|
||||
cachedInstalledPackages = await getAllPackages();
|
||||
}
|
||||
|
||||
res.header("x-total-count", `${cachedInstalledPackages.length}`);
|
||||
|
||||
res.json({ data: cachedInstalledPackages });
|
||||
});
|
||||
|
||||
let cachedAvailablePackages: AvailablePackageType[] | null = null;
|
||||
app.get("/api/available-packages", async (_, res) => {
|
||||
if (!cachedAvailablePackages) {
|
||||
cachedAvailablePackages = await getAvailablePackages();
|
||||
}
|
||||
|
||||
res.header("x-total-count", `${cachedAvailablePackages.length}`);
|
||||
|
||||
res.json({ data: cachedAvailablePackages });
|
||||
});
|
||||
|
||||
const cachedLatestPackages = new Map<string, any>();
|
||||
app.get("/api/packages/:packageName/latest", async (req, res) => {
|
||||
const { packageName } = req.params ?? {};
|
||||
|
||||
if (!packageName) {
|
||||
res.status(400).json({ error: "Package name is required" });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cachedLatestPackages.has(packageName)) {
|
||||
const latest = await getLatestPackageData(packageName);
|
||||
cachedLatestPackages.set(packageName, latest);
|
||||
}
|
||||
|
||||
return res.json({ data: cachedLatestPackages.get(packageName) });
|
||||
});
|
||||
|
||||
app.post("/api/packages/install", async (req, res) => {
|
||||
const { packages } = req.body ?? {};
|
||||
|
||||
if (packages?.length === 0) {
|
||||
res.status(400).json({ error: "Package name is required" });
|
||||
return;
|
||||
}
|
||||
|
||||
const success = await updatePackage(packages as string[]);
|
||||
|
||||
if (success) {
|
||||
cachedInstalledPackages = null;
|
||||
cachedAvailablePackages = null;
|
||||
res.status(200).json({ success: true });
|
||||
} else {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: "Failed to update package",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let cachedFeed: Feed | null = null;
|
||||
app.get("/api/feed", async (req, res) => {
|
||||
if (!cachedFeed) {
|
||||
cachedFeed = await getFeed();
|
||||
}
|
||||
|
||||
res.header("x-total-count", `${cachedFeed.length}`);
|
||||
|
||||
res.json({ data: cachedFeed });
|
||||
});
|
||||
|
||||
app.get("/api/project-id/status", async (_, res) => {
|
||||
const projectId = await getProjectIdFromPackageJson();
|
||||
|
||||
if (projectId) {
|
||||
res.status(200).json({ projectId });
|
||||
return;
|
||||
} else if (projectId === false) {
|
||||
res.status(404).json({ projectId: null });
|
||||
return;
|
||||
} else {
|
||||
res.status(500).json({ projectId: null });
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/api/project-id/update", async (req, res) => {
|
||||
const { projectId } = req.body ?? {};
|
||||
|
||||
if (!projectId) {
|
||||
res.status(400).json({ error: "Project ID is required" });
|
||||
return;
|
||||
}
|
||||
|
||||
const success = await updateProjectId(projectId);
|
||||
|
||||
if (success) {
|
||||
res.status(200).json({ success: true });
|
||||
return;
|
||||
} else {
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: "Failed to update project ID",
|
||||
});
|
||||
return;
|
||||
}
|
||||
});
|
||||
};
|
||||
18
packages/devtools-server/src/serve-client.ts
Normal file
18
packages/devtools-server/src/serve-client.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import express from "express";
|
||||
import path from "path";
|
||||
|
||||
import type { Express } from "express";
|
||||
|
||||
export const serveClient = (app: Express) => {
|
||||
app.use(express.static(path.join(__dirname, "client")));
|
||||
|
||||
app.use((req, res, next) => {
|
||||
if (req.path.startsWith("/api")) {
|
||||
return next();
|
||||
}
|
||||
if (req.path.startsWith("/open-in-editor")) {
|
||||
return next();
|
||||
}
|
||||
res.status(200).sendFile(path.join(__dirname + "/client/index.html"));
|
||||
});
|
||||
};
|
||||
16
packages/devtools-server/src/serve-open-in-editor.ts
Normal file
16
packages/devtools-server/src/serve-open-in-editor.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Express } from "express";
|
||||
import path from "path";
|
||||
|
||||
export const serveOpenInEditor = (app: Express, basePath: string) => {
|
||||
app.get("/open-in-editor/*", (req, res) => {
|
||||
const { line, column } = req.query;
|
||||
|
||||
const filePath = req.path.replace("/open-in-editor", "");
|
||||
|
||||
const vscodeUrl = `vscode://file/${path.join(basePath, filePath)}?${
|
||||
line ? `line=${line}` : ""
|
||||
}${column ? `&column=${column}` : ""}`;
|
||||
|
||||
res.redirect(vscodeUrl);
|
||||
});
|
||||
};
|
||||
193
packages/devtools-server/src/serve-proxy.ts
Normal file
193
packages/devtools-server/src/serve-proxy.ts
Normal file
@@ -0,0 +1,193 @@
|
||||
import { readJSON, writeJSON } from "fs-extra";
|
||||
import { FrontendApi } from "@ory/client";
|
||||
import { createProxyMiddleware, Options } from "http-proxy-middleware";
|
||||
import path from "path";
|
||||
import { REFINE_API_URL, SERVER_PORT } from "./constants";
|
||||
import { getProjectIdFromPackageJson } from "./project-id/get-project-id-from-package-json";
|
||||
|
||||
import type { Express, RequestHandler } from "express";
|
||||
|
||||
let currentProjectId: string | null | false = null;
|
||||
const projectIdAppender: RequestHandler = async (req, res, next) => {
|
||||
if (!currentProjectId) {
|
||||
currentProjectId = await getProjectIdFromPackageJson();
|
||||
}
|
||||
|
||||
if (currentProjectId) {
|
||||
req.headers["x-project-id"] = currentProjectId;
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
|
||||
const restream: Options["onProxyReq"] = function (proxyReq, req) {
|
||||
if (req.body) {
|
||||
const bodyData = JSON.stringify(req.body);
|
||||
// incase if content-type is application/x-www-form-urlencoded -> we need to change to application/json
|
||||
proxyReq.setHeader("Content-Type", "application/json");
|
||||
proxyReq.setHeader("Content-Length", Buffer.byteLength(bodyData));
|
||||
// stream the content
|
||||
proxyReq.write(bodyData);
|
||||
}
|
||||
};
|
||||
|
||||
const tokenize = async (token: string) => {
|
||||
try {
|
||||
const ORY_URL = `${REFINE_API_URL}/.auth`;
|
||||
|
||||
const ory = new FrontendApi({
|
||||
isJsonMime: () => true,
|
||||
basePath: ORY_URL,
|
||||
baseOptions: {
|
||||
withCredentials: true,
|
||||
},
|
||||
});
|
||||
|
||||
const { data } = await ory.toSession({
|
||||
xSessionToken: token,
|
||||
tokenizeAs: "jwt_template_1",
|
||||
});
|
||||
|
||||
return data?.tokenized;
|
||||
} catch (err) {
|
||||
//
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const saveAuth = async (token?: string, jwt?: string) => {
|
||||
try {
|
||||
writeJSON(path.join(__dirname, "..", ".persist.json"), {
|
||||
token: token,
|
||||
jwt: jwt,
|
||||
});
|
||||
} catch (error) {
|
||||
//
|
||||
}
|
||||
};
|
||||
|
||||
const loadAuth = async () => {
|
||||
try {
|
||||
const persist = await readJSON(
|
||||
path.join(__dirname, "..", ".persist.json"),
|
||||
);
|
||||
return persist as { token?: string; jwt?: string };
|
||||
} catch (error) {
|
||||
//
|
||||
}
|
||||
|
||||
return {
|
||||
token: undefined,
|
||||
jwt: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
const handleLogoutToken: (
|
||||
token?: string,
|
||||
) => NonNullable<Options["onProxyReq"]> = (token) => {
|
||||
return function (proxyReq, req) {
|
||||
if (req.url.includes("self-service/logout/api")) {
|
||||
const bodyData = JSON.stringify({
|
||||
session_token: token,
|
||||
});
|
||||
proxyReq.setHeader("Content-Length", Buffer.byteLength(bodyData));
|
||||
// stream the content
|
||||
proxyReq.write(bodyData);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const handleSignInCallbacks: (
|
||||
onToken: (token?: string, jwt?: string) => void,
|
||||
) => NonNullable<Options["onProxyRes"]> = (onToken) => {
|
||||
return function (proxyRes, req, res) {
|
||||
let body = "";
|
||||
proxyRes.on("data", (chunk) => {
|
||||
body += chunk;
|
||||
});
|
||||
proxyRes.on("end", () => {
|
||||
let sessionToken: string | undefined = undefined;
|
||||
try {
|
||||
const parsed = JSON.parse(body);
|
||||
sessionToken = parsed.session_token;
|
||||
} catch (err) {
|
||||
//
|
||||
}
|
||||
if (!sessionToken) {
|
||||
if (body?.includes?.("an+account+with+the+same+identifier")) {
|
||||
res.redirect(
|
||||
"/after-login?error=An+account+with+the+same+identifier+exists+already",
|
||||
);
|
||||
return;
|
||||
}
|
||||
res.redirect("/after-login?error=Invalid-session-token");
|
||||
return;
|
||||
}
|
||||
|
||||
// After grabbing the session_token, convert it to JWT, then redirect to /after-login
|
||||
tokenize(sessionToken).then((tokenized) => {
|
||||
onToken(sessionToken, tokenized ?? "");
|
||||
res.redirect(`/after-login`);
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const serveProxy = async (app: Express) => {
|
||||
let { token, jwt } = await loadAuth();
|
||||
|
||||
const authProxy = createProxyMiddleware({
|
||||
target: REFINE_API_URL,
|
||||
// secure: false,
|
||||
changeOrigin: true,
|
||||
pathRewrite: { "^/api/.auth": "/.auth" },
|
||||
cookieDomainRewrite: {
|
||||
"refine.dev": "",
|
||||
},
|
||||
logLevel: __DEVELOPMENT__ ? "debug" : "silent",
|
||||
headers: {
|
||||
"auth-base-url-rewrite": `http://localhost:${SERVER_PORT}/api/.auth`,
|
||||
},
|
||||
selfHandleResponse: true,
|
||||
onProxyReq: (proxyReq, req, ...rest) => {
|
||||
if (token) {
|
||||
proxyReq.setHeader("X-Session-Token", token ?? "");
|
||||
|
||||
handleLogoutToken(token)(proxyReq, req, ...rest);
|
||||
}
|
||||
},
|
||||
onProxyRes: (proxyRes, req, res) => {
|
||||
if (req.url.includes("self-service/methods/oidc/callback")) {
|
||||
return handleSignInCallbacks((_token, _jwt) => {
|
||||
token = _token;
|
||||
jwt = _jwt;
|
||||
saveAuth(token, jwt);
|
||||
})(proxyRes, req, res);
|
||||
} else {
|
||||
res.writeHead(proxyRes.statusCode || 500, proxyRes.headers);
|
||||
proxyRes.pipe(res, { end: true });
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
app.use("/api/.auth", authProxy);
|
||||
|
||||
const refineApiProxy = createProxyMiddleware({
|
||||
target: REFINE_API_URL,
|
||||
secure: false,
|
||||
changeOrigin: true,
|
||||
logLevel: __DEVELOPMENT__ ? "debug" : "silent",
|
||||
pathRewrite: { "^/api/.refine": "/.refine" },
|
||||
onProxyReq: (proxyReq, ...rest) => {
|
||||
if (jwt) {
|
||||
proxyReq.setHeader("Authorization", `Bearer ${jwt}`);
|
||||
proxyReq.removeHeader("cookie");
|
||||
}
|
||||
|
||||
restream(proxyReq, ...rest);
|
||||
},
|
||||
});
|
||||
|
||||
app.use("/api/.refine", projectIdAppender, refineApiProxy);
|
||||
};
|
||||
51
packages/devtools-server/src/serve-ws.ts
Normal file
51
packages/devtools-server/src/serve-ws.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import WebSocket from "ws";
|
||||
import { SERVER_PORT, WS_PORT } from "./constants";
|
||||
import { DevtoolsEvent, send } from "@refinedev/devtools-shared";
|
||||
import { bold, cyanBright } from "chalk";
|
||||
|
||||
export const serveWs = () => {
|
||||
const ws = new WebSocket.Server({ port: WS_PORT }).on(
|
||||
"error",
|
||||
(error: any) => {
|
||||
if (error?.code === "EADDRINUSE") {
|
||||
console.error(
|
||||
`\n${cyanBright.bold("\u2717 ")}${bold(
|
||||
"refine devtools",
|
||||
)} failed to start. Port ${WS_PORT} is already in use, please make sure no other devtools server is running\n`,
|
||||
);
|
||||
} else {
|
||||
console.error(
|
||||
`\n${cyanBright.bold("\u2717 ")}${bold(
|
||||
"error from refine devtools",
|
||||
)}`,
|
||||
error,
|
||||
);
|
||||
}
|
||||
process.exit(1);
|
||||
},
|
||||
);
|
||||
|
||||
ws.on("connection", (client) => {
|
||||
if (__DEVELOPMENT__) {
|
||||
console.log(`WebSocket server started on PORT ${WS_PORT}`);
|
||||
}
|
||||
// send client the devtools client url
|
||||
send(client as any, DevtoolsEvent.DEVTOOLS_HANDSHAKE, {
|
||||
url: `http://localhost:${SERVER_PORT}`,
|
||||
});
|
||||
|
||||
client.on("close", () => {
|
||||
client.terminate();
|
||||
});
|
||||
});
|
||||
|
||||
process.on("SIGTERM", () => {
|
||||
ws.close(() => {
|
||||
if (__DEVELOPMENT__) {
|
||||
console.log("Process terminated");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return ws;
|
||||
};
|
||||
44
packages/devtools-server/src/setup-server.ts
Normal file
44
packages/devtools-server/src/setup-server.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import type { Express } from "express";
|
||||
import { SERVER_PORT } from "./constants";
|
||||
import { bold, cyanBright } from "chalk";
|
||||
|
||||
export const setupServer = (app: Express) => {
|
||||
const server = app
|
||||
.listen(SERVER_PORT, () => {
|
||||
if (__DEVELOPMENT__) {
|
||||
console.log(`Server started on PORT ${SERVER_PORT}`);
|
||||
}
|
||||
})
|
||||
.on("error", (error: any) => {
|
||||
if (error?.code === "EADDRINUSE") {
|
||||
console.error(
|
||||
`\n${cyanBright.bold("\u2717 ")}${bold(
|
||||
"refine devtools",
|
||||
)} failed to start. Port ${SERVER_PORT} is already in use, please make sure no other devtools server is running\n`,
|
||||
);
|
||||
} else {
|
||||
console.error(
|
||||
`\n${cyanBright.bold("\u2717 ")}${bold(
|
||||
"error from refine devtools",
|
||||
)}`,
|
||||
error,
|
||||
);
|
||||
}
|
||||
process.exit(1);
|
||||
})
|
||||
.on("listening", () => {
|
||||
console.log(
|
||||
`\n${cyanBright.bold("\u2713 ")}${bold(
|
||||
"refine devtools",
|
||||
)} is running at port ${cyanBright.bold(SERVER_PORT)}\n`,
|
||||
);
|
||||
});
|
||||
|
||||
process.on("SIGTERM", () => {
|
||||
server.close(() => {
|
||||
if (__DEVELOPMENT__) {
|
||||
console.log("Process terminated");
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
22
packages/devtools-server/tsconfig.declarations.json
Normal file
22
packages/devtools-server/tsconfig.declarations.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"test",
|
||||
"../test/**/*",
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.test.tsx"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"declarationDir": "dist",
|
||||
"declaration": true,
|
||||
"emitDeclarationOnly": true,
|
||||
"noEmit": false,
|
||||
"declarationMap": true,
|
||||
"paths": {}
|
||||
}
|
||||
}
|
||||
13
packages/devtools-server/tsconfig.json
Normal file
13
packages/devtools-server/tsconfig.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"include": ["src", "types"],
|
||||
"extends": "../../tsconfig.build.json",
|
||||
"compilerOptions": {
|
||||
"types": ["node", "jest", "@testing-library/jest-dom"],
|
||||
"rootDir": "./src",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@test/*": ["test/*"],
|
||||
"@test": ["test"]
|
||||
}
|
||||
}
|
||||
}
|
||||
9
packages/devtools-server/tsconfig.test.json
Normal file
9
packages/devtools-server/tsconfig.test.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["test", "src"],
|
||||
"compilerOptions": {
|
||||
"rootDir": ".",
|
||||
"types": ["node", "jest", "@testing-library/jest-dom"],
|
||||
"typeRoots": ["../../node_modules/@types", "src"]
|
||||
}
|
||||
}
|
||||
31
packages/devtools-server/tsup.config.ts
Normal file
31
packages/devtools-server/tsup.config.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { defineConfig } from "tsup";
|
||||
import { NodeResolvePlugin } from "@esbuild-plugins/node-resolve";
|
||||
|
||||
export default defineConfig((tsupOptions) => ({
|
||||
entry: ["src/index.ts", "src/cli.ts"],
|
||||
splitting: false,
|
||||
sourcemap: true,
|
||||
clean: false,
|
||||
platform: "node",
|
||||
dts: false,
|
||||
esbuildOptions: (options) => {
|
||||
options.define = {
|
||||
...options.define,
|
||||
__DEVELOPMENT__: tsupOptions.watch ? "true" : "false",
|
||||
};
|
||||
},
|
||||
esbuildPlugins: [
|
||||
NodeResolvePlugin({
|
||||
extensions: [".js", "ts", "tsx", "jsx"],
|
||||
onResolved: (resolved) => {
|
||||
if (resolved.includes("node_modules")) {
|
||||
return {
|
||||
external: true,
|
||||
};
|
||||
}
|
||||
return resolved;
|
||||
},
|
||||
}),
|
||||
],
|
||||
onSuccess: "tsc --project tsconfig.declarations.json",
|
||||
}));
|
||||
Reference in New Issue
Block a user