@rpcbase/client 0.230.0 → 0.231.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/package.json +11 -113
  2. package/src/apiClient/getServerApiClient.ts +131 -0
  3. package/src/apiClient/index.ts +86 -0
  4. package/src/index.ts +3 -0
  5. package/src/initClient.ts +32 -0
  6. package/src/types.ts +7 -0
  7. package/AppProvider/AnalyticsContainer.js +0 -56
  8. package/AppProvider/debug.js +0 -4
  9. package/AppProvider/index.tsx +0 -79
  10. package/access-control/ACLForm/components/GrantField/OpSelector.tsx +0 -129
  11. package/access-control/ACLForm/components/GrantField/ResourceSelector.tsx +0 -86
  12. package/access-control/ACLForm/components/GrantField/UsersSelector.tsx +0 -96
  13. package/access-control/ACLForm/components/GrantField/grant-field.scss +0 -26
  14. package/access-control/ACLForm/components/GrantField/icons/CheckMark.tsx +0 -16
  15. package/access-control/ACLForm/components/GrantField/icons/CollapseArrow.tsx +0 -14
  16. package/access-control/ACLForm/components/GrantField/icons/ExpandArrow.tsx +0 -14
  17. package/access-control/ACLForm/components/GrantField/index.tsx +0 -91
  18. package/access-control/ACLForm/components/GrantsList.tsx +0 -48
  19. package/access-control/ACLForm/components/RoleForm.tsx +0 -134
  20. package/access-control/ACLForm/components/RoleView.tsx +0 -115
  21. package/access-control/ACLForm/components/RolesList.tsx +0 -79
  22. package/access-control/ACLForm/components/constants.tsx +0 -1
  23. package/access-control/ACLForm/components/resolver.ts +0 -57
  24. package/access-control/ACLForm/components/role-form.scss +0 -19
  25. package/access-control/ACLForm/index.tsx +0 -48
  26. package/access-control/ACLModal/acl-modal.scss +0 -7
  27. package/access-control/ACLModal/index.tsx +0 -66
  28. package/access-control/PolicyEditor/TargetSelector/QueryBuilder.tsx +0 -48
  29. package/access-control/PolicyEditor/TargetSelector/index.tsx +0 -5
  30. package/access-control/PolicyEditor/TargetSelector/query-builder.scss +0 -9
  31. package/access-control/PolicyEditor/index.tsx +0 -165
  32. package/access-control/index.ts +0 -3
  33. package/apiClient.js +0 -15
  34. package/auth/authProps.js +0 -8
  35. package/auth/components/AccountsList/AccountListItem.js +0 -61
  36. package/auth/components/AccountsList/account-list-item.scss +0 -5
  37. package/auth/components/AccountsList/index.js +0 -17
  38. package/auth/components/Footer/index.js +0 -11
  39. package/auth/components/ForgotPassword/forgot-password.scss +0 -37
  40. package/auth/components/ForgotPassword/index.js +0 -114
  41. package/auth/components/SetNewPassword/index.js +0 -130
  42. package/auth/components/SetNewPassword/set-new-password.scss +0 -47
  43. package/auth/components/SignIn/SignInEmailForm.tsx +0 -115
  44. package/auth/components/SignIn/index.js +0 -69
  45. package/auth/components/SignIn/sign-in.scss +0 -56
  46. package/auth/components/SignOut/index.js +0 -144
  47. package/auth/components/SignOut/sign-out.scss +0 -34
  48. package/auth/components/SignUp/SignUpEmailForm.tsx +0 -98
  49. package/auth/components/SignUp/index.js +0 -66
  50. package/auth/components/SignUp/sign-up.scss +0 -56
  51. package/auth/getTenantId.js +0 -12
  52. package/auth/getUid.js +0 -11
  53. package/auth/helpers/redirectSignIn.native.js +0 -9
  54. package/auth/helpers/redirectSignIn.web.js +0 -7
  55. package/auth/index.js +0 -146
  56. package/auth/signOut.js +0 -20
  57. package/auth/useAuthRouter.js +0 -56
  58. package/env.d.ts +0 -3
  59. package/firebase/index.js +0 -1
  60. package/firebase/sw.js +0 -1
  61. package/form/FileInput/FileUploadContext.tsx +0 -162
  62. package/form/FileInput/FileUploadForm/index.tsx +0 -139
  63. package/form/FileInput/FileUploadForm/usePreventUnload.js +0 -21
  64. package/form/FileInput/UploadButton.tsx +0 -23
  65. package/form/FileInput/constants.ts +0 -16
  66. package/form/FileInput/file-input.scss +0 -1
  67. package/form/FileInput/index.tsx +0 -21
  68. package/form/FileInput/upload-worker/get_file_hash.js +0 -63
  69. package/form/FileInput/upload-worker/index.js +0 -16
  70. package/form/FileInput/upload-worker/no_compress_exts.ts +0 -33
  71. package/form/FileInput/upload-worker/upload_file.js +0 -129
  72. package/form/Form.tsx +0 -23
  73. package/form/Input.tsx +0 -62
  74. package/form/SubmitButton/index.tsx +0 -58
  75. package/form/hook-form.tsx +0 -7
  76. package/form/index.tsx +0 -5
  77. package/getBaseUrl.js +0 -14
  78. package/getObjectId.ts +0 -31
  79. package/hashState.js +0 -158
  80. package/helpers/createBatcher/index.js +0 -36
  81. package/helpers/getInitials.js +0 -39
  82. package/helpers/onReady.js +0 -15
  83. package/helpers/post.js +0 -18
  84. package/helpers/postRPC.js +0 -42
  85. package/helpers/useRPC.js +0 -41
  86. package/helpers/useStoredValue/batchedGetStoredValues.js +0 -30
  87. package/helpers/useStoredValue/index.js +0 -107
  88. package/helpers/useStoredValue/setStoredValues.js +0 -14
  89. package/i18n/en/rb.nav.json +0 -13
  90. package/i18n/en/rb.sign_in.json +0 -11
  91. package/i18n/en/rb.sign_out.json +0 -5
  92. package/i18n/fr/rb.sign_in.json +0 -11
  93. package/i18n/fr/rb.sign_out.json +0 -5
  94. package/i18n/index.js +0 -63
  95. package/index.js +0 -6
  96. package/isEqualValues.js +0 -47
  97. package/jest.config.js +0 -16
  98. package/notifications/Notification/index.js +0 -36
  99. package/notifications/Notification/notification.scss +0 -1
  100. package/notifications/NotificationItem/HeaderStatus.js +0 -93
  101. package/notifications/NotificationItem/index.js +0 -65
  102. package/notifications/NotificationItem/notification-item.scss +0 -25
  103. package/notifications/NotificationsContainer/index.js +0 -37
  104. package/notifications/NotificationsContainer/notifications-container.scss +0 -38
  105. package/notifications/NotificationsContainer/useLLTs.js +0 -28
  106. package/notifications/NotificationsContext/index.js +0 -71
  107. package/notifications/NotificationsContext/useNotificationsList.js +0 -75
  108. package/notifications/NotificationsSettingsModal/SettingsForm.js +0 -52
  109. package/notifications/NotificationsSettingsModal/index.js +0 -48
  110. package/notifications/NotificationsSettingsModal/notifications-settings.scss +0 -1
  111. package/notifications/config.js +0 -1
  112. package/notifications/index.js +0 -4
  113. package/page.js +0 -9
  114. package/publish-output.txt +0 -0
  115. package/rpc.js +0 -32
  116. package/rr-trace/get_fingerprint.js +0 -10
  117. package/rr-trace/get_perf_vitals.js +0 -24
  118. package/rr-trace/get_session_id.js +0 -29
  119. package/rr-trace/index.js +0 -138
  120. package/rr-trace/write_session_data.js +0 -86
  121. package/rts/boot.js +0 -3
  122. package/rts/getUseDocument.js +0 -21
  123. package/rts/getUseQuery/index.js +0 -233
  124. package/rts/getUseQuery/useData.js +0 -55
  125. package/rts/index.js +0 -10
  126. package/rts/rts.js +0 -243
  127. package/rts/signout.ts +0 -8
  128. package/rts/store/constants.js +0 -3
  129. package/rts/store/debug.js +0 -24
  130. package/rts/store/get_collection.js +0 -55
  131. package/rts/store/index.js +0 -100
  132. package/rts/store/replace_query_keys.js +0 -31
  133. package/rts/store/satisfies_projection.js +0 -32
  134. package/rts/store/update_docs.js +0 -47
  135. package/storage/index.jest.js +0 -15
  136. package/storage/index.native.js +0 -38
  137. package/storage/index.web.js +0 -25
  138. package/types.ts +0 -6
  139. package/ui/ActivityIndicator/index.js +0 -113
  140. package/ui/Avatar/index.native.js +0 -31
  141. package/ui/Avatar/index.web.js +0 -37
  142. package/ui/Avatar/styles.js +0 -41
  143. package/ui/ErrorBoundary/index.js +0 -12
  144. package/ui/ExpandableFloatView/exp.scss +0 -15
  145. package/ui/ExpandableFloatView/index.tsx +0 -123
  146. package/ui/ExpandableFloatView/useBackdrop.js +0 -45
  147. package/ui/LottiePlayer/LottiePlayer.js +0 -4
  148. package/ui/LottiePlayer/index.js +0 -8
  149. package/ui/Modal/HashStateModal.js +0 -30
  150. package/ui/Modal/Modal.js +0 -93
  151. package/ui/Modal/ModalForm/AlertBanner.js +0 -82
  152. package/ui/Modal/ModalForm/index.js +0 -188
  153. package/ui/Modal/ModalForm/modal-form.scss +0 -63
  154. package/ui/Modal/index.js +0 -10
  155. package/ui/Modal/modal.scss +0 -101
  156. package/ui/Modal/withHashStateModal.js +0 -24
  157. package/ui/RedboxError/index.js +0 -3
  158. package/ui/Search/SearchHistory/index.js +0 -45
  159. package/ui/Search/SearchHistory/search-history.scss +0 -9
  160. package/ui/Search/SearchHistory/useSearchHistory.tsx +0 -57
  161. package/ui/Search/SearchResults/index.tsx +0 -90
  162. package/ui/Search/index.tsx +0 -298
  163. package/ui/Search/search.scss +0 -0
  164. package/ui/SelectPills/index.tsx +0 -96
  165. package/ui/SelectPills/select-pills.scss +0 -66
  166. package/ui/Tabs/index.tsx +0 -161
  167. package/ui/Tabs/tabs.scss +0 -53
  168. package/ui/Tree/index.js +0 -257
  169. package/ui/Tree/model.js +0 -71
  170. package/ui/Tree/node.js +0 -112
  171. package/ui/Tree/tree.scss +0 -98
  172. package/ui/UserAvatar/default_colors.json +0 -82
  173. package/ui/UserAvatar/index.js +0 -55
  174. package/ui/View/index.tsx +0 -17
  175. package/ui/View/index.web.js +0 -44
  176. package/ui/animations/checkmark.json +0 -1
  177. package/ui/helpers/SizeContext/index.tsx +0 -11
  178. package/ui/helpers/helpers.scss +0 -61
  179. package/ui/helpers/index.ts +0 -6
  180. package/ui/helpers/stopEventPropagation.js +0 -5
  181. package/ui/helpers/useActiveListItemIndex/index.tsx +0 -45
  182. package/ui/helpers/useScrollSelectorIntoView/index.tsx +0 -14
  183. package/ui/helpers/useThrottledMeasure/index.js +0 -47
  184. package/ui/helpers/withSuspense/index.js +0 -37
  185. package/ui/icons/AddAccount.tsx +0 -5
  186. package/ui/icons/Billing.tsx +0 -6
  187. package/ui/icons/Close.tsx +0 -14
  188. package/ui/icons/Organization.tsx +0 -5
  189. package/ui/icons/Signout.tsx +0 -5
  190. package/ui/icons/index.tsx +0 -6
  191. package/ui/nav/AccountsDropdown/SwitchAccounts.tsx +0 -28
  192. package/ui/nav/AccountsDropdown/accounts-dropdown.scss +0 -51
  193. package/ui/nav/AccountsDropdown/index.tsx +0 -90
  194. package/ui/nav/AccountsToggle/index.tsx +0 -24
  195. package/ui/nav/ContentView/ContentViewContext.ts +0 -23
  196. package/ui/nav/ContentView/index.tsx +0 -115
  197. package/ui/nav/HeaderContainer/header.scss +0 -52
  198. package/ui/nav/HeaderContainer/index.tsx +0 -23
  199. package/ui/nav/HeaderContainer/variables.scss +0 -1
  200. package/ui/nav/MorphingDropdown/MorphingDropdownContext.tsx +0 -151
  201. package/ui/nav/MorphingDropdown/MorphingDropdownMenu.tsx +0 -38
  202. package/ui/nav/MorphingDropdown/MorphingDropdownPortal.tsx +0 -166
  203. package/ui/nav/MorphingDropdown/MorphingDropdownToggle.tsx +0 -34
  204. package/ui/nav/MorphingDropdown/index.tsx +0 -16
  205. package/ui/nav/MorphingDropdown/morphing-dropdown.scss +0 -35
  206. package/ui/nav/NotificationsDropdown/index.tsx +0 -52
  207. package/ui/nav/NotificationsDropdown/notifications-dropdown.scss +0 -5
  208. package/ui/nav/NotificationsToggle/NotificationsGlyph.tsx +0 -54
  209. package/ui/nav/NotificationsToggle/index.tsx +0 -12
  210. package/ui/nav/NotificationsToggle/notification-animation.json +0 -1
  211. package/ui/nav/NotificationsToggle/notifications-toggle.scss +0 -26
  212. package/ui/nav/SidebarContainer/index.tsx +0 -48
  213. package/ui/nav/SidebarContainer/sidebar-container.scss +0 -21
  214. package/ui/nav/SlideoutContainer/components/Body.tsx +0 -19
  215. package/ui/nav/SlideoutContainer/components/Header.tsx +0 -23
  216. package/ui/nav/SlideoutContainer/components/Wrapper.tsx +0 -46
  217. package/ui/nav/SlideoutContainer/index.tsx +0 -50
  218. package/ui/nav/SlideoutContainer/slideout-container.scss +0 -40
  219. package/ui/nav/index.ts +0 -13
  220. package/ui/oauth/GitHub.js +0 -38
  221. package/ui/oauth/getGitHubSigninUrl.js +0 -30
  222. package/ui/oauth/index.js +0 -9
  223. package/ui/oauth/oauth.scss +0 -16
  224. package/ui/sortable-hoc/AutoScroller.js +0 -76
  225. package/ui/sortable-hoc/DragHandle.js +0 -31
  226. package/ui/sortable-hoc/Manager.js +0 -54
  227. package/ui/sortable-hoc/README.md +0 -1
  228. package/ui/sortable-hoc/SortableContainer/defaultGetHelperDimensions.js +0 -7
  229. package/ui/sortable-hoc/SortableContainer/defaultShouldCancelStart.js +0 -24
  230. package/ui/sortable-hoc/SortableContainer/index.js +0 -994
  231. package/ui/sortable-hoc/SortableContainer/props.js +0 -81
  232. package/ui/sortable-hoc/SortableElement.js +0 -111
  233. package/ui/sortable-hoc/SortableHandle.js +0 -45
  234. package/ui/sortable-hoc/drag-handle.scss +0 -14
  235. package/ui/sortable-hoc/index.js +0 -9
  236. package/ui/sortable-hoc/utils.js +0 -292
  237. package/ui/springs.ts +0 -17
package/package.json CHANGED
@@ -1,81 +1,20 @@
1
1
  {
2
2
  "name": "@rpcbase/client",
3
- "version": "0.230.0",
3
+ "version": "0.231.0",
4
+ "type": "module",
5
+ "main": "./src/index.ts",
4
6
  "scripts": {
5
- "build": "../../node_modules/.bin/wireit",
6
- "test": "../../node_modules/.bin/wireit"
7
- },
8
- "publishConfig": {
9
- "registry": "https://registry.npmjs.org/"
7
+ "build": "tsc --watch",
8
+ "release": "wireit"
10
9
  },
11
10
  "wireit": {
12
- "install": {
13
- "command": "NODE_ENV=development yarn install --mutex network --frozen-lockfile",
14
- "files": [
15
- "yarn.lock"
16
- ],
17
- "output": [
18
- "node_modules/"
19
- ],
20
- "allowUsuallyExcludedPaths": true
21
- },
22
- "build-firebase": {
23
- "command": "webpack -c firebase/webpack.config.js",
24
- "dependencies": [
25
- "install"
26
- ],
27
- "files": [
28
- "firebase/entry*.js",
29
- "firebase/webpack.config.js"
30
- ],
31
- "output": [
32
- "firebase/index.js",
33
- "firebase/sw.js"
34
- ]
35
- },
36
- "build": {
37
- "dependencies": [
38
- "build-firebase"
39
- ]
40
- },
41
- "test": {
42
- "command": "jest --coverage --coverageDirectory coverage/",
43
- "dependencies": [
44
- "build"
45
- ],
46
- "files": [
47
- "**/*.js",
48
- "!coverage/",
49
- "!node_modules/"
50
- ],
51
- "output": [
52
- "coverage/"
53
- ]
54
- },
55
- "apply-version": {
56
- "command": "node ../../scripts/prflow/apply-prerelease-versions.js $BRANCH_NAME",
57
- "files": [
58
- "package.json"
59
- ],
60
- "output": [],
61
- "env": {
62
- "BRANCH_NAME": {
63
- "external": true
64
- }
65
- }
66
- },
67
11
  "release": {
68
- "command": "npm publish --tag $NPM_RELEASE_CHANNEL | tee publish-output.txt",
69
- "dependencies": [
70
- "test",
71
- "apply-version"
72
- ],
12
+ "command": "../../scripts/publish.js",
13
+ "dependencies": [],
73
14
  "files": [
74
15
  "package.json"
75
16
  ],
76
- "output": [
77
- "publish-output.txt"
78
- ],
17
+ "output": [],
79
18
  "env": {
80
19
  "NPM_RELEASE_CHANNEL": {
81
20
  "external": true
@@ -83,50 +22,9 @@
83
22
  }
84
23
  }
85
24
  },
25
+ "peerDependencies": {},
86
26
  "dependencies": {
87
- "@fingerprintjs/fingerprintjs": "3.4.2",
88
- "@rpcbase/lottie": "3.5.3",
89
- "@rpcbase/redbox-react": "0.3.0",
90
- "@ui-kitten/components": "5.3.1",
91
- "figma-squircle": "0.3.1",
92
- "firebase": "11.0.2",
93
- "framer-motion": "11.11.17",
94
- "fuzzysort": "3.1.0",
95
- "i18next": "23.16.4",
96
- "i18next-chained-backend": "4.6.2",
97
- "i18next-resources-to-backend": "1.2.1",
98
- "js-tree": "2.0.2",
99
- "lz-string": "1.5.0",
100
- "posthog-js": "1.188.0",
101
- "pouchdb-adapter-indexeddb": "9.0.0",
102
- "pouchdb-core": "9.0.0",
103
- "pouchdb-find": "9.0.0",
104
- "react-bootstrap-typeahead": "6.3.2",
105
- "react-i18next": "15.1.0",
106
- "rrweb": "1.1.3",
107
- "socket.io-client": "4.8.1",
108
- "web-vitals": "4.2.4"
27
+ "axios": "1.7.9"
109
28
  },
110
- "devDependencies": {
111
- "@babel/core": "7.26.0",
112
- "@babel/plugin-transform-modules-commonjs": "7.25.9",
113
- "@babel/plugin-transform-runtime": "7.25.9",
114
- "@babel/preset-react": "7.25.9",
115
- "@testing-library/dom": "10.4.0",
116
- "@testing-library/react": "16.0.1",
117
- "axios": "1.7.7",
118
- "babel-jest": "29.7.0",
119
- "bluebird": "3.7.2",
120
- "jest": "29.7.0",
121
- "jest-environment-jsdom": "29.7.0",
122
- "lodash": "4.17.21",
123
- "page": "1.11.6",
124
- "react": "19.0.0-rc.1",
125
- "react-dom": "19.0.0-rc.1",
126
- "@rpcbase/react-native-web": "0.19.13",
127
- "react-test-renderer": "19.0.0-rc.1",
128
- "validator": "13.12.0",
129
- "webpack": "5.96.1",
130
- "webpack-cli": "5.1.4"
131
- }
29
+ "devDependencies": {}
132
30
  }
@@ -0,0 +1,131 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import assert from "assert"
3
+
4
+ import { Application, IRouter, Request, Response } from "express"
5
+
6
+ // import { Ctx } from "@rpcbase/api"
7
+ type Ctx = any
8
+
9
+
10
+ export const getServerApiClient = async(app: Application) => {
11
+ const callRoute = async <TResponse = Record<string, unknown>>(
12
+ app: Application,
13
+ method: string,
14
+ path: string,
15
+ req: Partial<Request>,
16
+ res: Partial<Response>
17
+ ): Promise<TResponse> => {
18
+ return new Promise((resolve, reject) => {
19
+ let isEnded = false
20
+
21
+ const mockReq = {
22
+ ...req,
23
+ method: method.toUpperCase(),
24
+ url: path
25
+ } as Request
26
+
27
+ const mockRes = {
28
+ ...res,
29
+ json: (data: any) => {
30
+ if (!isEnded) {
31
+ isEnded = true
32
+ resolve(data)
33
+ }
34
+ },
35
+ status: (statusCode: number) => {
36
+ console.log("Status:", statusCode)
37
+ return mockRes
38
+ },
39
+ } as Response
40
+
41
+ const routerStack: any[] = (app.router as unknown as IRouter).stack
42
+
43
+ const firstApiMiddlewareIndex = routerStack.findIndex((layer) => layer.name === "__FIRST_API_MIDDLEWARE__")
44
+ if (!(firstApiMiddlewareIndex > -1)) {
45
+ throw new Error("middleware: __FIRST_API_MIDDLEWARE__ was not found in stack")
46
+ }
47
+
48
+ const apiStack = routerStack.slice(firstApiMiddlewareIndex + 1)
49
+
50
+ const processLayer = async (index: number) => {
51
+ if (index >= apiStack.length || isEnded) return
52
+
53
+ const layer = apiStack[index]
54
+
55
+ const isNonMatchingLayer = !layer.match(path)
56
+ if (isNonMatchingLayer) {
57
+ // console.log("not machthing route:", path, "to layer:", index, layer.name, layer, "reason: ", {isNonMatchingLayer})
58
+ await processLayer(index + 1)
59
+ return
60
+ }
61
+
62
+ const runHandler = async(handler: any) => new Promise<void>((resolveMiddleware, rejectMiddleware) => {
63
+ handler(mockReq, mockRes, (err?: any) => {
64
+ if (err) {
65
+ console.error("Middleware error:", err)
66
+ if (!isEnded) {
67
+ isEnded = true
68
+ rejectMiddleware(err)
69
+ }
70
+ return
71
+ }
72
+ resolveMiddleware()
73
+ })
74
+ })
75
+
76
+ if (layer.route) {
77
+ if (!layer.route.methods[method.toLowerCase()]) {
78
+ // console.log("not machthing route:", path, "to route layer:", index, layer.name, layer, "reason: method not matching")
79
+ await processLayer(index + 1)
80
+ return
81
+ }
82
+
83
+ assert(layer.route.stack.length === 1, `expected only one handler per route for route: ${layer.route.path}`)
84
+
85
+ await runHandler(layer.route.stack[0].handle)
86
+
87
+ } else {
88
+ await runHandler(layer.handle)
89
+ }
90
+
91
+ if (!isEnded) {
92
+ await processLayer(index + 1)
93
+ }
94
+ }
95
+
96
+ // AWAIT ??
97
+ processLayer(0)
98
+
99
+ // Set a timeout to prevent hanging
100
+ setTimeout(() => {
101
+ if (!isEnded) {
102
+ reject("Route handler timed out")
103
+ }
104
+ }, 30000)
105
+ })
106
+ }
107
+
108
+ const createMethod = (method: string) => {
109
+ return async <TResponse = Record<string, unknown>>(
110
+ path: string,
111
+ payload: Record<string, unknown>,
112
+ ctx?: Ctx,
113
+ ): Promise<TResponse> => {
114
+ assert(ctx, "Context must be provided in SSR mode")
115
+
116
+ ctx.req.body = payload
117
+ return callRoute<TResponse>(app, method, path, ctx.req, ctx.res)
118
+ }
119
+ }
120
+
121
+ const apiClient = {
122
+ get: createMethod("get"),
123
+ post: createMethod("post"),
124
+ put: createMethod("put"),
125
+ delete: createMethod("delete")
126
+ }
127
+
128
+ return apiClient
129
+ }
130
+
131
+ export default getServerApiClient
@@ -0,0 +1,86 @@
1
+ import assert from "assert"
2
+
3
+ import type { Application } from "express"
4
+
5
+ // import { Ctx } from "@rpcbase/api"
6
+ type Ctx = any
7
+
8
+
9
+ type ServerArgs = {
10
+ app: Application;
11
+ };
12
+
13
+ type PayloadNotCtx = Record<string, unknown> & {
14
+ [P in keyof Ctx]?: never;
15
+ };
16
+
17
+ type ApiClientMethod = <TResponse = Record<string, unknown>>(
18
+ path: string,
19
+ payload: PayloadNotCtx,
20
+ ctx?: Ctx,
21
+ ) => Promise<TResponse>;
22
+
23
+ export type HttpMethod = "get" | "put" | "post" | "delete";
24
+ type MethodRecord<T> = Record<HttpMethod, T>;
25
+
26
+ export type ApiClient = MethodRecord<ApiClientMethod>;
27
+
28
+ let apiClient: ApiClient
29
+
30
+ export const initApiClient = async (args?: ServerArgs) => {
31
+ // @ts-ignore
32
+ if (import.meta.env.SSR) {
33
+ assert(args, "Server args must be provided in SSR mode")
34
+
35
+ const { getServerApiClient } = await import("./getServerApiClient")
36
+
37
+ apiClient = await getServerApiClient(args.app)
38
+ } else {
39
+ const axios = (await import("axios")).default
40
+
41
+ const axiosClient = axios.create({
42
+ baseURL: "/",
43
+ withCredentials: true,
44
+ headers: {
45
+ "Content-Type": "application/json",
46
+ },
47
+ })
48
+
49
+ const createMethod = (method: string): ApiClientMethod => {
50
+ return async <TResponse = Record<string, unknown>>(
51
+ path: string,
52
+ payload: PayloadNotCtx,
53
+ _ctx?: Ctx,
54
+ ): Promise<TResponse> => {
55
+ const config = {
56
+ method,
57
+ url: path,
58
+ data: payload,
59
+ headers: {
60
+ // ...(typeof ctxOrPath !== 'string' && {
61
+ // // 'X-Custom-Header': ctxOrPath.someHeaderValue,
62
+ // // ...ctxOrPath.additionalHeaders,
63
+ // }),
64
+ },
65
+ }
66
+
67
+ try {
68
+ const response = await axiosClient(config)
69
+ return response.data
70
+ } catch (error) {
71
+ console.log("AXIOS API ERROR", error)
72
+ throw error
73
+ }
74
+ }
75
+ }
76
+
77
+ apiClient = {
78
+ get: createMethod("get"),
79
+ put: createMethod("put"),
80
+ post: createMethod("post"),
81
+ delete: createMethod("delete"),
82
+ }
83
+ }
84
+ }
85
+
86
+ export { apiClient }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./apiClient"
2
+ export * from "./initClient"
3
+ export * from "./types"
@@ -0,0 +1,32 @@
1
+ import { initApiClient } from "./apiClient"
2
+
3
+ /* eslint-disable @typescript-eslint/no-explicit-any */
4
+ const showErrorOverlay = (err: { title: string, message: string, reason: string, plugin: string }) => {
5
+ const ErrorOverlay = customElements.get("vite-error-overlay")
6
+ // don't open outside vite environment
7
+ if (!ErrorOverlay) {return}
8
+ console.log(err)
9
+ const overlay = new ErrorOverlay(err)
10
+ document.body.appendChild(overlay)
11
+ }
12
+
13
+
14
+ const handleServerErrors = () => {
15
+ if ((window as any).__staticRouterHydrationData?.errors) {
16
+
17
+ const {errors} = (window as any).__staticRouterHydrationData
18
+
19
+ Object.values(errors).forEach((error: any) => {
20
+ showErrorOverlay({
21
+ plugin: "ssr-router",
22
+ ...error.reason
23
+ })
24
+ })
25
+ }
26
+ }
27
+
28
+ export const initClient = () => {
29
+ initApiClient()
30
+
31
+ handleServerErrors()
32
+ }
package/src/types.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { Ctx } from "@rpcbase/api";
2
+ import { Params } from "@rpcbase/router"
3
+
4
+ export type LoaderArgs = {params: Params, ctx: Ctx}
5
+
6
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
+ export type Loader = ({params, ctx}: LoaderArgs) => Promise<any>
@@ -1,56 +0,0 @@
1
- /* @flow */
2
- import {useEffect} from "react"
3
- import {usePostHog} from "posthog-js/react"
4
- import FingerprintJS from "@fingerprintjs/fingerprintjs"
5
-
6
- import getUid from "../auth/getUid"
7
-
8
- // TMP: RB_TENANT_ID must come from the server, not be set in env here
9
- import {RB_TENANT_ID, POSTHOG_KEY} from "env"
10
-
11
-
12
- const AnalyticsContainer = ({children}) => {
13
- const {hostname} = window.location
14
- if (__DEV__ || hostname === "localhost" || hostname.endsWith(".local")) return null
15
- if (!POSTHOG_KEY) return null
16
-
17
- const posthog = usePostHog()
18
-
19
- const uid = getUid()
20
-
21
- useEffect(() => {
22
- if (!posthog) return
23
-
24
- if (uid) {
25
- posthog.identify(uid, {
26
- uid,
27
- env: __DEV__ ? "dev" : "prod",
28
- })
29
- posthog.group("customer", RB_TENANT_ID, {
30
- name: "default",
31
- })
32
- posthog.group("env", __DEV__ ? "dev" : "prod")
33
- }
34
- // user isn't identified, use fingerprint instead
35
- else {
36
- const run = async() => {
37
- const fp = await FingerprintJS.load()
38
- const fpResult = await fp.get()
39
-
40
- posthog.identify(fpResult.visitorId, {
41
- type: "fingerprint",
42
- env: __DEV__ ? "dev" : "prod",
43
- })
44
- }
45
-
46
- run()
47
- }
48
- }, [posthog, uid])
49
-
50
-
51
- return (
52
- <>{children}</>
53
- )
54
- }
55
-
56
- export default AnalyticsContainer
@@ -1,4 +0,0 @@
1
- /* @flow */
2
- import {DEBUG} from "env"
3
-
4
- localStorage.debug = DEBUG
@@ -1,79 +0,0 @@
1
- import "./debug"
2
- import {useEffect} from "react"
3
- import {PostHogProvider} from "posthog-js/react"
4
-
5
- import page from "../page"
6
- import {HashStateProvider} from "../hashState"
7
-
8
- import AnalyticsContainer from "./AnalyticsContainer"
9
-
10
- // TODO: flags here should be optional
11
- import {flagValues} from "config/flags"
12
-
13
- import {POSTHOG_KEY} from "env"
14
- import {useAuthRouter} from "../auth/useAuthRouter"
15
- import getTenantId from "../auth/getTenantId"
16
- import getUid from "../auth/getUid"
17
- import {NotificationsProvider, NotificationsContainer} from "../notifications"
18
- import {connect as rts_connect} from "../rts/rts"
19
-
20
- // initial rts connect
21
- const tenantId = getTenantId()
22
- rts_connect(tenantId, getUid())
23
-
24
-
25
- const PostHogWrapper = ({children, ...props}) => {
26
-
27
- const {hostname} = window.location
28
-
29
- const hasPostHogKey = !!POSTHOG_KEY
30
-
31
- if (__DEV__ || hostname === "localhost" || hostname.endsWith(".local") || !hasPostHogKey) {
32
- return (
33
- <>{children}</>
34
- )
35
- } else {
36
- return (
37
- <PostHogProvider
38
- apiKey={POSTHOG_KEY}
39
- options={{
40
- api_host: "https://eu.posthog.com",
41
- // TODO: this doesn't work
42
- bootstrap: {
43
- featureFlags: flagValues,
44
- },
45
- }}
46
- >
47
- <AnalyticsContainer>
48
- {children}
49
- </AnalyticsContainer>
50
- </PostHogProvider>
51
- )
52
- }
53
- }
54
-
55
- const AppProvider = ({children, ...props}) => {
56
-
57
- const {authComponent} = useAuthRouter()
58
-
59
- useEffect(() => {
60
- page.start()
61
- }, [])
62
-
63
- return (
64
- <PostHogWrapper>
65
- <HashStateProvider>
66
- <NotificationsProvider>
67
- <div className={cx({"d-none": !!authComponent})}>
68
- {children}
69
- </div>
70
- {authComponent}
71
- <NotificationsContainer />
72
- </NotificationsProvider>
73
- </HashStateProvider>
74
- </PostHogWrapper>
75
- )
76
-
77
- }
78
-
79
- export default AppProvider
@@ -1,129 +0,0 @@
1
- import _get from "lodash/get"
2
- import {useState} from "react"
3
- import ToggleButton from "react-bootstrap/ToggleButton"
4
- import ToggleButtonGroup from "react-bootstrap/ToggleButtonGroup"
5
-
6
- import {useFormContext} from "react-hook-form"
7
-
8
- import {GRANTS_FIELD} from "../constants"
9
- import {CheckMark} from "./icons/CheckMark"
10
-
11
-
12
- const OPS = {
13
- create: "Create",
14
- read: "Read",
15
- update: "Update",
16
- delete: "Delete",
17
- }
18
-
19
- export const OpSelector = ({field, index, update}) => {
20
- const PREFIX = `select-op-field-${field.id}`
21
-
22
- const {
23
- formState: {errors},
24
- setValue,
25
- } = useFormContext()
26
-
27
- const fieldKey = `${GRANTS_FIELD}.${index}.ops`
28
- const err = _get(errors, fieldKey, null)
29
-
30
- const [ops, setOps] = useState(field.ops || {})
31
-
32
- const updateOps = (nextOps) => {
33
- setOps(nextOps)
34
- setValue(fieldKey, nextOps, {
35
- shouldTouch: true,
36
- shouldValidate: !!err, // revalidate if there is an error
37
- })
38
- }
39
-
40
- const handleChange = (selected) => {
41
- const nextOps = {...ops}
42
- // remove unselected keys from ops
43
- Object.keys(nextOps).forEach((k) => !selected.includes[k] && delete nextOps[k])
44
- // add new selected keys
45
- selected.forEach((s) => (nextOps[s] = "own"))
46
- updateOps(nextOps)
47
- }
48
-
49
- const getCRUDOps = () => Object.keys(ops)
50
-
51
- const getOpScope = (k) => ops[k]
52
-
53
- const updateOpScope = (k, selected) => {
54
- const nextOps = {...ops}
55
- nextOps[k] = selected
56
- updateOps(nextOps)
57
- }
58
-
59
- const getCaption = () => {
60
- if (err) {
61
- return <p className="text-danger pt-1">{err.message}</p>
62
- } else {
63
- // iterate on OPS first, not ops to preserve semantic order
64
- const targetOps = Object.keys(OPS).filter((k) => Object.keys(ops).includes(k))
65
- let captionStr
66
- if (targetOps.length === 0) {
67
- captionStr = "Select operations above"
68
- } else captionStr = `Allow ${targetOps.map((k) => `${OPS[k]}:${ops[k]}`).join(", ")}`
69
- return <p className="text-secondary mt-1">{captionStr}</p>
70
- }
71
- }
72
-
73
- return (
74
- <div className="op-selector">
75
- <div className="mb-1 fw-bold">Grant Operation:</div>
76
- <ToggleButtonGroup
77
- type="checkbox"
78
- // TODO: support vertical layout when the modal isn't wide enough
79
- // vertical
80
- className={cx("w-100", {"border": !!err, "border-danger": !!err})}
81
- value={getCRUDOps()}
82
- onChange={handleChange}
83
- >
84
- {Object.keys(OPS).map((k) => (
85
- <ToggleButton
86
- variant="light"
87
- key={`${PREFIX}-${index}-${k}`}
88
- id={`${PREFIX}-${index}-${k}`}
89
- value={k}
90
- className="toggle-button-op py-1"
91
- >
92
- <>
93
- <div className="">
94
- <CheckMark hide={!getCRUDOps().includes(k)} />
95
- {OPS[k]}
96
- </div>
97
- <ToggleButtonGroup
98
- className="pt-1"
99
- type="radio"
100
- name={`${k}_op_scope`}
101
- value={getOpScope(k)}
102
- onChange={(selected) => updateOpScope(k, selected)}
103
- >
104
- <ToggleButton
105
- variant="primary"
106
- id={`${PREFIX}-${index}-${k}-own`}
107
- value={"own"}
108
- className="toggle-button-op py-1 text-monospace"
109
- >
110
- own
111
- </ToggleButton>
112
- <ToggleButton
113
- variant="primary"
114
- id={`${PREFIX}-${index}-${k}-any`}
115
- value={"any"}
116
- className="toggle-button-op py-1 text-monospace"
117
- >
118
- any
119
- </ToggleButton>
120
- </ToggleButtonGroup>
121
- </>
122
- </ToggleButton>
123
- ))}
124
- </ToggleButtonGroup>
125
-
126
- {getCaption()}
127
- </div>
128
- )
129
- }