Revamp backend code to support good local function development (#657)
* Move concurrently dep upwards * Add express as explicit dependency * Accept just one HTTP method per endpoint * Fix endpoint option coalescing * Expressification of cloud functions * Nicer logging of API requests * Refactor web package.json * Add ts-node and nodemon to dev dependencies, bring back cors * Add scaffolding to point dev server at local functions * Enable emulator in dev server scaffolding * Fix up a little stuff I broke
This commit is contained in:
parent
6ad43b02c7
commit
a1d5d161dd
|
@ -12,7 +12,9 @@ export class APIError extends Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getFunctionUrl(name: string) {
|
export function getFunctionUrl(name: string) {
|
||||||
if (process.env.NEXT_PUBLIC_FIREBASE_EMULATE) {
|
if (process.env.NEXT_PUBLIC_FUNCTIONS_URL) {
|
||||||
|
return `${process.env.NEXT_PUBLIC_FUNCTIONS_URL}/${name}`
|
||||||
|
} else if (process.env.NEXT_PUBLIC_FIREBASE_EMULATE) {
|
||||||
const { projectId, region } = ENV_CONFIG.firebaseConfig
|
const { projectId, region } = ENV_CONFIG.firebaseConfig
|
||||||
return `http://localhost:5001/${projectId}/${region}/${name}`
|
return `http://localhost:5001/${projectId}/${region}/${name}`
|
||||||
} else {
|
} else {
|
||||||
|
|
45
dev.sh
Executable file
45
dev.sh
Executable file
|
@ -0,0 +1,45 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
ENV=${1:-dev}
|
||||||
|
case $ENV in
|
||||||
|
dev)
|
||||||
|
FIREBASE_PROJECT=dev
|
||||||
|
NEXT_ENV=DEV
|
||||||
|
EMULATOR=false ;;
|
||||||
|
prod)
|
||||||
|
FIREBASE_PROJECT=prod
|
||||||
|
NEXT_ENV=PROD
|
||||||
|
EMULATOR=false ;;
|
||||||
|
localdb)
|
||||||
|
FIREBASE_PROJECT=dev
|
||||||
|
NEXT_ENV=DEV
|
||||||
|
EMULATOR=true ;;
|
||||||
|
*)
|
||||||
|
echo "Invalid environment; must be dev, prod, or localdb."
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
||||||
|
firebase use $FIREBASE_PROJECT
|
||||||
|
|
||||||
|
if [ ! -z $EMULATOR ]
|
||||||
|
then
|
||||||
|
npx concurrently \
|
||||||
|
-n FIRESTORE,FUNCTIONS,NEXT,TS \
|
||||||
|
-c green,white,magenta,cyan \
|
||||||
|
"yarn --cwd=functions firestore" \
|
||||||
|
"cross-env FIRESTORE_EMULATOR_HOST=localhost:8080 yarn --cwd=functions dev" \
|
||||||
|
"cross-env NEXT_PUBLIC_FUNCTIONS_URL=http://localhost:8088 \
|
||||||
|
NEXT_PUBLIC_FIREBASE_EMULATE=TRUE \
|
||||||
|
NEXT_PUBLIC_FIREBASE_ENV=${NEXT_ENV} \
|
||||||
|
yarn --cwd=web serve" \
|
||||||
|
"cross-env yarn --cwd=web ts-watch"
|
||||||
|
else
|
||||||
|
npx concurrently \
|
||||||
|
-n FUNCTIONS,NEXT,TS \
|
||||||
|
-c white,magenta,cyan \
|
||||||
|
"yarn --cwd=functions dev" \
|
||||||
|
"cross-env NEXT_PUBLIC_FUNCTIONS_URL=http://localhost:8088 \
|
||||||
|
NEXT_PUBLIC_FIREBASE_ENV=${NEXT_ENV} \
|
||||||
|
yarn --cwd=web serve" \
|
||||||
|
"cross-env yarn --cwd=web ts-watch"
|
||||||
|
fi
|
|
@ -12,6 +12,8 @@
|
||||||
"start": "yarn shell",
|
"start": "yarn shell",
|
||||||
"deploy": "firebase deploy --only functions",
|
"deploy": "firebase deploy --only functions",
|
||||||
"logs": "firebase functions:log",
|
"logs": "firebase functions:log",
|
||||||
|
"dev": "nodemon src/serve.ts",
|
||||||
|
"firestore": "firebase emulators:start --only firestore --import=./firestore_export",
|
||||||
"serve": "firebase use dev && yarn build && firebase emulators:start --only functions,firestore --import=./firestore_export",
|
"serve": "firebase use dev && yarn build && firebase emulators:start --only functions,firestore --import=./firestore_export",
|
||||||
"db:update-local-from-remote": "yarn db:backup-remote && gsutil rsync -r gs://$npm_package_config_firestore/firestore_export ./firestore_export",
|
"db:update-local-from-remote": "yarn db:backup-remote && gsutil rsync -r gs://$npm_package_config_firestore/firestore_export ./firestore_export",
|
||||||
"db:backup-local": "firebase emulators:export --force ./firestore_export",
|
"db:backup-local": "firebase emulators:export --force ./firestore_export",
|
||||||
|
@ -29,6 +31,8 @@
|
||||||
"@tiptap/extension-link": "2.0.0-beta.43",
|
"@tiptap/extension-link": "2.0.0-beta.43",
|
||||||
"@tiptap/extension-mention": "2.0.0-beta.102",
|
"@tiptap/extension-mention": "2.0.0-beta.102",
|
||||||
"@tiptap/starter-kit": "2.0.0-beta.190",
|
"@tiptap/starter-kit": "2.0.0-beta.190",
|
||||||
|
"cors": "2.8.5",
|
||||||
|
"express": "4.18.1",
|
||||||
"firebase-admin": "10.0.0",
|
"firebase-admin": "10.0.0",
|
||||||
"firebase-functions": "3.21.2",
|
"firebase-functions": "3.21.2",
|
||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import * as admin from 'firebase-admin'
|
import * as admin from 'firebase-admin'
|
||||||
import { logger } from 'firebase-functions/v2'
|
import { Request, RequestHandler, Response } from 'express'
|
||||||
import { HttpsOptions, onRequest, Request } from 'firebase-functions/v2/https'
|
import { error } from 'firebase-functions/logger'
|
||||||
|
import { HttpsOptions } from 'firebase-functions/v2/https'
|
||||||
import { log } from './utils'
|
import { log } from './utils'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { APIError } from '../../common/api'
|
import { APIError } from '../../common/api'
|
||||||
|
@ -45,7 +46,7 @@ export const parseCredentials = async (req: Request): Promise<Credentials> => {
|
||||||
return { kind: 'jwt', data: await auth.verifyIdToken(payload) }
|
return { kind: 'jwt', data: await auth.verifyIdToken(payload) }
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// This is somewhat suspicious, so get it into the firebase console
|
// This is somewhat suspicious, so get it into the firebase console
|
||||||
logger.error('Error verifying Firebase JWT: ', err)
|
error('Error verifying Firebase JWT: ', err)
|
||||||
throw new APIError(403, 'Error validating token.')
|
throw new APIError(403, 'Error validating token.')
|
||||||
}
|
}
|
||||||
case 'Key':
|
case 'Key':
|
||||||
|
@ -83,6 +84,11 @@ export const zTimestamp = () => {
|
||||||
}, z.date())
|
}, z.date())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type EndpointDefinition = {
|
||||||
|
opts: EndpointOptions & { method: string }
|
||||||
|
handler: RequestHandler
|
||||||
|
}
|
||||||
|
|
||||||
export const validate = <T extends z.ZodTypeAny>(schema: T, val: unknown) => {
|
export const validate = <T extends z.ZodTypeAny>(schema: T, val: unknown) => {
|
||||||
const result = schema.safeParse(val)
|
const result = schema.safeParse(val)
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
|
@ -99,12 +105,12 @@ export const validate = <T extends z.ZodTypeAny>(schema: T, val: unknown) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EndpointOptions extends HttpsOptions {
|
export interface EndpointOptions extends HttpsOptions {
|
||||||
methods?: string[]
|
method?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_OPTS = {
|
const DEFAULT_OPTS = {
|
||||||
methods: ['POST'],
|
method: 'POST',
|
||||||
minInstances: 1,
|
minInstances: 1,
|
||||||
concurrency: 100,
|
concurrency: 100,
|
||||||
memory: '2GiB',
|
memory: '2GiB',
|
||||||
|
@ -113,16 +119,16 @@ const DEFAULT_OPTS = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const newEndpoint = (endpointOpts: EndpointOptions, fn: Handler) => {
|
export const newEndpoint = (endpointOpts: EndpointOptions, fn: Handler) => {
|
||||||
const opts = Object.assign(endpointOpts, DEFAULT_OPTS)
|
const opts = Object.assign({}, DEFAULT_OPTS, endpointOpts)
|
||||||
return onRequest(opts, async (req, res) => {
|
return {
|
||||||
log('Request processing started.')
|
opts,
|
||||||
|
handler: async (req: Request, res: Response) => {
|
||||||
|
log(`${req.method} ${req.url} ${JSON.stringify(req.body)}`)
|
||||||
try {
|
try {
|
||||||
if (!opts.methods.includes(req.method)) {
|
if (opts.method !== req.method) {
|
||||||
const allowed = opts.methods.join(', ')
|
throw new APIError(405, `This endpoint supports only ${opts.method}.`)
|
||||||
throw new APIError(405, `This endpoint supports only ${allowed}.`)
|
|
||||||
}
|
}
|
||||||
const authedUser = await lookupUser(await parseCredentials(req))
|
const authedUser = await lookupUser(await parseCredentials(req))
|
||||||
log('User credentials processed.')
|
|
||||||
res.status(200).json(await fn(req, authedUser))
|
res.status(200).json(await fn(req, authedUser))
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof APIError) {
|
if (e instanceof APIError) {
|
||||||
|
@ -132,9 +138,10 @@ export const newEndpoint = (endpointOpts: EndpointOptions, fn: Handler) => {
|
||||||
}
|
}
|
||||||
res.status(e.code).json(output)
|
res.status(e.code).json(output)
|
||||||
} else {
|
} else {
|
||||||
logger.error(e)
|
error(e)
|
||||||
res.status(500).json({ message: 'An unknown error occurred.' })
|
res.status(500).json({ message: 'An unknown error occurred.' })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
} as EndpointDefinition
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { newEndpoint } from './api'
|
import { newEndpoint } from './api'
|
||||||
|
|
||||||
export const health = newEndpoint({ methods: ['GET'] }, async (_req, auth) => {
|
export const health = newEndpoint({ method: 'GET' }, async (_req, auth) => {
|
||||||
return {
|
return {
|
||||||
message: 'Server is working.',
|
message: 'Server is working.',
|
||||||
uid: auth.uid,
|
uid: auth.uid,
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import * as admin from 'firebase-admin'
|
import * as admin from 'firebase-admin'
|
||||||
|
import { onRequest } from 'firebase-functions/v2/https'
|
||||||
|
import { EndpointDefinition } from './api'
|
||||||
|
|
||||||
admin.initializeApp()
|
admin.initializeApp()
|
||||||
|
|
||||||
|
@ -25,20 +27,63 @@ export * from './on-delete-group'
|
||||||
export * from './score-contracts'
|
export * from './score-contracts'
|
||||||
|
|
||||||
// v2
|
// v2
|
||||||
export * from './health'
|
import { health } from './health'
|
||||||
export * from './transact'
|
import { transact } from './transact'
|
||||||
export * from './change-user-info'
|
import { changeuserinfo } from './change-user-info'
|
||||||
export * from './create-user'
|
import { createuser } from './create-user'
|
||||||
export * from './create-answer'
|
import { createanswer } from './create-answer'
|
||||||
export * from './place-bet'
|
import { placebet } from './place-bet'
|
||||||
export * from './cancel-bet'
|
import { cancelbet } from './cancel-bet'
|
||||||
export * from './sell-bet'
|
import { sellbet } from './sell-bet'
|
||||||
export * from './sell-shares'
|
import { sellshares } from './sell-shares'
|
||||||
export * from './claim-manalink'
|
import { claimmanalink } from './claim-manalink'
|
||||||
export * from './create-contract'
|
import { createmarket } from './create-contract'
|
||||||
export * from './add-liquidity'
|
import { addliquidity } from './add-liquidity'
|
||||||
export * from './withdraw-liquidity'
|
import { withdrawliquidity } from './withdraw-liquidity'
|
||||||
export * from './create-group'
|
import { creategroup } from './create-group'
|
||||||
export * from './resolve-market'
|
import { resolvemarket } from './resolve-market'
|
||||||
export * from './unsubscribe'
|
import { unsubscribe } from './unsubscribe'
|
||||||
export * from './stripe'
|
import { stripewebhook, createcheckoutsession } from './stripe'
|
||||||
|
|
||||||
|
const toCloudFunction = ({ opts, handler }: EndpointDefinition) => {
|
||||||
|
return onRequest(opts, handler as any)
|
||||||
|
}
|
||||||
|
const healthFunction = toCloudFunction(health)
|
||||||
|
const transactFunction = toCloudFunction(transact)
|
||||||
|
const changeUserInfoFunction = toCloudFunction(changeuserinfo)
|
||||||
|
const createUserFunction = toCloudFunction(createuser)
|
||||||
|
const createAnswerFunction = toCloudFunction(createanswer)
|
||||||
|
const placeBetFunction = toCloudFunction(placebet)
|
||||||
|
const cancelBetFunction = toCloudFunction(cancelbet)
|
||||||
|
const sellBetFunction = toCloudFunction(sellbet)
|
||||||
|
const sellSharesFunction = toCloudFunction(sellshares)
|
||||||
|
const claimManalinkFunction = toCloudFunction(claimmanalink)
|
||||||
|
const createMarketFunction = toCloudFunction(createmarket)
|
||||||
|
const addLiquidityFunction = toCloudFunction(addliquidity)
|
||||||
|
const withdrawLiquidityFunction = toCloudFunction(withdrawliquidity)
|
||||||
|
const createGroupFunction = toCloudFunction(creategroup)
|
||||||
|
const resolveMarketFunction = toCloudFunction(resolvemarket)
|
||||||
|
const unsubscribeFunction = toCloudFunction(unsubscribe)
|
||||||
|
const stripeWebhookFunction = toCloudFunction(stripewebhook)
|
||||||
|
const createCheckoutSessionFunction = toCloudFunction(createcheckoutsession)
|
||||||
|
|
||||||
|
export {
|
||||||
|
healthFunction as health,
|
||||||
|
transactFunction as transact,
|
||||||
|
changeUserInfoFunction as changeuserinfo,
|
||||||
|
createUserFunction as createuser,
|
||||||
|
createAnswerFunction as createanswer,
|
||||||
|
placeBetFunction as placebet,
|
||||||
|
cancelBetFunction as cancelbet,
|
||||||
|
sellBetFunction as sellbet,
|
||||||
|
sellSharesFunction as sellshares,
|
||||||
|
claimManalinkFunction as claimmanalink,
|
||||||
|
createMarketFunction as createmarket,
|
||||||
|
addLiquidityFunction as addliquidity,
|
||||||
|
withdrawLiquidityFunction as withdrawliquidity,
|
||||||
|
createGroupFunction as creategroup,
|
||||||
|
resolveMarketFunction as resolvemarket,
|
||||||
|
unsubscribeFunction as unsubscribe,
|
||||||
|
stripeWebhookFunction as stripewebhook,
|
||||||
|
createCheckoutSessionFunction as createcheckoutsession,
|
||||||
|
}
|
||||||
|
|
|
@ -66,10 +66,18 @@ export const getServiceAccountCredentials = (env?: string) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initAdmin = (env?: string) => {
|
export const initAdmin = (env?: string) => {
|
||||||
|
try {
|
||||||
const serviceAccount = getServiceAccountCredentials(env)
|
const serviceAccount = getServiceAccountCredentials(env)
|
||||||
console.log(`Initializing connection to ${serviceAccount.project_id}...`)
|
console.log(
|
||||||
|
`Initializing connection to ${serviceAccount.project_id} Firebase...`
|
||||||
|
)
|
||||||
return admin.initializeApp({
|
return admin.initializeApp({
|
||||||
projectId: serviceAccount.project_id,
|
projectId: serviceAccount.project_id,
|
||||||
credential: admin.credential.cert(serviceAccount),
|
credential: admin.credential.cert(serviceAccount),
|
||||||
})
|
})
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
console.log(`Initializing connection to default Firebase...`)
|
||||||
|
return admin.initializeApp()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
68
functions/src/serve.ts
Normal file
68
functions/src/serve.ts
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import * as cors from 'cors'
|
||||||
|
import * as express from 'express'
|
||||||
|
import { Express, Request, Response, NextFunction } from 'express'
|
||||||
|
import { EndpointDefinition } from './api'
|
||||||
|
|
||||||
|
const PORT = 8088
|
||||||
|
|
||||||
|
import { initAdmin } from './scripts/script-init'
|
||||||
|
initAdmin()
|
||||||
|
|
||||||
|
import { health } from './health'
|
||||||
|
import { transact } from './transact'
|
||||||
|
import { changeuserinfo } from './change-user-info'
|
||||||
|
import { createuser } from './create-user'
|
||||||
|
import { createanswer } from './create-answer'
|
||||||
|
import { placebet } from './place-bet'
|
||||||
|
import { cancelbet } from './cancel-bet'
|
||||||
|
import { sellbet } from './sell-bet'
|
||||||
|
import { sellshares } from './sell-shares'
|
||||||
|
import { claimmanalink } from './claim-manalink'
|
||||||
|
import { createmarket } from './create-contract'
|
||||||
|
import { addliquidity } from './add-liquidity'
|
||||||
|
import { withdrawliquidity } from './withdraw-liquidity'
|
||||||
|
import { creategroup } from './create-group'
|
||||||
|
import { resolvemarket } from './resolve-market'
|
||||||
|
import { unsubscribe } from './unsubscribe'
|
||||||
|
import { stripewebhook, createcheckoutsession } from './stripe'
|
||||||
|
|
||||||
|
type Middleware = (req: Request, res: Response, next: NextFunction) => void
|
||||||
|
const app = express()
|
||||||
|
|
||||||
|
const addEndpointRoute = (
|
||||||
|
path: string,
|
||||||
|
endpoint: EndpointDefinition,
|
||||||
|
...middlewares: Middleware[]
|
||||||
|
) => {
|
||||||
|
const method = endpoint.opts.method.toLowerCase() as keyof Express
|
||||||
|
const corsMiddleware = cors({ origin: endpoint.opts.cors })
|
||||||
|
const allMiddleware = [...middlewares, corsMiddleware]
|
||||||
|
app.options(path, corsMiddleware) // preflight requests
|
||||||
|
app[method](path, ...allMiddleware, endpoint.handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
const addJsonEndpointRoute = (name: string, endpoint: EndpointDefinition) => {
|
||||||
|
addEndpointRoute(name, endpoint, express.json())
|
||||||
|
}
|
||||||
|
|
||||||
|
addEndpointRoute('/health', health)
|
||||||
|
addJsonEndpointRoute('/transact', transact)
|
||||||
|
addJsonEndpointRoute('/changeuserinfo', changeuserinfo)
|
||||||
|
addJsonEndpointRoute('/createuser', createuser)
|
||||||
|
addJsonEndpointRoute('/createanswer', createanswer)
|
||||||
|
addJsonEndpointRoute('/placebet', placebet)
|
||||||
|
addJsonEndpointRoute('/cancelbet', cancelbet)
|
||||||
|
addJsonEndpointRoute('/sellbet', sellbet)
|
||||||
|
addJsonEndpointRoute('/sellshares', sellshares)
|
||||||
|
addJsonEndpointRoute('/claimmanalink', claimmanalink)
|
||||||
|
addJsonEndpointRoute('/createmarket', createmarket)
|
||||||
|
addJsonEndpointRoute('/addliquidity', addliquidity)
|
||||||
|
addJsonEndpointRoute('/withdrawliquidity', withdrawliquidity)
|
||||||
|
addJsonEndpointRoute('/creategroup', creategroup)
|
||||||
|
addJsonEndpointRoute('/resolvemarket', resolvemarket)
|
||||||
|
addJsonEndpointRoute('/unsubscribe', unsubscribe)
|
||||||
|
addJsonEndpointRoute('/createcheckoutsession', createcheckoutsession)
|
||||||
|
addEndpointRoute('/stripewebhook', stripewebhook, express.raw())
|
||||||
|
|
||||||
|
app.listen(PORT)
|
||||||
|
console.log(`Serving functions on port ${PORT}.`)
|
|
@ -1,7 +1,7 @@
|
||||||
import { onRequest } from 'firebase-functions/v2/https'
|
|
||||||
import * as admin from 'firebase-admin'
|
import * as admin from 'firebase-admin'
|
||||||
import Stripe from 'stripe'
|
import Stripe from 'stripe'
|
||||||
|
|
||||||
|
import { EndpointDefinition } from './api'
|
||||||
import { getPrivateUser, getUser, isProd, payUser } from './utils'
|
import { getPrivateUser, getUser, isProd, payUser } from './utils'
|
||||||
import { sendThankYouEmail } from './emails'
|
import { sendThankYouEmail } from './emails'
|
||||||
import { track } from './analytics'
|
import { track } from './analytics'
|
||||||
|
@ -42,9 +42,9 @@ const manticDollarStripePrice = isProd()
|
||||||
10000: 'price_1K8bEiGdoFKoCJW7Us4UkRHE',
|
10000: 'price_1K8bEiGdoFKoCJW7Us4UkRHE',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createcheckoutsession = onRequest(
|
export const createcheckoutsession: EndpointDefinition = {
|
||||||
{ minInstances: 1, secrets: ['STRIPE_APIKEY'] },
|
opts: { method: 'POST', minInstances: 1, secrets: ['STRIPE_APIKEY'] },
|
||||||
async (req, res) => {
|
handler: async (req, res) => {
|
||||||
const userId = req.query.userId?.toString()
|
const userId = req.query.userId?.toString()
|
||||||
|
|
||||||
const manticDollarQuantity = req.query.manticDollarQuantity?.toString()
|
const manticDollarQuantity = req.query.manticDollarQuantity?.toString()
|
||||||
|
@ -86,21 +86,24 @@ export const createcheckoutsession = onRequest(
|
||||||
})
|
})
|
||||||
|
|
||||||
res.redirect(303, session.url || '')
|
res.redirect(303, session.url || '')
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
export const stripewebhook = onRequest(
|
export const stripewebhook: EndpointDefinition = {
|
||||||
{
|
opts: {
|
||||||
|
method: 'POST',
|
||||||
minInstances: 1,
|
minInstances: 1,
|
||||||
secrets: ['MAILGUN_KEY', 'STRIPE_APIKEY', 'STRIPE_WEBHOOKSECRET'],
|
secrets: ['MAILGUN_KEY', 'STRIPE_APIKEY', 'STRIPE_WEBHOOKSECRET'],
|
||||||
},
|
},
|
||||||
async (req, res) => {
|
handler: async (req, res) => {
|
||||||
const stripe = initStripe()
|
const stripe = initStripe()
|
||||||
let event
|
let event
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Cloud Functions jam the raw body into a special `rawBody` property
|
||||||
|
const rawBody = (req as any).rawBody ?? req.body
|
||||||
event = stripe.webhooks.constructEvent(
|
event = stripe.webhooks.constructEvent(
|
||||||
req.rawBody,
|
rawBody,
|
||||||
req.headers['stripe-signature'] as string,
|
req.headers['stripe-signature'] as string,
|
||||||
process.env.STRIPE_WEBHOOKSECRET as string
|
process.env.STRIPE_WEBHOOKSECRET as string
|
||||||
)
|
)
|
||||||
|
@ -116,8 +119,8 @@ export const stripewebhook = onRequest(
|
||||||
}
|
}
|
||||||
|
|
||||||
res.status(200).send('success')
|
res.status(200).send('success')
|
||||||
|
},
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
const issueMoneys = async (session: StripeSession) => {
|
const issueMoneys = async (session: StripeSession) => {
|
||||||
const { id: sessionId } = session
|
const { id: sessionId } = session
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import { onRequest } from 'firebase-functions/v2/https'
|
|
||||||
import * as admin from 'firebase-admin'
|
import * as admin from 'firebase-admin'
|
||||||
|
import { EndpointDefinition } from './api'
|
||||||
import { getUser } from './utils'
|
import { getUser } from './utils'
|
||||||
import { PrivateUser } from '../../common/user'
|
import { PrivateUser } from '../../common/user'
|
||||||
|
|
||||||
export const unsubscribe = onRequest({ minInstances: 1 }, async (req, res) => {
|
export const unsubscribe: EndpointDefinition = {
|
||||||
|
opts: { method: 'GET', minInstances: 1 },
|
||||||
|
handler: async (req, res) => {
|
||||||
const id = req.query.id as string
|
const id = req.query.id as string
|
||||||
let type = req.query.type as string
|
let type = req.query.type as string
|
||||||
if (!id || !type) {
|
if (!id || !type) {
|
||||||
|
@ -14,9 +16,12 @@ export const unsubscribe = onRequest({ minInstances: 1 }, async (req, res) => {
|
||||||
if (type === 'market-resolved') type = 'market-resolve'
|
if (type === 'market-resolved') type = 'market-resolve'
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!['market-resolve', 'market-comment', 'market-answer', 'generic'].includes(
|
![
|
||||||
type
|
'market-resolve',
|
||||||
)
|
'market-comment',
|
||||||
|
'market-answer',
|
||||||
|
'generic',
|
||||||
|
].includes(type)
|
||||||
) {
|
) {
|
||||||
res.status(400).send('Invalid type parameter.')
|
res.status(400).send('Invalid type parameter.')
|
||||||
return
|
return
|
||||||
|
@ -61,6 +66,7 @@ export const unsubscribe = onRequest({ minInstances: 1 }, async (req, res) => {
|
||||||
`${name}, you have been unsubscribed from market answer emails on Manifold Markets.`
|
`${name}, you have been unsubscribed from market answer emails on Manifold Markets.`
|
||||||
)
|
)
|
||||||
else res.send(`${name}, you have been unsubscribed.`)
|
else res.send(`${name}, you have been unsubscribed.`)
|
||||||
})
|
},
|
||||||
|
}
|
||||||
|
|
||||||
const firestore = admin.firestore()
|
const firestore = admin.firestore()
|
||||||
|
|
|
@ -14,10 +14,13 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "5.25.0",
|
"@typescript-eslint/eslint-plugin": "5.25.0",
|
||||||
"@typescript-eslint/parser": "5.25.0",
|
"@typescript-eslint/parser": "5.25.0",
|
||||||
|
"concurrently": "6.5.1",
|
||||||
"eslint": "8.15.0",
|
"eslint": "8.15.0",
|
||||||
"eslint-plugin-lodash": "^7.4.0",
|
"eslint-plugin-lodash": "^7.4.0",
|
||||||
"prettier": "2.5.0",
|
"prettier": "2.5.0",
|
||||||
"typescript": "4.6.4"
|
"typescript": "4.6.4",
|
||||||
|
"ts-node": "10.9.1",
|
||||||
|
"nodemon": "2.0.19"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"@types/react": "17.0.43"
|
"@types/react": "17.0.43"
|
||||||
|
|
|
@ -3,12 +3,14 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "concurrently -n NEXT,TS -c magenta,cyan \"next dev -p 3000\" \"yarn ts --watch\"",
|
"serve": "next dev -p 3000",
|
||||||
"devdev": "cross-env NEXT_PUBLIC_FIREBASE_ENV=DEV concurrently -n NEXT,TS -c magenta,cyan \"cross-env FIREBASE_ENV=DEV next dev -p 3000\" \"cross-env FIREBASE_ENV=DEV yarn ts --watch\"",
|
"ts-watch": "tsc --watch --noEmit --incremental --preserveWatchOutput --pretty",
|
||||||
|
"dev": "concurrently -n NEXT,TS -c magenta,cyan \"yarn serve\" \"yarn ts-watch\"",
|
||||||
|
"devdev": "cross-env NEXT_PUBLIC_FIREBASE_ENV=DEV yarn dev",
|
||||||
"dev:dev": "yarn devdev",
|
"dev:dev": "yarn devdev",
|
||||||
"dev:the": "cross-env NEXT_PUBLIC_FIREBASE_ENV=THEOREMONE concurrently -n NEXT,TS -c magenta,cyan \"cross-env FIREBASE_ENV=THEOREMONE next dev -p 3000\" \"cross-env FIREBASE_ENV=THEOREMONE yarn ts --watch\"",
|
"dev:the": "cross-env NEXT_PUBLIC_FIREBASE_ENV=THEOREMONE yarn dev",
|
||||||
|
"dev:local": "cross-env NEXT_PUBLIC_FUNCTIONS_URL=http://localhost:8080 yarn devdev",
|
||||||
"dev:emulate": "cross-env NEXT_PUBLIC_FIREBASE_EMULATE=TRUE yarn devdev",
|
"dev:emulate": "cross-env NEXT_PUBLIC_FIREBASE_EMULATE=TRUE yarn devdev",
|
||||||
"ts": "tsc --noEmit --incremental --preserveWatchOutput --pretty",
|
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
|
@ -62,7 +64,6 @@
|
||||||
"@types/react": "17.0.43",
|
"@types/react": "17.0.43",
|
||||||
"@types/string-similarity": "^4.0.0",
|
"@types/string-similarity": "^4.0.0",
|
||||||
"autoprefixer": "10.2.6",
|
"autoprefixer": "10.2.6",
|
||||||
"concurrently": "6.5.1",
|
|
||||||
"critters": "0.0.16",
|
"critters": "0.0.16",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint-config-next": "12.1.6",
|
"eslint-config-next": "12.1.6",
|
||||||
|
|
143
yarn.lock
143
yarn.lock
|
@ -1353,6 +1353,13 @@
|
||||||
resolved "https://registry.yarnpkg.com/@corex/deepmerge/-/deepmerge-2.6.148.tgz#8fa825d53ffd1cbcafce1b6a830eefd3dcc09dd5"
|
resolved "https://registry.yarnpkg.com/@corex/deepmerge/-/deepmerge-2.6.148.tgz#8fa825d53ffd1cbcafce1b6a830eefd3dcc09dd5"
|
||||||
integrity sha512-6QMz0/2h5C3ua51iAnXMPWFbb1QOU1UvSM4bKBw5mzdT+WtLgjbETBBIQZ+Sh9WvEcGwlAt/DEdRpIC3XlDBMA==
|
integrity sha512-6QMz0/2h5C3ua51iAnXMPWFbb1QOU1UvSM4bKBw5mzdT+WtLgjbETBBIQZ+Sh9WvEcGwlAt/DEdRpIC3XlDBMA==
|
||||||
|
|
||||||
|
"@cspotcode/source-map-support@^0.8.0":
|
||||||
|
version "0.8.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"
|
||||||
|
integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/trace-mapping" "0.3.9"
|
||||||
|
|
||||||
"@docsearch/css@3.1.0":
|
"@docsearch/css@3.1.0":
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.1.0.tgz#6781cad43fc2e034d012ee44beddf8f93ba21f19"
|
resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.1.0.tgz#6781cad43fc2e034d012ee44beddf8f93ba21f19"
|
||||||
|
@ -2337,6 +2344,14 @@
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c"
|
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c"
|
||||||
integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==
|
integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==
|
||||||
|
|
||||||
|
"@jridgewell/trace-mapping@0.3.9":
|
||||||
|
version "0.3.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
|
||||||
|
integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/resolve-uri" "^3.0.3"
|
||||||
|
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||||
|
|
||||||
"@jridgewell/trace-mapping@^0.3.9":
|
"@jridgewell/trace-mapping@^0.3.9":
|
||||||
version "0.3.13"
|
version "0.3.13"
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea"
|
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea"
|
||||||
|
@ -3106,6 +3121,26 @@
|
||||||
resolved "https://registry.yarnpkg.com/@tsconfig/docusaurus/-/docusaurus-1.0.5.tgz#5298c5b0333c6263f06c3149b38ebccc9f169a4e"
|
resolved "https://registry.yarnpkg.com/@tsconfig/docusaurus/-/docusaurus-1.0.5.tgz#5298c5b0333c6263f06c3149b38ebccc9f169a4e"
|
||||||
integrity sha512-KM/TuJa9fugo67dTGx+ktIqf3fVc077J6jwHu845Hex4EQf7LABlNonP/mohDKT0cmncdtlYVHHF74xR/YpThg==
|
integrity sha512-KM/TuJa9fugo67dTGx+ktIqf3fVc077J6jwHu845Hex4EQf7LABlNonP/mohDKT0cmncdtlYVHHF74xR/YpThg==
|
||||||
|
|
||||||
|
"@tsconfig/node10@^1.0.7":
|
||||||
|
version "1.0.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2"
|
||||||
|
integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==
|
||||||
|
|
||||||
|
"@tsconfig/node12@^1.0.7":
|
||||||
|
version "1.0.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d"
|
||||||
|
integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==
|
||||||
|
|
||||||
|
"@tsconfig/node14@^1.0.0":
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1"
|
||||||
|
integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==
|
||||||
|
|
||||||
|
"@tsconfig/node16@^1.0.2":
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e"
|
||||||
|
integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==
|
||||||
|
|
||||||
"@types/body-parser@*":
|
"@types/body-parser@*":
|
||||||
version "1.19.2"
|
version "1.19.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0"
|
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0"
|
||||||
|
@ -3670,7 +3705,7 @@ acorn-walk@^7.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
|
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
|
||||||
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
|
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
|
||||||
|
|
||||||
acorn-walk@^8.0.0:
|
acorn-walk@^8.0.0, acorn-walk@^8.1.1:
|
||||||
version "8.2.0"
|
version "8.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
|
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
|
||||||
integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
|
integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
|
||||||
|
@ -3854,6 +3889,11 @@ anymatch@~3.1.2:
|
||||||
normalize-path "^3.0.0"
|
normalize-path "^3.0.0"
|
||||||
picomatch "^2.0.4"
|
picomatch "^2.0.4"
|
||||||
|
|
||||||
|
arg@^4.1.0:
|
||||||
|
version "4.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
|
||||||
|
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
|
||||||
|
|
||||||
arg@^5.0.0:
|
arg@^5.0.0:
|
||||||
version "5.0.1"
|
version "5.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb"
|
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb"
|
||||||
|
@ -4410,7 +4450,7 @@ cheerio@^1.0.0-rc.10:
|
||||||
parse5-htmlparser2-tree-adapter "^7.0.0"
|
parse5-htmlparser2-tree-adapter "^7.0.0"
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
|
|
||||||
chokidar@^3.4.2, chokidar@^3.5.3:
|
chokidar@^3.4.2, chokidar@^3.5.2, chokidar@^3.5.3:
|
||||||
version "3.5.3"
|
version "3.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
||||||
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
|
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
|
||||||
|
@ -4772,6 +4812,11 @@ cosmiconfig@^7.0.0, cosmiconfig@^7.0.1:
|
||||||
path-type "^4.0.0"
|
path-type "^4.0.0"
|
||||||
yaml "^1.10.0"
|
yaml "^1.10.0"
|
||||||
|
|
||||||
|
create-require@^1.1.0:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
|
||||||
|
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
|
||||||
|
|
||||||
critters@0.0.16:
|
critters@0.0.16:
|
||||||
version "0.0.16"
|
version "0.0.16"
|
||||||
resolved "https://registry.yarnpkg.com/critters/-/critters-0.0.16.tgz#ffa2c5561a65b43c53b940036237ce72dcebfe93"
|
resolved "https://registry.yarnpkg.com/critters/-/critters-0.0.16.tgz#ffa2c5561a65b43c53b940036237ce72dcebfe93"
|
||||||
|
@ -5274,6 +5319,11 @@ didyoumean@^1.2.2:
|
||||||
resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
|
resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
|
||||||
integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==
|
integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==
|
||||||
|
|
||||||
|
diff@^4.0.1:
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
|
||||||
|
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
|
||||||
|
|
||||||
dir-glob@^3.0.1:
|
dir-glob@^3.0.1:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
|
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
|
||||||
|
@ -5927,7 +5977,7 @@ execa@^5.0.0:
|
||||||
signal-exit "^3.0.3"
|
signal-exit "^3.0.3"
|
||||||
strip-final-newline "^2.0.0"
|
strip-final-newline "^2.0.0"
|
||||||
|
|
||||||
express@^4.16.4, express@^4.17.1, express@^4.17.3:
|
express@4.18.1, express@^4.16.4, express@^4.17.1, express@^4.17.3:
|
||||||
version "4.18.1"
|
version "4.18.1"
|
||||||
resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf"
|
resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf"
|
||||||
integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==
|
integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==
|
||||||
|
@ -7059,6 +7109,11 @@ idb@3.0.2:
|
||||||
resolved "https://registry.yarnpkg.com/idb/-/idb-3.0.2.tgz#c8e9122d5ddd40f13b60ae665e4862f8b13fa384"
|
resolved "https://registry.yarnpkg.com/idb/-/idb-3.0.2.tgz#c8e9122d5ddd40f13b60ae665e4862f8b13fa384"
|
||||||
integrity sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==
|
integrity sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==
|
||||||
|
|
||||||
|
ignore-by-default@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
|
||||||
|
integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==
|
||||||
|
|
||||||
ignore@^5.1.9, ignore@^5.2.0:
|
ignore@^5.1.9, ignore@^5.2.0:
|
||||||
version "5.2.0"
|
version "5.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
|
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
|
||||||
|
@ -8083,6 +8138,11 @@ make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
semver "^6.0.0"
|
semver "^6.0.0"
|
||||||
|
|
||||||
|
make-error@^1.1.1:
|
||||||
|
version "1.3.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
|
||||||
|
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
|
||||||
|
|
||||||
markdown-escapes@^1.0.0:
|
markdown-escapes@^1.0.0:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535"
|
resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535"
|
||||||
|
@ -8434,7 +8494,23 @@ node-releases@^2.0.3:
|
||||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.4.tgz#f38252370c43854dc48aa431c766c6c398f40476"
|
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.4.tgz#f38252370c43854dc48aa431c766c6c398f40476"
|
||||||
integrity sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==
|
integrity sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==
|
||||||
|
|
||||||
nopt@1.0.10:
|
nodemon@2.0.19:
|
||||||
|
version "2.0.19"
|
||||||
|
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.19.tgz#cac175f74b9cb8b57e770d47841995eebe4488bd"
|
||||||
|
integrity sha512-4pv1f2bMDj0Eeg/MhGqxrtveeQ5/G/UVe9iO6uTZzjnRluSA4PVWf8CW99LUPwGB3eNIA7zUFoP77YuI7hOc0A==
|
||||||
|
dependencies:
|
||||||
|
chokidar "^3.5.2"
|
||||||
|
debug "^3.2.7"
|
||||||
|
ignore-by-default "^1.0.1"
|
||||||
|
minimatch "^3.0.4"
|
||||||
|
pstree.remy "^1.1.8"
|
||||||
|
semver "^5.7.1"
|
||||||
|
simple-update-notifier "^1.0.7"
|
||||||
|
supports-color "^5.5.0"
|
||||||
|
touch "^3.1.0"
|
||||||
|
undefsafe "^2.0.5"
|
||||||
|
|
||||||
|
nopt@1.0.10, nopt@~1.0.10:
|
||||||
version "1.0.10"
|
version "1.0.10"
|
||||||
resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee"
|
resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee"
|
||||||
integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=
|
integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=
|
||||||
|
@ -9552,6 +9628,11 @@ pseudomap@^1.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
|
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
|
||||||
integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
|
integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
|
||||||
|
|
||||||
|
pstree.remy@^1.1.8:
|
||||||
|
version "1.1.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a"
|
||||||
|
integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==
|
||||||
|
|
||||||
pump@^3.0.0:
|
pump@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
|
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
|
||||||
|
@ -10422,12 +10503,12 @@ semver-diff@^3.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
semver "^6.3.0"
|
semver "^6.3.0"
|
||||||
|
|
||||||
"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.6.0:
|
"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.6.0, semver@^5.7.1:
|
||||||
version "5.7.1"
|
version "5.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||||
|
|
||||||
semver@7.0.0:
|
semver@7.0.0, semver@~7.0.0:
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
|
||||||
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
|
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
|
||||||
|
@ -10574,6 +10655,13 @@ signal-exit@^3.0.2, signal-exit@^3.0.3:
|
||||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
|
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
|
||||||
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
|
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
|
||||||
|
|
||||||
|
simple-update-notifier@^1.0.7:
|
||||||
|
version "1.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz#7edf75c5bdd04f88828d632f762b2bc32996a9cc"
|
||||||
|
integrity sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==
|
||||||
|
dependencies:
|
||||||
|
semver "~7.0.0"
|
||||||
|
|
||||||
sirv@^1.0.7:
|
sirv@^1.0.7:
|
||||||
version "1.0.19"
|
version "1.0.19"
|
||||||
resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49"
|
resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49"
|
||||||
|
@ -10937,7 +11025,7 @@ stylehacks@^5.1.0:
|
||||||
browserslist "^4.16.6"
|
browserslist "^4.16.6"
|
||||||
postcss-selector-parser "^6.0.4"
|
postcss-selector-parser "^6.0.4"
|
||||||
|
|
||||||
supports-color@^5.3.0:
|
supports-color@^5.3.0, supports-color@^5.5.0:
|
||||||
version "5.5.0"
|
version "5.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
|
||||||
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
|
integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
|
||||||
|
@ -11117,6 +11205,13 @@ totalist@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df"
|
resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df"
|
||||||
integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==
|
integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==
|
||||||
|
|
||||||
|
touch@^3.1.0:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b"
|
||||||
|
integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==
|
||||||
|
dependencies:
|
||||||
|
nopt "~1.0.10"
|
||||||
|
|
||||||
tr46@~0.0.3:
|
tr46@~0.0.3:
|
||||||
version "0.0.3"
|
version "0.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||||
|
@ -11142,6 +11237,25 @@ trough@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406"
|
resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406"
|
||||||
integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==
|
integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==
|
||||||
|
|
||||||
|
ts-node@10.9.1:
|
||||||
|
version "10.9.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b"
|
||||||
|
integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==
|
||||||
|
dependencies:
|
||||||
|
"@cspotcode/source-map-support" "^0.8.0"
|
||||||
|
"@tsconfig/node10" "^1.0.7"
|
||||||
|
"@tsconfig/node12" "^1.0.7"
|
||||||
|
"@tsconfig/node14" "^1.0.0"
|
||||||
|
"@tsconfig/node16" "^1.0.2"
|
||||||
|
acorn "^8.4.1"
|
||||||
|
acorn-walk "^8.1.1"
|
||||||
|
arg "^4.1.0"
|
||||||
|
create-require "^1.1.0"
|
||||||
|
diff "^4.0.1"
|
||||||
|
make-error "^1.1.1"
|
||||||
|
v8-compile-cache-lib "^3.0.1"
|
||||||
|
yn "3.1.1"
|
||||||
|
|
||||||
tsc-files@1.1.3:
|
tsc-files@1.1.3:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/tsc-files/-/tsc-files-1.1.3.tgz#ef4cfcb7affc9b90577d707a879dc53bb105be83"
|
resolved "https://registry.yarnpkg.com/tsc-files/-/tsc-files-1.1.3.tgz#ef4cfcb7affc9b90577d707a879dc53bb105be83"
|
||||||
|
@ -11253,6 +11367,11 @@ unbox-primitive@^1.0.2:
|
||||||
has-symbols "^1.0.3"
|
has-symbols "^1.0.3"
|
||||||
which-boxed-primitive "^1.0.2"
|
which-boxed-primitive "^1.0.2"
|
||||||
|
|
||||||
|
undefsafe@^2.0.5:
|
||||||
|
version "2.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c"
|
||||||
|
integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==
|
||||||
|
|
||||||
unherit@^1.0.4:
|
unherit@^1.0.4:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22"
|
resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22"
|
||||||
|
@ -11511,6 +11630,11 @@ uuid@^8.0.0, uuid@^8.3.2:
|
||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||||
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||||
|
|
||||||
|
v8-compile-cache-lib@^3.0.1:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
|
||||||
|
integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==
|
||||||
|
|
||||||
v8-compile-cache@^2.0.3:
|
v8-compile-cache@^2.0.3:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
||||||
|
@ -11930,6 +12054,11 @@ yargs@^16.2.0:
|
||||||
y18n "^5.0.5"
|
y18n "^5.0.5"
|
||||||
yargs-parser "^20.2.2"
|
yargs-parser "^20.2.2"
|
||||||
|
|
||||||
|
yn@3.1.1:
|
||||||
|
version "3.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
|
||||||
|
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
|
||||||
|
|
||||||
yocto-queue@^0.1.0:
|
yocto-queue@^0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user