Skip to content

Commit

Permalink
Refactor node / browser to share Context, EventQueue, attempt(), Stat…
Browse files Browse the repository at this point in the history
…s, dispatch(), Plugins, and update traits and context interface (#722)
  • Loading branch information
silesky authored Dec 14, 2022
1 parent ad76582 commit 61688e2
Show file tree
Hide file tree
Showing 83 changed files with 810 additions and 3,094 deletions.
7 changes: 7 additions & 0 deletions .changeset/sweet-rings-tie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@segment/analytics-next': minor
'@segment/analytics-core': minor
---

Improve core interfaces. Refactor analytics-next to use shared EventQueue, dispatch, and other methods.
Augment Browser interface with traits and context options type.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ module.exports = {
'@typescript-eslint/ban-ts-ignore': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-empty-interface': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-floating-promises': [
Expand Down
6 changes: 2 additions & 4 deletions examples/standalone-playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@
"hoistingLimits": "workspaces"
},
"scripts": {
"dev": "yarn concurrently 'yarn run -T watch --filter=standalone-playground' 'sleep 10 && npx http-server .'"
"dev": "yarn concurrently 'yarn run -T watch --filter=standalone-playground' 'sleep 10 && npx http-server .'",
"concurrently": "yarn run -T concurrently"
},
"dependencies": {
"@segment/analytics-next": "workspace:^"
},
"devDependencies": {
"concurrently": "^7.2.1"
}
}
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,17 @@
"@changesets/cli": "^2.23.2",
"@internal/config": "workspace:^",
"@npmcli/promise-spawn": "^3.0.0",
"@types/express": "4",
"@types/jest": "^28.1.1",
"@types/lodash": "^4",
"@types/node-fetch": "^2.6.2",
"@typescript-eslint/eslint-plugin": "^5.21.0",
"@typescript-eslint/parser": "^5.21.0",
"concurrently": "^7.2.1",
"concurrently": "^7.6.0",
"eslint": "^8.14.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0",
"express": "^4.18.2",
"get-monorepo-packages": "^1.2.0",
"husky": "^8.0.0",
"jest": "^28.1.0",
Expand All @@ -60,6 +62,7 @@
},
"resolutions": {
"@segment/analytics-next": "workspace:*",
"@segment/analytics-node": "workspace:*"
"@segment/analytics-node": "workspace:*",
"@segment/analytics-core": "workspace:*"
}
}
1 change: 1 addition & 0 deletions packages/browser-integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"scripts": {
"test": "playwright test",
"lint": "yarn concurrently 'yarn:eslint .' 'yarn:tsc --noEmit'",
"concurrently": "yarn run -T concurrently",
"watch:test": "yarn test --watch",
"tsc": "yarn run -T tsc",
"eslint": "yarn run -T eslint",
Expand Down
3 changes: 1 addition & 2 deletions packages/browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"tsc": "yarn run -T tsc",
"jest": "yarn run -T jest",
"concurrently": "yarn run -T concurrently",
"watch": "yarn concurrently 'NODE_ENV=production yarn umd --watch' 'yarn pkg --watch --incremental'",
"watch": "yarn concurrently 'NODE_ENV=production WATCH=true yarn umd --watch' 'yarn pkg --watch'",
"build": "yarn clean && yarn build-prep && yarn concurrently 'NODE_ENV=production yarn umd' 'yarn pkg' 'yarn cjs'",
"release:cdn": "yarn run -T browser+deps build && NODE_ENV=production bash scripts/release.sh",
"pkg": "yarn tsc -p tsconfig.build.json",
Expand Down Expand Up @@ -79,7 +79,6 @@
"circular-dependency-plugin": "^5.2.2",
"compression-webpack-plugin": "^8.0.1",
"execa": "^4.1.0",
"express": "^4.17.3",
"flat": "^5.0.2",
"fs-extra": "^9.0.1",
"jest-dev-server": "^6.0.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const writeKey = 'foo'

const errMsg = 'errMsg'

jest.spyOn(console, 'error').mockImplementation(() => {}) // silence console spam

describe('Pre-initialization', () => {
const trackSpy = jest.spyOn(Analytics.prototype, 'track')
const identifySpy = jest.spyOn(Analytics.prototype, 'identify')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import unfetch from 'unfetch'
import { PersistedPriorityQueue } from '../../lib/priority-queue/persisted'
import { sleep } from '../../lib/sleep'
import * as Factory from '../../test-helpers/factories'
import { EventQueue } from '@segment/analytics-core'
import { EventQueue } from '../../core/queue/event-queue'

const track = jest.fn()
const identify = jest.fn()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { Analytics } from '@/core/analytics'
import { Context } from '@/core/context'
import { AnalyticsBrowser } from '@/browser'
import { assertNotAny, assertIs } from '@/test-helpers/type-assertions'
import { Group, User } from '../../../core/user'
import { AnalyticsBrowser, Analytics, Context, User, Group } from '../../..'
import { assertNotAny, assertIs } from '../../../test-helpers/type-assertions'

/**
* These are general typescript definition tests;
Expand Down Expand Up @@ -77,23 +74,23 @@ export default {
'Identify should work with spread objects ': () => {
const user = {
name: 'john',
id: 12345,
id: 'abc123',
}
const { id, ...traits } = user
void AnalyticsBrowser.load({ writeKey: 'foo' }).identify('foo', traits)
},
'Track should work with spread objects': () => {
const user = {
name: 'john',
id: 12345,
id: 'abc123',
}
const { id, ...traits } = user
void AnalyticsBrowser.load({ writeKey: 'foo' }).track('foo', traits)
},
'Identify should work with generic objects ': () => {
const user = {
name: 'john',
id: 12345,
id: 'abc123',
}
void AnalyticsBrowser.load({ writeKey: 'foo' }).identify('foo', user)
},
Expand Down Expand Up @@ -122,4 +119,12 @@ export default {
assertNotAny(analytics)
assertIs<AnalyticsBrowser>(analytics)
},
'Should error if there is a type conflict in Traits': () => {
const analytics = new AnalyticsBrowser().load({ writeKey: 'foo' })
assertNotAny(analytics)
assertIs<AnalyticsBrowser>(analytics)

// @ts-expect-error - id should be a string
void analytics.identify('foo', { id: 123 })
},
}
2 changes: 1 addition & 1 deletion packages/browser/src/browser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ async function loadAnalytics(

const plugins = settings.plugins ?? []
const classicIntegrations = settings.classicIntegrations ?? []
Context.initMetrics(legacySettings.metrics)
Context.initRemoteMetrics(legacySettings.metrics)

// needs to be flushed before plugins are registered
flushPreBuffer(analytics, preInitBuffer)
Expand Down
24 changes: 12 additions & 12 deletions packages/browser/src/core/analytics/__tests__/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import { Plugin } from '../../plugin'
import { EventQueue } from '../../queue/event-queue'
import { Analytics } from '../index'
import {
AfterPlugin,
BeforePlugin,
DestinationPlugin,
EnrichmentPlugin,
TestAfterPlugin,
TestBeforePlugin,
TestDestinationPlugin,
TestEnrichmentPlugin,
} from './test-plugins'

describe('Analytics', () => {
Expand All @@ -34,7 +34,7 @@ describe('Analytics', () => {
const shouldThrow = true

it(`"before" plugin errors should not throw (single dispatched event)`, async () => {
const plugin = new BeforePlugin({ shouldThrow })
const plugin = new TestBeforePlugin({ shouldThrow })
const trackSpy = jest.spyOn(plugin, 'track')

await analytics.register(plugin)
Expand All @@ -45,7 +45,7 @@ describe('Analytics', () => {
})

it(`"before" plugin errors should not throw (multiple dispatched events)`, async () => {
const plugin = new BeforePlugin({ shouldThrow })
const plugin = new TestBeforePlugin({ shouldThrow })
const trackSpy = jest.spyOn(plugin, 'track')

await analytics.register(plugin)
Expand All @@ -63,7 +63,7 @@ describe('Analytics', () => {
})

it(`"before" plugin errors should not impact callbacks`, async () => {
const plugin = new BeforePlugin({ shouldThrow })
const plugin = new TestBeforePlugin({ shouldThrow })
const trackSpy = jest.spyOn(plugin, 'track')

await analytics.register(plugin)
Expand Down Expand Up @@ -102,9 +102,9 @@ describe('Analytics', () => {
}

const testPlugins = [
new EnrichmentPlugin({ shouldThrow }),
new DestinationPlugin({ shouldThrow }),
new AfterPlugin({ shouldThrow }),
new TestEnrichmentPlugin({ shouldThrow }),
new TestDestinationPlugin({ shouldThrow }),
new TestAfterPlugin({ shouldThrow }),
]
testPlugins.forEach((plugin) => {
it(`"${plugin.type}" plugin errors should not throw (single dispatched event)`, async () => {
Expand Down Expand Up @@ -152,7 +152,7 @@ describe('Analytics', () => {
})

it('"before" plugin supports cancelation (single dispatched event)', async () => {
const plugin = new BeforePlugin({ shouldCancel: true })
const plugin = new TestBeforePlugin({ shouldCancel: true })
const trackSpy = jest.spyOn(plugin, 'track')

await analytics.register(plugin)
Expand All @@ -164,7 +164,7 @@ describe('Analytics', () => {
})

it('"before" plugin supports cancelation (multiple dispatched events)', async () => {
const plugin = new BeforePlugin({ shouldCancel: true })
const plugin = new TestBeforePlugin({ shouldCancel: true })
const trackSpy = jest.spyOn(plugin, 'track')

await analytics.register(plugin)
Expand Down
13 changes: 9 additions & 4 deletions packages/browser/src/core/analytics/__tests__/test-plugins.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Context, ContextCancelation, Plugin } from '../../../index'
import type { DestinationPlugin } from '../../plugin'

export interface BasePluginOptions {
shouldThrow?: boolean
Expand Down Expand Up @@ -64,26 +65,30 @@ class BasePlugin implements Partial<Plugin> {
}
}

export class BeforePlugin extends BasePlugin implements Plugin {
export class TestBeforePlugin extends BasePlugin implements Plugin {
public name = 'Test Before Error'
public type = 'before' as const
}

export class EnrichmentPlugin extends BasePlugin implements Plugin {
export class TestEnrichmentPlugin extends BasePlugin implements Plugin {
public name = 'Test Enrichment Error'
public type = 'enrichment' as const
}

export class DestinationPlugin extends BasePlugin implements Plugin {
export class TestDestinationPlugin
extends BasePlugin
implements DestinationPlugin
{
public name = 'Test Destination Error'
public type = 'destination' as const
addMiddleware() {}

public ready() {
return Promise.resolve(true)
}
}

export class AfterPlugin extends BasePlugin implements Plugin {
export class TestAfterPlugin extends BasePlugin implements Plugin {
public name = 'Test After Error'
public type = 'after' as const
}
Loading

0 comments on commit 61688e2

Please sign in to comment.