This commit is contained in:
Stefan Pejcic
2024-11-07 19:03:37 +01:00
parent c6df945ed5
commit 09f9f9502d
2472 changed files with 620417 additions and 0 deletions

1
packages/devtools-server/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.persist.json

View 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

View File

@@ -0,0 +1,514 @@
# @refinedev/devtools-server
## 1.1.37
### Patch Changes
- [#6354](https://github.com/refinedev/refine/pull/6354) [`da9da4ed1a9700c7a48db6520d683168c48b226e`](https://github.com/refinedev/refine/commit/da9da4ed1a9700c7a48db6520d683168c48b226e) Thanks [@arndom](https://github.com/arndom)! - chore: bump express version to latest
Bump `express` dependecy to `^4.21.0` to fix vulnerability in `serve-static`.
[Resolves #6321](https://github.com/refinedev/refine/issues/6321)
## 1.1.36
### Patch Changes
- [#6253](https://github.com/refinedev/refine/pull/6253) [`6963e591f8f307aee9362d5dfff99972eb64bf03`](https://github.com/refinedev/refine/commit/6963e591f8f307aee9362d5dfff99972eb64bf03) Thanks [@aliemir](https://github.com/aliemir)! - chore(devtools-server): replace `preferred-pm` with `package-manager-detector` #6242
`preferred-pm` has 24 dependencies: https://npmgraph.js.org/?q=preferred-pm
`package-manager-detector` has no dependencies: https://npmgraph.js.org/?q=package-manager-detector
## 1.1.35
### Patch Changes
- [#6185](https://github.com/refinedev/refine/pull/6185) [`603c73eb7d376fc2357a577f5921f844a8f444e4`](https://github.com/refinedev/refine/commit/603c73eb7d376fc2357a577f5921f844a8f444e4) Thanks [@aliemir](https://github.com/aliemir)! - feat(devtools): ability to change the port of the devtools server
Now users can change the port of the devtools server by setting the `REFINE_DEVTOOLS_PORT` environment variable. Previously, the port was hardcoded to "5001" and could not be changed.
If you're using `@refinedev/cli`'s runner commands to start your development server, `REFINE_DEVTOOLS_PORT` will be propagated to your app with appropriate prefix. E.g. if you're using Vite, the environment variable will be `VITE_REFINE_DEVTOOLS_PORT` and it will be used by the `@refinedev/devtools`'s `<DevtoolsProvider />` component to connect to the devtools server.
- In Next.js apps, it will be prefixed with `NEXT_PUBLIC_`
- In Craco and Create React App apps, it will be prefixed with `REACT_APP_`
- In Remix apps and other custom setups, the environment variable will be used as is.
In some scenarios where the environment variables are not passed to the browser, you may need to manually set the Refine Devtools URL in the `<DevtoolsProvider />` component via the `url` prop. Remix apps do not automatically pass environment variables to the browser, so you will need to set the URL manually. If not set, the default URL will be used.
While the port can be changed, this feature also allows users to host the devtools server on a different machine or domain and provide the `<DevtoolsProvider />` with the custom domain URL. This such case will be useful if you're dockerizing your app and devtools server separately.
**Enterprise Edition**: Refine Devtools running on ports other than "5001" is only available in the Enterprise Edition. If you're using the Community Edition, Refine Devtools will not work if the port is changed.
[Resolves #5111](https://github.com/refinedev/refine/issues/5111)
- Updated dependencies [[`603c73eb7d376fc2357a577f5921f844a8f444e4`](https://github.com/refinedev/refine/commit/603c73eb7d376fc2357a577f5921f844a8f444e4)]:
- @refinedev/devtools-shared@1.1.12
## 1.1.34
### Patch Changes
- [#6098](https://github.com/refinedev/refine/pull/6098) [`8bc2c1c6790d1e098ce0d98e01f608e3310f7b4a`](https://github.com/refinedev/refine/commit/8bc2c1c6790d1e098ce0d98e01f608e3310f7b4a) Thanks [@aliemir](https://github.com/aliemir)! - refactor(devtools): updated flow for login callbacks
Previously, when the login flow had an error, the Devtools UI was displaying it in the secondary window, which was not user-friendly and lead to multiple clients to connect unnecessarily. This change updates the flow to display the error message in the main Devtools window.
- [#6098](https://github.com/refinedev/refine/pull/6098) [`8bc2c1c6790d1e098ce0d98e01f608e3310f7b4a`](https://github.com/refinedev/refine/commit/8bc2c1c6790d1e098ce0d98e01f608e3310f7b4a) Thanks [@aliemir](https://github.com/aliemir)! - refactor(devtools): updated auth flow
Previously, a proxy in the Devtools Server was used as an auth server to handle sign-ins in the localhost (Devtools Server). This change updates the flow and moves the authentication flow to `https://auth.refine.dev` to handle sign-ins and sign-outs. Now the Devtools Server is only responsible for the connection between the auth server and the user interface while also managing the user's session.
- [#6098](https://github.com/refinedev/refine/pull/6098) [`8bc2c1c6790d1e098ce0d98e01f608e3310f7b4a`](https://github.com/refinedev/refine/commit/8bc2c1c6790d1e098ce0d98e01f608e3310f7b4a) Thanks [@aliemir](https://github.com/aliemir)! - refactor(devtools-server): handle project id without polluting user console
When project ID is missing in the project, Devtools Server was returning with `400` and `404` status codes, which leads to unwanted logs in the user console. To avoid this, the server now returns a `200` status code with an error message in the response body. This change is accompanied by a new error handler in the `@refinedev/devtools-ui` package to handle the error message and display it in the user interface.
- [#6052](https://github.com/refinedev/refine/pull/6052) [`50d21076928ca738ec54cc5bcd17fad2683653dd`](https://github.com/refinedev/refine/commit/50d21076928ca738ec54cc5bcd17fad2683653dd) Thanks [@aliemir](https://github.com/aliemir)! - fix(devtools-server): lodash import from root
`@refinedev/devtools-server` was using `lodash` imports from root which are interpreted as CJS imports in the ESM bundle. To avoid any future issues, lodash imports have been replaced with subdirectory imports.
- Updated dependencies [[`8bc2c1c6790d1e098ce0d98e01f608e3310f7b4a`](https://github.com/refinedev/refine/commit/8bc2c1c6790d1e098ce0d98e01f608e3310f7b4a), [`8bc2c1c6790d1e098ce0d98e01f608e3310f7b4a`](https://github.com/refinedev/refine/commit/8bc2c1c6790d1e098ce0d98e01f608e3310f7b4a)]:
- @refinedev/devtools-shared@1.1.11
## 1.1.32
### Patch Changes
- [#6059](https://github.com/refinedev/refine/pull/6059) [`ad42665ad9ccb07f6090da353377d016b67acdd0`](https://github.com/refinedev/refine/commit/ad42665ad9ccb07f6090da353377d016b67acdd0) Thanks [@aliemir](https://github.com/aliemir)! - fix(devtools-server): missing header check on auth requests
Devtools was failing to determine the auth status and always end up redirecting to the login page regardless of the actual auth status. This was due to the missing check on the auth request that was causing all valid responses treated as unauthenticated.
Resolves [#6047](https://github.com/refinedev/refine/issues/6047)
## 1.1.31
### Patch Changes
- [`6bd14228760d3e1e205ea9248e427f9afa2ec046`](https://github.com/refinedev/refine/commit/6bd14228760d3e1e205ea9248e427f9afa2ec046) Thanks [@BatuhanW](https://github.com/BatuhanW)! - fix: capitalize Refine
Capitalized "Refine" in the user-facing texts
- [`6bd14228760d3e1e205ea9248e427f9afa2ec046`](https://github.com/refinedev/refine/commit/6bd14228760d3e1e205ea9248e427f9afa2ec046) Thanks [@BatuhanW](https://github.com/BatuhanW)! - refactor: use same port for ws and http servers
This PR merges WebSocket and Http server ports into one (5001) to simplify the configuration and avoid port conflicts. Previously the WebSocket server was running on port 5002 and the Http server on port 5001. Now both servers are running on port 5001.
- [`6bd14228760d3e1e205ea9248e427f9afa2ec046`](https://github.com/refinedev/refine/commit/6bd14228760d3e1e205ea9248e427f9afa2ec046) Thanks [@BatuhanW](https://github.com/BatuhanW)! - chore(devtools-server): customizable exit function
This change allows you to customize the exit function of the devtools server when using it via API.
- [`6bd14228760d3e1e205ea9248e427f9afa2ec046`](https://github.com/refinedev/refine/commit/6bd14228760d3e1e205ea9248e427f9afa2ec046) Thanks [@BatuhanW](https://github.com/BatuhanW)! - chore: added `type` qualifier to imports used as type only.
```diff
- import { A } from "./example.ts";
+ import type { A } from "./example.ts";
```
- [`6bd14228760d3e1e205ea9248e427f9afa2ec046`](https://github.com/refinedev/refine/commit/6bd14228760d3e1e205ea9248e427f9afa2ec046) Thanks [@BatuhanW](https://github.com/BatuhanW)! - fix: remove annoying auth error at initial project loads
When users create a new project or their devtools token expires, their console is polluted with network errors due to missing authentication. This PR removes these errors by handling auth requests in a user-friendly way.
- Updated dependencies [[`6bd14228760d3e1e205ea9248e427f9afa2ec046`](https://github.com/refinedev/refine/commit/6bd14228760d3e1e205ea9248e427f9afa2ec046), [`6bd14228760d3e1e205ea9248e427f9afa2ec046`](https://github.com/refinedev/refine/commit/6bd14228760d3e1e205ea9248e427f9afa2ec046), [`6bd14228760d3e1e205ea9248e427f9afa2ec046`](https://github.com/refinedev/refine/commit/6bd14228760d3e1e205ea9248e427f9afa2ec046)]:
- @refinedev/devtools-shared@1.1.9
## 1.1.30
### Patch Changes
- [#5945](https://github.com/refinedev/refine/pull/5945) [`429009db854653ab3ca00fbfb84561de38b3a255`](https://github.com/refinedev/refine/commit/429009db854653ab3ca00fbfb84561de38b3a255) Thanks [@aliemir](https://github.com/aliemir)! - fix: capitalize Refine
Capitalized "Refine" in the user-facing texts
- [#5945](https://github.com/refinedev/refine/pull/5945) [`6c22ece19f44ca2b99ad70543f9ee40b4b139863`](https://github.com/refinedev/refine/commit/6c22ece19f44ca2b99ad70543f9ee40b4b139863) Thanks [@aliemir](https://github.com/aliemir)! - refactor: use same port for ws and http servers
This PR merges WebSocket and Http server ports into one (5001) to simplify the configuration and avoid port conflicts. Previously the WebSocket server was running on port 5002 and the Http server on port 5001. Now both servers are running on port 5001.
- [#5945](https://github.com/refinedev/refine/pull/5945) [`6c22ece19f44ca2b99ad70543f9ee40b4b139863`](https://github.com/refinedev/refine/commit/6c22ece19f44ca2b99ad70543f9ee40b4b139863) Thanks [@aliemir](https://github.com/aliemir)! - chore(devtools-server): customizable exit function
This change allows you to customize the exit function of the devtools server when using it via API.
- [#5945](https://github.com/refinedev/refine/pull/5945) [`90930b381d8d369c63bc59beedf69c391875166d`](https://github.com/refinedev/refine/commit/90930b381d8d369c63bc59beedf69c391875166d) Thanks [@aliemir](https://github.com/aliemir)! - chore: added `type` qualifier to imports used as type only.
```diff
- import { A } from "./example.ts";
+ import type { A } from "./example.ts";
```
- [#5945](https://github.com/refinedev/refine/pull/5945) [`bb89dc34bf6ef061d0bcdcf0cb3173fe7014ae5e`](https://github.com/refinedev/refine/commit/bb89dc34bf6ef061d0bcdcf0cb3173fe7014ae5e) Thanks [@aliemir](https://github.com/aliemir)! - fix: remove annoying auth error at initial project loads
When users create a new project or their devtools token expires, their console is polluted with network errors due to missing authentication. This PR removes these errors by handling auth requests in a user-friendly way.
- Updated dependencies [[`bb89dc34bf6ef061d0bcdcf0cb3173fe7014ae5e`](https://github.com/refinedev/refine/commit/bb89dc34bf6ef061d0bcdcf0cb3173fe7014ae5e), [`6c22ece19f44ca2b99ad70543f9ee40b4b139863`](https://github.com/refinedev/refine/commit/6c22ece19f44ca2b99ad70543f9ee40b4b139863), [`90930b381d8d369c63bc59beedf69c391875166d`](https://github.com/refinedev/refine/commit/90930b381d8d369c63bc59beedf69c391875166d)]:
- @refinedev/devtools-shared@1.1.8
## 1.1.29
### Patch Changes
- Updated dependencies [[`db9756e7908`](https://github.com/refinedev/refine/commit/db9756e79086ff80774ee75d570d610bf0d5d76d)]:
- @refinedev/devtools-shared@1.1.7
## 1.1.28
### Patch Changes
- [#5875](https://github.com/refinedev/refine/pull/5875) [`1c9a95f22ab`](https://github.com/refinedev/refine/commit/1c9a95f22ab8c3f1d1e48c7c889227ce1d9160cf) Thanks [@aliemir](https://github.com/aliemir)! - chore: move `@refinedev/devtools-ui` dependency
Moved `@refinedev/devtools-ui` dependency to `devDependencies` since only the `vite` output is used in the server.
- [#5875](https://github.com/refinedev/refine/pull/5875) [`1c9a95f22ab`](https://github.com/refinedev/refine/commit/1c9a95f22ab8c3f1d1e48c7c889227ce1d9160cf) Thanks [@aliemir](https://github.com/aliemir)! - feat: update resource name accessing logic
Updated resource name displaying logic to use `resourceName` from activity records to make sure `resource` is correctly displayed with custom query keys.
- [#5875](https://github.com/refinedev/refine/pull/5875) [`1c9a95f22ab`](https://github.com/refinedev/refine/commit/1c9a95f22ab8c3f1d1e48c7c889227ce1d9160cf) Thanks [@aliemir](https://github.com/aliemir)! - feat: add invalidate query button
Added `Invalidate Query` button to settled queries in the devtools panel to allow users to manually invalidate queries for debugging purposes.
- [#5865](https://github.com/refinedev/refine/pull/5865) [`a9dbd808782`](https://github.com/refinedev/refine/commit/a9dbd808782212ed0bf6cf4401f85b675975a744) Thanks [@aliemir](https://github.com/aliemir)! - fix: devtools authentication not working with safari
Fixed the authentication flow and cookie handling for Safari. Now devtools users will be able to authenticate and use the devtools server using Safari.
Resolves [#5753](https://github.com/refinedev/refine/issues/5753)
- Updated dependencies [[`1c9a95f22ab`](https://github.com/refinedev/refine/commit/1c9a95f22ab8c3f1d1e48c7c889227ce1d9160cf), [`1c9a95f22ab`](https://github.com/refinedev/refine/commit/1c9a95f22ab8c3f1d1e48c7c889227ce1d9160cf), [`ba719f6ea26`](https://github.com/refinedev/refine/commit/ba719f6ea264ee87226f42de900a754e81f1f22f)]:
- @refinedev/devtools-shared@1.1.6
## 1.1.27
### Patch Changes
- [#5823](https://github.com/refinedev/refine/pull/5823) [`aedc6a2961c`](https://github.com/refinedev/refine/commit/aedc6a2961cfe69309d4e14292147a858f94e3bf) Thanks [@aliemir](https://github.com/aliemir)! - fix: broken lodash imports in ESM builds
Fixed lodash imports in ESM builds which requires `lodash-es` imports to use `.js` extension to work properly unless the bundler is configured to handle non-fully-specified imports.
Resolves [#5822](https://github.com/refinedev/refine/issues/5822)
- Updated dependencies [[`aedc6a2961c`](https://github.com/refinedev/refine/commit/aedc6a2961cfe69309d4e14292147a858f94e3bf)]:
- @refinedev/devtools-ui@1.1.20
## 1.1.26
### Patch Changes
- [#5807](https://github.com/refinedev/refine/pull/5807) [`b20a18e4dfc`](https://github.com/refinedev/refine/commit/b20a18e4dfc97481be865a2a012ea1c588bd76c6) Thanks [@BatuhanW](https://github.com/BatuhanW)! - chore: update jscodeshift version to 0.15.2
- [#5765](https://github.com/refinedev/refine/pull/5765) [`0c197d82393`](https://github.com/refinedev/refine/commit/0c197d823939ae1fd4e0ee4b5a422322853b1e45) Thanks [@aliemir](https://github.com/aliemir)! - refactor: package bundles and package.json configuration for exports
Previously, Refine packages had exported ESM and CJS bundles with same `.js` extension and same types for both with `.d.ts` extensions. This was causing issues with bundlers and compilers to pick up the wrong files for the wrong environment. Now we're outputting ESM bundles with `.mjs` extension and CJS bundles with `.cjs` extension. Also types are now exported with both `.d.mts` and `.d.cts` extensions.
In older versions ESM and CJS outputs of some packages were using wrong imports/requires to dependencies causing errors in some environments. This will be fixed since now we're also enforcing the module type with extensions.
Above mentioned changes also supported with changes in `package.json` files of the packages to support the new extensions and types. All Refine packages now include `exports` fields in their configuration to make sure the correct bundle is picked up by the bundlers and compilers.
- [#5749](https://github.com/refinedev/refine/pull/5749) [`51f368eab1a`](https://github.com/refinedev/refine/commit/51f368eab1a72e2134981e999dc0b3e26e2b74e8) Thanks [@alicanerdurmaz](https://github.com/alicanerdurmaz)! - chore: Vite upgraded to [v5.x.x](https://vitejs.dev/guide/migration). #5749
- [#5754](https://github.com/refinedev/refine/pull/5754) [`56ed144a0f5`](https://github.com/refinedev/refine/commit/56ed144a0f5af218fd9e6edbfd999ae433329927) Thanks [@alicanerdurmaz](https://github.com/alicanerdurmaz)! - chore: TypeScript upgraded to [v5.x.x](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html). #5752
- Updated dependencies [[`0c197d82393`](https://github.com/refinedev/refine/commit/0c197d823939ae1fd4e0ee4b5a422322853b1e45), [`56ed144a0f5`](https://github.com/refinedev/refine/commit/56ed144a0f5af218fd9e6edbfd999ae433329927)]:
- @refinedev/devtools-shared@1.1.5
- @refinedev/devtools-ui@1.1.19
## 1.1.25
### Patch Changes
- [#5695](https://github.com/refinedev/refine/pull/5695) [`79865affa1c`](https://github.com/refinedev/refine/commit/79865affa1c657e6b14ed34585caeec1f3d3da7f) Thanks [@BatuhanW](https://github.com/BatuhanW)! - chore: apply biome format and fix lint errors.
- Updated dependencies [[`79865affa1c`](https://github.com/refinedev/refine/commit/79865affa1c657e6b14ed34585caeec1f3d3da7f)]:
- @refinedev/devtools-shared@1.1.4
- @refinedev/devtools-ui@1.1.18
## 1.1.24
### Patch Changes
- Updated dependencies [[`546df06482`](https://github.com/refinedev/refine/commit/546df06482807e59a7f2a735361a8e9169bb2563)]:
- @refinedev/devtools-shared@1.1.3
- @refinedev/devtools-ui@1.1.17
## 1.1.23
### Patch Changes
- [#5574](https://github.com/refinedev/refine/pull/5574) [`ee0f7867c3`](https://github.com/refinedev/refine/commit/ee0f7867c3648dcbf1e2504f430a0b5814d91019) Thanks [@BatuhanW](https://github.com/BatuhanW)! - chore: upgrade @ory/client package version to 1.5.2 #5530
- Updated dependencies [[`ee0f7867c3`](https://github.com/refinedev/refine/commit/ee0f7867c3648dcbf1e2504f430a0b5814d91019)]:
- @refinedev/devtools-ui@1.1.16
## 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
![refine devtools](https://github.com/refinedev/refine/assets/1110414/15ed6907-d0c8-4213-9024-2f6b0a09968f)
## 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

View 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.

View 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.

View 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&#8594](https://refine.dev/docs/)
[Step up to refine tutorials &#8594](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
```

View 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",
},
],
},
};

View File

@@ -0,0 +1,131 @@
{
"name": "@refinedev/devtools-server",
"version": "1.1.37",
"private": false,
"description": "refine devtools offers a set of features from monitoring to quickly prototyping a UI.",
"repository": {
"type": "git",
"url": "https://github.com/refinedev/refine.git",
"directory": "packages/devtools"
},
"license": "MIT",
"author": "refine",
"sideEffects": false,
"exports": {
".": {
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
},
"main": "dist/index.cjs",
"module": "dist/index.mjs",
"typings": "dist/index.d.ts",
"bin": {
"refine-devtools": "./dist/cli.cjs"
},
"files": [
"dist",
"src"
],
"scripts": {
"attw": "attw --pack .",
"build": "pnpm build:client && tsup && node ../shared/generate-declarations.js",
"build:client": "cross-env NODE_ENV=production tsc && vite build --config src/client/vite.config.ts",
"dev": "pnpm dev:client & tsup --watch",
"dev:client": "vite build --watch --config src/client/vite.config.ts",
"prepare": "pnpm build",
"publint": "publint --strict=true --level=suggestion",
"start:server": "node dist/cli.cjs",
"test": "jest --passWithNoTests --runInBand",
"types": "node ../shared/generate-declarations.js"
},
"dependencies": {
"@refinedev/devtools-shared": "1.1.12",
"body-parser": "^1.20.2",
"boxen": "^5.1.2",
"chalk": "^4.1.2",
"dedent": "^0.7.0",
"dotenv": "^16.0.3",
"error-stack-parser": "^2.1.4",
"execa": "^5.1.1",
"express": "^4.21.0",
"fs-extra": "^10.1.0",
"globby": "^11.1.0",
"gray-matter": "^4.0.3",
"http-proxy-middleware": "^3.0.0",
"jscodeshift": "0.15.2",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"marked": "^4.3.0",
"node-fetch": "^2.6.7",
"package-manager-detector": "^0.1.1",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"sanitize-html": "^2.11.0",
"ws": "^8.13.0"
},
"devDependencies": {
"@esbuild-plugins/node-resolve": "^0.1.4",
"@refinedev/devtools-ui": "1.1.28",
"@testing-library/jest-dom": "^5.16.4",
"@types/dedent": "^0.7.0",
"@types/express": "^4.17.21",
"@types/fs-extra": "^9.0.13",
"@types/jest": "^29.2.4",
"@types/jscodeshift": "^0.11.11",
"@types/lodash": "^4.14.171",
"@types/marked": "^5.0.1",
"@types/node": "^18.16.2",
"@types/node-fetch": "^2.6.11",
"@types/sanitize-html": "^2.9.0",
"@types/ws": "^8.5.5",
"@vitejs/plugin-react": "^4.2.1",
"esbuild-copy-static-files": "^0.1.0",
"jest": "^29.3.1",
"jest-environment-jsdom": "^29.3.1",
"react-router-dom": "^6.8.1",
"ts-jest": "^29.1.2",
"tslib": "^2.6.2",
"tsup": "^6.7.0",
"typescript": "^5.4.2",
"vite": "^5.1.6"
},
"peerDependencies": {
"@types/react": "^17.0.0 || ^18.0.0",
"@types/react-dom": "^17.0.0 || ^18.0.0",
"react": "^17.0.0 || ^18.0.0",
"react-dom": "^17.0.0 || ^18.0.0"
},
"engines": {
"node": ">=10"
},
"publishConfig": {
"access": "public"
},
"nx": {
"targets": {
"build": {
"dependsOn": [
"^build",
"build:client"
],
"cache": true
},
"build:client": {
"dependsOn": [
"^build"
],
"outputs": [
"{projectRoot}/dist"
],
"cache": true
}
}
}
}

View File

@@ -0,0 +1,4 @@
#!/usr/bin/env node
import { server } from "./index";
server().catch(() => 0);

View File

@@ -0,0 +1,33 @@
<!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" />
<!--
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 run dev` or `yarn dev`.
To create a production bundle, use `npm run build` or `yarn build`.
--></body>
</html>

View 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");
}

View 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",
},
});

View File

@@ -0,0 +1,25 @@
import dotenv from "dotenv";
const refineEnv: Record<string, string> = {};
dotenv.config({ processEnv: refineEnv });
const RAW_ENV_REFINE_DEVTOOLS_PORT =
process.env.REFINE_DEVTOOLS_PORT || refineEnv.REFINE_DEVTOOLS_PORT;
export const DEFAULT_SERVER_PORT = 5001;
export const SERVER_PORT =
Number(RAW_ENV_REFINE_DEVTOOLS_PORT) || DEFAULT_SERVER_PORT;
export const AUTH_SERVER_URL = __DEVELOPMENT__
? "https://develop.auth.refine.dev"
: "https://auth.refine.dev";
export const REFINE_API_URL = __DEVELOPMENT__
? "https://develop.cloud.refine.dev"
: "https://cloud2.refine.dev";
export const AUTH_TRIGGER_API_PATH = "/api/login";
export const AUTH_CALLBACK_API_PATH = "/api/login-callback";
export const AUTH_CALLBACK_UI_PATH = "/after-login";
export const FEED_MD_URL =
"https://raw.githubusercontent.com/refinedev/refine/master/packages/devtools-server/FEED.md";

View File

@@ -0,0 +1,34 @@
import type {
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,
};
};

View File

@@ -0,0 +1 @@
declare const __DEVELOPMENT__: boolean;

View File

@@ -0,0 +1,65 @@
import fetch from "node-fetch";
import matter from "gray-matter";
import { marked } from "marked";
import sanitizeHtml from "sanitize-html";
import type { 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 [];
}
};

View File

@@ -0,0 +1,165 @@
import express from "express";
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 { type Activity, createDb } from "./create-db";
import { serveApi } from "./serve-api";
import { serveProxy } from "./serve-proxy";
import { serveOpenInEditor } from "./serve-open-in-editor";
type Options = {
projectPath?: string;
onError?: () => void;
};
export const server = async ({
projectPath = process.cwd(),
onError = () => {
process.exit(1);
},
}: Options = {}) => {
return new Promise((_, reject) => {
const app = express();
const server = setupServer(app, () => {
reject();
onError();
});
const ws = serveWs(server, () => {
reject();
onError();
});
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_INVALIDATE_QUERY,
({ queryKey }) => {
ws.clients.forEach((c) => {
send(c as any, DevtoolsEvent.DEVTOOLS_INVALIDATE_QUERY_ACTION, {
queryKey,
});
});
},
);
receive(client as any, DevtoolsEvent.DEVTOOLS_LOGIN_SUCCESS, () => {
ws.clients.forEach((c) => {
send(c as any, DevtoolsEvent.DEVTOOLS_RELOAD_AFTER_LOGIN, {});
});
});
receive(
client as any,
DevtoolsEvent.DEVTOOLS_LOGIN_FAILURE,
({ error, code }) => {
ws.clients.forEach((c) => {
send(c as any, DevtoolsEvent.DEVTOOLS_DISPLAY_LOGIN_FAILURE, {
error,
code,
});
});
},
);
// 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);
serveApi(app, db);
serveProxy(app);
serveOpenInEditor(app, projectPath);
process.on("SIGTERM", () => {
reject();
});
});
};

View File

@@ -0,0 +1,28 @@
import type { 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 [];
}
};

View File

@@ -0,0 +1,514 @@
import type { 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 @tabler/icons-react",
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-react",
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),
);
};

View File

@@ -0,0 +1,3 @@
export const getChangelog = (packageName: string) => {
return packageName.replace("@refinedev/", "https://c.refine.dev/");
};

View File

@@ -0,0 +1,3 @@
export const getDocumentation = (packageName: string) => {
return "https://refine.dev/docs/api-reference/general-concepts/";
};

View File

@@ -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;
}
};

View File

@@ -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;
}
};

View File

@@ -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 };
}
};

View File

@@ -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;
};

View File

@@ -0,0 +1,21 @@
import { detect } from "package-manager-detector";
import execa from "execa";
export const updatePackage = async (
packages: string[],
projectPath: string = process.cwd(),
) => {
try {
const detected = await detect({ cwd: projectPath });
const [pm] = (detected?.agent || "npm").split("@");
const { failed } = await execa(pm, [
"install",
...packages.map((p) => `${p}@latest`),
]);
return !failed;
} catch (error) {
return false;
}
};

View File

@@ -0,0 +1,22 @@
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;
}
};

View File

@@ -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;
}
};

View File

@@ -0,0 +1,40 @@
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;
};

View File

@@ -0,0 +1,88 @@
import type { namedTypes } from "ast-types";
import type {
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();
}

View 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;
}
};

View File

@@ -0,0 +1,32 @@
import fs from "fs";
import path from "path";
import debounce from "lodash/debounce";
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;

View File

@@ -0,0 +1,174 @@
import type { Express } from "express";
import { json } from "express";
import uniq from "lodash/uniq";
import type {
AvailablePackageType,
Feed,
PackageType,
} from "@refinedev/devtools-shared";
import type { 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 CODES = {
OK: 0,
NOT_FOUND: 1,
ERROR: 2,
};
const projectId = await getProjectIdFromPackageJson();
if (projectId) {
res.status(200).json({ projectId, status: CODES.OK });
return;
}
if (projectId === false) {
res.status(200).json({ projectId: null, status: CODES.NOT_FOUND });
return;
}
res.status(200).json({ projectId: null, status: CODES.ERROR });
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;
}
res.status(500).json({
success: false,
error: "Failed to update project ID",
});
return;
});
};

View 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`));
});
};

View File

@@ -0,0 +1,16 @@
import type { 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);
});
};

View File

@@ -0,0 +1,151 @@
import path from "path";
import { readJSON, writeJSON } from "fs-extra";
import { createProxyMiddleware, fixRequestBody } from "http-proxy-middleware";
import {
REFINE_API_URL,
AUTH_SERVER_URL,
AUTH_CALLBACK_API_PATH,
AUTH_CALLBACK_UI_PATH,
AUTH_TRIGGER_API_PATH,
} from "./constants";
import { getProjectIdFromPackageJson } from "./project-id/get-project-id-from-package-json";
import type { Express, RequestHandler } from "express";
const persistPath = path.join(__dirname, "..", ".persist.json");
const saveAuth = async (token?: string, jwt?: string) => {
try {
await writeJSON(persistPath, { token, jwt });
} catch (error) {
//
}
};
const loadAuth = async () => {
try {
return (await readJSON(persistPath)) as { token?: string; jwt?: string };
} catch (error) {
//
}
return {};
};
export const serveProxy = async (app: Express) => {
let { token, jwt } = await loadAuth();
const authProxy = createProxyMiddleware({
target: `${AUTH_SERVER_URL}/api/.auth`,
secure: false,
changeOrigin: true,
logger: __DEVELOPMENT__ ? console : undefined,
on: {
proxyReq: fixRequestBody,
proxyRes: (_proxyRes, req) => {
if (req.url?.includes("self-service/logout/api")) {
token = undefined;
jwt = undefined;
saveAuth();
}
},
},
});
const refineProxy = createProxyMiddleware({
target: `${REFINE_API_URL}/.refine`,
secure: false,
changeOrigin: true,
logger: __DEVELOPMENT__ ? console : undefined,
on: {
proxyReq: fixRequestBody,
},
});
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 appendAuth: RequestHandler = async (req, _res, next) => {
if (token) {
req.headers["X-Session-Token"] = token;
}
if (req.url?.includes("self-service/logout/api")) {
req.body = {
session_token: token,
};
req.headers["Content-Length"] = Buffer.byteLength(
JSON.stringify(req.body),
).toString();
}
next();
};
const appendJwt: RequestHandler = async (req, _res, next) => {
if (jwt) {
req.headers["Authorization"] = `Bearer ${jwt}`;
delete req.headers["cookie"];
}
next();
};
const loginCallback: RequestHandler = async (req, res, _next) => {
const query = req.query;
if (query.token && query.jwt) {
token = query.token as string;
jwt = query.jwt as string;
await saveAuth(query.token as string, query.jwt as string);
}
const errorParams = new URLSearchParams();
if (query.error) {
errorParams.set("error", query.error as string);
}
if (query.code) {
errorParams.set("code", query.code as string);
}
res.redirect(`${AUTH_CALLBACK_UI_PATH}?${errorParams.toString()}`);
};
const loginTrigger: RequestHandler = async (req, res, _next) => {
const query = req.query;
const protocol = req.secure ? "https" : "http";
const host = req.headers.host;
if (!host) {
res.redirect(`${AUTH_CALLBACK_API_PATH}?error=Missing%20Host`);
return;
}
const callbackUrl = `${protocol}://${host}${AUTH_CALLBACK_API_PATH}`;
const params = new URLSearchParams({
provider: query.provider as string,
returnUrl: encodeURIComponent(callbackUrl),
});
res.redirect(`${AUTH_SERVER_URL}/login?${params.toString()}`);
};
app.use(AUTH_TRIGGER_API_PATH, loginTrigger);
app.use(AUTH_CALLBACK_API_PATH, loginCallback);
app.use("/api/.auth", appendAuth, authProxy);
app.use("/api/.refine", projectIdAppender, appendJwt, refineProxy);
};

View File

@@ -0,0 +1,46 @@
import WebSocket from "ws";
import { SERVER_PORT } from "./constants";
import { bold, cyanBright } from "chalk";
import type http from "http";
export const serveWs = (
server: http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>,
onError: () => void,
) => {
const ws = new WebSocket.Server({ server }).on("error", (error: any) => {
if (error?.code === "EADDRINUSE") {
console.error(
`\n${cyanBright.bold("\u2717 ")}${bold(
"Refine Devtools server",
)} (websocket) failed to start. Port ${SERVER_PORT} is already in use.\n`,
);
} else {
console.error(
`\n${cyanBright.bold("\u2717 ")}${bold("error from refine devtools")}`,
error,
);
}
ws.close(() => {
if (__DEVELOPMENT__) {
console.log("Process terminated");
}
});
onError();
});
ws.on("connection", (client) => {
client.on("close", () => {
client.terminate();
});
});
process.on("SIGTERM", () => {
ws.close(() => {
if (__DEVELOPMENT__) {
console.log("Process terminated");
}
});
});
return ws;
};

View File

@@ -0,0 +1,62 @@
import type { Express } from "express";
import { SERVER_PORT } from "./constants";
import { bold, cyanBright } from "chalk";
import http from "http";
export const setupServer = (app: Express, onError: () => void) => {
const server = http.createServer(app);
server
.on("error", (error: any) => {
if (error?.code === "EADDRINUSE") {
console.error(
`\n${cyanBright.bold("\u2717 ")}${bold(
"Refine Devtools server",
)} (http) failed to start. Port ${SERVER_PORT} is already in use.\n`,
);
console.info(
`${cyanBright.bold(
"\u2139 ",
)}You can change the port by setting the ${bold(
"REFINE_DEVTOOLS_PORT",
)} environment variable.`,
);
} else {
console.error(
`\n${cyanBright.bold("\u2717 ")}${bold(
"error from Refine Devtools",
)}`,
error,
);
}
server.close(() => {
if (__DEVELOPMENT__) {
console.log("Process terminated");
}
});
onError();
})
.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");
}
});
});
server.listen(SERVER_PORT, undefined, undefined, () => {
if (__DEVELOPMENT__) {
console.log(`Server started on PORT ${SERVER_PORT}`);
}
});
return server;
};

View File

@@ -0,0 +1,23 @@
{
"extends": "./tsconfig.json",
"exclude": [
"node_modules",
"dist",
"test",
"../test/**/*",
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"src/client/**/*"
],
"compilerOptions": {
"outDir": "dist",
"declarationDir": "dist",
"declaration": true,
"emitDeclarationOnly": true,
"noEmit": false,
"declarationMap": true,
"paths": {}
}
}

View File

@@ -0,0 +1,14 @@
{
"include": ["src", "types"],
"exclude": ["src/client/**/*"],
"extends": "../../tsconfig.build.json",
"compilerOptions": {
"types": ["node"],
"rootDir": "./src",
"baseUrl": ".",
"paths": {
"@test/*": ["test/*"],
"@test": ["test"]
}
}
}

View File

@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"include": ["test", "src"],
"compilerOptions": {
"rootDir": ".",
"types": ["node", "jest", "@testing-library/jest-dom"]
}
}

View File

@@ -0,0 +1,47 @@
import { defineConfig } from "tsup";
import { NodeResolvePlugin } from "@esbuild-plugins/node-resolve";
import { lodashReplacePlugin } from "../shared/lodash-replace-plugin";
export default defineConfig((tsupOptions) => {
const onSuccess = [
...(tsupOptions.watch ? ["pnpm types"] : []),
...(process.env.STANDALONE_DEVTOOLS_SERVER === "true" && tsupOptions.watch
? ["pnpm start:server"]
: []),
].join(" && ");
return {
entry: ["src/index.ts", "src/cli.ts"],
splitting: false,
sourcemap: true,
clean: false,
minify: true,
format: ["cjs", "esm"],
outExtension: ({ format }) => ({ js: format === "cjs" ? ".cjs" : ".mjs" }),
platform: "node",
esbuildOptions: (options) => {
options.define = {
...options.define,
__DEVELOPMENT__:
process.env.USE_DEV_ENV === "true" || tsupOptions.watch
? "true"
: "false",
};
},
esbuildPlugins: [
lodashReplacePlugin,
NodeResolvePlugin({
extensions: [".js", "ts", "tsx", "jsx"],
onResolved: (resolved) => {
if (resolved.includes("node_modules")) {
return {
external: true,
};
}
return resolved;
},
}),
],
onSuccess: onSuccess ? onSuccess : undefined,
};
});