From 83bc1298c75afe997c599d2449ffa86707da55d8 Mon Sep 17 00:00:00 2001 From: "shunquan.wang" Date: Wed, 7 Aug 2024 15:53:43 +0800 Subject: [PATCH 01/28] feat: perfect isTrackable funtion --- src/adapter/adapter-base.ts | 6 ++- src/core/track-builder.ts | 9 +++- src/helpers/helper-select-adapter.ts | 10 +++- src/types/types-adapter.ts | 9 +++- tests/fixtures/adapter/report-adapter.ts | 4 +- tests/test-track-execute-select.spec.ts | 61 ++++++++++++++++++------ 6 files changed, 79 insertions(+), 20 deletions(-) diff --git a/src/adapter/adapter-base.ts b/src/adapter/adapter-base.ts index f0c9858..4d2bfc7 100644 --- a/src/adapter/adapter-base.ts +++ b/src/adapter/adapter-base.ts @@ -24,7 +24,11 @@ export abstract class BaseAdapter< private afterHook?: AdapterAfterFunction; - abstract isTrackable(): boolean | Promise; + abstract isTrackable( + ctx: Context, + eventType: EventType, + eventData: EventData[EventType] + ): boolean | Promise; protected report( ctx: Context, diff --git a/src/core/track-builder.ts b/src/core/track-builder.ts index fd46ee6..01c8915 100644 --- a/src/core/track-builder.ts +++ b/src/core/track-builder.ts @@ -150,9 +150,16 @@ export class TrackBuilder< async ({ trackCtx }) => { const adapterMap = await executeSelect< Context, + EventType, EventData, AdapterMap - >(trackCtx, innerTrackAdapterMap as AdapterMap, selectRule); + >( + trackCtx, + eventType, + eventData, + innerTrackAdapterMap as AdapterMap, + selectRule + ); return { trackCtx, adapterMap }; }, async ({ trackCtx, adapterMap }) => { diff --git a/src/helpers/helper-select-adapter.ts b/src/helpers/helper-select-adapter.ts index 56edea1..67b6701 100644 --- a/src/helpers/helper-select-adapter.ts +++ b/src/helpers/helper-select-adapter.ts @@ -18,10 +18,13 @@ import { isFunction } from './helper-is-function.js'; */ export const executeSelect = async < Context extends TrackContext, + EventType extends keyof EventData, EventData extends TrackEventDataBase, TrackMap extends TrackAdapterMap, >( ctx: Context, + eventType: EventType, + eventData: EventData[EventType], adapterMap: TrackMap, selectRule: TrackSelectFunction = [] ): Promise> => { @@ -43,7 +46,12 @@ export const executeSelect = async < const lasterAdapterMap: TrackAdapterMap = {}; for (const [adapterName, adapter] of Object.entries(adapterMap)) { - const isTrackable = await executeFunction(adapter.isTrackable); + const isTrackable = await executeFunction( + adapter.isTrackable, + ctx, + eventType, + eventData + ); if (isTrackable && names.includes(adapterName)) { lasterAdapterMap[adapterName] = adapterMap[adapterName]; } diff --git a/src/types/types-adapter.ts b/src/types/types-adapter.ts index aa04d19..4a3e8e5 100644 --- a/src/types/types-adapter.ts +++ b/src/types/types-adapter.ts @@ -81,9 +81,16 @@ export interface TrackAdapter< /** * Checks if the adapter is available. + * @param ctx The track context. + * @param eventType The type of the event. + * @param eventData The data associated with the event. * @returns A boolean indicating if the adapter is available. */ - isTrackable(): boolean | Promise; + isTrackable( + ctx: Context, + eventType: EventType, + eventData: EventData[EventType] + ): boolean | Promise; /** * Tracks an event. diff --git a/tests/fixtures/adapter/report-adapter.ts b/tests/fixtures/adapter/report-adapter.ts index ed08c65..c9bffa6 100644 --- a/tests/fixtures/adapter/report-adapter.ts +++ b/tests/fixtures/adapter/report-adapter.ts @@ -10,10 +10,10 @@ export class ReportAdapter extends BaseAdapter< EventDataOption, AdapterOptions, EventDataOption> > { - isTrackable(): boolean | Promise { + + isTrackable(ctx: TrackContext, eventType: EventType, eventData: EventDataOption[EventType]): boolean | Promise { return true; } - report( ctx: TrackContext, reportData: AdapterReportData, diff --git a/tests/test-track-execute-select.spec.ts b/tests/test-track-execute-select.spec.ts index 454a77f..e92a5b6 100644 --- a/tests/test-track-execute-select.spec.ts +++ b/tests/test-track-execute-select.spec.ts @@ -23,7 +23,13 @@ describe('test-track-execute-select.spec', () => { logAdapter: adapter, businessAdapter: adapter, }; - const lastAdapterMap = await executeSelect(ctx, adapterMap, undefined); + const lastAdapterMap = await executeSelect( + ctx, + 'addCart', + {}, + adapterMap, + undefined + ); expect(Object.keys(lastAdapterMap).length).toBe(5); expect(lastAdapterMap).toMatchObject({ @@ -47,6 +53,8 @@ describe('test-track-execute-select.spec', () => { }; const lastAdapterMap = await executeSelect( ctx, + 'addCart', + {}, adapterMap, 'consoleAdapter' ); @@ -67,7 +75,7 @@ describe('test-track-execute-select.spec', () => { logAdapter: adapter, businessAdapter: adapter, }; - const lastAdapterMap = await executeSelect(ctx, adapterMap, [ + const lastAdapterMap = await executeSelect(ctx, 'addCart', {}, adapterMap, [ 'consoleAdapter', 'analyzerAdapter', 'reportAdapter', @@ -92,6 +100,8 @@ describe('test-track-execute-select.spec', () => { }; const lastAdapterMap = await executeSelect( ctx, + 'addCart', + {}, adapterMap, () => 'consoleAdapter' ); @@ -112,11 +122,13 @@ describe('test-track-execute-select.spec', () => { logAdapter: adapter, businessAdapter: adapter, }; - const lastAdapterMap = await executeSelect(ctx, adapterMap, () => [ - 'consoleAdapter', - 'analyzerAdapter', - 'reportAdapter', - ]); + const lastAdapterMap = await executeSelect( + ctx, + 'addCart', + {}, + adapterMap, + () => ['consoleAdapter', 'analyzerAdapter', 'reportAdapter'] + ); expect(Object.keys(lastAdapterMap).length).toBe(3); expect(lastAdapterMap).toMatchObject({ @@ -136,8 +148,12 @@ describe('test-track-execute-select.spec', () => { logAdapter: adapter, businessAdapter: adapter, }; - const lastAdapterMap = await executeSelect(ctx, adapterMap, () => - Promise.resolve('analyzerAdapter') + const lastAdapterMap = await executeSelect( + ctx, + 'addCart', + {}, + adapterMap, + () => Promise.resolve('analyzerAdapter') ); expect(Object.keys(lastAdapterMap).length).toBe(1); @@ -156,8 +172,13 @@ describe('test-track-execute-select.spec', () => { logAdapter: adapter, businessAdapter: adapter, }; - const lastAdapterMap = await executeSelect(ctx, adapterMap, () => - Promise.resolve(['businessAdapter', 'analyzerAdapter', 'logAdapter']) + const lastAdapterMap = await executeSelect( + ctx, + 'addCart', + {}, + adapterMap, + () => + Promise.resolve(['businessAdapter', 'analyzerAdapter', 'logAdapter']) ); expect(Object.keys(lastAdapterMap).length).toBe(3); @@ -188,7 +209,13 @@ describe('test-track-execute-select.spec', () => { logAdapter: adapter4, businessAdapter: adapter5, }; - let lastAdapterMap = await executeSelect(ctx, adapterMap, undefined); + let lastAdapterMap = await executeSelect( + ctx, + 'addCart', + {}, + adapterMap, + undefined + ); expect(Object.keys(lastAdapterMap).length).toBe(5); expect(lastAdapterMap).toMatchObject({ @@ -212,7 +239,13 @@ describe('test-track-execute-select.spec', () => { logAdapter: adapter4, businessAdapter: adapter5, }; - lastAdapterMap = await executeSelect(ctx, adapterMap, undefined); + lastAdapterMap = await executeSelect( + ctx, + 'addCart', + {}, + adapterMap, + undefined + ); expect(Object.keys(lastAdapterMap).length).toBe(1); expect(lastAdapterMap).toMatchObject({ consoleAdapter: adapter1, @@ -231,7 +264,7 @@ describe('test-track-execute-select.spec', () => { logAdapter: adapter4, businessAdapter: adapter5, }; - lastAdapterMap = await executeSelect(ctx, adapterMap, () => { + lastAdapterMap = await executeSelect(ctx, 'addCart', {}, adapterMap, () => { return Promise.resolve(['reportAdapter']); }); expect(Object.keys(lastAdapterMap).length).toBe(1); From c8c602f8c02d551e64fd57ac83ca655462e13d10 Mon Sep 17 00:00:00 2001 From: "shunquan.wang" Date: Wed, 7 Aug 2024 21:24:13 +0800 Subject: [PATCH 02/28] =?UTF-8?q?feat:=20isTrackable=20add=20ctx=E3=80=81e?= =?UTF-8?q?ventType=E3=80=81eventData?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test-adapter.spec.ts | 10 ++++++ tests/test-deep-merge.spec.ts | 35 ++++++++++++++++++++ tests/test-track-parallel-pipeline.spec.ts | 37 +++++++++++++++++++++- vitest.config.ts | 6 ++++ 4 files changed, 87 insertions(+), 1 deletion(-) diff --git a/tests/test-adapter.spec.ts b/tests/test-adapter.spec.ts index 8695edc..b9383c8 100644 --- a/tests/test-adapter.spec.ts +++ b/tests/test-adapter.spec.ts @@ -33,6 +33,16 @@ describe('test-adapter.spec', () => { }, }; + it('test adapter is undefined', async () => { + expect(() => + createAdapterBuilder< + TrackContext, + EventDataOption, + AdapterOptions, EventDataOption> + >(undefined as unknown as ReportAdapter) + ).toThrowError('Adapter is required'); + }); + it('test adapter hook', async () => { const reportAdapter = new ReportAdapter(); diff --git a/tests/test-deep-merge.spec.ts b/tests/test-deep-merge.spec.ts index 9fcebcb..c883dbd 100644 --- a/tests/test-deep-merge.spec.ts +++ b/tests/test-deep-merge.spec.ts @@ -1,6 +1,41 @@ import { deepMerge } from '../src/helpers/helper-deep-merge.js'; +import { isObject } from '../src/index.js'; describe('test-deep-merge.spec', () => { + it('source is undefined', () => { + const nestedObject = { b: 2, y: 2 }; + const input: any = { + a: nestedObject, + x: 1, + }; + + const result = deepMerge(input, undefined as any); + expect(result).toBe(input); + }); + + it('target key is not object', () => { + const nestedObject = { + b: 2, + y: 2, + x: { + xxx: 1, + }, + }; + const input: any = { + a: nestedObject, + x: ['a', 'b'], + }; + + const result = deepMerge(input, nestedObject as any); + + expect(result).toMatchObject({ + a: { b: 2, y: 2, x: { xxx: 1 } }, + x: { xxx: 1 }, + b: 2, + y: 2, + }); + }); + it('creates a new object reference', () => { const nestedObject = { b: 2, y: 2 }; const input: any = { diff --git a/tests/test-track-parallel-pipeline.spec.ts b/tests/test-track-parallel-pipeline.spec.ts index 16418dc..bd76ba1 100644 --- a/tests/test-track-parallel-pipeline.spec.ts +++ b/tests/test-track-parallel-pipeline.spec.ts @@ -41,10 +41,20 @@ describe('test-track-pipeline.spec', () => { consoleAdapter: consoleAdapter, }; + const createData: TrackData = { + bizMode: 'test', + env: 'prod', + platform: 'android', + ip: '0.0.0.0', + userId: 'test', + }; + const trackBuilder = createTrackBuilder< TrackContext, EventDataOption - >(); + >({ + createData, + }); const trackBuilderFactory = trackBuilder.init(() => adapterMap); @@ -54,6 +64,10 @@ describe('test-track-pipeline.spec', () => { await trackBuilderFactory .select('analyzerAdapter') .track('addCart', eventData.addCart); + // analyzerAdapter + expect(analyzerReportFun.mock.lastCall?.[0]?.data).toMatchObject( + createData + ); expect(analyzerReportCallback.mock.results[0].value).toBe( 'analyzerAdapter' ); @@ -61,12 +75,24 @@ describe('test-track-pipeline.spec', () => { setTimeout(async () => { await trackBuilderFactory.select().track('addCart', eventData.addCart); + // reportAdapter + expect(reportReportFun.mock.lastCall?.[0]?.data).toMatchObject( + createData + ); expect(reportReportCallback.mock.results[0].value).toBe( 'reportAdapter' ); + // analyzerAdapter + expect(analyzerReportFun.mock.lastCall?.[0]?.data).toMatchObject( + createData + ); expect(analyzerReportCallback.mock.results[0].value).toBe( 'analyzerAdapter' ); + // consoleAdapter + expect(consoleReportFun.mock.lastCall?.[0]?.data).toMatchObject( + createData + ); expect(consoleReportCallback.mock.results[0].value).toBe( 'consoleAdapter' ); @@ -78,9 +104,18 @@ describe('test-track-pipeline.spec', () => { return ['consoleAdapter', 'analyzerAdapter']; }) .track('addCart', eventData.addCart); + + // analyzerAdapter + expect(analyzerReportFun.mock.lastCall?.[0]?.data).toMatchObject( + createData + ); expect(analyzerReportCallback.mock.results[0].value).toBe( 'analyzerAdapter' ); + // consoleAdapter + expect(consoleReportFun.mock.lastCall?.[0]?.data).toMatchObject( + createData + ); expect(consoleReportCallback.mock.results[0].value).toBe( 'consoleAdapter' ); diff --git a/vitest.config.ts b/vitest.config.ts index 2ae0a72..0267552 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -9,5 +9,11 @@ export default defineConfig({ '@/': new URL('./src/', import.meta.url).pathname, }, include: ['**/?(*.){test,spec}.?(c|m)[jt]s?(x)'], + coverage: { + provider: 'istanbul', + reporter: ['html'], + include: ['src/**'], + enabled: true, + }, }, }); From de5701d1cba16dab7b41e3efa724fb97db193ca6 Mon Sep 17 00:00:00 2001 From: "shunquan.wang" Date: Thu, 8 Aug 2024 21:46:00 +0800 Subject: [PATCH 03/28] docs: perfect readme --- README.md | 210 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 140 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index 0d2e6c4..ca509a4 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,17 @@ A typed, smart, scalable , powerful data collection engine written in typescript -## Usage +## Install -### Create TrackBuilder +```ts +// npm +npm i @hyperse/track -Create a builder to load the track +// yarn +yarn add @hyperse/track +``` + +## Usage ```ts export type Context = { @@ -46,87 +52,151 @@ export type EventData = { }; }; -const trackBuilder = await createTrackBuilder({ - createCtx() { - // Used to build a global context - return Promise.resolve(context); - }, - eventData: { - // Generic EventData-type data is deeply merged during the transform phase - }, - // The formatStrategy for logger - formatStrategy: formatStrategy, -}); -``` - -### Create Adapter - -Create a adapter by createAdapterBuilder function - -```ts -const adapterBuilder = await createAdapterBuilder(); +export type AdapterOptions = { + setup?: ( + ctx: Context, + eventData: EventData[keyof EventData] + ) => Promise<{ + name: 'setup' | 'setup1' | 'setup2'; + timeStamp: number; + }>; +}; -const adapter = await adapterBuilder - .init(() => { - // Initialization adapter - }) - .before((ctx) => { - // Execute before the adapter track function - }) - .isTrackable(() => { - // Determine whether the adapter is trackable +// custom report adapter +export class ReportAdapter extends BaseAdapter< + TrackContext, + EventData, + AdapterOptions, EventData> +> { + isTrackable( + ctx: TrackContext, + eventType: EventType, + eventData: EventData[EventType] + ): boolean | Promise { return true; + } + report( + ctx: TrackContext, + reportData: AdapterReportData, + setupData?: + | { + name: 'setup' | 'setup1' | 'setup2'; + timeStamp: number; + } + | undefined + ): void | Promise {} +} + +const reportAdapter = new ReportAdapter(); + +// create adapter builder +const adapterBuilder = createAdapterBuilder< + TrackContext, + EventData, + AdapterOptions, EventData> +>(reportAdapter); + +// mount adapter hook +adapterBuilder + .setup((ctx, eventData) => { + return Promise.resolve({ + name: 'setup' as const, + timeStamp: new Date().getTime(), + newField: 'newField', + }); }) - .transform((ctx, eventType, eventData) => { - // Transform the eventData - return eventData; + .before(async (ctx, eventType, eventData) => { + console.log('before'); }) - .after((ctx) => { - // Execute after the adapter track function + .transform('addCart', (ctx, eventType, eventData) => { + return { + ...eventData, + pay: { + payId: 'p123', + payName: 'Sample Pay', + payType: 'credit', + }, + timeStamp: '2024-09-01T00:00:00Z', + }; + }) + .after(async (ctx, eventType, eventData) => { + console.log('after', eventData); }) - // Return a adapter instance .build(); + +// create track builder +const trackBuilder = createTrackBuilder< + TrackContext, + EventDataOption +>(); + +// mount track hook +await trackBuilder + .init({ reportAdapter: reportAdapter }) + .before(async (ctx) => {}) + .after(async (ctx) => {}) + .select(() => ['reportAdapter']) + .track('addCart', eventData.addCart); ``` -> The createAdapterBuilder function can accept an optional parameter (TrackAdapter) to handle eventdata escalation logic. By default, the ReportAdapter provided by Track is used +## Options -### Report data through track +### ReportAdapter -- Load the adapter in track +Adapter used to process event data reporting -- Event Data is reported through the track method provided by track +#### `isTrackable` -```ts -await trackBuilder - .before((ctx) => { - // Execute before the track function - }) - .after((ctx) => { - // Execute after the track function - }) - .transform((ctx, eventData) => { - // Global Transform the eventData - return eventData; - }) - .useAdapter(() => { - // Load all adapters - return { - reportData: adapter, - }; - }) - // Filter the adapter used to process eventData - .select(['reportData']) - // EventType: previewGoods - // EventData: eventData - .track('previewGoods', eventData); -``` +Checks if the adapter is available. + +#### `report` + +Data report + +### AdapterBuilder + +A builder for track adapter. Provides the ability to load adpater corresponding hooks + +#### `setup` + +The adapter hook Performs data consolidation against the rules defined by AdapterOptions. Passes the returned results to report. Executes before the report function is called + +#### `before` + +The adapter hook function is executed before tracking an event. + +#### `transform` + +The adapter hook function that converts EventData corresponding to different EventType + +#### `after` + +The adapter hook function is triggered after the report is executed + +#### `build` + +Return adapter instance + +### TrackBuilder + +A builder for track. Provides the ability to load track corresponding hooks + +#### `init` + +Track builder initialization, which loads the adapter into the track + +#### `before` + +A function that is executed before tracking + +#### `after` -## Errors +A function that is executed after a track event -## Development +#### `select` -yarn install +Selects track adapter from a given context, event data, and adapter map. -## Testing +#### `track` -yarn test +Event reporting activation function From 5d8616b294cafa27de197f3bd530a9a1c7b2189a Mon Sep 17 00:00:00 2001 From: "shunquan.wang" Date: Mon, 12 Aug 2024 21:16:48 +0800 Subject: [PATCH 04/28] feat: update docs --- .github/workflows/coverage-pr.yml | 34 +++ .husky/pre-commit | 3 + package.json | 1 + src/core/track-builder.ts | 9 +- src/helpers/helper-adapter-track.ts | 14 +- src/helpers/helper-select-adapter.ts | 13 +- tests/test-adapter.spec.ts | 8 +- tests/test-track-error.spec.ts | 10 +- tests/test-track-execute-select.spec.ts | 147 +++++----- tests/test-track-logger.spec.ts | 8 +- tests/test-track-parallel-pipeline.spec.ts | 8 +- tests/test-track-pipeline.spec.ts | 8 +- .../adapter/default-adapter-builder.ts | 5 +- .../adapter/default-adapter.ts | 19 +- .../adapter/default-tack-instance.ts | 2 +- .../adapter/report-adapter.ts | 9 +- .../console-logger.ts | 0 .../types/type-adapter-options.ts | 0 .../types/type-event.ts | 0 .../types/type-track-data.ts | 0 vitest.config.ts | 6 +- website/docs/adapters/google-adapter.md | 1 + website/docs/api-reference.md | 138 --------- website/docs/api/adapter-builder.md | 111 ++++++++ website/docs/api/base-adapter.md | 93 ++++++ website/docs/api/track-builder.md | 49 ++++ website/docs/changelog.md | 7 + website/docs/color-validation.md | 22 -- website/docs/community/contributing.md | 5 + website/docs/css.md | 41 --- website/docs/faq.md | 1 + website/docs/inheritance.md | 15 - website/docs/intro.md | 117 +++++++- website/docs/playground.md | 5 - website/docs/react-hook-form.md | 48 ---- website/docs/typescript.md | 33 --- website/sidebars.ts | 64 ++++- .../src/components/Amimate/DynamicCoding.tsx | 34 +++ website/src/pages/index.module.css | 4 + website/src/pages/index.tsx | 5 + yarn.lock | 264 +++++++++++++++++- 41 files changed, 911 insertions(+), 450 deletions(-) create mode 100644 .github/workflows/coverage-pr.yml rename tests/{fixtures => test-utils}/adapter/default-adapter-builder.ts (86%) rename tests/{fixtures => test-utils}/adapter/default-adapter.ts (51%) rename tests/{fixtures => test-utils}/adapter/default-tack-instance.ts (95%) rename tests/{fixtures => test-utils}/adapter/report-adapter.ts (76%) rename tests/{fixtures => test-utils}/console-logger.ts (100%) rename tests/{fixtures => test-utils}/types/type-adapter-options.ts (100%) rename tests/{fixtures => test-utils}/types/type-event.ts (100%) rename tests/{fixtures => test-utils}/types/type-track-data.ts (100%) create mode 100644 website/docs/adapters/google-adapter.md delete mode 100644 website/docs/api-reference.md create mode 100644 website/docs/api/adapter-builder.md create mode 100644 website/docs/api/base-adapter.md create mode 100644 website/docs/api/track-builder.md create mode 100644 website/docs/changelog.md delete mode 100644 website/docs/color-validation.md create mode 100644 website/docs/community/contributing.md delete mode 100644 website/docs/css.md create mode 100644 website/docs/faq.md delete mode 100644 website/docs/inheritance.md delete mode 100644 website/docs/playground.md delete mode 100644 website/docs/react-hook-form.md delete mode 100644 website/docs/typescript.md create mode 100644 website/src/components/Amimate/DynamicCoding.tsx diff --git a/.github/workflows/coverage-pr.yml b/.github/workflows/coverage-pr.yml new file mode 100644 index 0000000..580e999 --- /dev/null +++ b/.github/workflows/coverage-pr.yml @@ -0,0 +1,34 @@ +name: "PR Build and Test" +on: + pull_request: + +jobs: + build-and-test: + permissions: + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: "Install Node" + uses: actions/setup-node@v4 + with: + node-version: "20.x" + - name: 📥 Install Dependencies + run: yarn --frozen-lockfile + + - name: "Build" + run: yarn build + + - name: run coverage + run: yarn test:coverage + + # Remove node_modules to see if this action runs entirely compiled + - name: "Remove Node Modules" + run: rm -rf node_modules + + - name: "PR Test Reports" + uses: hyperse-io/vitest-coverage-reporter@v1.0.13 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + include-all-projects: "false" + name: "PR Test Reports" \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit index 9eaba41..4aec334 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,5 +1,8 @@ #!/bin/sh . "$(dirname -- "$0")/_/husky.sh" +yarn run test:coverage +yarn generate-coverage-report --type readme +git add . yarn lint-staged-files --debug diff --git a/package.json b/package.json index e220284..7bed498 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "@commitlint/config-conventional": "19.2.2", "@hyperse/eslint-config-hyperse": "^1.0.12", "@hyperse/exec-program": "^1.0.10", + "@hyperse/vitest-coverage-reporter": "^1.0.13", "@types/lodash": "^4", "@types/node": "^22.1.0", "@types/react": "^18.3.3", diff --git a/src/core/track-builder.ts b/src/core/track-builder.ts index 01c8915..fd46ee6 100644 --- a/src/core/track-builder.ts +++ b/src/core/track-builder.ts @@ -150,16 +150,9 @@ export class TrackBuilder< async ({ trackCtx }) => { const adapterMap = await executeSelect< Context, - EventType, EventData, AdapterMap - >( - trackCtx, - eventType, - eventData, - innerTrackAdapterMap as AdapterMap, - selectRule - ); + >(trackCtx, innerTrackAdapterMap as AdapterMap, selectRule); return { trackCtx, adapterMap }; }, async ({ trackCtx, adapterMap }) => { diff --git a/src/helpers/helper-adapter-track.ts b/src/helpers/helper-adapter-track.ts index ab707f9..dd14f22 100644 --- a/src/helpers/helper-adapter-track.ts +++ b/src/helpers/helper-adapter-track.ts @@ -1,5 +1,6 @@ import { TrackContext } from '../types/types-create.js'; import { TrackAdapterMap, TrackEventDataBase } from '../types/types-track.js'; +import { executeFunction } from './helper-execute.js'; /** * Executes the track function of each adapter in the adapterMap for the given eventType and result. @@ -22,7 +23,18 @@ export const executeAdapterTrack = async < eventType: EventType, result: EventData[EventType] ): Promise => { - for (const adapter of Object.values(adapterMap)) { + for (const [adapterName, adapter] of Object.entries(adapterMap)) { + const isTrackable = await executeFunction( + adapter.isTrackable, + ctx, + eventType, + result + ); + + if (!isTrackable) { + ctx.logger?.warn(`Adapter is not trackable: ${adapterName}`); + continue; + } await adapter.track(ctx, eventType, result); } return result; diff --git a/src/helpers/helper-select-adapter.ts b/src/helpers/helper-select-adapter.ts index 67b6701..71ad7ec 100644 --- a/src/helpers/helper-select-adapter.ts +++ b/src/helpers/helper-select-adapter.ts @@ -18,13 +18,10 @@ import { isFunction } from './helper-is-function.js'; */ export const executeSelect = async < Context extends TrackContext, - EventType extends keyof EventData, EventData extends TrackEventDataBase, TrackMap extends TrackAdapterMap, >( ctx: Context, - eventType: EventType, - eventData: EventData[EventType], adapterMap: TrackMap, selectRule: TrackSelectFunction = [] ): Promise> => { @@ -46,14 +43,8 @@ export const executeSelect = async < const lasterAdapterMap: TrackAdapterMap = {}; for (const [adapterName, adapter] of Object.entries(adapterMap)) { - const isTrackable = await executeFunction( - adapter.isTrackable, - ctx, - eventType, - eventData - ); - if (isTrackable && names.includes(adapterName)) { - lasterAdapterMap[adapterName] = adapterMap[adapterName]; + if (names.includes(adapterName)) { + lasterAdapterMap[adapterName] = adapter; } } return lasterAdapterMap; diff --git a/tests/test-adapter.spec.ts b/tests/test-adapter.spec.ts index b9383c8..f1622d2 100644 --- a/tests/test-adapter.spec.ts +++ b/tests/test-adapter.spec.ts @@ -1,9 +1,9 @@ import { createAdapterBuilder } from '../src/adapter/create-adapter-builder.js'; import { TrackContext } from '../src/types/types-create.js'; -import { ReportAdapter } from './fixtures/adapter/report-adapter.js'; -import { AdapterOptions } from './fixtures/types/type-adapter-options.js'; -import { EventDataOption } from './fixtures/types/type-event.js'; -import { TrackData } from './fixtures/types/type-track-data.js'; +import { ReportAdapter } from './test-utils/adapter/report-adapter.js'; +import { AdapterOptions } from './test-utils/types/type-adapter-options.js'; +import { EventDataOption } from './test-utils/types/type-event.js'; +import { TrackData } from './test-utils/types/type-track-data.js'; describe('test-adapter.spec', () => { const trackData: TrackData = { diff --git a/tests/test-track-error.spec.ts b/tests/test-track-error.spec.ts index 792466c..be89b96 100644 --- a/tests/test-track-error.spec.ts +++ b/tests/test-track-error.spec.ts @@ -1,11 +1,11 @@ import { createTrackBuilder } from '../src/core/create-track-builder.js'; import { TrackAdapter } from '../src/types/types-adapter.js'; import { TrackContext } from '../src/types/types-create.js'; -import { defaultAdapterBuilder } from './fixtures/adapter/default-adapter-builder.js'; -import { ConsoleLogger } from './fixtures/console-logger.js'; -import { AdapterOptions } from './fixtures/types/type-adapter-options.js'; -import { EventDataOption } from './fixtures/types/type-event.js'; -import { TrackData } from './fixtures/types/type-track-data.js'; +import { defaultAdapterBuilder } from './test-utils/adapter/default-adapter-builder.js'; +import { ConsoleLogger } from './test-utils/console-logger.js'; +import { AdapterOptions } from './test-utils/types/type-adapter-options.js'; +import { EventDataOption } from './test-utils/types/type-event.js'; +import { TrackData } from './test-utils/types/type-track-data.js'; describe('test-track-error.spec', () => { const trackData: TrackData = { diff --git a/tests/test-track-execute-select.spec.ts b/tests/test-track-execute-select.spec.ts index e92a5b6..beefe55 100644 --- a/tests/test-track-execute-select.spec.ts +++ b/tests/test-track-execute-select.spec.ts @@ -1,6 +1,10 @@ import { executeSelect } from '../src/helpers/helper-select-adapter.js'; -import { defaultAdapter } from './fixtures/adapter/default-adapter.js'; -import { defaultTackInstance } from './fixtures/adapter/default-tack-instance.js'; +import { createTrackBuilder } from '../src/index.js'; +import { TrackContext } from '../src/types/types-create.js'; +import { defaultAdapter } from './test-utils/adapter/default-adapter.js'; +import { ConsoleLogger } from './test-utils/console-logger.js'; +import { EventDataOption } from './test-utils/types/type-event.js'; +import { TrackData } from './test-utils/types/type-track-data.js'; describe('test-track-execute-select.spec', () => { const ctx = { @@ -13,6 +17,25 @@ describe('test-track-execute-select.spec', () => { }, }; + const eventData: EventDataOption = { + registry: { + userName: 'testUser', + mobile: '1234567890', + pwd: 'password123', + email: 'testuser@example.com', + }, + previewGoods: { + goodsId: 'g123', + goodsName: 'Sample Goods', + }, + addCart: { + price: 99.99, + goodsId: 'g123', + goodsName: 'Sample Goods', + count: 2, + }, + }; + it('executeSelect names is empty', async () => { const adapter = defaultAdapter(); @@ -23,13 +46,7 @@ describe('test-track-execute-select.spec', () => { logAdapter: adapter, businessAdapter: adapter, }; - const lastAdapterMap = await executeSelect( - ctx, - 'addCart', - {}, - adapterMap, - undefined - ); + const lastAdapterMap = await executeSelect(ctx, adapterMap, undefined); expect(Object.keys(lastAdapterMap).length).toBe(5); expect(lastAdapterMap).toMatchObject({ @@ -53,8 +70,6 @@ describe('test-track-execute-select.spec', () => { }; const lastAdapterMap = await executeSelect( ctx, - 'addCart', - {}, adapterMap, 'consoleAdapter' ); @@ -75,7 +90,7 @@ describe('test-track-execute-select.spec', () => { logAdapter: adapter, businessAdapter: adapter, }; - const lastAdapterMap = await executeSelect(ctx, 'addCart', {}, adapterMap, [ + const lastAdapterMap = await executeSelect(ctx, adapterMap, [ 'consoleAdapter', 'analyzerAdapter', 'reportAdapter', @@ -100,8 +115,6 @@ describe('test-track-execute-select.spec', () => { }; const lastAdapterMap = await executeSelect( ctx, - 'addCart', - {}, adapterMap, () => 'consoleAdapter' ); @@ -122,13 +135,11 @@ describe('test-track-execute-select.spec', () => { logAdapter: adapter, businessAdapter: adapter, }; - const lastAdapterMap = await executeSelect( - ctx, - 'addCart', - {}, - adapterMap, - () => ['consoleAdapter', 'analyzerAdapter', 'reportAdapter'] - ); + const lastAdapterMap = await executeSelect(ctx, adapterMap, () => [ + 'consoleAdapter', + 'analyzerAdapter', + 'reportAdapter', + ]); expect(Object.keys(lastAdapterMap).length).toBe(3); expect(lastAdapterMap).toMatchObject({ @@ -148,12 +159,8 @@ describe('test-track-execute-select.spec', () => { logAdapter: adapter, businessAdapter: adapter, }; - const lastAdapterMap = await executeSelect( - ctx, - 'addCart', - {}, - adapterMap, - () => Promise.resolve('analyzerAdapter') + const lastAdapterMap = await executeSelect(ctx, adapterMap, () => + Promise.resolve('analyzerAdapter') ); expect(Object.keys(lastAdapterMap).length).toBe(1); @@ -172,13 +179,8 @@ describe('test-track-execute-select.spec', () => { logAdapter: adapter, businessAdapter: adapter, }; - const lastAdapterMap = await executeSelect( - ctx, - 'addCart', - {}, - adapterMap, - () => - Promise.resolve(['businessAdapter', 'analyzerAdapter', 'logAdapter']) + const lastAdapterMap = await executeSelect(ctx, adapterMap, () => + Promise.resolve(['businessAdapter', 'analyzerAdapter', 'logAdapter']) ); expect(Object.keys(lastAdapterMap).length).toBe(3); @@ -190,12 +192,25 @@ describe('test-track-execute-select.spec', () => { }); it('executeSelect isTrackable', async () => { + const logger = new ConsoleLogger(); + const print = vi.fn((message: any, context?: string) => { + return message; + }); + vi.spyOn(logger, 'warn').mockImplementation(print); + const adapter1 = defaultAdapter(); const adapter2 = defaultAdapter(); const adapter3 = defaultAdapter(); const adapter4 = defaultAdapter(); const adapter5 = defaultAdapter(); + const trackBuilder = createTrackBuilder< + TrackContext, + EventDataOption + >({ + logger: logger, + }); + vi.spyOn(adapter1, 'isTrackable').mockReturnValue(true); vi.spyOn(adapter2, 'isTrackable').mockReturnValue(true); vi.spyOn(adapter3, 'isTrackable').mockReturnValue(true); @@ -209,22 +224,10 @@ describe('test-track-execute-select.spec', () => { logAdapter: adapter4, businessAdapter: adapter5, }; - let lastAdapterMap = await executeSelect( - ctx, - 'addCart', - {}, - adapterMap, - undefined - ); - expect(Object.keys(lastAdapterMap).length).toBe(5); - expect(lastAdapterMap).toMatchObject({ - consoleAdapter: adapter1, - analyzerAdapter: adapter2, - reportAdapter: adapter3, - logAdapter: adapter4, - businessAdapter: adapter5, - }); + await trackBuilder.init(adapterMap).track('addCart', eventData.addCart); + expect(print.mock.calls).toHaveLength(0); + expect(print.mock.results).toHaveLength(0); vi.spyOn(adapter1, 'isTrackable').mockReturnValue(true); vi.spyOn(adapter2, 'isTrackable').mockReturnValue(false); @@ -239,37 +242,21 @@ describe('test-track-execute-select.spec', () => { logAdapter: adapter4, businessAdapter: adapter5, }; - lastAdapterMap = await executeSelect( - ctx, - 'addCart', - {}, - adapterMap, - undefined - ); - expect(Object.keys(lastAdapterMap).length).toBe(1); - expect(lastAdapterMap).toMatchObject({ - consoleAdapter: adapter1, - }); - - vi.spyOn(adapter1, 'isTrackable').mockReturnValue(true); - vi.spyOn(adapter2, 'isTrackable').mockReturnValue(true); - vi.spyOn(adapter3, 'isTrackable').mockReturnValue(true); - vi.spyOn(adapter4, 'isTrackable').mockReturnValue(false); - vi.spyOn(adapter5, 'isTrackable').mockReturnValue(false); + await trackBuilder.init(adapterMap).track('addCart', eventData.addCart); - adapterMap = { - consoleAdapter: adapter1, - analyzerAdapter: adapter2, - reportAdapter: adapter3, - logAdapter: adapter4, - businessAdapter: adapter5, - }; - lastAdapterMap = await executeSelect(ctx, 'addCart', {}, adapterMap, () => { - return Promise.resolve(['reportAdapter']); - }); - expect(Object.keys(lastAdapterMap).length).toBe(1); - expect(lastAdapterMap).toMatchObject({ - reportAdapter: adapter3, - }); + expect(print.mock.calls).toHaveLength(4); + expect(print.mock.results).toHaveLength(4); + expect(print.mock.results?.[0].value).toBe( + 'Adapter is not trackable: analyzerAdapter' + ); + expect(print.mock.results?.[1].value).toBe( + 'Adapter is not trackable: reportAdapter' + ); + expect(print.mock.results?.[2].value).toBe( + 'Adapter is not trackable: logAdapter' + ); + expect(print.mock.results?.[3].value).toBe( + 'Adapter is not trackable: businessAdapter' + ); }); }); diff --git a/tests/test-track-logger.spec.ts b/tests/test-track-logger.spec.ts index f4f4eb2..9c62815 100644 --- a/tests/test-track-logger.spec.ts +++ b/tests/test-track-logger.spec.ts @@ -5,10 +5,10 @@ import { TrackAdapterOptions, TrackContext, } from '../src/types/types-create.js'; -import { ReportAdapter } from './fixtures/adapter/report-adapter.js'; -import { ConsoleLogger } from './fixtures/console-logger.js'; -import { EventDataOption } from './fixtures/types/type-event.js'; -import { TrackData } from './fixtures/types/type-track-data.js'; +import { ReportAdapter } from './test-utils/adapter/report-adapter.js'; +import { ConsoleLogger } from './test-utils/console-logger.js'; +import { EventDataOption } from './test-utils/types/type-event.js'; +import { TrackData } from './test-utils/types/type-track-data.js'; describe('test-track-logger.spec', () => { const trackData: TrackData = { diff --git a/tests/test-track-parallel-pipeline.spec.ts b/tests/test-track-parallel-pipeline.spec.ts index bd76ba1..0f83ff4 100644 --- a/tests/test-track-parallel-pipeline.spec.ts +++ b/tests/test-track-parallel-pipeline.spec.ts @@ -3,10 +3,10 @@ import { createAdapterBuilder } from '../src/adapter/create-adapter-builder.js'; import { createTrackBuilder } from '../src/core/create-track-builder.js'; import { TrackAdapter } from '../src/types/types-adapter.js'; import { TrackContext } from '../src/types/types-create.js'; -import { ReportAdapter } from './fixtures/adapter/report-adapter.js'; -import { AdapterOptions } from './fixtures/types/type-adapter-options.js'; -import { EventDataOption } from './fixtures/types/type-event.js'; -import { TrackData } from './fixtures/types/type-track-data.js'; +import { ReportAdapter } from './test-utils/adapter/report-adapter.js'; +import { AdapterOptions } from './test-utils/types/type-adapter-options.js'; +import { EventDataOption } from './test-utils/types/type-event.js'; +import { TrackData } from './test-utils/types/type-track-data.js'; describe('test-track-pipeline.spec', () => { const eventData: EventDataOption = { diff --git a/tests/test-track-pipeline.spec.ts b/tests/test-track-pipeline.spec.ts index 9ece948..01fb715 100644 --- a/tests/test-track-pipeline.spec.ts +++ b/tests/test-track-pipeline.spec.ts @@ -1,10 +1,10 @@ import { createAdapterBuilder } from '../src/adapter/create-adapter-builder.js'; import { createTrackBuilder } from '../src/core/create-track-builder.js'; import { TrackContext } from '../src/types/types-create.js'; -import { ReportAdapter } from './fixtures/adapter/report-adapter.js'; -import { AdapterOptions } from './fixtures/types/type-adapter-options.js'; -import { EventDataOption } from './fixtures/types/type-event.js'; -import { TrackData } from './fixtures/types/type-track-data.js'; +import { ReportAdapter } from './test-utils/adapter/report-adapter.js'; +import { AdapterOptions } from './test-utils/types/type-adapter-options.js'; +import { EventDataOption } from './test-utils/types/type-event.js'; +import { TrackData } from './test-utils/types/type-track-data.js'; describe('test-track-pipeline.spec', () => { const trackData: TrackData = { diff --git a/tests/fixtures/adapter/default-adapter-builder.ts b/tests/test-utils/adapter/default-adapter-builder.ts similarity index 86% rename from tests/fixtures/adapter/default-adapter-builder.ts rename to tests/test-utils/adapter/default-adapter-builder.ts index 5fc1db9..3cf451f 100644 --- a/tests/fixtures/adapter/default-adapter-builder.ts +++ b/tests/test-utils/adapter/default-adapter-builder.ts @@ -7,13 +7,12 @@ import { EventDataOption } from '../types/type-event.js'; import { TrackData } from '../types/type-track-data.js'; import { ReportAdapter } from './report-adapter.js'; -export const defaultAdapterBuilder = () => { +export const defaultAdapterBuilder = () => { const adapter = new ReportAdapter(); - return createAdapterBuilder< + return createAdapterBuilder< TrackContext, EventDataOption, TrackAdapterOptions, EventDataOption> >(adapter); - }; diff --git a/tests/fixtures/adapter/default-adapter.ts b/tests/test-utils/adapter/default-adapter.ts similarity index 51% rename from tests/fixtures/adapter/default-adapter.ts rename to tests/test-utils/adapter/default-adapter.ts index 3a3f484..a6f03c1 100644 --- a/tests/fixtures/adapter/default-adapter.ts +++ b/tests/test-utils/adapter/default-adapter.ts @@ -7,13 +7,26 @@ import { EventDataOption } from '../types/type-event.js'; import { TrackData } from '../types/type-track-data.js'; import { ReportAdapter } from './report-adapter.js'; -export const defaultAdapter = () => { +export const defaultAdapter = () => { const adapter = new ReportAdapter(); - const adapterBuilder = createAdapterBuilder< + const adapterBuilder = createAdapterBuilder< TrackContext, EventDataOption, TrackAdapterOptions, EventDataOption> >(adapter); - return adapterBuilder.build(); + return adapterBuilder + .transform('addCart', (ctx, eventType, eventData) => { + return eventData; + }) + .transform('previewGoods', (ctx, eventType, eventData) => { + return eventData; + }) + .transform('registry', (ctx, eventType, eventData) => { + return eventData; + }) + .transform('timeStamp', (ctx, eventType, eventData) => { + return eventData; + }) + .build(); }; diff --git a/tests/fixtures/adapter/default-tack-instance.ts b/tests/test-utils/adapter/default-tack-instance.ts similarity index 95% rename from tests/fixtures/adapter/default-tack-instance.ts rename to tests/test-utils/adapter/default-tack-instance.ts index 76ea10f..ad8ca2a 100644 --- a/tests/fixtures/adapter/default-tack-instance.ts +++ b/tests/test-utils/adapter/default-tack-instance.ts @@ -4,7 +4,7 @@ import { ConsoleLogger } from '../console-logger.js'; import { TrackData } from '../types/type-track-data.js'; export const defaultTackInstance = () => { - const configuration = { + const configuration = { logger: new ConsoleLogger(), data: { bizMode: 'test', diff --git a/tests/fixtures/adapter/report-adapter.ts b/tests/test-utils/adapter/report-adapter.ts similarity index 76% rename from tests/fixtures/adapter/report-adapter.ts rename to tests/test-utils/adapter/report-adapter.ts index c9bffa6..25a4887 100644 --- a/tests/fixtures/adapter/report-adapter.ts +++ b/tests/test-utils/adapter/report-adapter.ts @@ -10,8 +10,11 @@ export class ReportAdapter extends BaseAdapter< EventDataOption, AdapterOptions, EventDataOption> > { - - isTrackable(ctx: TrackContext, eventType: EventType, eventData: EventDataOption[EventType]): boolean | Promise { + isTrackable( + ctx: TrackContext, + eventType: EventType, + eventData: EventDataOption[EventType] + ): boolean | Promise { return true; } report( @@ -19,7 +22,7 @@ export class ReportAdapter extends BaseAdapter< reportData: AdapterReportData, setupData?: | { - name: 'setup' | 'setup1' | 'setup2'; + name: 'setup' | 'setup1' | 'setup2'; timeStamp: number; user?: string; } diff --git a/tests/fixtures/console-logger.ts b/tests/test-utils/console-logger.ts similarity index 100% rename from tests/fixtures/console-logger.ts rename to tests/test-utils/console-logger.ts diff --git a/tests/fixtures/types/type-adapter-options.ts b/tests/test-utils/types/type-adapter-options.ts similarity index 100% rename from tests/fixtures/types/type-adapter-options.ts rename to tests/test-utils/types/type-adapter-options.ts diff --git a/tests/fixtures/types/type-event.ts b/tests/test-utils/types/type-event.ts similarity index 100% rename from tests/fixtures/types/type-event.ts rename to tests/test-utils/types/type-event.ts diff --git a/tests/fixtures/types/type-track-data.ts b/tests/test-utils/types/type-track-data.ts similarity index 100% rename from tests/fixtures/types/type-track-data.ts rename to tests/test-utils/types/type-track-data.ts diff --git a/vitest.config.ts b/vitest.config.ts index 0267552..24730b6 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -10,10 +10,10 @@ export default defineConfig({ }, include: ['**/?(*.){test,spec}.?(c|m)[jt]s?(x)'], coverage: { - provider: 'istanbul', - reporter: ['html'], include: ['src/**'], - enabled: true, + provider: 'istanbul', + reporter: ['text', 'json', 'json-summary'], + reportOnFailure: true, }, }, }); diff --git a/website/docs/adapters/google-adapter.md b/website/docs/adapters/google-adapter.md new file mode 100644 index 0000000..c538aec --- /dev/null +++ b/website/docs/adapters/google-adapter.md @@ -0,0 +1 @@ +# GoogleAdapter diff --git a/website/docs/api-reference.md b/website/docs/api-reference.md deleted file mode 100644 index 12c9deb..0000000 --- a/website/docs/api-reference.md +++ /dev/null @@ -1,138 +0,0 @@ ---- -sidebar_position: 3 ---- - -# API Reference - -This article discusses the API and props of **MuiColorInput**. Props are defined within `MuiColorInputProps`. - -## `value` - -- Type: `MuiColorInputValue` -- Required: `true` - -The string parsing is very permissive. It is meant to make typing a color as input as easy as possible. All commas, percentages, parenthesis are optional, and most input allow either 0-1, 0%-100%, or 0-n (where n is either 100, 255, or 360 depending on the value). - -HSL and HSV both require either 0%-100% or 0-1 for the `S`/`L`/`V` properties. The `H` (hue) can have values between 0%-100% or 0-360. - -RGB input requires either 0-255 or 0%-100%. - -Source : https://github.com/scttcper/tinycolor#accepted-string-input - -Here are some examples of string input: - -### Hex, 8-digit (RGBA) Hex - -```tsx - - - - - - -``` - -### RGB, RGBA - -```tsx - - - - -``` - -### HSL, HSLA - -```tsx - - - - -``` - -### HSV, HSVA - -```tsx - - - - -``` - -## `onChange` - -- Default: `undefined` -- Type: `(color: string, colors: MuiColorInputColors) => void` -- Required: `false` - -Gets called once the user updates the color value. - -The callback gives you **2 parameters**: - -1. The new color [value](#value) stringified -2. An object of the color value in different formats stringified (`hex`, `hex8`, `hsl`, `hsv`, `rgb`) - -Example: - -```tsx -const handleChange = (color, colors) => { - /** - color: "#ffffff" - colors: { - hex: "#ffffff", - hex8: "#ffffffff", - hsl: "hsl(0, 0%, 100%)", - hsv: "hsv(0, 0%, 100%)", - rgb: "rgb(255, 255, 255)" - } - **/ -}; - -; -``` - -## `format` - -- Default: `"rgb"` -- Type: `MuiColorInputFormat` -- Required: `false` - -The format to use for the color [value](#value). The first parameter of `onChange` respects this format. - -**Available formats**: `hex`, `hex8`, `hsl`, `hsv` and `rgb`. - -```tsx - - - - - -``` - -## `fallbackValue` - -- Default: `"black"` -- Type: `MuiColorInputValue` -- Required: `false` - -A fallback color [value](#value) in case the user updates the input with an invalid color value. - -```tsx - - - - - -``` - -## `isAlphaHidden` - -- Default: `false` -- Type: `boolean` -- Required: `false` - -Whether to show input controls for a color’s alpha channel. - -```tsx - -``` diff --git a/website/docs/api/adapter-builder.md b/website/docs/api/adapter-builder.md new file mode 100644 index 0000000..db1ec7f --- /dev/null +++ b/website/docs/api/adapter-builder.md @@ -0,0 +1,111 @@ +# AdapterBuilder + +The `AdapterBuilder` class is used to create a new adapter instance. It is a factory class that creates a new adapter instance based on the provided configuration. + +```typescript title="Signature" +export class AdapterBuilder< + Context extends TrackContext, + EventData extends TrackEventDataBase, + AdapterOptions extends TrackAdapterOptions, +> { + constructor( + options: AdapterBuilderOptions + ); +} +``` + +## Hooks + +### `setup` + +`Function` + +Sets up the adapter. + +#### Props + +- **ctx** : `Context` - The track context. + +#### Returns + +- `Promise` - A promise that resolves when the adapter is set up. + +#### Example + +```typescript title="AdapterBuilder.ts" +const adapterBuilder = new AdapterBuilder({ + new ReportAdapter(), +}); + +adapterBuilder.setup(ctx); +``` + +### `build` + +`Function` + +Builds a new adapter instance. + +#### Props + +- **ctx** : `Context` - The track context. + +#### Returns + +- `Adapter` - A new adapter instance. + +#### Example + +```typescript title="AdapterBuilder.ts" +const adapterBuilder = new AdapterBuilder({ + new ReportAdapter(), +}); + +const adapter = adapterBuilder.build(ctx); +``` + +### `before` + +The adapter hook function is executed before tracking an event. + +#### Props + +- **event** : `EventData` - The event data. + +#### Returns + +- `EventData` - The modified event data. + +#### Example + +```typescript title="AdapterBuilder.ts" +const adapterBuilder = new AdapterBuilder({ + new ReportAdapter(), +}); + +adapterBuilder.before(event); +``` + +### `transform` + +The adapter hook function is executed to transform the event data before tracking. + +#### Props + +- **event** : `EventData` - The event data. + +#### Returns + +- `EventData` - The modified event data. + +#### Example + +```typescript title="AdapterBuilder.ts" +const adapterBuilder = new AdapterBuilder({ + new ReportAdapter(), +}); + +adapterBuilder.transform(event); +``` + +### `after` diff --git a/website/docs/api/base-adapter.md b/website/docs/api/base-adapter.md new file mode 100644 index 0000000..440b6cd --- /dev/null +++ b/website/docs/api/base-adapter.md @@ -0,0 +1,93 @@ +# BaseAdapter + +BaseAdapter is an abstract class that serves as the base for implementing track adapters. It provides common functionality and hooks for tracking events. + +```typescript title="Signature" +export interface TrackAdapter< + Context extends TrackContext, + EventData extends TrackEventDataBase, + AdapterOptions extends TrackAdapterOptions, +> { + abstract isTrackable( + ctx: Context, + eventType: EventType, + eventData: EventData[EventType] + ): boolean | Promise; + + protected report( + ctx: Context, + reportData: AdapterReportData, + setupData?: Required['setup'] extends (...args: any) => any + ? Awaited['setup']>> + : undefined + ): void | Promise {} +} +``` + +### `isTrackable` + +`abstract Function` + +Checks if the adapter is available. + +#### Props + +- **ctx** : `Context` - The track context. +- **eventType** : `EventType` - The type of the event. +- **eventData** : `EventData[EventType]` - The data associated with the event. + +#### Returns + +- `boolean | Promise` - A boolean indicating if the adapter is available. + +#### Example + +```typescript title="ReportAdapter.ts" +export class ReportAdapter extends BaseAdapter< + TrackContext, + EventDataOption, + AdapterOptions, EventDataOption> +> { + isTrackable( + ctx: TrackContext, + eventType: EventType, + eventData: EventDataOption[EventType] + ): boolean | Promise { + return eventType === 'addCart'; + } +} +``` + +### `report` + +`protected Function` + +Reports the event to the adapter. + +#### Props + +- **ctx** : `Context` - The track context. +- **reportData** : `AdapterReportData` - The data to report. +- **setupData** : `Required['setup'] extends (...args: any) => any ? Awaited['setup']> : undefined` - The setup data. + +#### Returns + +- `void | Promise` - A void or a promise that resolves to void. + +#### Example + +```typescript title="ReportAdapter.ts" +export class ReportAdapter extends BaseAdapter< + TrackContext, + EventDataOption, + AdapterOptions, EventDataOption> +> { + report( + ctx: TrackContext, + reportData: AdapterReportData, + setupData?: Awaited, EventDataOption>['setup']> + ): void | Promise { + // do something + } +} +``` diff --git a/website/docs/api/track-builder.md b/website/docs/api/track-builder.md new file mode 100644 index 0000000..ffc013b --- /dev/null +++ b/website/docs/api/track-builder.md @@ -0,0 +1,49 @@ +# TrackBuilder + +The `TrackBuilder` class is used to create a track from a list of waypoints. The waypoints are used to create a track that can be used to generate a path for a vehicle to follow. + +```typescript title="Signature" + +``` + +## Hooks + +### `before` + +`Function` + +#### Props + +#### Returns + +#### Example + +### `after` + +`Function` + +#### Props + +#### Returns + +#### Example + +### `select` + +`Function` + +#### Props + +#### Returns + +#### Example + +### `track` + +`Function` + +#### Props + +#### Returns + +#### Example diff --git a/website/docs/changelog.md b/website/docs/changelog.md new file mode 100644 index 0000000..735ea60 --- /dev/null +++ b/website/docs/changelog.md @@ -0,0 +1,7 @@ +--- +sidebar_position: 1 +--- + +# ChangeLog + +12312 diff --git a/website/docs/color-validation.md b/website/docs/color-validation.md deleted file mode 100644 index fc9bcb8..0000000 --- a/website/docs/color-validation.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -sidebar_position: 2 ---- - -# Color validation - -Maybe you need to validate the color value and check that it's correct. To do that, just import `matchIsValidColor` from the package and use this function, it will return a `boolean`. - -```jsx -import React from 'react'; -import { MuiColorInput, matchIsValidColor } from 'mui-color-input'; - -const MyComponent = () => { - const [value, setValue] = React.useState('#ffffff'); - - const handleChange = (newValue) => { - matchIsValidColor(newValue); // boolean - }; - - return ; -}; -``` diff --git a/website/docs/community/contributing.md b/website/docs/community/contributing.md new file mode 100644 index 0000000..e3c5a93 --- /dev/null +++ b/website/docs/community/contributing.md @@ -0,0 +1,5 @@ +# contributing + +All contributions are welcome! + +Please take a moment to review guidelines [PR](https://github.com/hyperse-io/track/pulls) | [Issues](https://github.com/hyperse-io/track/issues) diff --git a/website/docs/css.md b/website/docs/css.md deleted file mode 100644 index baef8c2..0000000 --- a/website/docs/css.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -sidebar_position: 5 ---- - -# CSS - -Like any component, if you want to override a component's styles using custom classes, you can use the `className` prop. - -```jsx - -``` - -Then, you can use the differents global class names (see below) to target an element of `MuiColorInput`. - -| Global class | Description | -| ---------------------------- | ----------------------------------------------------------------------------------- | -| `.MuiColorInput-TextField` | Styles applied to the root element. | -| `.MuiColorInput-Button` | Styles applied to the [Button](https://mui.com/material-ui/api/button/) component | -| `.MuiColorInput-Popover` | Styles applied to the [Popover](https://mui.com/material-ui/api/popover/) component | -| `.MuiColorInput-ColorSpace` | Styles applied to the ColorSpace component | -| `.MuiColorInput-HueSlider` | Styles applied to the Hue [Slider](https://mui.com/material-ui/api/slider/) | -| `.MuiColorInput-AlphaSlider` | Styles applied to the Alpha [Slider](https://mui.com/material-ui/api/slider/) | - -For example: target the `.MuiColorInput-HueSlider` global class name to customize the Hue Slider. - -## Example with styled-component / emotion - -```jsx -import { styled } from 'styled-component'; // or emotion -import { MuiColorInput } from 'mui-color-input'; - -const MuiColorInputStyled = styled(MuiColorInput)` - & .MuiColorInput-AlphaSlider { - margin-top: 10px; - } -`; - -function MyComponent() { - return ; -} -``` diff --git a/website/docs/faq.md b/website/docs/faq.md new file mode 100644 index 0000000..525e937 --- /dev/null +++ b/website/docs/faq.md @@ -0,0 +1 @@ +# FAQ's diff --git a/website/docs/inheritance.md b/website/docs/inheritance.md deleted file mode 100644 index 18bf4f6..0000000 --- a/website/docs/inheritance.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -sidebar_position: 4 ---- - -# TextField inheritance - -While not explicitly documented, the props of the MUI **[TextField](https://mui.com/api/text-field)** component are also available on the **MuiColorInput** component. - -See: https://mui.com/material-ui/api/text-field/ - -### Example - -```jsx - -``` diff --git a/website/docs/intro.md b/website/docs/intro.md index 0e09fab..4e1f1e2 100644 --- a/website/docs/intro.md +++ b/website/docs/intro.md @@ -8,13 +8,13 @@ slug: /getting-started ## Install ```bash -npm install mui-color-input --save +npm install @hyperse/track --save ``` or you can use **yarn** ```bash -yarn add mui-color-input +yarn add @hyperse/track ``` We have completed installing the package. @@ -23,19 +23,114 @@ We have completed installing the package. Here is a simple usage for using the component: -```jsx -import React from 'react'; -import { MuiColorInput } from 'mui-color-input'; - -const MyComponent = () => { - const [color, setColor] = React.useState('#ffffff'); +```ts +export type Context = { + env: 'prod' | 'uat'; + platform: 'android' | 'ios'; + ip: string; + userId: string; +}; - const handleChange = (color) => { - setColor(color); +export type EventData = { + registry: { + userName: string; + mobile: string; + pwd: string; + email: string; + }; + addCart: { + price: number; + goodsId: string; + goodsName: string; + count: number; }; +}; - return ; +export type AdapterOptions = { + setup?: ( + ctx: Context, + eventData: EventData[keyof EventData] + ) => Promise<{ + name: 'setup' | 'setup1' | 'setup2'; + timeStamp: number; + }>; }; + +// custom report adapter +export class ReportAdapter extends BaseAdapter< + TrackContext, + EventData, + AdapterOptions, EventData> +> { + isTrackable( + ctx: TrackContext, + eventType: EventType, + eventData: EventData[EventType] + ): boolean | Promise { + return true; + } + report( + ctx: TrackContext, + reportData: AdapterReportData, + setupData?: + | { + name: 'setup' | 'setup1' | 'setup2'; + timeStamp: number; + } + | undefined + ): void | Promise {} +} + +const reportAdapter = new ReportAdapter(); + +// create adapter builder +const adapterBuilder = createAdapterBuilder< + TrackContext, + EventData, + AdapterOptions, EventData> +>(reportAdapter); + +// mount adapter hook +adapterBuilder + .setup((ctx, eventData) => { + return Promise.resolve({ + name: 'setup' as const, + timeStamp: new Date().getTime(), + newField: 'newField', + }); + }) + .before(async (ctx, eventType, eventData) => { + console.log('before'); + }) + .transform('addCart', (ctx, eventType, eventData) => { + return { + ...eventData, + pay: { + payId: 'p123', + payName: 'Sample Pay', + payType: 'credit', + }, + timeStamp: '2024-09-01T00:00:00Z', + }; + }) + .after(async (ctx, eventType, eventData) => { + console.log('after', eventData); + }) + .build(); + +// create track builder +const trackBuilder = createTrackBuilder< + TrackContext, + EventDataOption +>(); + +// mount track hook +await trackBuilder + .init({ reportAdapter: reportAdapter }) + .before(async (ctx) => {}) + .after(async (ctx) => {}) + .select(() => ['reportAdapter']) + .track('addCart', eventData.addCart); ``` ## Congratulations ! diff --git a/website/docs/playground.md b/website/docs/playground.md deleted file mode 100644 index 3bf1382..0000000 --- a/website/docs/playground.md +++ /dev/null @@ -1,5 +0,0 @@ -# Playground - -Need to play around with **MuiColorInput** in a live environment before deciding if it's the right fit? No problem. - -[![Open in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/mui-color-input-fgvny5?fontsize=14&hidenavigation=1&theme=dark) diff --git a/website/docs/react-hook-form.md b/website/docs/react-hook-form.md deleted file mode 100644 index a4c995a..0000000 --- a/website/docs/react-hook-form.md +++ /dev/null @@ -1,48 +0,0 @@ -# React Hook Form - -Here an example if you want to plug `MuiColorInput` to your form using [React Hook Form](https://react-hook-form.com/). - -```tsx -import React from 'react'; -import ReactDOM from 'react-dom'; -import Button from '@mui/material/Button'; -import { MuiColorInput, matchIsValidColor } from 'mui-color-input'; -import { Controller, useForm } from 'react-hook-form'; - -const App = () => { - const { control, handleSubmit } = useForm({ - defaultValues: { - color: '#ffffff', - }, - }); - - const onSubmit = (data) => { - alert(JSON.stringify(data)); - }; - - return ( -
- ( - - )} - /> -
- -
- - ); -}; -``` - -[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/react-hook-form-with-mui-color-input-94iiv1?fontsize=14&hidenavigation=1&theme=dark) diff --git a/website/docs/typescript.md b/website/docs/typescript.md deleted file mode 100644 index 1434089..0000000 --- a/website/docs/typescript.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -sidebar_position: 4 ---- - -# TypeScript - -This package is written in **TypeScript**. So you don't need to create your own types. Here an example if you use **TypeScript**. - -**Nota bene**: Props are defined within the `MuiColorInputProps` interface. - -```tsx -import React from 'react'; -import { - MuiColorInput, - MuiColorInputValue, - MuiColorInputColors, - MuiColorInputFormat, -} from 'mui-color-input'; - -const MyComponent = () => { - const [value, setValue] = React.useState('#ffffff'); - - const handleChange = (newValue: string, colors: MuiColorInputColors) => { - setValue(newValue); - }; - - const format: MuiColorInputFormat = 'hex'; - - return ( - - ); -}; -``` diff --git a/website/sidebars.ts b/website/sidebars.ts index 465fb41..1f5a17b 100644 --- a/website/sidebars.ts +++ b/website/sidebars.ts @@ -13,7 +13,64 @@ import type { SidebarsConfig } from '@docusaurus/plugin-content-docs'; const sidebars: SidebarsConfig = { // By default, Docusaurus generates a sidebar from the docs folder structure tutorialSidebar: [ - { type: 'autogenerated', dirName: '.' }, + { + type: 'doc', + id: 'intro', + label: 'Getting Started', + }, + { + type: 'category', + label: 'API', + items: [ + { + type: 'doc', + id: 'api/base-adapter', + label: 'BaseAdapter', + }, + { + type: 'doc', + id: 'api/adapter-builder', + label: 'AdapterBuilder', + }, + { + type: 'doc', + id: 'api/track-builder', + label: 'TrackBuilder', + }, + ], + }, + { + type: 'category', + label: 'Adapters', + items: [ + { + type: 'doc', + id: 'adapters/google-adapter', + label: 'GoogleAdapter', + }, + ], + }, + { + type: 'category', + label: 'Community', + items: [ + { + type: 'doc', + id: 'community/contributing', + label: 'Contributing', + }, + { + type: 'link', + label: 'ChangeLog', + href: 'https://github.com/hyperse-io/track/blob/main/CHANGELOG.md', + }, + { + type: 'link', + label: 'Hyperse', + href: 'https://github.com/hyperse-io', + }, + ], + }, { type: 'category', label: 'Related projects', @@ -30,6 +87,11 @@ const sidebars: SidebarsConfig = { }, ], }, + { + type: 'doc', + id: 'faq', + label: "FAQ's", + }, ], }; diff --git a/website/src/components/Amimate/DynamicCoding.tsx b/website/src/components/Amimate/DynamicCoding.tsx new file mode 100644 index 0000000..d08f40d --- /dev/null +++ b/website/src/components/Amimate/DynamicCoding.tsx @@ -0,0 +1,34 @@ +import React, { useEffect, useRef } from 'react'; + +export default function DynamicCoding(): JSX.Element { + const preRef = useRef(null); + + const [mounted, setMounted] = React.useState(false); + + useEffect(() => { + setMounted(true); + }, []); + + useEffect(() => { + if (!mounted) { + return; + } + }, [mounted]); + + return ( +
+
+
+          
+ +
coding
+
+
+
+
+
+ ); +} diff --git a/website/src/pages/index.module.css b/website/src/pages/index.module.css index 46a46a5..98cf351 100644 --- a/website/src/pages/index.module.css +++ b/website/src/pages/index.module.css @@ -23,4 +23,8 @@ top: 0rem; width: 100%; @apply h-[15em] md:h-[30em]; +} + +::-webkit-scrollbar { + display: none; } \ No newline at end of file diff --git a/website/src/pages/index.tsx b/website/src/pages/index.tsx index a7467e5..89aa50c 100644 --- a/website/src/pages/index.tsx +++ b/website/src/pages/index.tsx @@ -5,6 +5,7 @@ import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import { CheckIcon } from '@heroicons/react/24/outline'; import { DocumentDuplicateIcon } from '@heroicons/react/24/outline'; +import DynamicCoding from '@site/src/components/Amimate/DynamicCoding'; import HomepageFeatures from '@site/src/components/HomepageFeatures'; import LogoDark from '@site/static/img/logo-dark.svg'; import LogoWhite from '@site/static/img/logo-white.svg'; @@ -105,6 +106,10 @@ export default function Home() { >
+
+
Sample Usage
+ +
diff --git a/yarn.lock b/yarn.lock index e57c688..5bbdbef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,6 +12,38 @@ __metadata: languageName: node linkType: hard +"@actions/core@npm:1.10.1": + version: 1.10.1 + resolution: "@actions/core@npm:1.10.1" + dependencies: + "@actions/http-client": "npm:^2.0.1" + uuid: "npm:^8.3.2" + checksum: 10/d32af783ecb07f25a0f190112ee8e749a4c4cb88327d6df756ea1dcee146ab413c0e651a9c949294f8202ced1436c049d7b469485431a5cc4491d66926ec8323 + languageName: node + linkType: hard + +"@actions/github@npm:6.0.0": + version: 6.0.0 + resolution: "@actions/github@npm:6.0.0" + dependencies: + "@actions/http-client": "npm:^2.2.0" + "@octokit/core": "npm:^5.0.1" + "@octokit/plugin-paginate-rest": "npm:^9.0.0" + "@octokit/plugin-rest-endpoint-methods": "npm:^10.0.0" + checksum: 10/81831a78377175d8825fc0b94247ff366c0e87ad1dfa48df9b30b8659506f216dcf1e2d3124fcd318839b92c24ba20165e238b3cc11a34db89c69c40825e9ccf + languageName: node + linkType: hard + +"@actions/http-client@npm:^2.0.1, @actions/http-client@npm:^2.2.0": + version: 2.2.1 + resolution: "@actions/http-client@npm:2.2.1" + dependencies: + tunnel: "npm:^0.0.6" + undici: "npm:^5.25.4" + checksum: 10/b7338f13461eeca945acc9ccdd20a46e545624dc872bc12869eca7d9a58536ee3e1ecc0d1a1d4c16e8610c2b783e7108e12148b6db5d7fb8bf8b950b8a002d66 + languageName: node + linkType: hard + "@algolia/autocomplete-core@npm:1.9.3": version: 1.9.3 resolution: "@algolia/autocomplete-core@npm:1.9.3" @@ -3114,6 +3146,13 @@ __metadata: languageName: node linkType: hard +"@fastify/busboy@npm:^2.0.0": + version: 2.1.1 + resolution: "@fastify/busboy@npm:2.1.1" + checksum: 10/2bb8a7eca8289ed14c9eb15239bc1019797454624e769b39a0b90ed204d032403adc0f8ed0d2aef8a18c772205fa7808cf5a1b91f21c7bfc7b6032150b1062c5 + languageName: node + linkType: hard + "@hapi/hoek@npm:^9.0.0, @hapi/hoek@npm:^9.3.0": version: 9.3.0 resolution: "@hapi/hoek@npm:9.3.0" @@ -3251,6 +3290,7 @@ __metadata: "@hyperse/eslint-config-hyperse": "npm:^1.0.12" "@hyperse/exec-program": "npm:^1.0.10" "@hyperse/pipeline": "npm:^1.0.4" + "@hyperse/vitest-coverage-reporter": "npm:^1.0.13" "@types/lodash": "npm:^4" "@types/node": "npm:^22.1.0" "@types/react": "npm:^18.3.3" @@ -3286,6 +3326,25 @@ __metadata: languageName: node linkType: hard +"@hyperse/vitest-coverage-reporter@npm:^1.0.13": + version: 1.0.13 + resolution: "@hyperse/vitest-coverage-reporter@npm:1.0.13" + dependencies: + "@actions/core": "npm:1.10.1" + "@actions/github": "npm:6.0.0" + "@manypkg/get-packages": "npm:^2.2.2" + common-tags: "npm:1.8.2" + mdast-util-to-string: "npm:^4.0.0" + minimist: "npm:^1.2.8" + remark-parse: "npm:^11.0.0" + remark-stringify: "npm:^11.0.0" + unified: "npm:^11.0.5" + bin: + generate-coverage-report: bin/generate-coverage-report.mjs + checksum: 10/d3e506e97d8988df27ea8f16005970b407a6034fe47e7b320618951eb60df2c1b0b2acfc29370edd509d988a43df010ad2e2f52cda042886e0256b555aea9fca + languageName: node + linkType: hard + "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -3411,6 +3470,15 @@ __metadata: languageName: node linkType: hard +"@manypkg/find-root@npm:^2.2.2": + version: 2.2.3 + resolution: "@manypkg/find-root@npm:2.2.3" + dependencies: + "@manypkg/tools": "npm:^1.1.2" + checksum: 10/b0e6e530bda0019ea098fc88903c703b64f0eee3e568eb7e82258b1b487c330c76648bd27569835fcc61cf60d15d257a2779ac0051d1bc8a682f0fb629b989ef + languageName: node + linkType: hard + "@manypkg/get-packages@npm:^1.1.3": version: 1.1.3 resolution: "@manypkg/get-packages@npm:1.1.3" @@ -3425,6 +3493,27 @@ __metadata: languageName: node linkType: hard +"@manypkg/get-packages@npm:^2.2.2": + version: 2.2.2 + resolution: "@manypkg/get-packages@npm:2.2.2" + dependencies: + "@manypkg/find-root": "npm:^2.2.2" + "@manypkg/tools": "npm:^1.1.1" + checksum: 10/90a6f08a0b79f8edefeddb34eb0f1dad9ae08f5a86fc0df02349111cb85a239feb5aefb20d82c097caff2181581b3ec59b043c21cafd32e6baf9af6b19cc9de4 + languageName: node + linkType: hard + +"@manypkg/tools@npm:^1.1.1, @manypkg/tools@npm:^1.1.2": + version: 1.1.2 + resolution: "@manypkg/tools@npm:1.1.2" + dependencies: + fast-glob: "npm:^3.3.2" + jju: "npm:^1.4.0" + js-yaml: "npm:^4.1.0" + checksum: 10/f3d57b52d07634aef92a136e8f02009626ce7cc283d77d129787bf81d1ad8b0dae9a2cedfd794bd71caf601184929125fc2f4aa105bc0a8d3fcf56a0ce1cf0a0 + languageName: node + linkType: hard + "@mdx-js/mdx@npm:^3.0.0": version: 3.0.1 resolution: "@mdx-js/mdx@npm:3.0.1" @@ -3631,6 +3720,126 @@ __metadata: languageName: node linkType: hard +"@octokit/auth-token@npm:^4.0.0": + version: 4.0.0 + resolution: "@octokit/auth-token@npm:4.0.0" + checksum: 10/60e42701e341d700f73c518c7a35675d36d79fa9d5e838cc3ade96d147e49f5ba74db2e07b2337c2b95aaa540aa42088116df2122daa25633f9e70a2c8785c44 + languageName: node + linkType: hard + +"@octokit/core@npm:^5.0.1": + version: 5.2.0 + resolution: "@octokit/core@npm:5.2.0" + dependencies: + "@octokit/auth-token": "npm:^4.0.0" + "@octokit/graphql": "npm:^7.1.0" + "@octokit/request": "npm:^8.3.1" + "@octokit/request-error": "npm:^5.1.0" + "@octokit/types": "npm:^13.0.0" + before-after-hook: "npm:^2.2.0" + universal-user-agent: "npm:^6.0.0" + checksum: 10/2e40baf0b5c6949922436a653c213be43befd9690c43dd89872f669f3ac23117ae8ae5e5d6c18094813756c71c3f4fbedd575a891f0b89e12f58b2c38b7f3c13 + languageName: node + linkType: hard + +"@octokit/endpoint@npm:^9.0.1": + version: 9.0.5 + resolution: "@octokit/endpoint@npm:9.0.5" + dependencies: + "@octokit/types": "npm:^13.1.0" + universal-user-agent: "npm:^6.0.0" + checksum: 10/212122f653bf076ec37dd7de44bd54db74aa3cd16be4c395c91444488331becd83351e26b30248168e2cc28fc07b1a96e8f74adbbab02826f76de92e069f391f + languageName: node + linkType: hard + +"@octokit/graphql@npm:^7.1.0": + version: 7.1.0 + resolution: "@octokit/graphql@npm:7.1.0" + dependencies: + "@octokit/request": "npm:^8.3.0" + "@octokit/types": "npm:^13.0.0" + universal-user-agent: "npm:^6.0.0" + checksum: 10/da6857a69dc93cd20a11d3a905db4214d269d246a6aaee1d8734f922024b08ffdef0b3cba2ac79917633043b4f50464242b0bd92a265c960083dfff5b833dbbe + languageName: node + linkType: hard + +"@octokit/openapi-types@npm:^20.0.0": + version: 20.0.0 + resolution: "@octokit/openapi-types@npm:20.0.0" + checksum: 10/9f60572af1201dd92626c412253d83d986b8ab1956250b95f417013ee8e7baf25870eeb801d16672cabc2c420544bc9c2f0a979e07603ff5997eff038c71a8c3 + languageName: node + linkType: hard + +"@octokit/openapi-types@npm:^22.2.0": + version: 22.2.0 + resolution: "@octokit/openapi-types@npm:22.2.0" + checksum: 10/0471b0c789fada5aa2390e6f82ba477738228ef7d2d986dda9aab0cb625d1562bd178ba0ba4d2655ce841079cd5efff9e58ece2077c27e569ea22109ea301830 + languageName: node + linkType: hard + +"@octokit/plugin-paginate-rest@npm:^9.0.0": + version: 9.2.1 + resolution: "@octokit/plugin-paginate-rest@npm:9.2.1" + dependencies: + "@octokit/types": "npm:^12.6.0" + peerDependencies: + "@octokit/core": 5 + checksum: 10/1528ab17eedb6705e30ad8576493f06b40f29a87c920a4affeb9715fe5f386e064b79eadd401c0cd1e7ec22287a461da4f5353a4ee57bc614fd890b0aa139d77 + languageName: node + linkType: hard + +"@octokit/plugin-rest-endpoint-methods@npm:^10.0.0": + version: 10.4.1 + resolution: "@octokit/plugin-rest-endpoint-methods@npm:10.4.1" + dependencies: + "@octokit/types": "npm:^12.6.0" + peerDependencies: + "@octokit/core": 5 + checksum: 10/1090fc5a1bebb7b48c512e178f8ad69a3ef8332e583274972f3a3035e9be9200093e22a5dbfe0f71aa1a7a8817e54bb915af3c2a3f88db1311a2873cef176552 + languageName: node + linkType: hard + +"@octokit/request-error@npm:^5.1.0": + version: 5.1.0 + resolution: "@octokit/request-error@npm:5.1.0" + dependencies: + "@octokit/types": "npm:^13.1.0" + deprecation: "npm:^2.0.0" + once: "npm:^1.4.0" + checksum: 10/d03f9f7a408af673cd991eeb450b6f4a5cee6c368f6349eb0211dfc0404fddfcff8b5225ef186020a2a1829adba0aa8c9174155b49ab2ed00a94fb9a886a1dd3 + languageName: node + linkType: hard + +"@octokit/request@npm:^8.3.0, @octokit/request@npm:^8.3.1": + version: 8.4.0 + resolution: "@octokit/request@npm:8.4.0" + dependencies: + "@octokit/endpoint": "npm:^9.0.1" + "@octokit/request-error": "npm:^5.1.0" + "@octokit/types": "npm:^13.1.0" + universal-user-agent: "npm:^6.0.0" + checksum: 10/176cd83c68bde87111a01d50e2d21cf12ec362c1a30b33649eb8771d37397f6d6dd0b0844aab8d59b16d74c825252e39cadd52e37a4b1669d6facd1cb2cdc995 + languageName: node + linkType: hard + +"@octokit/types@npm:^12.6.0": + version: 12.6.0 + resolution: "@octokit/types@npm:12.6.0" + dependencies: + "@octokit/openapi-types": "npm:^20.0.0" + checksum: 10/19b77a8d25af2a5df4561f8750f807edfc9fca5b07cfa9fb21dce4665e1b188c966688f5ed5e08089404428100dfe44ad353f8d8532f1d30fe47e61c5faa1440 + languageName: node + linkType: hard + +"@octokit/types@npm:^13.0.0, @octokit/types@npm:^13.1.0": + version: 13.5.0 + resolution: "@octokit/types@npm:13.5.0" + dependencies: + "@octokit/openapi-types": "npm:^22.2.0" + checksum: 10/d2aeebc1d8684c4e950f054a52b484e898b72d9f5f8433bcf010161716eea20d1132820d922212f19557a8f147354f2674d1a27b22941308b7c298bdd2674ffa + languageName: node + linkType: hard + "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" @@ -5606,6 +5815,13 @@ __metadata: languageName: node linkType: hard +"before-after-hook@npm:^2.2.0": + version: 2.2.3 + resolution: "before-after-hook@npm:2.2.3" + checksum: 10/e676f769dbc4abcf4b3317db2fd2badb4a92c0710e0a7da12cf14b59c3482d4febf835ad7de7874499060fd4e13adf0191628e504728b3c5bb4ec7a878c09940 + languageName: node + linkType: hard + "better-path-resolve@npm:1.0.0": version: 1.0.0 resolution: "better-path-resolve@npm:1.0.0" @@ -6399,6 +6615,13 @@ __metadata: languageName: node linkType: hard +"common-tags@npm:1.8.2": + version: 1.8.2 + resolution: "common-tags@npm:1.8.2" + checksum: 10/c665d0f463ee79dda801471ad8da6cb33ff7332ba45609916a508ad3d77ba07ca9deeb452e83f81f24c2b081e2c1315347f23d239210e63d1c5e1a0c7c019fe2 + languageName: node + linkType: hard + "compare-func@npm:^2.0.0": version: 2.0.0 resolution: "compare-func@npm:2.0.0" @@ -7184,6 +7407,13 @@ __metadata: languageName: node linkType: hard +"deprecation@npm:^2.0.0": + version: 2.3.1 + resolution: "deprecation@npm:2.3.1" + checksum: 10/f56a05e182c2c195071385455956b0c4106fe14e36245b00c689ceef8e8ab639235176a96977ba7c74afb173317fac2e0ec6ec7a1c6d1e6eaa401c586c714132 + languageName: node + linkType: hard + "dequal@npm:^2.0.0": version: 2.0.3 resolution: "dequal@npm:2.0.3" @@ -10910,6 +11140,13 @@ __metadata: languageName: node linkType: hard +"jju@npm:^1.4.0": + version: 1.4.0 + resolution: "jju@npm:1.4.0" + checksum: 10/1067ff8ce02221faac5a842116ed0ec79a53312a111d0bf8342a80bd02c0a3fdf0b8449694a65947db0a3e8420e8b326dffb489c7dd5866efc380c0d1708a707 + languageName: node + linkType: hard + "joi@npm:^17.9.2": version: 17.13.3 resolution: "joi@npm:17.13.3" @@ -13133,7 +13370,7 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.3.0": +"once@npm:^1.3.0, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -16873,6 +17110,13 @@ __metadata: languageName: node linkType: hard +"tunnel@npm:^0.0.6": + version: 0.0.6 + resolution: "tunnel@npm:0.0.6" + checksum: 10/cf1ffed5e67159b901a924dbf94c989f20b2b3b65649cfbbe4b6abb35955ce2cf7433b23498bdb2c5530ab185b82190fce531597b3b4a649f06a907fc8702405 + languageName: node + linkType: hard + "type-check@npm:^0.4.0, type-check@npm:~0.4.0": version: 0.4.0 resolution: "type-check@npm:0.4.0" @@ -17048,6 +17292,15 @@ __metadata: languageName: node linkType: hard +"undici@npm:^5.25.4": + version: 5.28.4 + resolution: "undici@npm:5.28.4" + dependencies: + "@fastify/busboy": "npm:^2.0.0" + checksum: 10/a666a9f5ac4270c659fafc33d78b6b5039a0adbae3e28f934774c85dcc66ea91da907896f12b414bd6f578508b44d5dc206fa636afa0e49a4e1c9e99831ff065 + languageName: node + linkType: hard + "unicode-canonical-property-names-ecmascript@npm:^2.0.0": version: 2.0.0 resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.0" @@ -17122,7 +17375,7 @@ __metadata: languageName: node linkType: hard -"unified@npm:^11.0.0, unified@npm:^11.0.3, unified@npm:^11.0.4": +"unified@npm:^11.0.0, unified@npm:^11.0.3, unified@npm:^11.0.4, unified@npm:^11.0.5": version: 11.0.5 resolution: "unified@npm:11.0.5" dependencies: @@ -17249,6 +17502,13 @@ __metadata: languageName: node linkType: hard +"universal-user-agent@npm:^6.0.0": + version: 6.0.1 + resolution: "universal-user-agent@npm:6.0.1" + checksum: 10/fdc8e1ae48a05decfc7ded09b62071f571c7fe0bd793d700704c80cea316101d4eac15cc27ed2bb64f4ce166d2684777c3198b9ab16034f547abea0d3aa1c93c + languageName: node + linkType: hard + "universalify@npm:^0.1.0": version: 0.1.2 resolution: "universalify@npm:0.1.2" From 785218a5ef17ef4a3fee0ef2abf3450f4ccf2f7a Mon Sep 17 00:00:00 2001 From: "shunquan.wang" Date: Mon, 12 Aug 2024 21:22:57 +0800 Subject: [PATCH 05/28] feat: add vitest reporter --- .husky/pre-commit | 1 - README.md | 6 ++++++ package.json | 1 + vitest.config.ts | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index 4aec334..95dc3ee 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,5 +1,4 @@ #!/bin/sh -. "$(dirname -- "$0")/_/husky.sh" yarn run test:coverage yarn generate-coverage-report --type readme diff --git a/README.md b/README.md index ca509a4..84df188 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,12 @@

+ + +## Coverage Report + +
Status Category Percentage Covered / Total
🔵 Lines 100% 185 / 185
🔵 Statements 100% 185 / 185
🔵 Functions 98.18% 54 / 55
🔵 Branches 93.75% 75 / 80
+ A typed, smart, scalable , powerful data collection engine written in typescript ## Install diff --git a/package.json b/package.json index 7bed498..02f0485 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "lint-staged-files": "lint-staged --allow-empty", "changeset": "changeset", "release": "yarn build && changeset publish", + "test:coverage": "vitest run --coverage", "cz": "cz", "prepare": "husky" }, diff --git a/vitest.config.ts b/vitest.config.ts index 24730b6..e0123dd 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -12,7 +12,7 @@ export default defineConfig({ coverage: { include: ['src/**'], provider: 'istanbul', - reporter: ['text', 'json', 'json-summary'], + reporter: ['text', 'json-summary', 'json'], reportOnFailure: true, }, }, From 81494dd32913d8e055b08767f0521d1e9e96bddf Mon Sep 17 00:00:00 2001 From: "shunquan.wang" Date: Tue, 13 Aug 2024 20:54:36 +0800 Subject: [PATCH 06/28] feat: perfect docs --- src/adapter/adapter-base.ts | 9 +++++---- src/types/types-create.ts | 6 ++++-- tests/test-adapter.spec.ts | 5 +++-- tests/test-utils/types/type-adapter-options.ts | 5 +++-- website/docs/api/adapter-builder.md | 12 +++++++++--- website/docs/api/base-adapter.md | 2 +- 6 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/adapter/adapter-base.ts b/src/adapter/adapter-base.ts index 4d2bfc7..9d28dd1 100644 --- a/src/adapter/adapter-base.ts +++ b/src/adapter/adapter-base.ts @@ -82,14 +82,15 @@ export abstract class BaseAdapter< return result; }; - private executeReport = async ( + private executeReport = async ( ctx: Context, - eventData: EventData[keyof EventData], + eventType: EventType, + eventData: EventData[EventType], reportData: ReportData ): Promise => { let setupResult; if (this.setupHook) { - setupResult = await this.setupHook(ctx, eventData); + setupResult = await this.setupHook(ctx, eventType, eventData); } await this.report(ctx, reportData, setupResult); return reportData; @@ -113,7 +114,7 @@ export abstract class BaseAdapter< await executeFunction(this.beforeHook, ctx, eventType, eventData), async () => await this.executeTransform(ctx, eventType, eventData), async (reportData) => - await this.executeReport(ctx, eventData, reportData), + await this.executeReport(ctx, eventType, eventData, reportData), async (reportData) => await executeFunction(this.afterHook, ctx, eventType, reportData) )(); diff --git a/src/types/types-create.ts b/src/types/types-create.ts index 7003632..cea9360 100644 --- a/src/types/types-create.ts +++ b/src/types/types-create.ts @@ -55,11 +55,13 @@ export type TrackAdapterOptions< * Executes before the report function is called * * @param ctx - The track context. + * @param eventType - The event type. * @param eventData - The event data. * @returns A value or a promise that resolves to a value. */ - setup?: ( + setup?: ( ctx: Context, - eventData: EventData[keyof EventData] + eventType: EventType, + eventData: EventData[EventType] ) => any | Promise; }; diff --git a/tests/test-adapter.spec.ts b/tests/test-adapter.spec.ts index f1622d2..8ef2d67 100644 --- a/tests/test-adapter.spec.ts +++ b/tests/test-adapter.spec.ts @@ -52,7 +52,7 @@ describe('test-adapter.spec', () => { AdapterOptions, EventDataOption> >(reportAdapter); - const setupFun = vi.fn((ctx, eventData) => { + const setupFun = vi.fn((ctx, eventType, eventData) => { return Promise.resolve({ name: 'setup' as const, timeStamp: new Date().getTime(), @@ -89,7 +89,8 @@ describe('test-adapter.spec', () => { expect(setupFun.mock.lastCall?.[0]).toMatchObject({ data: trackData, }); - expect(setupFun.mock.lastCall?.[1]).toMatchObject({ ...eventData.addCart }); + expect(setupFun.mock.lastCall?.[1]).toBe('addCart'); + expect(setupFun.mock.lastCall?.[2]).toMatchObject({ ...eventData.addCart }); expect(setupFun.mock.results[0].value).toBeDefined(); expect(setupFun.mock.results?.[0].value).toMatchObject( Promise.resolve({ diff --git a/tests/test-utils/types/type-adapter-options.ts b/tests/test-utils/types/type-adapter-options.ts index fcb2633..d03cc73 100644 --- a/tests/test-utils/types/type-adapter-options.ts +++ b/tests/test-utils/types/type-adapter-options.ts @@ -1,7 +1,8 @@ export type AdapterOptions = { - setup?: ( + setup?: ( ctx: Context, - eventData: EventData[keyof EventData] + eventTYpe: EventType, + eventData: EventData[EventType] ) => Promise<{ name: 'setup' | 'setup1' | 'setup2'; timeStamp: number; diff --git a/website/docs/api/adapter-builder.md b/website/docs/api/adapter-builder.md index db1ec7f..d018a53 100644 --- a/website/docs/api/adapter-builder.md +++ b/website/docs/api/adapter-builder.md @@ -18,17 +18,23 @@ export class AdapterBuilder< ### `setup` -`Function` +`( + ctx: Context, + eventType: EventType, + eventData: EventData[EventType] + ) => any | Promise` -Sets up the adapter. +The setup data. It is often useful to extend the report method by configuring some additional data to be used in the report phase without the transform processing #### Props - **ctx** : `Context` - The track context. +- **eventType** : `EventType` - The event type. +- **eventData** : `EventData[EventType]` - The event data. #### Returns -- `Promise` - A promise that resolves when the adapter is set up. +- `any` | `Promise` - A value or a promise that resolves to a value. #### Example diff --git a/website/docs/api/base-adapter.md b/website/docs/api/base-adapter.md index 440b6cd..4b4bf80 100644 --- a/website/docs/api/base-adapter.md +++ b/website/docs/api/base-adapter.md @@ -68,7 +68,7 @@ Reports the event to the adapter. - **ctx** : `Context` - The track context. - **reportData** : `AdapterReportData` - The data to report. -- **setupData** : `Required['setup'] extends (...args: any) => any ? Awaited['setup']> : undefined` - The setup data. +- **setupData** : `Required['setup'] extends (...args: any) => any ? Awaited['setup']> : undefined` - The setup data. It is often useful to extend the report method by configuring some additional data to be used in the report phase without the transform processing #### Returns From 5030255f43e144fdad215f82641fdbca893aedb9 Mon Sep 17 00:00:00 2001 From: "shunquan.wang" Date: Tue, 13 Aug 2024 22:03:54 +0800 Subject: [PATCH 07/28] docs: perfect docs --- README.md | 28 +++--- hyperse-track.code-workspace | 3 + tests/test-track-docs.spec.ts | 141 +++++++++++++++++++++++++++ website/docs/api/adapter-builder.md | 144 +++++++++++++++++----------- website/docs/api/track-builder.md | 93 +++++++++++++++--- website/src/pages/index.tsx | 5 - 6 files changed, 325 insertions(+), 89 deletions(-) create mode 100644 tests/test-track-docs.spec.ts diff --git a/README.md b/README.md index 84df188..a0be893 100644 --- a/README.md +++ b/README.md @@ -147,15 +147,11 @@ await trackBuilder ## Options -### ReportAdapter - -Adapter used to process event data reporting - -#### `isTrackable` +#### [`isTrackable`](https://hyperse-io.github.io/track/docs/api/base-adapter#istrackable) Checks if the adapter is available. -#### `report` +#### [`report`](https://hyperse-io.github.io/track/docs/api/base-adapter#istrackable) Data report @@ -163,23 +159,23 @@ Data report A builder for track adapter. Provides the ability to load adpater corresponding hooks -#### `setup` +#### [`setup`](https://hyperse-io.github.io/track/docs/api/adapter-builder#setup) The adapter hook Performs data consolidation against the rules defined by AdapterOptions. Passes the returned results to report. Executes before the report function is called -#### `before` +#### [`before`](https://hyperse-io.github.io/track/docs/api/adapter-builder#before) The adapter hook function is executed before tracking an event. -#### `transform` +#### [`transform`](https://hyperse-io.github.io/track/docs/api/adapter-builder#transform) The adapter hook function that converts EventData corresponding to different EventType -#### `after` +#### [`after`](https://hyperse-io.github.io/track/docs/api/adapter-builder#after) The adapter hook function is triggered after the report is executed -#### `build` +#### [`build`](https://hyperse-io.github.io/track/docs/api/adapter-builder#build) Return adapter instance @@ -187,22 +183,22 @@ Return adapter instance A builder for track. Provides the ability to load track corresponding hooks -#### `init` +#### [`init`](https://hyperse-io.github.io/track/docs/api/track-builder#init) Track builder initialization, which loads the adapter into the track -#### `before` +#### [`before`](https://hyperse-io.github.io/track/docs/api/track-builder#before) A function that is executed before tracking -#### `after` +#### [`after`](https://hyperse-io.github.io/track/docs/api/track-builder#after) A function that is executed after a track event -#### `select` +#### [`select`](https://hyperse-io.github.io/track/docs/api/track-builder#select) Selects track adapter from a given context, event data, and adapter map. -#### `track` +#### [`track`](https://hyperse-io.github.io/track/docs/api/track-builder#track) Event reporting activation function diff --git a/hyperse-track.code-workspace b/hyperse-track.code-workspace index 19d0497..e0751a9 100644 --- a/hyperse-track.code-workspace +++ b/hyperse-track.code-workspace @@ -56,5 +56,8 @@ "i18n-ally.localesPaths": [ "i18n" ], + "[markdown]": { + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + }, }, } \ No newline at end of file diff --git a/tests/test-track-docs.spec.ts b/tests/test-track-docs.spec.ts new file mode 100644 index 0000000..02370da --- /dev/null +++ b/tests/test-track-docs.spec.ts @@ -0,0 +1,141 @@ +import { createAdapterBuilder } from '../src/adapter/create-adapter-builder.js'; +import { createTrackBuilder } from '../src/core/create-track-builder.js'; +import { TrackContext } from '../src/types/types-create.js'; +import { ReportAdapter } from './test-utils/adapter/report-adapter.js'; +import { AdapterOptions } from './test-utils/types/type-adapter-options.js'; +import { EventDataOption } from './test-utils/types/type-event.js'; +import { TrackData } from './test-utils/types/type-track-data.js'; + +describe('test-track-pipeline.spec', () => { + const trackData: TrackData = { + bizMode: 'test', + env: 'prod', + platform: 'android', + ip: '0.0.0.0', + userId: 'uuid_10001', + }; + + const eventData: EventDataOption = { + registry: { + userName: 'testUser', + mobile: '1234567890', + pwd: 'password123', + email: 'testuser@example.com', + }, + previewGoods: { + goodsId: 'g123', + goodsName: 'Sample Goods', + }, + addCart: { + price: 99.99, + goodsId: 'g123', + goodsName: 'Sample Goods', + count: 2, + }, + timeStamp: '1000', + }; + + it('docs example', async () => { + const adapter = new ReportAdapter(); + + const adapterBuilder = createAdapterBuilder< + TrackContext, + EventDataOption, + AdapterOptions, EventDataOption> + >(adapter); + + adapterBuilder + .setup( + ( + ctx: TrackContext, + eventType: keyof EventDataOption, + eventData: EventDataOption[keyof EventDataOption] + ) => { + return Promise.resolve({ + name: 'setup', + timeStamp: Date.now(), + }); + } + ) + .before( + ( + ctx: TrackContext, + eventType: keyof EventDataOption, + eventData: EventDataOption[keyof EventDataOption] + ) => { + //do something + } + ) + .transform( + 'addCart', + ( + ctx: TrackContext, + eventType: 'addCart', + eventData: EventDataOption['addCart'] + ) => { + return { + ...eventData, + goodName: 'ac_' + eventData?.goodsName, + timeStamp: Date.now(), + }; + } + ) + .transform( + 'previewGoods', + ( + ctx: TrackContext, + eventType: 'previewGoods', + eventData: EventDataOption['previewGoods'] + ) => { + return { + ...eventData, + goodName: 'pg_' + eventData?.goodsName, + timeStamp: Date.now(), + }; + } + ) + .after( + ( + ctx: TrackContext, + eventType: keyof EventDataOption, + eventData: EventDataOption[keyof EventDataOption] + ) => { + //do something + } + ) + .build(); + + const trackBuilder = createTrackBuilder< + TrackContext, + EventDataOption + >(); + + await trackBuilder + .init(() => { + return { reportAdapter: adapter, consoleAdapter: adapter }; + }) + .before(async (ctx) => { + // do something + }) + .after(async (ctx) => { + // do something + }) + .select( + ( + ctx: TrackContext, + adapterMap: { + reportAdapter: ReportAdapter; + consoleAdapter: ReportAdapter; + } + ) => 'consoleAdapter' + ) + .track('addCart', { + price: 99.99, + goodsId: 'g123', + goodsName: 'Sample Goods', + count: 2, + }); + + expect(true).toBeTruthy(); + }); +}); diff --git a/website/docs/api/adapter-builder.md b/website/docs/api/adapter-builder.md index d018a53..c761589 100644 --- a/website/docs/api/adapter-builder.md +++ b/website/docs/api/adapter-builder.md @@ -3,14 +3,12 @@ The `AdapterBuilder` class is used to create a new adapter instance. It is a factory class that creates a new adapter instance based on the provided configuration. ```typescript title="Signature" -export class AdapterBuilder< +class AdapterBuilder< Context extends TrackContext, EventData extends TrackEventDataBase, AdapterOptions extends TrackAdapterOptions, > { - constructor( - options: AdapterBuilderOptions - ); + constructor(adapter: TrackAdapter); } ``` @@ -18,12 +16,6 @@ export class AdapterBuilder< ### `setup` -`( - ctx: Context, - eventType: EventType, - eventData: EventData[EventType] - ) => any | Promise` - The setup data. It is often useful to extend the report method by configuring some additional data to be used in the report phase without the transform processing #### Props @@ -32,86 +24,128 @@ The setup data. It is often useful to extend the report method by configuring so - **eventType** : `EventType` - The event type. - **eventData** : `EventData[EventType]` - The event data. -#### Returns - -- `any` | `Promise` - A value or a promise that resolves to a value. - #### Example ```typescript title="AdapterBuilder.ts" -const adapterBuilder = new AdapterBuilder({ - new ReportAdapter(), -}); - -adapterBuilder.setup(ctx); +adapterBuilder.setup( + ( + ctx: TrackContext, + eventType: keyof EventDataOption, + eventData: EventDataOption[keyof EventDataOption] + ) => { + return Promise.resolve({ + name: 'setup', + timeStamp: Date.now(), + }); + } +); ``` -### `build` - -`Function` +### `before` -Builds a new adapter instance. +The adapter hook function is executed before tracking an event. #### Props - **ctx** : `Context` - The track context. - -#### Returns - -- `Adapter` - A new adapter instance. +- **eventType** : `EventType` - The event type. +- **eventData** : `EventData[EventType]` - The event data. #### Example ```typescript title="AdapterBuilder.ts" -const adapterBuilder = new AdapterBuilder({ - new ReportAdapter(), -}); - -const adapter = adapterBuilder.build(ctx); +adapterBuilder.before( + ( + ctx: TrackContext, + eventType: keyof EventDataOption, + eventData: EventDataOption[keyof EventDataOption] + ) => { + //do something + } +); ``` -### `before` +### `transform` -The adapter hook function is executed before tracking an event. +The adapter hook function is executed to transform the event data before tracking. #### Props -- **event** : `EventData` - The event data. - -#### Returns - -- `EventData` - The modified event data. +- **eventType** : `EventType` - The event type. +- **fun** : `( + ctx: Context, + eventType: Key, + eventData: LeftEventData[Key] +) => AdapterReportData | Promise` - The transform function. #### Example ```typescript title="AdapterBuilder.ts" -const adapterBuilder = new AdapterBuilder({ - new ReportAdapter(), -}); - -adapterBuilder.before(event); +adapterBuilder + .transform( + 'addCart', + ( + ctx: TrackContext, + eventType: 'addCart', + eventData: EventDataOption['addCart'] + ) => { + return { + ...eventData, + goodName: 'ac_' + eventData?.goodsName, + timeStamp: Date.now(), + }; + } + ) + .transform( + 'previewGoods', + ( + ctx: TrackContext, + eventType: 'previewGoods', + eventData: EventDataOption['previewGoods'] + ) => { + return { + ...eventData, + goodName: 'pg_' + eventData?.goodsName, + timeStamp: Date.now(), + }; + } + ); ``` -### `transform` +### `after` -The adapter hook function is executed to transform the event data before tracking. +The adapter hook function is executed after report an event. #### Props -- **event** : `EventData` - The event data. +- **ctx** : `Context` - The track context. +- **eventType** : `EventType` - The event type. +- **reportData** : `any` - The report data. + +#### Example + +```typescript title="AdapterBuilder.ts" +adapterBuilder.after( + ( + ctx: TrackContext, + eventType: keyof EventDataOption, + eventData: EventDataOption[keyof EventDataOption] + ) => { + //do something + } +); +``` + +### `build` + +Builds a adapter instance. #### Returns -- `EventData` - The modified event data. +- `Adapter` - Adapter instance. #### Example ```typescript title="AdapterBuilder.ts" -const adapterBuilder = new AdapterBuilder({ - new ReportAdapter(), -}); - -adapterBuilder.transform(event); +const adapter = adapterBuilder.build(); ``` - -### `after` diff --git a/website/docs/api/track-builder.md b/website/docs/api/track-builder.md index ffc013b..16a7950 100644 --- a/website/docs/api/track-builder.md +++ b/website/docs/api/track-builder.md @@ -3,47 +3,114 @@ The `TrackBuilder` class is used to create a track from a list of waypoints. The waypoints are used to create a track that can be used to generate a path for a vehicle to follow. ```typescript title="Signature" - +class TrackBuilder< + Context extends TrackContext, + EventData extends TrackEventDataBase, +> { + constructor(options: TrackCreateOptions = {}); +} ``` ## Hooks -### `before` +### `init` + +#### Props + +- `options` - The options to create the track. -`Function` +#### Example + +```typescript title="TrackBuilder.ts" +// method 1 +trackBuilder.init({ reportAdapter: adapter, consoleAdapter: adapter }); +// method 2 +trackBuilder.init(() => { + return { reportAdapter: adapter, consoleAdapter: adapter }; +}); +``` + +### `before` #### Props -#### Returns +- **ctx** : `Context` - The track context. #### Example -### `after` +```typescript title="TrackBuilder.ts" +trackBuilder.before(async (ctx: TrackContext) => { + // do something +}); +``` -`Function` +### `after` #### Props -#### Returns +- **ctx** : `Context` - The track context. #### Example -### `select` +```typescript title="TrackBuilder.ts" +trackBuilder.after(async (ctx: TrackContext) => { + // do something +}); +``` -`Function` +### `select` #### Props -#### Returns +- **ctx** : `Context` - The track context. +- **adapterMap** : `Record>` - The adapter map. #### Example -### `track` +```typescript title="TrackBuilder.ts" +// method 1 +trackBuilder.select(['consoleAdapter', 'reportAdapter']); +// method 2 +trackBuilder.select( + ( + ctx: TrackContext, + adapterMap: { + reportAdapter: ReportAdapter; + consoleAdapter: ReportAdapter; + } + ) => ['consoleAdapter', 'reportAdapter'] +); +// method 3 +trackBuilder.select( + ( + ctx: TrackContext, + adapterMap: { + reportAdapter: ReportAdapter; + consoleAdapter: ReportAdapter; + } + ) => Promise.resolve(['consoleAdapter', 'reportAdapter']) +); +``` -`Function` +### `track` #### Props -#### Returns +- **eventType** : `addCart` - The event type. +- **eventData** : `{ + price: 99.99, + goodsId: 'g123', + goodsName: 'Sample Goods', + count: 2, +}` - The event data. #### Example + +```typescript title="TrackBuilder.ts" +trackBuilder.track('addCart', { + price: 99.99, + goodsId: 'g123', + goodsName: 'Sample Goods', + count: 2, +}); +``` diff --git a/website/src/pages/index.tsx b/website/src/pages/index.tsx index 89aa50c..a7467e5 100644 --- a/website/src/pages/index.tsx +++ b/website/src/pages/index.tsx @@ -5,7 +5,6 @@ import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import { CheckIcon } from '@heroicons/react/24/outline'; import { DocumentDuplicateIcon } from '@heroicons/react/24/outline'; -import DynamicCoding from '@site/src/components/Amimate/DynamicCoding'; import HomepageFeatures from '@site/src/components/HomepageFeatures'; import LogoDark from '@site/static/img/logo-dark.svg'; import LogoWhite from '@site/static/img/logo-white.svg'; @@ -106,10 +105,6 @@ export default function Home() { >
-
-
Sample Usage
- -
From cb4896cee2c327583b982302b7b57a1b07fbf893 Mon Sep 17 00:00:00 2001 From: "shunquan.wang" Date: Tue, 13 Aug 2024 22:14:35 +0800 Subject: [PATCH 08/28] docs: perfect docs --- tests/test-track-docs.spec.ts | 3 ++- website/docs/api/adapter-builder.md | 22 +++++++++++----------- website/docs/api/base-adapter.md | 8 ++++---- website/docs/api/track-builder.md | 6 +++--- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/tests/test-track-docs.spec.ts b/tests/test-track-docs.spec.ts index 02370da..59f515e 100644 --- a/tests/test-track-docs.spec.ts +++ b/tests/test-track-docs.spec.ts @@ -1,5 +1,6 @@ import { createAdapterBuilder } from '../src/adapter/create-adapter-builder.js'; import { createTrackBuilder } from '../src/core/create-track-builder.js'; +import { AdapterReportData } from '../src/types/types-adapter.js'; import { TrackContext } from '../src/types/types-create.js'; import { ReportAdapter } from './test-utils/adapter/report-adapter.js'; import { AdapterOptions } from './test-utils/types/type-adapter-options.js'; @@ -98,7 +99,7 @@ describe('test-track-pipeline.spec', () => { ( ctx: TrackContext, eventType: keyof EventDataOption, - eventData: EventDataOption[keyof EventDataOption] + reportData: AdapterReportData ) => { //do something } diff --git a/website/docs/api/adapter-builder.md b/website/docs/api/adapter-builder.md index c761589..733b789 100644 --- a/website/docs/api/adapter-builder.md +++ b/website/docs/api/adapter-builder.md @@ -20,9 +20,9 @@ The setup data. It is often useful to extend the report method by configuring so #### Props -- **ctx** : `Context` - The track context. -- **eventType** : `EventType` - The event type. -- **eventData** : `EventData[EventType]` - The event data. +- **ctx** : `TrackContext` - The track context. +- **eventType** : `keyof EventDataOption` - The event type. +- **eventData** : `EventDataOption[keyof EventDataOption]` - The event data. #### Example @@ -47,9 +47,9 @@ The adapter hook function is executed before tracking an event. #### Props -- **ctx** : `Context` - The track context. -- **eventType** : `EventType` - The event type. -- **eventData** : `EventData[EventType]` - The event data. +- **ctx** : `TrackContext` - The track context. +- **eventType** : `keyof EventDataOption` - The event type. +- **eventData** : `EventDataOption[keyof EventDataOption]` - The event data. #### Example @@ -71,7 +71,7 @@ The adapter hook function is executed to transform the event data before trackin #### Props -- **eventType** : `EventType` - The event type. +- **eventType** : `keyof EventDataOption` - The event type. - **fun** : `( ctx: Context, eventType: Key, @@ -118,9 +118,9 @@ The adapter hook function is executed after report an event. #### Props -- **ctx** : `Context` - The track context. -- **eventType** : `EventType` - The event type. -- **reportData** : `any` - The report data. +- **ctx** : `TrackContext` - The track context. +- **eventType** : `keyof EventDataOption` - The event type. +- **reportData** : `AdapterReportData` - The report data. #### Example @@ -129,7 +129,7 @@ adapterBuilder.after( ( ctx: TrackContext, eventType: keyof EventDataOption, - eventData: EventDataOption[keyof EventDataOption] + reportData: AdapterReportData ) => { //do something } diff --git a/website/docs/api/base-adapter.md b/website/docs/api/base-adapter.md index 4b4bf80..c5072fa 100644 --- a/website/docs/api/base-adapter.md +++ b/website/docs/api/base-adapter.md @@ -32,9 +32,9 @@ Checks if the adapter is available. #### Props -- **ctx** : `Context` - The track context. -- **eventType** : `EventType` - The type of the event. -- **eventData** : `EventData[EventType]` - The data associated with the event. +- **ctx** : `TrackContext` - The track context. +- **eventType** : `keyof EventDataOption` - The event type. +- **eventData** : `EventData[keyof EventDataOption]` - The data associated with the event. #### Returns @@ -66,7 +66,7 @@ Reports the event to the adapter. #### Props -- **ctx** : `Context` - The track context. +- **ctx** : `TrackContext` - The track context. - **reportData** : `AdapterReportData` - The data to report. - **setupData** : `Required['setup'] extends (...args: any) => any ? Awaited['setup']> : undefined` - The setup data. It is often useful to extend the report method by configuring some additional data to be used in the report phase without the transform processing diff --git a/website/docs/api/track-builder.md b/website/docs/api/track-builder.md index 16a7950..1ee0bbe 100644 --- a/website/docs/api/track-builder.md +++ b/website/docs/api/track-builder.md @@ -34,7 +34,7 @@ trackBuilder.init(() => { #### Props -- **ctx** : `Context` - The track context. +- **ctx** : `TrackContext` - The track context. #### Example @@ -48,7 +48,7 @@ trackBuilder.before(async (ctx: TrackContext) => { #### Props -- **ctx** : `Context` - The track context. +- **ctx** : `TrackContext` - The track context. #### Example @@ -62,7 +62,7 @@ trackBuilder.after(async (ctx: TrackContext) => { #### Props -- **ctx** : `Context` - The track context. +- **ctx** : `TrackContext` - The track context. - **adapterMap** : `Record>` - The adapter map. #### Example From 8994a8408a9fab0e072806e214e97c949c4dd7d2 Mon Sep 17 00:00:00 2001 From: "shunquan.wang" Date: Tue, 13 Aug 2024 22:21:53 +0800 Subject: [PATCH 09/28] docs: update docs --- website/docs/api/base-adapter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/api/base-adapter.md b/website/docs/api/base-adapter.md index c5072fa..9ce7596 100644 --- a/website/docs/api/base-adapter.md +++ b/website/docs/api/base-adapter.md @@ -62,7 +62,7 @@ export class ReportAdapter extends BaseAdapter< `protected Function` -Reports the event to the adapter. +Method of reporting data to a third party, where the converted data can be obtained #### Props From 24298b98bc3ef3f9586cf332288b09842c6e6628 Mon Sep 17 00:00:00 2001 From: "shunquan.wang" Date: Mon, 19 Aug 2024 22:00:26 +0800 Subject: [PATCH 10/28] feat: prefect docs --- tests/test-track-docs.spec.ts | 142 ------------ tests/website-source/index.tsx | 33 +++ tests/website-source/report-adapter.ts | 32 +++ tests/website-source/track.ts | 60 +++++ tests/website-source/types.ts | 33 +++ website/.DS_Store | Bin 0 -> 6148 bytes website/docs/api/adapter-builder.md | 91 +++++--- website/docs/api/base-adapter.md | 71 ++++-- website/docs/api/track-builder.md | 64 ++++-- website/docs/community/contributing.md | 145 +++++++++++- website/docs/intro.md | 138 ------------ website/docs/intro/installation.md | 23 ++ website/docs/intro/introducing.md | 54 +++++ website/docs/intro/live-example.md | 21 ++ website/docs/intro/sample-example.md | 186 ++++++++++++++++ website/docusaurus.config.ts | 62 ++++-- website/package.json | 1 + website/sidebars.ts | 29 ++- .../src/components/Amimate/DynamicCoding.tsx | 37 ++-- .../src/components/Amimate/styles.module.css | 4 + .../src/components/HomepageFeatures/index.tsx | 151 ++++++++++--- website/src/components/PreviewUML/index.tsx | 24 ++ website/src/components/Stackblitz/index.tsx | 2 +- website/src/pages/index.module.css | 114 +++++++++- website/src/pages/index.tsx | 15 +- website/static/img/bars.svg | 1 + website/static/img/browser.svg | 1 + website/static/img/lightbulb.svg | 3 + website/static/img/logo.svg | 208 +----------------- website/static/img/muscle.svg | 1 + website/static/img/puzzle.svg | 1 + website/static/img/shield.svg | 4 + website/static/img/uml-dark.png | Bin 0 -> 124573 bytes website/static/img/uml-light.png | Bin 0 -> 119626 bytes website/static/media/code.mp4 | Bin 0 -> 10960713 bytes yarn.lock | 195 +++++++++++++++- 36 files changed, 1322 insertions(+), 624 deletions(-) delete mode 100644 tests/test-track-docs.spec.ts create mode 100644 tests/website-source/index.tsx create mode 100644 tests/website-source/report-adapter.ts create mode 100644 tests/website-source/track.ts create mode 100644 tests/website-source/types.ts create mode 100644 website/.DS_Store delete mode 100644 website/docs/intro.md create mode 100644 website/docs/intro/installation.md create mode 100644 website/docs/intro/introducing.md create mode 100644 website/docs/intro/live-example.md create mode 100644 website/docs/intro/sample-example.md create mode 100644 website/src/components/Amimate/styles.module.css create mode 100644 website/src/components/PreviewUML/index.tsx create mode 100644 website/static/img/bars.svg create mode 100644 website/static/img/browser.svg create mode 100644 website/static/img/lightbulb.svg create mode 100644 website/static/img/muscle.svg create mode 100644 website/static/img/puzzle.svg create mode 100644 website/static/img/shield.svg create mode 100644 website/static/img/uml-dark.png create mode 100644 website/static/img/uml-light.png create mode 100644 website/static/media/code.mp4 diff --git a/tests/test-track-docs.spec.ts b/tests/test-track-docs.spec.ts deleted file mode 100644 index 59f515e..0000000 --- a/tests/test-track-docs.spec.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { createAdapterBuilder } from '../src/adapter/create-adapter-builder.js'; -import { createTrackBuilder } from '../src/core/create-track-builder.js'; -import { AdapterReportData } from '../src/types/types-adapter.js'; -import { TrackContext } from '../src/types/types-create.js'; -import { ReportAdapter } from './test-utils/adapter/report-adapter.js'; -import { AdapterOptions } from './test-utils/types/type-adapter-options.js'; -import { EventDataOption } from './test-utils/types/type-event.js'; -import { TrackData } from './test-utils/types/type-track-data.js'; - -describe('test-track-pipeline.spec', () => { - const trackData: TrackData = { - bizMode: 'test', - env: 'prod', - platform: 'android', - ip: '0.0.0.0', - userId: 'uuid_10001', - }; - - const eventData: EventDataOption = { - registry: { - userName: 'testUser', - mobile: '1234567890', - pwd: 'password123', - email: 'testuser@example.com', - }, - previewGoods: { - goodsId: 'g123', - goodsName: 'Sample Goods', - }, - addCart: { - price: 99.99, - goodsId: 'g123', - goodsName: 'Sample Goods', - count: 2, - }, - timeStamp: '1000', - }; - - it('docs example', async () => { - const adapter = new ReportAdapter(); - - const adapterBuilder = createAdapterBuilder< - TrackContext, - EventDataOption, - AdapterOptions, EventDataOption> - >(adapter); - - adapterBuilder - .setup( - ( - ctx: TrackContext, - eventType: keyof EventDataOption, - eventData: EventDataOption[keyof EventDataOption] - ) => { - return Promise.resolve({ - name: 'setup', - timeStamp: Date.now(), - }); - } - ) - .before( - ( - ctx: TrackContext, - eventType: keyof EventDataOption, - eventData: EventDataOption[keyof EventDataOption] - ) => { - //do something - } - ) - .transform( - 'addCart', - ( - ctx: TrackContext, - eventType: 'addCart', - eventData: EventDataOption['addCart'] - ) => { - return { - ...eventData, - goodName: 'ac_' + eventData?.goodsName, - timeStamp: Date.now(), - }; - } - ) - .transform( - 'previewGoods', - ( - ctx: TrackContext, - eventType: 'previewGoods', - eventData: EventDataOption['previewGoods'] - ) => { - return { - ...eventData, - goodName: 'pg_' + eventData?.goodsName, - timeStamp: Date.now(), - }; - } - ) - .after( - ( - ctx: TrackContext, - eventType: keyof EventDataOption, - reportData: AdapterReportData - ) => { - //do something - } - ) - .build(); - - const trackBuilder = createTrackBuilder< - TrackContext, - EventDataOption - >(); - - await trackBuilder - .init(() => { - return { reportAdapter: adapter, consoleAdapter: adapter }; - }) - .before(async (ctx) => { - // do something - }) - .after(async (ctx) => { - // do something - }) - .select( - ( - ctx: TrackContext, - adapterMap: { - reportAdapter: ReportAdapter; - consoleAdapter: ReportAdapter; - } - ) => 'consoleAdapter' - ) - .track('addCart', { - price: 99.99, - goodsId: 'g123', - goodsName: 'Sample Goods', - count: 2, - }); - - expect(true).toBeTruthy(); - }); -}); diff --git a/tests/website-source/index.tsx b/tests/website-source/index.tsx new file mode 100644 index 0000000..e99352d --- /dev/null +++ b/tests/website-source/index.tsx @@ -0,0 +1,33 @@ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +//@ts-nocheck +import { reportTrack } from './track.js'; + +export const Index = () => { + const onAddToCart = async () => { + await reportTrack().select('reportAdapter').track('addCart', { + price: 25.99, + goodsId: '23432252', + goodsName: 'Long Chair', + count: 1, + }); + }; + return ( +
+
+
+
+
+
+ Long Chair +

ID: 23432252

+
+ $25.99 +
+ +
+
+
+ ); +}; diff --git a/tests/website-source/report-adapter.ts b/tests/website-source/report-adapter.ts new file mode 100644 index 0000000..805382c --- /dev/null +++ b/tests/website-source/report-adapter.ts @@ -0,0 +1,32 @@ +import { BaseAdapter } from '../../src/index.js'; +import { AdapterReportData } from '../../src/types/types-adapter.js'; +import { TrackContext } from '../../src/types/types-create.js'; +import { + ReportAdapterOptions, + ReportEventData, + ReportTrackData, +} from './types.js'; + +export class ReportAdapter extends BaseAdapter< + TrackContext, + ReportEventData, + ReportAdapterOptions, ReportEventData> +> { + isTrackable( + ctx: TrackContext, + eventType: EventType, + eventData: ReportEventData[EventType] + ): boolean | Promise { + return true; + } + + protected report( + ctx: TrackContext, + reportData: AdapterReportData, + setupData?: + | { name: 'setup' | 'setup2' | 'setup3'; timeStamp: number } + | undefined + ): void | Promise { + console.log('report', ctx, reportData, setupData); + } +} diff --git a/tests/website-source/track.ts b/tests/website-source/track.ts new file mode 100644 index 0000000..ceb5e58 --- /dev/null +++ b/tests/website-source/track.ts @@ -0,0 +1,60 @@ +import { createAdapterBuilder, createTrackBuilder } from '../../src/index.js'; +import { TrackContext } from '../../src/types/types-create.js'; +import { ReportAdapter } from './report-adapter.js'; +import { + ReportAdapterOptions, + ReportEventData, + ReportTrackData, +} from './types.js'; + +export const reportTrack = () => { + const reportAdapter = new ReportAdapter(); + + const adapterBuilder = createAdapterBuilder< + TrackContext, + ReportEventData, + ReportAdapterOptions, ReportEventData> + >(reportAdapter); + + const adapter = adapterBuilder + .setup(() => { + return Promise.resolve({ + name: 'setup', + timeStamp: Date.now(), + }); + }) + .before((ctx, eventType, eventData) => { + console.log('before', ctx, eventType, eventData); + }) + .transform('addCart', (ctx, eventType, eventData) => { + return { + ...eventData, + goodName: 'ac_' + eventData?.goodsName, + }; + }) + .transform('registry', (ctx, eventType, eventData) => { + return { ...eventData, userName: 'rg_' + eventData?.userName }; + }) + .after((ctx, eventType, reportData) => { + console.log('after', ctx, eventType, reportData); + }) + .build(); + + const trackBuilder = createTrackBuilder< + TrackContext, + ReportEventData + >(); + + return trackBuilder + .init(() => { + return { + reportAdapter: adapter, + }; + }) + .before((ctx) => { + console.log('before track', ctx); + }) + .after((ctx) => { + console.log('after track', ctx); + }); +}; diff --git a/tests/website-source/types.ts b/tests/website-source/types.ts new file mode 100644 index 0000000..ef02436 --- /dev/null +++ b/tests/website-source/types.ts @@ -0,0 +1,33 @@ +export type ReportAdapterOptions = { + setup?: ( + ctx: Context, + eventTYpe: EventType, + eventData: EventData[EventType] + ) => Promise<{ + name: 'setup' | 'setup2' | 'setup3'; + timeStamp: number; + }>; +}; + +export type ReportTrackData = { + bizMode: 'test' | 'test2'; + env: 'prod' | 'uat'; + platform: 'android' | 'ios'; + ip: string; + userId: string; +}; + +export type ReportEventData = { + registry?: { + userName: string; + mobile: string; + pwd: string; + email: string; + }; + addCart?: { + price: number; + goodsId: string; + goodsName: string; + count: number; + }; +}; diff --git a/website/.DS_Store b/website/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0` + + The context in which the tracking is occurring. This typically includes details such as user information, environment, or other contextual data relevant to the tracking event. + +- **eventType** : `keyof EventData` -#### Props + The type of event being tracked. This is usually a key from the EventData that corresponds to specific events like click, purchase, etc. -- **ctx** : `TrackContext` - The track context. -- **eventType** : `keyof EventDataOption` - The event type. -- **eventData** : `EventDataOption[keyof EventDataOption]` - The event data. +- **eventData** : `EventData[keyof EventData]` + + The data associated with the event. This contains all relevant information for the specific event type. #### Example @@ -30,8 +40,8 @@ The setup data. It is often useful to extend the report method by configuring so adapterBuilder.setup( ( ctx: TrackContext, - eventType: keyof EventDataOption, - eventData: EventDataOption[keyof EventDataOption] + eventType: keyof EventData, + eventData: EventData[keyof EventData] ) => { return Promise.resolve({ name: 'setup', @@ -43,13 +53,21 @@ adapterBuilder.setup( ### `before` -The adapter hook function is executed before tracking an event. +The `before` hook is executed before tracking an event. This is where you can perform any necessary preprocessing or validation. + +#### Parameters + +- **ctx** : `TrackContext` + + The context in which the tracking is occurring. This typically includes details such as user information, environment, or other contextual data relevant to the tracking event. + +- **eventType** : `keyof EventData` -#### Props + The type of event being tracked. This is usually a key from the EventData that corresponds to specific events like click, purchase, etc. -- **ctx** : `TrackContext` - The track context. -- **eventType** : `keyof EventDataOption` - The event type. -- **eventData** : `EventDataOption[keyof EventDataOption]` - The event data. +- **eventData** : `EventData[keyof EventData]` + + The data associated with the event. This contains all relevant information for the specific event type. #### Example @@ -57,8 +75,8 @@ The adapter hook function is executed before tracking an event. adapterBuilder.before( ( ctx: TrackContext, - eventType: keyof EventDataOption, - eventData: EventDataOption[keyof EventDataOption] + eventType: keyof EventData, + eventData: EventData[keyof EventData] ) => { //do something } @@ -67,16 +85,21 @@ adapterBuilder.before( ### `transform` -The adapter hook function is executed to transform the event data before tracking. +The `transform` hook allows you to modify the event data before it is sent to the tracking system. You can use this hook to change, enrich, or sanitize the event data. + +#### Parameters + +- **eventType** : `keyof EventData` -#### Props + The type of event being tracked. This is usually a key from the EventData that corresponds to specific events like click, purchase, etc. -- **eventType** : `keyof EventDataOption` - The event type. - **fun** : `( ctx: Context, eventType: Key, eventData: LeftEventData[Key] -) => AdapterReportData | Promise` - The transform function. +) => AdapterReportData | Promise` + + The function to transform the event data. #### Example @@ -87,7 +110,7 @@ adapterBuilder ( ctx: TrackContext, eventType: 'addCart', - eventData: EventDataOption['addCart'] + eventData: EventData['addCart'] ) => { return { ...eventData, @@ -101,7 +124,7 @@ adapterBuilder ( ctx: TrackContext, eventType: 'previewGoods', - eventData: EventDataOption['previewGoods'] + eventData: EventData['previewGoods'] ) => { return { ...eventData, @@ -114,13 +137,21 @@ adapterBuilder ### `after` -The adapter hook function is executed after report an event. +The `after` hook is executed after the event has been reported. This is where you can perform any post-processing, such as logging or triggering additional actions based on the reported data. + +#### Parameters -#### Props +- **ctx** : `TrackContext` -- **ctx** : `TrackContext` - The track context. -- **eventType** : `keyof EventDataOption` - The event type. -- **reportData** : `AdapterReportData` - The report data. + The context in which the tracking is occurring. This typically includes details such as user information, environment, or other contextual data relevant to the tracking event. + +- **eventType** : `keyof EventData` + + The type of event being tracked. This is usually a key from the EventData that corresponds to specific events like click, purchase, etc. + +- **reportData** : `AdapterReportData` + + The data that needs to be reported. This can include the event type, associated data, and any additional metadata that should be sent to the third-party service. #### Example @@ -128,7 +159,7 @@ The adapter hook function is executed after report an event. adapterBuilder.after( ( ctx: TrackContext, - eventType: keyof EventDataOption, + eventType: keyof EventData, reportData: AdapterReportData ) => { //do something @@ -138,11 +169,13 @@ adapterBuilder.after( ### `build` -Builds a adapter instance. +The `build` method finalizes the adapter configuration and creates an instance of the adapter. #### Returns -- `Adapter` - Adapter instance. +- `Adapter` + + The configured adapter instance. #### Example diff --git a/website/docs/api/base-adapter.md b/website/docs/api/base-adapter.md index 9ce7596..3e53be8 100644 --- a/website/docs/api/base-adapter.md +++ b/website/docs/api/base-adapter.md @@ -1,6 +1,15 @@ # BaseAdapter -BaseAdapter is an abstract class that serves as the base for implementing track adapters. It provides common functionality and hooks for tracking events. +`BaseAdapter` is an abstract class that serves as the foundation for creating track adapters. It provides common functionality and hooks for tracking events, allowing you to extend and customize behavior for specific use cases. + +## Overview + +The `BaseAdapter` class defines two key methods: + +- isTrackable: This method checks if a particular event should be tracked. +- report: This method handles the reporting of event data to a third-party service or system. + +Both methods are meant to be extended in a concrete implementation of the `BaseAdapter` class. ```typescript title="Signature" export interface TrackAdapter< @@ -26,32 +35,40 @@ export interface TrackAdapter< ### `isTrackable` -`abstract Function` +`isTrackable` is an abstract method that checks whether a specific event should be tracked by the adapter. This method must be implemented in any subclass of `BaseAdapter`. + +#### Parameters + +- **ctx** : `TrackContext` + + The context in which the tracking is occurring. This typically includes details such as user information, environment, or other contextual data relevant to the tracking event. + +- **eventType** : `keyof EventData` -Checks if the adapter is available. + The type of event being tracked. This is usually a key from the EventData that corresponds to specific events like click, purchase, etc. -#### Props +- **eventData** : `EventData[keyof EventData]` -- **ctx** : `TrackContext` - The track context. -- **eventType** : `keyof EventDataOption` - The event type. -- **eventData** : `EventData[keyof EventDataOption]` - The data associated with the event. + The data associated with the event. This contains all relevant information for the specific event type. #### Returns -- `boolean | Promise` - A boolean indicating if the adapter is available. +- `boolean | Promise` - A boolean or a promise that resolves to a boolean, indicating whether the event should be tracked. `true` means the event is trackable, while `false` means it is not. #### Example +Here’s an example implementation of `isTrackable` that only tracks `addCart` events: + ```typescript title="ReportAdapter.ts" export class ReportAdapter extends BaseAdapter< TrackContext, - EventDataOption, - AdapterOptions, EventDataOption> + EventData, + AdapterOptions, EventData> > { - isTrackable( + isTrackable( ctx: TrackContext, eventType: EventType, - eventData: EventDataOption[EventType] + eventData: EventData[EventType] ): boolean | Promise { return eventType === 'addCart'; } @@ -60,32 +77,42 @@ export class ReportAdapter extends BaseAdapter< ### `report` -`protected Function` +`report` is a protected method used to send event data to an external system or service. This method can be overridden in a subclass to customize the reporting process, such as transforming the data or adding additional logic before the report is sent. + +#### Parameters + +- **ctx** : `TrackContext` -Method of reporting data to a third party, where the converted data can be obtained + The context in which the tracking is occurring. This typically includes details such as user information, environment, or other contextual data relevant to the tracking event. -#### Props +- **reportData** : `AdapterReportData` -- **ctx** : `TrackContext` - The track context. -- **reportData** : `AdapterReportData` - The data to report. -- **setupData** : `Required['setup'] extends (...args: any) => any ? Awaited['setup']> : undefined` - The setup data. It is often useful to extend the report method by configuring some additional data to be used in the report phase without the transform processing + The data that needs to be reported. This can include the event type, associated data, and any additional metadata that should be sent to the third-party service. + +- **setupData** : `Required['setup'] extends (...args: any) => any ? Awaited['setup']> : undefined` (Optional) + + The setup data, which may include configurations or preliminary data used during the report phase. This allows for additional data processing or setup before the reporting occurs. #### Returns -- `void | Promise` - A void or a promise that resolves to void. +- `void | Promise` + + This method can either return `void` or a `Promise` that resolves to `void`, depending on whether the reporting process is asynchronous. #### Example +Here’s an example implementation of the report method: + ```typescript title="ReportAdapter.ts" export class ReportAdapter extends BaseAdapter< TrackContext, - EventDataOption, - AdapterOptions, EventDataOption> + EventData, + AdapterOptions, EventData> > { report( ctx: TrackContext, reportData: AdapterReportData, - setupData?: Awaited, EventDataOption>['setup']> + setupData?: Awaited, EventData>['setup']> ): void | Promise { // do something } diff --git a/website/docs/api/track-builder.md b/website/docs/api/track-builder.md index 1ee0bbe..e45521d 100644 --- a/website/docs/api/track-builder.md +++ b/website/docs/api/track-builder.md @@ -1,6 +1,15 @@ # TrackBuilder -The `TrackBuilder` class is used to create a track from a list of waypoints. The waypoints are used to create a track that can be used to generate a path for a vehicle to follow. +The `TrackBuilder` class is designed to create a track from a series of waypoints. It provides a structured way to generate a path for a vehicle or an event tracking system to follow. This class includes hooks that allow you to customize the behavior of the track creation process. + +## Overview + +The `TrackBuilder` class allows you to define and customize the process of building a track by: + +- Initializing the track with specific options. +- Adding hooks to execute custom logic before and after certain stages of the track building. +- Selecting specific adapters for tracking events. +- Tracking events with custom data. ```typescript title="Signature" class TrackBuilder< @@ -11,13 +20,23 @@ class TrackBuilder< } ``` +### Constructor + +- options: `TrackCreateOptions` (Optional) + + The options used to create the track. These options typically include configurations for the tracking adapters, context, and other relevant settings. + ## Hooks ### `init` -#### Props +The `init` method is used to initialize the track builder with specific options, such as which adapters to use for reporting and console output. -- `options` - The options to create the track. +#### Parameters + +- options: `TrackCreateOptions` + + An object containing the initialization options for the track. This typically includes the adapters and other configurations necessary to build the track. #### Example @@ -32,9 +51,13 @@ trackBuilder.init(() => { ### `before` +The `before` method is a hook that allows you to execute custom logic before the track building process begins. This can be used for tasks such as preprocessing, validation, or logging. + #### Props -- **ctx** : `TrackContext` - The track context. +- **ctx** : `TrackContext` + + The context in which the tracking is occurring. This typically includes details such as user information, environment, or other contextual data relevant to the tracking event. #### Example @@ -46,9 +69,13 @@ trackBuilder.before(async (ctx: TrackContext) => { ### `after` +The `after` method is a hook that allows you to execute custom logic after the track building process is completed. This can be used for tasks such as cleanup, final validation, or post-processing. + #### Props -- **ctx** : `TrackContext` - The track context. +- **ctx** : `TrackContext` + + The context in which the tracking is occurring. This typically includes details such as user information, environment, or other contextual data relevant to the tracking event. #### Example @@ -60,10 +87,17 @@ trackBuilder.after(async (ctx: TrackContext) => { ### `select` +The `select` method is used to choose which adapters should be used during the track creation process. This allows for dynamic selection based on the context or specific conditions. + #### Props -- **ctx** : `TrackContext` - The track context. -- **adapterMap** : `Record>` - The adapter map. +- **ctx** : `TrackContext` + + The context in which the tracking is occurring. This typically includes details such as user information, environment, or other contextual data relevant to the tracking event. + +- **adapterMap** : `Record>` + + A map of available adapters, where the key is the adapter name and the value is the adapter instance. #### Example @@ -94,15 +128,17 @@ trackBuilder.select( ### `track` +The `track` method is used to track an event by specifying the event type and associated event data. This method triggers the tracking process, using the previously selected adapters. + #### Props -- **eventType** : `addCart` - The event type. -- **eventData** : `{ - price: 99.99, - goodsId: 'g123', - goodsName: 'Sample Goods', - count: 2, -}` - The event data. +- **eventType** : `addCart` + + The type of event being tracked. This is usually a key from the EventData that corresponds to specific events like click, purchase, etc. + +- **eventData** : `EventData[keyof EventData]` + + An object containing the data associated with the event. This data usually includes information such as item details, pricing, quantity, and other relevant attributes. #### Example diff --git a/website/docs/community/contributing.md b/website/docs/community/contributing.md index e3c5a93..5251f1a 100644 --- a/website/docs/community/contributing.md +++ b/website/docs/community/contributing.md @@ -1,5 +1,144 @@ -# contributing +## All contributions are welcome! -All contributions are welcome! +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; -Please take a moment to review guidelines [PR](https://github.com/hyperse-io/track/pulls) | [Issues](https://github.com/hyperse-io/track/issues) +:::info + +Thank you for your interest in contributing to our documentation site! We appreciate your support and value the insights and expertise of our community. This page outlines the guidelines and process for contributing, as well as the rewards you can earn for your efforts. + +::: + +We welcome contributions in a variety of forms, including but not limited to: + +1. Pointing out a mistake/typo and (optionally) providing a solution +2. Providing translation +3. Creating or improving diagrams, charts, or visual aids +4. Suggesting improvements to the documentation structure or organization +5. Writing or updating a tutorial or guide +6. Creating or updating code samples, examples, or demos +7. Polishing or improving document writing + +To make a contribution, please take one of the following actions: + +- **Report an Issue**: If you spot a problem or is willing to suggest improvements, [create an issue](https://github.com/hyperse-io/track/issues/new/choose) to let us know. +- **Submit Changes**: For direct contributions to content, [create a pull request](https://github.com/hyperse-io/track/compare). + +## Create an Issue + +You can create an issue for the following purposes: + +- To report any mistakes or typos. +- To request new content or improvements to current content. + +You can typically create an issue directly through the [GitHub web page](https://github.com/hyperse-io/track/issues/new/choose). Here, you'll find various templates to guide your issue submission. + +If you're able to address the issue yourself, we encourage you to take the initiative. When creating an issue, you can indicate your willingness to resolve it. For bug reports, select the option “I'd be willing to fix this issue myself” in the BUG template. For feature requests, select “I'd be willing to contribute this feature myself” in the Feature Request template. + + + + +**Describe the bug** + +A clear and concise description of what the bug is. + +**To Reproduce** + +Steps to reproduce the behavior: + +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** + +A clear and concise description of what you expected to happen. + +**Environment (please complete the following information):** + +- @hyperse/track version: +- Nodejs version + +**Additional context** + +Add any other context about the problem here. + + + +**Is your feature request related to a problem? Please describe.** + +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** + +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** + +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** + +Add any other context or screenshots about the feature request here. + + + + +## Create a Pull Request + +Contributing to projects through a pull request (PR) is a valuable way to improve existing documentation or code. This guide will walk you through the process step by step, ensuring clarity and ease of understanding, especially for those new to GitHub and git operations. + +For complex operations, you can also check the [closed pull requests](https://github.com/hyperse-io/track/pulls?q=is%3Apr+is%3Aclosed) for grammar reference. For example, + +- [Added Ecosystem Page + Video](https://github.com/hyperse-io/track/pull/392) shows how to add an article with video reference. +- [feat: template example](https://github.com/hyperse-io/track/pull/410) shows how to make use of mdx's feature to create similar pages using template. + +:::note + +This process does not apply to [TRANSLATIONS](#provide-translation). + +::: + +### Local Development for Substantial Changes + +:::tip + +Refer to [Github's tutorial](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project) if you are not familiar with git or Github operations. + +::: + +For more significant contributions like adding a new page or extensive revisions: + +1. Setting Up: + + - Ensure you have [node.js](https://nodejs.org/en) (version `>= 18`) and [yarn](https://yarnpkg.com/getting-started/install) installed. + - Fork and clone the [hyperse-io/track](https://github.com/hyperse-io/track)repository. Detailed instructions for forking and cloning are available on GitHub's help pages. + +2. Making Changes Locally: + +- Run `yarn` in your terminal to preview the project. +- Complete the place you need to change and provide the corresponding UT. +- Run `yarn test` command to check whether the function is complete. +- Navigate to the `website/**` folder and complete documentation for new features. + +3. Submitting Your Changes: + +- After making changes, run `npx changeset add` to improve the changelog. +- Commit your changes with a meaningful message, then push to your forked repository. Initiate a pull request on GitHub by comparing your branch to the original repository. + +### Working on an Existing Issue + +To avoid overlapping efforts and streamline contributions, it is suggested to follow these steps: + +1. Check for Accepted Issues: + +- Look for issues labeled "ACCEPTED" or similarly indicating readiness for contributions. If unsure, ask in the issue comments. + +2. Announce Your Intentions: + +- Comment on the issue stating that you are working on it. This helps prevent duplicate efforts. + +3. (Optional)Link Your Contributions: + +- When committing your changes, reference the issue number in your commit message, e.g., `fix: typo. Ref #123456`. diff --git a/website/docs/intro.md b/website/docs/intro.md deleted file mode 100644 index 4e1f1e2..0000000 --- a/website/docs/intro.md +++ /dev/null @@ -1,138 +0,0 @@ ---- -sidebar_position: 1 -slug: /getting-started ---- - -# Getting Started - -## Install - -```bash -npm install @hyperse/track --save -``` - -or you can use **yarn** - -```bash -yarn add @hyperse/track -``` - -We have completed installing the package. - -## Simple usage - -Here is a simple usage for using the component: - -```ts -export type Context = { - env: 'prod' | 'uat'; - platform: 'android' | 'ios'; - ip: string; - userId: string; -}; - -export type EventData = { - registry: { - userName: string; - mobile: string; - pwd: string; - email: string; - }; - addCart: { - price: number; - goodsId: string; - goodsName: string; - count: number; - }; -}; - -export type AdapterOptions = { - setup?: ( - ctx: Context, - eventData: EventData[keyof EventData] - ) => Promise<{ - name: 'setup' | 'setup1' | 'setup2'; - timeStamp: number; - }>; -}; - -// custom report adapter -export class ReportAdapter extends BaseAdapter< - TrackContext, - EventData, - AdapterOptions, EventData> -> { - isTrackable( - ctx: TrackContext, - eventType: EventType, - eventData: EventData[EventType] - ): boolean | Promise { - return true; - } - report( - ctx: TrackContext, - reportData: AdapterReportData, - setupData?: - | { - name: 'setup' | 'setup1' | 'setup2'; - timeStamp: number; - } - | undefined - ): void | Promise {} -} - -const reportAdapter = new ReportAdapter(); - -// create adapter builder -const adapterBuilder = createAdapterBuilder< - TrackContext, - EventData, - AdapterOptions, EventData> ->(reportAdapter); - -// mount adapter hook -adapterBuilder - .setup((ctx, eventData) => { - return Promise.resolve({ - name: 'setup' as const, - timeStamp: new Date().getTime(), - newField: 'newField', - }); - }) - .before(async (ctx, eventType, eventData) => { - console.log('before'); - }) - .transform('addCart', (ctx, eventType, eventData) => { - return { - ...eventData, - pay: { - payId: 'p123', - payName: 'Sample Pay', - payType: 'credit', - }, - timeStamp: '2024-09-01T00:00:00Z', - }; - }) - .after(async (ctx, eventType, eventData) => { - console.log('after', eventData); - }) - .build(); - -// create track builder -const trackBuilder = createTrackBuilder< - TrackContext, - EventDataOption ->(); - -// mount track hook -await trackBuilder - .init({ reportAdapter: reportAdapter }) - .before(async (ctx) => {}) - .after(async (ctx) => {}) - .select(() => ['reportAdapter']) - .track('addCart', eventData.addCart); -``` - -## Congratulations ! - -That's all, now let's deep dive into the [props](/docs/api-reference). diff --git a/website/docs/intro/installation.md b/website/docs/intro/installation.md new file mode 100644 index 0000000..d22cf11 --- /dev/null +++ b/website/docs/intro/installation.md @@ -0,0 +1,23 @@ +# Installation + +## Requirements + +- [Node.js](https://nodejs.org/en/) v18 or above, with support for even-numbered Node.js versions. + +## Install + +```bash +npm install @hyperse/track --save +``` + +or you can use **yarn** + +```bash +yarn add @hyperse/track +``` + +We have completed installing the package. + +## Congratulations ! + +That's all, now let's deep dive into the [props](/docs/api/base-adapter). diff --git a/website/docs/intro/introducing.md b/website/docs/intro/introducing.md new file mode 100644 index 0000000..a2cbc68 --- /dev/null +++ b/website/docs/intro/introducing.md @@ -0,0 +1,54 @@ +# Introducing Track + +import PreviewUML from '@site/src/components/PreviewUML'; + +## What is Track ? + +### Track: A Modern TypeScript Library for Data Collection + +**Track** is a sophisticated TypeScript library designed specifically for efficient and versatile data collection in web applications. With a focus on modern development practices, Track incorporates several powerful features, making it an ideal choice for developers seeking a reliable and scalable solution for front-end data tracking. + + + +### Key Features of Track + +1. **TypeScript-Based Development**: + + - **Track** is built using TypeScript, which provides strong typing and advanced development tools. This ensures that developers can catch errors during development, resulting in more reliable and maintainable code. + +2. **Strong Typing and Type Inference**: + + - Track fully supports TypeScript's type inference, allowing developers to benefit from strong typing without having to manually specify types everywhere. This reduces runtime errors and improves overall code stability. + +3. **Smart Data Collection**: + + - Track integrates intelligent data collection strategies that optimize the process based on user behavior and changing data. This ensures that the data collected is both accurate and timely, without overloading the front-end application. + +4. **Scalable Design**: + + - Whether you're working on a small project or a large-scale application, Track is designed to scale effortlessly. Its architecture supports the collection of vast amounts of data without compromising performance, making it suitable for applications of all sizes. + +5. **Powerful and Flexible**: + + - Track is equipped with a robust set of features that allow it to handle a wide variety of data sources. From DOM elements to user inputs and network requests, Track can collect and process data from multiple sources with ease. Its flexibility allows developers to customize collection parameters, such as frequency, format, and filtering rules, to meet specific application needs. + +6. **Front-End Focused**: + + - Designed with the front-end in mind, Track is lightweight and optimized for performance. It collects data efficiently without affecting the user experience, making it an excellent choice for modern web applications where performance is critical. + +7. **Easy Integration**: + - Track provides an intuitive API that seamlessly integrates with popular front-end frameworks like React, Vue, and Angular. This makes it easy to add data collection capabilities to existing projects without disrupting the current workflow. + +### Use Cases for Track + +- **User Behavior Analysis**: Track can be used to gather detailed information about how users interact with your web application. By tracking clicks, scrolls, form submissions, and other actions, you can gain insights into user behavior and optimize your application accordingly. + +- **Performance Monitoring**: Track allows you to monitor the performance of your web application in real-time. By collecting data on page load times, resource usage, and other metrics, you can quickly identify and address performance bottlenecks. + +- **A/B Testing**: With Track, you can easily implement A/B testing by collecting data from different versions of your web pages. This helps you make data-driven decisions by comparing how users interact with each version. + +- **Event Tracking**: Track makes it easy to set up custom event tracking in your application. Whether you need to monitor specific user actions or track conversions, Track provides the tools you need to capture and analyze the data. + +## Congratulations ! + +That's all, now let's deep dive into the [props](/docs/api/base-adapter). diff --git a/website/docs/intro/live-example.md b/website/docs/intro/live-example.md new file mode 100644 index 0000000..3baba30 --- /dev/null +++ b/website/docs/intro/live-example.md @@ -0,0 +1,21 @@ +# Example + +import Stackblitz from '../../src/components/Stackblitz'; + +## Live usage + +Below is the complete usage of the component, representing a real business scenario: + +--- + +:::info + +Read more in [**User guide > introducing**](/docs/intro/introducing) + +::: + + + +## Congratulations ! + +That's all, now let's deep dive into the [props](/docs/api/base-adapter). diff --git a/website/docs/intro/sample-example.md b/website/docs/intro/sample-example.md new file mode 100644 index 0000000..8798246 --- /dev/null +++ b/website/docs/intro/sample-example.md @@ -0,0 +1,186 @@ +# Example + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +## Simple usage + +Here is a simple usage for using the component: + +--- + +:::info + +Read more in [**User guide > introducing**](/docs/intro/introducing) + +::: + + + + + +```typescript title="track.ts" +export const reportTrack = () => { + const reportAdapter = new ReportAdapter(); + + const adapterBuilder = createAdapterBuilder< + TrackContext, + ReportEventData, + ReportAdapterOptions, ReportEventData> + >(reportAdapter); + + const adapter = adapterBuilder + .setup(() => { + return Promise.resolve({ + name: 'setup', + timeStamp: Date.now(), + }); + }) + .before((ctx, eventType, eventData) => { + console.log('before', ctx, eventType, eventData); + }) + .transform('addCart', (ctx, eventType, eventData) => { + return { + ...eventData, + goodName: 'ac_' + eventData?.goodsName, + }; + }) + .transform('registry', (ctx, eventType, eventData) => { + return { ...eventData, userName: 'rg_' + eventData?.userName }; + }) + .after((ctx, eventType, reportData) => { + console.log('after', ctx, eventType, reportData); + }) + .build(); + + const trackBuilder = createTrackBuilder< + TrackContext, + ReportEventData + >(); + + return trackBuilder + .init(() => { + return { + reportAdapter: adapter, + }; + }) + .before((ctx) => { + console.log('before track', ctx); + }) + .after((ctx) => { + console.log('after track', ctx); + }); +}; +``` + + + + +```typescript title="reportAdapter.ts" +export class ReportAdapter extends BaseAdapter< + TrackContext, + ReportEventData, + ReportAdapterOptions, ReportEventData> +> { + isTrackable( + ctx: TrackContext, + eventType: EventType, + eventData: ReportEventData[EventType] + ): boolean | Promise { + return true; + } + + protected report( + ctx: TrackContext, + reportData: AdapterReportData, + setupData?: + | { name: 'setup' | 'setup2' | 'setup3'; timeStamp: number } + | undefined + ): void | Promise { + console.log('report', ctx, reportData, setupData); + } +} +``` + + + + + +```typescript title="types.ts" +export type ReportAdapterOptions = { + setup?: ( + ctx: Context, + eventTYpe: EventType, + eventData: EventData[EventType] + ) => Promise<{ + name: 'setup' | 'setup2' | 'setup3'; + timeStamp: number; + }>; +}; + +export type ReportTrackData = { + bizMode: 'test' | 'test2'; + env: 'prod' | 'uat'; + platform: 'android' | 'ios'; + ip: string; + userId: string; +}; + +export type ReportEventData = { + registry?: { + userName: string; + mobile: string; + pwd: string; + email: string; + }; + addCart?: { + price: number; + goodsId: string; + goodsName: string; + count: number; + }; +}; +``` + + + + + +```typescript title="index.tsx" +export const Index = () => { + const onAddToCart = async () => { + await reportTrack().select('reportAdapter').track('addCart', { + price: 25.99, + goodsId: '23432252', + goodsName: 'Long Chair', + count: 1, + }); + }; + return ( +
+
+
+
+
+
+ Long Chair +

ID: 23432252

+
+ $25.99 +
+ +
+
+
+ ); +}; +``` + +
+
+ +## Congratulations ! + +That's all, now let's deep dive into the [props](/docs/api/base-adapter). diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index 1a2482b..7d02e37 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -11,7 +11,7 @@ const config: Config = { baseUrl: '/track', onBrokenLinks: 'throw', onBrokenMarkdownLinks: 'warn', - favicon: '/icon/favicon.ico', + favicon: '/icon/favicon.svg', organizationName: 'Hyperse', projectName: 'hyperse tracker', presets: [ @@ -47,7 +47,8 @@ const config: Config = { }, docs: { sidebar: { - hideable: true, + hideable: false, + autoCollapseCategories: true, }, }, navbar: { @@ -63,9 +64,14 @@ const config: Config = { items: [ { type: 'doc', - docId: 'intro', + docId: 'intro/introducing', position: 'left', - label: 'Documentation', + label: 'User Guide', + }, + { + href: 'https://www.npmjs.com/package/@hyperse/track', + label: 'NPM', + position: 'right', }, { href: 'https://github.com/hyperse-io/track', @@ -73,23 +79,49 @@ const config: Config = { position: 'right', }, { - href: 'https://www.npmjs.com/package/@hyperse/track', - label: 'NPM', + href: 'https://discord.com/invite/tj3ahjXXzM', + label: 'Discord', position: 'right', }, ], }, footer: { - style: 'dark', - logo: { - alt: 'Hyperse', - src: '/img/logo.svg', - height: 40, - style: { - borderRadius: '2px', + links: [ + { + title: 'Resources', + items: [ + { + label: 'hyperse', + href: 'https://www.hyperse.net/', + }, + { + label: 'hyperse blog', + href: 'https://www.hyperse.net/blog', + }, + { + label: 'hyperse devutils', + href: 'https://devutils.hyperse.net/', + }, + ], }, - href: 'https://github.com/hyperse-io', - }, + { + title: 'Community', + items: [ + { + label: 'Discord', + href: 'https://discord.com/invite/tj3ahjXXzM', + }, + { + label: 'Twitter', + href: 'https://x.com/hyperse_net', + }, + { + label: 'GitHub', + href: 'https://github.com/hyperse-io', + }, + ], + }, + ], copyright: `Copyright © ${new Date().getFullYear()} Hyperse`, }, algolia: { diff --git a/website/package.json b/website/package.json index 4799c42..6bffb9a 100644 --- a/website/package.json +++ b/website/package.json @@ -53,6 +53,7 @@ "@heroicons/react": "^2.1.5", "@mdx-js/react": "^3.0.1", "clsx": "^2.1.1", + "docusaurus-theme-search-typesense": "^0.20.0", "postcss": "^8.4.40", "prism-react-renderer": "^2.3.1", "react": "^18.3.1", diff --git a/website/sidebars.ts b/website/sidebars.ts index 1f5a17b..c97b3b8 100644 --- a/website/sidebars.ts +++ b/website/sidebars.ts @@ -14,13 +14,34 @@ const sidebars: SidebarsConfig = { // By default, Docusaurus generates a sidebar from the docs folder structure tutorialSidebar: [ { - type: 'doc', - id: 'intro', + type: 'category', label: 'Getting Started', + items: [ + { + type: 'doc', + id: 'intro/introducing', + label: 'Introducing', + }, + { + type: 'doc', + id: 'intro/installation', + label: 'Installation', + }, + { + type: 'doc', + id: 'intro/sample-example', + label: 'Sample Example', + }, + { + type: 'doc', + id: 'intro/live-example', + label: 'Live Example', + }, + ], }, { type: 'category', - label: 'API', + label: 'How-to Guides', items: [ { type: 'doc', @@ -41,7 +62,7 @@ const sidebars: SidebarsConfig = { }, { type: 'category', - label: 'Adapters', + label: 'Core Plugins', items: [ { type: 'doc', diff --git a/website/src/components/Amimate/DynamicCoding.tsx b/website/src/components/Amimate/DynamicCoding.tsx index d08f40d..2e5a869 100644 --- a/website/src/components/Amimate/DynamicCoding.tsx +++ b/website/src/components/Amimate/DynamicCoding.tsx @@ -1,8 +1,8 @@ -import React, { useEffect, useRef } from 'react'; +import React, { useEffect } from 'react'; +import clsx from 'clsx'; +import styles from './styles.module.css'; export default function DynamicCoding(): JSX.Element { - const preRef = useRef(null); - const [mounted, setMounted] = React.useState(false); useEffect(() => { @@ -16,19 +16,22 @@ export default function DynamicCoding(): JSX.Element { }, [mounted]); return ( -
-
-
-          
- -
coding
-
-
-
-
-
+
+ +
); } diff --git a/website/src/components/Amimate/styles.module.css b/website/src/components/Amimate/styles.module.css new file mode 100644 index 0000000..1bb37f6 --- /dev/null +++ b/website/src/components/Amimate/styles.module.css @@ -0,0 +1,4 @@ +.code_video { + box-shadow: rgba(239, 240, 241, 0.102) 0px 6px 43px; + border-radius: 1rem; +} diff --git a/website/src/components/HomepageFeatures/index.tsx b/website/src/components/HomepageFeatures/index.tsx index a56f21f..025405b 100644 --- a/website/src/components/HomepageFeatures/index.tsx +++ b/website/src/components/HomepageFeatures/index.tsx @@ -1,38 +1,124 @@ import React from 'react'; -import clsx from 'clsx'; -import mountain from '@site/static/img/undraw_docusaurus_mountain.svg'; -import react from '@site/static/img/undraw_docusaurus_react.svg'; -import tree from '@site/static/img/undraw_docusaurus_tree.svg'; +import bars from '@site/static/img/bars.svg'; +import browser from '@site/static/img/browser.svg'; +import lightbulb from '@site/static/img/lightbulb.svg'; +import muscle from '@site/static/img/muscle.svg'; +import puzzle from '@site/static/img/puzzle.svg'; +import shield from '@site/static/img/shield.svg'; import styles from './styles.module.css'; const FeatureList = [ { - title: 'Easy to Use', - Svg: mountain, + title: 'Typed', + Svg: shield, description: ( <> - Docusaurus was designed from the ground up to be easily installed and - used to get your website up and running quickly. +

+ Leveraging TypeScript's static type checking, Hyperse ensures that + most errors are caught during development, reducing runtime issues and + enhancing the robustness and stability of front-end code. +

+

+ The strong typing system also aids developers in faster code + completion, refactoring, and debugging, thereby increasing development + efficiency. +

), }, { - title: 'Focus on What Matters', - Svg: tree, + title: 'Smart', + Svg: lightbulb, description: ( <> - Docusaurus lets you focus on your docs, and we'll do the chores. Go - ahead and move your docs into the docs directory. +

+ Hyperse integrates intelligent data collection strategies that + automatically optimize the collection process based on user behavior, + data changes, and network conditions, ensuring real-time data accuracy + and timeliness. +

+

+ It supports dynamic configuration, allowing the adjustment of + collection strategies to meet performance needs across different + front-end scenarios. +

), }, { - title: 'Powered by React', - Svg: react, + title: 'Scalable', + Svg: bars, description: ( <> - Extend or customize your website layout by reusing React. Docusaurus can - be extended while reusing the same header and footer. +

+ Optimized for large-scale front-end data collection tasks, Hyperse + efficiently gathers necessary data whether in single-page applications + (SPA) or multi-page applications. +

+

+ Its modular design allows developers to extend and adjust collection + features as needed, ensuring scalability to accommodate future + requirements. +

+ + ), + }, + + { + title: 'Powerful', + Svg: muscle, + description: ( + <> +

+ Supports multiple data sources and formats, including browser APIs, + user inputs, DOM elements, and network requests, covering a wide range + of front-end data collection scenarios. +

+

+ Offers flexible configuration options, enabling developers to + customize collection frequency, data formats, filtering rules, and + more, catering to specific application needs. +

+

+ Integrated with basic data cleansing functionalities, ensuring the + collected data is accurate and consistent. +

+ + ), + }, + + { + title: 'Front-End Friendly', + Svg: browser, + description: ( + <> +

+ Designed with front-end performance and user experience in mind, + Hyperse collects data without significantly impacting page load times + or user interactions. +

+

+ Its lightweight design ensures smooth operation even on + resource-constrained mobile devices. +

+ + ), + }, + + { + title: 'Easy Integration', + Svg: puzzle, + description: ( + <> +

+ Provides an intuitive API that simplifies integration with existing + front-end frameworks and libraries such as React, Vue, and Angular. +

+

+ Supports real-time data transmission to backend systems or third-party + services via Webhooks or other front-end communication methods, + ensuring a smooth data flow. +

), }, @@ -40,28 +126,35 @@ const FeatureList = [ function Feature({ Svg, title, description }) { return ( -
-
- -
-
-

{title}

-

{description}

+
+
+

+ + {title} +

+
+
+ {description} +
+
-
+ +
+
+ ); } export default function HomepageFeatures() { return ( -
-
-
+
+
+
{FeatureList.map((props, idx) => ( ))}
-
-
+ +
); } diff --git a/website/src/components/PreviewUML/index.tsx b/website/src/components/PreviewUML/index.tsx new file mode 100644 index 0000000..e3b1fda --- /dev/null +++ b/website/src/components/PreviewUML/index.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import UmlImageUrlDark from '@site/static/img/uml-dark.png'; +import UmlImageUrlLight from '@site/static/img/uml-light.png'; + +export default function Index() { + return ( +
+ + +
+ ); +} diff --git a/website/src/components/Stackblitz/index.tsx b/website/src/components/Stackblitz/index.tsx index 943db85..de0d253 100644 --- a/website/src/components/Stackblitz/index.tsx +++ b/website/src/components/Stackblitz/index.tsx @@ -8,7 +8,7 @@ export default function Stackblitz(props: { id: string }) { minHeight: '500px', borderRadius: '8px', }} - src={`https://stackblitz.com/edit/${props.id}?ctl=1&embed=1`} + src={`https://stackblitz.com/edit/${props.id}?embed=1&theme=dark`} /> ); } diff --git a/website/src/pages/index.module.css b/website/src/pages/index.module.css index 98cf351..68b03f3 100644 --- a/website/src/pages/index.module.css +++ b/website/src/pages/index.module.css @@ -16,8 +16,116 @@ } .topBackground { - background: linear-gradient(180deg,hsla(0,0%,100%,.031) 0,rgba(102,117,127,.102)); - clip-path: polygon(100% 0,0 0,0 65%,1% 64.95%,2% 64.8%,3% 64.6%,4% 64.3%,5% 63.9%,6% 63.45%,7% 62.9%,8% 62.25%,9% 61.55%,10% 60.8%,11% 59.95%,12% 59.05%,13% 58.1%,14% 57.1%,15% 56.05%,16% 55%,17% 53.9%,18% 52.8%,19% 51.65%,20% 50.5%,21% 49.35%,22% 48.2%,23% 47.05%,24% 45.9%,25% 44.8%,26% 43.75%,27% 42.75%,28% 41.75%,29% 40.8%,30% 39.9%,31% 39.1%,32% 38.35%,33% 37.65%,34% 37.05%,35% 36.5%,36% 36.05%,37% 35.65%,38% 35.35%,39% 35.15%,40% 35.05%,41% 35%,42% 35.05%,43% 35.2%,44% 35.45%,45% 35.75%,46% 36.15%,47% 36.65%,48% 37.2%,49% 37.85%,50% 38.55%,51% 39.35%,52% 40.2%,53% 41.1%,54% 42.05%,55% 43.05%,56% 44.1%,57% 45.15%,58% 46.3%,59% 47.4%,60% 48.55%,61% 49.7%,62% 50.85%,63% 52%,64% 53.15%,65% 54.25%,66% 55.35%,67% 56.4%,68% 57.45%,69% 58.4%,70% 59.35%,71% 60.2%,72% 61.05%,73% 61.8%,74% 62.45%,75% 63.05%,76% 63.6%,77% 64.05%,78% 64.4%,79% 64.7%,80% 64.85%,81% 65%,82% 65%,83% 64.9%,84% 64.75%,85% 64.5%,86% 64.2%,87% 63.75%,88% 63.25%,89% 62.7%,90% 62.05%,91% 61.3%,92% 60.5%,93% 59.65%,94% 58.75%,95% 57.8%,96% 56.8%,97% 55.75%,98% 54.65%,99% 53.55%,100% 52.4%); + background: linear-gradient( + 180deg, + hsla(0, 0%, 100%, 0.031) 0, + rgba(102, 117, 127, 0.102) + ); + clip-path: polygon( + 100% 0, + 0 0, + 0 65%, + 1% 64.95%, + 2% 64.8%, + 3% 64.6%, + 4% 64.3%, + 5% 63.9%, + 6% 63.45%, + 7% 62.9%, + 8% 62.25%, + 9% 61.55%, + 10% 60.8%, + 11% 59.95%, + 12% 59.05%, + 13% 58.1%, + 14% 57.1%, + 15% 56.05%, + 16% 55%, + 17% 53.9%, + 18% 52.8%, + 19% 51.65%, + 20% 50.5%, + 21% 49.35%, + 22% 48.2%, + 23% 47.05%, + 24% 45.9%, + 25% 44.8%, + 26% 43.75%, + 27% 42.75%, + 28% 41.75%, + 29% 40.8%, + 30% 39.9%, + 31% 39.1%, + 32% 38.35%, + 33% 37.65%, + 34% 37.05%, + 35% 36.5%, + 36% 36.05%, + 37% 35.65%, + 38% 35.35%, + 39% 35.15%, + 40% 35.05%, + 41% 35%, + 42% 35.05%, + 43% 35.2%, + 44% 35.45%, + 45% 35.75%, + 46% 36.15%, + 47% 36.65%, + 48% 37.2%, + 49% 37.85%, + 50% 38.55%, + 51% 39.35%, + 52% 40.2%, + 53% 41.1%, + 54% 42.05%, + 55% 43.05%, + 56% 44.1%, + 57% 45.15%, + 58% 46.3%, + 59% 47.4%, + 60% 48.55%, + 61% 49.7%, + 62% 50.85%, + 63% 52%, + 64% 53.15%, + 65% 54.25%, + 66% 55.35%, + 67% 56.4%, + 68% 57.45%, + 69% 58.4%, + 70% 59.35%, + 71% 60.2%, + 72% 61.05%, + 73% 61.8%, + 74% 62.45%, + 75% 63.05%, + 76% 63.6%, + 77% 64.05%, + 78% 64.4%, + 79% 64.7%, + 80% 64.85%, + 81% 65%, + 82% 65%, + 83% 64.9%, + 84% 64.75%, + 85% 64.5%, + 86% 64.2%, + 87% 63.75%, + 88% 63.25%, + 89% 62.7%, + 90% 62.05%, + 91% 61.3%, + 92% 60.5%, + 93% 59.65%, + 94% 58.75%, + 95% 57.8%, + 96% 56.8%, + 97% 55.75%, + 98% 54.65%, + 99% 53.55%, + 100% 52.4% + ); left: 0; position: absolute; top: 0rem; @@ -27,4 +135,4 @@ ::-webkit-scrollbar { display: none; -} \ No newline at end of file +} diff --git a/website/src/pages/index.tsx b/website/src/pages/index.tsx index a7467e5..856ccaa 100644 --- a/website/src/pages/index.tsx +++ b/website/src/pages/index.tsx @@ -5,6 +5,7 @@ import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import { CheckIcon } from '@heroicons/react/24/outline'; import { DocumentDuplicateIcon } from '@heroicons/react/24/outline'; +import DynamicCoding from '@site/src/components/Amimate/DynamicCoding'; import HomepageFeatures from '@site/src/components/HomepageFeatures'; import LogoDark from '@site/static/img/logo-dark.svg'; import LogoWhite from '@site/static/img/logo-white.svg'; @@ -34,24 +35,24 @@ function HomepageHeader() {
Watch Get Started Donate
-
+
+
+
+ ); + })} ); } diff --git a/examples/next-example/app/service.ts b/examples/next-example/app/service.ts new file mode 100644 index 0000000..9c33cd6 --- /dev/null +++ b/examples/next-example/app/service.ts @@ -0,0 +1,20 @@ +import Mock from 'mockjs'; + +export interface GoodsRecord { + goodsName: string; + goodsId: string; + price: number; +} + +export const fetchGoodsList = (): GoodsRecord[] => { + const data = Mock.mock({ + 'list|10-20': [ + { + goodsName: '@cword(3,5)', + goodsId: '@id()', + price: '@float(10, 100, 2, 2)', + }, + ], + }); + return data.list; +}; diff --git a/examples/next-example/eslint.config.mjs b/examples/next-example/eslint.config.mjs index c9bf557..0df168d 100644 --- a/examples/next-example/eslint.config.mjs +++ b/examples/next-example/eslint.config.mjs @@ -1,7 +1,7 @@ -import { base, defineConfig } from '@hyperse/eslint-config-hyperse'; +import { defineConfig, nextjs } from '@hyperse/eslint-config-hyperse'; export default defineConfig([ - ...base, + ...nextjs, { rules: { '@typescript-eslint/no-explicit-any': 'off', diff --git a/examples/next-example/lint-staged.config.mjs b/examples/next-example/lint-staged.config.mjs deleted file mode 100644 index 136f4e7..0000000 --- a/examples/next-example/lint-staged.config.mjs +++ /dev/null @@ -1,28 +0,0 @@ -import { dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; -/** - * This is the base lint-staged rules config and just includes prettier by default. - * A good practice is to override this base configuration in each package and/or application - * where we are able to add customization depending on the nature of the project (eslint...). - */ -import { getEslintFixCmd } from '../lint-staged.common.mjs'; - -/** - * @type {Record string | string[] | Promise>} - */ -const rules = { - '**/*.{js,jsx,ts,tsx,mjs,cjs}': (filenames) => { - return getEslintFixCmd({ - cwd: dirname(fileURLToPath(import.meta.url)), - fix: true, - cache: true, - // when autofixing staged-files a good tip is to disable react-hooks/exhaustive-deps, cause - // a change here can potentially break things without proper visibility. - rules: [], - maxWarnings: 25, - files: filenames, - }); - }, -}; - -export default rules; diff --git a/examples/next-example/next.config.js b/examples/next-example/next.config.js deleted file mode 100644 index 35f01bb..0000000 --- a/examples/next-example/next.config.js +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = {}; - -export default nextConfig diff --git a/examples/next-example/next.config.mjs b/examples/next-example/next.config.mjs new file mode 100644 index 0000000..3732864 --- /dev/null +++ b/examples/next-example/next.config.mjs @@ -0,0 +1,11 @@ +/** + * Don't be scared of the generics here. + * All they do is to give us autocompletion when using this. + * @type {import("next").NextConfig} + */ +export default { + reactStrictMode: true, + eslint: { + ignoreDuringBuilds: true, + }, +}; diff --git a/examples/next-example/package.json b/examples/next-example/package.json index 98f143f..d9a2117 100644 --- a/examples/next-example/package.json +++ b/examples/next-example/package.json @@ -1,13 +1,15 @@ { - "name": "next-example", - "version": "0.1.0", + "name": "@hyperse/track-next-example", + "version": "1.0.0", "private": true, "type": "module", "scripts": { "dev": "next dev -p 3001", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "eslint .", + "lint-fix": "yarn lint --fix", + "lint-staged-files": "lint-staged --allow-empty" }, "repository": { "type": "git", @@ -19,12 +21,13 @@ } }, "dependencies": { + "@hyperse/track": "latest", "@types/node": "20.6.2", "@types/react": "18.2.22", "@types/react-dom": "18.2.7", "autoprefixer": "10.4.15", - "eslint": "8.49.0", - "eslint-config-next": "13.5.1", + "eslint": "^9.8.0", + "eslint-config-next": "14.2.5", "next": "14.2.5", "postcss": "8.4.30", "react": "18.2.0", @@ -33,6 +36,8 @@ "typescript": "5.2.2" }, "devDependencies": { - "@hyperse/eslint-config-hyperse": "1.1.3" + "@hyperse/eslint-config-hyperse": "1.1.3", + "@types/mockjs": "^1", + "mockjs": "^1.1.0" } } diff --git a/examples/next-example/tailwind.config.cjs b/examples/next-example/tailwind.config.cjs index 7a509de..3634037 100644 --- a/examples/next-example/tailwind.config.cjs +++ b/examples/next-example/tailwind.config.cjs @@ -5,9 +5,7 @@ module.exports = { // Avoid conflicts with antd preflight: false, }, - content: [ - './app/**/*.{js,tsx,md,mdx}', - ], + content: ['./app/**/*.{js,tsx,md,mdx}'], theme: { extend: {}, }, diff --git a/examples/next-example/track/report-adapter.ts b/examples/next-example/track/report-adapter.ts new file mode 100644 index 0000000..e69de29 diff --git a/examples/next-example/track/track.ts b/examples/next-example/track/track.ts new file mode 100644 index 0000000..7696e41 --- /dev/null +++ b/examples/next-example/track/track.ts @@ -0,0 +1 @@ +export const reportTrack = () => {}; diff --git a/examples/next-example/track/types.ts b/examples/next-example/track/types.ts new file mode 100644 index 0000000..8537556 --- /dev/null +++ b/examples/next-example/track/types.ts @@ -0,0 +1,30 @@ +export type ReportAdapterOptions = { + setup?: ( + ctx: Context, + eventTYpe: EventType, + eventData: EventData[EventType] + ) => Promise<{ + timeStamp: number; + }>; +}; + +export type ReportTrackData = { + env: 'prod' | 'uat'; + platform: 'android' | 'ios'; + ip: string; +}; + +export type ReportEventData = { + pv?: { + url: string; + timeStamp: number; + userName: string; + userId: string; + }; + addCart?: { + price: number; + goodsId: string; + goodsName: string; + count: number; + }; +}; diff --git a/examples/next-example/tsconfig.json b/examples/next-example/tsconfig.json index 84824ec..1acc222 100644 --- a/examples/next-example/tsconfig.json +++ b/examples/next-example/tsconfig.json @@ -1,6 +1,5 @@ { "compilerOptions": { - "baseUrl": "./", "target": "es5", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, diff --git a/package.json b/package.json index c60a734..cef03e8 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ ], "workspaces": [ "website", - "examples/next-example", + "examples/*", "./" ], "scripts": { diff --git a/src/helpers/index.ts b/src/helpers/index.ts index 5a7004d..3d68b0d 100644 --- a/src/helpers/index.ts +++ b/src/helpers/index.ts @@ -1,3 +1,4 @@ +export * from './helper-adapter-ctx.js'; export * from './helper-adapter-track.js'; export * from './helper-deep-clone.js'; export * from './helper-deep-merge.js'; diff --git a/src/types/index.ts b/src/types/index.ts index c4c6bed..efa0123 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1 +1,5 @@ +export * from './type-union-tuple.js'; +export * from './types-adapter.js'; +export * from './types-create.js'; +export * from './types-logger.js'; export * from './types-track.js'; diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts index 030e563..c2b9cf7 100644 --- a/website/docusaurus.config.ts +++ b/website/docusaurus.config.ts @@ -131,9 +131,9 @@ const config: Config = { copyright: copyrightConfig, }, algolia: { - apiKey: '441074cace987cbf4640c039ebed303c', - appId: 'J0EABTYI1A', - indexName: 'docusaurus-openapi', + apiKey: 'e337db95355de648d3a47a18aaee8e25', + appId: 'O6DZ543ZMD', + indexName: 'hyperse-ioio', }, prism: { theme: themes.nightOwlLight, diff --git a/yarn.lock b/yarn.lock index 6bdfef4..fda5c02 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3125,7 +3125,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.11.0, @eslint-community/regexpp@npm:^4.6.1, @eslint-community/regexpp@npm:^4.8.0, @eslint-community/regexpp@npm:^4.9.1": +"@eslint-community/regexpp@npm:^4.10.0, @eslint-community/regexpp@npm:^4.11.0, @eslint-community/regexpp@npm:^4.8.0, @eslint-community/regexpp@npm:^4.9.1": version: 4.11.0 resolution: "@eslint-community/regexpp@npm:4.11.0" checksum: 10/f053f371c281ba173fe6ee16dbc4fe544c84870d58035ccca08dba7f6ce1830d895ce3237a0db89ba37616524775dca82f1c502066b58e2d5712d7f87f5ba17c @@ -3143,23 +3143,6 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.1.2": - version: 2.1.4 - resolution: "@eslint/eslintrc@npm:2.1.4" - dependencies: - ajv: "npm:^6.12.4" - debug: "npm:^4.3.2" - espree: "npm:^9.6.0" - globals: "npm:^13.19.0" - ignore: "npm:^5.2.0" - import-fresh: "npm:^3.2.1" - js-yaml: "npm:^4.1.0" - minimatch: "npm:^3.1.2" - strip-json-comments: "npm:^3.1.1" - checksum: 10/7a3b14f4b40fc1a22624c3f84d9f467a3d9ea1ca6e9a372116cb92507e485260359465b58e25bcb6c9981b155416b98c9973ad9b796053fd7b3f776a6946bce8 - languageName: node - linkType: hard - "@eslint/eslintrc@npm:^3.1.0": version: 3.1.0 resolution: "@eslint/eslintrc@npm:3.1.0" @@ -3177,13 +3160,6 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.49.0": - version: 8.49.0 - resolution: "@eslint/js@npm:8.49.0" - checksum: 10/544acf1150629596eda78f1340220299151e59325a0af5bb38cdedf983d07f0ad0ec57a1e9d2c5e19d374f9bb37720ae8537856ad8199818aea55958b1ae7854 - languageName: node - linkType: hard - "@eslint/js@npm:9.8.0, @eslint/js@npm:^9.8.0": version: 9.8.0 resolution: "@eslint/js@npm:9.8.0" @@ -3237,17 +3213,6 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.11": - version: 0.11.14 - resolution: "@humanwhocodes/config-array@npm:0.11.14" - dependencies: - "@humanwhocodes/object-schema": "npm:^2.0.2" - debug: "npm:^4.3.1" - minimatch: "npm:^3.0.5" - checksum: 10/3ffb24ecdfab64014a230e127118d50a1a04d11080cbb748bc21629393d100850496456bbcb4e8c438957fe0934430d731042f1264d6a167b62d32fc2863580a - languageName: node - linkType: hard - "@humanwhocodes/module-importer@npm:^1.0.1": version: 1.0.1 resolution: "@humanwhocodes/module-importer@npm:1.0.1" @@ -3255,13 +3220,6 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^2.0.2": - version: 2.0.3 - resolution: "@humanwhocodes/object-schema@npm:2.0.3" - checksum: 10/05bb99ed06c16408a45a833f03a732f59bf6184795d4efadd33238ff8699190a8c871ad1121241bb6501589a9598dc83bf25b99dcbcf41e155cdf36e35e937a3 - languageName: node - linkType: hard - "@humanwhocodes/retry@npm:^0.3.0": version: 0.3.0 resolution: "@humanwhocodes/retry@npm:0.3.0" @@ -3341,7 +3299,7 @@ __metadata: languageName: node linkType: hard -"@hyperse/pipeline@npm:^1.0.4": +"@hyperse/pipeline@npm:^1.0.1, @hyperse/pipeline@npm:^1.0.4": version: 1.0.4 resolution: "@hyperse/pipeline@npm:1.0.4" dependencies: @@ -3388,6 +3346,38 @@ __metadata: languageName: unknown linkType: soft +"@hyperse/track-next-example@workspace:examples/next-example": + version: 0.0.0-use.local + resolution: "@hyperse/track-next-example@workspace:examples/next-example" + dependencies: + "@hyperse/eslint-config-hyperse": "npm:1.1.3" + "@hyperse/track": "npm:latest" + "@types/mockjs": "npm:^1" + "@types/node": "npm:20.6.2" + "@types/react": "npm:18.2.22" + "@types/react-dom": "npm:18.2.7" + autoprefixer: "npm:10.4.15" + eslint: "npm:^9.8.0" + eslint-config-next: "npm:14.2.5" + mockjs: "npm:^1.1.0" + next: "npm:14.2.5" + postcss: "npm:8.4.30" + react: "npm:18.2.0" + react-dom: "npm:18.2.0" + tailwindcss: "npm:3.3.3" + typescript: "npm:5.2.2" + languageName: unknown + linkType: soft + +"@hyperse/track@npm:latest": + version: 1.0.1 + resolution: "@hyperse/track@npm:1.0.1" + dependencies: + "@hyperse/pipeline": "npm:^1.0.1" + checksum: 10/84045db71e332ddbc8593674bbb671806cc516994217c370a5c19ef45c6e51236fa63bf21b161564bd46f1a4eb32a64829cd7b67ed0c7f4b45050f3b4f9057ec + languageName: node + linkType: hard + "@hyperse/track@workspace:.": version: 0.0.0-use.local resolution: "@hyperse/track@workspace:." @@ -3673,16 +3663,7 @@ __metadata: languageName: node linkType: hard -"@next/eslint-plugin-next@npm:13.5.1": - version: 13.5.1 - resolution: "@next/eslint-plugin-next@npm:13.5.1" - dependencies: - glob: "npm:7.1.7" - checksum: 10/57bc824debab7fd71f5a835f0c2427a286a1b05f85ead6d6e5f9d5e63da4a5744b4e6945ba0eace4f7e25acaadd6d6882006536e9a7e9c4bf5ce37357d56cafb - languageName: node - linkType: hard - -"@next/eslint-plugin-next@npm:^14.2.5": +"@next/eslint-plugin-next@npm:14.2.5, @next/eslint-plugin-next@npm:^14.2.5": version: 14.2.5 resolution: "@next/eslint-plugin-next@npm:14.2.5" dependencies: @@ -4699,6 +4680,13 @@ __metadata: languageName: node linkType: hard +"@types/mockjs@npm:^1": + version: 1.0.10 + resolution: "@types/mockjs@npm:1.0.10" + checksum: 10/9e047378beeba3a82e847eb9018ed4721cdb2a0920b2616964c76f1b60d7b7231b09389491426ae8a646dfc405e0dc98566ef3069e98e2083f75516cdcde3f21 + languageName: node + linkType: hard + "@types/ms@npm:*": version: 0.7.34 resolution: "@types/ms@npm:0.7.34" @@ -5057,31 +5045,21 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/parser@npm:^5.4.2 || ^6.0.0": - version: 6.21.0 - resolution: "@typescript-eslint/parser@npm:6.21.0" +"@typescript-eslint/parser@npm:^5.4.2 || ^6.0.0 || 7.0.0 - 7.2.0": + version: 7.2.0 + resolution: "@typescript-eslint/parser@npm:7.2.0" dependencies: - "@typescript-eslint/scope-manager": "npm:6.21.0" - "@typescript-eslint/types": "npm:6.21.0" - "@typescript-eslint/typescript-estree": "npm:6.21.0" - "@typescript-eslint/visitor-keys": "npm:6.21.0" + "@typescript-eslint/scope-manager": "npm:7.2.0" + "@typescript-eslint/types": "npm:7.2.0" + "@typescript-eslint/typescript-estree": "npm:7.2.0" + "@typescript-eslint/visitor-keys": "npm:7.2.0" debug: "npm:^4.3.4" peerDependencies: - eslint: ^7.0.0 || ^8.0.0 + eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10/4d51cdbc170e72275efc5ef5fce48a81ec431e4edde8374f4d0213d8d370a06823e1a61ae31d502a5f1b0d1f48fc4d29a1b1b5c2dcf809d66d3872ccf6e46ac7 - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:6.21.0": - version: 6.21.0 - resolution: "@typescript-eslint/scope-manager@npm:6.21.0" - dependencies: - "@typescript-eslint/types": "npm:6.21.0" - "@typescript-eslint/visitor-keys": "npm:6.21.0" - checksum: 10/fe91ac52ca8e09356a71dc1a2f2c326480f3cccfec6b2b6d9154c1a90651ab8ea270b07c67df5678956c3bbf0bbe7113ab68f68f21b20912ea528b1214197395 + checksum: 10/2236acd9f794ccb34062309f3d6fa2a0e34ac6560262213807a11fb42592011cd13ff3290a2fdbdf441fb3d248cbe23383e6c7e6c744d1cacc916159d885204f languageName: node linkType: hard @@ -5095,6 +5073,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/scope-manager@npm:7.2.0": + version: 7.2.0 + resolution: "@typescript-eslint/scope-manager@npm:7.2.0" + dependencies: + "@typescript-eslint/types": "npm:7.2.0" + "@typescript-eslint/visitor-keys": "npm:7.2.0" + checksum: 10/9b1d43c87b0fc269df1820ebcbdb08e1c5c8cc719a6af8298d87077ca78cf5ebbfa8caa6eb5141f4dfb4cbb3a641291c50c73a213faab90bc43d34abfc68a1fe + languageName: node + linkType: hard + "@typescript-eslint/scope-manager@npm:8.0.0-alpha.30": version: 8.0.0-alpha.30 resolution: "@typescript-eslint/scope-manager@npm:8.0.0-alpha.30" @@ -5145,13 +5133,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:6.21.0": - version: 6.21.0 - resolution: "@typescript-eslint/types@npm:6.21.0" - checksum: 10/e26da86d6f36ca5b6ef6322619f8ec55aabcd7d43c840c977ae13ae2c964c3091fc92eb33730d8be08927c9de38466c5323e78bfb270a9ff1d3611fe821046c5 - languageName: node - linkType: hard - "@typescript-eslint/types@npm:7.10.0": version: 7.10.0 resolution: "@typescript-eslint/types@npm:7.10.0" @@ -5159,6 +5140,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:7.2.0": + version: 7.2.0 + resolution: "@typescript-eslint/types@npm:7.2.0" + checksum: 10/d70cbd77f21caddbb1c3519bb523b5217a300d52682e9acfa9ff645d7250f7f07653f48930f531675216e848b5f83cb9b14cf63db76239cec1159550a989e16d + languageName: node + linkType: hard + "@typescript-eslint/types@npm:8.0.0-alpha.30": version: 8.0.0-alpha.30 resolution: "@typescript-eslint/types@npm:8.0.0-alpha.30" @@ -5173,41 +5161,41 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.21.0": - version: 6.21.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.21.0" +"@typescript-eslint/typescript-estree@npm:7.10.0": + version: 7.10.0 + resolution: "@typescript-eslint/typescript-estree@npm:7.10.0" dependencies: - "@typescript-eslint/types": "npm:6.21.0" - "@typescript-eslint/visitor-keys": "npm:6.21.0" + "@typescript-eslint/types": "npm:7.10.0" + "@typescript-eslint/visitor-keys": "npm:7.10.0" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" - minimatch: "npm:9.0.3" - semver: "npm:^7.5.4" - ts-api-utils: "npm:^1.0.1" + minimatch: "npm:^9.0.4" + semver: "npm:^7.6.0" + ts-api-utils: "npm:^1.3.0" peerDependenciesMeta: typescript: optional: true - checksum: 10/b32fa35fca2a229e0f5f06793e5359ff9269f63e9705e858df95d55ca2cd7fdb5b3e75b284095a992c48c5fc46a1431a1a4b6747ede2dd08929dc1cbacc589b8 + checksum: 10/d11d0c45749c9bd4a187b6dfdf5600e36ba8c87667cd2020d9158667c47c32ec0bcb1ef3b7eee5577b667def5f7f33d8131092a0f221b3d3e8105078800f923f languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:7.10.0": - version: 7.10.0 - resolution: "@typescript-eslint/typescript-estree@npm:7.10.0" +"@typescript-eslint/typescript-estree@npm:7.2.0": + version: 7.2.0 + resolution: "@typescript-eslint/typescript-estree@npm:7.2.0" dependencies: - "@typescript-eslint/types": "npm:7.10.0" - "@typescript-eslint/visitor-keys": "npm:7.10.0" + "@typescript-eslint/types": "npm:7.2.0" + "@typescript-eslint/visitor-keys": "npm:7.2.0" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" - minimatch: "npm:^9.0.4" - semver: "npm:^7.6.0" - ts-api-utils: "npm:^1.3.0" + minimatch: "npm:9.0.3" + semver: "npm:^7.5.4" + ts-api-utils: "npm:^1.0.1" peerDependenciesMeta: typescript: optional: true - checksum: 10/d11d0c45749c9bd4a187b6dfdf5600e36ba8c87667cd2020d9158667c47c32ec0bcb1ef3b7eee5577b667def5f7f33d8131092a0f221b3d3e8105078800f923f + checksum: 10/77a81dc903da1ccb302c96bf7f845f297d87ab7871849bfabdddee51583646a1147923fc23c550c6c783229bc7bda37a3ea147478fa08b3847d0440a34587198 languageName: node linkType: hard @@ -5291,16 +5279,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.21.0": - version: 6.21.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.21.0" - dependencies: - "@typescript-eslint/types": "npm:6.21.0" - eslint-visitor-keys: "npm:^3.4.1" - checksum: 10/30422cdc1e2ffad203df40351a031254b272f9c6f2b7e02e9bfa39e3fc2c7b1c6130333b0057412968deda17a3a68a578a78929a8139c6acef44d9d841dc72e1 - languageName: node - linkType: hard - "@typescript-eslint/visitor-keys@npm:7.10.0": version: 7.10.0 resolution: "@typescript-eslint/visitor-keys@npm:7.10.0" @@ -5311,6 +5289,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:7.2.0": + version: 7.2.0 + resolution: "@typescript-eslint/visitor-keys@npm:7.2.0" + dependencies: + "@typescript-eslint/types": "npm:7.2.0" + eslint-visitor-keys: "npm:^3.4.1" + checksum: 10/e0c9c7a9bb1ae93149e7a4816aed12651fd7374d0eb17e1f45348dbfddd8ee7014d3de35b40bc46b9df73cc1c9053aaf5d82b43270d93a0b551ed14e8afde37a + languageName: node + linkType: hard + "@typescript-eslint/visitor-keys@npm:8.0.0-alpha.30": version: 8.0.0-alpha.30 resolution: "@typescript-eslint/visitor-keys@npm:8.0.0-alpha.30" @@ -7005,6 +6993,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:*, commander@npm:~12.1.0": + version: 12.1.0 + resolution: "commander@npm:12.1.0" + checksum: 10/cdaeb672d979816853a4eed7f1310a9319e8b976172485c2a6b437ed0db0a389a44cfb222bfbde772781efa9f215bdd1b936f80d6b249485b465c6cb906e1f93 + languageName: node + linkType: hard + "commander@npm:^10.0.0": version: 10.0.1 resolution: "commander@npm:10.0.1" @@ -7047,13 +7042,6 @@ __metadata: languageName: node linkType: hard -"commander@npm:~12.1.0": - version: 12.1.0 - resolution: "commander@npm:12.1.0" - checksum: 10/cdaeb672d979816853a4eed7f1310a9319e8b976172485c2a6b437ed0db0a389a44cfb222bfbde772781efa9f215bdd1b936f80d6b249485b465c6cb906e1f93 - languageName: node - linkType: hard - "comment-parser@npm:^1.4.0": version: 1.4.1 resolution: "comment-parser@npm:1.4.1" @@ -8067,15 +8055,6 @@ __metadata: languageName: node linkType: hard -"doctrine@npm:^3.0.0": - version: 3.0.0 - resolution: "doctrine@npm:3.0.0" - dependencies: - esutils: "npm:^2.0.2" - checksum: 10/b4b28f1df5c563f7d876e7461254a4597b8cabe915abe94d7c5d1633fed263fcf9a85e8d3836591fc2d040108e822b0d32758e5ec1fe31c590dc7e08086e3e48 - languageName: node - linkType: hard - "docusaurus-theme-search-typesense@npm:^0.20.0": version: 0.20.0 resolution: "docusaurus-theme-search-typesense@npm:0.20.0" @@ -8738,13 +8717,13 @@ __metadata: languageName: node linkType: hard -"eslint-config-next@npm:13.5.1": - version: 13.5.1 - resolution: "eslint-config-next@npm:13.5.1" +"eslint-config-next@npm:14.2.5": + version: 14.2.5 + resolution: "eslint-config-next@npm:14.2.5" dependencies: - "@next/eslint-plugin-next": "npm:13.5.1" + "@next/eslint-plugin-next": "npm:14.2.5" "@rushstack/eslint-patch": "npm:^1.3.3" - "@typescript-eslint/parser": "npm:^5.4.2 || ^6.0.0" + "@typescript-eslint/parser": "npm:^5.4.2 || ^6.0.0 || 7.0.0 - 7.2.0" eslint-import-resolver-node: "npm:^0.3.6" eslint-import-resolver-typescript: "npm:^3.5.2" eslint-plugin-import: "npm:^2.28.1" @@ -8757,7 +8736,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10/a8a2d17e4a1948609e99074d948fe43ce9af8decd9e867269eb915853c4fa71733cfb800ba739d5d77b6a8e05c58a8578218184183085f1c7c4c9125051ba5de + checksum: 10/3c362f080775541e936a5f2d273ffc63ed177b6cbb45a80d25efa2857e8eb265250ad9f60c2e3d940f4e565ec49ddc6c9885f2b7260c550aae77237620df9420 languageName: node linkType: hard @@ -9092,16 +9071,6 @@ __metadata: languageName: node linkType: hard -"eslint-scope@npm:^7.2.2": - version: 7.2.2 - resolution: "eslint-scope@npm:7.2.2" - dependencies: - esrecurse: "npm:^4.3.0" - estraverse: "npm:^5.2.0" - checksum: 10/5c660fb905d5883ad018a6fea2b49f3cb5b1cbf2cd4bd08e98646e9864f9bc2c74c0839bed2d292e90a4a328833accc197c8f0baed89cbe8d605d6f918465491 - languageName: node - linkType: hard - "eslint-scope@npm:^8.0.2": version: 8.0.2 resolution: "eslint-scope@npm:8.0.2" @@ -9126,53 +9095,6 @@ __metadata: languageName: node linkType: hard -"eslint@npm:8.49.0": - version: 8.49.0 - resolution: "eslint@npm:8.49.0" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.2.0" - "@eslint-community/regexpp": "npm:^4.6.1" - "@eslint/eslintrc": "npm:^2.1.2" - "@eslint/js": "npm:8.49.0" - "@humanwhocodes/config-array": "npm:^0.11.11" - "@humanwhocodes/module-importer": "npm:^1.0.1" - "@nodelib/fs.walk": "npm:^1.2.8" - ajv: "npm:^6.12.4" - chalk: "npm:^4.0.0" - cross-spawn: "npm:^7.0.2" - debug: "npm:^4.3.2" - doctrine: "npm:^3.0.0" - escape-string-regexp: "npm:^4.0.0" - eslint-scope: "npm:^7.2.2" - eslint-visitor-keys: "npm:^3.4.3" - espree: "npm:^9.6.1" - esquery: "npm:^1.4.2" - esutils: "npm:^2.0.2" - fast-deep-equal: "npm:^3.1.3" - file-entry-cache: "npm:^6.0.1" - find-up: "npm:^5.0.0" - glob-parent: "npm:^6.0.2" - globals: "npm:^13.19.0" - graphemer: "npm:^1.4.0" - ignore: "npm:^5.2.0" - imurmurhash: "npm:^0.1.4" - is-glob: "npm:^4.0.0" - is-path-inside: "npm:^3.0.3" - js-yaml: "npm:^4.1.0" - json-stable-stringify-without-jsonify: "npm:^1.0.1" - levn: "npm:^0.4.1" - lodash.merge: "npm:^4.6.2" - minimatch: "npm:^3.1.2" - natural-compare: "npm:^1.4.0" - optionator: "npm:^0.9.3" - strip-ansi: "npm:^6.0.1" - text-table: "npm:^0.2.0" - bin: - eslint: bin/eslint.js - checksum: 10/5ec661eefe4638bff52e9c92dee30138a7b38086ec0099f0b51dfa3a9999dda913d89d3cd9cb5b1c3dd0f2ddc7dce333cd91d4cbbde7014b52c054db9a52fc4c - languageName: node - linkType: hard - "eslint@npm:^9.8.0": version: 9.8.0 resolution: "eslint@npm:9.8.0" @@ -9228,7 +9150,7 @@ __metadata: languageName: node linkType: hard -"espree@npm:^9.0.0, espree@npm:^9.6.0, espree@npm:^9.6.1": +"espree@npm:^9.0.0, espree@npm:^9.6.1": version: 9.6.1 resolution: "espree@npm:9.6.1" dependencies: @@ -9249,15 +9171,6 @@ __metadata: languageName: node linkType: hard -"esquery@npm:^1.4.2": - version: 1.6.0 - resolution: "esquery@npm:1.6.0" - dependencies: - estraverse: "npm:^5.1.0" - checksum: 10/c587fb8ec9ed83f2b1bc97cf2f6854cc30bf784a79d62ba08c6e358bf22280d69aee12827521cf38e69ae9761d23fb7fde593ce315610f85655c139d99b05e5a - languageName: node - linkType: hard - "esquery@npm:^1.5.0": version: 1.5.0 resolution: "esquery@npm:1.5.0" @@ -9670,15 +9583,6 @@ __metadata: languageName: node linkType: hard -"file-entry-cache@npm:^6.0.1": - version: 6.0.1 - resolution: "file-entry-cache@npm:6.0.1" - dependencies: - flat-cache: "npm:^3.0.4" - checksum: 10/099bb9d4ab332cb93c48b14807a6918a1da87c45dce91d4b61fd40e6505d56d0697da060cb901c729c90487067d93c9243f5da3dc9c41f0358483bfdebca736b - languageName: node - linkType: hard - "file-entry-cache@npm:^8.0.0": version: 8.0.0 resolution: "file-entry-cache@npm:8.0.0" @@ -9837,17 +9741,6 @@ __metadata: languageName: node linkType: hard -"flat-cache@npm:^3.0.4": - version: 3.2.0 - resolution: "flat-cache@npm:3.2.0" - dependencies: - flatted: "npm:^3.2.9" - keyv: "npm:^4.5.3" - rimraf: "npm:^3.0.2" - checksum: 10/02381c6ece5e9fa5b826c9bbea481d7fd77645d96e4b0b1395238124d581d10e56f17f723d897b6d133970f7a57f0fab9148cbbb67237a0a0ffe794ba60c0c70 - languageName: node - linkType: hard - "flat-cache@npm:^4.0.0": version: 4.0.1 resolution: "flat-cache@npm:4.0.1" @@ -10265,20 +10158,6 @@ __metadata: languageName: node linkType: hard -"glob@npm:7.1.7": - version: 7.1.7 - resolution: "glob@npm:7.1.7" - dependencies: - fs.realpath: "npm:^1.0.0" - inflight: "npm:^1.0.4" - inherits: "npm:2" - minimatch: "npm:^3.0.4" - once: "npm:^1.3.0" - path-is-absolute: "npm:^1.0.0" - checksum: 10/ff5aab0386e9cace92b0550d42085b71013c5ea382982dd7fdded998a559635f61413b8ba6fb7294eef289c83b52f4e64136f888300ac8afc4f3e5623182d6c8 - languageName: node - linkType: hard - "glob@npm:7.2.3, glob@npm:^7.0.0, glob@npm:^7.1.3, glob@npm:^7.1.6": version: 7.2.3 resolution: "glob@npm:7.2.3" @@ -10378,15 +10257,6 @@ __metadata: languageName: node linkType: hard -"globals@npm:^13.19.0": - version: 13.24.0 - resolution: "globals@npm:13.24.0" - dependencies: - type-fest: "npm:^0.20.2" - checksum: 10/62c5b1997d06674fc7191d3e01e324d3eda4d65ac9cc4e78329fa3b5c4fd42a0e1c8722822497a6964eee075255ce21ccf1eec2d83f92ef3f06653af4d0ee28e - languageName: node - linkType: hard - "globals@npm:^14.0.0": version: 14.0.0 resolution: "globals@npm:14.0.0" @@ -13853,6 +13723,17 @@ __metadata: languageName: node linkType: hard +"mockjs@npm:^1.1.0": + version: 1.1.0 + resolution: "mockjs@npm:1.1.0" + dependencies: + commander: "npm:*" + bin: + random: bin/random + checksum: 10/44e7114e49c0244b16199e6bcef97cf177990ab4b7cd905bf74919fb311a6174fec9dbde97c8d9b781fee3c9474f771582ad5c1ccbcf7b2fc35771bfd735499b + languageName: node + linkType: hard + "monet@npm:^0.9.3": version: 0.9.3 resolution: "monet@npm:0.9.3" @@ -13955,26 +13836,6 @@ __metadata: languageName: node linkType: hard -"next-example@workspace:examples/next-example": - version: 0.0.0-use.local - resolution: "next-example@workspace:examples/next-example" - dependencies: - "@hyperse/eslint-config-hyperse": "npm:1.1.3" - "@types/node": "npm:20.6.2" - "@types/react": "npm:18.2.22" - "@types/react-dom": "npm:18.2.7" - autoprefixer: "npm:10.4.15" - eslint: "npm:8.49.0" - eslint-config-next: "npm:13.5.1" - next: "npm:14.2.5" - postcss: "npm:8.4.30" - react: "npm:18.2.0" - react-dom: "npm:18.2.0" - tailwindcss: "npm:3.3.3" - typescript: "npm:5.2.2" - languageName: unknown - linkType: soft - "next@npm:14.2.5": version: 14.2.5 resolution: "next@npm:14.2.5" @@ -18226,13 +18087,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^0.20.2": - version: 0.20.2 - resolution: "type-fest@npm:0.20.2" - checksum: 10/8907e16284b2d6cfa4f4817e93520121941baba36b39219ea36acfe64c86b9dbc10c9941af450bd60832c8f43464974d51c0957f9858bc66b952b66b6914cbb9 - languageName: node - linkType: hard - "type-fest@npm:^0.21.3": version: 0.21.3 resolution: "type-fest@npm:0.21.3" From 8def8e7f5d0b6f1f28767c9c459efba2dcb0a714 Mon Sep 17 00:00:00 2001 From: "shunquan.wang" Date: Tue, 20 Aug 2024 17:38:01 +0800 Subject: [PATCH 16/28] feat: perfect docs --- .changeset/funny-rivers-refuse.md | 5 ----- .changeset/stupid-days-decide.md | 5 ----- .changeset/two-buckets-cheer.md | 6 ------ examples/next-example/README.md | 21 -------------------- examples/next-example/package.json | 4 ++-- website/docs/intro/live-example.md | 2 +- website/src/components/Stackblitz/index.tsx | 8 ++++++-- website/static/media/code.mp4 | Bin 10960713 -> 3772105 bytes 8 files changed, 9 insertions(+), 42 deletions(-) delete mode 100644 .changeset/funny-rivers-refuse.md delete mode 100644 .changeset/stupid-days-decide.md delete mode 100644 .changeset/two-buckets-cheer.md diff --git a/.changeset/funny-rivers-refuse.md b/.changeset/funny-rivers-refuse.md deleted file mode 100644 index f0c1bf1..0000000 --- a/.changeset/funny-rivers-refuse.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@hyperse/track": patch ---- - -Track release diff --git a/.changeset/stupid-days-decide.md b/.changeset/stupid-days-decide.md deleted file mode 100644 index a6cbed2..0000000 --- a/.changeset/stupid-days-decide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@hyperse/track": patch ---- - -perfect track pipeline diff --git a/.changeset/two-buckets-cheer.md b/.changeset/two-buckets-cheer.md deleted file mode 100644 index dbf67b8..0000000 --- a/.changeset/two-buckets-cheer.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@hyperse/track-docs": patch -"@hyperse/track": patch ---- - -add docs website diff --git a/examples/next-example/README.md b/examples/next-example/README.md index 5ae7daf..9295c57 100644 --- a/examples/next-example/README.md +++ b/examples/next-example/README.md @@ -1,5 +1,3 @@ -This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). - ## Getting Started First, run the development server: @@ -15,22 +13,3 @@ bun run dev ``` Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/next-example/package.json b/examples/next-example/package.json index d9a2117..3aff65c 100644 --- a/examples/next-example/package.json +++ b/examples/next-example/package.json @@ -1,10 +1,10 @@ { - "name": "@hyperse/track-next-example", + "name": "@hyperse/next-example", "version": "1.0.0", "private": true, "type": "module", "scripts": { - "dev": "next dev -p 3001", + "dev": "next dev -p", "build": "next build", "start": "next start", "lint": "eslint .", diff --git a/website/docs/intro/live-example.md b/website/docs/intro/live-example.md index 3baba30..6d6fe1a 100644 --- a/website/docs/intro/live-example.md +++ b/website/docs/intro/live-example.md @@ -14,7 +14,7 @@ Read more in [**User guide > introducing**](/docs/intro/introducing) ::: - + ## Congratulations ! diff --git a/website/src/components/Stackblitz/index.tsx b/website/src/components/Stackblitz/index.tsx index de0d253..ab56265 100644 --- a/website/src/components/Stackblitz/index.tsx +++ b/website/src/components/Stackblitz/index.tsx @@ -1,6 +1,10 @@ import React from 'react'; -export default function Stackblitz(props: { id: string }) { +const GithubUrl = { + 'next-example': `https://stackblitz.com/fork/github/hyperse-io/track/tree/feat/track/examples/next-example?title=next-example&startScript=dev&embed=1&theme=dark`, +}; + +export default function Stackblitz(props: { id: keyof typeof GithubUrl }) { return (