setup: builds plugin and demo
This commit is contained in:
10
packages/plugin-sentry/.editorconfig
Normal file
10
packages/plugin-sentry/.editorconfig
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
end_of_line = lf
|
||||||
|
max_line_length = null
|
||||||
3
packages/plugin-sentry/.eslintrc.js
Normal file
3
packages/plugin-sentry/.eslintrc.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: ['@payloadcms'],
|
||||||
|
}
|
||||||
6
packages/plugin-sentry/.gitignore
vendored
Normal file
6
packages/plugin-sentry/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
node_modules
|
||||||
|
.env
|
||||||
|
dist
|
||||||
|
build
|
||||||
|
.DS_Store
|
||||||
|
package-lock.json
|
||||||
8
packages/plugin-sentry/.prettierrc.js
Normal file
8
packages/plugin-sentry/.prettierrc.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
module.exports = {
|
||||||
|
printWidth: 100,
|
||||||
|
parser: "typescript",
|
||||||
|
semi: false,
|
||||||
|
singleQuote: true,
|
||||||
|
trailingComma: "all",
|
||||||
|
arrowParens: "avoid",
|
||||||
|
};
|
||||||
6
packages/plugin-sentry/dev/.gitignore
vendored
Normal file
6
packages/plugin-sentry/dev/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
node_modules
|
||||||
|
.env
|
||||||
|
dist
|
||||||
|
build
|
||||||
|
.DS_Store
|
||||||
|
package-lock.json
|
||||||
7
packages/plugin-sentry/dev/README.md
Normal file
7
packages/plugin-sentry/dev/README.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Sentry Plugin Demo
|
||||||
|
|
||||||
|
This project was created using create-payload-app using the blank template.
|
||||||
|
|
||||||
|
## How to Use
|
||||||
|
|
||||||
|
`yarn dev` will start up your application and reload on any changes.
|
||||||
4
packages/plugin-sentry/dev/nodemon.json
Normal file
4
packages/plugin-sentry/dev/nodemon.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"ext": "ts",
|
||||||
|
"exec": "ts-node src/server.ts"
|
||||||
|
}
|
||||||
33
packages/plugin-sentry/dev/package.json
Normal file
33
packages/plugin-sentry/dev/package.json
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"name": "plugin-sentry-demo",
|
||||||
|
"description": "Payload project to demonstrate how to use the sentry plugin",
|
||||||
|
"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 copyfiles && yarn build:payload && yarn build:server",
|
||||||
|
"serve": "cross-env PAYLOAD_CONFIG_PATH=dist/payload.config.js NODE_ENV=production node dist/server.js",
|
||||||
|
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png}\" dist/",
|
||||||
|
"generate:types": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:types",
|
||||||
|
"generate:graphQLSchema": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:graphQLSchema"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@sentry/node": "^7.55.2",
|
||||||
|
"@sentry/react": "^7.55.2",
|
||||||
|
"dotenv": "^8.2.0",
|
||||||
|
"eslint": "^8.42.0",
|
||||||
|
"express": "^4.17.1",
|
||||||
|
"payload": "^1.9.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/express": "^4.17.9",
|
||||||
|
"copyfiles": "^2.4.1",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"nodemon": "^2.0.6",
|
||||||
|
"ts-node": "^9.1.1",
|
||||||
|
"typescript": "^4.8.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
18
packages/plugin-sentry/dev/src/collections/Users.ts
Normal file
18
packages/plugin-sentry/dev/src/collections/Users.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import type { 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
|
||||||
25
packages/plugin-sentry/dev/src/payload.config.ts
Normal file
25
packages/plugin-sentry/dev/src/payload.config.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/* eslint-disable import/no-relative-packages */
|
||||||
|
import path from 'path'
|
||||||
|
import { buildConfig } from 'payload/config'
|
||||||
|
|
||||||
|
import { sentry } from '../../src/index'
|
||||||
|
import Users from './collections/Users'
|
||||||
|
|
||||||
|
export default buildConfig({
|
||||||
|
serverURL: 'http://localhost:3000',
|
||||||
|
admin: {
|
||||||
|
user: Users.slug,
|
||||||
|
},
|
||||||
|
collections: [Users],
|
||||||
|
typescript: {
|
||||||
|
outputFile: path.resolve(__dirname, 'payload-types.ts'),
|
||||||
|
},
|
||||||
|
graphQL: {
|
||||||
|
schemaOutputFile: path.resolve(__dirname, 'generated-schema.graphql'),
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
sentry({
|
||||||
|
dsn: 'https://61edebe5ee6d4d38a9d6459c7323d777@o4505289711681536.ingest.sentry.io/4505357688242176',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
27
packages/plugin-sentry/dev/src/server.ts
Normal file
27
packages/plugin-sentry/dev/src/server.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import dotenv from 'dotenv'
|
||||||
|
import express from 'express'
|
||||||
|
import payload from 'payload'
|
||||||
|
|
||||||
|
dotenv.config()
|
||||||
|
const app = express()
|
||||||
|
|
||||||
|
// Redirect root to Admin panel
|
||||||
|
app.get('/', (_, res) => {
|
||||||
|
res.redirect('/admin')
|
||||||
|
})
|
||||||
|
|
||||||
|
// Initialize Payload
|
||||||
|
const start = async (): Promise<void> => {
|
||||||
|
await payload.init({
|
||||||
|
secret: process.env.PAYLOAD_SECRET,
|
||||||
|
mongoURL: process.env.MONGODB_URI,
|
||||||
|
express: app,
|
||||||
|
onInit: () => {
|
||||||
|
payload.logger.info(`Payload Admin URL: ${payload.getAdminURL()}`)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
app.listen(3000)
|
||||||
|
}
|
||||||
|
|
||||||
|
start()
|
||||||
20
packages/plugin-sentry/dev/tsconfig.json
Normal file
20
packages/plugin-sentry/dev/tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"esnext"
|
||||||
|
],
|
||||||
|
"strict": false,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
"rootDir": "../",
|
||||||
|
"jsx": "react",
|
||||||
|
"sourceMap": true
|
||||||
|
},
|
||||||
|
"ts-node": {
|
||||||
|
"transpileOnly": true
|
||||||
|
}
|
||||||
|
}
|
||||||
60
packages/plugin-sentry/package.json
Normal file
60
packages/plugin-sentry/package.json
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"name": "@payloadcms/plugin-sentry",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"homepage:": "https://payloadcms.com",
|
||||||
|
"repository": "git@github.com:payloadcms/plugin-sentry.git",
|
||||||
|
"description": "Sentry plugin for Payload",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"lint": "eslint src",
|
||||||
|
"lint:fix": "eslint --fix --ext .ts,.tsx src"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"payload",
|
||||||
|
"cms",
|
||||||
|
"plugin",
|
||||||
|
"typescript",
|
||||||
|
"sentry",
|
||||||
|
"error handling"
|
||||||
|
],
|
||||||
|
"author": "dev@payloadcms.com",
|
||||||
|
"license": "MIT",
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"peerDependencies": {
|
||||||
|
"payload": "^1.9.2",
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@sentry/node": "^7.55.2",
|
||||||
|
"@sentry/types": "^7.54.0",
|
||||||
|
"express": "^4.18.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@payloadcms/eslint-config": "^0.0.1",
|
||||||
|
"@types/express": "^4.17.9",
|
||||||
|
"@types/node": "18.11.3",
|
||||||
|
"@types/react": "18.0.21",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.51.0",
|
||||||
|
"@typescript-eslint/parser": "^5.51.0",
|
||||||
|
"copyfiles": "^2.4.1",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"dotenv": "^8.2.0",
|
||||||
|
"eslint": "^8.19.0",
|
||||||
|
"eslint-config-prettier": "^8.5.0",
|
||||||
|
"eslint-plugin-filenames": "^1.3.2",
|
||||||
|
"eslint-plugin-import": "2.25.4",
|
||||||
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
|
"eslint-plugin-simple-import-sort": "^10.0.0",
|
||||||
|
"nodemon": "^2.0.6",
|
||||||
|
"payload": "^1.9.2",
|
||||||
|
"prettier": "^2.7.1",
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
|
"typescript": "^4.1.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
5
packages/plugin-sentry/src/captureException.ts
Normal file
5
packages/plugin-sentry/src/captureException.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import * as Sentry from '@sentry/node'
|
||||||
|
|
||||||
|
export const captureException = (err: Error): void => {
|
||||||
|
Sentry.captureException(err)
|
||||||
|
}
|
||||||
38
packages/plugin-sentry/src/index.ts
Normal file
38
packages/plugin-sentry/src/index.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
import type { Config } from 'payload/config'
|
||||||
|
|
||||||
|
import { captureException } from './captureException'
|
||||||
|
import { startSentry } from './startSentry'
|
||||||
|
import type { PluginOptions } from './types'
|
||||||
|
import { extendWebpackConfig } from './webpack'
|
||||||
|
|
||||||
|
export const sentry =
|
||||||
|
(pluginOptions: PluginOptions) =>
|
||||||
|
(incomingConfig: Config): Config => {
|
||||||
|
if (!pluginOptions.dsn) {
|
||||||
|
console.log('Sentry plugin is disabled because no DSN was provided')
|
||||||
|
return incomingConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
let config = { ...incomingConfig }
|
||||||
|
const webpack = extendWebpackConfig(incomingConfig)
|
||||||
|
|
||||||
|
config.admin = {
|
||||||
|
...(config.admin || {}),
|
||||||
|
webpack,
|
||||||
|
}
|
||||||
|
|
||||||
|
config.hooks = {
|
||||||
|
...(incomingConfig.hooks || {}),
|
||||||
|
afterError: (err: any) => {
|
||||||
|
captureException(err)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
startSentry({
|
||||||
|
dsn: pluginOptions.dsn,
|
||||||
|
options: pluginOptions?.options,
|
||||||
|
})
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
||||||
4
packages/plugin-sentry/src/mocks/mockFile.js
Normal file
4
packages/plugin-sentry/src/mocks/mockFile.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
module.exports = {
|
||||||
|
startSentry: () => {},
|
||||||
|
captureException: () => {},
|
||||||
|
}
|
||||||
48
packages/plugin-sentry/src/startSentry.ts
Normal file
48
packages/plugin-sentry/src/startSentry.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
import * as Sentry from '@sentry/node'
|
||||||
|
import express from 'express'
|
||||||
|
|
||||||
|
import type { PluginOptions } from './types'
|
||||||
|
|
||||||
|
export const startSentry = (pluginOptions: PluginOptions): any => {
|
||||||
|
const { dsn, options } = pluginOptions
|
||||||
|
|
||||||
|
try {
|
||||||
|
const app = express()
|
||||||
|
|
||||||
|
Sentry.init({
|
||||||
|
dsn: dsn,
|
||||||
|
tracesSampleRate: 1.0,
|
||||||
|
integrations: [
|
||||||
|
new Sentry.Integrations.Http({ tracing: true }),
|
||||||
|
new Sentry.Integrations.Express({ app }),
|
||||||
|
...Sentry.autoDiscoverNodePerformanceMonitoringIntegrations(),
|
||||||
|
],
|
||||||
|
...options,
|
||||||
|
})
|
||||||
|
|
||||||
|
app.use(Sentry.Handlers.requestHandler())
|
||||||
|
app.use(Sentry.Handlers.tracingHandler())
|
||||||
|
app.use(
|
||||||
|
Sentry.Handlers.errorHandler({
|
||||||
|
shouldHandleError(error) {
|
||||||
|
if (error.status === 404 || error.status === 500) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
app.use(Sentry.Handlers.requestHandler())
|
||||||
|
app.get('/', function rootHandler(req, res) {
|
||||||
|
res.end('Sentry running')
|
||||||
|
})
|
||||||
|
|
||||||
|
app.use(function onError(err, req, res, next) {
|
||||||
|
res.statusCode = 500
|
||||||
|
res.end(res.sentry + '\n')
|
||||||
|
})
|
||||||
|
} catch (err: unknown) {
|
||||||
|
console.log('There was an error initializing Sentry, please ensure you entered a valid DSN')
|
||||||
|
}
|
||||||
|
}
|
||||||
6
packages/plugin-sentry/src/types.ts
Normal file
6
packages/plugin-sentry/src/types.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import type { ClientOptions } from '@sentry/types'
|
||||||
|
|
||||||
|
export interface PluginOptions {
|
||||||
|
dsn: string
|
||||||
|
options?: ClientOptions
|
||||||
|
}
|
||||||
28
packages/plugin-sentry/src/webpack.ts
Normal file
28
packages/plugin-sentry/src/webpack.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import path from 'path'
|
||||||
|
import type { Config } from 'payload/config'
|
||||||
|
import type { Configuration as WebpackConfig } from 'webpack'
|
||||||
|
|
||||||
|
export const extendWebpackConfig =
|
||||||
|
(config: Config): ((webpackConfig: WebpackConfig) => WebpackConfig) =>
|
||||||
|
webpackConfig => {
|
||||||
|
const existingWebpackConfig =
|
||||||
|
typeof config.admin?.webpack === 'function'
|
||||||
|
? config.admin.webpack(webpackConfig)
|
||||||
|
: webpackConfig
|
||||||
|
|
||||||
|
const mockModulePath = path.resolve(__dirname, './mocks/mockFile.js')
|
||||||
|
|
||||||
|
const newWebpack = {
|
||||||
|
...existingWebpackConfig,
|
||||||
|
resolve: {
|
||||||
|
...(existingWebpackConfig.resolve || {}),
|
||||||
|
alias: {
|
||||||
|
...(existingWebpackConfig.resolve?.alias ? existingWebpackConfig.resolve.alias : {}),
|
||||||
|
[path.resolve(__dirname, './startSentry')]: mockModulePath,
|
||||||
|
[path.resolve(__dirname, './captureException')]: mockModulePath,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return newWebpack
|
||||||
|
}
|
||||||
18
packages/plugin-sentry/tsconfig.json
Normal file
18
packages/plugin-sentry/tsconfig.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"outDir": "./dist",
|
||||||
|
"allowJs": true,
|
||||||
|
"module": "commonjs",
|
||||||
|
"sourceMap": true,
|
||||||
|
"jsx": "react",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"declaration": true,
|
||||||
|
"declarationDir": "./dist",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/*"
|
||||||
|
],
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user