Skip to content

Commit 5994f88

Browse files
committed
feat(analytics): introduce @metamask/analytics-client package for analytics handling
- Created a new package `@metamask/analytics-client` to encapsulate analytics functionality. - Added TypeScript types for analytics events and originator information in `@metamask/sdk-types`. - Updated various SDK packages to utilize the new analytics client, enhancing modularity and maintainability. - Refactored existing analytics code to leverage the new package, ensuring consistent event tracking across the SDK. - Updated package dependencies and configurations to support the new structure.
1 parent 3349f7f commit 5994f88

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+860
-296
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"packages/sdk-react-native",
1616
"packages/sdk-react-ui",
1717
"packages/sdk-ui",
18+
"packages/sdk-types",
1819
"packages/sdk-lab",
1920
"packages/devsocket",
2021
"packages/devreact",
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const path = require('path');
2+
3+
/**
4+
* @type {import('eslint').Linter.Config}
5+
*/
6+
module.exports = {
7+
extends: ['@metamask/eslint-config-typescript', '../../.eslintrc.js'],
8+
root: true,
9+
parser: '@typescript-eslint/parser',
10+
parserOptions: {
11+
project: [path.resolve(__dirname, 'tsconfig.eslint.json')],
12+
},
13+
14+
ignorePatterns: [
15+
'.prettierrc.js',
16+
'**/.eslintrc.js',
17+
'**/jest.config.ts',
18+
'**/dist*/',
19+
],
20+
21+
overrides: [
22+
{
23+
files: ['**/*.ts'],
24+
rules: {
25+
// Add any specific rule overrides for analytics-client here if needed
26+
// Example:
27+
// '@typescript-eslint/consistent-type-definitions': [
28+
// 'error',
29+
// 'interface',
30+
// ],
31+
},
32+
},
33+
],
34+
};

packages/analytics-client/STEPS.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Analytics Client Migration Plan
2+
3+
This plan outlines the steps to extract the analytics client logic from `@metamask/sdk-communication-layer` into this new `@metamask/analytics-client` package.
4+
5+
1. **Configure `package.json` for Public Release (`packages/analytics-client/package.json`):**
6+
7+
- Ensure `name` is `@metamask/analytics-client`.
8+
- Set a starting `version` (e.g., `0.1.0`).
9+
- Set `private: false`.
10+
- Add essential public package fields: `description`, `license`, `homepage`, `bugs`, `repository`, `author` (copy/adapt from another public package like `@metamask/sdk-communication-layer`).
11+
- Define `main: "dist/src/index.js"` and `types: "dist/src/index.d.ts"`.
12+
- Add build/lint/test/clean scripts (copy/adapt from another package).
13+
- Add `dependencies`: `"cross-fetch": "latest"`, `"@metamask/sdk-communication-layer": "workspace:^"`.
14+
- Add standard `devDependencies` (`typescript`, `@types/node`, etc., adapt from another package).
15+
- Add `publishConfig: { "access": "public" }`.
16+
- Ensure `files` includes `dist/`.
17+
18+
2. **Verify & Configure `tsconfig.json` (`packages/analytics-client/tsconfig.json`):**
19+
20+
- Ensure it extends a base config if applicable (e.g., `../../tsconfig.base.json`).
21+
- Set `compilerOptions.outDir` to `"./dist"`.
22+
- Set `compilerOptions.rootDir` to `"./src"`.
23+
- Include `"src/**/*"` and exclude `node_modules`, `dist`.
24+
25+
3. **Move Analytics Code:**
26+
27+
- Move the file `packages/sdk-communication-layer/src/Analytics.ts` to `packages/analytics-client/src/Analytics.ts`.
28+
29+
4. **Refactor Moved Code (`packages/analytics-client/src/Analytics.ts`):**
30+
31+
- Update import paths for types (`TrackingEvents`, `OriginatorInfo`, `CommunicationLayerPreference`) to point to `@metamask/sdk-communication-layer`.
32+
- Remove the import and usage of the `logger` from `sdk-communication-layer`. (Logging within `SendAnalytics` can be revisited if necessary).
33+
34+
5. **Export from New Package (`packages/analytics-client/src/index.ts`):**
35+
36+
- Export `SendAnalytics` and `AnalyticsProps` from `./Analytics`.
37+
- Re-export `TrackingEvents`, `OriginatorInfo`, `CommunicationLayerPreference` from `@metamask/sdk-communication-layer` for consumer convenience.
38+
39+
6. **Update Dependencies in Consuming Packages:**
40+
41+
- In `packages/sdk/package.json`: Add `"@metamask/analytics-client": "workspace:^"` to `dependencies`.
42+
- In `packages/sdk-communication-layer/package.json`: Remove `"cross-fetch"` from `dependencies` (if it's no longer used elsewhere in that package).
43+
44+
7. **Update SDK Code (`packages/sdk/src/services/Analytics.ts` & `Analytics.test.ts`):**
45+
46+
- Change imports of `SendAnalytics`, `AnalyticsProps`, `TrackingEvents` from `@metamask/sdk-communication-layer` to `@metamask/analytics-client`.
47+
- Keep the import for `DEFAULT_SERVER_URL` pointing to `@metamask/sdk-communication-layer`.
48+
- Update the `jest.mock` path in `Analytics.test.ts` to `@metamask/analytics-client`.
49+
50+
8. **Clean Up Communication Layer (`packages/sdk-communication-layer`):**
51+
52+
- Delete the original `packages/sdk-communication-layer/src/Analytics.ts` file.
53+
- In `packages/sdk-communication-layer/src/index.ts`, remove the exports for `SendAnalytics` and `AnalyticsProps`. Keep exports for the shared types (`TrackingEvents`, `OriginatorInfo`, etc.).
54+
55+
9. **Install & Build:**
56+
57+
- Run `yarn install` at the workspace root to link the new package and update dependencies.
58+
- Run `yarn build` (or the appropriate workspace build command) at the root to compile the new package and check for errors.
59+
60+
10. **Test:**
61+
- Run `yarn test` (or the appropriate workspace test command) at the root. Address any test failures, particularly in `packages/sdk`.
Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,58 @@
11
{
2-
"name": "analytics-client",
2+
"name": "@metamask/analytics-client",
3+
"version": "0.1.0",
4+
"description": "Client library for sending analytics events for MetaMask SDK",
5+
"homepage": "https://github.com/MetaMask/metamask-sdk#readme",
6+
"bugs": {
7+
"url": "https://github.com/MetaMask/metamask-sdk/issues"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "https://github.com/MetaMask/metamask-sdk.git",
12+
"directory": "packages/analytics-client"
13+
},
14+
"license": "MIT",
15+
"author": "MetaMask",
16+
"main": "dist/index.js",
17+
"types": "dist/index.d.ts",
18+
"files": [
19+
"/dist"
20+
],
21+
"scripts": {
22+
"build": "yarn build:clean && tsc --project tsconfig.json",
23+
"build:types": "tsc --project tsconfig.json --emitDeclarationOnly --outDir dist/types",
24+
"build:clean": "rimraf ./dist && rimraf tsconfig.tsbuildinfo",
25+
"clean": "rimraf ./dist && rimraf tsconfig.tsbuildinfo",
26+
"lint": "yarn lint:eslint && yarn lint:misc --check",
27+
"lint:eslint": "eslint . --cache --ext js,ts",
28+
"lint:fix": "yarn lint:eslint --fix && yarn lint:misc --write",
29+
"lint:misc": "prettier '**/*.json' '**/*.md' '!CHANGELOG.md' --ignore-path ../../.gitignore",
30+
"typecheck": "tsc --noEmit"
31+
},
32+
"dependencies": {
33+
"@metamask/sdk-types": "workspace:^",
34+
"cross-fetch": "^4.0.0"
35+
},
36+
"devDependencies": {
37+
"@lavamoat/allow-scripts": "^2.3.1",
38+
"@types/analytics-node": "^3.1.13",
39+
"@types/body-parser": "^1.19.4",
40+
"@types/cors": "^2.8.15",
41+
"@types/express": "^4.17.20",
42+
"@types/node": "^20.4.1",
43+
"@typescript-eslint/eslint-plugin": "^4.20.0",
44+
"@typescript-eslint/parser": "^4.20.0",
45+
"eslint": "^7.30.0",
46+
"eslint-config-prettier": "^8.3.0",
47+
"eslint-plugin-prettier": "^3.4.0",
48+
"prettier": "^2.8.8",
49+
"rimraf": "^6.0.1",
50+
"ts-node": "^10.9.1",
51+
"typescript": "^4.3.5"
52+
},
53+
"publishConfig": {
54+
"access": "public",
55+
"registry": "https://registry.npmjs.org/"
56+
},
357
"packageManager": "[email protected]"
458
}

packages/sdk-communication-layer/src/Analytics.ts renamed to packages/analytics-client/src/Analytics.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
import crossFetch from 'cross-fetch';
2-
import { CommunicationLayerPreference } from './types/CommunicationLayerPreference';
3-
import { OriginatorInfo } from './types/OriginatorInfo';
4-
import { TrackingEvents } from './types/TrackingEvent';
5-
import { logger } from './utils/logger';
2+
import { type OriginatorInfo, TrackingEvent } from '@metamask/sdk-types'; // Use types package
63

7-
export interface AnalyticsProps {
4+
// Changed to type as per lint rule
5+
export type AnalyticsProps = {
86
id: string;
9-
event: TrackingEvents;
10-
originatorInfo?: OriginatorInfo;
11-
commLayer?: CommunicationLayerPreference;
7+
event: TrackingEvent; // Reverted back to enum type
8+
originatorInfo?: OriginatorInfo; // Now uses local type
9+
// commLayer?: CommunicationLayerPreference; // Removed prop
1210
sdkVersion?: string;
1311
commLayerVersion?: string;
1412
walletVersion?: string;
1513
params?: Record<string, unknown>;
16-
}
14+
};
1715

1816
// Buffer for storing events
1917
let analyticsBuffer: AnalyticsProps[] = [];
@@ -63,10 +61,6 @@ async function sendBufferedEvents(parameters: AnalyticsProps) {
6361

6462
const body = JSON.stringify(flatParams);
6563

66-
logger.RemoteCommunication(
67-
`[sendBufferedEvents] Sending ${analyticsBuffer.length} analytics events to ${serverUrl}`,
68-
);
69-
7064
try {
7165
const response = await crossFetch(serverUrl, {
7266
method: 'POST',
@@ -77,14 +71,22 @@ async function sendBufferedEvents(parameters: AnalyticsProps) {
7771
body,
7872
});
7973

80-
const text = await response.text();
81-
logger.RemoteCommunication(`[sendBufferedEvents] Response: ${text}`);
74+
// Check if the request was successful before clearing the buffer
75+
if (!response.ok) {
76+
// Log a warning if the request failed
77+
console.warn(
78+
`[Analytics] Failed to send analytics event: ${response.status} ${response.statusText}`,
79+
);
80+
// Optionally, handle the error differently, e.g., retry or log more details
81+
// For now, we proceed to clear the buffer even on failure to prevent buildup
82+
}
8283

8384
// Clear the processed buffer --- operation is atomic and no race condition can happen since we use a separate buffer
8485
// eslint-disable-next-line require-atomic-updates
8586
analyticsBuffer.length = 0;
8687
} catch (error) {
87-
console.warn(`Error sending analytics`, error);
88+
// console.warn is kept as a basic logging mechanism for now
89+
console.warn(`[Analytics] Error sending analytics`, error);
8890
}
8991
}
9092

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export { SendAnalytics } from './Analytics';
2+
export type { AnalyticsProps } from './Analytics';
3+
4+
// Removed re-exports from communication-layer
5+
// export type {
6+
// TrackingEvents,
7+
// OriginatorInfo,
8+
// CommunicationLayerPreference,
9+
// } from '@metamask/sdk-communication-layer';
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"include": [
4+
"src/**/*.ts",
5+
"*.js"
6+
// Include test files if applicable and not covered by the main tsconfig
7+
// "test/**/*.ts"
8+
],
9+
"compilerOptions": {
10+
"noEmit": true // Important: ESLint only needs parsing, not compilation output
11+
}
12+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"extends": "../../tsconfig.base.json",
3+
"compilerOptions": {
4+
"outDir": "./dist",
5+
"rootDir": "./src",
6+
"composite": true
7+
// Override or add any specific compiler options for this package if needed
8+
// e.g., "lib": ["es2020", "dom"]
9+
},
10+
"include": ["src/**/*"],
11+
"exclude": [
12+
"node_modules",
13+
"dist",
14+
"**/*.test.ts" // Exclude tests from main build if separate test command used
15+
],
16+
"references": [
17+
// Add references to other workspace packages this package depends on
18+
{ "path": "../sdk-types" } // Added reference to sdk-types
19+
]
20+
}
Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
1+
const path = require('path');
2+
3+
/**
4+
* @type {import('eslint').Linter.Config}
5+
*/
16
module.exports = {
2-
root: true,
3-
parser: '@typescript-eslint/parser',
4-
plugins: ['@typescript-eslint'],
57
extends: [
6-
'eslint:recommended',
7-
'plugin:@typescript-eslint/recommended',
8-
'prettier',
8+
'@metamask/eslint-config-nodejs', // Use nodejs config for server
9+
'@metamask/eslint-config-typescript',
10+
'../../.eslintrc.js' // Extend the root config
911
],
10-
env: {
11-
node: true,
12-
es6: true,
12+
root: true,
13+
parser: '@typescript-eslint/parser',
14+
parserOptions: {
15+
project: [path.resolve(__dirname, 'tsconfig.eslint.json')], // Point to eslint tsconfig
1316
},
17+
18+
ignorePatterns: [
19+
'.prettierrc.js',
20+
'**/.eslintrc.js',
21+
'**/jest.config.ts',
22+
'**/dist*/',
23+
],
24+
25+
// Remove env and basic rules as they are likely handled by extended configs
26+
// Keep specific overrides if necessary
1427
rules: {
15-
'@typescript-eslint/explicit-module-boundary-types': 'off',
16-
'@typescript-eslint/no-explicit-any': 'warn',
17-
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
18-
},
28+
// Example override (if needed):
29+
// '@typescript-eslint/no-explicit-any': 'warn',
30+
}
1931
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"extends": "./tsconfig.json", // Assuming analytics-server has a tsconfig.json
3+
"include": [
4+
"src/**/*.ts",
5+
"*.js"
6+
// Include test files if applicable
7+
],
8+
"compilerOptions": {
9+
"noEmit": true
10+
}
11+
}

0 commit comments

Comments
 (0)