From 55deb3f01b7090216bd2db150ec9d689553ec696 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 25 Nov 2020 08:09:51 -0500 Subject: [PATCH 01/12] types hooks --- .../components/forms/RenderFields/index.tsx | 2 +- src/admin/hooks/useDebounce.tsx | 2 +- src/admin/hooks/useIntersect.tsx | 15 +++++++++-- src/admin/hooks/useMountEffect.tsx | 2 +- src/admin/hooks/usePayloadAPI.tsx | 27 +++++++++++++++---- src/admin/hooks/useThrottledEffect.tsx | 4 ++- src/admin/hooks/useTitle.tsx | 2 +- src/admin/hooks/useUnmountEffect.tsx | 2 +- 8 files changed, 43 insertions(+), 13 deletions(-) diff --git a/src/admin/components/forms/RenderFields/index.tsx b/src/admin/components/forms/RenderFields/index.tsx index ca0c2ba01f..b817b4e04e 100644 --- a/src/admin/components/forms/RenderFields/index.tsx +++ b/src/admin/components/forms/RenderFields/index.tsx @@ -13,7 +13,7 @@ const RenderedFieldContext = createContext({}); export const useRenderedFields = () => useContext(RenderedFieldContext); -const RenderFields = (props) => { +const RenderFields: React.FC = (props) => { const { fieldSchema, fieldTypes, diff --git a/src/admin/hooks/useDebounce.tsx b/src/admin/hooks/useDebounce.tsx index 51a1d0306d..d4ffae61f0 100644 --- a/src/admin/hooks/useDebounce.tsx +++ b/src/admin/hooks/useDebounce.tsx @@ -1,7 +1,7 @@ import { useState, useEffect } from 'react'; // Our hook -export default function useDebounce(value, delay) { +export default function useDebounce(value: unknown, delay: number): unknown { // State and setters for debounced value const [debouncedValue, setDebouncedValue] = useState(value); diff --git a/src/admin/hooks/useIntersect.tsx b/src/admin/hooks/useIntersect.tsx index b3ae43460c..c38cbe210d 100644 --- a/src/admin/hooks/useIntersect.tsx +++ b/src/admin/hooks/useIntersect.tsx @@ -1,8 +1,17 @@ /* eslint-disable no-shadow */ import { useEffect, useRef, useState } from 'react'; -export default ({ root = null, rootMargin, threshold = 0 } = {}) => { - const [entry, updateEntry] = useState({}); +type Intersect = [ + setNode: React.Dispatch, + entry: IntersectionObserverEntry +] + +const useIntersect = ({ + root = null, + rootMargin = '0px', + threshold = 0, +} = {}): Intersect => { + const [entry, updateEntry] = useState(); const [node, setNode] = useState(null); const observer = useRef( @@ -27,3 +36,5 @@ export default ({ root = null, rootMargin, threshold = 0 } = {}) => { return [setNode, entry]; }; + +export default useIntersect; diff --git a/src/admin/hooks/useMountEffect.tsx b/src/admin/hooks/useMountEffect.tsx index 655f74b59f..f6ac8434ae 100644 --- a/src/admin/hooks/useMountEffect.tsx +++ b/src/admin/hooks/useMountEffect.tsx @@ -1,5 +1,5 @@ import { useEffect } from 'react'; -const useMountEffect = func => useEffect(func, []); +const useMountEffect = (func: () => void): void => useEffect(func, []); export default useMountEffect; diff --git a/src/admin/hooks/usePayloadAPI.tsx b/src/admin/hooks/usePayloadAPI.tsx index 60f6204bdb..6343028681 100644 --- a/src/admin/hooks/usePayloadAPI.tsx +++ b/src/admin/hooks/usePayloadAPI.tsx @@ -3,11 +3,28 @@ import queryString from 'qs'; import { useLocale } from '../components/utilities/Locale'; import { requests } from '../api'; -const usePayloadAPI = (url, options = {}) => { +type Result = [ + { + isLoading: boolean + isError: boolean + data: unknown + }, + { + setParams: React.Dispatch + } +] + +type Options = { + initialParams?: unknown + initialData?: unknown +} + +type UsePayloadAPI = (url: string, options?: Options) => Result; + +const usePayloadAPI: UsePayloadAPI = (url, options = {}) => { const { initialParams = {}, initialData = {}, - onLoad, } = options; const [data, setData] = useState(initialData); @@ -18,8 +35,8 @@ const usePayloadAPI = (url, options = {}) => { const search = queryString.stringify({ locale, - ...params, - }, { depth: 10 }); + ...(typeof params === 'object' ? params : {}), + }); useEffect(() => { const fetchData = async () => { @@ -48,7 +65,7 @@ const usePayloadAPI = (url, options = {}) => { setIsError(false); setIsLoading(false); } - }, [url, locale, search, onLoad]); + }, [url, locale, search]); return [{ data, isLoading, isError }, { setParams }]; }; diff --git a/src/admin/hooks/useThrottledEffect.tsx b/src/admin/hooks/useThrottledEffect.tsx index 440988eac4..79d1125b7e 100644 --- a/src/admin/hooks/useThrottledEffect.tsx +++ b/src/admin/hooks/useThrottledEffect.tsx @@ -1,7 +1,9 @@ /* eslint-disable react-hooks/exhaustive-deps */ import { useEffect, useRef } from 'react'; -const useThrottledEffect = (callback, delay, deps = []) => { +type useThrottledEffect = (callback: React.EffectCallback, delay: number, deps: React.DependencyList) => void; + +const useThrottledEffect: useThrottledEffect = (callback, delay, deps = []) => { const lastRan = useRef(Date.now()); useEffect( diff --git a/src/admin/hooks/useTitle.tsx b/src/admin/hooks/useTitle.tsx index 6d29cc327e..4863e9460c 100644 --- a/src/admin/hooks/useTitle.tsx +++ b/src/admin/hooks/useTitle.tsx @@ -1,6 +1,6 @@ import { useFormFields } from '../components/forms/Form/context'; -const useTitle = (useAsTitle) => { +const useTitle = (useAsTitle: string): string => { const { getField } = useFormFields(); const titleField = getField(useAsTitle); return titleField?.value; diff --git a/src/admin/hooks/useUnmountEffect.tsx b/src/admin/hooks/useUnmountEffect.tsx index 5ae99d6902..597bbd49f4 100644 --- a/src/admin/hooks/useUnmountEffect.tsx +++ b/src/admin/hooks/useUnmountEffect.tsx @@ -1,6 +1,6 @@ import { useEffect } from 'react'; // eslint-disable-next-line react-hooks/exhaustive-deps -const useUnmountEffect = (callback) => useEffect(() => callback, []); +const useUnmountEffect = (callback: React.EffectCallback): void => useEffect(() => callback, []); export default useUnmountEffect; From ed8d7f2106cd673c061b1992304d70a3403b6dd5 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 25 Nov 2020 10:50:35 -0500 Subject: [PATCH 02/12] adds paths to local ts declarations --- package.json | 2 +- .../components/utilities/Locale/index.tsx | 10 ++++----- src/admin/components/utilities/Meta/index.tsx | 6 ++--- .../components/utilities/Portal/index.tsx | 3 ++- .../utilities/RenderCustomComponent/index.tsx | 22 ++----------------- .../utilities/RenderCustomComponent/types.ts | 7 ++++++ .../utilities/SearchParams/index.tsx | 4 ++-- src/types/assets/index.d.ts | 22 ------------------- tsconfig.json | 15 ++++++++----- yarn.lock | 8 +++---- 10 files changed, 36 insertions(+), 63 deletions(-) create mode 100644 src/admin/components/utilities/RenderCustomComponent/types.ts delete mode 100644 src/types/assets/index.d.ts diff --git a/package.json b/package.json index 32a342a4de..d5b35fdc21 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@faceless-ui/modal": "^1.0.4", "@faceless-ui/scroll-info": "^1.1.1", "@faceless-ui/window-info": "^1.2.2", - "@payloadcms/config-provider": "0.0.7", + "@payloadcms/config-provider": "0.0.9", "@typescript-eslint/parser": "4.0.1", "@udecode/slate-plugins": "^0.64.3", "ajv": "^6.12.6", diff --git a/src/admin/components/utilities/Locale/index.tsx b/src/admin/components/utilities/Locale/index.tsx index 9b61e96eef..c75a1b6c16 100644 --- a/src/admin/components/utilities/Locale/index.tsx +++ b/src/admin/components/utilities/Locale/index.tsx @@ -5,17 +5,17 @@ import PropTypes from 'prop-types'; import { useConfig } from '@payloadcms/config-provider'; import { useSearchParams } from '../SearchParams'; -const Context = createContext({}); +const Context = createContext(''); -export const LocaleProvider = ({ children }) => { +export const LocaleProvider: React.FC = ({ children }) => { const { localization } = useConfig(); const defaultLocale = (localization && localization.defaultLocale) ? localization.defaultLocale : 'en'; - const [locale, setLocale] = useState(defaultLocale); + const [locale, setLocale] = useState(defaultLocale); const searchParams = useSearchParams(); const localeFromParams = searchParams.locale; useEffect(() => { - if (localeFromParams && localization.locales.indexOf(localeFromParams) > -1) setLocale(localeFromParams); + if (localeFromParams && localization.locales.indexOf(localeFromParams) > -1) setLocale(localeFromParams as string); }, [localeFromParams, localization]); return ( @@ -25,7 +25,7 @@ export const LocaleProvider = ({ children }) => { ); }; -export const useLocale = () => useContext(Context); +export const useLocale = (): string => useContext(Context); LocaleProvider.propTypes = { children: PropTypes.oneOfType([ diff --git a/src/admin/components/utilities/Meta/index.tsx b/src/admin/components/utilities/Meta/index.tsx index b7c96c0472..94910d0a0d 100644 --- a/src/admin/components/utilities/Meta/index.tsx +++ b/src/admin/components/utilities/Meta/index.tsx @@ -13,9 +13,9 @@ const Meta: React.FC = ({ keywords = 'CMS, Admin, Dashboard', }) => { const config = useConfig(); - const titleSuffix = config?.admin?.meta?.titleSuffix ?? '- Payload'; - const favicon = config?.admin?.meta?.favicon ?? payloadFavicon; - const ogImage = config?.admin?.meta?.ogImage ?? payloadOgImage; + const titleSuffix = config.admin.meta?.titleSuffix ?? '- Payload'; + const favicon = config.admin.meta.favicon ?? payloadFavicon; + const ogImage = config.admin.meta.ogImage ?? payloadOgImage; return ( ReactDOM.createPortal(children, document.getElementById('portal')); +const Portal = ({ children }: { children: React.ReactNode}): React.ReactPortal => ReactDOM.createPortal(children, document.getElementById('portal')); export default Portal; diff --git a/src/admin/components/utilities/RenderCustomComponent/index.tsx b/src/admin/components/utilities/RenderCustomComponent/index.tsx index 6f0cd7cac5..efa60f698c 100644 --- a/src/admin/components/utilities/RenderCustomComponent/index.tsx +++ b/src/admin/components/utilities/RenderCustomComponent/index.tsx @@ -1,7 +1,7 @@ import React from 'react'; -import PropTypes from 'prop-types'; +import { Props } from './types'; -const RenderCustomComponent = (props) => { +const RenderCustomComponent: React.FC = (props) => { const { CustomComponent, DefaultComponent, componentProps } = props; if (CustomComponent) { @@ -15,22 +15,4 @@ const RenderCustomComponent = (props) => { ); }; -RenderCustomComponent.defaultProps = { - path: undefined, - componentProps: {}, - CustomComponent: null, -}; - -RenderCustomComponent.propTypes = { - path: PropTypes.string, - DefaultComponent: PropTypes.oneOfType([ - PropTypes.shape({}), - PropTypes.func, - PropTypes.node, - PropTypes.element, - ]).isRequired, - CustomComponent: PropTypes.func, - componentProps: PropTypes.shape({}), -}; - export default RenderCustomComponent; diff --git a/src/admin/components/utilities/RenderCustomComponent/types.ts b/src/admin/components/utilities/RenderCustomComponent/types.ts new file mode 100644 index 0000000000..364151bc64 --- /dev/null +++ b/src/admin/components/utilities/RenderCustomComponent/types.ts @@ -0,0 +1,7 @@ +import React from 'react'; + +export type Props = { + CustomComponent: React.FC + DefaultComponent: React.FC + componentProps: unknown +} diff --git a/src/admin/components/utilities/SearchParams/index.tsx b/src/admin/components/utilities/SearchParams/index.tsx index 97c226cfc2..2d89485944 100644 --- a/src/admin/components/utilities/SearchParams/index.tsx +++ b/src/admin/components/utilities/SearchParams/index.tsx @@ -5,7 +5,7 @@ import qs from 'qs'; const Context = createContext({}); -export const SearchParamsProvider = ({ children }) => { +export const SearchParamsProvider: React.FC = ({ children }) => { const location = useLocation(); const params = qs.parse( @@ -27,4 +27,4 @@ SearchParamsProvider.propTypes = { ]).isRequired, }; -export const useSearchParams = () => useContext(Context); +export const useSearchParams = (): qs.ParsedQs => useContext(Context); diff --git a/src/types/assets/index.d.ts b/src/types/assets/index.d.ts deleted file mode 100644 index 67591d0000..0000000000 --- a/src/types/assets/index.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -declare module '*.svg' { - import React = require('react'); - - export const ReactComponent: React.SFC>; - const src: string; - export default src; -} - -declare module '*.jpg' { - const content: string; - export default content; -} - -declare module '*.png' { - const content: string; - export default content; -} - -declare module '*.json' { - const content: string; - export default content; -} diff --git a/tsconfig.json b/tsconfig.json index 89b1ac9c11..d932b841fa 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,16 +18,21 @@ "payload/config": [ "src/admin/types/config" // Webpack alias to user config ], + "@payloadcms/payload/config": [ + "src/config/types.ts" + ], + "@payloadcms/payload/auth": [ + "src/auth/types.ts" + ], + "@payloadcms/payload/types": [ + "src/types/index.ts" + ] }, "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ "resolveJsonModule": true, "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ "skipLibCheck": true, /* Skip type checking of declaration files. */ "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */ - // "typeRoots": [ - // "./src", - // "./node_modules/@types" - // ] }, "include": [ "src/" @@ -38,6 +43,6 @@ "build", "src/tests", "src/tests/**/*.spec.ts", - // "node_modules/" + "node_modules" ] } diff --git a/yarn.lock b/yarn.lock index 5105104f78..52b8e51a95 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1360,10 +1360,10 @@ dependencies: mkdirp "^1.0.4" -"@payloadcms/config-provider@0.0.7": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@payloadcms/config-provider/-/config-provider-0.0.7.tgz#c225f29cf1737e039c95bd54ba25be5e32550ae1" - integrity sha512-qiiz5i/BRPkU6wyBg01Cf5pikfYxudanIjONdpTx7Z4xaUN67OZ0SDCfRno5LGrUupsFgxlEfSIXFGWb9h4gdw== +"@payloadcms/config-provider@0.0.9": + version "0.0.9" + resolved "https://registry.yarnpkg.com/@payloadcms/config-provider/-/config-provider-0.0.9.tgz#b2f89bb64418b96c04ff8e08a7d39f82eb6fa281" + integrity sha512-M8Lgp7tw0uIIKSJ5MjLsP3yS5406cmUEWtdnH/zshq3uRNGYmvlg/hOmFl0pJpZdut9An+qCFVhvjSTaQAok/Q== "@popperjs/core@^2.4.4": version "2.5.4" From 472a6cb232a7f4fbba51d145393b09f72d33e416 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 25 Nov 2020 11:23:03 -0500 Subject: [PATCH 03/12] 13639$ types 13639$ --- .../modals/LeaveWithoutSaving/index.tsx | 6 ++--- .../components/modals/StayLoggedIn/index.tsx | 3 ++- .../components/modals/StayLoggedIn/types.ts | 4 ++++ .../components/templates/Default/index.tsx | 18 +++------------ .../components/templates/Default/types.ts | 3 +++ .../components/templates/Minimal/index.tsx | 22 +++++-------------- .../components/templates/Minimal/types.ts | 7 ++++++ .../components/utilities/Locale/index.tsx | 2 +- .../utilities/RenderCustomComponent/types.ts | 6 ++--- src/config/types.ts | 6 ++++- 10 files changed, 37 insertions(+), 40 deletions(-) create mode 100644 src/admin/components/modals/StayLoggedIn/types.ts create mode 100644 src/admin/components/templates/Default/types.ts create mode 100644 src/admin/components/templates/Minimal/types.ts diff --git a/src/admin/components/modals/LeaveWithoutSaving/index.tsx b/src/admin/components/modals/LeaveWithoutSaving/index.tsx index a13368477b..ca1234c7c3 100644 --- a/src/admin/components/modals/LeaveWithoutSaving/index.tsx +++ b/src/admin/components/modals/LeaveWithoutSaving/index.tsx @@ -1,20 +1,20 @@ import React from 'react'; import NavigationPrompt from 'react-router-navigation-prompt'; +import { useAuth } from '@payloadcms/config-provider'; import { useFormModified } from '../../forms/Form/context'; import MinimalTemplate from '../../templates/Minimal'; import Button from '../../elements/Button'; -import { useAuth } from '@payloadcms/config-provider'; import './index.scss'; const modalSlug = 'leave-without-saving'; -const LeaveWithoutSaving = () => { +const LeaveWithoutSaving: React.FC = () => { const modified = useFormModified(); const { user } = useAuth(); return ( - + {({ onConfirm, onCancel }) => (
diff --git a/src/admin/components/modals/StayLoggedIn/index.tsx b/src/admin/components/modals/StayLoggedIn/index.tsx index 137e12c323..9f3f4d501e 100644 --- a/src/admin/components/modals/StayLoggedIn/index.tsx +++ b/src/admin/components/modals/StayLoggedIn/index.tsx @@ -5,12 +5,13 @@ import { useModal, Modal } from '@faceless-ui/modal'; import { useConfig } from '@payloadcms/config-provider'; import MinimalTemplate from '../../templates/Minimal'; import Button from '../../elements/Button'; +import { Props } from './types'; import './index.scss'; const baseClass = 'stay-logged-in'; -const StayLoggedInModal = (props) => { +const StayLoggedInModal: React.FC = (props) => { const { refreshCookie } = props; const history = useHistory(); const { routes: { admin } } = useConfig(); diff --git a/src/admin/components/modals/StayLoggedIn/types.ts b/src/admin/components/modals/StayLoggedIn/types.ts new file mode 100644 index 0000000000..578f5616f6 --- /dev/null +++ b/src/admin/components/modals/StayLoggedIn/types.ts @@ -0,0 +1,4 @@ + +export type Props = { + refreshCookie: () => void +} diff --git a/src/admin/components/templates/Default/index.tsx b/src/admin/components/templates/Default/index.tsx index 781376ba21..3301de2777 100644 --- a/src/admin/components/templates/Default/index.tsx +++ b/src/admin/components/templates/Default/index.tsx @@ -1,16 +1,16 @@ import React from 'react'; -import PropTypes from 'prop-types'; -import DefaultNav from '../../elements/Nav'; import { useConfig } from '@payloadcms/config-provider'; +import DefaultNav from '../../elements/Nav'; import { StepNavProvider } from '../../elements/StepNav'; import RenderCustomComponent from '../../utilities/RenderCustomComponent'; import Meta from '../../utilities/Meta'; +import { Props } from './types'; import './index.scss'; const baseClass = 'template-default'; -const Default = ({ children, className }) => { +const Default: React.FC = ({ children, className }) => { const { admin: { components: { @@ -44,16 +44,4 @@ const Default = ({ children, className }) => { ); }; -Default.defaultProps = { - className: '', -}; - -Default.propTypes = { - children: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.node), - PropTypes.node, - ]).isRequired, - className: PropTypes.string, -}; - export default Default; diff --git a/src/admin/components/templates/Default/types.ts b/src/admin/components/templates/Default/types.ts new file mode 100644 index 0000000000..8f2da3ac4b --- /dev/null +++ b/src/admin/components/templates/Default/types.ts @@ -0,0 +1,3 @@ +export type Props = { + className?: string, +}; diff --git a/src/admin/components/templates/Minimal/index.tsx b/src/admin/components/templates/Minimal/index.tsx index 273c138436..8b6039d14b 100644 --- a/src/admin/components/templates/Minimal/index.tsx +++ b/src/admin/components/templates/Minimal/index.tsx @@ -1,13 +1,16 @@ import React from 'react'; -import PropTypes from 'prop-types'; +import { Props } from './types'; import './index.scss'; const baseClass = 'template-minimal'; -const Minimal = (props) => { +const Minimal: React.FC = (props) => { const { - className, style, children, width, + className, + style = {}, + children, + width = 'normal', } = props; const classes = [ @@ -28,17 +31,4 @@ const Minimal = (props) => { ); }; -Minimal.defaultProps = { - className: null, - style: {}, - width: 'normal', -}; - -Minimal.propTypes = { - className: PropTypes.string, - style: PropTypes.shape({}), - children: PropTypes.node.isRequired, - width: PropTypes.oneOf(['normal', 'wide']), -}; - export default Minimal; diff --git a/src/admin/components/templates/Minimal/types.ts b/src/admin/components/templates/Minimal/types.ts new file mode 100644 index 0000000000..43b37a1af5 --- /dev/null +++ b/src/admin/components/templates/Minimal/types.ts @@ -0,0 +1,7 @@ +import React from 'react'; + +export type Props = { + className?: string, + width?: 'normal' | 'wide' + style?: React.CSSProperties +}; diff --git a/src/admin/components/utilities/Locale/index.tsx b/src/admin/components/utilities/Locale/index.tsx index c75a1b6c16..f73d86232b 100644 --- a/src/admin/components/utilities/Locale/index.tsx +++ b/src/admin/components/utilities/Locale/index.tsx @@ -15,7 +15,7 @@ export const LocaleProvider: React.FC = ({ children }) => { const localeFromParams = searchParams.locale; useEffect(() => { - if (localeFromParams && localization.locales.indexOf(localeFromParams) > -1) setLocale(localeFromParams as string); + if (localeFromParams && localization.locales.indexOf(localeFromParams as string) > -1) setLocale(localeFromParams as string); }, [localeFromParams, localization]); return ( diff --git a/src/admin/components/utilities/RenderCustomComponent/types.ts b/src/admin/components/utilities/RenderCustomComponent/types.ts index 364151bc64..4908a5d63d 100644 --- a/src/admin/components/utilities/RenderCustomComponent/types.ts +++ b/src/admin/components/utilities/RenderCustomComponent/types.ts @@ -1,7 +1,7 @@ import React from 'react'; export type Props = { - CustomComponent: React.FC - DefaultComponent: React.FC - componentProps: unknown + CustomComponent: React.ComponentType + DefaultComponent: React.ComponentType + componentProps?: unknown } diff --git a/src/config/types.ts b/src/config/types.ts index 54c0b5e333..4266431d81 100644 --- a/src/config/types.ts +++ b/src/config/types.ts @@ -57,6 +57,9 @@ export type PayloadConfig = { } disable?: boolean; indexHTML?: string; + components?: { + Nav: React.ComponentType + } }; collections?: Collection[]; globals?: Global[]; @@ -92,7 +95,8 @@ export type PayloadConfig = { }; }; localization?: { - locales: string[]; + locales: string[] + defaultLocale: string }; defaultLocale?: string; fallback?: boolean; From 254524ab1b1f74497056ca30e054cc03938a4140 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 25 Nov 2020 11:31:36 -0500 Subject: [PATCH 04/12] updates webpack 5 dependencies --- package.json | 2 +- src/webpack/getWebpackProdConfig.ts | 65 ++++++++++++----------------- yarn.lock | 35 ++++++++-------- 3 files changed, 44 insertions(+), 58 deletions(-) diff --git a/package.json b/package.json index d5b35fdc21..d16b4cb5bb 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "compression": "^1.7.4", "connect-history-api-fallback": "^1.6.0", "css-loader": "^5.0.1", + "css-minimizer-webpack-plugin": "^1.1.5", "date-fns": "^2.14.0", "deepmerge": "^4.2.2", "dotenv": "^6.0.0", @@ -86,7 +87,6 @@ "node-sass": "^4.14.1", "nodemailer": "^6.4.2", "object-to-formdata": "^3.0.9", - "optimize-css-assets-webpack-plugin": "^5.0.4", "passport": "^0.4.1", "passport-anonymous": "^1.0.1", "passport-headerapikey": "^1.2.1", diff --git a/src/webpack/getWebpackProdConfig.ts b/src/webpack/getWebpackProdConfig.ts index c6aee75e04..fd68519b6f 100644 --- a/src/webpack/getWebpackProdConfig.ts +++ b/src/webpack/getWebpackProdConfig.ts @@ -1,7 +1,7 @@ import HtmlWebpackPlugin from 'html-webpack-plugin'; import TerserJSPlugin from 'terser-webpack-plugin'; import MiniCSSExtractPlugin from 'mini-css-extract-plugin'; -import OptimizeCSSAssetsPlugin from 'optimize-css-assets-webpack-plugin'; +import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'; import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; import path from 'path'; import webpack, { Configuration } from 'webpack'; @@ -25,7 +25,7 @@ export default (config: Config): Configuration => { devtool: 'source-map', stats: 'errors-only', optimization: { - minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})], + minimizer: [new TerserJSPlugin({}), new CssMinimizerPlugin()], splitChunks: { cacheGroups: { styles: { @@ -48,46 +48,33 @@ export default (config: Config): Configuration => { options: babelConfig({ env: () => false }), }, }, + + { + test: /\.(sa|sc|c)ss$/, + sideEffects: true, + use: [ + MiniCSSExtractPlugin.loader, + require.resolve('css-loader'), + { + loader: require.resolve('postcss-loader'), + options: { + postcssOptions: { + plugins: [require.resolve('postcss-preset-env')], + }, + }, + }, + require.resolve('sass-loader'), + ], + }, { oneOf: [ { - test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], - loader: require.resolve('url-loader'), - options: { - limit: 10000, - name: 'static/media/[name].[hash:8].[ext]', - }, + test: /\.(?:ico|gif|png|jpg|jpeg)$/i, + type: 'asset/resource', }, { - test: /\.(sa|sc|c)ss$/, - sideEffects: true, - use: [ - MiniCSSExtractPlugin.loader, - require.resolve('css-loader'), - { - loader: require.resolve('postcss-loader'), - options: { - postcssOptions: { - plugins: [ - [ - require.resolve('postcss-preset-env'), - { - // Options - }, - ], - ], - }, - }, - }, - require.resolve('sass-loader'), - ], - }, - { - exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/], - loader: require.resolve('file-loader'), - options: { - name: 'static/media/[name].[hash:8].[ext]', - }, + test: /\.(woff(2)?|eot|ttf|otf|svg|)$/, + type: 'asset/inline', }, ], }, @@ -112,7 +99,7 @@ export default (config: Config): Configuration => { template: config.admin && config.admin.indexHTML ? path.join(config.paths.configDir, config.admin.indexHTML) : path.resolve(__dirname, '../admin/index.html'), - filename: './index.html', + filename: path.normalize('./index.html'), }), new webpack.DefinePlugin(Object.entries(config.publicENV).reduce((values, [key, val]) => ({ ...values, @@ -142,7 +129,7 @@ export default (config: Config): Configuration => { } if (config.webpack && typeof config.webpack === 'function') { - webpackConfig = config.webpack(webpackConfig, 'production'); + webpackConfig = config.webpack(webpackConfig); } return webpackConfig; diff --git a/yarn.lock b/yarn.lock index 52b8e51a95..0a60e0a891 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4083,6 +4083,21 @@ css-loader@^5.0.1: schema-utils "^3.0.0" semver "^7.3.2" +css-minimizer-webpack-plugin@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-1.1.5.tgz#f6f41358518d0f28b7a2d6819dfe1e410bc404f6" + integrity sha512-mXgaoFjNpIudZfxD49N1aPtLxfXGJt+BVPVjQ+H66I48b5n4wJtFpYfffVr7izK8W6fD01J7K0kUcP6HGjw90w== + dependencies: + cacache "^15.0.5" + cssnano "^4.1.10" + find-cache-dir "^3.3.1" + jest-worker "^26.3.0" + p-limit "^3.0.2" + schema-utils "^3.0.0" + serialize-javascript "^5.0.1" + source-map "^0.6.1" + webpack-sources "^1.4.3" + css-prefers-color-scheme@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4" @@ -7079,7 +7094,7 @@ jest-watcher@^26.6.2: jest-util "^26.6.2" string-length "^4.0.1" -jest-worker@^26.5.0, jest-worker@^26.6.1, jest-worker@^26.6.2: +jest-worker@^26.3.0, jest-worker@^26.5.0, jest-worker@^26.6.1, jest-worker@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== @@ -7328,14 +7343,6 @@ language-tags@^1.0.5: dependencies: language-subtag-registry "~0.3.2" -last-call-webpack-plugin@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555" - integrity sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w== - dependencies: - lodash "^4.17.5" - webpack-sources "^1.1.0" - latest-version@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" @@ -7515,7 +7522,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.0.0, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.10: +lodash@^4.0.0, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@~4.17.10: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -8447,14 +8454,6 @@ opener@^1.5.1: resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== -optimize-css-assets-webpack-plugin@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.4.tgz#85883c6528aaa02e30bbad9908c92926bb52dc90" - integrity sha512-wqd6FdI2a5/FdoiCNNkEvLeA//lHHfG24Ln2Xm2qqdIk4aOlsR18jwpyOihqQ8849W3qu2DX8fOYxpvTMj+93A== - dependencies: - cssnano "^4.1.10" - last-call-webpack-plugin "^3.0.0" - optionator@^0.8.1, optionator@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" From b584d22b3aa7c62f0a7ce71d5532096758771f3d Mon Sep 17 00:00:00 2001 From: James Date: Wed, 25 Nov 2020 13:43:01 -0500 Subject: [PATCH 05/12] adds bin executable --- bin.js | 1 + package.json | 4 ++-- .../forms/field-types/Relationship/index.tsx | 2 +- src/utilities/asyncSome.ts | 10 ++++++++++ src/webpack/getWebpackDevConfig.ts | 1 - src/webpack/getWebpackProdConfig.ts | 1 - yarn.lock | 20 ------------------- 7 files changed, 14 insertions(+), 25 deletions(-) create mode 100644 bin.js create mode 100644 src/utilities/asyncSome.ts diff --git a/bin.js b/bin.js new file mode 100644 index 0000000000..d986755c6a --- /dev/null +++ b/bin.js @@ -0,0 +1 @@ +require('./dist/src/bin'); diff --git a/package.json b/package.json index d16b4cb5bb..94261928f3 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "typings": "./dist/src/index.d.ts", "sideEffects": false, "bin": { - "payload": "./dist/src/bin/index.js" + "payload": "./bin.js" }, "scripts": { "copyfiles": "copyfiles src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png} dist/", @@ -44,7 +44,6 @@ "@typescript-eslint/parser": "4.0.1", "@udecode/slate-plugins": "^0.64.3", "ajv": "^6.12.6", - "async-some": "^1.0.2", "autoprefixer": "^9.7.4", "babel-jest": "^26.3.0", "babel-loader": "^8.1.0", @@ -220,6 +219,7 @@ "typescript": "^4.1.2" }, "files": [ + "bin.js", "dist", "docs", "components", diff --git a/src/admin/components/forms/field-types/Relationship/index.tsx b/src/admin/components/forms/field-types/Relationship/index.tsx index 8751f415f5..fa2b8da413 100644 --- a/src/admin/components/forms/field-types/Relationship/index.tsx +++ b/src/admin/components/forms/field-types/Relationship/index.tsx @@ -2,8 +2,8 @@ import React, { Component, useCallback, } from 'react'; import PropTypes from 'prop-types'; -import some from 'async-some'; import { useConfig } from '@payloadcms/config-provider'; +import some from '../../../../../utilities/asyncSome'; import withCondition from '../../withCondition'; import ReactSelect from '../../../elements/ReactSelect'; import useFieldType from '../../useFieldType'; diff --git a/src/utilities/asyncSome.ts b/src/utilities/asyncSome.ts new file mode 100644 index 0000000000..124ccdf70a --- /dev/null +++ b/src/utilities/asyncSome.ts @@ -0,0 +1,10 @@ +const asyncSome = async (arr: unknown[], predicate: (event: unknown) => Promise): Promise => { + // eslint-disable-next-line no-restricted-syntax + for (const e of arr) { + // eslint-disable-next-line no-await-in-loop + if (await predicate(e)) return true; + } + return false; +}; + +export default asyncSome; diff --git a/src/webpack/getWebpackDevConfig.ts b/src/webpack/getWebpackDevConfig.ts index d11fad6521..3bb75ef28b 100644 --- a/src/webpack/getWebpackDevConfig.ts +++ b/src/webpack/getWebpackDevConfig.ts @@ -74,7 +74,6 @@ export default (config: Config): Configuration => { crypto: false, https: false, http: false, - assert: false, }, modules: ['node_modules', path.resolve(__dirname, '../../node_modules')], alias: { diff --git a/src/webpack/getWebpackProdConfig.ts b/src/webpack/getWebpackProdConfig.ts index fd68519b6f..f72ccd1469 100644 --- a/src/webpack/getWebpackProdConfig.ts +++ b/src/webpack/getWebpackProdConfig.ts @@ -86,7 +86,6 @@ export default (config: Config): Configuration => { crypto: false, https: false, http: false, - assert: false, }, modules: ['node_modules', path.resolve(__dirname, '../../node_modules')], alias: { diff --git a/yarn.lock b/yarn.lock index 0a60e0a891..7ed1ced001 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2840,11 +2840,6 @@ array.prototype.flatmap@^1.2.3: es-abstract "^1.18.0-next.1" function-bind "^1.1.1" -asap@^2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= - asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -2887,13 +2882,6 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -async-some@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/async-some/-/async-some-1.0.2.tgz#4d8a81620d5958791b5b98f802d3207776e95509" - integrity sha1-TYqBYg1ZWHkbW5j4AtMgd3bpVQk= - dependencies: - dezalgo "^1.0.2" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -4483,14 +4471,6 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== -dezalgo@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" - integrity sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY= - dependencies: - asap "^2.0.0" - wrappy "1" - dicer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872" From e930abe7412c4a5189665234a2c36bbb580ebea3 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 25 Nov 2020 13:43:05 -0500 Subject: [PATCH 06/12] 0.1.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 94261928f3..4bb629ae18 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@payloadcms/payload", - "version": "0.1.6", + "version": "0.1.7", "description": "CMS and Application Framework", "license": "ISC", "author": "Payload CMS LLC", From a00809db8e1cfa60effbd58312685386601a6401 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 25 Nov 2020 15:10:59 -0500 Subject: [PATCH 07/12] further types frontend --- package.json | 5 +- .../components/elements/ReactSelect/index.tsx | 1 + src/admin/components/forms/Form/index.tsx | 4 +- .../components/forms/RenderFields/index.tsx | 30 ++------- .../components/forms/RenderFields/types.ts | 17 +++++ .../forms/field-types/Relationship/index.tsx | 10 +-- .../forms/field-types/Relationship/types.ts | 25 ++++++++ src/collections/config/types.ts | 13 ++++ src/fields/config/types.ts | 2 +- src/utilities/asyncSome.ts | 64 ++++++++++++++++--- yarn.lock | 12 +++- 11 files changed, 139 insertions(+), 44 deletions(-) create mode 100644 src/admin/components/forms/RenderFields/types.ts create mode 100644 src/admin/components/forms/field-types/Relationship/types.ts diff --git a/package.json b/package.json index 4bb629ae18..7f04159c46 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "@typescript-eslint/parser": "4.0.1", "@udecode/slate-plugins": "^0.64.3", "ajv": "^6.12.6", + "asap": "^2.0.6", "autoprefixer": "^9.7.4", "babel-jest": "^26.3.0", "babel-loader": "^8.1.0", @@ -133,12 +134,14 @@ "webpack-bundle-analyzer": "^3.8.0", "webpack-cli": "^4.2.0", "webpack-dev-middleware": "^4.0.2", - "webpack-hot-middleware": "^2.25.0" + "webpack-hot-middleware": "^2.25.0", + "wrappy": "^1.0.2" }, "devDependencies": { "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.0.4", "@trbl/eslint-config": "^1.2.4", + "@types/asap": "^2.0.0", "@types/autoprefixer": "^9.7.2", "@types/babel__core": "^7.1.12", "@types/babel__plugin-transform-runtime": "^7.9.1", diff --git a/src/admin/components/elements/ReactSelect/index.tsx b/src/admin/components/elements/ReactSelect/index.tsx index b7e992d05f..51e6f282f9 100644 --- a/src/admin/components/elements/ReactSelect/index.tsx +++ b/src/admin/components/elements/ReactSelect/index.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import Select from 'react-select'; import { Props } from './types'; import Chevron from '../../icons/Chevron'; diff --git a/src/admin/components/forms/Form/index.tsx b/src/admin/components/forms/Form/index.tsx index be1e74a48f..9d86291c4d 100644 --- a/src/admin/components/forms/Form/index.tsx +++ b/src/admin/components/forms/Form/index.tsx @@ -5,10 +5,10 @@ import { objectToFormData } from 'object-to-formdata'; import { useHistory } from 'react-router-dom'; import PropTypes from 'prop-types'; import { toast } from 'react-toastify'; +import { useAuth } from '@payloadcms/config-provider'; import { useLocale } from '../../utilities/Locale'; import { requests } from '../../../api'; import useThrottledEffect from '../../../hooks/useThrottledEffect'; -import { useAuth } from '@payloadcms/config-provider'; import fieldReducer from './fieldReducer'; import initContextState from './initContextState'; import reduceFieldsToValues from './reduceFieldsToValues'; @@ -24,7 +24,7 @@ import './index.scss'; const baseClass = 'form'; -const Form = (props) => { +const Form: React.FC = (props) => { const { disabled, onSubmit, diff --git a/src/admin/components/forms/RenderFields/index.tsx b/src/admin/components/forms/RenderFields/index.tsx index b817b4e04e..9b3f0fc67f 100644 --- a/src/admin/components/forms/RenderFields/index.tsx +++ b/src/admin/components/forms/RenderFields/index.tsx @@ -1,7 +1,7 @@ import React, { createContext, useEffect, useContext, useState } from 'react'; -import PropTypes from 'prop-types'; import RenderCustomComponent from '../../utilities/RenderCustomComponent'; import useIntersect from '../../../hooks/useIntersect'; +import { Props, Context } from './types'; const baseClass = 'render-fields'; @@ -9,11 +9,11 @@ const intersectionObserverOptions = { rootMargin: '1000px', }; -const RenderedFieldContext = createContext({}); +const RenderedFieldContext = createContext({} as Context); -export const useRenderedFields = () => useContext(RenderedFieldContext); +export const useRenderedFields = (): Context => useContext(RenderedFieldContext); -const RenderFields: React.FC = (props) => { +const RenderFields: React.FC = (props) => { const { fieldSchema, fieldTypes, @@ -135,26 +135,4 @@ const RenderFields: React.FC = (props) => { return null; }; -RenderFields.defaultProps = { - filter: null, - readOnly: false, - permissions: {}, - operation: undefined, - className: undefined, -}; - -RenderFields.propTypes = { - fieldSchema: PropTypes.arrayOf( - PropTypes.shape({}), - ).isRequired, - fieldTypes: PropTypes.shape({ - hidden: PropTypes.function, - }).isRequired, - filter: PropTypes.func, - permissions: PropTypes.shape({}), - readOnly: PropTypes.bool, - operation: PropTypes.string, - className: PropTypes.string, -}; - export default RenderFields; diff --git a/src/admin/components/forms/RenderFields/types.ts b/src/admin/components/forms/RenderFields/types.ts new file mode 100644 index 0000000000..524b544336 --- /dev/null +++ b/src/admin/components/forms/RenderFields/types.ts @@ -0,0 +1,17 @@ +import { CollectionPermission, GlobalPermission } from '../../../../auth/types'; +import { Field } from '../../../../fields/config/types'; + +export type Operation = 'create' | 'update' + +export type Context = { + operation: Operation +} + +export type Props = { + className?: string + operation: Operation + readOnly: boolean + permissions: CollectionPermission | GlobalPermission + filter: (field: Field) => boolean + fieldSchema: Field[] +} diff --git a/src/admin/components/forms/field-types/Relationship/index.tsx b/src/admin/components/forms/field-types/Relationship/index.tsx index fa2b8da413..a64223764e 100644 --- a/src/admin/components/forms/field-types/Relationship/index.tsx +++ b/src/admin/components/forms/field-types/Relationship/index.tsx @@ -10,6 +10,8 @@ import useFieldType from '../../useFieldType'; import Label from '../../Label'; import Error from '../../Error'; import { relationship } from '../../../../../fields/validations'; +import { PaginatedDocs } from '../../../../../collections/config/types'; +import { RelationshipProps, OptionsPage } from './types'; import './index.scss'; @@ -17,7 +19,7 @@ const maxResultsPerRequest = 10; const baseClass = 'relationship'; -class Relationship extends Component { +class Relationship extends Component { constructor(props) { super(props); @@ -77,7 +79,7 @@ class Relationship extends Component { const fieldToSearch = collection?.admin?.useAsTitle || 'id'; const searchParam = search ? `&where[${fieldToSearch}][like]=${search}` : ''; const response = await fetch(`${serverURL}${api}/${relation}?limit=${maxResultsPerRequest}&page=${lastLoadedPage}${searchParam}`); - const data = await response.json(); + const data: PaginatedDocs = await response.json(); if (response.ok) { if (data.hasNextPage) { @@ -87,7 +89,7 @@ class Relationship extends Component { }); } - return callback({ relation, data }); + return callback(true, { relation, data }); } let error = 'There was a problem loading options for this field.'; @@ -99,7 +101,7 @@ class Relationship extends Component { return this.setState({ errorLoading: error, }); - }, (lastPage, nextPage) => { + }, (lastPage: OptionsPage, nextPage: OptionsPage) => { if (nextPage) { const { data, relation } = nextPage; this.addOptions(data, relation); diff --git a/src/admin/components/forms/field-types/Relationship/types.ts b/src/admin/components/forms/field-types/Relationship/types.ts new file mode 100644 index 0000000000..3302039a3b --- /dev/null +++ b/src/admin/components/forms/field-types/Relationship/types.ts @@ -0,0 +1,25 @@ +import React from 'react'; +import { PaginatedDocs } from '../../../../../collections/config/types'; +import { Config } from '../../../../../config/types'; + +export type OptionsPage = { + relation: string + data: PaginatedDocs +} + +export type RelationshipProps = { + required: boolean + errorMessage: string + hasMany: boolean + showError: boolean + value: unknown + path: string + formProcessing: boolean + admin: { + readOnly: boolean + style: React.CSSProperties + width: string + } + relationTo: string | string[] + config: Config +} diff --git a/src/collections/config/types.ts b/src/collections/config/types.ts index 4be03c4640..6f2786b230 100644 --- a/src/collections/config/types.ts +++ b/src/collections/config/types.ts @@ -144,3 +144,16 @@ export type AfterLoginHook = (args?: { export type AfterForgotPasswordHook = (args?: { args?: any; }) => any; + +export type PaginatedDocs = { + docs: unknown[] + totalDocs: number + limit: number + totalPages: number + page: number + pagingCounter: number + hasPrevPage: boolean + hasNextPage: boolean + prevPage: number | null + nextPage: number | null +} diff --git a/src/fields/config/types.ts b/src/fields/config/types.ts index b3e605e6ef..1f25e7d8f9 100644 --- a/src/fields/config/types.ts +++ b/src/fields/config/types.ts @@ -39,7 +39,7 @@ type FieldBase = { readOnly?: boolean; disabled?: boolean; condition?: (...args: any[]) => any | void; - components?: { [key: string]: JSX.Element | (() => JSX.Element) }; + components?: { [key: string]: React.ComponentType }; }; access?: { create?: Access; diff --git a/src/utilities/asyncSome.ts b/src/utilities/asyncSome.ts index 124ccdf70a..9deb2e73e3 100644 --- a/src/utilities/asyncSome.ts +++ b/src/utilities/asyncSome.ts @@ -1,10 +1,56 @@ -const asyncSome = async (arr: unknown[], predicate: (event: unknown) => Promise): Promise => { - // eslint-disable-next-line no-restricted-syntax - for (const e of arr) { - // eslint-disable-next-line no-await-in-loop - if (await predicate(e)) return true; - } - return false; -}; +/* eslint-disable no-use-before-define */ +/* eslint-disable consistent-return */ +import wrappy from 'wrappy'; +import asap from 'asap'; -export default asyncSome; +type Reduce = (er: boolean, result: unknown) => void; +type Callback = (last: unknown, next: unknown) => void; + +const ensureFutureTick = wrappy((cb: Callback) => { + let sync = true; + asap(() => { + sync = false; + }); + + return function safe(...args: unknown[]) { + if (sync) { + asap(() => { + cb.apply(this, args); + }); + } else { cb.apply(this, args); } + }; +}); + +function some(list: unknown[], predicate: (item: unknown, reduce: Reduce) => void, cb: Callback): void { + const array = slice(list); + let index = 0; + const { length } = array; + const hecomes = ensureFutureTick(cb); + + + const reduce: Reduce = (er, result) => { + if (er) return hecomes(er, false); + if (result) return hecomes(null, result); + + index += 1; + map(); + }; + + map(); + + function map() { + if (index >= length) return hecomes(null, false); + + predicate(array[index], reduce); + } +} + +function slice(args: unknown[]) { + const l = args.length; + const a = []; + let i: number; + for (i = 0; i < l; i += 1) a[i] = args[i]; + return a; +} + +export default some; diff --git a/yarn.lock b/yarn.lock index 7ed1ced001..b7e2e09e62 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1446,6 +1446,11 @@ resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0" integrity sha512-iIgQNzCm0v7QMhhe4Jjn9uRh+I6GoPmt03CbEtwx3ao8/EfoQcmgtqH4vQ5Db/lxiIGaWDv6nwvunuh0RyX0+A== +"@types/asap@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/asap/-/asap-2.0.0.tgz#d529e9608c83499a62ae08c871c5e62271aa2963" + integrity sha512-upIS0Gt9Mc8eEpCbYMZ1K8rhNosfKUtimNcINce+zLwJF5UpM3Vv7yz3S5l/1IX+DxTa8lTkUjqynvjRXyJzsg== + "@types/autoprefixer@^9.7.2": version "9.7.2" resolved "https://registry.yarnpkg.com/@types/autoprefixer/-/autoprefixer-9.7.2.tgz#64b3251c9675feef5a631b7dd34cfea50a8fdbcc" @@ -2840,6 +2845,11 @@ array.prototype.flatmap@^1.2.3: es-abstract "^1.18.0-next.1" function-bind "^1.1.1" +asap@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -12421,7 +12431,7 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrappy@1: +wrappy@1, wrappy@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= From ca55c4e55fa2a76abdb786b84397d1d8f6a12e52 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 25 Nov 2020 15:11:07 -0500 Subject: [PATCH 08/12] 0.1.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7f04159c46..da87ce9e1e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@payloadcms/payload", - "version": "0.1.7", + "version": "0.1.8", "description": "CMS and Application Framework", "license": "ISC", "author": "Payload CMS LLC", From f88f482837e48568684e8bf8960c90328a5a7949 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 25 Nov 2020 15:14:12 -0500 Subject: [PATCH 09/12] properly formats bin --- bin.js | 2 ++ src/bin/index.ts | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) mode change 100644 => 100755 bin.js diff --git a/bin.js b/bin.js old mode 100644 new mode 100755 index d986755c6a..53f4897049 --- a/bin.js +++ b/bin.js @@ -1 +1,3 @@ +#!/usr/bin/env node + require('./dist/src/bin'); diff --git a/src/bin/index.ts b/src/bin/index.ts index 63c830000a..5952749e61 100755 --- a/src/bin/index.ts +++ b/src/bin/index.ts @@ -1,5 +1,3 @@ -#!/usr/bin/env node - import minimist from 'minimist'; import build from './build'; From 56072e952d496e93e4e8adcb057e719c10882888 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 25 Nov 2020 15:14:18 -0500 Subject: [PATCH 10/12] 0.1.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index da87ce9e1e..c4ab1c64fc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@payloadcms/payload", - "version": "0.1.8", + "version": "0.1.9", "description": "CMS and Application Framework", "license": "ISC", "author": "Payload CMS LLC", From 0e2fbe0e8fe96ed92b009cf9c03f9f10261a13ec Mon Sep 17 00:00:00 2001 From: James Date: Wed, 25 Nov 2020 18:57:17 -0500 Subject: [PATCH 11/12] enables build w/ typescript, refines the way configs are found --- bin.js | 1 - package.json | 4 +++- src/bin/build.ts | 26 ++++++++++++++++++++---- src/config/find.ts | 31 ++++++++++------------------- src/webpack/getWebpackProdConfig.ts | 8 ++++++-- tsconfig.json | 3 --- yarn.lock | 29 +++++++++++++++++++++++++++ 7 files changed, 71 insertions(+), 31 deletions(-) diff --git a/bin.js b/bin.js index 53f4897049..317b4712e6 100755 --- a/bin.js +++ b/bin.js @@ -1,3 +1,2 @@ #!/usr/bin/env node - require('./dist/src/bin'); diff --git a/package.json b/package.json index c4ab1c64fc..e5f49a5b1b 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "scripts": { "copyfiles": "copyfiles src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png} dist/", "build:components": "webpack --config src/webpack/components.config.js", - "build": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.js node src/bin/build", + "build": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.js node dist/src/bin/build", "build:tsc": "tsc", "build:analyze": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.js PAYLOAD_ANALYZE_BUNDLE=true node src/bin/build", "cov": "npm run core:build && node ./node_modules/jest/bin/jest.js src/tests --coverage", @@ -62,6 +62,7 @@ "express-rate-limit": "^5.1.3", "falsey": "^1.0.0", "file-loader": "^1.1.11", + "find-up": "^5.0.0", "flatley": "^5.2.0", "graphql": "15.4.0", "graphql-playground-middleware-express": "^1.7.14", @@ -156,6 +157,7 @@ "@types/express-rate-limit": "^5.1.0", "@types/extract-text-webpack-plugin": "^3.0.4", "@types/file-loader": "^4.2.0", + "@types/find-up": "^4.0.0", "@types/html-webpack-plugin": "^3.2.4", "@types/ignore-styles": "^5.0.0", "@types/is-hotkey": "^0.1.2", diff --git a/src/bin/build.ts b/src/bin/build.ts index bdf46f9e44..4b4d0a7416 100755 --- a/src/bin/build.ts +++ b/src/bin/build.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable global-require */ /* eslint-disable import/no-dynamic-require */ @@ -5,14 +6,31 @@ import webpack from 'webpack'; import getWebpackProdConfig from '../webpack/getWebpackProdConfig'; import findConfig from '../config/find'; import loadConfig from '../config/load'; -import { buildConfig } from '../config/build'; +import getBabelConfig from '../babel.config'; + +const babelConfig = getBabelConfig({ + env: () => false, +}); const configPath = findConfig(); -const build = () => { +const build = (): void => { try { - const unsanitizedConfig = loadConfig(); - const config = buildConfig(unsanitizedConfig); + require('@babel/register')({ + ...babelConfig, + extensions: ['.js', '.jsx', '.ts', '.tsx'], + plugins: [ + [ + require('babel-plugin-ignore-html-and-css-imports'), + { + removeExtensions: ['.svg', '.css', '.scss', '.png', '.jpg'], + }, + ], + ...babelConfig.plugins, + ], + }); + + const config = loadConfig(); const webpackProdConfig = getWebpackProdConfig({ ...config, diff --git a/src/config/find.ts b/src/config/find.ts index 7369ca6187..da6f2f0a36 100644 --- a/src/config/find.ts +++ b/src/config/find.ts @@ -1,5 +1,5 @@ import path from 'path'; -import fs from 'fs'; +import findUp from 'find-up'; const findConfig = (): string => { // If the developer has specified a config path, @@ -12,30 +12,21 @@ const findConfig = (): string => { return path.resolve(process.cwd(), process.env.PAYLOAD_CONFIG_PATH); } - // By default, Payload is installed as a node_module. - // Traverse up three levels and check for config - const defaultPath = path.resolve(__dirname, '../../../payload.config.js'); + const configPath = findUp.sync((dir) => { + const tsPath = path.join(dir, 'payload.config.ts'); + const hasTS = findUp.sync.exists(tsPath); - if (fs.existsSync(defaultPath)) { - return defaultPath; - } + if (hasTS) return tsPath; - const defaultTSPath = path.resolve(__dirname, '../../../payload.config.ts'); + const jsPath = path.join(dir, 'payload.config.js'); + const hasJS = findUp.sync.exists(jsPath); - if (fs.existsSync(defaultTSPath)) { - return defaultTSPath; - } + if (hasJS) return jsPath; - // Check for config in current working directory - const cwdJSPath = path.resolve(process.cwd(), 'payload.config.js'); - if (fs.existsSync(cwdJSPath)) { - return cwdJSPath; - } + return undefined; + }); - const cwdTSPath = path.resolve(process.cwd(), 'payload.config.ts'); - if (fs.existsSync(cwdTSPath)) { - return cwdTSPath; - } + if (configPath) return configPath; throw new Error('Error: cannot find Payload config. Please create a configuration file located at the root of your current working directory called "payload.config.js" or "payload.config.ts".'); }; diff --git a/src/webpack/getWebpackProdConfig.ts b/src/webpack/getWebpackProdConfig.ts index f72ccd1469..93757c134a 100644 --- a/src/webpack/getWebpackProdConfig.ts +++ b/src/webpack/getWebpackProdConfig.ts @@ -8,7 +8,7 @@ import webpack, { Configuration } from 'webpack'; import { Config } from '../config/types'; import babelConfig from '../babel.config'; -const mockModulePath = path.resolve(__dirname, '../mocks/emptyModule.js'); +const mockModulePath = path.resolve(__dirname, './mocks/emptyModule.js'); export default (config: Config): Configuration => { let webpackConfig: Configuration = { @@ -41,7 +41,7 @@ export default (config: Config): Configuration => { module: { rules: [ { - test: /\.js$/, + test: /\.(t|j|)sx?$/, exclude: /node_modules[\\/](?!(@payloadcms[\\/]payload)[\\/]).*/, use: { loader: require.resolve('babel-loader'), @@ -92,8 +92,12 @@ export default (config: Config): Configuration => { 'payload/config': config.paths.config, '@payloadcms/payload$': mockModulePath, }, + extensions: ['.ts', '.tsx', '.js', '.json'], }, plugins: [ + new webpack.ProvidePlugin( + { process: 'process/browser' }, + ), new HtmlWebpackPlugin({ template: config.admin && config.admin.indexHTML ? path.join(config.paths.configDir, config.admin.indexHTML) diff --git a/tsconfig.json b/tsconfig.json index d932b841fa..791acc1fee 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,9 +15,6 @@ "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ "baseUrl": "", "paths": { - "payload/config": [ - "src/admin/types/config" // Webpack alias to user config - ], "@payloadcms/payload/config": [ "src/config/types.ts" ], diff --git a/yarn.lock b/yarn.lock index b7e2e09e62..e67742e363 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1644,6 +1644,13 @@ dependencies: "@types/webpack" "*" +"@types/find-up@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/find-up/-/find-up-4.0.0.tgz#6b74a76670477a23f0793cfaf2dafc86df59723a" + integrity sha512-QlRNKeOPFWKisbNtKVOOGXw3AeLbkw8UmT/EyEGM6brfqpYffKBcch7f1y40NYN9O90aK2+K0xBMDJfOAsg2qg== + dependencies: + find-up "*" + "@types/graceful-fs@^4.1.2": version "4.1.4" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.4.tgz#4ff9f641a7c6d1a3508ff88bc3141b152772e753" @@ -5404,6 +5411,14 @@ find-root@^1.1.0: resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== +find-up@*, find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -7430,6 +7445,13 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + lockfile@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.4.tgz#07f819d25ae48f87e538e6578b6964a4981a5609" @@ -8531,6 +8553,13 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + p-map@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" From 1889f00f8fcd21923fb7d594f0c3067e89fa2f97 Mon Sep 17 00:00:00 2001 From: Elliot DeNolf Date: Thu, 26 Nov 2020 11:44:14 -0500 Subject: [PATCH 12/12] more field type adjustments --- package.json | 1 + src/fields/config/types.ts | 15 +++++---------- src/index.ts | 1 - src/mongoose/buildSchema.ts | 36 +++++++++++++++++++----------------- 4 files changed, 25 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index e5f49a5b1b..129277b19d 100644 --- a/package.json +++ b/package.json @@ -171,6 +171,7 @@ "@types/mongodb": "^3.5.34", "@types/mongoose": "^5.10.1", "@types/mongoose-paginate-v2": "^1.3.8", + "@types/node-fetch": "^2.5.7", "@types/node-sass": "^4.11.1", "@types/nodemailer": "^6.4.0", "@types/nodemon": "^1.19.0", diff --git a/src/fields/config/types.ts b/src/fields/config/types.ts index 1f25e7d8f9..298b15c958 100644 --- a/src/fields/config/types.ts +++ b/src/fields/config/types.ts @@ -52,6 +52,7 @@ type FieldBase = { } export type StandardField = FieldBase & { + type: string; fields?: Field[]; } @@ -120,6 +121,7 @@ export type RadioField = FieldBase & { value: string; label: string; }[]; + hasMany?: boolean; } export type Block = { @@ -135,23 +137,16 @@ export type BlockField = FieldBase & { type: 'blocks'; minRows?: number; maxRows?: number; - blocks?: Block[]; + blocks?: Field[]; }; -export type Field = NumberField - | TextField - | EmailField - | TextareaField - | CodeField - | CheckboxField - | DateField +export type Field = + | StandardField | BlockField | RadioField | RelationshipField | ArrayField | RichTextField - | GroupField - | RowField | SelectField | SelectManyField | UploadField; diff --git a/src/index.ts b/src/index.ts index f5d5a95d76..f5974621fd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -139,7 +139,6 @@ export class Payload { this.initCollections = initCollections.bind(this); this.initGlobals = initGlobals.bind(this); this.initGraphQLPlayground = initGraphQLPlayground.bind(this); - // this.buildEmail = buildEmail.bind(this); this.sendEmail = this.sendEmail.bind(this); this.getMockEmailCredentials = this.getMockEmailCredentials.bind(this); this.initStatic = initStatic.bind(this); diff --git a/src/mongoose/buildSchema.ts b/src/mongoose/buildSchema.ts index 5a8a13697f..cbbd16e6b7 100644 --- a/src/mongoose/buildSchema.ts +++ b/src/mongoose/buildSchema.ts @@ -1,15 +1,17 @@ /* eslint-disable no-use-before-define */ import { Schema } from 'mongoose'; import { MissingFieldInputOptions } from '../errors'; -import { ArrayField, BlockField, CheckboxField, CodeField, DateField, EmailField, Field, GroupField, NumberField, RadioField, RelationshipField, RichTextField, RowField, SelectField, TextareaField, TextField, UploadField } from '../fields/config/types'; +import { ArrayField, BlockField, Field, RadioField, RelationshipField, SelectField, StandardField, UploadField } from '../fields/config/types'; const setBlockDiscriminators = (fields: Field[], schema) => { fields.forEach((field) => { - if (field.type === 'blocks' && field.blocks && field.blocks.length > 0) { - field.blocks.forEach((block) => { + const blockFieldType = field as BlockField; + if (blockFieldType.type === 'blocks' && blockFieldType.blocks && blockFieldType.blocks.length > 0) { + blockFieldType.blocks.forEach((blockItem: StandardField) => { let blockSchemaFields = {}; - block.fields.forEach((blockField) => { + // TODO: Would this blow up on a relationship since it doesn't have fields? + blockItem.fields.forEach((blockField) => { const fieldSchema = fieldToSchemaMap[blockField.type]; if (fieldSchema) { blockSchemaFields = fieldSchema(blockField, blockSchemaFields); @@ -17,9 +19,9 @@ const setBlockDiscriminators = (fields: Field[], schema) => { }); const blockSchema = new Schema(blockSchemaFields, { _id: false }); - schema.path(field.name).discriminator(block.slug, blockSchema); + schema.path(field.name).discriminator(blockItem.slug, blockSchema); - setBlockDiscriminators(block.fields, blockSchema); + setBlockDiscriminators(blockItem.fields, blockSchema); }); } }); @@ -58,27 +60,27 @@ const buildSchema = (configFields: Field[], options = {}): Schema => { }; const fieldToSchemaMap = { - number: (field: NumberField, fields: Field[]) => ({ + number: (field: Field, fields: Field[]) => ({ ...fields, [field.name]: { ...formatBaseSchema(field), type: Number }, }), - text: (field: TextField, fields: Field[]) => ({ + text: (field: Field, fields: Field[]) => ({ ...fields, [field.name]: { ...formatBaseSchema(field), type: String }, }), - email: (field: EmailField, fields: Field[]) => ({ + email: (field: Field, fields: Field[]) => ({ ...fields, [field.name]: { ...formatBaseSchema(field), type: String }, }), - textarea: (field: TextareaField, fields: Field[]) => ({ + textarea: (field: Field, fields: Field[]) => ({ ...fields, [field.name]: { ...formatBaseSchema(field), type: String }, }), - richText: (field: RichTextField, fields: Field[]) => ({ + richText: (field: Field, fields: Field[]) => ({ ...fields, [field.name]: { ...formatBaseSchema(field), type: Schema.Types.Mixed }, }), - code: (field: CodeField, fields: Field[]) => ({ + code: (field: Field, fields: Field[]) => ({ ...fields, [field.name]: { ...formatBaseSchema(field), type: String }, }), @@ -101,11 +103,11 @@ const fieldToSchemaMap = { [field.name]: field.hasMany ? [schema] : schema, // TODO: radio group with hasMany?? }; }, - checkbox: (field: CheckboxField, fields: Field[]) => ({ + checkbox: (field: Field, fields: Field[]) => ({ ...fields, [field.name]: { ...formatBaseSchema(field), type: Boolean }, }), - date: (field: DateField, fields: Field[]) => ({ + date: (field: Field, fields: Field[]) => ({ ...fields, [field.name]: { ...formatBaseSchema(field), type: Date }, }), @@ -147,10 +149,10 @@ const fieldToSchemaMap = { [field.name]: schema, }; }, - row: (field: RowField, fields: Field[]) => { + row: (field: StandardField, fields: Field[]) => { const newFields = { ...fields }; - field.fields.forEach((rowField) => { + field.fields.forEach((rowField: Field) => { const fieldSchemaMap = fieldToSchemaMap[rowField.type]; if (fieldSchemaMap) { @@ -172,7 +174,7 @@ const fieldToSchemaMap = { }, }; }, - group: (field: GroupField, fields: Field[]) => { + group: (field: StandardField, fields: Field[]) => { const schema = buildSchema(field.fields, { _id: false, id: false }); return {