codeforlife 2.6.4 → 2.6.6
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.
- package/CHANGELOG.md +14 -0
- package/package.json +1 -1
- package/src/api/createApi.ts +9 -2
- package/src/components/form/TextField.tsx +25 -1
- package/src/utils/api.tsx +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [2.6.6](https://github.com/ocadotechnology/codeforlife-package-javascript/compare/v2.6.5...v2.6.6) (2025-01-27)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* csrf header for non-safe http methods ([#75](https://github.com/ocadotechnology/codeforlife-package-javascript/issues/75)) ([d0b2b78](https://github.com/ocadotechnology/codeforlife-package-javascript/commit/d0b2b7852fbdc9f84ade5ec4d46cc8a980e60f1e))
|
|
7
|
+
|
|
8
|
+
## [2.6.5](https://github.com/ocadotechnology/codeforlife-package-javascript/compare/v2.6.4...v2.6.5) (2025-01-17)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* unique values ([#74](https://github.com/ocadotechnology/codeforlife-package-javascript/issues/74)) ([1d183d2](https://github.com/ocadotechnology/codeforlife-package-javascript/commit/1d183d2806a7aa8ba98e78bf8a3fa9927ff37389))
|
|
14
|
+
|
|
1
15
|
## [2.6.4](https://github.com/ocadotechnology/codeforlife-package-javascript/compare/v2.6.3...v2.6.4) (2025-01-10)
|
|
2
16
|
|
|
3
17
|
|
package/package.json
CHANGED
package/src/api/createApi.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createApi as _createApi,
|
|
3
3
|
fetchBaseQuery,
|
|
4
|
+
type FetchArgs,
|
|
4
5
|
} from "@reduxjs/toolkit/query/react"
|
|
5
6
|
|
|
6
7
|
import { SERVICE_API_URL } from "../settings"
|
|
7
8
|
import defaultTagTypes from "./tagTypes"
|
|
8
9
|
import { buildLogoutEndpoint } from "./endpoints/session"
|
|
9
10
|
import { getCsrfCookie } from "../utils/auth"
|
|
11
|
+
import { isSafeHttpMethod } from "../utils/api"
|
|
10
12
|
|
|
11
13
|
// TODO: decide if we want to keep any of this.
|
|
12
14
|
// export function handleResponseError(error: FetchBaseQueryError): void {
|
|
@@ -36,8 +38,13 @@ export default function createApi<TagTypes extends string = never>({
|
|
|
36
38
|
const fetch = fetchBaseQuery({
|
|
37
39
|
baseUrl: `${SERVICE_API_URL}/`,
|
|
38
40
|
credentials: "include",
|
|
39
|
-
prepareHeaders: (headers,
|
|
40
|
-
|
|
41
|
+
prepareHeaders: (headers, endpoint) => {
|
|
42
|
+
const { type, arg } = endpoint as typeof endpoint & {
|
|
43
|
+
arg: string | FetchArgs
|
|
44
|
+
}
|
|
45
|
+
const method = typeof arg === "string" ? "GET" : arg.method || "GET"
|
|
46
|
+
|
|
47
|
+
if (type === "mutation" || !isSafeHttpMethod(method)) {
|
|
41
48
|
let csrfToken = getCsrfCookie()
|
|
42
49
|
if (csrfToken) headers.set("x-csrftoken", csrfToken)
|
|
43
50
|
}
|
|
@@ -30,6 +30,8 @@ export type TextFieldProps = Omit<
|
|
|
30
30
|
validateOptions?: ValidateOptions
|
|
31
31
|
dirty?: boolean
|
|
32
32
|
split?: string | RegExp
|
|
33
|
+
unique?: boolean
|
|
34
|
+
uniqueCaseInsensitive?: boolean
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
// https://formik.org/docs/examples/with-material-ui
|
|
@@ -40,6 +42,8 @@ const TextField: FC<TextFieldProps> = ({
|
|
|
40
42
|
type = "text",
|
|
41
43
|
required = false,
|
|
42
44
|
dirty = false,
|
|
45
|
+
unique = false,
|
|
46
|
+
uniqueCaseInsensitive = false,
|
|
43
47
|
split,
|
|
44
48
|
validateOptions,
|
|
45
49
|
...otherTextFieldProps
|
|
@@ -49,7 +53,27 @@ const TextField: FC<TextFieldProps> = ({
|
|
|
49
53
|
const dotPath = name.split(".")
|
|
50
54
|
|
|
51
55
|
let _schema: Schema = schema
|
|
52
|
-
if (split)
|
|
56
|
+
if (split) {
|
|
57
|
+
_schema = YupArray().of(_schema)
|
|
58
|
+
if (unique || uniqueCaseInsensitive) {
|
|
59
|
+
_schema = _schema.test({
|
|
60
|
+
message: "cannot have duplicates",
|
|
61
|
+
test: values => {
|
|
62
|
+
if (Array.isArray(values) && values.length >= 2) {
|
|
63
|
+
return (
|
|
64
|
+
new Set(
|
|
65
|
+
uniqueCaseInsensitive && typeof values[0] === "string"
|
|
66
|
+
? values.map(value => value.toLowerCase())
|
|
67
|
+
: values,
|
|
68
|
+
).size === values.length
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return true
|
|
73
|
+
},
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
}
|
|
53
77
|
if (required) {
|
|
54
78
|
_schema = _schema.required()
|
|
55
79
|
if (split) _schema = (_schema as ArraySchema<string[], any>).min(1)
|
package/src/utils/api.tsx
CHANGED
|
@@ -325,3 +325,8 @@ export function handleResultState<QueryArg, ResultType>(
|
|
|
325
325
|
// Have yet to call the API.
|
|
326
326
|
return loadingNode
|
|
327
327
|
}
|
|
328
|
+
|
|
329
|
+
export function isSafeHttpMethod(method: string) {
|
|
330
|
+
// https://datatracker.ietf.org/doc/html/rfc9110.html#section-9.2.1
|
|
331
|
+
return ["GET", "HEAD", "OPTIONS", "TRACE"].includes(method.toUpperCase())
|
|
332
|
+
}
|