diff --git a/dev-packages/e2e-tests/verdaccio-config/config.yaml b/dev-packages/e2e-tests/verdaccio-config/config.yaml index 6e57ee2ea812..beb758aca018 100644 --- a/dev-packages/e2e-tests/verdaccio-config/config.yaml +++ b/dev-packages/e2e-tests/verdaccio-config/config.yaml @@ -74,6 +74,12 @@ packages: unpublish: $all # proxy: npmjs # Don't proxy for E2E tests! + '@sentry/effect': + access: $all + publish: $all + unpublish: $all + # proxy: npmjs # Don't proxy for E2E tests! + '@sentry/ember': access: $all publish: $all diff --git a/package.json b/package.json index 91bc549e4527..59d0415142c1 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "packages/core", "packages/cloudflare", "packages/deno", + "packages/effect", "packages/ember", "packages/eslint-config-sdk", "packages/eslint-plugin-sdk", diff --git a/packages/effect/.eslintrc.js b/packages/effect/.eslintrc.js new file mode 100644 index 000000000000..d37e458c151c --- /dev/null +++ b/packages/effect/.eslintrc.js @@ -0,0 +1,15 @@ +module.exports = { + env: { + browser: true, + node: true, + }, + overrides: [ + { + files: ['vite.config.ts', 'vitest.config.ts'], + parserOptions: { + project: ['tsconfig.vite.json'], + }, + }, + ], + extends: ['../../.eslintrc.js'], +}; diff --git a/packages/effect/LICENSE b/packages/effect/LICENSE new file mode 100644 index 000000000000..fea6013e7dbf --- /dev/null +++ b/packages/effect/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Functional Software Inc. dba Sentry + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/effect/README.md b/packages/effect/README.md new file mode 100644 index 000000000000..a209c930b659 --- /dev/null +++ b/packages/effect/README.md @@ -0,0 +1,47 @@ +# Official Sentry SDK for Effect.ts (Alpha) + +[![npm version](https://img.shields.io/npm/v/@sentry/effect.svg)](https://www.npmjs.com/package/@sentry/effect) +[![npm dm](https://img.shields.io/npm/dm/@sentry/effect.svg)](https://www.npmjs.com/package/@sentry/effect) +[![npm dt](https://img.shields.io/npm/dt/@sentry/effect.svg)](https://www.npmjs.com/package/@sentry/effect) + +> NOTICE: This package is in alpha state and may be subject to breaking changes. + +## Getting Started + +This SDK does not have docs yet. Stay tuned. + +## Usage + +```typescript +import * as Sentry from '@sentry/effect/server'; +import { NodeRuntime } from '@effect/platform-node'; +import { Layer } from 'effect'; +import { HttpLive } from './Http.js'; + +const MainLive = HttpLive.pipe( + Layer.provide( + Sentry.effectLayer({ + dsn: '__DSN__', + enableLogs: true, + enableMetrics: true, + }), + ), +); + +MainLive.pipe(Layer.launch, NodeRuntime.runMain); +``` + +The `effectLayer` function initializes Sentry and returns an Effect Layer that provides: + +- Distributed tracing with automatic HTTP header extraction/injection +- Effect spans traced as Sentry spans +- Effect logs forwarded to Sentry (when `enableLogs` is set) +- Effect metrics sent to Sentry (when `enableMetrics` is set) + +## Links + + + +- [Sentry.io](https://sentry.io/?utm_source=github&utm_medium=npm_effect) +- [Sentry Discord Server](https://discord.gg/Ww9hbqr) +- [Stack Overflow](https://stackoverflow.com/questions/tagged/sentry) diff --git a/packages/effect/package.json b/packages/effect/package.json new file mode 100644 index 000000000000..dbee14b478a8 --- /dev/null +++ b/packages/effect/package.json @@ -0,0 +1,67 @@ +{ + "name": "@sentry/effect", + "version": "10.42.0", + "description": "Official Sentry SDK for Effect", + "repository": "git://github.com/getsentry/sentry-javascript.git", + "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/effect", + "author": "Sentry", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "files": [ + "/build" + ], + "main": "build/cjs/index.js", + "module": "build/esm/index.js", + "types": "build/types/index.d.ts", + "exports": { + "./package.json": "./package.json", + ".": { + "import": { + "types": "./build/types/index.d.ts", + "default": "./build/esm/index.js" + }, + "require": { + "types": "./build/types/index.d.ts", + "default": "./build/cjs/index.js" + } + } + }, + "typesVersions": { + "<5.0": { + "build/types/index.d.ts": [ + "build/types-ts3.8/index.d.ts" + ] + } + }, + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@sentry/core": "10.42.0" + }, + "scripts": { + "build": "run-p build:transpile build:types", + "build:dev": "yarn build", + "build:transpile": "rollup -c rollup.npm.config.mjs", + "build:types": "run-s build:types:core build:types:downlevel", + "build:types:core": "tsc -p tsconfig.types.json", + "build:types:downlevel": "yarn downlevel-dts build/types build/types-ts3.8 --to ts3.8", + "build:watch": "run-p build:transpile:watch", + "build:dev:watch": "yarn build:watch", + "build:transpile:watch": "rollup -c rollup.npm.config.mjs --watch", + "build:tarball": "npm pack", + "circularDepCheck": "madge --circular src/index.ts", + "clean": "rimraf build coverage sentry-effect-*.tgz", + "fix": "eslint . --format stylish --fix", + "lint": "eslint . --format stylish", + "test": "vitest run", + "test:watch": "vitest --watch", + "yalc:publish": "yalc publish --push --sig" + }, + "volta": { + "extends": "../../package.json" + }, + "sideEffects": false +} diff --git a/packages/effect/rollup.npm.config.mjs b/packages/effect/rollup.npm.config.mjs new file mode 100644 index 000000000000..ca36da81392f --- /dev/null +++ b/packages/effect/rollup.npm.config.mjs @@ -0,0 +1,11 @@ +import { makeBaseNPMConfig, makeNPMConfigVariants } from '@sentry-internal/rollup-utils'; + +export default makeNPMConfigVariants( + makeBaseNPMConfig({ + packageSpecificConfig: { + output: { + preserveModulesRoot: 'src', + }, + }, + }), +); diff --git a/packages/effect/src/index.ts b/packages/effect/src/index.ts new file mode 100644 index 000000000000..88781f88051a --- /dev/null +++ b/packages/effect/src/index.ts @@ -0,0 +1,87 @@ +export type { + Breadcrumb, + BreadcrumbHint, + Context, + Contexts, + RequestEventData, + SdkInfo, + Event, + EventHint, + ErrorEvent, + Exception, + SeverityLevel, + StackFrame, + Stacktrace, + Thread, + User, + Session, + CaptureContext, + ExclusiveEventHintOrCaptureContext, + Log, + LogSeverityLevel, + Span, +} from '@sentry/core'; + +export { + addEventProcessor, + addBreadcrumb, + addIntegration, + captureException, + captureEvent, + captureFeedback, + captureMessage, + close, + createTransport, + lastEventId, + flush, + getClient, + isInitialized, + isEnabled, + getCurrentScope, + getIsolationScope, + getGlobalScope, + setCurrentClient, + Scope, + continueTrace, + getTraceData, + suppressTracing, + SDK_VERSION, + setContext, + setExtra, + setExtras, + setTag, + setTags, + setUser, + withScope, + withIsolationScope, + functionToStringIntegration, + eventFiltersIntegration, + dedupeIntegration, + parameterize, + startSession, + captureSession, + endSession, + spanToJSON, + spanToTraceHeader, + spanToBaggageHeader, + updateSpanName, + metrics, + getActiveSpan, + getRootSpan, + startSpan, + startInactiveSpan, + startSpanManual, + withActiveSpan, + startNewTrace, + getSpanDescendants, + setMeasurement, + getSpanStatusFromHttpCode, + setHttpStatus, +} from '@sentry/core'; + +export { + SEMANTIC_ATTRIBUTE_SENTRY_OP, + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, + SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, +} from '@sentry/core'; diff --git a/packages/effect/test/index.test.ts b/packages/effect/test/index.test.ts new file mode 100644 index 000000000000..f774de6eaf24 --- /dev/null +++ b/packages/effect/test/index.test.ts @@ -0,0 +1,8 @@ +import { describe, expect, it } from 'vitest'; +import * as index from '../src'; + +describe('effect index export', () => { + it('has correct exports', () => { + expect(index.captureException).toBeDefined(); + }); +}); diff --git a/packages/effect/tsconfig.json b/packages/effect/tsconfig.json new file mode 100644 index 000000000000..ee81c1a20817 --- /dev/null +++ b/packages/effect/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "module": "esnext", + "outDir": "build" + }, + "include": ["src/**/*"] +} diff --git a/packages/effect/tsconfig.test.json b/packages/effect/tsconfig.test.json new file mode 100644 index 000000000000..9dd90014ef37 --- /dev/null +++ b/packages/effect/tsconfig.test.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + + "include": ["test/**/*", "vitest.config.ts"], + + "compilerOptions": { + "types": ["node"] + } +} diff --git a/packages/effect/tsconfig.types.json b/packages/effect/tsconfig.types.json new file mode 100644 index 000000000000..76eb1a9bb7c3 --- /dev/null +++ b/packages/effect/tsconfig.types.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "build/types" + }, + "include": ["src/**/*"] +} diff --git a/packages/effect/tsconfig.vite.json b/packages/effect/tsconfig.vite.json new file mode 100644 index 000000000000..4f2b7371b076 --- /dev/null +++ b/packages/effect/tsconfig.vite.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + + "include": ["vite.config.ts", "vitest.config.ts"], + + "compilerOptions": { + "types": ["node"] + } +} diff --git a/packages/effect/vitest.config.ts b/packages/effect/vitest.config.ts new file mode 100644 index 000000000000..ed62557713c1 --- /dev/null +++ b/packages/effect/vitest.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'vitest/config'; +import baseConfig from '../../vite/vite.config'; + +export default defineConfig({ + ...baseConfig, + test: { + ...baseConfig.test, + include: ['test/**/*.test.ts'], + }, +});