further types
This commit is contained in:
14
demo/client/index.html
Normal file
14
demo/client/index.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<div id="portal"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -35,7 +35,7 @@ export default buildConfig({
|
||||
serverURL: 'http://localhost:3000',
|
||||
admin: {
|
||||
user: 'admins',
|
||||
// indexHTML: 'custom-index.html',
|
||||
indexHTML: path.resolve(__dirname, './client/index.html'),
|
||||
// meta: {
|
||||
// titleSuffix: '- Payload Demo',
|
||||
// // ogImage: '/static/find-image-here.jpg',
|
||||
|
||||
@@ -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 dist/src/bin/build",
|
||||
"build": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.ts 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",
|
||||
|
||||
@@ -59,8 +59,8 @@ export type User = {
|
||||
type GenerateVerifyEmailHTML = (args: { req: PayloadRequest, token: string, user: any}) => Promise<string> | string
|
||||
type GenerateVerifyEmailSubject = (args: { req: PayloadRequest, token: string, user: any}) => Promise<string> | string
|
||||
|
||||
type GenerateForgotPasswordEmailHTML = (args?: { token?: string, email?: string, req?: PayloadRequest }) => string
|
||||
type GenerateForgotPasswordEmailSubject = (args?: { req?: PayloadRequest }) => string
|
||||
type GenerateForgotPasswordEmailHTML = (args?: { token?: string, email?: string, req?: PayloadRequest }) => Promise<string> | string
|
||||
type GenerateForgotPasswordEmailSubject = (args?: { req?: PayloadRequest }) => Promise<string> | string
|
||||
|
||||
export interface IncomingAuthType {
|
||||
tokenExpiration?: number;
|
||||
|
||||
@@ -6,14 +6,11 @@ import getWebpackProdConfig from '../webpack/getWebpackProdConfig';
|
||||
import findConfig from '../config/find';
|
||||
import loadConfig from '../config/load';
|
||||
import { buildConfig } from '../config/build';
|
||||
import babelConfig from '../babel.config';
|
||||
|
||||
const configPath = findConfig();
|
||||
|
||||
const build = (): void => {
|
||||
export const build = (): void => {
|
||||
try {
|
||||
require('@babel/register')(babelConfig);
|
||||
|
||||
const loadedConfig = loadConfig();
|
||||
const config = buildConfig(loadedConfig);
|
||||
const webpackProdConfig = getWebpackProdConfig({
|
||||
@@ -43,6 +40,3 @@ const build = (): void => {
|
||||
if (module.id === require.main.id) {
|
||||
build();
|
||||
}
|
||||
|
||||
|
||||
export default build;
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
import minimist from 'minimist';
|
||||
import build from './build';
|
||||
import babelConfig from '../babel.config';
|
||||
|
||||
require('@babel/register')({
|
||||
...babelConfig,
|
||||
extensions: ['.ts', '.tsx', '.js', '.jsx'],
|
||||
});
|
||||
|
||||
const { build } = require('./build');
|
||||
|
||||
const args = minimist(process.argv.slice(2));
|
||||
|
||||
|
||||
@@ -44,42 +44,48 @@ const collectionSchema = joi.object().keys({
|
||||
afterLogin: joi.array().items(joi.func()).default([]),
|
||||
afterForgotPassword: joi.array().items(joi.func()).default([]),
|
||||
}).default(),
|
||||
auth: joi.object({
|
||||
tokenExpiration: joi.number(),
|
||||
depth: joi.number().default(0),
|
||||
verify: joi.alternatives().try(
|
||||
joi.boolean(),
|
||||
joi.object().keys({
|
||||
auth: joi.alternatives().try(
|
||||
joi.object({
|
||||
tokenExpiration: joi.number(),
|
||||
depth: joi.number().default(0),
|
||||
verify: joi.alternatives().try(
|
||||
joi.boolean(),
|
||||
joi.object().keys({
|
||||
generateEmailHTML: joi.func(),
|
||||
generateEmailSubject: joi.func(),
|
||||
}),
|
||||
),
|
||||
lockTime: joi.number(),
|
||||
useAPIKey: joi.boolean(),
|
||||
cookies: joi.object().keys({
|
||||
secure: joi.boolean(),
|
||||
sameSite: joi.string(), // TODO: add further specificity with joi.xor
|
||||
domain: joi.string(),
|
||||
}),
|
||||
forgotPassword: joi.object().keys({
|
||||
generateEmailHTML: joi.func(),
|
||||
generateEmailSubject: joi.func(),
|
||||
}),
|
||||
),
|
||||
lockTime: joi.number(),
|
||||
useAPIKey: joi.boolean(),
|
||||
cookies: joi.object().keys({
|
||||
secure: joi.boolean(),
|
||||
sameSite: joi.string(), // TODO: add further specificity with joi.xor
|
||||
domain: joi.string(),
|
||||
maxLoginAttempts: joi.number(),
|
||||
}),
|
||||
forgotPassword: joi.object().keys({
|
||||
generateEmailHTML: joi.func(),
|
||||
generateEmailSubject: joi.func(),
|
||||
joi.boolean(),
|
||||
).default(false),
|
||||
upload: joi.alternatives().try(
|
||||
joi.object({
|
||||
staticURL: joi.string(),
|
||||
staticDir: joi.string(),
|
||||
adminThumbnail: joi.string(),
|
||||
imageSizes: joi.array().items(
|
||||
joi.object().keys({
|
||||
name: joi.string(),
|
||||
width: joi.number(),
|
||||
height: joi.number(),
|
||||
crop: joi.string(), // TODO: add further specificity with joi.xor
|
||||
}),
|
||||
),
|
||||
}),
|
||||
maxLoginAttempts: joi.number(),
|
||||
}).default(false),
|
||||
upload: joi.object({
|
||||
staticURL: joi.string(),
|
||||
staticDir: joi.string(),
|
||||
adminThumbnail: joi.string(),
|
||||
imageSizes: joi.array().items(
|
||||
joi.object().keys({
|
||||
name: joi.string(),
|
||||
width: joi.number(),
|
||||
height: joi.number(),
|
||||
crop: joi.string(), // TODO: add further specificity with joi.xor
|
||||
}),
|
||||
),
|
||||
}).default(false),
|
||||
joi.boolean(),
|
||||
).default(false),
|
||||
});
|
||||
|
||||
export default collectionSchema;
|
||||
|
||||
@@ -118,13 +118,13 @@ export type PayloadCollectionConfig = {
|
||||
afterLogin?: AfterLoginHook[];
|
||||
afterForgotPassword?: AfterForgotPasswordHook[];
|
||||
};
|
||||
access: {
|
||||
create: Access;
|
||||
read: Access;
|
||||
update: Access;
|
||||
delete: Access;
|
||||
admin: Access;
|
||||
unlock: Access;
|
||||
access?: {
|
||||
create?: Access;
|
||||
read?: Access;
|
||||
update?: Access;
|
||||
delete?: Access;
|
||||
admin?: Access;
|
||||
unlock?: Access;
|
||||
};
|
||||
auth?: Auth | boolean;
|
||||
upload?: Upload | boolean;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export default async function find(options) {
|
||||
import { FindOptions } from '../../../types';
|
||||
|
||||
export default async function find(options: FindOptions) {
|
||||
const {
|
||||
collection: collectionSlug,
|
||||
depth,
|
||||
|
||||
@@ -9,6 +9,7 @@ import { PayloadCollectionConfig } from '../collections/config/types';
|
||||
import { PayloadGlobalConfig } from '../globals/config/types';
|
||||
import { PayloadRequest } from '../express/types/payloadRequest';
|
||||
import InitializeGraphQL from '../graphql';
|
||||
import { Where } from '../types';
|
||||
|
||||
type MockEmailTransport = {
|
||||
transport?: 'mock';
|
||||
@@ -47,7 +48,7 @@ export type MockEmailCredentials = {
|
||||
web: string;
|
||||
};
|
||||
|
||||
export type Access = (args?: any) => boolean;
|
||||
export type Access = (args?: any) => boolean | Where;
|
||||
|
||||
export type PayloadConfig = {
|
||||
admin?: {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import passport from 'passport';
|
||||
import { PayloadConfig } from '../../config/types';
|
||||
import { Payload } from '../../index';
|
||||
|
||||
export default (config: PayloadConfig) => {
|
||||
export default (config: Payload) => {
|
||||
const methods = config.collections.reduce((enabledMethods, collection) => {
|
||||
if (collection.auth && collection.auth.useAPIKey) {
|
||||
const collectionMethods = [...enabledMethods];
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { Request } from 'express';
|
||||
import { Payload } from '../../index';
|
||||
import { Collection } from '../../collections/config/types';
|
||||
import { User } from '../../auth/types';
|
||||
|
||||
export type PayloadRequest = Request & {
|
||||
payload: Payload;
|
||||
locale?: string;
|
||||
fallbackLocale?: string;
|
||||
collection?: Collection;
|
||||
payloadAPI: 'REST' | 'local'
|
||||
payloadAPI: 'REST' | 'local' | 'graphQL'
|
||||
file?: {
|
||||
name: string,
|
||||
}
|
||||
// user: User
|
||||
user: User | null
|
||||
};
|
||||
|
||||
@@ -207,6 +207,13 @@ export const richText = baseField.keys({
|
||||
}),
|
||||
});
|
||||
|
||||
export const date = baseField.keys({
|
||||
type: joi.string().valid('date').required(),
|
||||
name: joi.string().required(),
|
||||
defaultValue: joi.string(),
|
||||
});
|
||||
|
||||
|
||||
const fieldSchema = joi.alternatives()
|
||||
.try(
|
||||
text,
|
||||
@@ -224,6 +231,7 @@ const fieldSchema = joi.alternatives()
|
||||
upload,
|
||||
richText,
|
||||
blocks,
|
||||
date,
|
||||
)
|
||||
.id('field');
|
||||
|
||||
|
||||
@@ -2,15 +2,18 @@
|
||||
import { CSSProperties } from 'react';
|
||||
import { PayloadRequest } from '../../express/types/payloadRequest';
|
||||
import { Access } from '../../config/types';
|
||||
import { Document } from '../../types';
|
||||
|
||||
// TODO: add generic type and use mongoose types for originalDoc & data
|
||||
export type FieldHook = (args: {
|
||||
value?: any,
|
||||
originalDoc?: any,
|
||||
data?: any,
|
||||
value?: unknown,
|
||||
originalDoc?: Document,
|
||||
data?: {
|
||||
[key: string]: unknown
|
||||
},
|
||||
operation?: 'create' | 'update',
|
||||
req?: PayloadRequest
|
||||
}) => Promise<any> | any;
|
||||
}) => Promise<unknown> | unknown;
|
||||
|
||||
type FieldBase = {
|
||||
name: string;
|
||||
@@ -33,7 +36,7 @@ type FieldBase = {
|
||||
afterRead?: FieldHook[];
|
||||
}
|
||||
admin?: {
|
||||
position?: 'sidebar';
|
||||
position?: string;
|
||||
width?: string;
|
||||
style?: CSSProperties;
|
||||
readOnly?: boolean;
|
||||
|
||||
@@ -3,9 +3,9 @@ import crypto from 'crypto';
|
||||
import { TestAccount } from 'nodemailer';
|
||||
import { AuthenticateOptions } from 'passport';
|
||||
import {
|
||||
Config,
|
||||
EmailOptions,
|
||||
InitOptions,
|
||||
PayloadConfig,
|
||||
} from './config/types';
|
||||
import {
|
||||
Collection,
|
||||
@@ -53,7 +53,7 @@ require('isomorphic-fetch');
|
||||
* @description Payload
|
||||
*/
|
||||
export class Payload {
|
||||
config: PayloadConfig = loadConfig();
|
||||
config: Config = loadConfig();
|
||||
|
||||
collections: Collection[] = [];
|
||||
|
||||
|
||||
@@ -2,6 +2,12 @@ import { PayloadRequest } from '../express/types/payloadRequest';
|
||||
import { Field } from '../fields/config/types';
|
||||
import { Payload } from '../index';
|
||||
|
||||
export { FieldHook } from '../fields/config/types';
|
||||
|
||||
export type Where = {
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type Document = {
|
||||
id: string;
|
||||
[key: string]: unknown;
|
||||
|
||||
@@ -3,7 +3,7 @@ import { promisify } from 'util';
|
||||
|
||||
const stat = promisify(fs.stat);
|
||||
|
||||
export default async (fileName) => {
|
||||
export default async (fileName: string): Promise<boolean> => {
|
||||
try {
|
||||
await stat(fileName);
|
||||
return true;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export default function formatBytes(bytes, decimals = 0) {
|
||||
export default function formatBytes(bytes: number, decimals = 0): string {
|
||||
if (bytes === 0) return '0 bytes';
|
||||
|
||||
const k = 1024;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import sanitize from 'sanitize-filename';
|
||||
import fileExists from './fileExists';
|
||||
|
||||
const incrementName = (name) => {
|
||||
const incrementName = (name: string) => {
|
||||
const extension = name.split('.').pop();
|
||||
const baseFilename = sanitize(name.substr(0, name.lastIndexOf('.')) || name);
|
||||
let incrementedName = baseFilename;
|
||||
@@ -19,7 +19,7 @@ const incrementName = (name) => {
|
||||
return `${incrementedName}.${extension}`;
|
||||
};
|
||||
|
||||
async function getSafeFileName(staticPath, desiredFilename) {
|
||||
async function getSafeFileName(staticPath: string, desiredFilename: string): Promise<string> {
|
||||
let modifiedFilename = desiredFilename;
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import isImage from './isImage';
|
||||
import { FileData } from './types';
|
||||
|
||||
const getThumbnail = (mimeType, staticURL, filename, sizes, adminThumbnail): string | boolean => {
|
||||
const getThumbnail = (mimeType: string, staticURL: string, filename: string, sizes: FileData[], adminThumbnail: string): string | boolean => {
|
||||
if (isImage(mimeType)) {
|
||||
if (sizes?.[adminThumbnail]?.filename) {
|
||||
return `${staticURL}/${sizes[adminThumbnail].filename}`;
|
||||
|
||||
@@ -3,7 +3,7 @@ import sharp from 'sharp';
|
||||
import sanitize from 'sanitize-filename';
|
||||
import getImageSize from './getImageSize';
|
||||
import fileExists from './fileExists';
|
||||
import { Collection } from '../collections/config/types';
|
||||
import { CollectionConfig } from '../collections/config/types';
|
||||
import { FileSizes } from './types';
|
||||
|
||||
function getOutputImage(sourceImage, size) {
|
||||
@@ -28,7 +28,7 @@ function getOutputImage(sourceImage, size) {
|
||||
*/
|
||||
export default async function resizeAndSave(
|
||||
staticPath: string,
|
||||
config: Collection,
|
||||
config: CollectionConfig,
|
||||
savedFilename: string,
|
||||
mimeType: string,
|
||||
): Promise<FileSizes> {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { DuplicateCollection } from '../errors';
|
||||
import { Collection } from '../collections/config/types';
|
||||
import { CollectionConfig } from '../collections/config/types';
|
||||
|
||||
const getDuplicates = (arr) => arr.filter((item, index) => arr.indexOf(item) !== index);
|
||||
const getDuplicates = (arr: string[]) => arr.filter((item, index) => arr.indexOf(item) !== index);
|
||||
|
||||
const checkDuplicateCollections = (collections: Collection[]): void => {
|
||||
const checkDuplicateCollections = (collections: CollectionConfig[]): void => {
|
||||
const duplicateSlugs = getDuplicates(collections.map((c) => c.slug));
|
||||
if (duplicateSlugs.length > 0) {
|
||||
throw new DuplicateCollection('slug', duplicateSlugs);
|
||||
|
||||
@@ -91,6 +91,7 @@ export default (config: Config): Configuration => {
|
||||
alias: {
|
||||
'payload/config': config.paths.config,
|
||||
'@payloadcms/payload$': mockModulePath,
|
||||
'payload-scss-overrides': config.paths.scss,
|
||||
},
|
||||
extensions: ['.ts', '.tsx', '.js', '.json'],
|
||||
},
|
||||
@@ -99,9 +100,7 @@ export default (config: Config): Configuration => {
|
||||
{ process: 'process/browser' },
|
||||
),
|
||||
new HtmlWebpackPlugin({
|
||||
template: config.admin && config.admin.indexHTML
|
||||
? path.join(config.paths.configDir, config.admin.indexHTML)
|
||||
: path.resolve(__dirname, '../admin/index.html'),
|
||||
template: config.admin.indexHTML,
|
||||
filename: path.normalize('./index.html'),
|
||||
}),
|
||||
new webpack.DefinePlugin(Object.entries(config.publicENV).reduce((values, [key, val]) => ({
|
||||
@@ -125,12 +124,6 @@ export default (config: Config): Configuration => {
|
||||
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
|
||||
}
|
||||
|
||||
if (config.paths.scss) {
|
||||
webpackConfig.resolve.alias['payload-scss-overrides'] = path.join(config.paths.configDir, config.paths.scss);
|
||||
} else {
|
||||
webpackConfig.resolve.alias['payload-scss-overrides'] = path.resolve(__dirname, '../admin/scss/overrides.scss');
|
||||
}
|
||||
|
||||
if (config.webpack && typeof config.webpack === 'function') {
|
||||
webpackConfig = config.webpack(webpackConfig);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user