Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new buffered methods, improve types #561

Merged
merged 6 commits into from
Aug 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/grumpy-oranges-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@segment/analytics-next': minor
---

Add 'screen', 'register', 'deregister', 'user' method and 'VERSION' property on AnalyticsBrowser. Allow buffering of 'screen', 'register', 'deregister' methods for snippet users.
3 changes: 3 additions & 0 deletions examples/standalone-playground/pages/index-local-batched.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
else {
analytics.invoked = !0
analytics.methods = [
'screen',
'register',
'deregister',
'trackSubmit',
'trackClick',
'trackLink',
Expand Down
3 changes: 3 additions & 0 deletions examples/standalone-playground/pages/index-local-csp.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
else {
analytics.invoked = !0
analytics.methods = [
'screen',
'register',
'deregister',
'trackSubmit',
'trackClick',
'trackLink',
Expand Down
3 changes: 3 additions & 0 deletions examples/standalone-playground/pages/index-local-errors.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
else {
analytics.invoked = !0
analytics.methods = [
'screen',
'register',
'deregister',
'trackSubmit',
'trackClick',
'trackLink',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
else {
analytics.invoked = !0
analytics.methods = [
'screen',
'register',
'deregister',
'trackSubmit',
'trackClick',
'trackLink',
Expand Down
3 changes: 3 additions & 0 deletions examples/standalone-playground/pages/index-local.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
else {
analytics.invoked = !0
analytics.methods = [
'screen',
'register',
'deregister',
'trackSubmit',
'trackClick',
'trackLink',
Expand Down
3 changes: 3 additions & 0 deletions examples/standalone-playground/pages/index-remote.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
else {
analytics.invoked = !0
analytics.methods = [
'screen',
'register',
'deregister',
'trackSubmit',
'trackClick',
'trackLink',
Expand Down
2 changes: 1 addition & 1 deletion packages/browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"size-limit": [
{
"path": "dist/umd/index.js",
"limit": "25.85 KB"
"limit": "25.9 KB"
}
],
"dependencies": {
Expand Down
6 changes: 6 additions & 0 deletions packages/browser/qa/__fixtures__/snippets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ export function next(writekey: string, obfuscate: boolean) {
else {
analytics.invoked = !0
analytics.methods = [
'screen',
'register',
'deregister',
'trackSubmit',
'trackClick',
'trackLink',
Expand Down Expand Up @@ -84,6 +87,9 @@ export function classic(writekey: string) {
else {
analytics.invoked = !0
analytics.methods = [
'screen',
'register',
'deregister',
'trackSubmit',
'trackClick',
'trackLink',
Expand Down
9 changes: 4 additions & 5 deletions packages/browser/src/browser/__tests__/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { Context } from '@/core/context'
import { Plugin } from '@/core/plugin'
import { JSDOM } from 'jsdom'
import { Analytics } from '../../core/analytics'
import { Group } from '../../core/user'
import { LegacyDestination } from '../../plugins/ajs-destination'
import { PersistedPriorityQueue } from '../../lib/priority-queue/persisted'
// @ts-ignore loadLegacySettings mocked dependency is accused as unused
Expand Down Expand Up @@ -258,7 +257,7 @@ describe('Initialization', () => {
)

expect(ajs.user().options.persist).toBe(false)
expect((ajs.group() as Group).options.persist).toBe(false)
expect(ajs.group().options.persist).toBe(false)
})

it('fetch remote source settings by default', async () => {
Expand Down Expand Up @@ -536,11 +535,11 @@ describe('Group', () => {
writeKey,
})

const group = analytics.group() as Group
const group = analytics.group()

const ctx = (await analytics.group('coolKids', {
const ctx = await analytics.group('coolKids', {
coolKids: true,
})) as Context
})

expect(ctx.event.groupId).toEqual('coolKids')
expect(ctx.event.traits).toEqual({ coolKids: true })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Analytics } from '@/core/analytics'
import { Context } from '@/core/context'
import { AnalyticsBrowser } from '@/browser'
import { assertNotAny, assertIs } from '@/test-helpers/type-assertions'
import { Group } from '../../../core/user'

/**
* These are general typescript definition tests;
Expand Down Expand Up @@ -54,4 +55,16 @@ export default {
assertIs<number | [Analytics, Context]>(response)
})
},

'Group should have the correct type': () => {
const ajs = AnalyticsBrowser.load({ writeKey: 'foo' })
{
const grpResult = ajs.group()
assertIs<Promise<Group>>(grpResult)
}
{
const grpResult = ajs.group('foo')
assertIs<Promise<Context>>(grpResult)
}
},
}
88 changes: 32 additions & 56 deletions packages/browser/src/core/analytics/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,18 @@ import {
UserParams,
} from '../arguments-resolver'
import type { FormArgs, LinkArgs } from '../auto-track'
import { Callback, invokeCallback } from '../callback'
import { invokeCallback } from '../callback'
import { isOffline } from '../connection'
import { Context } from '../context'
import { Emitter } from '@segment/analytics-core'
import { EventFactory, Integrations, Plan, SegmentEvent } from '../events'
import {
Callback,
EventFactory,
Integrations,
Plan,
EventProperties,
SegmentEvent,
} from '../events'
import { Plugin } from '../plugin'
import { EventQueue } from '../queue/event-queue'
import { CookieOptions, Group, ID, User, UserOptions } from '../user'
Expand All @@ -30,6 +37,7 @@ import { version } from '../../generated/version'
import { PriorityQueue } from '../../lib/priority-queue'
import { getGlobal } from '../../lib/get-global'
import { inspectorHost } from '../inspector'
import { AnalyticsClassic, AnalyticsSnippetCore } from './interfaces'

const deprecationWarning =
'This is being deprecated and will be not be available in future releases of Analytics JS'
Expand Down Expand Up @@ -69,7 +77,15 @@ export interface InitOptions {
obfuscate?: boolean
}

export class Analytics extends Emitter {
/* analytics-classic stubs */
function _stub(this: never) {
console.warn(deprecationWarning)
}

export class Analytics
extends Emitter
implements AnalyticsSnippetCore, AnalyticsClassic
{
protected settings: AnalyticsSettings
private _user: User
private _group: Group
Expand Down Expand Up @@ -127,7 +143,7 @@ export class Analytics extends Emitter {

const segmentEvent = this.eventFactory.track(
name,
data as SegmentEvent['properties'],
data as EventProperties,
opts,
this.integrations
)
Expand Down Expand Up @@ -180,6 +196,8 @@ export class Analytics extends Emitter {
})
}

group(): Group
group(...args: UserParams): Promise<DispatchedEvent>
group(...args: UserParams): Promise<DispatchedEvent> | Group {
if (args.length === 0) {
return this._group
Expand Down Expand Up @@ -503,58 +521,16 @@ export class Analytics extends Emitter {
return integrations
}

// analytics-classic stubs

log() {
console.warn(deprecationWarning)
return
}

addIntegrationMiddleware() {
console.warn(deprecationWarning)
return
}

listeners() {
console.warn(deprecationWarning)
return
}

addEventListener() {
console.warn(deprecationWarning)
return
}

removeAllListeners() {
console.warn(deprecationWarning)
return
}

removeListener() {
console.warn(deprecationWarning)
return
}

removeEventListener() {
console.warn(deprecationWarning)
return
}

hasListeners() {
console.warn(deprecationWarning)
return
}

// This function is only used to add GA and Appcue, but these are already being added to Integrations by AJSN
addIntegration() {
console.warn(deprecationWarning)
return
}

add() {
console.warn(deprecationWarning)
return
}
log = _stub
addIntegrationMiddleware = _stub
listeners = _stub
addEventListener = _stub
removeAllListeners = _stub
removeListener = _stub
removeEventListener = _stub
hasListeners = _stub
add = _stub
addIntegration = _stub

// snippet function
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down
106 changes: 106 additions & 0 deletions packages/browser/src/core/analytics/interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import type { Analytics, AnalyticsSettings, InitOptions } from '.'
import type { Plugin } from '../plugin'
import type {
EventParams,
DispatchedEvent,
PageParams,
UserParams,
AliasParams,
} from '../arguments-resolver'
import type { Context } from '../context'
import type { SegmentEvent } from '../events'
import type { Group, User } from '../user'
import type { LegacyIntegration } from '../../plugins/ajs-destination/types'

// we can define a contract because:
// - it gives us a neat place to put all our typedocs (they end up being inherited by the class that implements them).
// - it makes it easy to reason about what's being shared between browser and node

/**
* All of these methods are a no-op.
*/
/** @deprecated */
interface AnalyticsClassicStubs {
/** @deprecated */
log(this: never): void
/** @deprecated */
addIntegrationMiddleware(this: never): void
/** @deprecated */
listeners(this: never): void
/** @deprecated */
addEventListener(this: never): void
/** @deprecated */
removeAllListeners(this: never): void
/** @deprecated */
removeListener(this: never): void
/** @deprecated */
removeEventListener(this: never): void
/** @deprecated */
hasListeners(this: never): void
/** @deprecated */
// This function is only used to add GA and Appcue, but these are already being added to Integrations by AJSN
addIntegration(this: never): void
/** @deprecated */
add(this: never): void
}

/** @deprecated */
export interface AnalyticsClassic extends AnalyticsClassicStubs {
/** @deprecated */
initialize(
settings?: AnalyticsSettings,
options?: InitOptions
): Promise<Analytics>

/** @deprecated */
noConflict(): Analytics

/** @deprecated */
normalize(msg: SegmentEvent): SegmentEvent

/** @deprecated */
readonly failedInitializations: string[]

/** @deprecated */
pageview(url: string): Promise<Analytics>

/** @deprecated*/
readonly plugins: any

/** @deprecated */
readonly Integrations: Record<string, LegacyIntegration>
}

/**
* Interface implemented by the snippet ('Analytics')
*/
export interface AnalyticsSnippetCore {
track(...args: EventParams): Promise<DispatchedEvent>
page(...args: PageParams): Promise<DispatchedEvent>
identify(...args: UserParams): Promise<DispatchedEvent>
group(): Group
group(...args: UserParams): Promise<DispatchedEvent>
alias(...args: AliasParams): Promise<DispatchedEvent>
screen(...args: PageParams): Promise<DispatchedEvent>
register(...plugins: Plugin[]): Promise<Context>
deregister(...plugins: string[]): Promise<Context>
user(): User
readonly VERSION: string
}

/**
* Interface implemented by AnalyticsBrowser
*/
export interface AnalyticsBrowserCore {
track: AnalyticsSnippetCore['track']
page: AnalyticsSnippetCore['page']
identify: AnalyticsSnippetCore['identify']
group(): Promise<Group> // Different than AnalyticsSnippetCore ^
group(...args: UserParams): Promise<DispatchedEvent>
alias: AnalyticsSnippetCore['alias']
screen: AnalyticsSnippetCore['screen']
register: AnalyticsSnippetCore['register']
deregister: AnalyticsSnippetCore['deregister']
user(): Promise<User> // Different than AnalyticsSnippetCore ^
readonly VERSION: AnalyticsSnippetCore['VERSION']
}
Loading