refactor: rewrite in typescript (#7)
This commit is contained in:
15
src/index.ts
Normal file
15
src/index.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Main } from './main'
|
||||
import { init, handleException } from './utils/usage'
|
||||
import { error } from './utils/log'
|
||||
;(async () => {
|
||||
const trx = init()
|
||||
const main = new Main()
|
||||
try {
|
||||
await main.init()
|
||||
} catch (e) {
|
||||
handleException(e)
|
||||
error(`An error has occurred: ${e && e.message}`)
|
||||
} finally {
|
||||
trx.finish()
|
||||
}
|
||||
})()
|
||||
49
src/lib/createProject.test.ts
Normal file
49
src/lib/createProject.test.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import fse from 'fs-extra'
|
||||
import path from 'path'
|
||||
import type { ProjectTemplate } from '../types'
|
||||
import {
|
||||
createProject,
|
||||
getLatestPayloadVersion,
|
||||
updatePayloadVersion,
|
||||
} from './createProject'
|
||||
|
||||
describe('createProject', () => {
|
||||
const projectDir = path.resolve(__dirname, './tmp')
|
||||
beforeAll(() => {
|
||||
console.log = jest.fn()
|
||||
fse.rmdirSync(projectDir, { recursive: true })
|
||||
})
|
||||
afterEach(() => {
|
||||
fse.rmdirSync(projectDir, { recursive: true })
|
||||
})
|
||||
|
||||
describe('#createProject', () => {
|
||||
const args = { _: ['project-name'], '--no-deps': true }
|
||||
const packageManager = 'yarn'
|
||||
|
||||
it('creates static project', async () => {
|
||||
const expectedPayloadVersion = await getLatestPayloadVersion()
|
||||
const template: ProjectTemplate = { name: 'ts-todo', type: 'static' }
|
||||
await createProject(args, projectDir, template, packageManager)
|
||||
|
||||
const packageJsonPath = path.resolve(projectDir, 'package.json')
|
||||
const packageJson = fse.readJsonSync(packageJsonPath)
|
||||
expect(packageJson.dependencies.payload).toBe(expectedPayloadVersion)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#updatePayloadVersion', () => {
|
||||
it('updates payload version in package.json', async () => {
|
||||
const packageJsonPath = path.resolve(projectDir, 'package.json')
|
||||
await fse.mkdir(projectDir)
|
||||
await fse.writeJson(
|
||||
packageJsonPath,
|
||||
{ dependencies: { payload: '0.0.1' } },
|
||||
{ spaces: 2 },
|
||||
)
|
||||
await updatePayloadVersion(projectDir)
|
||||
const modified = await fse.readJson(packageJsonPath)
|
||||
expect(modified.dependencies.payload).not.toBe('0.0.1')
|
||||
})
|
||||
})
|
||||
})
|
||||
112
src/lib/createProject.ts
Normal file
112
src/lib/createProject.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import path from 'path'
|
||||
import chalk from 'chalk'
|
||||
import fse from 'fs-extra'
|
||||
import execa from 'execa'
|
||||
import ora from 'ora'
|
||||
import degit from 'degit'
|
||||
|
||||
import { success, error, warning } from '../utils/log'
|
||||
import { setTags } from '../utils/usage'
|
||||
import type { CliArgs, ProjectTemplate } from '../types'
|
||||
|
||||
async function createProjectDir(projectDir: string): Promise<void> {
|
||||
await fse.mkdir(projectDir)
|
||||
const readDir = await fse.readdir(projectDir)
|
||||
if (readDir && readDir.length > 0) {
|
||||
error(`The project directory '${projectDir}' is not empty`)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
async function installDeps(
|
||||
args: CliArgs,
|
||||
dir: string,
|
||||
packageManager: string,
|
||||
): Promise<boolean> {
|
||||
if (args['--no-deps']) {
|
||||
return true
|
||||
}
|
||||
const cmd = packageManager === 'yarn' ? 'yarn' : 'npm install --legacy-peer-deps'
|
||||
|
||||
try {
|
||||
await execa.command(cmd, {
|
||||
cwd: path.resolve(dir),
|
||||
})
|
||||
return true
|
||||
} catch (error: unknown) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export async function getLatestPayloadVersion(): Promise<false | string> {
|
||||
try {
|
||||
const { stdout } = await execa('npm info payload version', [], { shell: true })
|
||||
return `^${stdout}`
|
||||
} catch (error: unknown) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export async function updatePayloadVersion(projectDir: string): Promise<void> {
|
||||
const payloadVersion = await getLatestPayloadVersion()
|
||||
if (!payloadVersion) {
|
||||
warning(
|
||||
'Error retrieving latest Payload version. Please update your package.json manually.',
|
||||
)
|
||||
return
|
||||
}
|
||||
setTags({ payload_version: payloadVersion })
|
||||
|
||||
const packageJsonPath = path.resolve(projectDir, 'package.json')
|
||||
try {
|
||||
const packageObj = await fse.readJson(packageJsonPath)
|
||||
packageObj.dependencies.payload = payloadVersion
|
||||
await fse.writeJson(packageJsonPath, packageObj, { spaces: 2 })
|
||||
} catch (err) {
|
||||
warning(
|
||||
'Unable to write Payload version to package.json. Please update your package.json manually.',
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export async function createProject(
|
||||
args: CliArgs,
|
||||
projectDir: string,
|
||||
template: ProjectTemplate,
|
||||
packageManager: string,
|
||||
): Promise<void> {
|
||||
createProjectDir(projectDir)
|
||||
const templateDir = path.resolve(__dirname, `../templates/${template.name}`)
|
||||
|
||||
console.log(
|
||||
`\n Creating a new Payload app in ${chalk.green(path.resolve(projectDir))}\n`,
|
||||
)
|
||||
|
||||
if (template.type === 'starter') {
|
||||
const emitter = degit(template.url)
|
||||
await emitter.clone(projectDir)
|
||||
} else {
|
||||
try {
|
||||
await fse.copy(templateDir, projectDir, { recursive: true })
|
||||
success('Project directory created')
|
||||
} catch (err) {
|
||||
const msg =
|
||||
'Unable to copy template files. Please check template name or directory permissions.'
|
||||
error(msg)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
const spinner = ora('Checking latest Payload version...').start()
|
||||
await updatePayloadVersion(projectDir)
|
||||
|
||||
spinner.text = 'Installing dependencies...'
|
||||
const result = await installDeps(args, projectDir, packageManager)
|
||||
spinner.stop()
|
||||
spinner.clear()
|
||||
if (result) {
|
||||
success('Dependencies installed')
|
||||
} else {
|
||||
error('Error installing dependencies')
|
||||
}
|
||||
}
|
||||
27
src/lib/getDatabaseConnection.ts
Normal file
27
src/lib/getDatabaseConnection.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import prompts from 'prompts'
|
||||
import slugify from '@sindresorhus/slugify'
|
||||
import type { CliArgs } from '../types'
|
||||
|
||||
export async function getDatabaseConnection(
|
||||
args: CliArgs,
|
||||
projectName: string,
|
||||
): Promise<string> {
|
||||
if (args['--db']) return args['--db']
|
||||
|
||||
const response = await prompts(
|
||||
{
|
||||
type: 'text',
|
||||
name: 'value',
|
||||
message: 'Enter MongoDB connection',
|
||||
initial: `mongodb://localhost/${slugify(projectName)}`,
|
||||
validate: (value: string) => value.length,
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
return response.value
|
||||
}
|
||||
22
src/lib/getPayloadSecret.ts
Normal file
22
src/lib/getPayloadSecret.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import prompts from 'prompts'
|
||||
import type { CliArgs } from '../types'
|
||||
|
||||
export async function getPayloadSecret(args: CliArgs): Promise<string> {
|
||||
if (args['--secret']) return args['--secret']
|
||||
|
||||
const response = await prompts(
|
||||
{
|
||||
type: 'password',
|
||||
name: 'value',
|
||||
message: 'Enter a long, complex string for Payload’s encryption key',
|
||||
validate: (value: string) => value.length,
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
return response.value
|
||||
}
|
||||
32
src/lib/parseLanguage.ts
Normal file
32
src/lib/parseLanguage.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import prompts from 'prompts'
|
||||
import type { CliArgs } from '../types'
|
||||
|
||||
export async function parseLanguage(args: CliArgs): Promise<string> {
|
||||
if (args['--template']) return args['--template']
|
||||
|
||||
const response = await prompts(
|
||||
{
|
||||
type: 'select',
|
||||
name: 'value',
|
||||
message: 'Choose language',
|
||||
choices: [
|
||||
{
|
||||
title: 'javascript',
|
||||
value: 'js',
|
||||
},
|
||||
{
|
||||
title: 'typescript',
|
||||
value: 'ts',
|
||||
},
|
||||
],
|
||||
validate: (value: string) => value.length,
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
return response.value
|
||||
}
|
||||
23
src/lib/parseProjectName.ts
Normal file
23
src/lib/parseProjectName.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import prompts from 'prompts'
|
||||
import type { CliArgs } from '../types'
|
||||
|
||||
export async function parseProjectName(args: CliArgs): Promise<string> {
|
||||
if (args['--name']) return args['--name']
|
||||
if (args._[0]) return args._[0]
|
||||
|
||||
const response = await prompts(
|
||||
{
|
||||
type: 'text',
|
||||
name: 'value',
|
||||
message: 'Project name?',
|
||||
validate: (value: string) => value.length,
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
return response.value
|
||||
}
|
||||
45
src/lib/parseTemplate.ts
Normal file
45
src/lib/parseTemplate.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import prompts from 'prompts'
|
||||
import type { CliArgs, ProjectTemplate } from '../types'
|
||||
import { setTags } from '../utils/usage'
|
||||
|
||||
export async function parseTemplate(
|
||||
args: CliArgs,
|
||||
validTemplates: ProjectTemplate[],
|
||||
language: string,
|
||||
): Promise<ProjectTemplate> {
|
||||
if (args['--template']) {
|
||||
const templateName = args['--template']
|
||||
const template = validTemplates.find(template => template.name === templateName)
|
||||
if (!template) throw new Error('Invalid template given')
|
||||
setTags({ template: template.name })
|
||||
return template
|
||||
}
|
||||
|
||||
const filteredTemplates = validTemplates
|
||||
.filter(d => d.name.startsWith(language))
|
||||
.map(t => t.name.replace(`${language}-`, ''))
|
||||
|
||||
const response = await prompts(
|
||||
{
|
||||
type: 'select',
|
||||
name: 'value',
|
||||
message: 'Choose project template',
|
||||
choices: filteredTemplates.map(p => {
|
||||
return { title: p, value: `${language}-${p}` }
|
||||
}),
|
||||
validate: (value: string) => value.length,
|
||||
},
|
||||
{
|
||||
onCancel: () => {
|
||||
process.exit(0)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
// const template = `${language}-${response.value}`
|
||||
const template = validTemplates.find(t => t.name === response.value)
|
||||
if (!template) throw new Error('Template is undefined')
|
||||
setTags({ template: template.name })
|
||||
|
||||
return template
|
||||
}
|
||||
30
src/lib/templates.ts
Normal file
30
src/lib/templates.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
import { error, info } from '../utils/log'
|
||||
import type { ProjectTemplate } from '../types'
|
||||
|
||||
export async function validateTemplate(templateName: string): Promise<boolean> {
|
||||
const validTemplates = await getValidTemplates()
|
||||
if (!validTemplates.map(t => t.name).includes(templateName)) {
|
||||
error(`'${templateName}' is not a valid template.`)
|
||||
info(`Valid templates: ${validTemplates.join(', ')}`)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export async function getValidTemplates(): Promise<ProjectTemplate[]> {
|
||||
const templateDir = path.resolve(__dirname, '../templates')
|
||||
const dirs = getDirectories(templateDir)
|
||||
|
||||
const templates: ProjectTemplate[] = dirs.map(name => {
|
||||
return { name, type: 'static' }
|
||||
})
|
||||
return templates
|
||||
}
|
||||
|
||||
function getDirectories(dir: string) {
|
||||
return fs.readdirSync(dir).filter(file => {
|
||||
return fs.statSync(dir + '/' + file).isDirectory()
|
||||
})
|
||||
}
|
||||
21
src/lib/writeEnvFile.ts
Normal file
21
src/lib/writeEnvFile.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import slugify from '@sindresorhus/slugify'
|
||||
import fs from 'fs-extra'
|
||||
import { error, success } from '../utils/log'
|
||||
|
||||
export async function writeEnvFile(
|
||||
projectName: string,
|
||||
databaseUri: string,
|
||||
payloadSecret: string,
|
||||
): Promise<void> {
|
||||
const content = `MONGODB_URI=${databaseUri}\nPAYLOAD_SECRET=${payloadSecret}`
|
||||
|
||||
try {
|
||||
const projectDir = `./${slugify(projectName)}`
|
||||
await fs.outputFile(`${projectDir}/.env`, content)
|
||||
success('.env file created')
|
||||
} catch (err) {
|
||||
error('Unable to write .env file')
|
||||
error(err)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
92
src/main.ts
Normal file
92
src/main.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import slugify from '@sindresorhus/slugify'
|
||||
import arg from 'arg'
|
||||
import commandExists from 'command-exists'
|
||||
import { createProject } from './lib/createProject'
|
||||
import { getDatabaseConnection } from './lib/getDatabaseConnection'
|
||||
import { getPayloadSecret } from './lib/getPayloadSecret'
|
||||
import { parseLanguage } from './lib/parseLanguage'
|
||||
import { parseProjectName } from './lib/parseProjectName'
|
||||
import { parseTemplate } from './lib/parseTemplate'
|
||||
import { getValidTemplates, validateTemplate } from './lib/templates'
|
||||
import { writeEnvFile } from './lib/writeEnvFile'
|
||||
import type { CliArgs } from './types'
|
||||
import { success } from './utils/log'
|
||||
import { helpMessage, successMessage, welcomeMessage } from './utils/messages'
|
||||
import { setTags } from './utils/usage'
|
||||
|
||||
export class Main {
|
||||
args: CliArgs
|
||||
|
||||
constructor() {
|
||||
this.args = arg(
|
||||
{
|
||||
'--help': Boolean,
|
||||
'--name': String,
|
||||
'--template': String,
|
||||
'--db': String,
|
||||
'--secret': String,
|
||||
'--use-npm': Boolean,
|
||||
'--no-deps': Boolean,
|
||||
'--dry-run': Boolean,
|
||||
|
||||
'-h': '--help',
|
||||
'-n': '--name',
|
||||
'-t': '--template',
|
||||
},
|
||||
{ permissive: true },
|
||||
)
|
||||
}
|
||||
|
||||
async init(): Promise<void> {
|
||||
try {
|
||||
if (this.args['--help']) {
|
||||
console.log(await helpMessage())
|
||||
process.exit(0)
|
||||
}
|
||||
const templateArg = this.args['--template']
|
||||
if (templateArg) {
|
||||
const valid = await validateTemplate(templateArg)
|
||||
if (!valid) {
|
||||
console.log(await helpMessage())
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
console.log(welcomeMessage)
|
||||
const projectName = await parseProjectName(this.args)
|
||||
const language = await parseLanguage(this.args)
|
||||
const validTemplates = await getValidTemplates()
|
||||
const template = await parseTemplate(this.args, validTemplates, language)
|
||||
const databaseUri = await getDatabaseConnection(this.args, projectName)
|
||||
const payloadSecret = await getPayloadSecret(this.args)
|
||||
const projectDir = `./${slugify(projectName)}`
|
||||
const packageManager = await getPackageManager(this.args)
|
||||
|
||||
if (!this.args['--dry-run']) {
|
||||
await createProject(this.args, projectDir, template, packageManager)
|
||||
await writeEnvFile(projectName, databaseUri, payloadSecret)
|
||||
}
|
||||
|
||||
success('Payload project successfully created')
|
||||
console.log(await successMessage(projectDir, packageManager))
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getPackageManager(args: CliArgs): Promise<string> {
|
||||
let packageManager: string
|
||||
if (args['--use-npm']) {
|
||||
packageManager = 'npm'
|
||||
} else {
|
||||
try {
|
||||
await commandExists('yarn')
|
||||
packageManager = 'yarn'
|
||||
} catch (error) {
|
||||
packageManager = 'npm'
|
||||
}
|
||||
}
|
||||
setTags({ package_manager: packageManager })
|
||||
return packageManager
|
||||
}
|
||||
15
src/templates/js-blank/collections/Examples.js
Normal file
15
src/templates/js-blank/collections/Examples.js
Normal file
@@ -0,0 +1,15 @@
|
||||
// Example Collection - For reference only, this must be added to payload.config.js to be used.
|
||||
const Examples = {
|
||||
slug: 'examples',
|
||||
admin: {
|
||||
useAsTitle: 'someField',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'someField',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export default Examples;
|
||||
16
src/templates/js-blank/collections/Users.js
Normal file
16
src/templates/js-blank/collections/Users.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const Users = {
|
||||
slug: 'users',
|
||||
auth: true,
|
||||
admin: {
|
||||
useAsTitle: 'email',
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
// Email added by default
|
||||
// Add more fields as needed
|
||||
],
|
||||
};
|
||||
|
||||
export default Users;
|
||||
3
src/templates/js-blank/nodemon.json
Normal file
3
src/templates/js-blank/nodemon.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"exec": "node server.js"
|
||||
}
|
||||
20
src/templates/js-blank/package.json
Normal file
20
src/templates/js-blank/package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "payload-starter-javascript",
|
||||
"description": "Blank template - no collections",
|
||||
"version": "1.0.0",
|
||||
"main": "server.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "nodemon",
|
||||
"build": "payload build",
|
||||
"serve": "NODE_ENV=production node server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"payload": "0.1.145",
|
||||
"dotenv": "^8.2.0",
|
||||
"express": "^4.17.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.6"
|
||||
}
|
||||
}
|
||||
15
src/templates/js-blank/payload.config.js
Normal file
15
src/templates/js-blank/payload.config.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import { buildConfig } from 'payload/config';
|
||||
import Examples from './collections/Examples';
|
||||
import Users from './collections/Users';
|
||||
|
||||
export default buildConfig({
|
||||
serverURL: 'http://localhost:3000',
|
||||
admin: {
|
||||
user: Users.slug,
|
||||
},
|
||||
collections: [
|
||||
Users,
|
||||
// Add Collections here
|
||||
// Examples
|
||||
],
|
||||
});
|
||||
19
src/templates/js-blank/server.js
Normal file
19
src/templates/js-blank/server.js
Normal file
@@ -0,0 +1,19 @@
|
||||
const express = require('express');
|
||||
const payload = require('payload');
|
||||
|
||||
require('dotenv').config();
|
||||
const app = express();
|
||||
|
||||
// Initialize Payload
|
||||
payload.init({
|
||||
secret: process.env.PAYLOAD_SECRET,
|
||||
mongoURL: process.env.MONGODB_URI,
|
||||
express: app,
|
||||
onInit: () => {
|
||||
payload.logger.info(`Payload Admin URL: ${payload.getAdminURL()}`);
|
||||
},
|
||||
});
|
||||
|
||||
// Add your own express routes here
|
||||
|
||||
app.listen(3000);
|
||||
18
src/templates/js-blog/collections/Categories.js
Normal file
18
src/templates/js-blog/collections/Categories.js
Normal file
@@ -0,0 +1,18 @@
|
||||
const Categories = {
|
||||
slug: 'categories',
|
||||
admin: {
|
||||
useAsTitle: 'name',
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'name',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
timestamps: false,
|
||||
}
|
||||
|
||||
export default Categories;
|
||||
60
src/templates/js-blog/collections/Posts.js
Normal file
60
src/templates/js-blog/collections/Posts.js
Normal file
@@ -0,0 +1,60 @@
|
||||
const Posts = {
|
||||
slug: 'posts',
|
||||
admin: {
|
||||
defaultColumns: ['title', 'author', 'category', 'tags', 'status'],
|
||||
useAsTitle: 'title',
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'author',
|
||||
type: 'relationship',
|
||||
relationTo: 'users',
|
||||
},
|
||||
{
|
||||
name: 'publishedDate',
|
||||
type: 'date',
|
||||
},
|
||||
{
|
||||
name: 'category',
|
||||
type: 'relationship',
|
||||
relationTo: 'categories'
|
||||
},
|
||||
{
|
||||
name: 'tags',
|
||||
type: 'relationship',
|
||||
relationTo: 'tags',
|
||||
hasMany: true,
|
||||
},
|
||||
{
|
||||
name: 'content',
|
||||
type: 'richText'
|
||||
},
|
||||
{
|
||||
name: 'status',
|
||||
type: 'select',
|
||||
options: [
|
||||
{
|
||||
value: 'draft',
|
||||
label: 'Draft',
|
||||
},
|
||||
{
|
||||
value: 'published',
|
||||
label: 'Published',
|
||||
},
|
||||
],
|
||||
defaultValue: 'draft',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
}
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
export default Posts;
|
||||
18
src/templates/js-blog/collections/Tags.js
Normal file
18
src/templates/js-blog/collections/Tags.js
Normal file
@@ -0,0 +1,18 @@
|
||||
const Tags = {
|
||||
slug: 'tags',
|
||||
admin: {
|
||||
useAsTitle: 'name',
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'name',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
timestamps: false,
|
||||
}
|
||||
|
||||
export default Tags;
|
||||
30
src/templates/js-blog/collections/Users.js
Normal file
30
src/templates/js-blog/collections/Users.js
Normal file
@@ -0,0 +1,30 @@
|
||||
const onlyNameIfPublic = ({ req: { user }, doc }) => {
|
||||
// Only return name if not logged in
|
||||
if (!user) {
|
||||
return { name: doc.name };
|
||||
}
|
||||
return doc;
|
||||
};
|
||||
|
||||
const Users = {
|
||||
slug: 'users',
|
||||
auth: true,
|
||||
admin: {
|
||||
useAsTitle: 'email',
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
hooks: {
|
||||
beforeRead: [onlyNameIfPublic]
|
||||
},
|
||||
fields: [
|
||||
// Email added by default
|
||||
{
|
||||
name: 'name',
|
||||
type: 'text',
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
export default Users;
|
||||
3
src/templates/js-blog/nodemon.json
Normal file
3
src/templates/js-blog/nodemon.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"exec": "node server.js"
|
||||
}
|
||||
20
src/templates/js-blog/package.json
Normal file
20
src/templates/js-blog/package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "payload-blog",
|
||||
"description": "Blog template",
|
||||
"version": "1.0.0",
|
||||
"main": "server.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "nodemon",
|
||||
"build": "payload build",
|
||||
"serve": "NODE_ENV=production node server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"payload": "0.1.145",
|
||||
"dotenv": "^8.2.0",
|
||||
"express": "^4.17.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.6"
|
||||
}
|
||||
}
|
||||
18
src/templates/js-blog/payload.config.js
Normal file
18
src/templates/js-blog/payload.config.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import { buildConfig } from 'payload/config';
|
||||
import Categories from './collections/Categories';
|
||||
import Posts from './collections/Posts';
|
||||
import Tags from './collections/Tags';
|
||||
import Users from './collections/Users';
|
||||
|
||||
export default buildConfig({
|
||||
serverURL: 'http://localhost:3000',
|
||||
admin: {
|
||||
user: Users.slug,
|
||||
},
|
||||
collections: [
|
||||
Categories,
|
||||
Posts,
|
||||
Tags,
|
||||
Users,
|
||||
],
|
||||
});
|
||||
19
src/templates/js-blog/server.js
Normal file
19
src/templates/js-blog/server.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import express from 'express'
|
||||
import payload from 'payload'
|
||||
|
||||
require('dotenv').config()
|
||||
const app = express()
|
||||
|
||||
// Initialize Payload
|
||||
payload.init({
|
||||
secret: process.env.PAYLOAD_SECRET,
|
||||
mongoURL: process.env.MONGODB_URI,
|
||||
express: app,
|
||||
onInit: () => {
|
||||
payload.logger.info(`Payload Admin URL: ${payload.getAdminURL()}`)
|
||||
},
|
||||
})
|
||||
|
||||
// Add your own express routes here
|
||||
|
||||
app.listen(3000)
|
||||
36
src/templates/js-todo/collections/TodoLists.js
Normal file
36
src/templates/js-todo/collections/TodoLists.js
Normal file
@@ -0,0 +1,36 @@
|
||||
const Todo = {
|
||||
slug: 'todos',
|
||||
admin: {
|
||||
defaultColumns: ['listName', 'tasks', 'updatedAt'],
|
||||
useAsTitle: 'listName',
|
||||
},
|
||||
access: {
|
||||
create: () => true,
|
||||
read: () => true,
|
||||
update: () => true,
|
||||
delete: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'listName',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'tasks',
|
||||
type: 'array',
|
||||
fields: [
|
||||
{
|
||||
name: 'name',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'complete',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export default Todo;
|
||||
16
src/templates/js-todo/collections/Users.js
Normal file
16
src/templates/js-todo/collections/Users.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const Users = {
|
||||
slug: 'users',
|
||||
auth: true,
|
||||
admin: {
|
||||
useAsTitle: 'email',
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
// Email added by default
|
||||
// Add more fields as needed
|
||||
],
|
||||
};
|
||||
|
||||
export default Users;
|
||||
3
src/templates/js-todo/nodemon.json
Normal file
3
src/templates/js-todo/nodemon.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"exec": "node server.js"
|
||||
}
|
||||
20
src/templates/js-todo/package.json
Normal file
20
src/templates/js-todo/package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "payload-starter-javascript",
|
||||
"description": "Simple to-do list example",
|
||||
"version": "1.0.0",
|
||||
"main": "server.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "nodemon",
|
||||
"build": "payload build",
|
||||
"serve": "NODE_ENV=production node server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"payload": "0.1.145",
|
||||
"dotenv": "^8.2.0",
|
||||
"express": "^4.17.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.6"
|
||||
}
|
||||
}
|
||||
14
src/templates/js-todo/payload.config.js
Normal file
14
src/templates/js-todo/payload.config.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { buildConfig } from 'payload/config';
|
||||
import TodoLists from './collections/TodoLists';
|
||||
import Users from './collections/Users';
|
||||
|
||||
export default buildConfig({
|
||||
serverURL: 'http://localhost:3000',
|
||||
admin: {
|
||||
user: Users.slug,
|
||||
},
|
||||
collections: [
|
||||
TodoLists,
|
||||
Users,
|
||||
],
|
||||
});
|
||||
19
src/templates/js-todo/server.js
Normal file
19
src/templates/js-todo/server.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import express from 'express'
|
||||
import payload from 'payload'
|
||||
|
||||
require('dotenv').config()
|
||||
const app = express()
|
||||
|
||||
// Initialize Payload
|
||||
payload.init({
|
||||
secret: process.env.PAYLOAD_SECRET,
|
||||
mongoURL: process.env.MONGODB_URI,
|
||||
express: app,
|
||||
onInit: () => {
|
||||
payload.logger.info(`Payload Admin URL: ${payload.getAdminURL()}`)
|
||||
},
|
||||
})
|
||||
|
||||
// Add your own express routes here
|
||||
|
||||
app.listen(3000)
|
||||
4
src/templates/ts-blank/nodemon.json
Normal file
4
src/templates/ts-blank/nodemon.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"ext": "ts",
|
||||
"exec": "ts-node src/server.ts"
|
||||
}
|
||||
26
src/templates/ts-blank/package.json
Normal file
26
src/templates/ts-blank/package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "payload-starter-typescript",
|
||||
"description": "Blank template - no collections",
|
||||
"version": "1.0.0",
|
||||
"main": "dist/server.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts nodemon",
|
||||
"build:payload": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload build",
|
||||
"build:server": "tsc",
|
||||
"build": "yarn build:payload && yarn build:server",
|
||||
"serve": "cross-env PAYLOAD_CONFIG_PATH=dist/payload.config.js NODE_ENV=production node dist/server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"payload": "0.1.145",
|
||||
"dotenv": "^8.2.0",
|
||||
"express": "^4.17.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.9",
|
||||
"cross-env": "^7.0.3",
|
||||
"nodemon": "^2.0.6",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.1.3"
|
||||
}
|
||||
}
|
||||
17
src/templates/ts-blank/src/collections/Examples.ts
Normal file
17
src/templates/ts-blank/src/collections/Examples.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
|
||||
// Example Collection - For reference only, this must be added to payload.config.ts to be used.
|
||||
const Examples: CollectionConfig = {
|
||||
slug: 'examples',
|
||||
admin: {
|
||||
useAsTitle: 'someField',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'someField',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export default Examples;
|
||||
18
src/templates/ts-blank/src/collections/Users.ts
Normal file
18
src/templates/ts-blank/src/collections/Users.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
|
||||
const Users: CollectionConfig = {
|
||||
slug: 'users',
|
||||
auth: true,
|
||||
admin: {
|
||||
useAsTitle: 'email',
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
// Email added by default
|
||||
// Add more fields as needed
|
||||
],
|
||||
};
|
||||
|
||||
export default Users;
|
||||
15
src/templates/ts-blank/src/payload.config.ts
Normal file
15
src/templates/ts-blank/src/payload.config.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { buildConfig } from 'payload/config';
|
||||
// import Examples from './collections/Examples';
|
||||
import Users from './collections/Users';
|
||||
|
||||
export default buildConfig({
|
||||
serverURL: 'http://localhost:3000',
|
||||
admin: {
|
||||
user: Users.slug,
|
||||
},
|
||||
collections: [
|
||||
Users,
|
||||
// Add Collections here
|
||||
// Examples,
|
||||
],
|
||||
});
|
||||
19
src/templates/ts-blank/src/server.ts
Normal file
19
src/templates/ts-blank/src/server.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import express from 'express';
|
||||
import payload from 'payload';
|
||||
|
||||
require('dotenv').config();
|
||||
const app = express();
|
||||
|
||||
// Initialize Payload
|
||||
payload.init({
|
||||
secret: process.env.PAYLOAD_SECRET,
|
||||
mongoURL: process.env.MONGODB_URI,
|
||||
express: app,
|
||||
onInit: () => {
|
||||
payload.logger.info(`Payload Admin URL: ${payload.getAdminURL()}`);
|
||||
},
|
||||
});
|
||||
|
||||
// Add your own express routes here
|
||||
|
||||
app.listen(3000);
|
||||
19
src/templates/ts-blank/tsconfig.json
Normal file
19
src/templates/ts-blank/tsconfig.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"strict": false,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"jsx": "react",
|
||||
},
|
||||
"ts-node": {
|
||||
"transpileOnly": true
|
||||
}
|
||||
}
|
||||
4
src/templates/ts-blog/nodemon.json
Normal file
4
src/templates/ts-blog/nodemon.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"ext": "ts",
|
||||
"exec": "ts-node src/server.ts"
|
||||
}
|
||||
26
src/templates/ts-blog/package.json
Normal file
26
src/templates/ts-blog/package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "payload-blog-typescript",
|
||||
"description": "Blog template",
|
||||
"version": "1.0.0",
|
||||
"main": "dist/server.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts nodemon",
|
||||
"build:payload": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload build",
|
||||
"build:server": "tsc",
|
||||
"build": "yarn build:payload && yarn build:server",
|
||||
"serve": "cross-env PAYLOAD_CONFIG_PATH=dist/payload.config.js NODE_ENV=production node dist/server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"payload": "0.1.144",
|
||||
"dotenv": "^8.2.0",
|
||||
"express": "^4.17.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.9",
|
||||
"cross-env": "^7.0.3",
|
||||
"nodemon": "^2.0.6",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.1.3"
|
||||
}
|
||||
}
|
||||
20
src/templates/ts-blog/src/collections/Categories.ts
Normal file
20
src/templates/ts-blog/src/collections/Categories.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
|
||||
const Categories: CollectionConfig = {
|
||||
slug: 'categories',
|
||||
admin: {
|
||||
useAsTitle: 'name',
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'name',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
timestamps: false,
|
||||
}
|
||||
|
||||
export default Categories;
|
||||
62
src/templates/ts-blog/src/collections/Posts.ts
Normal file
62
src/templates/ts-blog/src/collections/Posts.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
|
||||
const Posts: CollectionConfig = {
|
||||
slug: 'posts',
|
||||
admin: {
|
||||
defaultColumns: ['title', 'author', 'category', 'tags', 'status'],
|
||||
useAsTitle: 'title',
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'author',
|
||||
type: 'relationship',
|
||||
relationTo: 'users',
|
||||
},
|
||||
{
|
||||
name: 'publishedDate',
|
||||
type: 'date',
|
||||
},
|
||||
{
|
||||
name: 'category',
|
||||
type: 'relationship',
|
||||
relationTo: 'categories'
|
||||
},
|
||||
{
|
||||
name: 'tags',
|
||||
type: 'relationship',
|
||||
relationTo: 'tags',
|
||||
hasMany: true,
|
||||
},
|
||||
{
|
||||
name: 'content',
|
||||
type: 'richText'
|
||||
},
|
||||
{
|
||||
name: 'status',
|
||||
type: 'select',
|
||||
options: [
|
||||
{
|
||||
value: 'draft',
|
||||
label: 'Draft',
|
||||
},
|
||||
{
|
||||
value: 'published',
|
||||
label: 'Published',
|
||||
},
|
||||
],
|
||||
defaultValue: 'draft',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
}
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
export default Posts;
|
||||
20
src/templates/ts-blog/src/collections/Tags.ts
Normal file
20
src/templates/ts-blog/src/collections/Tags.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
|
||||
const Tags: CollectionConfig = {
|
||||
slug: 'tags',
|
||||
admin: {
|
||||
useAsTitle: 'name',
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'name',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
timestamps: false,
|
||||
}
|
||||
|
||||
export default Tags;
|
||||
33
src/templates/ts-blog/src/collections/Users.ts
Normal file
33
src/templates/ts-blog/src/collections/Users.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { BeforeReadHook } from 'payload/dist/collections/config/types';
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
|
||||
const onlyNameIfPublic: BeforeReadHook = ({ req: { user }, doc }) => {
|
||||
// Only return name if not logged in
|
||||
if (!user) {
|
||||
return { name: doc.name };
|
||||
}
|
||||
return doc;
|
||||
};
|
||||
|
||||
const Users: CollectionConfig = {
|
||||
slug: 'users',
|
||||
auth: true,
|
||||
admin: {
|
||||
useAsTitle: 'email',
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
hooks: {
|
||||
beforeRead: [onlyNameIfPublic]
|
||||
},
|
||||
fields: [
|
||||
// Email added by default
|
||||
{
|
||||
name: 'name',
|
||||
type: 'text',
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
export default Users;
|
||||
18
src/templates/ts-blog/src/payload.config.ts
Normal file
18
src/templates/ts-blog/src/payload.config.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { buildConfig } from 'payload/config';
|
||||
import Categories from './collections/Categories';
|
||||
import Posts from './collections/Posts';
|
||||
import Tags from './collections/Tags';
|
||||
import Users from './collections/Users';
|
||||
|
||||
export default buildConfig({
|
||||
serverURL: 'http://localhost:3000',
|
||||
admin: {
|
||||
user: Users.slug,
|
||||
},
|
||||
collections: [
|
||||
Categories,
|
||||
Posts,
|
||||
Tags,
|
||||
Users,
|
||||
],
|
||||
});
|
||||
19
src/templates/ts-blog/src/server.ts
Normal file
19
src/templates/ts-blog/src/server.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import express from 'express';
|
||||
import payload from 'payload';
|
||||
|
||||
require('dotenv').config();
|
||||
const app = express();
|
||||
|
||||
// Initialize Payload
|
||||
payload.init({
|
||||
secret: process.env.PAYLOAD_SECRET,
|
||||
mongoURL: process.env.MONGODB_URI,
|
||||
express: app,
|
||||
onInit: () => {
|
||||
payload.logger.info(`Payload Admin URL: ${payload.getAdminURL()}`);
|
||||
},
|
||||
});
|
||||
|
||||
// Add your own express routes here
|
||||
|
||||
app.listen(3000);
|
||||
19
src/templates/ts-blog/tsconfig.json
Normal file
19
src/templates/ts-blog/tsconfig.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"strict": false,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"jsx": "react",
|
||||
},
|
||||
"ts-node": {
|
||||
"transpileOnly": true
|
||||
}
|
||||
}
|
||||
4
src/templates/ts-todo/nodemon.json
Normal file
4
src/templates/ts-todo/nodemon.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"ext": "ts",
|
||||
"exec": "ts-node src/server.ts"
|
||||
}
|
||||
26
src/templates/ts-todo/package.json
Normal file
26
src/templates/ts-todo/package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "payload-starter-typescript",
|
||||
"description": "Simple to-do list example",
|
||||
"version": "1.0.0",
|
||||
"main": "dist/server.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts nodemon",
|
||||
"build:payload": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload build",
|
||||
"build:server": "tsc",
|
||||
"build": "yarn build:payload && yarn build:server",
|
||||
"serve": "cross-env PAYLOAD_CONFIG_PATH=dist/payload.config.js NODE_ENV=production node dist/server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"payload": "0.1.145",
|
||||
"dotenv": "^8.2.0",
|
||||
"express": "^4.17.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.9",
|
||||
"cross-env": "^7.0.3",
|
||||
"nodemon": "^2.0.6",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.1.3"
|
||||
}
|
||||
}
|
||||
38
src/templates/ts-todo/src/collections/TodoLists.ts
Normal file
38
src/templates/ts-todo/src/collections/TodoLists.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
|
||||
const Todo: CollectionConfig = {
|
||||
slug: 'todos',
|
||||
admin: {
|
||||
defaultColumns: ['listName', 'tasks', 'updatedAt'],
|
||||
useAsTitle: 'listName',
|
||||
},
|
||||
access: {
|
||||
create: () => true,
|
||||
read: () => true,
|
||||
update: () => true,
|
||||
delete: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'listName',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'tasks',
|
||||
type: 'array',
|
||||
fields: [
|
||||
{
|
||||
name: 'name',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'complete',
|
||||
type: 'checkbox',
|
||||
defaultValue: false,
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export default Todo;
|
||||
18
src/templates/ts-todo/src/collections/Users.ts
Normal file
18
src/templates/ts-todo/src/collections/Users.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
|
||||
const Users: CollectionConfig = {
|
||||
slug: 'users',
|
||||
auth: true,
|
||||
admin: {
|
||||
useAsTitle: 'email',
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
// Email added by default
|
||||
// Add more fields as needed
|
||||
],
|
||||
};
|
||||
|
||||
export default Users;
|
||||
14
src/templates/ts-todo/src/payload.config.ts
Normal file
14
src/templates/ts-todo/src/payload.config.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { buildConfig } from 'payload/config';
|
||||
import TodoLists from './collections/TodoLists';
|
||||
import Users from './collections/Users';
|
||||
|
||||
export default buildConfig({
|
||||
serverURL: 'http://localhost:3000',
|
||||
admin: {
|
||||
user: Users.slug,
|
||||
},
|
||||
collections: [
|
||||
TodoLists,
|
||||
Users,
|
||||
],
|
||||
});
|
||||
19
src/templates/ts-todo/src/server.ts
Normal file
19
src/templates/ts-todo/src/server.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import express from 'express';
|
||||
import payload from 'payload';
|
||||
|
||||
require('dotenv').config();
|
||||
const app = express();
|
||||
|
||||
// Initialize Payload
|
||||
payload.init({
|
||||
secret: process.env.PAYLOAD_SECRET,
|
||||
mongoURL: process.env.MONGODB_URI,
|
||||
express: app,
|
||||
onInit: () => {
|
||||
payload.logger.info(`Payload Admin URL: ${payload.getAdminURL()}`);
|
||||
},
|
||||
});
|
||||
|
||||
// Add your own express routes here
|
||||
|
||||
app.listen(3000);
|
||||
19
src/templates/ts-todo/tsconfig.json
Normal file
19
src/templates/ts-todo/tsconfig.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"strict": false,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"jsx": "react",
|
||||
},
|
||||
"ts-node": {
|
||||
"transpileOnly": true
|
||||
}
|
||||
}
|
||||
30
src/types.ts
Normal file
30
src/types.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import type arg from 'arg'
|
||||
|
||||
export type Args = {
|
||||
'--help': BooleanConstructor
|
||||
'--name': StringConstructor
|
||||
'--template': StringConstructor
|
||||
'--db': StringConstructor
|
||||
'--secret': StringConstructor
|
||||
'--use-npm': BooleanConstructor
|
||||
'--no-deps': BooleanConstructor
|
||||
'--dry-run': BooleanConstructor
|
||||
'-h': string
|
||||
'-n': string
|
||||
'-t': string
|
||||
}
|
||||
|
||||
export type CliArgs = arg.Result<Args>
|
||||
|
||||
export type ProjectTemplate = StaticTemplate | GitTemplate
|
||||
|
||||
export type StaticTemplate = {
|
||||
name: string
|
||||
type: 'static'
|
||||
}
|
||||
|
||||
export type GitTemplate = {
|
||||
name: string
|
||||
type: 'starter'
|
||||
url: string
|
||||
}
|
||||
18
src/utils/log.ts
Normal file
18
src/utils/log.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import chalk from 'chalk'
|
||||
import figures from 'figures'
|
||||
|
||||
export const success = (message: string): void => {
|
||||
console.log(chalk.green(figures.tick) + ' ' + chalk.bold(message))
|
||||
}
|
||||
|
||||
export const warning = (message: string): void => {
|
||||
console.log(chalk.yellow('? ') + chalk.bold(message))
|
||||
}
|
||||
|
||||
export const info = (message: string): void => {
|
||||
console.log(chalk.yellow(figures.info) + ' ' + chalk.bold(message))
|
||||
}
|
||||
|
||||
export const error = (message: string): void => {
|
||||
console.log(chalk.red(figures.cross) + ' ' + chalk.bold(message))
|
||||
}
|
||||
52
src/utils/messages.ts
Normal file
52
src/utils/messages.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import chalk from 'chalk'
|
||||
import figures from 'figures'
|
||||
import terminalLink from 'terminal-link'
|
||||
import { getValidTemplates } from '../lib/templates'
|
||||
|
||||
const header = (message: string) =>
|
||||
chalk.yellow(figures.star) + ' ' + chalk.bold(message)
|
||||
|
||||
export const welcomeMessage = chalk`
|
||||
{green Welcome to Payload. Let's create a project! }
|
||||
`
|
||||
|
||||
export async function helpMessage(): Promise<string> {
|
||||
const validTemplates = await getValidTemplates()
|
||||
return chalk`
|
||||
{bold USAGE}
|
||||
|
||||
{dim $} {bold npx create-payload-app}
|
||||
|
||||
{bold OPTIONS}
|
||||
|
||||
--name {underline my-payload-app} Set project name
|
||||
--template {underline template_name} Choose specific template
|
||||
|
||||
{dim Available templates: ${validTemplates.join(', ')}}
|
||||
|
||||
--use-npm Use npm to install dependencies
|
||||
--no-deps Do not install any dependencies
|
||||
--help Show help
|
||||
`
|
||||
}
|
||||
|
||||
export function successMessage(projectDir: string, packageManager: string): string {
|
||||
return `
|
||||
${header('Launch Application:')}
|
||||
|
||||
- cd ${projectDir}
|
||||
- ${packageManager === 'yarn' ? 'yarn' : 'npm run'} dev
|
||||
|
||||
${header('Documentation:')}
|
||||
|
||||
- ${terminalLink(
|
||||
'Getting Started',
|
||||
'https://payloadcms.com/docs/getting-started/what-is-payload',
|
||||
)}
|
||||
- ${terminalLink(
|
||||
'Configuration',
|
||||
'https://payloadcms.com/docs/configuration/overview',
|
||||
)}
|
||||
|
||||
`
|
||||
}
|
||||
32
src/utils/usage.ts
Normal file
32
src/utils/usage.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import * as Sentry from '@sentry/node'
|
||||
import type { Primitive, Transaction } from '@sentry/types'
|
||||
import os from 'os'
|
||||
|
||||
type SentryTags = { [key: string]: Primitive }
|
||||
|
||||
export const init = (): Transaction => {
|
||||
Sentry.init({
|
||||
dsn: 'https://139de3d0197f464082d5715a0c48a497@o589961.ingest.sentry.io/5739829',
|
||||
tracesSampleRate: 1.0,
|
||||
})
|
||||
|
||||
Sentry.setTags({
|
||||
os_type: os.type(),
|
||||
os_platform: os.platform(),
|
||||
os_release: os.release(),
|
||||
node_version: process.version,
|
||||
})
|
||||
|
||||
return Sentry.startTransaction({
|
||||
op: 'create-payload-app',
|
||||
name: 'New Project',
|
||||
})
|
||||
}
|
||||
|
||||
export const setTags = (tags: SentryTags): void => {
|
||||
Sentry.setTags({ ...tags })
|
||||
}
|
||||
|
||||
export const handleException = (e: unknown): void => {
|
||||
Sentry.captureException(e)
|
||||
}
|
||||
Reference in New Issue
Block a user