@terreno/mcp 57.21.0 → 58.0.0-beta.1

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 (244) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +57 -3
  3. package/dist/bootstrap.d.ts.map +1 -1
  4. package/dist/bootstrap.js +17 -16
  5. package/dist/bootstrap.js.map +1 -1
  6. package/dist/docs/guidelines/admin-frontend/guidelines/core.md +6 -5
  7. package/dist/docs/guidelines/ui/guidelines/core.md +1 -1
  8. package/dist/docs/prompts/debug.md +6 -4
  9. package/dist/docs/prompts/screen.md +11 -17
  10. package/dist/docs/resources/overview.md +5 -3
  11. package/dist/docs/resources/patterns.md +157 -238
  12. package/dist/docs/resources/syncdb.md +44 -16
  13. package/dist/docs/templates/bootstrap/CLAUDE.template.md +2 -2
  14. package/dist/docs/templates/bootstrap/cursorrules.template.md +7 -5
  15. package/dist/docs/templates/bootstrap/frontend/app/(tabs)/profile.template.tsx +8 -12
  16. package/dist/docs/templates/bootstrap/frontend/app/_layout.template.tsx +75 -52
  17. package/dist/docs/templates/bootstrap/frontend/app/login.template.tsx +46 -108
  18. package/dist/docs/templates/bootstrap/frontend/app/signup.template.tsx +53 -0
  19. package/dist/docs/templates/bootstrap/frontend/lib/betterAuth.template.md +18 -0
  20. package/dist/docs/templates/bootstrap/frontend/store/apiClient.template.md +33 -0
  21. package/dist/docs/templates/bootstrap/frontend/store/apiSdk.template.md +76 -0
  22. package/dist/docs/templates/bootstrap/frontend/store/syncdb.template.md +56 -0
  23. package/dist/docs/templates/bootstrap/frontend/utils/index.template.md +0 -4
  24. package/dist/docs/upgrades/58.0.0-beta.1.md +504 -0
  25. package/dist/docs/upgrades/58.0.0.md +495 -4
  26. package/dist/docs/versioned/next/README.md +2 -2
  27. package/dist/docs/versioned/next/approval-rubric.md +2 -2
  28. package/dist/docs/versioned/next/explanation/admin-interface.md +6 -5
  29. package/dist/docs/versioned/next/explanation/admin-plugin-frontend.md +1 -1
  30. package/dist/docs/versioned/next/explanation/ai-workflows.md +5 -3
  31. package/dist/docs/versioned/next/explanation/announcements/rtk-deprecation.md +16 -11
  32. package/dist/docs/versioned/next/explanation/authentication.md +62 -43
  33. package/dist/docs/versioned/next/explanation/dependency-management.md +1 -1
  34. package/dist/docs/versioned/next/explanation/deployment-baseline.md +1 -1
  35. package/dist/docs/versioned/next/explanation/example-coverage.md +2 -2
  36. package/dist/docs/versioned/next/explanation/explicit-any-policy.md +5 -6
  37. package/dist/docs/versioned/next/explanation/gcp-hosting-architecture.md +1 -1
  38. package/dist/docs/versioned/next/explanation/local-first-data.md +11 -9
  39. package/dist/docs/versioned/next/explanation/model-router-actions.md +1 -1
  40. package/dist/docs/versioned/next/explanation/modular-api-design.md +2 -2
  41. package/dist/docs/versioned/next/explanation/no-barrel-imports.md +5 -5
  42. package/dist/docs/versioned/next/explanation/roadmap-seed-issues.md +4 -3
  43. package/dist/docs/versioned/next/explanation/source-rules.md +2 -2
  44. package/dist/docs/versioned/next/explanation/typescript-configuration.md +2 -4
  45. package/dist/docs/versioned/next/explanation/versioning-policy.md +3 -3
  46. package/dist/docs/versioned/next/how-to/README.md +3 -2
  47. package/dist/docs/versioned/next/how-to/add-feature-flags.md +50 -25
  48. package/dist/docs/versioned/next/how-to/add-organizations.md +2 -1
  49. package/dist/docs/versioned/next/how-to/admin-custom-home.md +8 -2
  50. package/dist/docs/versioned/next/how-to/admin-custom-widget.md +0 -1
  51. package/dist/docs/versioned/next/how-to/agent-ui-asks.md +6 -6
  52. package/dist/docs/versioned/next/how-to/build-admin-screens.md +10 -8
  53. package/dist/docs/versioned/next/how-to/build-for-web.md +1 -1
  54. package/dist/docs/versioned/next/how-to/call-external-apis.md +2 -2
  55. package/dist/docs/versioned/next/how-to/circleci.md +12 -6
  56. package/dist/docs/versioned/next/how-to/configure-better-auth.md +114 -60
  57. package/dist/docs/versioned/next/how-to/connect-mcp-service-token.md +10 -4
  58. package/dist/docs/versioned/next/how-to/create-a-terreno-app.md +14 -2
  59. package/dist/docs/versioned/next/how-to/debug-with-mcp.md +8 -13
  60. package/dist/docs/versioned/next/how-to/expose-mcp-tools.md +15 -4
  61. package/dist/docs/versioned/next/how-to/generate-the-client-sdk.md +33 -0
  62. package/dist/docs/versioned/next/how-to/github-actions-ci.md +2 -2
  63. package/dist/docs/versioned/next/how-to/in-app-notifications.md +1 -1
  64. package/dist/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +318 -447
  65. package/dist/docs/versioned/next/how-to/password-reset.md +1 -1
  66. package/dist/docs/versioned/next/how-to/product-announcements.md +6 -3
  67. package/dist/docs/versioned/next/how-to/rate-limiting.md +38 -16
  68. package/dist/docs/versioned/next/how-to/run-mongodb-migrations.md +19 -0
  69. package/dist/docs/versioned/next/how-to/run-tests-locally.md +2 -3
  70. package/dist/docs/versioned/next/how-to/set-up-social-login.md +1 -1
  71. package/dist/docs/versioned/next/how-to/set-up-terreno-mcp.md +2 -2
  72. package/dist/docs/versioned/next/how-to/track-upstream-expo.md +1 -1
  73. package/dist/docs/versioned/next/how-to/upgrade-banner.md +5 -3
  74. package/dist/docs/versioned/next/how-to/upgrade-terreno.md +5 -5
  75. package/dist/docs/versioned/next/how-to/use-syncdb-correctly.md +1 -1
  76. package/dist/docs/versioned/next/how-to/websocket-integration.md +113 -402
  77. package/dist/docs/versioned/next/implementationPlans/b2b-platform-program.md +1 -1
  78. package/dist/docs/versioned/next/implementationPlans/migrate-admin-to-syncdb.md +5 -0
  79. package/dist/docs/versioned/next/implementationPlans/native-module-baseline.md +29 -5
  80. package/dist/docs/versioned/next/implementationPlans/remove-legacy-realtime.md +1 -1
  81. package/dist/docs/versioned/next/implementationPlans/remove-rtk.md +185 -0
  82. package/dist/docs/versioned/next/reference/README.md +1 -1
  83. package/dist/docs/versioned/next/reference/admin-frontend.md +85 -70
  84. package/dist/docs/versioned/next/reference/admin-spa.md +10 -4
  85. package/dist/docs/versioned/next/reference/ai.md +36 -4
  86. package/dist/docs/versioned/next/reference/announcements.md +3 -3
  87. package/dist/docs/versioned/next/reference/api.md +39 -24
  88. package/dist/docs/versioned/next/reference/cli.md +3 -4
  89. package/dist/docs/versioned/next/reference/environment-variables.md +16 -16
  90. package/dist/docs/versioned/next/reference/feature-flags.md +48 -7
  91. package/dist/docs/versioned/next/reference/jobs.md +2 -2
  92. package/dist/docs/versioned/next/reference/legacy/rtk.md +25 -600
  93. package/dist/docs/versioned/next/reference/mcp-server.md +441 -1158
  94. package/dist/docs/versioned/next/reference/syncdb.md +426 -16
  95. package/dist/docs/versioned/next/reference/test.md +28 -3
  96. package/dist/docs/versioned/next/reference/ui.md +132 -19
  97. package/dist/docs/versioned/next/tasks/native-module-baseline.md +8 -4
  98. package/dist/docs/versioned/next/tasks/rate-limiting.md +9 -2
  99. package/dist/docs/versioned/next/tasks/remove-legacy-realtime.md +5 -5
  100. package/dist/docs/versioned/next/tasks/remove-rtk.md +155 -0
  101. package/dist/local/localTools.d.ts.map +1 -1
  102. package/dist/local/localTools.js +3 -54
  103. package/dist/local/localTools.js.map +1 -1
  104. package/dist/local/tools/runtime.d.ts +0 -21
  105. package/dist/local/tools/runtime.d.ts.map +1 -1
  106. package/dist/local/tools/runtime.js +0 -176
  107. package/dist/local/tools/runtime.js.map +1 -1
  108. package/dist/local/tools/syncDb.d.ts +0 -11
  109. package/dist/local/tools/syncDb.d.ts.map +1 -1
  110. package/dist/local/tools/syncDb.js +1 -5
  111. package/dist/local/tools/syncDb.js.map +1 -1
  112. package/dist/packageGuidelines.d.ts +3 -2
  113. package/dist/packageGuidelines.d.ts.map +1 -1
  114. package/dist/packageGuidelines.js +4 -11
  115. package/dist/packageGuidelines.js.map +1 -1
  116. package/dist/prompts.d.ts.map +1 -1
  117. package/dist/prompts.js +17 -18
  118. package/dist/prompts.js.map +1 -1
  119. package/dist/resources.d.ts.map +1 -1
  120. package/dist/resources.js +1 -8
  121. package/dist/resources.js.map +1 -1
  122. package/dist/search/chunker.d.ts +1 -1
  123. package/dist/search/chunker.d.ts.map +1 -1
  124. package/dist/search/inferPackages.d.ts +1 -1
  125. package/dist/search/inferPackages.js +5 -5
  126. package/dist/search/inferPackages.js.map +1 -1
  127. package/dist/tools.d.ts +6 -0
  128. package/dist/tools.d.ts.map +1 -1
  129. package/dist/tools.js +126 -119
  130. package/dist/tools.js.map +1 -1
  131. package/package.json +6 -6
  132. package/src/docs/guidelines/admin-frontend/guidelines/core.md +6 -5
  133. package/src/docs/guidelines/ui/guidelines/core.md +1 -1
  134. package/src/docs/prompts/debug.md +6 -4
  135. package/src/docs/prompts/screen.md +11 -17
  136. package/src/docs/resources/overview.md +5 -3
  137. package/src/docs/resources/patterns.md +157 -238
  138. package/src/docs/resources/syncdb.md +44 -16
  139. package/src/docs/templates/bootstrap/CLAUDE.template.md +2 -2
  140. package/src/docs/templates/bootstrap/cursorrules.template.md +7 -5
  141. package/src/docs/templates/bootstrap/frontend/app/(tabs)/profile.template.tsx +8 -12
  142. package/src/docs/templates/bootstrap/frontend/app/_layout.template.tsx +75 -52
  143. package/src/docs/templates/bootstrap/frontend/app/login.template.tsx +46 -108
  144. package/src/docs/templates/bootstrap/frontend/app/signup.template.tsx +53 -0
  145. package/src/docs/templates/bootstrap/frontend/lib/betterAuth.template.md +18 -0
  146. package/src/docs/templates/bootstrap/frontend/store/apiClient.template.md +33 -0
  147. package/src/docs/templates/bootstrap/frontend/store/apiSdk.template.md +76 -0
  148. package/src/docs/templates/bootstrap/frontend/store/syncdb.template.md +56 -0
  149. package/src/docs/templates/bootstrap/frontend/utils/index.template.md +0 -4
  150. package/src/docs/upgrades/58.0.0-beta.1.md +504 -0
  151. package/src/docs/upgrades/58.0.0.md +495 -4
  152. package/src/docs/versioned/next/README.md +2 -2
  153. package/src/docs/versioned/next/approval-rubric.md +2 -2
  154. package/src/docs/versioned/next/explanation/admin-interface.md +6 -5
  155. package/src/docs/versioned/next/explanation/admin-plugin-frontend.md +1 -1
  156. package/src/docs/versioned/next/explanation/ai-workflows.md +5 -3
  157. package/src/docs/versioned/next/explanation/announcements/rtk-deprecation.md +16 -11
  158. package/src/docs/versioned/next/explanation/authentication.md +62 -43
  159. package/src/docs/versioned/next/explanation/dependency-management.md +1 -1
  160. package/src/docs/versioned/next/explanation/deployment-baseline.md +1 -1
  161. package/src/docs/versioned/next/explanation/example-coverage.md +2 -2
  162. package/src/docs/versioned/next/explanation/explicit-any-policy.md +5 -6
  163. package/src/docs/versioned/next/explanation/gcp-hosting-architecture.md +1 -1
  164. package/src/docs/versioned/next/explanation/local-first-data.md +11 -9
  165. package/src/docs/versioned/next/explanation/model-router-actions.md +1 -1
  166. package/src/docs/versioned/next/explanation/modular-api-design.md +2 -2
  167. package/src/docs/versioned/next/explanation/no-barrel-imports.md +5 -5
  168. package/src/docs/versioned/next/explanation/roadmap-seed-issues.md +4 -3
  169. package/src/docs/versioned/next/explanation/source-rules.md +2 -2
  170. package/src/docs/versioned/next/explanation/typescript-configuration.md +2 -4
  171. package/src/docs/versioned/next/explanation/versioning-policy.md +3 -3
  172. package/src/docs/versioned/next/how-to/README.md +3 -2
  173. package/src/docs/versioned/next/how-to/add-feature-flags.md +50 -25
  174. package/src/docs/versioned/next/how-to/add-organizations.md +2 -1
  175. package/src/docs/versioned/next/how-to/admin-custom-home.md +8 -2
  176. package/src/docs/versioned/next/how-to/admin-custom-widget.md +0 -1
  177. package/src/docs/versioned/next/how-to/agent-ui-asks.md +6 -6
  178. package/src/docs/versioned/next/how-to/build-admin-screens.md +10 -8
  179. package/src/docs/versioned/next/how-to/build-for-web.md +1 -1
  180. package/src/docs/versioned/next/how-to/call-external-apis.md +2 -2
  181. package/src/docs/versioned/next/how-to/circleci.md +12 -6
  182. package/src/docs/versioned/next/how-to/configure-better-auth.md +114 -60
  183. package/src/docs/versioned/next/how-to/connect-mcp-service-token.md +10 -4
  184. package/src/docs/versioned/next/how-to/create-a-terreno-app.md +14 -2
  185. package/src/docs/versioned/next/how-to/debug-with-mcp.md +8 -13
  186. package/src/docs/versioned/next/how-to/expose-mcp-tools.md +15 -4
  187. package/src/docs/versioned/next/how-to/generate-the-client-sdk.md +33 -0
  188. package/src/docs/versioned/next/how-to/github-actions-ci.md +2 -2
  189. package/src/docs/versioned/next/how-to/in-app-notifications.md +1 -1
  190. package/src/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +318 -447
  191. package/src/docs/versioned/next/how-to/password-reset.md +1 -1
  192. package/src/docs/versioned/next/how-to/product-announcements.md +6 -3
  193. package/src/docs/versioned/next/how-to/rate-limiting.md +38 -16
  194. package/src/docs/versioned/next/how-to/run-mongodb-migrations.md +19 -0
  195. package/src/docs/versioned/next/how-to/run-tests-locally.md +2 -3
  196. package/src/docs/versioned/next/how-to/set-up-social-login.md +1 -1
  197. package/src/docs/versioned/next/how-to/set-up-terreno-mcp.md +2 -2
  198. package/src/docs/versioned/next/how-to/track-upstream-expo.md +1 -1
  199. package/src/docs/versioned/next/how-to/upgrade-banner.md +5 -3
  200. package/src/docs/versioned/next/how-to/upgrade-terreno.md +5 -5
  201. package/src/docs/versioned/next/how-to/use-syncdb-correctly.md +1 -1
  202. package/src/docs/versioned/next/how-to/websocket-integration.md +113 -402
  203. package/src/docs/versioned/next/implementationPlans/b2b-platform-program.md +1 -1
  204. package/src/docs/versioned/next/implementationPlans/migrate-admin-to-syncdb.md +5 -0
  205. package/src/docs/versioned/next/implementationPlans/native-module-baseline.md +29 -5
  206. package/src/docs/versioned/next/implementationPlans/remove-legacy-realtime.md +1 -1
  207. package/src/docs/versioned/next/implementationPlans/remove-rtk.md +185 -0
  208. package/src/docs/versioned/next/reference/README.md +1 -1
  209. package/src/docs/versioned/next/reference/admin-frontend.md +85 -70
  210. package/src/docs/versioned/next/reference/admin-spa.md +10 -4
  211. package/src/docs/versioned/next/reference/ai.md +36 -4
  212. package/src/docs/versioned/next/reference/announcements.md +3 -3
  213. package/src/docs/versioned/next/reference/api.md +39 -24
  214. package/src/docs/versioned/next/reference/cli.md +3 -4
  215. package/src/docs/versioned/next/reference/environment-variables.md +16 -16
  216. package/src/docs/versioned/next/reference/feature-flags.md +48 -7
  217. package/src/docs/versioned/next/reference/jobs.md +2 -2
  218. package/src/docs/versioned/next/reference/legacy/rtk.md +25 -600
  219. package/src/docs/versioned/next/reference/mcp-server.md +441 -1158
  220. package/src/docs/versioned/next/reference/syncdb.md +426 -16
  221. package/src/docs/versioned/next/reference/test.md +28 -3
  222. package/src/docs/versioned/next/reference/ui.md +132 -19
  223. package/src/docs/versioned/next/tasks/native-module-baseline.md +8 -4
  224. package/src/docs/versioned/next/tasks/rate-limiting.md +9 -2
  225. package/src/docs/versioned/next/tasks/remove-legacy-realtime.md +5 -5
  226. package/src/docs/versioned/next/tasks/remove-rtk.md +155 -0
  227. package/dist/docs/guidelines/rtk/guidelines/core.md +0 -26
  228. package/dist/docs/resources/rtk.md +0 -181
  229. package/dist/docs/templates/bootstrap/frontend/openapi-config.template.md +0 -16
  230. package/dist/docs/templates/bootstrap/frontend/scripts/generate-sdk.template.md +0 -49
  231. package/dist/docs/templates/bootstrap/frontend/store/appState.template.md +0 -45
  232. package/dist/docs/templates/bootstrap/frontend/store/errors.template.md +0 -51
  233. package/dist/docs/templates/bootstrap/frontend/store/index.template.md +0 -86
  234. package/dist/docs/templates/bootstrap/frontend/store/openApiSdk.template.md +0 -49
  235. package/dist/docs/templates/bootstrap/frontend/store/sdk.template.md +0 -80
  236. package/src/docs/guidelines/rtk/guidelines/core.md +0 -26
  237. package/src/docs/resources/rtk.md +0 -181
  238. package/src/docs/templates/bootstrap/frontend/openapi-config.template.md +0 -16
  239. package/src/docs/templates/bootstrap/frontend/scripts/generate-sdk.template.md +0 -49
  240. package/src/docs/templates/bootstrap/frontend/store/appState.template.md +0 -45
  241. package/src/docs/templates/bootstrap/frontend/store/errors.template.md +0 -51
  242. package/src/docs/templates/bootstrap/frontend/store/index.template.md +0 -86
  243. package/src/docs/templates/bootstrap/frontend/store/openApiSdk.template.md +0 -49
  244. package/src/docs/templates/bootstrap/frontend/store/sdk.template.md +0 -80
@@ -1,181 +0,0 @@
1
- # @terreno/rtk Documentation (legacy)
2
-
3
- > **Deprecated for data synchronization** as of `56.0.0`. Use `@terreno/syncdb` for collection CRUD. This resource documents RTK for OpenAPI SDK codegen, Better Auth session Redux, feature flags, and sockets during the support window. See [migrate-rtk-to-syncdb.md](https://github.com/TerrenoLabs/terreno/blob/master/docs/how-to/migrate-rtk-to-syncdb.md).
4
-
5
- Redux Toolkit Query utilities for frontends connecting to @terreno/api backends.
6
-
7
- ## Key Exports
8
-
9
- - `emptyApi` - Base RTK Query API configured with axios
10
- - `authSlice` - Redux slice for auth state
11
- - `generateProfileEndpoints` - Auth endpoint builder
12
- - Token utilities: `getTokenExpirationTimes()`, `getFriendlyExpirationInfo()`, `getAuthToken()`
13
-
14
- ## Setup
15
-
16
- ### Store Configuration
17
-
18
- ```typescript
19
- import { configureStore } from "@reduxjs/toolkit";
20
- import { emptyApi, authSlice } from "@terreno/rtk";
21
- import { openApiSdk } from "./openApiSdk";
22
-
23
- export const store = configureStore({
24
- reducer: {
25
- [openApiSdk.reducerPath]: openApiSdk.reducer,
26
- auth: authSlice.reducer,
27
- },
28
- middleware: (getDefaultMiddleware) =>
29
- getDefaultMiddleware().concat(openApiSdk.middleware),
30
- });
31
- ```
32
-
33
- ### SDK Generation
34
-
35
- The SDK is auto-generated from your backend's OpenAPI spec:
36
-
37
- ```typescript
38
- // openApiSdk.ts - AUTO-GENERATED, DO NOT EDIT
39
- import { emptyApi } from "@terreno/rtk";
40
-
41
- export const openApiSdk = emptyApi.injectEndpoints({
42
- endpoints: (build) => ({
43
- getUsers: build.query<User[], GetUsersParams>({
44
- query: (params) => ({ url: "/users", params }),
45
- }),
46
- createUser: build.mutation<User, CreateUserBody>({
47
- query: (body) => ({ url: "/users", method: "POST", body }),
48
- }),
49
- }),
50
- });
51
-
52
- export const { useGetUsersQuery, useCreateUserMutation } = openApiSdk;
53
- ```
54
-
55
- ## Using the SDK
56
-
57
- ```typescript
58
- import { useGetUsersQuery, useCreateUserMutation } from "@/store/openApiSdk";
59
-
60
- const UserList = () => {
61
- const { data: users, isLoading, error } = useGetUsersQuery({ limit: 10 });
62
- const [createUser, { isLoading: isCreating }] = useCreateUserMutation();
63
-
64
- const handleCreate = async () => {
65
- try {
66
- const newUser = await createUser({ name: "John", email: "john@example.com" }).unwrap();
67
- console.info("Created user:", newUser);
68
- } catch (err) {
69
- console.error("Failed to create user:", err);
70
- }
71
- };
72
-
73
- if (isLoading) return <Text>Loading...</Text>;
74
- if (error) return <Text>Error loading users</Text>;
75
-
76
- return (
77
- <Box>
78
- {users?.map((user) => (
79
- <Text key={user.id}>{user.name}</Text>
80
- ))}
81
- <Button text="Add User" onClick={handleCreate} loading={isCreating} />
82
- </Box>
83
- );
84
- };
85
- ```
86
-
87
- ## Authentication
88
-
89
- ### Login
90
-
91
- ```typescript
92
- import { useEmailLoginMutation } from "@/store/openApiSdk";
93
- import { useAppDispatch } from "@/store/index";
94
- import { authSlice } from "@terreno/rtk";
95
-
96
- const LoginScreen = () => {
97
- const [email, setEmail] = useState("");
98
- const [password, setPassword] = useState("");
99
- const [emailLogin, { isLoading, error }] = useEmailLoginMutation();
100
- const dispatch = useAppDispatch();
101
-
102
- const handleLogin = async () => {
103
- try {
104
- const result = await emailLogin({ email, password }).unwrap();
105
- // Auth state is automatically updated
106
- } catch (err) {
107
- console.error("Login failed:", err);
108
- }
109
- };
110
-
111
- return (
112
- <Box padding={4} gap={3}>
113
- <EmailField label="Email" value={email} onChangeText={setEmail} />
114
- <PasswordField label="Password" value={password} onChangeText={setPassword} />
115
- <Button text="Login" onClick={handleLogin} loading={isLoading} />
116
- </Box>
117
- );
118
- };
119
- ```
120
-
121
- ### Auth State
122
-
123
- ```typescript
124
- import { useAppSelector } from "@/store/appState";
125
-
126
- const Component = () => {
127
- const userId = useAppSelector((state) => state.auth.userId);
128
- const isAuthenticated = !!userId;
129
-
130
- // ...
131
- };
132
- ```
133
-
134
- ### Logout
135
-
136
- ```typescript
137
- import { LOGOUT_ACTION_TYPE } from "@terreno/rtk";
138
-
139
- const handleLogout = () => {
140
- dispatch({ type: LOGOUT_ACTION_TYPE });
141
- };
142
- ```
143
-
144
- ## Token Management
145
-
146
- Tokens are automatically managed:
147
- - Stored in `expo-secure-store` (mobile) or AsyncStorage (web)
148
- - Auto-refresh with exponential backoff
149
- - Mutex-protected to prevent race conditions
150
-
151
- ```typescript
152
- import { getAuthToken, getTokenExpirationTimes } from "@terreno/rtk";
153
-
154
- // Get current token
155
- const token = await getAuthToken();
156
-
157
- // Check expiration
158
- const { accessTokenExpiry, refreshTokenExpiry } = getTokenExpirationTimes(token);
159
- ```
160
-
161
- ## Platform Detection
162
-
163
- ```typescript
164
- import { IsWeb, IsNative } from "@terreno/rtk";
165
-
166
- if (IsWeb) {
167
- // Web-specific code
168
- }
169
-
170
- if (IsNative) {
171
- // Mobile-specific code
172
- }
173
- ```
174
-
175
- ## Best Practices
176
-
177
- 1. **Never use axios directly** - Always use generated SDK hooks
178
- 2. **Don't modify generated SDK** - It's auto-generated from OpenAPI spec
179
- 3. **Use .unwrap()** for mutations to get the result or throw error
180
- 4. **Handle loading and error states** in your UI
181
- 5. **Use TypeScript** - The SDK provides full type safety
@@ -1,16 +0,0 @@
1
- import type {ConfigFile} from "@rtk-query/codegen-openapi";
2
-
3
- const config: ConfigFile = {
4
- apiFile: "@terreno/rtk",
5
- apiImport: "emptySplitApi",
6
- argSuffix: "Args",
7
- exportName: "openapi",
8
- flattenArg: true,
9
- hooks: true,
10
- outputFile: "./store/openApiSdk.ts",
11
- responseSuffix: "Res",
12
- schemaFile: process.env.OPENAPI_URL ?? "http://localhost:4000/openapi.json",
13
- tag: true,
14
- };
15
-
16
- export default config;
@@ -1,49 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- import {exec} from "node:child_process";
4
- import {existsSync, readFileSync, writeFileSync} from "node:fs";
5
- import {join} from "node:path";
6
-
7
- const cliPath = join(
8
- __dirname,
9
- "..",
10
- "node_modules",
11
- "@rtk-query",
12
- "codegen-openapi",
13
- "lib",
14
- "bin",
15
- "cli.mjs"
16
- );
17
- const configPath = join(__dirname, "..", "openapi-config.ts");
18
- const tsConfigPath = join(__dirname, "..", "tsconfig.codegen.json");
19
-
20
- const command = `TS_NODE_PROJECT=${tsConfigPath} tsx ${cliPath} ${configPath}`;
21
-
22
- exec(command, (error, _stdout, stderr) => {
23
- if (error) {
24
- console.error(`Error: ${error.message}`);
25
- process.exit(1);
26
- }
27
- if (stderr) {
28
- console.error(`stderr: ${stderr}`);
29
- }
30
-
31
- const sdkPath = join(__dirname, "..", "store", "openApiSdk.ts");
32
-
33
- if (existsSync(sdkPath)) {
34
- let content = readFileSync(sdkPath, "utf8");
35
- content = content.replace(/^export const \{\} = injectedRtkApi;\n?/m, "");
36
- writeFileSync(sdkPath, content, "utf8");
37
- }
38
-
39
- exec(
40
- "bunx biome check --unsafe --write store/openApiSdk.ts",
41
- {cwd: join(__dirname, "..")},
42
- (formatError) => {
43
- if (formatError) {
44
- console.error(`Formatting error: ${formatError.message}`);
45
- process.exit(1);
46
- }
47
- }
48
- );
49
- });
@@ -1,45 +0,0 @@
1
- import {createSlice, type PayloadAction} from "@reduxjs/toolkit";
2
- import type {RootState} from "@terreno/rtk";
3
- import {type TypedUseSelectorHook, useSelector} from "react-redux";
4
-
5
- export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
6
-
7
- export type AppState = {
8
- darkMode: boolean;
9
- language: string;
10
- };
11
-
12
- const initialState: AppState = {
13
- darkMode: false,
14
- language: "en",
15
- };
16
-
17
- export const appStateSlice = createSlice({
18
- initialState,
19
- name: "appState",
20
- reducers: {
21
- resetAppState: () => initialState,
22
- setDarkMode: (state, action: PayloadAction<boolean>) => {
23
- state.darkMode = action.payload;
24
- },
25
- setLanguage: (state, action: PayloadAction<string>) => {
26
- state.language = action.payload;
27
- },
28
- },
29
- });
30
-
31
- export const {setDarkMode, setLanguage, resetAppState} = appStateSlice.actions;
32
-
33
- export const useSelectDarkMode = (): boolean => {
34
- return useAppSelector((state: RootState): boolean => {
35
- return state.appState.darkMode;
36
- });
37
- };
38
-
39
- export const useSelectLanguage = (): string => {
40
- return useAppSelector((state: RootState): string => {
41
- return state.appState.language;
42
- });
43
- };
44
-
45
- export default appStateSlice.reducer;
@@ -1,51 +0,0 @@
1
- import type {Middleware} from "@reduxjs/toolkit";
2
- import {useToast} from "@terreno/ui";
3
-
4
- const ignoredErrors = [
5
- "Password or username is incorrect",
6
- "Token refresh failed with 401",
7
- "Failed to refresh token",
8
- ];
9
-
10
- // biome-ignore lint/suspicious/noExplicitAny: Generic middleware
11
- export const rtkQueryErrorMiddleware: Middleware = () => (next) => (action: any) => {
12
- if (action?.error && action?.payload) {
13
- const errorMessage =
14
- action.payload?.data?.title ??
15
- action.payload?.data?.message ??
16
- action.payload?.error ??
17
- JSON.stringify(action.payload);
18
-
19
- let endpointInfo = "unknown endpoint";
20
- if (action.meta?.baseQueryMeta?.request?.method && action.meta?.baseQueryMeta?.request?.url) {
21
- endpointInfo = `${action.meta.baseQueryMeta.request.url} ${action.meta.baseQueryMeta.request.method}`;
22
- } else if (action.meta?.arg?.endpointName) {
23
- endpointInfo = `${action.meta.arg.endpointName} rejected ${action.meta.arg.type || ""}`;
24
- }
25
-
26
- const message = `${endpointInfo.trim()}: ${errorMessage}`;
27
- console.debug(message);
28
-
29
- if (action.payload.status === 404 || action.payload.status === 401) {
30
- return next(action);
31
- }
32
-
33
- const shouldIgnore = ignoredErrors.some((err) => errorMessage.includes(err));
34
- if (!shouldIgnore) {
35
- console.warn(message);
36
- }
37
- }
38
-
39
- return next(action);
40
- };
41
-
42
- export const useSentryAndToast = (): ((errorMessage: string) => void) => {
43
- const toast = useToast();
44
- return (error: string): void => {
45
- if (!error) {
46
- return;
47
- }
48
- toast.error(error);
49
- console.warn(`Error: ${error}`);
50
- };
51
- };
@@ -1,86 +0,0 @@
1
- import AsyncStorage from "@react-native-async-storage/async-storage";
2
- import {combineReducers, configureStore} from "@reduxjs/toolkit";
3
- import {generateAuthSlice} from "@terreno/rtk";
4
- import {DateTime} from "luxon";
5
- import {useDispatch} from "react-redux";
6
- import type {Storage} from "redux-persist";
7
- import {persistReducer, persistStore} from "redux-persist";
8
-
9
- import appState from "./appState";
10
- import {rtkQueryErrorMiddleware} from "./errors";
11
- import {terrenoApi} from "./sdk";
12
-
13
- const authSlice = generateAuthSlice(terrenoApi);
14
-
15
- export const {logout} = authSlice;
16
-
17
- const createSafeStorage = (): Storage => {
18
- return {
19
- getItem: async (key: string): Promise<string | null> => {
20
- if (typeof window !== "undefined") {
21
- return AsyncStorage.getItem(key);
22
- }
23
- return null;
24
- },
25
- removeItem: async (key: string): Promise<void> => {
26
- if (typeof window !== "undefined") {
27
- return AsyncStorage.removeItem(key);
28
- }
29
- },
30
- setItem: async (key: string, value: string): Promise<void> => {
31
- if (typeof window !== "undefined") {
32
- return AsyncStorage.setItem(key, value);
33
- }
34
- },
35
- };
36
- };
37
-
38
- const persistConfig = {
39
- blacklist: ["terreno-rtk"],
40
- key: "root",
41
- storage: createSafeStorage(),
42
- timeout: 0,
43
- version: 1,
44
- };
45
-
46
- const rootReducer = combineReducers({
47
- appState,
48
- auth: authSlice.authReducer,
49
- "terreno-rtk": terrenoApi.reducer,
50
- });
51
-
52
- const persistedReducer = persistReducer(persistConfig, rootReducer);
53
-
54
- const store = configureStore({
55
- devTools: process.env.NODE_ENV !== "production" && {
56
- name: `App-${
57
- typeof window !== "undefined"
58
- // biome-ignore lint/suspicious/noAssignInExpressions: Window name assignment
59
- ? window.name || ((window.name = `Window-${DateTime.now().toFormat("HH:mm:ss")}`))
60
- : "Unknown"
61
- }`,
62
- },
63
- middleware: (getDefaultMiddleware) => {
64
- return getDefaultMiddleware({
65
- immutableCheck: false,
66
- serializableCheck: false,
67
- thunk: true,
68
- }).concat([
69
- ...authSlice.middleware,
70
- // biome-ignore lint/suspicious/noExplicitAny: RTK Query middleware typing
71
- terrenoApi.middleware as any,
72
- rtkQueryErrorMiddleware,
73
- // biome-ignore lint/suspicious/noExplicitAny: Middleware array typing
74
- ]) as any;
75
- },
76
- reducer: persistedReducer,
77
- });
78
-
79
- export const persistor = persistStore(store);
80
-
81
- export type RootState = ReturnType<typeof store.getState>;
82
- export type AppDispatch = typeof store.dispatch;
83
-
84
- export const useAppDispatch: () => AppDispatch = useDispatch;
85
-
86
- export default store;
@@ -1,49 +0,0 @@
1
- // THIS FILE IS AUTO-GENERATED. DO NOT EDIT.
2
- // Run "bun run sdk" to regenerate this file from the backend OpenAPI spec.
3
-
4
- import {emptySplitApi as api} from "@terreno/rtk";
5
- export const addTagTypes = ["Users", "Auth"] as const;
6
- const injectedRtkApi = api
7
- .enhanceEndpoints({
8
- addTagTypes,
9
- })
10
- .injectEndpoints({
11
- endpoints: (build) => ({
12
- emailLogin: build.mutation<EmailLoginRes, EmailLoginArgs>({
13
- query: (queryArg) => ({
14
- body: queryArg,
15
- method: "POST",
16
- url: `/auth/login`,
17
- }),
18
- }),
19
- emailSignUp: build.mutation<EmailSignUpRes, EmailSignUpArgs>({
20
- query: (queryArg) => ({
21
- body: queryArg,
22
- method: "POST",
23
- url: `/auth/signup`,
24
- }),
25
- }),
26
- }),
27
- overrideExisting: false,
28
- });
29
- export {injectedRtkApi as openapi};
30
- export type EmailLoginArgs = {
31
- email: string;
32
- password: string;
33
- };
34
- export type EmailLoginRes = {
35
- token: string;
36
- refreshToken: string;
37
- userId: string;
38
- };
39
- export type EmailSignUpArgs = {
40
- email: string;
41
- password: string;
42
- name: string;
43
- };
44
- export type EmailSignUpRes = {
45
- token: string;
46
- refreshToken: string;
47
- userId: string;
48
- };
49
- export const {useEmailLoginMutation, useEmailSignUpMutation} = injectedRtkApi;
@@ -1,80 +0,0 @@
1
- import {generateTags} from "@terreno/rtk";
2
- import startCase from "lodash/startCase";
3
-
4
- import {addTagTypes, openapi} from "./openApiSdk";
5
-
6
- export interface ProfileResponse {
7
- data: {
8
- _id: string;
9
- id: string;
10
- email: string;
11
- name: string;
12
- };
13
- }
14
-
15
- export interface UpdateProfileRequest {
16
- name?: string;
17
- email?: string;
18
- /** Required by the server when `email` changes the mailbox. */
19
- currentPassword?: string;
20
- password?: string;
21
- }
22
-
23
- export const terrenoApi = openapi
24
- .injectEndpoints({
25
- endpoints: (builder) => ({
26
- getMe: builder.query<ProfileResponse, void>({
27
- providesTags: ["profile"],
28
- query: () => ({
29
- method: "GET",
30
- url: "/auth/me",
31
- }),
32
- }),
33
- patchMe: builder.mutation<ProfileResponse, UpdateProfileRequest>({
34
- invalidatesTags: ["profile"],
35
- query: (body) => ({
36
- body,
37
- method: "PATCH",
38
- url: "/auth/me",
39
- }),
40
- }),
41
- }),
42
- })
43
- .enhanceEndpoints({
44
- addTagTypes: ["profile"],
45
- endpoints: {
46
- ...generateTags(openapi, [...addTagTypes]),
47
- },
48
- });
49
-
50
- export const {
51
- useEmailLoginMutation,
52
- useEmailSignUpMutation,
53
- useGetMeQuery,
54
- usePatchMeMutation,
55
- } = terrenoApi;
56
- export * from "./openApiSdk";
57
-
58
- type OpenApiEndpoints = Record<string, unknown>;
59
-
60
- export const getSdkHook = (
61
- modelName: string,
62
- type: "list" | "read" | "create" | "update" | "remove"
63
- ): Record<string, unknown> => {
64
- const modelPath = startCase(modelName).replace(/\s/g, "");
65
- const endpoints = openapi.endpoints as OpenApiEndpoints;
66
- switch (type) {
67
- case "list":
68
- return endpoints[`get${modelPath}`] as Record<string, unknown>;
69
- case "read":
70
- return endpoints[`get${modelPath}ById`] as Record<string, unknown>;
71
- case "create":
72
- return endpoints[`post${modelPath}`] as Record<string, unknown>;
73
- case "update":
74
- return endpoints[`patch${modelPath}ById`] as Record<string, unknown>;
75
- case "remove":
76
- return endpoints[`delete${modelPath}ById`] as Record<string, unknown>;
77
- default:
78
- throw new Error(`Invalid SDK hook: ${modelName}/${type}`);
79
- }
80
- };
@@ -1,26 +0,0 @@
1
- ### @terreno/rtk
2
-
3
- Redux Toolkit Query integration:
4
-
5
- - **generateAuthSlice**: Creates auth reducer and middleware with JWT handling
6
- - **emptyApi**: Base RTK Query API for code generation
7
- - **Platform utilities**: Secure token storage (expo-secure-store for native, AsyncStorage for web)
8
-
9
- Key imports:
10
-
11
- ```typescript
12
- import {generateAuthSlice} from "@terreno/rtk";
13
- ```
14
-
15
- Always use generated SDK hooks — never use `axios` or `request` directly:
16
-
17
- ```typescript
18
- // Correct
19
- import {useGetYourRouteQuery} from "@/store/openApiSdk";
20
- const {data, isLoading, error} = useGetYourRouteQuery({id: "value"});
21
-
22
- // Wrong - don't use axios directly
23
- // const result = await axios.get("/api/yourRoute/value");
24
- ```
25
-
26
- **No barrel imports** in app store code — import hooks from `@/store/sdk` or `@/store/openApiSdk`, not `@/store`. See `docs/explanation/no-barrel-imports.md`.