feat: Add Be and tbd skill, also added Roadmap file

This commit is contained in:
2026-05-10 16:32:12 -04:00
parent 3500ade13f
commit 0bb8885802
29587 changed files with 10611695 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
.nyc_output
coverage
node_modules

View File

@@ -0,0 +1,15 @@
1.1.1 / 2017-02-02
==================
* circle: fix publishing
1.1.0 / 2017-02-02
==================
* add optional `type` argument
1.0.0 / 2017-02-02
==================
* Initial commit

View File

@@ -0,0 +1,19 @@
# @segment/loosely-validate-event
Loosely validate an event.
## Example
```js
const validate = require('@segment/loosely-validate-event')
const event = {
type: 'track',
userId: 'abc123',
properties: {
foo: 'bar'
}
}
validate(event) // throws if `event` does not pass validation
```

View File

@@ -0,0 +1,25 @@
machine:
node:
version: 6
dependencies:
pre:
- npm config set "//registry.npmjs.org/:_authToken" $NPM_AUTH
- sudo apt-key adv --fetch-keys http://dl.yarnpkg.com/debian/pubkey.gpg
- echo "deb http://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
- sudo apt-get update -qq
- sudo apt-get install -y -qq yarn
cache_directories:
- ~/.yarn-cache
override:
- yarn
test:
override:
- yarn test
deployment:
publish:
tag: /v?[0-9]+(\.[0-9]+)*(-.+)?/
commands:
- npm publish

View File

@@ -0,0 +1,121 @@
var type = require('component-type')
var join = require('join-component')
var assert = require('assert')
module.exports = looselyValidateEvent
/**
* Validate an event.
*/
function looselyValidateEvent (event, type) {
validateGenericEvent(event)
type = type || event.type
assert(type, 'You must pass an event type.')
switch (type) {
case 'track':
return validateTrackEvent(event)
case 'group':
return validateGroupEvent(event)
case 'identify':
return validateIdentifyEvent(event)
case 'page':
return validatePageEvent(event)
case 'screen':
return validateScreenEvent(event)
case 'alias':
return validateAliasEvent(event)
default:
assert(0, 'Invalid event type: "' + type + '"')
}
}
/**
* Validate a "track" event.
*/
function validateTrackEvent (event) {
assert(event.anonymousId || event.userId, 'You must pass either an "anonymousId" or a "userId".')
assert(event.event, 'You must pass an "event".')
}
/**
* Validate a "group" event.
*/
function validateGroupEvent (event) {
assert(event.anonymousId || event.userId, 'You must pass either an "anonymousId" or a "userId".')
assert(event.groupId, 'You must pass a "groupId".')
}
/**
* Validate a "identify" event.
*/
function validateIdentifyEvent (event) {
assert(event.anonymousId || event.userId, 'You must pass either an "anonymousId" or a "userId".')
}
/**
* Validate a "page" event.
*/
function validatePageEvent (event) {
assert(event.anonymousId || event.userId, 'You must pass either an "anonymousId" or a "userId".')
}
/**
* Validate a "screen" event.
*/
function validateScreenEvent (event) {
assert(event.anonymousId || event.userId, 'You must pass either an "anonymousId" or a "userId".')
}
/**
* Validate an "alias" event.
*/
function validateAliasEvent (event) {
assert(event.userId, 'You must pass a "userId".')
assert(event.previousId, 'You must pass a "previousId".')
}
/**
* Validation rules.
*/
var genericValidationRules = {
anonymousId: [ 'string', 'number' ],
category: 'string',
context: 'object',
event: 'string',
groupId: [ 'string', 'number' ],
integrations: 'object',
name: 'string',
previousId: [ 'string', 'number' ],
timestamp: 'date',
userId: [ 'string', 'number' ],
type: 'string'
}
/**
* Validate an event object.
*/
function validateGenericEvent (event) {
assert(type(event) === 'object', 'You must pass a message object.')
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') + '.'
)
}
}

View File

@@ -0,0 +1,24 @@
{
"name": "@segment/loosely-validate-event",
"version": "1.1.2",
"main": "index.js",
"scripts": {
"test": "ava",
"coverage": "nyc ava"
},
"devDependencies": {
"ava": "^0.18.0",
"nyc": "^10.1.2",
"standard": "^8.6.0"
},
"dependencies": {
"component-type": "^1.2.1",
"join-component": "^1.1.0"
},
"nyc": {
"reporter": [
"lcov",
"html"
]
}
}

View File

@@ -0,0 +1,258 @@
var test = require('ava')
var AssertionError = require('assert').AssertionError
var validate = require('./')
test('requires "anonymousId" to be a string or number', t => {
const event = {
type: 'track',
anonymousId: { foo: 'bar' }
}
t.throws(() => {
validate(event)
}, '"anonymousId" must be a string or number.')
})
test('requires "category" to be a string', t => {
const event = {
type: 'track',
category: true
}
t.throws(() => {
validate(event)
}, '"category" must be a string.')
})
test('requires "integrations" to be an object', t => {
const event = {
type: 'track',
integrations: true
}
t.throws(() => {
validate(event)
}, '"integrations" must be an object.')
})
test('requires an event type', t => {
t.throws(() => {
validate({})
}, AssertionError)
t.throws(() => {
validate({ type: '' }, null)
}, AssertionError)
})
test('requires a valid event type', t => {
t.throws(() => {
validate({ type: 'banana' })
}, 'Invalid event type: "banana"')
})
test('requires anonymousId or userId on track events', t => {
t.throws(() => {
validate({
type: 'track',
event: 'Did Something'
})
}, 'You must pass either an "anonymousId" or a "userId".')
t.throws(() => {
validate({
type: 'track',
event: 'Did Something',
fooId: 'banana'
})
}, 'You must pass either an "anonymousId" or a "userId".')
t.notThrows(() => {
validate({
event: 'Did Something',
anonymousId: 'banana'
}, 'track')
})
t.notThrows(() => {
validate({
type: 'track',
event: 'Did Something',
userId: 'banana'
})
})
})
test('requires event on track events', t => {
t.throws(() => {
validate({
type: 'track',
userId: 'banana'
})
}, 'You must pass an "event".')
t.notThrows(() => {
validate({
type: 'track',
event: 'Did Something',
userId: 'banana'
})
})
})
test('requires anonymousId or userId on group events', t => {
t.throws(() => {
validate({
type: 'group',
groupId: 'foo'
})
}, 'You must pass either an "anonymousId" or a "userId".')
t.throws(() => {
validate({
type: 'group',
groupId: 'foo',
fooId: 'banana'
})
}, 'You must pass either an "anonymousId" or a "userId".')
t.notThrows(() => {
validate({
type: 'group',
groupId: 'foo',
anonymousId: 'banana'
})
})
t.notThrows(() => {
validate({
type: 'group',
groupId: 'foo',
userId: 'banana'
})
})
})
test('requires groupId on group events', t => {
t.throws(() => {
validate({
type: 'group',
userId: 'banana'
})
}, 'You must pass a "groupId".')
t.notThrows(() => {
validate({
type: 'group',
groupId: 'foo',
userId: 'banana'
})
})
})
test('requires anonymousId or userId on identify events', t => {
t.throws(() => {
validate({
type: 'identify'
})
}, 'You must pass either an "anonymousId" or a "userId".')
t.throws(() => {
validate({
type: 'identify',
fooId: 'banana'
})
}, 'You must pass either an "anonymousId" or a "userId".')
t.notThrows(() => {
validate({
type: 'identify',
anonymousId: 'banana'
})
})
t.notThrows(() => {
validate({
type: 'identify',
userId: 'banana'
})
})
})
test('requires anonymousId or userId on page events', t => {
t.throws(() => {
validate({
type: 'page'
})
}, 'You must pass either an "anonymousId" or a "userId".')
t.throws(() => {
validate({
type: 'page',
fooId: 'banana'
})
}, 'You must pass either an "anonymousId" or a "userId".')
t.notThrows(() => {
validate({
type: 'page',
anonymousId: 'banana'
})
})
t.notThrows(() => {
validate({
type: 'page',
userId: 'banana'
})
})
})
test('requires anonymousId or userId on screen events', t => {
t.throws(() => {
validate({
type: 'screen'
})
}, 'You must pass either an "anonymousId" or a "userId".')
t.throws(() => {
validate({
type: 'screen',
fooId: 'banana'
})
}, 'You must pass either an "anonymousId" or a "userId".')
t.notThrows(() => {
validate({
type: 'screen',
anonymousId: 'banana'
})
})
t.notThrows(() => {
validate({
type: 'screen',
userId: 'banana'
})
})
})
test('requires userId on alias events', t => {
t.throws(() => {
validate({
type: 'alias'
})
}, 'You must pass a "userId".')
t.throws(() => {
validate({
type: 'alias',
fooId: 'banana'
})
}, 'You must pass a "userId".')
t.notThrows(() => {
validate({
type: 'alias',
userId: 'banana',
previousId: 'apple'
})
})
})

File diff suppressed because it is too large Load Diff