diff --git a/.ceramicDev.config.json b/.ceramicDev.config.json index 3f5d12749..d49f91f76 100644 --- a/.ceramicDev.config.json +++ b/.ceramicDev.config.json @@ -1,5 +1,5 @@ { - "anchor": { }, + "anchor": {}, "http-api": { "cors-allowed-origins": [ ".*" @@ -16,8 +16,8 @@ "log-level": 2 }, "metrics": { - "metrics-exporter-enabled": false, - "metrics-port": 9090 + "prometheus-exporter-enabled": true, + "prometheus-exporter-port": 9464 }, "network": { "name": "inmemory" @@ -33,3 +33,4 @@ "models": [] } } + diff --git a/.github/workflows/build-and-test.yaml b/.github/workflows/build-and-test.yaml index 567ab7bc8..179b4ac83 100644 --- a/.github/workflows/build-and-test.yaml +++ b/.github/workflows/build-and-test.yaml @@ -22,6 +22,7 @@ env: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} CONTAINER_IMAGE: desci-server DOCKER_BUILDKIT: 1 + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} jobs: build-and-test: @@ -55,6 +56,15 @@ jobs: echo "{\"proxies\":[{\"address\":\"\"}]}" > desci-server/src/desci-contracts-config/unknown-research-object.json echo "{\"proxies\":[{\"address\":\"\"}]}" > desci-server/src/desci-contracts-config/unknown-dpid.json + - name: Set up Sentry CLI + run: | + npm install -g @sentry/cli + sentry-cli --version + sentry-cli login --auth-token $SENTRY_AUTH_TOKEN + # append to .env + echo -e "\nSENTRY_AUTH_TOKEN=$SENTRY_AUTH" >> desci-server/.env + cd desci-server && yarn build + - name: Run tests run: | cd desci-server && export DOCKER_BUILDKIT=1 && yarn --ignore-engines && yarn test diff --git a/.github/workflows/build-server.yaml b/.github/workflows/build-server.yaml index 31341a659..8d2ea2a31 100644 --- a/.github/workflows/build-server.yaml +++ b/.github/workflows/build-server.yaml @@ -23,6 +23,7 @@ env: AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} CONTAINER_IMAGE: desci-server DOCKER_BUILDKIT: 1 @@ -57,6 +58,14 @@ jobs: echo "{\"proxies\":[{\"address\":\"\"}]}" > desci-server/src/desci-contracts-config/unknown-research-object.json echo "{\"proxies\":[{\"address\":\"\"}]}" > desci-server/src/desci-contracts-config/unknown-dpid.json + - name: Set up Sentry CLI + run: | + npm install -g @sentry/cli + sentry-cli --version + sentry-cli login --auth-token $SENTRY_AUTH_TOKEN + # append to .env + echo -e "\nSENTRY_AUTH_TOKEN=$SENTRY_AUTH" >> desci-server/.env + - name: Run tests run: | cd desci-server && export DOCKER_BUILDKIT=1 && yarn --ignore-engines && yarn test @@ -113,6 +122,14 @@ jobs: echo "{\"proxies\":[{\"address\":\"\"}]}" > desci-server/src/desci-contracts-config/unknown-research-object.json echo "{\"proxies\":[{\"address\":\"\"}]}" > desci-server/src/desci-contracts-config/unknown-dpid.json + - name: Set up Sentry CLI + run: | + npm install -g @sentry/cli + sentry-cli --version + sentry-cli login --auth-token $SENTRY_AUTH_TOKEN + # append to .env + echo -e "\nSENTRY_AUTH_TOKEN=$SENTRY_AUTH" >> desci-server/.env + - name: Build and tag the image (DEV) if: github.ref == 'refs/heads/develop' run: | diff --git a/ceramic-k8s/ceramic_deployment_dev.yaml b/ceramic-k8s/ceramic_deployment_dev.yaml index 58946e7ec..5aa80dcdf 100644 --- a/ceramic-k8s/ceramic_deployment_dev.yaml +++ b/ceramic-k8s/ceramic_deployment_dev.yaml @@ -11,10 +11,7 @@ spec: matchLabels: App: JsCeramicDev strategy: - rollingUpdate: - maxSurge: 25% - maxUnavailable: 25% - type: RollingUpdate + type: Recreate template: metadata: annotations: @@ -41,7 +38,9 @@ spec: App: JsCeramicDev spec: containers: - - image: ceramicnetwork/js-ceramic:6.4.0 + # Enables a fix allowing us to heal dropped anchors on genesis commits: + # https://github.com/ceramicnetwork/js-ceramic/pull/3280 + - image: ceramicnetwork/js-ceramic:6.6.0-rc.0 name: js-ceramic-dev command: ["/bin/bash", "-c"] args: @@ -49,6 +48,8 @@ spec: ports: - containerPort: 7007 name: http-api + - containerPort: 9464 + name: metrics resources: limits: cpu: 2 @@ -70,9 +71,38 @@ spec: port: http-api failureThreshold: 60 periodSeconds: 1 - serviceAccountName: "vault-auth" --- +apiVersion: v1 +kind: Service +metadata: + name: js-ceramic-dev-service-internal + labels: + App: JsCeramicDev +spec: + type: ClusterIP + selector: + App: JsCeramicDev + ports: + - name: metrics + port: 9464 + targetPort: metrics +--- +apiVersion: v1 +kind: Service +metadata: + name: public-js-ceramic-dev-service + labels: + App: JsCeramicDev +spec: + type: LoadBalancer + selector: + App: JsCeramicDev + ports: + - protocol: TCP + port: 80 + targetPort: http-api +--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -91,19 +121,3 @@ spec: name: public-js-ceramic-dev-service port: number: 80 ---- -apiVersion: v1 -kind: Service -metadata: - name: public-js-ceramic-dev-service - labels: - App: JsCeramicDev -spec: - type: LoadBalancer - selector: - App: JsCeramicDev - ports: - - protocol: TCP - name: http - port: 80 - targetPort: 7007 diff --git a/ceramic-k8s/ceramic_deployment_prod.yaml b/ceramic-k8s/ceramic_deployment_prod.yaml index ce84fecec..f2c0352e3 100644 --- a/ceramic-k8s/ceramic_deployment_prod.yaml +++ b/ceramic-k8s/ceramic_deployment_prod.yaml @@ -62,7 +62,7 @@ spec: App: JsCeramicProd spec: containers: - - image: ceramicnetwork/js-ceramic:6.4.0 + - image: ceramicnetwork/js-ceramic:6.5.0 name: js-ceramic-prod command: ["/bin/bash", "-c"] volumeMounts: @@ -73,6 +73,8 @@ spec: ports: - containerPort: 7007 name: http-api + - containerPort: 9464 + name: metrics resources: limits: cpu: 2 @@ -107,9 +109,39 @@ spec: - name: ceramic-prod-persistent-storage persistentVolumeClaim: claimName: ceramic-prod-persistent-storage-pvc - serviceAccountName: "vault-auth" --- +apiVersion: v1 +kind: Service +metadata: + name: js-ceramic-prod-service-internal + labels: + App: JsCeramicProd +spec: + type: ClusterIP + selector: + App: JsCeramicProd + ports: + - name: metrics + port: 9464 + targetPort: metrics +--- +apiVersion: v1 +kind: Service +metadata: + name: public-js-ceramic-prod-service + labels: + App: JsCeramicProd +spec: + type: LoadBalancer + selector: + App: JsCeramicProd + ports: + - protocol: TCP + name: http + port: 80 + targetPort: http-api +--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -128,19 +160,3 @@ spec: name: public-js-ceramic-prod-service port: number: 80 ---- -apiVersion: v1 -kind: Service -metadata: - name: public-js-ceramic-prod-service - labels: - App: JsCeramicProd -spec: - type: LoadBalancer - selector: - App: JsCeramicProd - ports: - - protocol: TCP - name: http - port: 80 - targetPort: 7007 diff --git a/desci-repo/src/controllers/nodes/documents.ts b/desci-repo/src/controllers/nodes/documents.ts index 3a70577eb..0292f664c 100644 --- a/desci-repo/src/controllers/nodes/documents.ts +++ b/desci-repo/src/controllers/nodes/documents.ts @@ -59,18 +59,13 @@ export const createNodeDocument = async function (req: Request, res: Response) { export const getLatestNodeManifest = async function (req: Request, res: Response) { logger.info({ params: req.params }, 'START [getLatestNodeManifest]'); try { - console.log('[getLatestNodeManifest]', req.params); + logger.info({ params: req.params }, '[getLatestNodeManifest]'); if (!req.params.uuid) { res.status(400).send({ ok: false, message: 'Invalid data' }); return; } const { uuid } = req.params; - - // const queryResult = await pool.query('SELECT * FROM nodes WHERE uuid = $1', [uuid]); - // console.log('user:', queryResult.rows[0]); - - logger.info('[getLatestNodeManifest]', { uuid }); const node = await findNodeByUuid(uuid); logger.trace('[getLatestNodeManifest::node]', { node }); diff --git a/desci-server/.gitignore b/desci-server/.gitignore index e9b57f85c..358616150 100755 --- a/desci-server/.gitignore +++ b/desci-server/.gitignore @@ -16,3 +16,6 @@ server.log repo-tmp queries.sql + +# Sentry Config File +.sentryclirc diff --git a/desci-server/package.json b/desci-server/package.json index 3aaf2a113..470a8a218 100755 --- a/desci-server/package.json +++ b/desci-server/package.json @@ -25,7 +25,7 @@ "script:seed-social-data": "debug=* node --no-warnings --enable-source-maps --loader ts-node/esm ./src/scripts/seed-social-data.ts", "script:DESTRUCTIVE-clear-social-data": "debug=* node --no-warnings --enable-source-maps --loader ts-node/esm ./src/scripts/DESTRUCTIVE-clear-social-data.ts", "script:seed-community-member": "debug=* node --no-warnings --enable-source-maps --loader ts-node/esm ./src/scripts/seed-community-members.ts", - "build": "rimraf dist && tsc && yarn copy-files", + "build": "rimraf dist && tsc && yarn copy-files; if [ \"$SENTRY_AUTH_TOKEN\" ]; then yarn sentry:sourcemaps; else echo 'SENTRY_AUTH_TOKEN not set, sourcemaps will not upload'; fi", "copy-files": "copyfiles -u 1 src/**/*.cjs dist/", "generate": "npx prisma generate", "migrate:local": "DATABASE_URL=postgresql://walter:white@localhost:5433/boilerplate npx prisma migrate dev", @@ -50,7 +50,8 @@ "docker:prod": "../dockerProd.sh", "podman:dev": "podman-compose --file docker-compose.yml --file docker-compose.dev.yml up --build", "email-dev": "email dev --dir ./src/templates/emails --port 3777", - "check-deps": "npx npm-check" + "check-deps": "npx npm-check", + "sentry:sourcemaps": "sentry-cli sourcemaps inject --org desci-labs --project nodes-backend ./dist && sentry-cli sourcemaps upload --org desci-labs --project nodes-backend ./dist && echo 'Sentry sourcemaps uploaded'" }, "dependencies": { "@automerge/automerge-repo": "^1.0.19", @@ -68,7 +69,9 @@ "@prisma/client": "4.10.1", "@react-email/components": "0.0.15", "@sendgrid/mail": "^7.7.0", - "@sentry/node": "^7.12.0", + "@sentry/cli": "^2.35.0", + "@sentry/node": "^8.29.0", + "@sentry/profiling-node": "^8.32.0", "@sentry/tracing": "^7.12.0", "@types/lodash-es": "^4.17.12", "@types/mkdirp": "^1.0.2", diff --git a/desci-server/prisma/schema.prisma b/desci-server/prisma/schema.prisma index 8d18e432f..d44babc72 100755 --- a/desci-server/prisma/schema.prisma +++ b/desci-server/prisma/schema.prisma @@ -1,5 +1,6 @@ generator client { - provider = "prisma-client-js" + provider = "prisma-client-js" + previewFeatures = ["tracing"] } datasource db { diff --git a/desci-server/src/controllers/admin/communities/index.ts b/desci-server/src/controllers/admin/communities/index.ts new file mode 100644 index 000000000..2daba8585 --- /dev/null +++ b/desci-server/src/controllers/admin/communities/index.ts @@ -0,0 +1,311 @@ +import { CommunityMembershipRole } from '@prisma/client'; +import { NextFunction, Request, Response } from 'express'; +import { z } from 'zod'; + +import { + asyncMap, + attestationService, + BadRequestError, + communityService, + DuplicateDataError, + NotFoundError, + logger as parentLogger, + prisma, + SuccessMessageResponse, + SuccessResponse, +} from '../../../internal.js'; +import { + addAttestationSchema, + addCommunitySchema, + addEntryAttestationSchema, + addMemberSchema, + removeMemberSchema, + updateAttestationSchema, + updateCommunitySchema, +} from '../../../routes/v1/admin/communities/schema.js'; +import { processUploadToIpfs } from '../../../services/data/processing.js'; + +const logger = parentLogger.child({ module: 'Admin/Communities/controller' }); + +export const todoApi = async (_req: Request, res: Response, next: NextFunction) => { + new SuccessMessageResponse().send(res); +}; + +export const createCommunity = async (req: Request, res: Response, _next: NextFunction) => { + const body = req.body as Required['body']>; + + const exists = await communityService.findCommunityByNameOrSlug(body.slug); + if (exists) throw new DuplicateDataError(); + + let assets: { key: string; url: string }[]; + let uploads = Array.isArray(req.files) + ? req.files + : Object.values(req.files) + .map((files) => files[0]) + .filter(Boolean); + + if (uploads?.length > 0) { + uploads = uploads.map((file) => { + file.originalname = `${file.fieldname}.${file.originalname.split('.')?.[1]}`; + return file; + }); + logger.info({ uploads }, 'Uploads'); + const { ok, value } = await processUploadToIpfs({ files: uploads }); + if (ok && value) { + assets = value.map((ipfsImg) => ({ + key: ipfsImg.path, + url: `${process.env.IPFS_RESOLVER_OVERRIDE}/${ipfsImg.cid}`, + })); + } else { + throw new BadRequestError('Could not upload file to ipfs'); + } + } + + const image_url = assets?.find((img) => img.key.toLowerCase().includes('imageurl'))?.url || body.imageUrl; + delete body.imageUrl; + + if (!image_url) throw new BadRequestError('No community logo uploaded'); + + const hidden = body.hidden.toString() === 'true' ? true : false; + const community = await communityService.createCommunity({ ...body, hidden, image_url }); + new SuccessResponse(community).send(res); +}; + +export const updateCommunity = async (req: Request, res: Response, _next: NextFunction) => { + const body = req.body as Required['body']>; + const { communityId } = req.params as z.infer['params']; + logger.info({ body, communityId }, 'updateCommunity'); + + let community = await communityService.findCommunityById(+communityId); + + if (!community) throw new NotFoundError(); + + let assets: { key: string; url: string }[]; + let uploads = Array.isArray(req.files) + ? req.files + : Object.values(req.files) + ?.map((files) => files[0]) + .filter(Boolean); + + logger.info({ uploads: !!uploads }, 'Uploads'); + if (uploads?.length > 0) { + uploads = uploads.map((file) => { + file.originalname = `${file.fieldname}.${file.originalname.split('.')?.[1]}`; + return file; + }); + const { ok, value } = await processUploadToIpfs({ files: uploads }); + if (ok && value) { + assets = value.map((ipfsImg) => ({ + key: ipfsImg.path, + url: `${process.env.IPFS_RESOLVER_OVERRIDE}/${ipfsImg.cid}`, + })); + } else { + throw new BadRequestError('Could not upload file to ipfs'); + } + } + + // enforce strict non-empty check on image_url field + const image_url = + assets?.find((img) => img.key.toLowerCase().includes('imageurl'))?.url || body?.imageUrl || community.image_url; + delete body.imageUrl; + + if (!image_url) throw new BadRequestError('No community logo uploaded'); + const hidden = body.hidden.toString() === 'true' ? true : false; + + community = await communityService.updateCommunityById(+communityId, { ...body, hidden, image_url }); + new SuccessResponse(community).send(res); +}; + +export const listAllCommunities = async (_req: Request, res: Response, _next: NextFunction) => { + const communities = await communityService.adminGetCommunities(); + logger.info({ communities }, 'List communities'); + const data = await asyncMap(communities, async (community) => { + const engagements = await communityService.getCommunityEngagementSignals(community.id); + const verifiedEngagements = await communityService.getCommunityRadarEngagementSignal(community.id); + return { + ...community, + engagements, + verifiedEngagements, + }; + }); + new SuccessResponse(data).send(res); +}; + +export const createAttestation = async (req: Request, res: Response, _next: NextFunction) => { + const body = req.body as Required['body']>; + const { communityId } = req.params as z.infer['params']; + logger.info({ communityId, body }, 'Payload'); + + const community = await communityService.findCommunityById(Number(communityId)); + if (!community) throw new NotFoundError(`Community ${communityId} not found`); + + let assets: { key: string; url: string }[]; + let uploads = Array.isArray(req.files) + ? req.files + : Object.values(req.files) + .map((files) => files[0]) + .filter(Boolean); + + if (uploads) { + uploads = uploads.map((file) => { + file.originalname = `${file.fieldname}.${file.originalname.split('.')?.[1]}`; + return file; + }); + + const { ok, value } = await processUploadToIpfs({ files: uploads }); + if (ok && value) { + assets = value.map((ipfsImg) => ({ + key: ipfsImg.path, + url: `${process.env.IPFS_RESOLVER_OVERRIDE}/${ipfsImg.cid}`, + })); + } else { + throw new BadRequestError('Could not upload file to ipfs'); + } + } + + const image_url = assets.find((img) => img.key.toLowerCase().includes('imageurl'))?.url || body.imageUrl; + delete body.imageUrl; + const verified_image_url = + assets.find((img) => img.key.toLowerCase().includes('verifiedimageurl'))?.url || body.verifiedImageUrl; + delete body.verifiedImageUrl; + + logger.info({ image_url, verified_image_url }, 'Assets'); + + if (!image_url) throw new BadRequestError('No community logo uploaded'); + + const isProtected = body.protected.toString() === 'true' ? true : false; + const attestation = await attestationService.create({ + ...body, + image_url, + verified_image_url, + communityId: community.id, + protected: isProtected, + }); + new SuccessResponse(attestation).send(res); +}; + +export const updateAttestation = async (req: Request, res: Response, _next: NextFunction) => { + const body = req.body as Required['body']>; + const { attestationId } = req.params as z.infer['params']; + logger.info({ attestationId, body }, 'Payload'); + + const exists = await attestationService.findAttestationById(Number(attestationId)); + if (!exists) throw new NotFoundError(`Attestation ${attestationId} not found`); + + let assets: { key: string; url: string }[] | undefined; + let uploads = Array.isArray(req.files) + ? req.files + : Object.values(req.files) + .map((files) => files[0]) + .filter(Boolean); + + logger.info({ uploads: uploads?.map((up) => up.fieldname) }, 'Uploads'); + if (uploads?.length > 0) { + uploads = uploads.map((file) => { + file.originalname = `${file.fieldname}.${file.originalname.split('.')?.[1]}`; + return file; + }); + const { ok, value } = await processUploadToIpfs({ files: uploads }); + logger.info({ ok, value }, 'Uploads REsult'); + if (ok && value) { + assets = value.map((ipfsImg) => ({ + key: ipfsImg.path, + url: `${process.env.IPFS_RESOLVER_OVERRIDE}/${ipfsImg.cid}`, + })); + } else { + throw new BadRequestError('Could not upload file to ipfs'); + } + } + + const image_url = assets?.find((img) => img.key.toLowerCase().includes('imageurl'))?.url || body.imageUrl; + const verified_image_url = + assets?.find((img) => img.key.toLowerCase().includes('verifiedimageurl'))?.url || body.verifiedImageUrl; + delete body.imageUrl; + delete body.verifiedImageUrl; + + logger.info({ image_url, verified_image_url }, 'Assets'); + + if (!image_url) throw new BadRequestError('No attestation image uploaded'); + + const isProtected = body.protected.toString() === 'true' ? true : false; + const attestation = await attestationService.updateAttestation(exists.id, { + ...body, + image_url, + verified_image_url, + communityId: exists.communityId, + protected: isProtected, + }); + new SuccessResponse(attestation).send(res); +}; + +export const addMember = async (req: Request, res: Response, _next: NextFunction) => { + const { userId, role }: Required['body']> = req.body; + const { communityId }: z.infer['params'] = req.params; + + const user = await prisma.user.findFirst({ where: { id: userId } }); + if (!user) throw new NotFoundError('Invalid user'); + + const community = await communityService.findCommunityById(Number(communityId)); + if (!community) throw new NotFoundError(`No Desci community with ID: ${Number(communityId)} found!`); + + const exists = await communityService.findMemberByUserId(Number(communityId), userId); + if (exists) throw new DuplicateDataError(); + + const member = await communityService.addCommunityMember(parseInt(communityId), { + userId, + communityId: parseInt(communityId), + role, + }); + + new SuccessResponse(member).send(res); +}; + +export const removeMember = async (req: Request, res: Response, _next: NextFunction) => { + const { communityId, memberId }: z.infer['params'] = req.params; + + const community = await communityService.findCommunityById(Number(communityId)); + if (!community) throw new NotFoundError(`No Desci community with ID: ${Number(communityId)} found!`); + + const exists = await communityService.findMemberById(Number(memberId)); + if (!exists) throw new NotFoundError(); + + await communityService.removeMemberById(Number(memberId)); + + new SuccessMessageResponse().send(res); +}; + +export const addEntryAttestation = async (req: Request, res: Response, _next: NextFunction) => { + const { communityId, attestationId }: z.infer['params'] = req.params; + + const community = await communityService.findCommunityById(Number(communityId)); + if (!community) throw new NotFoundError(`No Desci community with ID: ${Number(communityId)} not found!`); + + const attestation = await attestationService.findAttestationById(+attestationId); + if (!attestation) throw new NotFoundError(`No attestation with ID: ${Number(attestationId)} not found!`); + + const exists = await attestationService.getCommunityEntryAttestation(Number(communityId), Number(attestationId)); + if (exists) throw new DuplicateDataError(); + + const data = await attestationService.addCommunityEntryAttestation({ + communityId: Number(communityId), + attestationId: Number(attestationId), + attestationVersion: attestation.AttestationVersion[attestation.AttestationVersion.length - 1].id, + }); + + new SuccessResponse(data).send(res); +}; + +export const removeEntryAttestation = async (req: Request, res: Response, _next: NextFunction) => { + const { communityId, attestationId }: z.infer['params'] = req.params; + + const attestation = await attestationService.findAttestationById(+attestationId); + if (!attestation) throw new NotFoundError(`No attestation with ID: ${Number(attestationId)} not found!`); + + const data = await attestationService.removeCommunityEntryAttestation({ + communityId: Number(communityId), + attestationId: Number(attestationId), + attestationVersion: attestation.AttestationVersion[attestation.AttestationVersion.length - 1].id, + }); + + new SuccessResponse(data).send(res); +}; diff --git a/desci-server/src/controllers/communities/util.ts b/desci-server/src/controllers/communities/util.ts index 71d135df6..e57bef7bb 100644 --- a/desci-server/src/controllers/communities/util.ts +++ b/desci-server/src/controllers/communities/util.ts @@ -32,7 +32,7 @@ export const resolveLatestNode = async (radar: Partial) => { const selectAttributes: (keyof typeof discovery)[] = ['ownerId', 'NodeCover']; const node: Partial = _.pick(discovery, selectAttributes); const publishedVersions = - (await prisma.$queryRaw`SELECT * from "NodeVersion" where "nodeId" = ${discovery.id} AND "transactionId" IS NOT NULL ORDER BY "createdAt" DESC`) as NodeVersion[]; + (await prisma.$queryRaw`SELECT * from "NodeVersion" where "nodeId" = ${discovery.id} AND ("transactionId" IS NOT NULL or "commitId" IS NOT NULL) ORDER BY "createdAt" DESC`) as NodeVersion[]; // const nodeVersions = (await getNodeVersion logger.info({ uuid: discovery.uuid, publishedVersions }, 'Resolve node'); @@ -61,13 +61,13 @@ export const resolveLatestNode = async (radar: Partial) => { }; export const getNodeVersion = async (uuid: string) => { - let indexingResults: { researchObjects: IndexedResearchObject[]}; + let indexingResults: { researchObjects: IndexedResearchObject[] }; try { indexingResults = await getIndexedResearchObjects([uuid]); const researchObject = indexingResults.researchObjects[0]; return researchObject?.versions?.length ?? 0; } catch (e) { - logger.error({ uuid, indexingResults }, "getNodeVersion failed"); + logger.error({ uuid, indexingResults }, 'getNodeVersion failed'); throw e; - }; + } }; diff --git a/desci-server/src/controllers/nodes/byDpid.ts b/desci-server/src/controllers/nodes/byDpid.ts index 10b575e24..b3a2077e0 100755 --- a/desci-server/src/controllers/nodes/byDpid.ts +++ b/desci-server/src/controllers/nodes/byDpid.ts @@ -14,6 +14,8 @@ type NodeByDpidParams = { type NodeByDpidSuccess = { uuid: string; + dpidAlias: number; + ceramicStream: string; }; type NodeByDpidError = { @@ -43,6 +45,8 @@ export const nodeByDpid = async ( node = await prisma.node.findFirstOrThrow({ select: { uuid: true, + dpidAlias: true, + ceramicStream: true, }, where: { dpidAlias: { diff --git a/desci-server/src/controllers/nodes/checkNodeAccess.ts b/desci-server/src/controllers/nodes/checkNodeAccess.ts index da59758e1..4f6c8feb6 100644 --- a/desci-server/src/controllers/nodes/checkNodeAccess.ts +++ b/desci-server/src/controllers/nodes/checkNodeAccess.ts @@ -13,8 +13,10 @@ type GetCheckNodeAccessResponse = { isOwner: boolean; isShared: boolean; hasAccess: boolean; - sharedOn?: number; isPublished: boolean; + ceramicStream?: string; + dpidAlias?: number; + sharedOn?: number; recentCid?: string; manifestUrl?: string; }; @@ -42,14 +44,10 @@ export const checkNodeAccess = async ( const node = await prisma.node.findFirst({ select: { uuid: true, - id: true, - createdAt: true, - updatedAt: true, ownerId: true, - title: true, manifestUrl: true, - cid: true, - NodeCover: true, + dpidAlias: true, + ceramicStream: true, versions: { select: { manifestUrl: true, @@ -92,6 +90,8 @@ export const checkNodeAccess = async ( isShared: !isOwner && !!privSharedNode, hasAccess, isPublished, + ceramicStream: node.ceramicStream, + dpidAlias: node.dpidAlias, sharedOn: privSharedNode?.createdAt.getTime(), recentCid: latestPublishedVersion?.manifestUrl, manifestUrl: hasAccess ? node.versions[0]?.manifestUrl : undefined, diff --git a/desci-server/src/core/ApiResponse.ts b/desci-server/src/core/ApiResponse.ts index 82a192182..bd81e30c7 100644 --- a/desci-server/src/core/ApiResponse.ts +++ b/desci-server/src/core/ApiResponse.ts @@ -24,7 +24,8 @@ export abstract class ApiResponse { protected prepare(res: Response, response: T, headers: { [key: string]: string }): Response { for (const [key, value] of Object.entries(headers)) res.append(key, value); - return res.status(this.status).json(ApiResponse.sanitize(response)); + const data = ApiResponse.sanitize(response); + return data ? res.status(this.status).json(data) : res.status(this.status).send(); } public send(res: Response, headers: Headers = {}): Response { @@ -35,8 +36,8 @@ export abstract class ApiResponse { const clone: T = {} as T; Object.assign(clone, response); delete clone.status; - for (const field in clone) if (clone[field] === 'undefined') delete clone[field]; - // if (!clone['message']) delete clone.message; + for (const field in clone) if (!clone[field]) delete clone[field]; + if (Object.keys(clone).length === 0) return undefined; return clone; } } diff --git a/desci-server/src/middleware/validator.ts b/desci-server/src/middleware/validator.ts index 2acafc15e..88b6a1f4f 100644 --- a/desci-server/src/middleware/validator.ts +++ b/desci-server/src/middleware/validator.ts @@ -1,7 +1,7 @@ import { NextFunction, Request, Response } from 'express'; import { ZodError, z } from 'zod'; -import { BadRequestError, InternalError, asyncHandler } from '../internal.js'; +import { BadRequestError, InternalError, asyncHandler, logger } from '../internal.js'; export const validate = (schema: z.ZodObject) => asyncHandler(async (req: Request, res: Response, next: NextFunction) => { @@ -9,6 +9,7 @@ export const validate = (schema: z.ZodObject) => await schema.parseAsync(req); next(); } catch (err) { + // logger.error({ body: req.body, file: req.file }, 'zod validator'); if (err instanceof ZodError) { console.log('Error', err); throw new BadRequestError( diff --git a/desci-server/src/routes/v1/admin.ts b/desci-server/src/routes/v1/admin.ts deleted file mode 100644 index 35b3c37a5..000000000 --- a/desci-server/src/routes/v1/admin.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Router } from 'express'; - -import { createCsv, getAnalytics } from '../../controllers/admin/analytics.js'; -import { debugAllNodesHandler, debugNodeHandler } from '../../controllers/admin/debug.js'; -import { listDoiRecords } from '../../internal.js'; -import { ensureAdmin } from '../../middleware/ensureAdmin.js'; -import { ensureUser } from '../../middleware/permissions.js'; - -const router = Router(); - -router.get('/analytics', [ensureUser, ensureAdmin], getAnalytics); -router.get('/analytics/csv', [ensureUser, ensureAdmin], createCsv); -router.get('/doi/list', [ensureUser, ensureAdmin], listDoiRecords); - -router.get('/debug', [ensureUser, ensureAdmin], debugAllNodesHandler); -router.get('/debug/:uuid', [ensureUser, ensureAdmin], debugNodeHandler); - -export default router; diff --git a/desci-server/src/routes/v1/admin/communities/index.ts b/desci-server/src/routes/v1/admin/communities/index.ts new file mode 100644 index 000000000..d6acaa0bb --- /dev/null +++ b/desci-server/src/routes/v1/admin/communities/index.ts @@ -0,0 +1,126 @@ +import { NextFunction, Response, Router } from 'express'; +import { Request } from 'express'; +import multer from 'multer'; +import multerS3 from 'multer-s3'; + +import { + addEntryAttestation, + addMember, + createAttestation, + createCommunity, + listAllCommunities, + removeEntryAttestation, + removeMember, + updateAttestation, + updateCommunity, +} from '../../../../controllers/admin/communities/index.js'; +import { asyncHandler, ensureAdmin, ensureUser, logger as parentLogger, validate } from '../../../../internal.js'; +import { isS3Configured, s3Client } from '../../../../services/s3.js'; + +import { + addAttestationSchema, + addCommunitySchema, + addEntryAttestationSchema, + addMemberSchema, + removeMemberSchema, + updateAttestationSchema, + updateCommunitySchema, +} from './schema.js'; + +const logger = parentLogger.child({ module: 'Admin/communities' }); +const router = Router(); + +const upload = isS3Configured + ? multer({ + preservePath: true, + storage: multerS3({ + s3: s3Client, + bucket: process.env.AWS_S3_BUCKET_NAME, + key: (req, file, cb) => { + // const userId = (req as any).user.id; + const { name, communitySlug } = (req as any).body; + if (!name || !name) { + cb(new Error('Missing required params to form key')); + } + const key = `${communitySlug}${name ? +'/' + name : ''}/${file.filename}`; // adjust for dir uploads, doesn't start with '/' + logger.info({ fileName: key }, 'Upload asset'); + cb(null, key); + }, + }), + }) + : multer({ preservePath: true }); + +const uploadHandler = upload.fields([ + { name: 'imageUrl', maxCount: 1 }, + { name: 'verifiedImageUrl', maxCount: 1 }, +]); + +const wrappedHandler = (req: Request, res: Response, next: NextFunction) => { + uploadHandler(req, res, (err) => { + if (err) { + if (err instanceof multer.MulterError) { + throw err; + } else { + logger.error({ err }, 'Upload Handler Error encountered'); + res.status(401).send({ msg: 'unauthorized' }); + return; + } + } + next(); + }); +}; + +const sanitizeBody = async (req: Request, _res: Response, next: NextFunction) => { + logger.info({ body: req.body }, 'sanitizeBody'); + req.body?.keywords ? (req.body.keywords = JSON.parse(req.body.keywords)) : null; + req.body?.links ? (req.body.links = JSON.parse(req.body.links)) : null; + next(); +}; + +router.get('/', [ensureUser, ensureAdmin], asyncHandler(listAllCommunities)); + +router.post( + '/', + [ensureUser, ensureAdmin, wrappedHandler, sanitizeBody, validate(addCommunitySchema)], + asyncHandler(createCommunity), +); + +router.put( + '/:communityId', + [ensureUser, ensureAdmin, wrappedHandler, sanitizeBody, validate(updateCommunitySchema)], + asyncHandler(updateCommunity), +); + +router.post( + '/:communityId/attestations', + [ensureUser, ensureAdmin, wrappedHandler, validate(addAttestationSchema)], + asyncHandler(createAttestation), +); + +router.put( + '/:communityId/attestations/:attestationId', + [ensureUser, ensureAdmin, wrappedHandler, validate(updateAttestationSchema)], + asyncHandler(updateAttestation), +); + +router.post('/:communityId/members', [ensureUser, ensureAdmin, validate(addMemberSchema)], asyncHandler(addMember)); + +router.delete( + '/:communityId/members/:memberId', + [ensureUser, ensureAdmin, validate(removeMemberSchema)], + asyncHandler(removeMember), +); + +router.post( + '/:communityId/addEntryAttestation/:attestationId', + [ensureUser, ensureAdmin, validate(addEntryAttestationSchema)], + asyncHandler(addEntryAttestation), +); + +router.delete( + '/:communityId/removeEntryAttestation/:attestationId', + [ensureUser, ensureAdmin, validate(addEntryAttestationSchema)], + asyncHandler(removeEntryAttestation), +); + +export default router; diff --git a/desci-server/src/routes/v1/admin/communities/schema.ts b/desci-server/src/routes/v1/admin/communities/schema.ts new file mode 100644 index 000000000..1c3467e13 --- /dev/null +++ b/desci-server/src/routes/v1/admin/communities/schema.ts @@ -0,0 +1,81 @@ +import { CommunityMembershipRole } from '@prisma/client'; +import { z } from 'zod'; + +export const addCommunitySchema = z.object({ + body: z.object({ + name: z.string(), + subtitle: z.string().min(1, 'Subtitle cannot be empty'), + description: z.string().min(1, 'Description cannot be empty'), + hidden: z.coerce + .boolean() + .transform((value) => (value.toString() === 'true' ? true : false)) + .default(false), + keywords: z.array(z.string()).min(1, 'Community must have at least one keyword'), + imageUrl: z.string().url().optional(), //"https://pub.desci.com/ipfs/bafkreie7kxhzpzhsbywcrpgyv5yvy3qxcjsibuxsnsh5olaztl2uvnrzx4", + slug: z.string().min(3), + links: z.array(z.string().url()), + }), +}); + +export const updateCommunitySchema = z.object({ + body: z.object({ + name: z.string().optional(), + subtitle: z.string().min(1, 'Subtitle cannot be empty').optional(), + description: z.string().min(1, 'Description cannot be empty').optional(), + hidden: z.coerce + .boolean() + .transform((value) => (value.toString() === 'true' ? true : false)) + .default(false), + keywords: z.array(z.string()).min(1, 'Community must have at least one keyword').optional(), + imageUrl: z.string().url().optional(), //"https://pub.desci.com/ipfs/bafkreie7kxhzpzhsbywcrpgyv5yvy3qxcjsibuxsnsh5olaztl2uvnrzx4", + slug: z.string().min(3).optional(), + links: z.array(z.string().url()).optional(), + }), + params: z.object({ + communityId: z.coerce.number(), + }), +}); + +export const addAttestationSchema = z.object({ + params: z.object({ + communityId: z.coerce.number(), + }), + body: z.object({ + name: z.string(), + description: z.string(), + imageUrl: z.string().url().optional(), //"https://pub.desci.com/ipfs/bafkreie7kxhzpzhsbywcrpgyv5yvy3qxcjsibuxsnsh5olaztl2uvnrzx4", + verifiedImageUrl: z.string().url().optional(), //"https://pub.desci.com/ipfs/bafkreie7kxhzpzhsbywcrpgyv5yvy3qxcjsibuxsnsh5olaztl2uvnrzx4", + protected: z.coerce + .boolean() + .transform((value) => (value.toString() === 'true' ? true : false)) + .default(false), + }), +}); + +export const updateAttestationSchema = addAttestationSchema.extend({ + params: z.object({ attestationId: z.coerce.number(), communityId: z.coerce.number() }), +}); + +export const addMemberSchema = z.object({ + params: z.object({ + communityId: z.string(), + }), + body: z.object({ + userId: z.number(), + role: z.enum([CommunityMembershipRole.ADMIN, CommunityMembershipRole.MEMBER]), + }), +}); + +export const removeMemberSchema = z.object({ + params: z.object({ + communityId: z.coerce.number(), + memberId: z.coerce.number(), + }), +}); + +export const addEntryAttestationSchema = z.object({ + params: z.object({ + communityId: z.coerce.number(), + attestationId: z.coerce.number(), + }), +}); diff --git a/desci-server/src/routes/v1/admin/index.ts b/desci-server/src/routes/v1/admin/index.ts new file mode 100644 index 000000000..561a9e111 --- /dev/null +++ b/desci-server/src/routes/v1/admin/index.ts @@ -0,0 +1,22 @@ +import { Router } from 'express'; + +import { createCsv, getAnalytics } from '../../../controllers/admin/analytics.js'; +import { debugAllNodesHandler, debugNodeHandler } from '../../../controllers/admin/debug.js'; +import { listDoiRecords } from '../../../internal.js'; +import { ensureAdmin } from '../../../middleware/ensureAdmin.js'; +import { ensureUser } from '../../../middleware/permissions.js'; + +import communities from './communities/index.js'; + +const router = Router(); + +router.get('/analytics', [ensureUser, ensureAdmin], getAnalytics); +router.get('/analytics/csv', [ensureUser, ensureAdmin], createCsv); +router.get('/doi/list', [ensureUser, ensureAdmin], listDoiRecords); + +router.get('/debug', [ensureUser, ensureAdmin], debugAllNodesHandler); +router.get('/debug/:uuid', [ensureUser, ensureAdmin], debugNodeHandler); + +router.use('/communities', [ensureUser, ensureAdmin], communities); + +export default router; diff --git a/desci-server/src/routes/v1/index.ts b/desci-server/src/routes/v1/index.ts index a87e0ebae..616777fc6 100755 --- a/desci-server/src/routes/v1/index.ts +++ b/desci-server/src/routes/v1/index.ts @@ -10,7 +10,7 @@ import { nft } from '../../controllers/raw/nft.js'; import { asyncHandler } from '../../internal.js'; import { ensureUser } from '../../middleware/permissions.js'; -import admin from './admin.js'; +import admin from './admin/index.js'; import attestations from './attestations/index.js'; import auth from './auth.js'; import communities from './communities/index.js'; diff --git a/desci-server/src/server.ts b/desci-server/src/server.ts index 392fecc1a..172964d54 100644 --- a/desci-server/src/server.ts +++ b/desci-server/src/server.ts @@ -7,6 +7,7 @@ import type { Server as HttpServer } from 'http'; // import path from 'path'; import * as Sentry from '@sentry/node'; +import { nodeProfilingIntegration } from '@sentry/profiling-node'; import * as Tracing from '@sentry/tracing'; import bodyParser from 'body-parser'; import cookieParser from 'cookie-parser'; @@ -224,15 +225,14 @@ class AppServer { Sentry.init({ dsn: 'https://d508a5c408f34b919ccd94aac093e076@o1330109.ingest.sentry.io/6619754', release: 'desci-nodes-server@' + process.env.npm_package_version, - integrations: [new Tracing.Integrations.Prisma({ client: prisma })], + integrations: [Sentry.prismaIntegration(), nodeProfilingIntegration()], // Set tracesSampleRate to 1.0 to capture 100% // of transactions for performance monitoring. // We recommend adjusting this value in production tracesSampleRate: 1.0, + profilesSampleRate: 1.0, }); - this.app.use(Sentry.Handlers.requestHandler()); - this.app.use(Sentry.Handlers.tracingHandler()); - this.app.use(Sentry.Handlers.errorHandler()); + Sentry.setupExpressErrorHandler(this.app); } else { logger.info('[DeSci Nodes] Telemetry disabled'); } diff --git a/desci-server/src/services/Attestation.ts b/desci-server/src/services/Attestation.ts index 475f58be1..e25bac597 100644 --- a/desci-server/src/services/Attestation.ts +++ b/desci-server/src/services/Attestation.ts @@ -17,6 +17,7 @@ import { DuplicateReactionError, DuplicateVerificationError, NoAccessError, + NotFoundError, VerificationError, VerificationNotFoundError, ensureUuidEndsWithDot, @@ -74,7 +75,7 @@ export class AttestationService { const node = await prisma.node.findFirst({ where: { uuid: nodeUuid } }); const publishedNodeVersions = - (await prisma.$queryRaw`SELECT COUNT(*) from "NodeVersion" where "nodeId" = ${node.id} AND "transactionId" IS NOT NULL`) as number; + (await prisma.$queryRaw`SELECT COUNT(*) from "NodeVersion" where "nodeId" = ${node.id} AND ("transactionId" IS NOT NULL or "commitId" IS NOT NULL)`) as number; if (nodeVersion >= publishedNodeVersions) { logger.warn({ nodeVersion, publishedNodeVersions }, 'Invalid Node version'); @@ -171,7 +172,10 @@ export class AttestationService { const attestation = await this.findAttestationById(attestationId); if (!attestation) throw new AttestationNotFoundError(); - + await prisma.attestation.update({ + where: { id: attestationId }, + data: { verified_image_url: data.verified_image_url }, + }); await this.#publishVersion({ name: data.name as string, description: data.description, @@ -236,6 +240,23 @@ export class AttestationService { }); } + async removeCommunityEntryAttestation({ + communityId, + attestationId, + attestationVersion: version, + }: { + communityId: number; + attestationId: number; + attestationVersion: number; + }) { + const existingSelection = await prisma.communityEntryAttestation.findFirst({ + where: { desciCommunityId: communityId, attestationId, attestationVersionId: version }, + }); + if (!existingSelection) return null; + + return await prisma.communityEntryAttestation.delete({ where: { id: existingSelection.id } }); + } + async getAllNodeAttestations(uuid: string) { return prisma.nodeAttestation.findMany({ where: { nodeUuid: ensureUuidEndsWithDot(uuid), revoked: false }, @@ -297,6 +318,12 @@ export class AttestationService { }); } + async getCommunityEntryAttestation(communityId: number, attestationId: number) { + return prisma.communityEntryAttestation.findFirst({ + where: { desciCommunityId: communityId, attestationId, required: true }, + }); + } + async getCommunityEntryAttestations(communityId: number) { const community = await communityService.findCommunityById(communityId); if (!community) throw new CommunityNotFoundError(); diff --git a/desci-server/src/services/Communities.ts b/desci-server/src/services/Communities.ts index 8b3114251..6e9a467aa 100644 --- a/desci-server/src/services/Communities.ts +++ b/desci-server/src/services/Communities.ts @@ -1,5 +1,5 @@ import { Attestation, CommunityMembershipRole, NodeAttestation, NodeFeedItem, Prisma } from '@prisma/client'; -import _ from 'lodash'; +import _, { includes } from 'lodash'; import { prisma } from '../client.js'; import { DuplicateDataError, logger } from '../internal.js'; @@ -18,6 +18,22 @@ export class CommunityService { return community; } + async adminGetCommunities() { + return prisma.desciCommunity.findMany({ + orderBy: { createdAt: 'asc' }, + include: { + CommunityMember: { + select: { id: true, role: true, userId: true, user: { select: { name: true, userOrganizations: true } } }, + orderBy: { role: 'asc' }, + }, + CommunityEntryAttestation: { + select: { id: true, attestationVersion: { select: { name: true, image_url: true } } }, + orderBy: { createdAt: 'asc' }, + }, + }, + }); + } + async getAllCommunities() { return prisma.desciCommunity.findMany({ select: { @@ -72,6 +88,13 @@ export class CommunityService { }); } + async updateCommunityById(id: number, community: Prisma.DesciCommunityUpdateInput) { + return prisma.desciCommunity.update({ + where: { id }, + data: community, + }); + } + /** * This query retrieves data from the "NodeAttestation" table along with the counts of related records from the * "Annotation", "NodeAttestationReaction", and "NodeAttestationVerification" tables. @@ -295,9 +318,17 @@ export class CommunityService { return await prisma.communityMember.findUnique({ where: { userId_communityId: { userId, communityId } } }); } + async findMemberById(id: number) { + return await prisma.communityMember.findUnique({ where: { id } }); + } + async removeMember(communityId: number, userId: number) { return prisma.communityMember.delete({ where: { userId_communityId: { userId, communityId } } }); } + + async removeMemberById(id: number) { + return prisma.communityMember.delete({ where: { id } }); + } } export const communityService = new CommunityService(); diff --git a/desci-server/src/services/ElasticSearchService.ts b/desci-server/src/services/ElasticSearchService.ts index 492369b8f..9a9a84383 100644 --- a/desci-server/src/services/ElasticSearchService.ts +++ b/desci-server/src/services/ElasticSearchService.ts @@ -61,6 +61,8 @@ export const RELEVANT_FIELDS = { ], }; +const NESTED_WORKS_ENTITIES = ['authors', 'best_locations', 'concepts', 'locations', 'topics', 'sources']; + type SortOrder = 'asc' | 'desc'; type SortField = { [field: string]: { order: SortOrder; missing?: string | number; type?: string; script?: any } }; @@ -192,7 +194,7 @@ function buildFilter(filter: Filter) { }; case 'term': const termFieldParts = filter.field.split('.'); - const isNested = termFieldParts.length > 1; + const isNested = NESTED_WORKS_ENTITIES.includes(termFieldParts[0]); const queryType = Array.isArray(filter.value) ? 'terms' : 'term'; let valFormatted = filter.value; if (Array.isArray(valFormatted)) { @@ -213,15 +215,24 @@ function buildFilter(filter: Filter) { } return query; case 'match_phrase': + const fieldParts = filter.field.split('.'); + const isNestedMatchPhrase = NESTED_WORKS_ENTITIES.includes(fieldParts[0]); + if (Array.isArray(filter.value)) { - const queries = filter.value.map((value) => ({ - nested: { - path: filter.field.split('.')[0], - query: { - match_phrase: { [filter.field]: { query: value, analyzer: 'edge_ngram_analyzer' } }, - }, - }, - })); + const queries = filter.value.map((value) => { + if (isNestedMatchPhrase) { + return { + nested: { + path: fieldParts[0], + query: { + match_phrase: { [filter.field]: { query: value, analyzer: 'edge_ngram_analyzer' } }, + }, + }, + }; + } else { + return { match_phrase: { [filter.field]: { query: value, analyzer: 'edge_ngram_analyzer' } } }; + } + }); return { bool: { @@ -231,8 +242,7 @@ function buildFilter(filter: Filter) { }; } - const fieldParts = filter.field.split('.'); - if (fieldParts.length > 1) { + if (isNestedMatchPhrase) { return { nested: { path: fieldParts[0], @@ -242,17 +252,34 @@ function buildFilter(filter: Filter) { }, }; } + return { match_phrase: { [filter.field]: { query: filter.value, analyzer: 'edge_ngram_analyzer' } } }; case 'match': - const matchQuery = { - match: { - [filter.field]: { - query: filter.value, - operator: filter.matchLogic || 'or', - // ...(filter.fuzziness && { fuzziness: filter.fuzziness }), + let matchQuery; + if (Array.isArray(filter.value)) { + matchQuery = { + bool: { + should: filter.value.map((value) => ({ + match: { + [filter.field]: { + query: value, + operator: filter.matchLogic || 'or', + }, + }, + })), + minimum_should_match: 1, }, - }, - }; + }; + } else { + matchQuery = { + match: { + [filter.field]: { + query: filter.value, + operator: filter.matchLogic || 'or', + }, + }, + }; + } if (filter.field.includes('.') && !filter.field.includes('institutions')) { const [nestedPath, nestedField] = filter.field.split('.'); diff --git a/desci-server/src/services/auth.ts b/desci-server/src/services/auth.ts index 3145f4e20..193df0ea7 100644 --- a/desci-server/src/services/auth.ts +++ b/desci-server/src/services/auth.ts @@ -124,7 +124,7 @@ const sendMagicLinkEmail = async (email: string, ip?: string) => { }); if (env.SHOULD_SEND_EMAIL) { - logger.info({ fn: 'sendMagicLinkEmail', email, token }, `Sending actual email to ${email} token: ${token}`); + logger.info({ fn: 'sendMagicLinkEmail', email }, `Sending actual email`); const url = `${env.DAPP_URL}/web/login?e=${email}&c=${token}`; const goodIp = ip?.length > 0 && ip !== '::1' && ip !== '127.0.0.1' && ip !== 'localhost'; diff --git a/desci-server/src/services/data/processing.ts b/desci-server/src/services/data/processing.ts index 254545b03..b17c5f9bb 100644 --- a/desci-server/src/services/data/processing.ts +++ b/desci-server/src/services/data/processing.ts @@ -348,7 +348,7 @@ export function extractRootDagCidFromManifest(manifest: ResearchObjectV1, manife } export async function getManifestFromNode( - node: { manifestUrl: string, cid?: string }, + node: { manifestUrl: string; cid?: string }, queryString?: string, ): Promise<{ manifest: ResearchObjectV1; manifestCid: string }> { // debugger; @@ -434,7 +434,7 @@ export async function pinNewFiles(files: any[], wrapWithDirectory = false): Prom if (structuredFilesForPinning.length) { if (structuredFilesForPinning.length) uploaded = await pinDirectory(structuredFilesForPinning, wrapWithDirectory); if (!uploaded.length) throw createIpfsUploadFailureError(); - logger.info('[UPDATE DATASET] Pinned files: ', uploaded.length); + logger.info({ uploaded }, '[UPDATE DATASET] Pinned files: '); } return uploaded; } @@ -748,3 +748,36 @@ export async function assignTypeMapInManifest( return manifest; } } + +/** + * Proccesses regular file uploads, pins S3 files to IPFS, adds them to the end of the context DAG node, creates data references for them and updates the manifest. + */ +export async function processUploadToIpfs({ + files, +}: { + files: + | { + [fieldname: string]: Express.Multer.File[]; + } + | Express.Multer.File[]; +}): Promise> { + let pinResult: IpfsPinnedResult[] = []; + try { + const uploads = Array.isArray(files) ? files : Object.values(files).map((files) => files[0]); + // Pin new files, add draftNodeTree entries + pinResult = await pinNewFiles(uploads, false); + if (pinResult) { + logger.info({ pinResult }, 'Files uploaded to Ipfs'); + } + + return { + ok: true, + value: pinResult, + }; + // SUCCESS + } catch (error) { + logger.error({ error }, 'Error processing S3 data to IPFS'); + const controlledErr = 'type' in error ? error : createUnhandledError(error); + return { ok: false, value: controlledErr }; + } +} diff --git a/desci-server/src/services/orcid.ts b/desci-server/src/services/orcid.ts index c3cc0a60a..751be20d6 100644 --- a/desci-server/src/services/orcid.ts +++ b/desci-server/src/services/orcid.ts @@ -54,7 +54,6 @@ class OrcidApiService { throw new Error('User does not have an orcid auth token'); } - // todo: refresh token if necessary try { const url = `https://${ORCID_DOMAIN}/oauth/token`; @@ -125,6 +124,9 @@ class OrcidApiService { * @returns */ async removeClaimRecord({ claimId, nodeUuid, orcid }: { claimId: number; nodeUuid: string; orcid: string }) { + const user = await prisma.user.findUnique({ where: { orcid } }); + const authToken = await this.getAccessToken(user.id); + const putCode = await prisma.orcidPutCodes.findFirst({ where: { claimId, @@ -133,18 +135,13 @@ class OrcidApiService { }, }); - if (!putCode) return; - - const user = await prisma.user.findUnique({ where: { orcid } }); - const authToken = await this.getAccessToken(user.id); - logger.info({ userId: user.id, authToken: !!authToken, nodeUuid }, '[ORCID::DELETE]:: START'); + // remove claim record on Orcid profile + if (putCode) { + logger.info({ userId: user.id, authToken: !!authToken, nodeUuid }, '[ORCID::DELETE]:: START'); - await this.removeWorkRecord({ orcid, putCode, authToken }); + await this.removeWorkRecord({ orcid, putCode, authToken }); + } - const { researchObjects } = await getIndexedResearchObjects([nodeUuid]); - const researchObject = researchObjects[0] as IndexedResearchObject; - const manifestCid = hexToCid(researchObject.recentCid); - const latestManifest = await getManifestByCid(manifestCid); let claims = await attestationService.getProtectedNodeClaims(nodeUuid); claims = claims.filter((claim) => claim.verifications > 0); logger.info({ claims: claims.length }, '[ORCID::DELETE]:: CHECK CLAIMS'); @@ -185,7 +182,7 @@ class OrcidApiService { code, orcid, }, - 'ORCID API DELETE RECORD', + 'ORCID API DELETE WORK RECORD', ); const response = await fetch(url, { method: 'DELETE', @@ -253,8 +250,14 @@ class OrcidApiService { let claims = await attestationService.getProtectedNodeClaims(nodeUuid); claims = claims.filter((claim) => claim.verifications > 0); - // TODO: if claims is empty remove orcid record - if (claims.length === 0) return; + if (claims.length === 0) { + const orcidPutCode = await prisma.orcidPutCodes.findUnique({ + where: { orcid_uuid_reference: { orcid, uuid: nodeUuid, reference: PutcodeReference.PREPRINT } }, + }); + + await orcidApiService.removeWorkRecord({ authToken, putCode: orcidPutCode, orcid: user.orcid }); + return; + } const latestVersion = researchObject.versions[researchObject.versions.length - 1]; const publicationDate = new Date(parseInt(latestVersion.time) * 1000).toLocaleDateString().replaceAll('/', '-'); @@ -270,8 +273,9 @@ class OrcidApiService { manifest: latestManifest, }); const claimRecordPromises = claims.map((claim) => { - const claimedVersionNumber = claims[claims.length - 1].nodeVersion; - const claimedVersion = researchObject.versions[claimedVersionNumber]; + const versionIndex = claims[claims.length - 1].nodeVersion; + const claimedVersionNumber = versionIndex + 1; + const claimedVersion = researchObject.versions[versionIndex]; const publicationDate = new Date(parseInt(claimedVersion.time) * 1000) .toLocaleDateString() .replaceAll('/', '-'); diff --git a/desci-server/src/services/repoService.ts b/desci-server/src/services/repoService.ts index 2c9a75557..9a6cdcb7c 100644 --- a/desci-server/src/services/repoService.ts +++ b/desci-server/src/services/repoService.ts @@ -85,12 +85,15 @@ class RepoService { } async getDraftDocument(arg: { uuid: NodeUuid }) { + if (!arg.uuid) { + logger.warn({ arg }, 'Attempt to retrieve draft manifest for empty UUID'); + return null; + } logger.info({ arg }, 'Retrieve Draft Document'); try { const response = await this.#client.get>( `${this.baseUrl}/v1/nodes/documents/draft/${arg.uuid}`, ); - logger.info({ response: response.status }, 'Draft Retrieval Response'); if (response.status === 200 && response.data.ok) { return response.data.document; } else { diff --git a/desci-server/src/theGraph.ts b/desci-server/src/theGraph.ts index 1e3cf9475..709b3b36e 100644 --- a/desci-server/src/theGraph.ts +++ b/desci-server/src/theGraph.ts @@ -77,7 +77,7 @@ export const getIndexedResearchObjects = async ( For stream resolution, build a map to allow for also returning the UUID to match the format returned by the graph lookup */ - const streamLookupMap: Record = {}; + let streamLookupMap: Record = {}; /** For legacy nodes, the graph lookup only needs the UUID */ const legacyUuids = []; @@ -100,6 +100,16 @@ export const getIndexedResearchObjects = async ( } } + /** + * fallback to _getIndexedResearchObjects() when resolving locally + * because calls to getHistoryFromStreams() never returns due to + * RESOLVER_URL not configured for local dpid resolution + */ + if (process.env.NODE_ENV === 'dev') { + legacyUuids.push(...paddedUuids); + streamLookupMap = {}; + } + let streamHistory = []; if (Object.keys(streamLookupMap).length > 0) { logger.info({ streamLookupMap }, 'Querying resolver for history'); @@ -109,7 +119,7 @@ export const getIndexedResearchObjects = async ( let legacyHistory = []; if (legacyUuids.length > 0) { - logger.info({ legacyUuids }, 'Falling back to subgraph query for history'); + logger.info({ legacyUuids, _urlSafeBase64s }, 'Falling back to subgraph query for history'); legacyHistory = (await _getIndexedResearchObjects(legacyUuids)).researchObjects; logger.info({ legacyHistory }, 'Subgraph history for nodes found'); } @@ -201,7 +211,7 @@ export const _getIndexedResearchObjects = async ( export const getTimeForTxOrCommits = async (txOrCommits: string[]): Promise> => { const isTx = (id: string) => id.startsWith('0x'); const txIds = txOrCommits.filter(isTx); - const commitIdStrs = txOrCommits.filter(id => !isTx(id)); + const commitIdStrs = txOrCommits.filter((id) => !isTx(id)); const commitTimeMap = await getCommitTimestamps(commitIdStrs); const txTimeMap = await getTxTimestamps(txIds); @@ -221,15 +231,15 @@ const getTxTimestamps = async (txIds: string[]): Promise> try { const graphTxTimestamps = await getTxTimeFromGraph(txIds); const timeMap = graphTxTimestamps.reduce( - (acc, { id, time }) => ({ ...acc, [id]: time}), + (acc, { id, time }) => ({ ...acc, [id]: time }), {} as Record, ); return timeMap; } catch (err) { logger.error({ txIds, err }, 'failed to get tx timestamps from graph, returning empty map'); return {}; - }; -} + } +}; type TransactionsWithTimestamp = { researchObjectVersions: { id: string; time: string }[]; diff --git a/desci-server/src/types/ProcessEnv.d.ts b/desci-server/src/types/ProcessEnv.d.ts index e7fe3592b..35ac96f86 100755 --- a/desci-server/src/types/ProcessEnv.d.ts +++ b/desci-server/src/types/ProcessEnv.d.ts @@ -20,5 +20,6 @@ declare namespace NodeJS { CROSSREF_API_KEY: string; AUTOMATED_METADATA_API: string; AUTOMATED_METADATA_API_KEY: string; + IPFS_RESOLVER_OVERRIDE: string; } } diff --git a/desci-server/tsconfig.json b/desci-server/tsconfig.json index 6b32eb774..c0d0c4e60 100755 --- a/desci-server/tsconfig.json +++ b/desci-server/tsconfig.json @@ -13,6 +13,7 @@ // "verbatimModuleSyntax": true, "lib": ["esnext", "dom"], + "outDir": "./dist", "removeComments": true, "emitDecoratorMetadata": true, @@ -21,14 +22,23 @@ "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "skipLibCheck": true, + // dagConcat.cjs requires this "allowJs": true, - "inlineSourceMap": true, + "paths": { // Overrides a built-in Response type "express": ["./src/types/express"] }, - "jsx": "react" + + "jsx": "react", + "sourceMap": true, + "inlineSources": true, + + // Set `sourceRoot` to "/" to strip the build path prefix + // from generated source code references. + // This improves issue grouping in Sentry. + "sourceRoot": "/" }, "include": ["./src/**/*.tsx", "./src/**/*.ts", "./src/**/*.cjs", "src/utils/dagConcat.ts"], "exclude": ["test/**/*.ts"], diff --git a/desci-server/yarn.lock b/desci-server/yarn.lock index 86f1570b4..73dfed96f 100644 --- a/desci-server/yarn.lock +++ b/desci-server/yarn.lock @@ -3605,7 +3605,21 @@ dependencies: "@opentelemetry/api" "^1.0.0" -"@opentelemetry/api@1.x": +"@opentelemetry/api-logs@0.52.1": + version "0.52.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz#52906375da4d64c206b0c4cb8ffa209214654ecc" + integrity sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A== + dependencies: + "@opentelemetry/api" "^1.0.0" + +"@opentelemetry/api-logs@0.53.0": + version "0.53.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.53.0.tgz#c478cbd8120ec2547b64edfa03a552cfe42170be" + integrity sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw== + dependencies: + "@opentelemetry/api" "^1.0.0" + +"@opentelemetry/api@1.x", "@opentelemetry/api@^1.8", "@opentelemetry/api@^1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== @@ -3674,6 +3688,11 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-1.8.0.tgz#6141ff59f7c07fac8eda3f9f208b6aaf06893471" integrity sha512-ueLmocbWDi1aoU4IPdOQyt4qz/Dx+NYyU4qoa3d683usbnkDLUXYXJFfKIMPFV2BbrI5qtnpTtzErCKewoM8aw== +"@opentelemetry/context-async-hooks@^1.25.1": + version "1.26.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-1.26.0.tgz#fa92f722cf685685334bba95f258d3ef9fce60f6" + integrity sha512-HedpXXYzzbaoutw6DFLWLDket2FwLkLpil4hGCZ1xYEIMTcivdfwEOISgdbLEWyG3HW52gTq2V9mOVJrONgiwg== + "@opentelemetry/core@1.14.0": version "1.14.0" resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.14.0.tgz#64e876b29cb736c984d54164cd47433f513eafd3" @@ -3702,6 +3721,13 @@ dependencies: "@opentelemetry/semantic-conventions" "1.25.0" +"@opentelemetry/core@1.26.0", "@opentelemetry/core@^1.1.0", "@opentelemetry/core@^1.25.1": + version "1.26.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.26.0.tgz#7d84265aaa850ed0ca5813f97d831155be42b328" + integrity sha512-1iKxXXE8415Cdv0yjG3G6hQnB5eVEsJce3QaawX8SjDn0mAS0ZM8fAbZZJD4ajvhC15cePvosSCut404KrIIvQ== + dependencies: + "@opentelemetry/semantic-conventions" "1.27.0" + "@opentelemetry/core@1.8.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.8.0.tgz#cca18594dd48ded6dc0d08c7e789c79af0315934" @@ -3896,6 +3922,15 @@ "@opentelemetry/instrumentation" "^0.40.0" "@opentelemetry/semantic-conventions" "^1.0.0" +"@opentelemetry/instrumentation-amqplib@^0.42.0": + version "0.42.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.42.0.tgz#b3cab5a7207736a30d769962eed3af3838f986c4" + integrity sha512-fiuU6OKsqHJiydHWgTRQ7MnIrJ2lEqsdgFtNIH4LbAUJl/5XmrIeoDzDnox+hfkgWK65jsleFuQDtYb5hW1koQ== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-aws-lambda@^0.35.3": version "0.35.3" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.35.3.tgz#19c42ba680f93a595a38edb06b28bac2b7da6f92" @@ -3933,6 +3968,16 @@ "@opentelemetry/instrumentation" "^0.40.0" "@opentelemetry/semantic-conventions" "^1.0.0" +"@opentelemetry/instrumentation-connect@0.39.0": + version "0.39.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.39.0.tgz#32bdbaac464cba061c95df6c850ee81efdd86f8b" + integrity sha512-pGBiKevLq7NNglMgqzmeKczF4XQMTOUOTkK8afRHMZMnrK3fcETyTH7lVaSozwiOM3Ws+SuEmXZT7DYrrhxGlg== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@types/connect" "3.4.36" + "@opentelemetry/instrumentation-connect@^0.31.4": version "0.31.4" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.31.4.tgz#c1693d26f103dc133cb6a9708cc9ed2fda288a52" @@ -3943,6 +3988,13 @@ "@opentelemetry/semantic-conventions" "^1.0.0" "@types/connect" "3.4.35" +"@opentelemetry/instrumentation-dataloader@0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.12.0.tgz#de03a3948dec4f15fed80aa424d6bd5d6a8d10c7" + integrity sha512-pnPxatoFE0OXIZDQhL2okF//dmbiWFzcSc8pUg9TqofCLYZySSxDCgQc69CJBo5JnI3Gz1KP+mOjS4WAeRIH4g== + dependencies: + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/instrumentation-dataloader@^0.4.3": version "0.4.3" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.4.3.tgz#13d2041d44d8ff4b9ebfc48bcbf9cbda74b61d00" @@ -3959,6 +4011,15 @@ "@opentelemetry/semantic-conventions" "^1.0.0" semver "^7.3.2" +"@opentelemetry/instrumentation-express@0.42.0": + version "0.42.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-express/-/instrumentation-express-0.42.0.tgz#279f195aa66baee2b98623a16666c6229c8e7564" + integrity sha512-YNcy7ZfGnLsVEqGXQPT+S0G1AE46N21ORY7i7yUQyfhGAL4RBjnZUqefMI0NwqIl6nGbr1IpF0rZGoN8Q7x12Q== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-express@^0.32.4": version "0.32.4" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-express/-/instrumentation-express-0.32.4.tgz#bced338cc6c2a5aeb3433f12302c0460207c7090" @@ -3969,6 +4030,15 @@ "@opentelemetry/semantic-conventions" "^1.0.0" "@types/express" "4.17.13" +"@opentelemetry/instrumentation-fastify@0.39.0": + version "0.39.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.39.0.tgz#96a040e4944daf77c53a8fe5a128bc3b2568e4aa" + integrity sha512-SS9uSlKcsWZabhBp2szErkeuuBDgxOUlllwkS92dVaWRnMmwysPhcEgHKB8rUe3BHg/GnZC1eo1hbTZv4YhfoA== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-fastify@^0.31.4": version "0.31.4" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.31.4.tgz#d3a17a190ba0b258330423982f7437c66e8f2b70" @@ -3978,6 +4048,14 @@ "@opentelemetry/instrumentation" "^0.40.0" "@opentelemetry/semantic-conventions" "^1.0.0" +"@opentelemetry/instrumentation-fs@0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.15.0.tgz#41658507860f39fee5209bca961cea8d24ca2a83" + integrity sha512-JWVKdNLpu1skqZQA//jKOcKdJC66TWKqa2FUFq70rKohvaSq47pmXlnabNO+B/BvLfmidfiaN35XakT5RyMl2Q== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/instrumentation-fs@^0.7.4": version "0.7.4" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.7.4.tgz#28a15842fc9b8d373f87c7fbf560049717f58156" @@ -3987,6 +4065,13 @@ "@opentelemetry/instrumentation" "^0.40.0" "@opentelemetry/semantic-conventions" "^1.0.0" +"@opentelemetry/instrumentation-generic-pool@0.39.0": + version "0.39.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.39.0.tgz#2b9af16ad82d5cbe67125c0125753cecd162a728" + integrity sha512-y4v8Y+tSfRB3NNBvHjbjrn7rX/7sdARG7FuK6zR8PGb28CTa0kHpEGCJqvL9L8xkTNvTXo+lM36ajFGUaK1aNw== + dependencies: + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/instrumentation-generic-pool@^0.31.4": version "0.31.4" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.31.4.tgz#049efa886f666c9e21cf0f32c06ef45642cbf992" @@ -3996,6 +4081,13 @@ "@opentelemetry/semantic-conventions" "^1.0.0" "@types/generic-pool" "^3.1.9" +"@opentelemetry/instrumentation-graphql@0.43.0": + version "0.43.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.43.0.tgz#71bb94ea775c70dbd388c739b397ec1418f3f170" + integrity sha512-aI3YMmC2McGd8KW5du1a2gBA0iOMOGLqg4s9YjzwbjFwjlmMNFSK1P3AIg374GWg823RPUGfVTIgZ/juk9CVOA== + dependencies: + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/instrumentation-graphql@^0.34.3": version "0.34.3" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.34.3.tgz#f55cb9223f616a27c8fa4303ee8c8b8f64059ddd" @@ -4011,6 +4103,15 @@ "@opentelemetry/instrumentation" "0.40.0" "@opentelemetry/semantic-conventions" "1.14.0" +"@opentelemetry/instrumentation-hapi@0.41.0": + version "0.41.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.41.0.tgz#de8711907256d8fae1b5faf71fc825cef4a7ddbb" + integrity sha512-jKDrxPNXDByPlYcMdZjNPYCvw0SQJjN+B1A+QH+sx+sAHsKSAf9hwFiJSrI6C4XdOls43V/f/fkp9ITkHhKFbQ== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-hapi@^0.31.4": version "0.31.4" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.31.4.tgz#df54ed4d36618f5adff0235bd95e68ae0da7ecd0" @@ -4021,6 +4122,16 @@ "@opentelemetry/semantic-conventions" "^1.0.0" "@types/hapi__hapi" "20.0.9" +"@opentelemetry/instrumentation-http@0.53.0": + version "0.53.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.53.0.tgz#0d806adf1b3aba036bc46e16162e3c0dbb8a6b60" + integrity sha512-H74ErMeDuZfj7KgYCTOFGWF5W9AfaPnqLQQxeFq85+D29wwV2yqHbz2IKLYpkOh7EI6QwDEl7rZCIxjJLyc/CQ== + dependencies: + "@opentelemetry/core" "1.26.0" + "@opentelemetry/instrumentation" "0.53.0" + "@opentelemetry/semantic-conventions" "1.27.0" + semver "^7.5.2" + "@opentelemetry/instrumentation-http@^0.40.0": version "0.40.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.40.0.tgz#ed4206ea96d64b5fd83b796f027642e42dca0cd1" @@ -4031,6 +4142,15 @@ "@opentelemetry/semantic-conventions" "1.14.0" semver "^7.3.5" +"@opentelemetry/instrumentation-ioredis@0.43.0": + version "0.43.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.43.0.tgz#dbadabaeefc4cb47c406f878444f1bcac774fa89" + integrity sha512-i3Dke/LdhZbiUAEImmRG3i7Dimm/BD7t8pDDzwepSvIQ6s2X6FPia7561gw+64w+nx0+G9X14D7rEfaMEmmjig== + dependencies: + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/redis-common" "^0.36.2" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-ioredis@^0.34.3": version "0.34.3" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.34.3.tgz#95fb4b6ff2b5eb29e01ee8d36ec24c69f2996019" @@ -4041,6 +4161,14 @@ "@opentelemetry/semantic-conventions" "^1.0.0" "@types/ioredis4" "npm:@types/ioredis@^4.28.10" +"@opentelemetry/instrumentation-kafkajs@0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.3.0.tgz#6687bce4dac8b90ef8ccbf1b662d5d1e95a34414" + integrity sha512-UnkZueYK1ise8FXQeKlpBd7YYUtC7mM8J0wzUSccEfc/G8UqHQqAzIyYCUOUPUKp8GsjLnWOOK/3hJc4owb7Jg== + dependencies: + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-knex@^0.31.4": version "0.31.4" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.31.4.tgz#15c747acf3de94f15bbad852140ec584b79d5cd9" @@ -4049,6 +4177,15 @@ "@opentelemetry/instrumentation" "^0.40.0" "@opentelemetry/semantic-conventions" "^1.0.0" +"@opentelemetry/instrumentation-koa@0.43.0": + version "0.43.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.43.0.tgz#963fd192a1b5f6cbae5dabf4ec82e3105cbb23b1" + integrity sha512-lDAhSnmoTIN6ELKmLJBplXzT/Jqs5jGZehuG22EdSMaTwgjMpxMDI1YtlKEhiWPWkrz5LUsd0aOO0ZRc9vn3AQ== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-koa@^0.34.6": version "0.34.6" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.34.6.tgz#88f2ab16f94f7c41bcd4b3487c254f9374a438c1" @@ -4076,6 +4213,15 @@ "@opentelemetry/semantic-conventions" "^1.0.0" "@types/memcached" "^2.2.6" +"@opentelemetry/instrumentation-mongodb@0.47.0": + version "0.47.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.47.0.tgz#f8107d878281433905e717f223fb4c0f10356a7b" + integrity sha512-yqyXRx2SulEURjgOQyJzhCECSh5i1uM49NUaq9TqLd6fA7g26OahyJfsr9NE38HFqGRHpi4loyrnfYGdrsoVjQ== + dependencies: + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/sdk-metrics" "^1.9.1" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-mongodb@^0.35.0": version "0.35.0" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.35.0.tgz#6ec571ef1c2ad8c88724ace826fdaf060dc8076a" @@ -4085,6 +4231,15 @@ "@opentelemetry/sdk-metrics" "^1.9.1" "@opentelemetry/semantic-conventions" "^1.0.0" +"@opentelemetry/instrumentation-mongoose@0.42.0": + version "0.42.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.42.0.tgz#375afd21adfcd897a8f521c1ffd2d91e6a428705" + integrity sha512-AnWv+RaR86uG3qNEMwt3plKX1ueRM7AspfszJYVkvkehiicC3bHQA6vWdb6Zvy5HAE14RyFbu9+2hUUjR2NSyg== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-mongoose@^0.32.4": version "0.32.4" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.32.4.tgz#f421d477264abd46e66d78ac65ca59f98c39b07c" @@ -4094,6 +4249,15 @@ "@opentelemetry/instrumentation" "^0.40.0" "@opentelemetry/semantic-conventions" "^1.0.0" +"@opentelemetry/instrumentation-mysql2@0.41.0": + version "0.41.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.41.0.tgz#6377b6e2d2487fd88e1d79aa03658db6c8d51651" + integrity sha512-REQB0x+IzVTpoNgVmy5b+UnH1/mDByrneimP6sbDHkp1j8QOl1HyWOrBH/6YWR0nrbU3l825Em5PlybjT3232g== + dependencies: + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/sql-common" "^0.40.1" + "@opentelemetry/instrumentation-mysql2@^0.33.4": version "0.33.4" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.33.4.tgz#fd69e38d1b5eefff6e4362fc257e60c5bec5a10f" @@ -4102,6 +4266,15 @@ "@opentelemetry/instrumentation" "^0.40.0" "@opentelemetry/semantic-conventions" "^1.0.0" +"@opentelemetry/instrumentation-mysql@0.41.0": + version "0.41.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.41.0.tgz#2d50691ead5219774bd36d66c35d5b4681485dd7" + integrity sha512-jnvrV6BsQWyHS2qb2fkfbfSb1R/lmYwqEZITwufuRl37apTopswu9izc0b1CYRp/34tUG/4k/V39PND6eyiNvw== + dependencies: + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@types/mysql" "2.15.26" + "@opentelemetry/instrumentation-mysql@^0.33.3": version "0.33.3" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.33.3.tgz#1f09c9cd19d971c2d5f142bb83c35f25c72975d9" @@ -4111,6 +4284,14 @@ "@opentelemetry/semantic-conventions" "^1.0.0" "@types/mysql" "2.15.19" +"@opentelemetry/instrumentation-nestjs-core@0.40.0": + version "0.40.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.40.0.tgz#2c0e6405b56caaec32747d55c57ff9a034668ea8" + integrity sha512-WF1hCUed07vKmf5BzEkL0wSPinqJgH7kGzOjjMAiTGacofNXjb/y4KQ8loj2sNsh5C/NN7s1zxQuCgbWbVTGKg== + dependencies: + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-nestjs-core@^0.32.5": version "0.32.5" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.32.5.tgz#ed4f81651f141a298b3a8d6107f50bc47b66004b" @@ -4127,6 +4308,17 @@ "@opentelemetry/instrumentation" "^0.40.0" "@opentelemetry/semantic-conventions" "^1.0.0" +"@opentelemetry/instrumentation-pg@0.44.0": + version "0.44.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.44.0.tgz#1e97a0aeb2dca068ee23ce75884a0a0063a7ce3f" + integrity sha512-oTWVyzKqXud1BYEGX1loo2o4k4vaU1elr3vPO8NZolrBtFvQ34nx4HgUaexUDuEog00qQt+MLR5gws/p+JXMLQ== + dependencies: + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/sql-common" "^0.40.1" + "@types/pg" "8.6.1" + "@types/pg-pool" "2.0.6" + "@opentelemetry/instrumentation-pg@^0.35.3": version "0.35.3" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.35.3.tgz#47b29891e2be797a2148e699bb43094fdf33a281" @@ -4145,6 +4337,15 @@ dependencies: "@opentelemetry/instrumentation" "^0.40.0" +"@opentelemetry/instrumentation-redis-4@0.42.0": + version "0.42.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.42.0.tgz#fc01104cfe884c7546385eaae03c57a47edd19d1" + integrity sha512-NaD+t2JNcOzX/Qa7kMy68JbmoVIV37fT/fJYzLKu2Wwd+0NCxt+K2OOsOakA8GVg8lSpFdbx4V/suzZZ2Pvdjg== + dependencies: + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/redis-common" "^0.36.2" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-redis-4@^0.34.6": version "0.34.6" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.34.6.tgz#2503f33b60f2cbe3311558fc95037d348e020575" @@ -4197,6 +4398,14 @@ "@opentelemetry/semantic-conventions" "^1.0.0" "@types/tedious" "^4.0.6" +"@opentelemetry/instrumentation-undici@0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.6.0.tgz#9436ee155c8dcb0b760b66947c0e0f347688a5ef" + integrity sha512-ABJBhm5OdhGmbh0S/fOTE4N69IZ00CsHC5ijMYfzbw3E5NwLgpQk5xsljaECrJ8wz1SfXbO03FiSuu5AyRAkvQ== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/instrumentation-winston@^0.31.4": version "0.31.4" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.31.4.tgz#09c160dfeb935ea6981d898176be79dea67f31c8" @@ -4224,6 +4433,41 @@ semver "^7.3.2" shimmer "^1.2.1" +"@opentelemetry/instrumentation@0.53.0", "@opentelemetry/instrumentation@^0.53.0": + version "0.53.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz#e6369e4015eb5112468a4d45d38dcada7dad892d" + integrity sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A== + dependencies: + "@opentelemetry/api-logs" "0.53.0" + "@types/shimmer" "^1.2.0" + import-in-the-middle "^1.8.1" + require-in-the-middle "^7.1.1" + semver "^7.5.2" + shimmer "^1.2.1" + +"@opentelemetry/instrumentation@^0.46.0": + version "0.46.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.46.0.tgz#a8a252306f82e2eace489312798592a14eb9830e" + integrity sha512-a9TijXZZbk0vI5TGLZl+0kxyFfrXHhX6Svtz7Pp2/VBlCSKrazuULEyoJQrOknJyFWNMEmbbJgOciHCCpQcisw== + dependencies: + "@types/shimmer" "^1.0.2" + import-in-the-middle "1.7.1" + require-in-the-middle "^7.1.1" + semver "^7.5.2" + shimmer "^1.2.1" + +"@opentelemetry/instrumentation@^0.49 || ^0.50 || ^0.51 || ^0.52.0": + version "0.52.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz#2e7e46a38bd7afbf03cf688c862b0b43418b7f48" + integrity sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw== + dependencies: + "@opentelemetry/api-logs" "0.52.1" + "@types/shimmer" "^1.0.2" + import-in-the-middle "^1.8.1" + require-in-the-middle "^7.1.1" + semver "^7.5.2" + shimmer "^1.2.1" + "@opentelemetry/otlp-exporter-base@0.34.0": version "0.34.0" resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.34.0.tgz#c6020b63590d4b8ac3833eda345a6f582fa014b1" @@ -4362,6 +4606,11 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/redis-common/-/redis-common-0.35.1.tgz#01356f6845d4f9f9fdfd2c4c562a74316d2d24d3" integrity sha512-qLXe7h9VzFLx3LaizFiUlpuohCRyvHlDW5b9synE6omHKTZr/n0EHEdmhp3GezBeAqMGI+q499Mht4SmStaSqQ== +"@opentelemetry/redis-common@^0.36.2": + version "0.36.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz#906ac8e4d804d4109f3ebd5c224ac988276fdc47" + integrity sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g== + "@opentelemetry/resource-detector-alibaba-cloud@^0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@opentelemetry/resource-detector-alibaba-cloud/-/resource-detector-alibaba-cloud-0.27.7.tgz#9eccdbf3b70eb891dcbd8f36a8019610ce838254" @@ -4429,6 +4678,14 @@ "@opentelemetry/core" "1.25.0" "@opentelemetry/semantic-conventions" "1.25.0" +"@opentelemetry/resources@1.26.0", "@opentelemetry/resources@^1.25.1", "@opentelemetry/resources@^1.26.0": + version "1.26.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.26.0.tgz#da4c7366018bd8add1f3aa9c91c6ac59fd503cef" + integrity sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw== + dependencies: + "@opentelemetry/core" "1.26.0" + "@opentelemetry/semantic-conventions" "1.27.0" + "@opentelemetry/resources@1.8.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.8.0.tgz#260be9742cf7bceccc0db928d8ca8d64391acfe3" @@ -4561,6 +4818,15 @@ "@opentelemetry/resources" "1.8.0" "@opentelemetry/semantic-conventions" "1.8.0" +"@opentelemetry/sdk-trace-base@^1.22", "@opentelemetry/sdk-trace-base@^1.25.1", "@opentelemetry/sdk-trace-base@^1.26.0": + version "1.26.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.26.0.tgz#0c913bc6d2cfafd901de330e4540952269ae579c" + integrity sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw== + dependencies: + "@opentelemetry/core" "1.26.0" + "@opentelemetry/resources" "1.26.0" + "@opentelemetry/semantic-conventions" "1.27.0" + "@opentelemetry/sdk-trace-base@^1.23.0": version "1.25.0" resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.25.0.tgz#263f9ce19001c5cd7a814d0eb40ebc6469ae763d" @@ -4623,11 +4889,23 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.0.tgz#390eb4d42a29c66bdc30066af9035645e9bb7270" integrity sha512-M+kkXKRAIAiAP6qYyesfrC5TOmDpDVtsxuGfPcqd9B/iBrac+E14jYwrgm0yZBUIbIP2OnqC3j+UgkXLm1vxUQ== +"@opentelemetry/semantic-conventions@1.27.0", "@opentelemetry/semantic-conventions@^1.17.0", "@opentelemetry/semantic-conventions@^1.25.1", "@opentelemetry/semantic-conventions@^1.27.0": + version "1.27.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.27.0.tgz#1a857dcc95a5ab30122e04417148211e6f945e6c" + integrity sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg== + "@opentelemetry/semantic-conventions@1.8.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.8.0.tgz#fe2aa90e6df050a11cd57f5c0f47b0641fd2cad3" integrity sha512-TYh1MRcm4JnvpqtqOwT9WYaBYY4KERHdToxs/suDTLviGRsQkIjS5yYROTYTSJQUnYLOn/TuOh5GoMwfLSU+Ew== +"@opentelemetry/sql-common@^0.40.1": + version "0.40.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/sql-common/-/sql-common-0.40.1.tgz#93fbc48d8017449f5b3c3274f2268a08af2b83b6" + integrity sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg== + dependencies: + "@opentelemetry/core" "^1.1.0" + "@penseapp/discord-notification@^2.0.9": version "2.0.9" resolved "https://registry.yarnpkg.com/@penseapp/discord-notification/-/discord-notification-2.0.9.tgz#0a52bb2eda2c575e076ee00476fd8dc717023a67" @@ -4758,6 +5036,15 @@ resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-4.10.1.tgz#c7062747f254e5d5fce98a8cae566c25f9f29fb2" integrity sha512-B3tcTxjx196nuAu1GOTKO9cGPUgTFHYRdkPkTS4m5ptb2cejyBlH9X7GOfSt3xlI7p4zAJDshJP4JJivCg9ouA== +"@prisma/instrumentation@5.19.1": + version "5.19.1" + resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-5.19.1.tgz#146319cf85f22b7a43296f0f40cfeac55516e66e" + integrity sha512-VLnzMQq7CWroL5AeaW0Py2huiNKeoMfCH3SUxstdzPrlWQi6UQ9UrfcbUkNHlVFqOMacqy8X/8YtE0kuKDpD9w== + dependencies: + "@opentelemetry/api" "^1.8" + "@opentelemetry/instrumentation" "^0.49 || ^0.50 || ^0.51 || ^0.52.0" + "@opentelemetry/sdk-trace-base" "^1.22" + "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" @@ -5360,6 +5647,60 @@ "@sentry/types" "7.106.1" "@sentry/utils" "7.106.1" +"@sentry/cli-darwin@2.35.0": + version "2.35.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.35.0.tgz#4bc9a07690f0de75d930ba47f4655f6465191768" + integrity sha512-dRtDaASkB1ncSbCLMIL8bxki4dPMimSdYz74XOUJ5IvDVVzEInEO7PqvyOj/cyafB+1FSNudaZ90ZRvsNN1Maw== + +"@sentry/cli-linux-arm64@2.35.0": + version "2.35.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.35.0.tgz#bad8a45b81d2b317f702991783a503f566b2294e" + integrity sha512-NpyVz2lQWWkMa9GZkt0m4cA/wsgYnWOE6Z+4ePUGjbOIG3Ws9DLaHjYxUUYI79kxfbVCp7wLo1S6kOkj+M1Dlw== + +"@sentry/cli-linux-arm@2.35.0": + version "2.35.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm/-/cli-linux-arm-2.35.0.tgz#dacfc219876f5dce3d8c65dab7128ea3e493f561" + integrity sha512-zNL+/HnepZ4/MkIS8wfoUQxSa+k6r0DSSdX1TpDH5436u+3LB5rfCTBfZ624DWHKMoXX+1dI+rWSi+zL8QFMsg== + +"@sentry/cli-linux-i686@2.35.0": + version "2.35.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-i686/-/cli-linux-i686-2.35.0.tgz#d0e6401b60b0a4b6c3578998995ba6cb31c1bf20" + integrity sha512-vIYwZVqx+kYZdPsenIm+UqjSCKe9Q2Aof6kzrzW0DPR1WyqIWbWG4NbiugiPTiuA1dLjUjYpGP8wyIqb8hxv4w== + +"@sentry/cli-linux-x64@2.35.0": + version "2.35.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-x64/-/cli-linux-x64-2.35.0.tgz#a1e8e7bff960ed8916b4cc9c0ef75a057e30f989" + integrity sha512-7Wy5QNt6wZ8EaxEbHqP0DEiyUcXRVItRt9jzhpa2nCaawL+fwDOQCjUkHGsdIC+y14UqA+er9CaPCSp8sA6Vaw== + +"@sentry/cli-win32-i686@2.35.0": + version "2.35.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-win32-i686/-/cli-win32-i686-2.35.0.tgz#c1b090f7c740c5b22d1019ca48a84f58cd4b2670" + integrity sha512-XDcBUtO5A9elH+xgFNs6NBjkMBnz0sZLo5DU7LE77qKXULnlLeJ63eZD1ukQIRPvxEDsIEPOllRweLuAlUMDtw== + +"@sentry/cli-win32-x64@2.35.0": + version "2.35.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.35.0.tgz#f592af483da239be846e556f57f5c6fc7dc1dc54" + integrity sha512-86yHO+31qAXUeAdSCH7MNodn/cn/9xd2fTrxjtfNZWO0pX0jW91sCdomfBxhu5b977cyV9gNcqeBbc9XSIKIIA== + +"@sentry/cli@^2.35.0": + version "2.35.0" + resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.35.0.tgz#5514eb8f5808bc70707ffa186156f8ff7ca5971e" + integrity sha512-7sHRJViEgHTfEXf+HD1Fb2cwmnxlILmb2NNxghP2vvrgC2PhuwuJU7AX4zg7HjJgxH9HBmnn4AJskDujaJ/6cQ== + dependencies: + https-proxy-agent "^5.0.0" + node-fetch "^2.6.7" + progress "^2.0.3" + proxy-from-env "^1.1.0" + which "^2.0.2" + optionalDependencies: + "@sentry/cli-darwin" "2.35.0" + "@sentry/cli-linux-arm" "2.35.0" + "@sentry/cli-linux-arm64" "2.35.0" + "@sentry/cli-linux-i686" "2.35.0" + "@sentry/cli-linux-x64" "2.35.0" + "@sentry/cli-win32-i686" "2.35.0" + "@sentry/cli-win32-x64" "2.35.0" + "@sentry/core@7.106.1": version "7.106.1" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.106.1.tgz#d4470f2a2f8e0c24e3afe4d7f83f98f5d2858605" @@ -5368,15 +5709,129 @@ "@sentry/types" "7.106.1" "@sentry/utils" "7.106.1" -"@sentry/node@^7.12.0": - version "7.106.1" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-7.106.1.tgz#8728fd79b8575ef0678a3a47f928c2830c9c9b6e" - integrity sha512-KB2Lkb9WqocD/gbKIZCk2mQQmx+G3khI9ChJUw6GJzd5mvdQ5xxr4/yQKIHR6L9z3oGWBno9/Xc8Aw9s3ZwGwQ== - dependencies: - "@sentry-internal/tracing" "7.106.1" - "@sentry/core" "7.106.1" - "@sentry/types" "7.106.1" - "@sentry/utils" "7.106.1" +"@sentry/core@8.29.0": + version "8.29.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.29.0.tgz#52032ece2d7b60f3775f10189c27e26b1cebdbca" + integrity sha512-scMbZaJ0Ov8NPgWn86EdjhyTLrhvRVbTxjg0imJAvhIvRbblH3xyqye/17Qnk2fOp8TNDOl7TBZHi0NCFQ5HUw== + dependencies: + "@sentry/types" "8.29.0" + "@sentry/utils" "8.29.0" + +"@sentry/core@8.32.0": + version "8.32.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.32.0.tgz#7c4b74afa7a15bd31f5e6881aac82ccfd753e1d6" + integrity sha512-+xidTr0lZ0c755tq4k75dXPEb8PA+qvIefW3U9+dQMORLokBrYoKYMf5zZTG2k/OfSJS6OSxatUj36NFuCs3aA== + dependencies: + "@sentry/types" "8.32.0" + "@sentry/utils" "8.32.0" + +"@sentry/node@8.32.0": + version "8.32.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-8.32.0.tgz#68822b3246fb2ed7418f21795ed539a18058cfa8" + integrity sha512-a2PoFA9j/HmJVGF/zXJhLP6QhRHGye/2EznQdHOELsH1BkeMgBaXl7D52r2E/b7qki647lXrdbspB6jid8NycA== + dependencies: + "@opentelemetry/api" "^1.9.0" + "@opentelemetry/context-async-hooks" "^1.25.1" + "@opentelemetry/core" "^1.25.1" + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/instrumentation-amqplib" "^0.42.0" + "@opentelemetry/instrumentation-connect" "0.39.0" + "@opentelemetry/instrumentation-dataloader" "0.12.0" + "@opentelemetry/instrumentation-express" "0.42.0" + "@opentelemetry/instrumentation-fastify" "0.39.0" + "@opentelemetry/instrumentation-fs" "0.15.0" + "@opentelemetry/instrumentation-generic-pool" "0.39.0" + "@opentelemetry/instrumentation-graphql" "0.43.0" + "@opentelemetry/instrumentation-hapi" "0.41.0" + "@opentelemetry/instrumentation-http" "0.53.0" + "@opentelemetry/instrumentation-ioredis" "0.43.0" + "@opentelemetry/instrumentation-kafkajs" "0.3.0" + "@opentelemetry/instrumentation-koa" "0.43.0" + "@opentelemetry/instrumentation-mongodb" "0.47.0" + "@opentelemetry/instrumentation-mongoose" "0.42.0" + "@opentelemetry/instrumentation-mysql" "0.41.0" + "@opentelemetry/instrumentation-mysql2" "0.41.0" + "@opentelemetry/instrumentation-nestjs-core" "0.40.0" + "@opentelemetry/instrumentation-pg" "0.44.0" + "@opentelemetry/instrumentation-redis-4" "0.42.0" + "@opentelemetry/instrumentation-undici" "0.6.0" + "@opentelemetry/resources" "^1.26.0" + "@opentelemetry/sdk-trace-base" "^1.26.0" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@prisma/instrumentation" "5.19.1" + "@sentry/core" "8.32.0" + "@sentry/opentelemetry" "8.32.0" + "@sentry/types" "8.32.0" + "@sentry/utils" "8.32.0" + import-in-the-middle "^1.11.0" + +"@sentry/node@^8.29.0": + version "8.29.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-8.29.0.tgz#6e462b8802356a630c56733dc795a4035464c4ab" + integrity sha512-RCKpWR6DUWmlxtms10MRXwJZRrFt1a2P38FjwEEahcdcK1R6wB8GPf0GO4JnJAiw6oeM0MERSqLIcSLT8+FxtA== + dependencies: + "@opentelemetry/api" "^1.9.0" + "@opentelemetry/context-async-hooks" "^1.25.1" + "@opentelemetry/core" "^1.25.1" + "@opentelemetry/instrumentation" "^0.53.0" + "@opentelemetry/instrumentation-connect" "0.39.0" + "@opentelemetry/instrumentation-express" "0.42.0" + "@opentelemetry/instrumentation-fastify" "0.39.0" + "@opentelemetry/instrumentation-fs" "0.15.0" + "@opentelemetry/instrumentation-generic-pool" "0.39.0" + "@opentelemetry/instrumentation-graphql" "0.43.0" + "@opentelemetry/instrumentation-hapi" "0.41.0" + "@opentelemetry/instrumentation-http" "0.53.0" + "@opentelemetry/instrumentation-ioredis" "0.43.0" + "@opentelemetry/instrumentation-koa" "0.43.0" + "@opentelemetry/instrumentation-mongodb" "0.47.0" + "@opentelemetry/instrumentation-mongoose" "0.42.0" + "@opentelemetry/instrumentation-mysql" "0.41.0" + "@opentelemetry/instrumentation-mysql2" "0.41.0" + "@opentelemetry/instrumentation-nestjs-core" "0.40.0" + "@opentelemetry/instrumentation-pg" "0.44.0" + "@opentelemetry/instrumentation-redis-4" "0.42.0" + "@opentelemetry/resources" "^1.25.1" + "@opentelemetry/sdk-trace-base" "^1.25.1" + "@opentelemetry/semantic-conventions" "^1.25.1" + "@prisma/instrumentation" "5.19.1" + "@sentry/core" "8.29.0" + "@sentry/opentelemetry" "8.29.0" + "@sentry/types" "8.29.0" + "@sentry/utils" "8.29.0" + import-in-the-middle "^1.11.0" + optionalDependencies: + opentelemetry-instrumentation-fetch-node "1.2.3" + +"@sentry/opentelemetry@8.29.0": + version "8.29.0" + resolved "https://registry.yarnpkg.com/@sentry/opentelemetry/-/opentelemetry-8.29.0.tgz#6ae54c640155925fc42ac86f37d125f9bb983794" + integrity sha512-MtfjDMUuKFYlyw9hZohp9xnphz+6QosyHb2zCV3e/fANoA53FDxmg/Co7haMohUCiOwwJPytUmSQQaP0nyL2Uw== + dependencies: + "@sentry/core" "8.29.0" + "@sentry/types" "8.29.0" + "@sentry/utils" "8.29.0" + +"@sentry/opentelemetry@8.32.0": + version "8.32.0" + resolved "https://registry.yarnpkg.com/@sentry/opentelemetry/-/opentelemetry-8.32.0.tgz#4af02c17102635e4b34942d2e82d3620ddb7d95a" + integrity sha512-YCD8EnwJJ2ab3zWWtu5VrvHP/6Ss6GGQH0TYx2cfeGG3c0wTA/5zYx9JR4i3hUtOh1pifN34HlY0yyQHD4yctg== + dependencies: + "@sentry/core" "8.32.0" + "@sentry/types" "8.32.0" + "@sentry/utils" "8.32.0" + +"@sentry/profiling-node@^8.32.0": + version "8.32.0" + resolved "https://registry.yarnpkg.com/@sentry/profiling-node/-/profiling-node-8.32.0.tgz#cb4bf0512dc7a6f0a9058529f3c4dbb8963a597d" + integrity sha512-wKE2JAvDM3DjVNFKd2YLzwhXFS3SurLxDPpvA1EjMQ9Me7sR5ssO9jFn3e6et5oT3e3EzGDyTfbrJ81BNQuZhQ== + dependencies: + "@sentry/core" "8.32.0" + "@sentry/node" "8.32.0" + "@sentry/types" "8.32.0" + "@sentry/utils" "8.32.0" + detect-libc "^2.0.2" + node-abi "^3.61.0" "@sentry/tracing@^7.12.0": version "7.106.1" @@ -5390,6 +5845,16 @@ resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.106.1.tgz#ea7c6b9090790e600c4f907f1c8bf94c8db2ecc4" integrity sha512-g3OcyAHGugBwkQP4fZYCCZqF2ng9K7yQc9FVngKq/y7PwHm84epXdYYGDGgfQOIC1d5/GMaPxmzI5IIrZexzkg== +"@sentry/types@8.29.0": + version "8.29.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-8.29.0.tgz#c19e43524b8e7766028f4da8f02eddcc33518541" + integrity sha512-j4gX3ctzgD4xVWllXAhm6M+kHFEvrFoUPFq60X/pgkjsWCocGuhtNfB0rW43ICG8hCnlz8IYl7O7b8V8qY7SPg== + +"@sentry/types@8.32.0": + version "8.32.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-8.32.0.tgz#dfd8aa9449a5f793b9c720888819a74a11f1790d" + integrity sha512-hxckvN2MzS5SgGDgVQ0/QpZXk13Vrq4BtZLwXhPhyeTmZtUiUfWvcL5TFQqLinfKdTKPe9q2MxeAJ0D4LalhMg== + "@sentry/utils@7.106.1": version "7.106.1" resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.106.1.tgz#7761ed50d489286dd1e482570c498f675445ce82" @@ -5397,6 +5862,20 @@ dependencies: "@sentry/types" "7.106.1" +"@sentry/utils@8.29.0": + version "8.29.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-8.29.0.tgz#d4a36643369e30ba62ef8f40f149420a100f64bb" + integrity sha512-nb93/m3SjQChQJFqJj3oNW3Rz/12yrT7jypTCire3c2hpYWG2uR5n8VY9UUMTA6HLNvdom6tckK7p3bXGXlF0w== + dependencies: + "@sentry/types" "8.29.0" + +"@sentry/utils@8.32.0": + version "8.32.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-8.32.0.tgz#99a4298ee8fd7208ade470931c19d71c571dfce8" + integrity sha512-t1WVERhgmYURxbBj9J4/H2P2X+VKqm7B3ce9iQyrZbdf5NekhcU4jHIecPUWCPHjQkFIqkVTorqeBmDTlg/UmQ== + dependencies: + "@sentry/types" "8.32.0" + "@sideway/address@^4.1.5": version "4.1.5" resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" @@ -6711,6 +7190,13 @@ dependencies: "@types/node" "*" +"@types/connect@3.4.36": + version "3.4.36" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.36.tgz#e511558c15a39cb29bd5357eebb57bd1459cd1ab" + integrity sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w== + dependencies: + "@types/node" "*" + "@types/content-disposition@*": version "0.5.8" resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.8.tgz#6742a5971f490dc41e59d277eee71361fea0b537" @@ -7034,6 +7520,13 @@ dependencies: "@types/node" "*" +"@types/mysql@2.15.26": + version "2.15.26" + resolved "https://registry.yarnpkg.com/@types/mysql/-/mysql-2.15.26.tgz#f0de1484b9e2354d587e7d2bd17a873cc8300836" + integrity sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ== + dependencies: + "@types/node" "*" + "@types/node@*", "@types/node@>=10.0.0", "@types/node@>=13.7.0", "@types/node@^20.10.4": version "20.11.27" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.27.tgz#debe5cfc8a507dd60fe2a3b4875b1604f215c2ac" @@ -7089,6 +7582,13 @@ dependencies: "@types/pg" "*" +"@types/pg-pool@2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/pg-pool/-/pg-pool-2.0.6.tgz#1376d9dc5aec4bb2ec67ce28d7e9858227403c77" + integrity sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ== + dependencies: + "@types/pg" "*" + "@types/pg@*": version "8.11.2" resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.11.2.tgz#e5c306601d2e0cc54c0801cc61a41761c8a95c92" @@ -7191,6 +7691,11 @@ resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.0.5.tgz#491d8984d4510e550bfeb02d518791d7f59d2b88" integrity sha512-9Hp0ObzwwO57DpLFF0InUjUm/II8GmKAvzbefxQTihCb7KI6yc9yzf0nLc4mVdby5N4DRCgQM2wCup9KTieeww== +"@types/shimmer@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.2.0.tgz#9b706af96fa06416828842397a70dfbbf1c14ded" + integrity sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg== + "@types/superagent@*": version "8.1.4" resolved "https://registry.yarnpkg.com/@types/superagent/-/superagent-8.1.4.tgz#f8290d1b7d6081f84f3047851c190c4a3c8cdb21" @@ -7532,6 +8037,11 @@ acorn-import-assertions@^1.9.0: resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== +acorn-import-attributes@^1.9.5: + version "1.9.5" + resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== + acorn-jsx@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -8726,6 +9236,11 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: inherits "^2.0.1" safe-buffer "^5.0.1" +cjs-module-lexer@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz#707413784dbb3a72aa11c2f2b042a0bef4004170" + integrity sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA== + classic-level@^1.2.0: version "1.4.1" resolved "https://registry.yarnpkg.com/classic-level/-/classic-level-1.4.1.tgz#169ecf9f9c6200ad42a98c8576af449c1badbaee" @@ -9367,6 +9882,13 @@ debug@^4.3.3: dependencies: ms "2.1.2" +debug@^4.3.5: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + decamelize-keys@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" @@ -9496,7 +10018,7 @@ detect-indent@6.1.0: resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== -detect-libc@^2.0.0: +detect-libc@^2.0.0, detect-libc@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== @@ -11538,6 +12060,26 @@ import-in-the-middle@1.3.5: dependencies: module-details-from-path "^1.0.3" +import-in-the-middle@1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.7.1.tgz#3e111ff79c639d0bde459bd7ba29dd9fdf357364" + integrity sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg== + dependencies: + acorn "^8.8.2" + acorn-import-assertions "^1.9.0" + cjs-module-lexer "^1.2.2" + module-details-from-path "^1.0.3" + +import-in-the-middle@^1.11.0, import-in-the-middle@^1.8.1: + version "1.11.0" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.11.0.tgz#a94c4925b8da18256cde3b3b7b38253e6ca5e708" + integrity sha512-5DimNQGoe0pLUHbR9qK84iWaWjjbsxiqXnw6Qz64+azRgleqv9k2kTt5fw7QsOpmaGYtuxxursnPPsnTKEx10Q== + dependencies: + acorn "^8.8.2" + acorn-import-attributes "^1.9.5" + cjs-module-lexer "^1.2.2" + module-details-from-path "^1.0.3" + import-meta-resolve@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz#0b1195915689f60ab00f830af0f15cc841e8919e" @@ -13500,6 +14042,13 @@ node-abi@^3.3.0: dependencies: semver "^7.3.5" +node-abi@^3.61.0: + version "3.68.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.68.0.tgz#8f37fb02ecf4f43ebe694090dcb52e0c4cc4ba25" + integrity sha512-7vbj10trelExNjFSBm5kTvZXXa7pZyKWx9RCKIyqe6I9Ev3IzGpQoqBP3a+cOdxY+pWj6VkP28n/2wWysBHD/A== + dependencies: + semver "^7.3.5" + node-addon-api@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" @@ -13515,7 +14064,7 @@ node-domexception@^1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.8, node-fetch@^2.6.9: +node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7, node-fetch@^2.6.8, node-fetch@^2.6.9: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== @@ -13815,6 +14364,14 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" +opentelemetry-instrumentation-fetch-node@1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/opentelemetry-instrumentation-fetch-node/-/opentelemetry-instrumentation-fetch-node-1.2.3.tgz#beb24048bdccb1943ba2a5bbadca68020e448ea7" + integrity sha512-Qb11T7KvoCevMaSeuamcLsAD+pZnavkhDnlVL0kRozfhl42dKG5Q3anUklAFKJZjY3twLR+BnRa6DlwwkIE/+A== + dependencies: + "@opentelemetry/instrumentation" "^0.46.0" + "@opentelemetry/semantic-conventions" "^1.17.0" + opentracing@^0.14.4: version "0.14.7" resolved "https://registry.yarnpkg.com/opentracing/-/opentracing-0.14.7.tgz#25d472bd0296dc0b64d7b94cbc995219031428f5" @@ -14470,7 +15027,7 @@ progress-events@^1.0.0: resolved "https://registry.yarnpkg.com/progress-events/-/progress-events-1.0.0.tgz#34f5e8fdb5dae3561837b22672d1e02277bb2109" integrity sha512-zIB6QDrSbPfRg+33FZalluFIowkbV5Xh1xSuetjG+rlC5he6u2dc6VQJ0TbMdlN3R1RHdpOqxEFMKTnQ+itUwA== -progress@^2.0.0: +progress@^2.0.0, progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -15007,6 +15564,15 @@ require-in-the-middle@^7.1.0: module-details-from-path "^1.0.3" resolve "^1.22.1" +require-in-the-middle@^7.1.1: + version "7.4.0" + resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.4.0.tgz#606977820d4b5f9be75e5a108ce34cfed25b3bb4" + integrity sha512-X34iHADNbNDfr6OTStIAHWSAvvKQRYgLO6duASaVf7J2VA3lvmNYboAHOuLC2huav1IwgZJtyEcJCKVzFxOSMQ== + dependencies: + debug "^4.3.5" + module-details-from-path "^1.0.3" + resolve "^1.22.8" + require-main-filename@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" @@ -15042,7 +15608,7 @@ resolve-global@1.0.0, resolve-global@^1.0.0: dependencies: global-dirs "^0.1.1" -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.2, resolve@^1.22.4: +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.2, resolve@^1.22.4, resolve@^1.22.8: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -15283,6 +15849,11 @@ semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.8, semve dependencies: lru-cache "^6.0.0" +semver@^7.5.2: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + semver@~7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" @@ -15756,7 +16327,16 @@ string-template@~0.2.1: resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" integrity sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -15829,7 +16409,7 @@ stringify-object@3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -15843,6 +16423,13 @@ strip-ansi@^3.0.0: dependencies: ansi-regex "^2.0.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -16878,7 +17465,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -16896,6 +17483,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 2be51c7fe..6302874a1 100755 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -184,10 +184,11 @@ services: - ./local-data/redis:/data ceramic: - image: ceramicnetwork/js-ceramic:6.4.0 + image: ceramicnetwork/js-ceramic:6.5.0 container_name: ceramic ports: - "7007:7007" + - "9464:9464" environment: NODE_ENV: production CERAMIC_PUBSUB_QPS_LIMIT: 500 diff --git a/nodes-lib/package.json b/nodes-lib/package.json index 1debe7631..9964f222e 100644 --- a/nodes-lib/package.json +++ b/nodes-lib/package.json @@ -1,6 +1,6 @@ { "name": "@desci-labs/nodes-lib", - "version": "0.0.11-rc1", + "version": "0.0.11", "homepage": "https://github.com/desci-labs/nodes#readme", "description": "Stand-alone client library for interacting with desci-server", "repository": { diff --git a/nodes-lib/src/util/signing.ts b/nodes-lib/src/util/signing.ts index 333f5dd8b..c68642984 100644 --- a/nodes-lib/src/util/signing.ts +++ b/nodes-lib/src/util/signing.ts @@ -76,7 +76,9 @@ export const authorizedSessionDidFromSigner = async ( const address = await signer.getAddress(); const network = await jsonRpcProvider.getNetwork(); - const chainId = `eip155:${chainIdOverride ?? network.chainId}`; + // Force sepolia chainID in CACAO to prevent segmenting the + // user's streams over AccountIDs with different chainIDs + const chainId = `eip155:${chainIdOverride ?? "11155111" }`; const caipAccountId = new AccountId({ address, chainId }); let authMethod: AuthMethod;