posthog-node
Advanced tools
Comparing version 1.0.10 to 1.0.11
80
cli.js
@@ -8,21 +8,21 @@ #!/usr/bin/env node | ||
const toObject = str => JSON.parse(str) | ||
const toObject = (str) => JSON.parse(str) | ||
program | ||
.version(pkg.version) | ||
.option('-k, --apiKey <key>', 'the PostHog api key to use') | ||
.option('-h, --host <host>', 'the PostHog API hostname to use') | ||
.option('-t, --type <type>', 'the PostHog message type') | ||
.version(pkg.version) | ||
.option('-k, --apiKey <key>', 'the PostHog api key to use') | ||
.option('-h, --host <host>', 'the PostHog API hostname to use') | ||
.option('-t, --type <type>', 'the PostHog message type') | ||
.option('-d, --distinctId <id>', 'the distinct id to send the event as') | ||
.option('-d, --distinctId <id>', 'the distinct id to send the event as') | ||
.option('-e, --event <event>', 'the event name to send with the event') | ||
.option('-p, --properties <properties>', 'the event properties to send (JSON-encoded)', toObject) | ||
.option('-e, --event <event>', 'the event name to send with the event') | ||
.option('-p, --properties <properties>', 'the event properties to send (JSON-encoded)', toObject) | ||
.option('-a, --alias <previousId>', 'alias for the distinct id') | ||
.option('-a, --alias <previousId>', 'alias for the distinct id') | ||
.parse(process.argv) | ||
.parse(process.argv) | ||
if (program.args.length !== 0) { | ||
program.help() | ||
program.help() | ||
} | ||
@@ -41,34 +41,34 @@ | ||
const run = (method, args) => { | ||
const posthog = new PostHog(apiKey, { host, flushAt: 1 }) | ||
posthog[method](args, err => { | ||
if (err) { | ||
console.error(err.stack) | ||
process.exit(1) | ||
} | ||
}) | ||
const posthog = new PostHog(apiKey, { host, flushAt: 1 }) | ||
posthog[method](args, (err) => { | ||
if (err) { | ||
console.error(err.stack) | ||
process.exit(1) | ||
} | ||
}) | ||
} | ||
switch (type) { | ||
case 'capture': | ||
run('capture', { | ||
event, | ||
properties, | ||
distinctId | ||
}) | ||
break | ||
case 'identify': | ||
run('identify', { | ||
properties, | ||
distinctId | ||
}) | ||
break | ||
case 'alias': | ||
run('alias', { | ||
alias, | ||
distinctId | ||
}) | ||
break | ||
default: | ||
console.error('invalid type:', type) | ||
process.exit(1) | ||
case 'capture': | ||
run('capture', { | ||
event, | ||
properties, | ||
distinctId, | ||
}) | ||
break | ||
case 'identify': | ||
run('identify', { | ||
properties, | ||
distinctId, | ||
}) | ||
break | ||
case 'alias': | ||
run('alias', { | ||
alias, | ||
distinctId, | ||
}) | ||
break | ||
default: | ||
console.error('invalid type:', type) | ||
process.exit(1) | ||
} |
@@ -14,16 +14,16 @@ var type = require('component-type') | ||
function eventValidation (event, type) { | ||
validateGenericEvent(event) | ||
type = type || event.type | ||
assert(type, 'You must pass an event type.') | ||
switch (type) { | ||
case 'capture': | ||
return validateCaptureEvent(event) | ||
case 'identify': | ||
return validateIdentifyEvent(event) | ||
case 'alias': | ||
return validateAliasEvent(event) | ||
default: | ||
assert(0, 'Invalid event type: "' + type + '"') | ||
} | ||
function eventValidation(event, type) { | ||
validateGenericEvent(event) | ||
type = type || event.type | ||
assert(type, 'You must pass an event type.') | ||
switch (type) { | ||
case 'capture': | ||
return validateCaptureEvent(event) | ||
case 'identify': | ||
return validateIdentifyEvent(event) | ||
case 'alias': | ||
return validateAliasEvent(event) | ||
default: | ||
assert(0, 'Invalid event type: "' + type + '"') | ||
} | ||
} | ||
@@ -35,5 +35,5 @@ | ||
function validateCaptureEvent (event) { | ||
assert(event.distinctId, 'You must pass a "distinctId".') | ||
assert(event.event, 'You must pass an "event".') | ||
function validateCaptureEvent(event) { | ||
assert(event.distinctId, 'You must pass a "distinctId".') | ||
assert(event.event, 'You must pass an "event".') | ||
} | ||
@@ -45,4 +45,4 @@ | ||
function validateIdentifyEvent (event) { | ||
assert(event.distinctId, 'You must pass a "distinctId".') | ||
function validateIdentifyEvent(event) { | ||
assert(event.distinctId, 'You must pass a "distinctId".') | ||
} | ||
@@ -54,5 +54,5 @@ | ||
function validateAliasEvent (event) { | ||
assert(event.distinctId, 'You must pass a "distinctId".') | ||
assert(event.alias, 'You must pass a "alias".') | ||
function validateAliasEvent(event) { | ||
assert(event.distinctId, 'You must pass a "distinctId".') | ||
assert(event.alias, 'You must pass a "alias".') | ||
} | ||
@@ -65,8 +65,8 @@ | ||
var genericValidationRules = { | ||
event: 'string', | ||
properties: 'object', | ||
alias: 'string', | ||
timestamp: 'date', | ||
distinctId: 'string', | ||
type: 'string' | ||
event: 'string', | ||
properties: 'object', | ||
alias: 'string', | ||
timestamp: 'date', | ||
distinctId: 'string', | ||
type: 'string', | ||
} | ||
@@ -78,21 +78,23 @@ | ||
function validateGenericEvent (event) { | ||
assert(type(event) === 'object', 'You must pass a message object.') | ||
var json = JSON.stringify(event) | ||
// Strings are variable byte encoded, so json.length is not sufficient. | ||
assert(Buffer.byteLength(json, 'utf8') < MAX_SIZE, 'Your message must be < 32kb.') | ||
function validateGenericEvent(event) { | ||
assert(type(event) === 'object', 'You must pass a message object.') | ||
var json = JSON.stringify(event) | ||
// Strings are variable byte encoded, so json.length is not sufficient. | ||
assert(Buffer.byteLength(json, 'utf8') < MAX_SIZE, 'Your message must be < 32kb.') | ||
for (var key in genericValidationRules) { | ||
var val = event[key] | ||
if (!val) continue | ||
var rule = genericValidationRules[key] | ||
if (type(rule) !== 'array') { | ||
rule = [ rule ] | ||
for (var key in genericValidationRules) { | ||
var val = event[key] | ||
if (!val) continue | ||
var rule = genericValidationRules[key] | ||
if (type(rule) !== 'array') { | ||
rule = [rule] | ||
} | ||
var a = rule[0] === 'object' ? 'an' : 'a' | ||
assert( | ||
rule.some(function (e) { | ||
return type(val) === e | ||
}), | ||
'"' + key + '" must be ' + a + ' ' + join(rule, 'or') + '.' | ||
) | ||
} | ||
var a = rule[0] === 'object' ? 'an' : 'a' | ||
assert( | ||
rule.some(function (e) { return type(val) === e }), | ||
'"' + key + '" must be ' + a + ' ' + join(rule, 'or') + '.' | ||
) | ||
} | ||
} |
105
index.d.ts
// Type definitions for posthog-node | ||
// Project: Posthog | ||
declare module "posthog-node" { | ||
interface Option { | ||
flushAt?: number; | ||
flushInterval?: number; | ||
host?: string; | ||
api_host?: string; | ||
enable?: boolean; | ||
} | ||
declare module 'posthog-node' { | ||
interface Option { | ||
flushAt?: number | ||
flushInterval?: number | ||
host?: string | ||
api_host?: string | ||
enable?: boolean | ||
} | ||
interface CommonParamsInterfacePropertiesProp { | ||
[key: string]: | ||
| string | ||
| number | ||
| Array<any | { [key: string]: string | number }>; | ||
} | ||
interface CommonParamsInterfacePropertiesProp { | ||
[key: string]: string | number | Array<any | { [key: string]: string | number }> | ||
} | ||
interface IdentifyMessage { | ||
distinctId: string; | ||
properties?: CommonParamsInterfacePropertiesProp; | ||
} | ||
interface IdentifyMessage { | ||
distinctId: string | ||
properties?: CommonParamsInterfacePropertiesProp | ||
} | ||
interface EventMessage extends IdentifyMessage { | ||
event: string; | ||
} | ||
interface EventMessage extends IdentifyMessage { | ||
event: string | ||
} | ||
export default class PostHog { | ||
constructor(apiKey: string, options?: Option); | ||
/** | ||
* @description Capture allows you to capture anything a user does within your system, | ||
* which you can later use in PostHog to find patterns in usage, | ||
* work out which features to improve or where people are giving up. | ||
* A capture call requires: | ||
* @param distinctId which uniquely identifies your user | ||
* @param event We recommend using [verb] [noun], like movie played or movie updated to easily identify what your events mean later on. | ||
* @param properties OPTIONAL | which can be a dict with any information you'd like to add | ||
*/ | ||
capture({ distinctId, event, properties }: EventMessage): PostHog; | ||
export default class PostHog { | ||
constructor(apiKey: string, options?: Option) | ||
/** | ||
* @description Capture allows you to capture anything a user does within your system, | ||
* which you can later use in PostHog to find patterns in usage, | ||
* work out which features to improve or where people are giving up. | ||
* A capture call requires: | ||
* @param distinctId which uniquely identifies your user | ||
* @param event We recommend using [verb] [noun], like movie played or movie updated to easily identify what your events mean later on. | ||
* @param properties OPTIONAL | which can be a dict with any information you'd like to add | ||
*/ | ||
capture({ distinctId, event, properties }: EventMessage): PostHog | ||
/** | ||
* @description Identify lets you add metadata on your users so you can more easily identify who they are in PostHog, | ||
* and even do things like segment users by these properties. | ||
* An identify call requires: | ||
* @param distinctId which uniquely identifies your user | ||
* @param properties with a dict with any key: value pairs | ||
*/ | ||
identify({ distinctId, properties }: IdentifyMessage): PostHog; | ||
/** | ||
* @description Identify lets you add metadata on your users so you can more easily identify who they are in PostHog, | ||
* and even do things like segment users by these properties. | ||
* An identify call requires: | ||
* @param distinctId which uniquely identifies your user | ||
* @param properties with a dict with any key: value pairs | ||
*/ | ||
identify({ distinctId, properties }: IdentifyMessage): PostHog | ||
/** | ||
* @description To marry up whatever a user does before they sign up or log in with what they do after you need to make an alias call. | ||
* This will allow you to answer questions like "Which marketing channels leads to users churning after a month?" | ||
* or "What do users do on our website before signing up?" | ||
* In a purely back-end implementation, this means whenever an anonymous user does something, you'll want to send a session ID with the capture call. | ||
* Then, when that users signs up, you want to do an alias call with the session ID and the newly created user ID. | ||
* The same concept applies for when a user logs in. If you're using PostHog in the front-end and back-end, | ||
* doing the identify call in the frontend will be enough.: | ||
* @param distinctId the current unique id | ||
* @param alias the unique ID of the user before | ||
*/ | ||
alias(data: { distinctId: string; alias: string }): PostHog; | ||
} | ||
/** | ||
* @description To marry up whatever a user does before they sign up or log in with what they do after you need to make an alias call. | ||
* This will allow you to answer questions like "Which marketing channels leads to users churning after a month?" | ||
* or "What do users do on our website before signing up?" | ||
* In a purely back-end implementation, this means whenever an anonymous user does something, you'll want to send a session ID with the capture call. | ||
* Then, when that users signs up, you want to do an alias call with the session ID and the newly created user ID. | ||
* The same concept applies for when a user logs in. If you're using PostHog in the front-end and back-end, | ||
* doing the identify call in the frontend will be enough.: | ||
* @param distinctId the current unique id | ||
* @param alias the unique ID of the user before | ||
*/ | ||
alias(data: { distinctId: string; alias: string }): PostHog | ||
} | ||
} |
435
index.js
@@ -15,268 +15,271 @@ 'use strict' | ||
class PostHog { | ||
/** | ||
* Initialize a new `PostHog` with your PostHog project's `apiKey` and an | ||
* optional dictionary of `options`. | ||
* | ||
* @param {String} apiKey | ||
* @param {Object} [options] (optional) | ||
* @property {Number} flushAt (default: 20) | ||
* @property {Number} flushInterval (default: 10000) | ||
* @property {String} host (default: 'https://app.posthog.com') | ||
* @property {Boolean} enable (default: true) | ||
*/ | ||
/** | ||
* Initialize a new `PostHog` with your PostHog project's `apiKey` and an | ||
* optional dictionary of `options`. | ||
* | ||
* @param {String} apiKey | ||
* @param {Object} [options] (optional) | ||
* @property {Number} flushAt (default: 20) | ||
* @property {Number} flushInterval (default: 10000) | ||
* @property {String} host (default: 'https://app.posthog.com') | ||
* @property {Boolean} enable (default: true) | ||
*/ | ||
constructor (apiKey, options) { | ||
options = options || {} | ||
constructor(apiKey, options) { | ||
options = options || {} | ||
assert(apiKey, 'You must pass your PostHog project\'s api key.') | ||
assert(apiKey, "You must pass your PostHog project's api key.") | ||
this.queue = [] | ||
this.apiKey = apiKey | ||
this.host = removeSlash(options.host || 'https://app.posthog.com') | ||
this.timeout = options.timeout || false | ||
this.flushAt = Math.max(options.flushAt, 1) || 20 | ||
this.flushInterval = typeof options.flushInterval === 'number' ? options.flushInterval : 10000 | ||
this.flushed = false | ||
Object.defineProperty(this, 'enable', { | ||
configurable: false, | ||
writable: false, | ||
enumerable: true, | ||
value: typeof options.enable === 'boolean' ? options.enable : true | ||
}) | ||
this.queue = [] | ||
this.apiKey = apiKey | ||
this.host = removeSlash(options.host || 'https://app.posthog.com') | ||
this.timeout = options.timeout || false | ||
this.flushAt = Math.max(options.flushAt, 1) || 20 | ||
this.flushInterval = typeof options.flushInterval === 'number' ? options.flushInterval : 10000 | ||
this.flushed = false | ||
Object.defineProperty(this, 'enable', { | ||
configurable: false, | ||
writable: false, | ||
enumerable: true, | ||
value: typeof options.enable === 'boolean' ? options.enable : true, | ||
}) | ||
axiosRetry(axios, { | ||
retries: options.retryCount || 3, | ||
retryCondition: this._isErrorRetryable, | ||
retryDelay: axiosRetry.exponentialDelay | ||
}) | ||
} | ||
axiosRetry(axios, { | ||
retries: options.retryCount || 3, | ||
retryCondition: this._isErrorRetryable, | ||
retryDelay: axiosRetry.exponentialDelay, | ||
}) | ||
} | ||
_validate (message, type) { | ||
try { | ||
looselyValidate(message, type) | ||
} catch (e) { | ||
if (e.message === 'Your message must be < 32kb.') { | ||
console.log('Your message must be < 32kb. This is currently surfaced as a warning to allow clients to update. Versions released after August 1, 2018 will throw an error instead. Please update your code before then.', message) | ||
return | ||
} | ||
throw e | ||
_validate(message, type) { | ||
try { | ||
looselyValidate(message, type) | ||
} catch (e) { | ||
if (e.message === 'Your message must be < 32kb.') { | ||
console.log( | ||
'Your message must be < 32kb. This is currently surfaced as a warning to allow clients to update. Versions released after August 1, 2018 will throw an error instead. Please update your code before then.', | ||
message | ||
) | ||
return | ||
} | ||
throw e | ||
} | ||
} | ||
} | ||
/** | ||
* Send an identify `message`. | ||
* | ||
* @param {Object} message | ||
* @param {Function} [callback] (optional) | ||
* @return {PostHog} | ||
*/ | ||
/** | ||
* Send an identify `message`. | ||
* | ||
* @param {Object} message | ||
* @param {Function} [callback] (optional) | ||
* @return {PostHog} | ||
*/ | ||
identify (message, callback) { | ||
this._validate(message, 'identify') | ||
identify(message, callback) { | ||
this._validate(message, 'identify') | ||
const apiMessage = Object.assign({}, message, { | ||
'$set': message.properties || {}, | ||
event: '$identify', | ||
properties: { | ||
'$lib': 'posthog-node', | ||
'$lib_version': version | ||
} | ||
}) | ||
const apiMessage = Object.assign({}, message, { | ||
$set: message.properties || {}, | ||
event: '$identify', | ||
properties: { | ||
$lib: 'posthog-node', | ||
$lib_version: version, | ||
}, | ||
}) | ||
this.enqueue('identify', apiMessage, callback) | ||
return this | ||
} | ||
this.enqueue('identify', apiMessage, callback) | ||
return this | ||
} | ||
/** | ||
* Send a capture `message`. | ||
* | ||
* @param {Object} message | ||
* @param {Function} [callback] (optional) | ||
* @return {PostHog} | ||
*/ | ||
/** | ||
* Send a capture `message`. | ||
* | ||
* @param {Object} message | ||
* @param {Function} [callback] (optional) | ||
* @return {PostHog} | ||
*/ | ||
capture (message, callback) { | ||
this._validate(message, 'capture') | ||
capture(message, callback) { | ||
this._validate(message, 'capture') | ||
const apiMessage = Object.assign({}, message, { | ||
properties: Object.assign({}, message.properties, { | ||
'$lib': 'posthog-node', | ||
'$lib_version': version | ||
}) | ||
}) | ||
const apiMessage = Object.assign({}, message, { | ||
properties: Object.assign({}, message.properties, { | ||
$lib: 'posthog-node', | ||
$lib_version: version, | ||
}), | ||
}) | ||
this.enqueue('capture', apiMessage, callback) | ||
return this | ||
} | ||
this.enqueue('capture', apiMessage, callback) | ||
return this | ||
} | ||
/** | ||
* Send an alias `message`. | ||
* | ||
* @param {Object} message | ||
* @param {Function} [callback] (optional) | ||
* @return {PostHog} | ||
*/ | ||
/** | ||
* Send an alias `message`. | ||
* | ||
* @param {Object} message | ||
* @param {Function} [callback] (optional) | ||
* @return {PostHog} | ||
*/ | ||
alias (message, callback) { | ||
this._validate(message, 'alias') | ||
alias(message, callback) { | ||
this._validate(message, 'alias') | ||
const apiMessage = Object.assign({}, message, { | ||
event: '$create_alias', | ||
properties: { | ||
distinct_id: message.distinctId || message.distinct_id, | ||
alias: message.alias, | ||
'$lib': 'posthog-node', | ||
'$lib_version': version | ||
} | ||
}) | ||
delete apiMessage.alias | ||
delete apiMessage.distinctId | ||
apiMessage.distinct_id = null | ||
const apiMessage = Object.assign({}, message, { | ||
event: '$create_alias', | ||
properties: { | ||
distinct_id: message.distinctId || message.distinct_id, | ||
alias: message.alias, | ||
$lib: 'posthog-node', | ||
$lib_version: version, | ||
}, | ||
}) | ||
delete apiMessage.alias | ||
delete apiMessage.distinctId | ||
apiMessage.distinct_id = null | ||
this.enqueue('alias', apiMessage, callback) | ||
return this | ||
} | ||
this.enqueue('alias', apiMessage, callback) | ||
return this | ||
} | ||
/** | ||
* Add a `message` of type `type` to the queue and | ||
* check whether it should be flushed. | ||
* | ||
* @param {String} type | ||
* @param {Object} message | ||
* @param {Function} [callback] (optional) | ||
* @api private | ||
*/ | ||
/** | ||
* Add a `message` of type `type` to the queue and | ||
* check whether it should be flushed. | ||
* | ||
* @param {String} type | ||
* @param {Object} message | ||
* @param {Function} [callback] (optional) | ||
* @api private | ||
*/ | ||
enqueue (type, message, callback) { | ||
callback = callback || noop | ||
enqueue(type, message, callback) { | ||
callback = callback || noop | ||
if (!this.enable) { | ||
return setImmediate(callback) | ||
} | ||
if (!this.enable) { | ||
return setImmediate(callback) | ||
} | ||
message = Object.assign({}, message) | ||
message.type = type | ||
message.library = 'posthog-node' | ||
message.library_version = version | ||
message = Object.assign({}, message) | ||
message.type = type | ||
message.library = 'posthog-node' | ||
message.library_version = version | ||
if (!message.timestamp) { | ||
message.timestamp = new Date() | ||
} | ||
if (!message.timestamp) { | ||
message.timestamp = new Date() | ||
} | ||
if (message.distinctId) { | ||
message.distinct_id = message.distinctId | ||
delete message.distinctId | ||
} | ||
if (message.distinctId) { | ||
message.distinct_id = message.distinctId | ||
delete message.distinctId | ||
} | ||
this.queue.push({ message, callback }) | ||
this.queue.push({ message, callback }) | ||
if (!this.flushed) { | ||
this.flushed = true | ||
this.flush() | ||
return | ||
} | ||
if (!this.flushed) { | ||
this.flushed = true | ||
this.flush() | ||
return | ||
} | ||
if (this.queue.length >= this.flushAt) { | ||
this.flush() | ||
} | ||
if (this.queue.length >= this.flushAt) { | ||
this.flush() | ||
} | ||
if (this.flushInterval && !this.timer) { | ||
this.timer = setTimeout(this.flush.bind(this), this.flushInterval) | ||
if (this.flushInterval && !this.timer) { | ||
this.timer = setTimeout(this.flush.bind(this), this.flushInterval) | ||
} | ||
} | ||
} | ||
/** | ||
* Flush the current queue | ||
* | ||
* @param {Function} [callback] (optional) | ||
* @return {PostHog} | ||
*/ | ||
/** | ||
* Flush the current queue | ||
* | ||
* @param {Function} [callback] (optional) | ||
* @return {PostHog} | ||
*/ | ||
flush (callback) { | ||
callback = callback || noop | ||
flush(callback) { | ||
callback = callback || noop | ||
if (!this.enable) { | ||
return setImmediate(callback) | ||
} | ||
if (!this.enable) { | ||
return setImmediate(callback) | ||
} | ||
if (this.timer) { | ||
clearTimeout(this.timer) | ||
this.timer = null | ||
} | ||
if (this.timer) { | ||
clearTimeout(this.timer) | ||
this.timer = null | ||
} | ||
if (!this.queue.length) { | ||
return setImmediate(callback) | ||
} | ||
if (!this.queue.length) { | ||
return setImmediate(callback) | ||
} | ||
const items = this.queue.splice(0, this.flushAt) | ||
const callbacks = items.map(item => item.callback) | ||
const messages = items.map(item => item.message) | ||
const items = this.queue.splice(0, this.flushAt) | ||
const callbacks = items.map((item) => item.callback) | ||
const messages = items.map((item) => item.message) | ||
const data = { | ||
api_key: this.apiKey, | ||
batch: messages | ||
} | ||
const data = { | ||
api_key: this.apiKey, | ||
batch: messages, | ||
} | ||
const done = err => { | ||
callbacks.forEach(callback => callback(err)) | ||
callback(err, data) | ||
} | ||
const done = (err) => { | ||
callbacks.forEach((callback) => callback(err)) | ||
callback(err, data) | ||
} | ||
// Don't set the user agent if we're not on a browser. The latest spec allows | ||
// the User-Agent header (see https://fetch.spec.whatwg.org/#terminology-headers | ||
// and https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader), | ||
// but browsers such as Chrome and Safari have not caught up. | ||
const headers = {} | ||
if (typeof window === 'undefined') { | ||
headers['user-agent'] = `posthog-node/${version}` | ||
} | ||
// Don't set the user agent if we're not on a browser. The latest spec allows | ||
// the User-Agent header (see https://fetch.spec.whatwg.org/#terminology-headers | ||
// and https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader), | ||
// but browsers such as Chrome and Safari have not caught up. | ||
const headers = {} | ||
if (typeof window === 'undefined') { | ||
headers['user-agent'] = `posthog-node/${version}` | ||
} | ||
const req = { | ||
method: 'POST', | ||
url: `${this.host}/batch/`, | ||
data, | ||
headers | ||
} | ||
const req = { | ||
method: 'POST', | ||
url: `${this.host}/batch/`, | ||
data, | ||
headers, | ||
} | ||
if (this.timeout) { | ||
req.timeout = typeof this.timeout === 'string' ? ms(this.timeout) : this.timeout | ||
if (this.timeout) { | ||
req.timeout = typeof this.timeout === 'string' ? ms(this.timeout) : this.timeout | ||
} | ||
axios(req) | ||
.then(() => done()) | ||
.catch((err) => { | ||
if (err.response) { | ||
const error = new Error(err.response.statusText) | ||
return done(error) | ||
} | ||
done(err) | ||
}) | ||
} | ||
axios(req) | ||
.then(() => done()) | ||
.catch(err => { | ||
if (err.response) { | ||
const error = new Error(err.response.statusText) | ||
return done(error) | ||
_isErrorRetryable(error) { | ||
// Retry Network Errors. | ||
if (axiosRetry.isNetworkError(error)) { | ||
return true | ||
} | ||
done(err) | ||
}) | ||
} | ||
if (!error.response) { | ||
// Cannot determine if the request can be retried | ||
return false | ||
} | ||
_isErrorRetryable (error) { | ||
// Retry Network Errors. | ||
if (axiosRetry.isNetworkError(error)) { | ||
return true | ||
} | ||
// Retry Server Errors (5xx). | ||
if (error.response.status >= 500 && error.response.status <= 599) { | ||
return true | ||
} | ||
if (!error.response) { | ||
// Cannot determine if the request can be retried | ||
return false | ||
} | ||
// Retry if rate limited. | ||
if (error.response.status === 429) { | ||
return true | ||
} | ||
// Retry Server Errors (5xx). | ||
if (error.response.status >= 500 && error.response.status <= 599) { | ||
return true | ||
return false | ||
} | ||
// Retry if rate limited. | ||
if (error.response.status === 429) { | ||
return true | ||
} | ||
return false | ||
} | ||
} | ||
module.exports = PostHog |
129
package.json
{ | ||
"name": "posthog-node", | ||
"version": "1.0.10", | ||
"description": "PostHog Node.js integration", | ||
"license": "MIT", | ||
"repository": "PostHog/posthog-node", | ||
"author": { | ||
"name": "PostHog", | ||
"email": "hey@posthog.com", | ||
"url": "https://posthog.com" | ||
}, | ||
"engines": { | ||
"node": ">=4" | ||
}, | ||
"size-limit": [ | ||
{ | ||
"limit": "25 KB", | ||
"path": "index.js" | ||
"name": "posthog-node", | ||
"version": "1.0.11", | ||
"description": "PostHog Node.js integration", | ||
"license": "MIT", | ||
"repository": "PostHog/posthog-node", | ||
"author": { | ||
"name": "PostHog", | ||
"email": "hey@posthog.com", | ||
"url": "https://posthog.com" | ||
}, | ||
"engines": { | ||
"node": ">=4" | ||
}, | ||
"size-limit": [ | ||
{ | ||
"limit": "25 KB", | ||
"path": "index.js" | ||
} | ||
], | ||
"scripts": { | ||
"dependencies": "yarn", | ||
"size": "size-limit", | ||
"test": "nyc ava", | ||
"report-coverage": "nyc report --reporter=lcov > coverage.lcov && codecov", | ||
"format": "prettier --write ." | ||
}, | ||
"files": [ | ||
"index.js", | ||
"index.d.ts", | ||
"event-validation.js", | ||
"cli.js" | ||
], | ||
"bin": { | ||
"posthog": "cli.js" | ||
}, | ||
"keywords": [ | ||
"posthog", | ||
"stats", | ||
"analysis", | ||
"funnels" | ||
], | ||
"dependencies": { | ||
"axios": "^0.21.1", | ||
"axios-retry": "^3.1.9", | ||
"component-type": "^1.2.1", | ||
"join-component": "^1.1.0", | ||
"md5": "^2.3.0", | ||
"ms": "^2.1.3", | ||
"remove-trailing-slash": "^0.1.1", | ||
"uuid": "^8.3.2" | ||
}, | ||
"devDependencies": { | ||
"ava": "^0.25.0", | ||
"basic-auth": "^2.0.1", | ||
"body-parser": "^1.17.1", | ||
"codecov": "^3.0.0", | ||
"commander": "^2.9.0", | ||
"delay": "^4.2.0", | ||
"express": "^4.15.2", | ||
"nyc": "^14.1.1", | ||
"pify": "^4.0.1", | ||
"prettier": "^2.3.1", | ||
"sinon": "^7.3.2", | ||
"size-limit": "^1.3.5", | ||
"snyk": "^1.171.1" | ||
} | ||
], | ||
"scripts": { | ||
"dependencies": "yarn", | ||
"size": "size-limit", | ||
"test": "standard && nyc ava", | ||
"report-coverage": "nyc report --reporter=lcov > coverage.lcov && codecov" | ||
}, | ||
"files": [ | ||
"index.js", | ||
"index.d.ts", | ||
"event-validation.js", | ||
"cli.js" | ||
], | ||
"bin": { | ||
"posthog": "cli.js" | ||
}, | ||
"keywords": [ | ||
"posthog", | ||
"stats", | ||
"analysis", | ||
"funnels" | ||
], | ||
"dependencies": { | ||
"axios": "^0.21.1", | ||
"axios-retry": "^3.1.9", | ||
"component-type": "^1.2.1", | ||
"join-component": "^1.1.0", | ||
"md5": "^2.3.0", | ||
"ms": "^2.1.3", | ||
"remove-trailing-slash": "^0.1.1", | ||
"uuid": "^8.3.2" | ||
}, | ||
"devDependencies": { | ||
"ava": "^0.25.0", | ||
"basic-auth": "^2.0.1", | ||
"body-parser": "^1.17.1", | ||
"codecov": "^3.0.0", | ||
"commander": "^2.9.0", | ||
"delay": "^4.2.0", | ||
"express": "^4.15.2", | ||
"nyc": "^14.1.1", | ||
"pify": "^4.0.1", | ||
"sinon": "^7.3.2", | ||
"size-limit": "^1.3.5", | ||
"snyk": "^1.171.1", | ||
"standard": "^12.0.1" | ||
} | ||
} |
@@ -10,1 +10,11 @@ # PostHog NodeJS | ||
### [Join our Slack community.](https://join.slack.com/t/posthogusers/shared_invite/enQtOTY0MzU5NjAwMDY3LTc2MWQ0OTZlNjhkODk3ZDI3NDVjMDE1YjgxY2I4ZjI4MzJhZmVmNjJkN2NmMGJmMzc2N2U3Yjc3ZjI5NGFlZDQ) | ||
## Development | ||
### How to Release | ||
1. Run `npm version patch` (or minor/major) | ||
3. Run `npm publish` | ||
## Thank You | ||
This library is largely based on the `analytics-node` package. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
18095
427
20
1