diff --git a/build/index.d.ts b/build/index.d.ts new file mode 100644 index 000000000..9bfd0e9bf --- /dev/null +++ b/build/index.d.ts @@ -0,0 +1,15 @@ +import * as ackeeTracker from "ackee-tracker"; +export declare var ackeeInstance: ackeeTracker.AckeeInstance | undefined; +/** + * Use Ackee in React. + * Creates an instance once and a new record every time the pathname changes. + * Safely no-ops during server-side rendering. + * @param {String} pathname - Current path. + * @param {Object} environment - Object containing the URL of the Ackee server and the domain id. + * @param {ackeeTracker.TrackingOptions} options - Ackee options. + */ +export declare const useAckee: (pathname: string, environment: { + server: string; + domainId: string; +}, options?: ackeeTracker.TrackingOptions) => void; +export default useAckee; diff --git a/build/index.js b/build/index.js new file mode 100644 index 000000000..7265999c2 --- /dev/null +++ b/build/index.js @@ -0,0 +1,42 @@ +import { useMemo, useEffect } from "react"; +import * as ackeeTracker from "ackee-tracker"; +const isBrowser = typeof window !== "undefined"; +export var ackeeInstance; +/** + * Use Ackee in React. + * Creates an instance once and a new record every time the pathname changes. + * Safely no-ops during server-side rendering. + * @param {String} pathname - Current path. + * @param {Object} environment - Object containing the URL of the Ackee server and the domain id. + * @param {ackeeTracker.TrackingOptions} options - Ackee options. + */ +export const useAckee = (pathname, environment, options = {}) => { + ackeeInstance = useMemo(() => { + if (isBrowser === false) + return; + return ackeeTracker.create(environment.server, options); + }, [ + environment.server, + options.detailed, + options.ignoreLocalhost, + options.ignoreOwnVisits, + ]); + useEffect(() => { + if (!ackeeInstance) { + console.warn("Skipped record creation because useAckee has been called in a non-browser environment"); + return; + } + if (!pathname.length) { + console.warn("Skipped record creation because useAckee has been called without pathname"); + return; + } + const attributes = ackeeTracker.attributes(options.detailed); + const url = new URL(pathname, location.toString()); + return ackeeInstance.record(environment.domainId, { + ...attributes, + siteLocation: url.href, + }).stop; + }, [ackeeInstance, pathname, environment.domainId]); +}; +export default useAckee; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/index.js.map b/build/index.js.map new file mode 100644 index 000000000..1d46550e8 --- /dev/null +++ b/build/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,YAAY,MAAM,eAAe,CAAC;AAE9C,MAAM,SAAS,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC;AAEhD,MAAM,CAAC,IAAI,aAAqD,CAAC;AAEjE;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,QAAgB,EAChB,WAAiD,EACjD,UAAwC,EAAE,EAC1C,EAAE;IACF,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE;QAC3B,IAAI,SAAS,KAAK,KAAK;YAAE,OAAO;QAEhC,OAAO,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1D,CAAC,EAAE;QACD,WAAW,CAAC,MAAM;QAClB,OAAO,CAAC,QAAQ;QAChB,OAAO,CAAC,eAAe;QACvB,OAAO,CAAC,eAAe;KACxB,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,aAAa,EAAE;YAClB,OAAO,CAAC,IAAI,CACV,uFAAuF,CACxF,CAAC;YACF,OAAO;SACR;QAED,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;YACpB,OAAO,CAAC,IAAI,CACV,2EAA2E,CAC5E,CAAC;YACF,OAAO;SACR;QAED,MAAM,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC7D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QAEnD,OAAO,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE;YAChD,GAAG,UAAU;YACb,YAAY,EAAE,GAAG,CAAC,IAAI;SACvB,CAAC,CAAC,IAAI,CAAC;IACV,CAAC,EAAE,CAAC,aAAa,EAAE,QAAQ,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;AACtD,CAAC,CAAC;AAEF,eAAe,QAAQ,CAAC"} \ No newline at end of file diff --git a/package.json b/package.json index 623f93778..f1bf75f09 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,6 @@ "Tobias Reich " ], "description": "Use Ackee in React", - "main": "src/index.js", "keywords": [ "react", "hooks", @@ -22,26 +21,31 @@ "url": "https://github.com/electerious/use-ackee.git" }, "files": [ - "src" + "build" ], "scripts": { "coveralls": "nyc report --reporter=lcov", - "test": "npm run lint && nyc node_modules/mocha/bin/_mocha", - "lint": "eslint \"{src,test}/**/*.js\"" + "test": "npm run build && nyc node_modules/mocha/bin/_mocha", + "lint": "eslint \"{build,test}/**/*.js\"", + "build": "tsc" }, "dependencies": { "ackee-tracker": "^5.0.1" }, "devDependencies": { "@electerious/eslint-config": "^3.0.0", + "@types/ackee-tracker": "^5.0.2", + "@types/node": "^18.11.0", + "@types/react": "^18.0.21", "chai": "^4.3.0", "coveralls": "^3.1.1", "mocha": "^9.1.3", "nyc": "^15.1.0", - "react": "^17.0.1" + "react": "^18.1.0", + "typescript": "^4.8.4" }, "peerDependencies": { - "react": "^17.0.0" + "react": "^18.1.0" }, "eslintConfig": { "root": true, @@ -49,5 +53,11 @@ }, "eslintIgnore": [ "demos" - ] + ], + "type": "module", + "exports": "./build/index.js", + "engines": { + "node": ">=14.16" + }, + "main": "./build/index.js" } diff --git a/src/index.js b/src/index.js deleted file mode 100644 index 775c7aad3..000000000 --- a/src/index.js +++ /dev/null @@ -1,50 +0,0 @@ -'use strict' - -const { useMemo, useEffect } = require('react') -const ackeeTracker = require('ackee-tracker') - -const isBrowser = typeof window !== 'undefined' - -/** - * Use Ackee in React. - * Creates an instance once and a new record every time the pathname changes. - * Safely no-ops during server-side rendering. - * @param {?String} pathname - Current path. - * @param {Object} environment - Object containing the URL of the Ackee server and the domain id. - * @param {?Object} options - Ackee options. - */ -const useAckee = function(pathname, environment, options = {}) { - const instance = useMemo(() => { - if (isBrowser === false) return - - return ackeeTracker.create(environment.server, options) - }, [ environment.server, options.detailed, options.ignoreLocalhost, options.ignoreOwnVisits ]) - - useEffect(() => { - if (instance == null) { - console.warn('Skipped record creation because useAckee has been called in a non-browser environment') - return - } - - const hasPathname = ( - pathname != null && - pathname !== '' - ) - - if (hasPathname === false) { - console.warn('Skipped record creation because useAckee has been called without pathname') - return - } - - const attributes = ackeeTracker.attributes(options.detailed) - const url = new URL(pathname, location) - - return instance.record(environment.domainId, { - ...attributes, - siteLocation: url.href, - }).stop - }, [ instance, pathname, environment.domainId ]) -} - -module.exports = useAckee -module.exports.useAckee = useAckee \ No newline at end of file diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 000000000..04f02b407 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,57 @@ +import { useMemo, useEffect } from "react"; +import * as ackeeTracker from "ackee-tracker"; + +const isBrowser = typeof window !== "undefined"; + +export var ackeeInstance: ackeeTracker.AckeeInstance | undefined; + +/** + * Use Ackee in React. + * Creates an instance once and a new record every time the pathname changes. + * Safely no-ops during server-side rendering. + * @param {String} pathname - Current path. + * @param {Object} environment - Object containing the URL of the Ackee server and the domain id. + * @param {ackeeTracker.TrackingOptions} options - Ackee options. + */ +export const useAckee = ( + pathname: string, + environment: { server: string; domainId: string }, + options: ackeeTracker.TrackingOptions = {} +) => { + ackeeInstance = useMemo(() => { + if (isBrowser === false) return; + + return ackeeTracker.create(environment.server, options); + }, [ + environment.server, + options.detailed, + options.ignoreLocalhost, + options.ignoreOwnVisits, + ]); + + useEffect(() => { + if (!ackeeInstance) { + console.warn( + "Skipped record creation because useAckee has been called in a non-browser environment" + ); + return; + } + + if (!pathname.length) { + console.warn( + "Skipped record creation because useAckee has been called without pathname" + ); + return; + } + + const attributes = ackeeTracker.attributes(options.detailed); + const url = new URL(pathname, location.toString()); + + return ackeeInstance.record(environment.domainId, { + ...attributes, + siteLocation: url.href, + }).stop; + }, [ackeeInstance, pathname, environment.domainId]); +}; + +export default useAckee; diff --git a/test/index.js b/test/index.js index 86272063f..142ee7286 100644 --- a/test/index.js +++ b/test/index.js @@ -1,10 +1,12 @@ -'use strict' +import { assert, expect } from 'chai'; +import { useAckee, ackeeInstance } from './../build/index.js'; +import * as ackeeTracker from "ackee-tracker"; -const assert = require('chai').assert -const index = require('./../src/index') - -describe('index', function() { - it('should be a function', function() { - assert.isFunction(index) +describe('index', function () { + it('should be a function', function () { + assert.isFunction(useAckee) + }) + it('ackeeInstance should be ackeeTracker.ackeeInstance type', () => { + expect(ackeeInstance).to.be.a(typeof ackeeTracker.ackeeInstance) }) }) \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..25d555646 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "outDir": "build", + "module": "ES2022", + "target": "ES2022", + "lib": ["ES2022", "DOM"], + "moduleResolution": "node", + "jsx": "preserve", + "allowJs": true, + "strict": true, + "declaration": true, + "sourceMap": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "esModuleInterop": true, + "noImplicitReturns": true, + "noImplicitAny": true, + "strictNullChecks": true, + "isolatedModules": true + }, + "include": ["src"], + "exclude": ["node_modules"] +}