Skip to content
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
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

# Session Replay Packages (Browser)
# Owned by the Session Replay SDK team
/packages/amp-semantic/ @amplitude/session-replay-sdk
/packages/session-replay-browser/ @amplitude/session-replay-sdk
/packages/plugin-session-replay-browser/ @amplitude/session-replay-sdk
/packages/segment-session-replay-plugin/ @amplitude/session-replay-sdk
Expand Down
44 changes: 44 additions & 0 deletions packages/amp-semantic/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# @amplitude/amp-semantic

Package foundation for semantic event capture in Amplitude. This increment establishes
workspace packaging, CommonJS/ESM builds, TypeScript declarations, linting, tests, and
the shared event envelope. It does not collect or emit events.

## Public contracts

- `SEMANTIC_VERSION`: payload envelope version (`1`).
- `SemanticIdentity`: `tab_id` and `document_id` correlation fields.
- `SemanticEventEnvelope<Name, Payload>`: a typed name, timestamp, and payload
containing the caller's fields plus version and identity.

No event families are defined or registered. The package has no browser listeners,
DOM observers, storage access, identity generation, capture runtime, or Session Replay
integration. It is not yet a usable capture SDK.

## Incremental implementation

1. **This PR:** package structure and shared envelope contracts.
2. **Context and visibility:** capture runtime, sampling/caps, identity generation,
recorders, event schemas, Session Replay integration, and a local test page.
3. **Dialog and notice:** rrweb mutation input, DOM enrichment, and feedback recorders.
4. Additional event families in later PRs.

The existing full implementation remains available in PR #2082. Each event increment
should add its contracts, implementation, documentation, and validation together.

## Development

From the repository root:

```sh
pnpm install
pnpm build
pnpm --filter @amplitude/amp-semantic typecheck
pnpm --filter @amplitude/amp-semantic test --runInBand
pnpm --filter @amplitude/amp-semantic lint
```

The package build cleans `lib` before generating `lib/cjs` and `lib/esm`, avoiding stale
recorders when switching between incremental branches. Runtime dependencies are limited
to the workspace-standard TypeScript helper library; event-specific dependencies arrive
with their implementations.
6 changes: 6 additions & 0 deletions packages/amp-semantic/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
...require('../../jest.config.js'),
displayName: '@amplitude/amp-semantic',
rootDir: '.',
testEnvironment: 'node',
};
36 changes: 36 additions & 0 deletions packages/amp-semantic/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "@amplitude/amp-semantic",
"version": "0.1.0",
"description": "Shared package foundation for Amplitude semantic event capture",
"license": "MIT",
"main": "lib/cjs/index.js",
"module": "lib/esm/index.js",
"types": "lib/esm/index.d.ts",
"sideEffects": false,
"files": [
"lib"
],
"publishConfig": {
"access": "public"
},
"scripts": {
"clean": "rimraf lib",
"build": "pnpm clean && pnpm build:es5 && pnpm build:esm",
"build:es5": "tsc -p tsconfig.es5.json",
"build:esm": "tsc -p tsconfig.esm.json",
"test": "jest",
"lint": "eslint '{src,test}/**/*.ts'",
"typecheck": "tsc -p tsconfig.json"
},
"dependencies": {
"tslib": "^2.4.1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/amplitude/Amplitude-TypeScript.git"
},
"homepage": "https://github.com/amplitude/Amplitude-TypeScript",
"devDependencies": {
"rimraf": "^3.0.2"
}
}
2 changes: 2 additions & 0 deletions packages/amp-semantic/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { SEMANTIC_VERSION } from './types';
export type { SemanticIdentity, SemanticEventEnvelope } from './types';
15 changes: 15 additions & 0 deletions packages/amp-semantic/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/** Version of the shared semantic payload envelope. */
export const SEMANTIC_VERSION = 1;

/** Correlation identifiers supplied by a future capture host. */
export interface SemanticIdentity {
readonly tab_id: string;
readonly document_id: string;
}

/** Internal event envelope, independent of any event family or replay transport. */
export interface SemanticEventEnvelope<Name extends string, Payload extends object> {
name: Name;
timestamp: number;
payload: Payload & SemanticIdentity & { v: typeof SEMANTIC_VERSION };
}
25 changes: 25 additions & 0 deletions packages/amp-semantic/test/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { SEMANTIC_VERSION, SemanticEventEnvelope, SemanticIdentity } from '../src';

// Exercise the public type exports without defining a production event family.
const identity: SemanticIdentity = { tab_id: 'test-tab', document_id: 'test-document' };
const event: SemanticEventEnvelope<'test-only', { count: number }> = {
name: 'test-only',
timestamp: 123,
payload: { ...identity, v: SEMANTIC_VERSION, count: 1 },
};

test('exports a versioned envelope contract that preserves the host payload', () => {
expect(JSON.parse(JSON.stringify(event))).toEqual({
name: 'test-only',
timestamp: 123,
payload: { tab_id: 'test-tab', document_id: 'test-document', v: 1, count: 1 },
});
});

// These compile-time assertions protect event-name/payload pairing and required metadata.
// @ts-expect-error The event name must match the selected family.
const invalidName: typeof event = { ...event, name: 'different-family' };
// @ts-expect-error Version and identity are mandatory, even for a payload with no domain fields.
const missingMetadata: SemanticEventEnvelope<'test-only', object> = { name: 'test-only', timestamp: 0, payload: {} };
void invalidName;
void missingMetadata;
10 changes: 10 additions & 0 deletions packages/amp-semantic/tsconfig.es5.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"include": ["src/**/*"],
"compilerOptions": {
"module": "commonjs",
"noEmit": false,
"rootDir": "src",
"outDir": "lib/cjs"
}
}
10 changes: 10 additions & 0 deletions packages/amp-semantic/tsconfig.esm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"include": ["src/**/*"],
"compilerOptions": {
"module": "es2020",
"noEmit": false,
"rootDir": "src",
"outDir": "lib/esm"
}
}
8 changes: 8 additions & 0 deletions packages/amp-semantic/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "../../tsconfig.json",
"include": ["src/**/*", "test/**/*"],
"compilerOptions": {
"noEmit": true,
"rootDir": "."
}
}
10 changes: 10 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading