diff --git a/dev-packages/node-integration-tests/package.json b/dev-packages/node-integration-tests/package.json index f36333c4daa8..68012d36269b 100644 --- a/dev-packages/node-integration-tests/package.json +++ b/dev-packages/node-integration-tests/package.json @@ -36,6 +36,7 @@ "apollo-server": "^3.11.1", "axios": "^0.27.2", "cors": "^2.8.5", + "cron": "^3.1.6", "express": "^4.17.3", "graphql": "^16.3.0", "http-terminator": "^3.2.0", diff --git a/dev-packages/node-integration-tests/suites/cron/node-cron/scenario.ts b/dev-packages/node-integration-tests/suites/cron/node-cron/scenario.ts new file mode 100644 index 000000000000..71b005d4dfd6 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/cron/node-cron/scenario.ts @@ -0,0 +1,9 @@ +import * as Sentry from '@sentry/node'; +import { CronJob } from 'cron'; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const CronJobWithCheckIn = Sentry.cron.instrumentCron(CronJob, 'my-cron-job'); + +setTimeout(() => { + process.exit(0); +}, 1_000); diff --git a/dev-packages/node-integration-tests/suites/cron/node-cron/test.ts b/dev-packages/node-integration-tests/suites/cron/node-cron/test.ts new file mode 100644 index 000000000000..b768599cd215 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/cron/node-cron/test.ts @@ -0,0 +1,9 @@ +import { cleanupChildProcesses, createRunner } from '../../../utils/runner'; + +afterAll(() => { + cleanupChildProcesses(); +}); + +test('node-cron types should match', done => { + createRunner(__dirname, 'scenario.ts').ensureNoErrorOutput().start(done); +}); diff --git a/dev-packages/node-integration-tests/utils/runner.ts b/dev-packages/node-integration-tests/utils/runner.ts index 1831761c3181..31969452ba74 100644 --- a/dev-packages/node-integration-tests/utils/runner.ts +++ b/dev-packages/node-integration-tests/utils/runner.ts @@ -70,6 +70,7 @@ export function createRunner(...paths: string[]) { const flags: string[] = []; const ignored: EnvelopeItemType[] = []; let withSentryServer = false; + let ensureNoErrorOutput = false; if (testPath.endsWith('.ts')) { flags.push('-r', 'ts-node/register'); @@ -92,6 +93,10 @@ export function createRunner(...paths: string[]) { ignored.push(...types); return this; }, + ensureNoErrorOutput: function () { + ensureNoErrorOutput = true; + return this; + }, start: function (done?: (e?: unknown) => void) { const expectedEnvelopeCount = expectedEnvelopes.length; @@ -190,8 +195,19 @@ export function createRunner(...paths: string[]) { CHILD_PROCESSES.add(child); + if (ensureNoErrorOutput) { + child.stderr.on('data', (data: Buffer) => { + const output = data.toString(); + complete(new Error(`Expected no error output but got: '${output}'`)); + }); + } + child.on('close', () => { hasExited = true; + + if (ensureNoErrorOutput) { + complete(); + } }); // Pass error to done to end the test quickly diff --git a/packages/node/src/cron/cron.ts b/packages/node/src/cron/cron.ts index 88a3e9e58eb5..2540d82e736b 100644 --- a/packages/node/src/cron/cron.ts +++ b/packages/node/src/cron/cron.ts @@ -8,10 +8,17 @@ export type CronJobParams = { start?: boolean | null; context?: unknown; runOnInit?: boolean | null; - utcOffset?: number; - timeZone?: string; unrefTimeout?: boolean | null; -}; +} & ( + | { + timeZone?: string | null; + utcOffset?: never; + } + | { + timeZone?: never; + utcOffset?: number | null; + } +); export type CronJob = { // @@ -28,6 +35,17 @@ export type CronJobConstructor = { timeZone?: CronJobParams['timeZone'], context?: CronJobParams['context'], runOnInit?: CronJobParams['runOnInit'], + utcOffset?: null, + unrefTimeout?: CronJobParams['unrefTimeout'], + ): CronJob; + new ( + cronTime: CronJobParams['cronTime'], + onTick: CronJobParams['onTick'], + onComplete?: CronJobParams['onComplete'], + start?: CronJobParams['start'], + timeZone?: null, + context?: CronJobParams['context'], + runOnInit?: CronJobParams['runOnInit'], utcOffset?: CronJobParams['utcOffset'], unrefTimeout?: CronJobParams['unrefTimeout'], ): CronJob; diff --git a/yarn.lock b/yarn.lock index 2a082acd3aa5..daeb04398140 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6268,6 +6268,11 @@ resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.0.tgz#57f228f2b80c046b4a1bd5cac031f81f207f4f03" integrity sha512-RaE0B+14ToE4l6UqdarKPnXwVDuigfFv+5j9Dze/Nqr23yyuqdNvzcZi3xB+3Agvi5R4EOgAksfv3lXX4vBt9w== +"@types/luxon@~3.3.0": + version "3.3.8" + resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-3.3.8.tgz#84dbf2d020a9209a272058725e168f21d331a67e" + integrity sha512-jYvz8UMLDgy3a5SkGJne8H7VA7zPV2Lwohjx0V8V31+SqAjNmurWMkk9cQhfvlcnXWudBpK9xPM1n4rljOcHYQ== + "@types/md5@2.1.33": version "2.1.33" resolved "https://registry.yarnpkg.com/@types/md5/-/md5-2.1.33.tgz#8c8dba30df4ad0e92296424f08c4898dd808e8df" @@ -11947,6 +11952,14 @@ critters@0.0.12: postcss "^8.3.7" pretty-bytes "^5.3.0" +cron@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/cron/-/cron-3.1.6.tgz#e7e1798a468e017c8d31459ecd7c2d088f97346c" + integrity sha512-cvFiQCeVzsA+QPM6fhjBtlKGij7tLLISnTSvFxVdnFGLdz+ZdXN37kNe0i2gefmdD17XuZA6n2uPVwzl4FxW/w== + dependencies: + "@types/luxon" "~3.3.0" + luxon "~3.4.0" + cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -20696,6 +20709,11 @@ lunr@^2.3.8: resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== +luxon@~3.4.0: + version "3.4.4" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.4.4.tgz#cf20dc27dc532ba41a169c43fdcc0063601577af" + integrity sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA== + lz-string@^1.4.4: version "1.4.4" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26"