From 6cce0f7607de60b94f091bcb8ed55c2750ce6640 Mon Sep 17 00:00:00 2001 From: Colin Date: Tue, 5 Mar 2019 17:24:11 -0800 Subject: [PATCH] fix: handle values with multiple types (including null) [SCH-1643] (#57) This PR extends our test suite to cover JSON Schemas with properties that specify union types (`type: ["string", "number"]`), including union types with a `null` type (`type: ["string", "null"]`). Specifically, this resolves an issue with the Android client not generating enums (and instead crashing during `typewriter gen-android`). ------ While testing the example Android app against Turo's inferred spec, I also noticed that there were collisions between property key names, because similar properties (like `optional any` and `optional_any`) would map to the same key identifier (`OPTIONAL_ANY_KEY`). This was fixed by inlining these values. ------- I also identified an issue with event name collisions, specifically if you have two event names that differ by delimiter characters (f.e. `check_in_event` and `checkin_event`). They both map to the same filename (causing one of the files to be overwritten). In this example case, `CheckInEvent.java` and `CheckinEvent.java` (note: file systems are case-insensitive). Java will end up complaining because the class name (either `CheckInEvent` or `CheckinEvent`) differs from the filename. This can be solved by an upstream PR to QuickType ([see our conversation in Slack](https://quicktype.slack.com/archives/C68E91E8J/p1551486779009600)), but I'm not going to block this PR on that. The fix would be to make the `Namer` case-insensitive so that it uses a suffix in both the class and file names to differentiate between these events. The simplest solution for affected users is to remove all but one of the colliding events. Usually these events appear due to inferring on bad data, so it usually won't be a problem. I've added a warning that notifies users when their Tracking Plan contains events that collide in Android. ------ I also made a few refactoring changes: - The logic to generate QuickType's `inputData` is duplicated across all QuickType-based clients, so I moved that out to `utils/rules.ts` - Removed `PropertiesSerializable` because it wasn't necessary --- .../segment/analytics/KicksAppAnalytics.java | 1 + .../com/segment/analytics/OrderCompleted.java | 44 +-- .../java/com/segment/analytics/Product.java | 45 +-- .../analytics/PropertiesSerializable.java | 17 - src/commands/gen-android.ts | 131 ++------ src/commands/gen-ios.ts | 28 +- src/commands/gen-js/typescript.ts | 24 +- src/lib/rules.ts | 29 +- tests/__fixtures__/tracking-plan-fixture.json | 67 +++- .../__snapshots__/ExampleEvent.java | 131 ++++---- .../__snapshots__/NumberOrString.java | 10 + .../__snapshots__/OptionalArray.java | 17 +- .../__snapshots__/OptionalObject.java | 17 +- .../__snapshots__/PropertiesSerializable.java | 17 - .../__snapshots__/RequiredArray.java | 17 +- .../__snapshots__/RequiredObject.java | 17 +- .../TestTrackingPlanAnalytics.java | 45 ++- .../The42_TerribleEventName3.java | 24 +- .../SEGTestTrackingPlanAnalytics.h | 32 +- .../SEGTestTrackingPlanAnalytics.m | 54 ++- .../gen-js/__snapshots__/index.amd.js | 296 +++++++++++++++-- .../commands/gen-js/__snapshots__/index.d.ts | 36 +- .../gen-js/__snapshots__/index.es5.js | 309 +++++++++++++++-- .../gen-js/__snapshots__/index.es5.node.js | 297 +++++++++++++++-- tests/commands/gen-js/__snapshots__/index.js | 299 +++++++++++++++-- .../gen-js/__snapshots__/index.node.d.ts | 40 ++- .../gen-js/__snapshots__/index.node.js | 291 ++++++++++++++-- .../gen-js/__snapshots__/index.prod.js | 30 +- .../gen-js/__snapshots__/index.prod.node.js | 22 +- .../gen-js/__snapshots__/index.system.js | 310 ++++++++++++++++-- .../gen-js/__snapshots__/index.umd.js | 296 +++++++++++++++-- 31 files changed, 2358 insertions(+), 635 deletions(-) delete mode 100644 examples/gen-android/java/app/src/main/java/com/segment/analytics/PropertiesSerializable.java create mode 100644 tests/commands/gen-android/__snapshots__/NumberOrString.java delete mode 100644 tests/commands/gen-android/__snapshots__/PropertiesSerializable.java diff --git a/examples/gen-android/java/app/src/main/java/com/segment/analytics/KicksAppAnalytics.java b/examples/gen-android/java/app/src/main/java/com/segment/analytics/KicksAppAnalytics.java index b535765c..aa1f54bb 100644 --- a/examples/gen-android/java/app/src/main/java/com/segment/analytics/KicksAppAnalytics.java +++ b/examples/gen-android/java/app/src/main/java/com/segment/analytics/KicksAppAnalytics.java @@ -1,6 +1,7 @@ // This code is auto-generated by Segment Typewriter. Do not edit. package com.segment.analytics; +import java.util.*; import com.segment.analytics.Analytics; import com.segment.analytics.Options; import android.content.Context; diff --git a/examples/gen-android/java/app/src/main/java/com/segment/analytics/OrderCompleted.java b/examples/gen-android/java/app/src/main/java/com/segment/analytics/OrderCompleted.java index e1a4b8a9..d0162939 100644 --- a/examples/gen-android/java/app/src/main/java/com/segment/analytics/OrderCompleted.java +++ b/examples/gen-android/java/app/src/main/java/com/segment/analytics/OrderCompleted.java @@ -1,14 +1,10 @@ // This code is auto-generated by Segment Typewriter. Do not edit. package com.segment.analytics; +import java.util.*; import android.support.annotation.NonNull; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public final class OrderCompleted extends PropertiesSerializable { +public final class OrderCompleted { private Properties properties; private OrderCompleted(Properties properties) { @@ -23,18 +19,6 @@ protected Properties toProperties() { * Builder for {@link OrderCompleted} */ public static class Builder { - private static String AFFILIATION_KEY = "affiliation"; - private static String CHECKOUT_ID_KEY = "checkout_id"; - private static String COUPON_KEY = "coupon"; - private static String CURRENCY_KEY = "currency"; - private static String DISCOUNT_KEY = "discount"; - private static String ORDER_ID_KEY = "order_id"; - private static String PRODUCTS_KEY = "products"; - private static String REVENUE_KEY = "revenue"; - private static String SHIPPING_KEY = "shipping"; - private static String TAX_KEY = "tax"; - private static String TOTAL_KEY = "total"; - private Properties properties; /** @@ -49,7 +33,7 @@ public Builder() { * This property is optional and not required to generate a valid OrderCompleted object */ public Builder affiliation(final @NonNull String affiliation) { - properties.putValue(AFFILIATION_KEY, affiliation); + properties.putValue("affiliation", affiliation); return this; } @@ -58,7 +42,7 @@ public Builder affiliation(final @NonNull String affiliation) { * This property is optional and not required to generate a valid OrderCompleted object */ public Builder checkoutID(final @NonNull String checkoutID) { - properties.putValue(CHECKOUT_ID_KEY, checkoutID); + properties.putValue("checkout_id", checkoutID); return this; } @@ -67,7 +51,7 @@ public Builder checkoutID(final @NonNull String checkoutID) { * This property is optional and not required to generate a valid OrderCompleted object */ public Builder coupon(final @NonNull String coupon) { - properties.putValue(COUPON_KEY, coupon); + properties.putValue("coupon", coupon); return this; } @@ -76,7 +60,7 @@ public Builder coupon(final @NonNull String coupon) { * This property is optional and not required to generate a valid OrderCompleted object */ public Builder currency(final @NonNull String currency) { - properties.putValue(CURRENCY_KEY, currency); + properties.putValue("currency", currency); return this; } @@ -85,7 +69,7 @@ public Builder currency(final @NonNull String currency) { * This property is optional and not required to generate a valid OrderCompleted object */ public Builder discount(final @NonNull Double discount) { - properties.putValue(DISCOUNT_KEY, discount); + properties.putValue("discount", discount); return this; } @@ -94,7 +78,7 @@ public Builder discount(final @NonNull Double discount) { * This property is required to generate a valid OrderCompleted object */ public Builder orderID(final @NonNull String orderID) { - properties.putValue(ORDER_ID_KEY, orderID); + properties.putValue("order_id", orderID); return this; } @@ -103,7 +87,7 @@ public Builder orderID(final @NonNull String orderID) { * This property is optional and not required to generate a valid OrderCompleted object */ public Builder products(final @NonNull List products) { - properties.putValue(PRODUCTS_KEY, PropertiesSerializable.toPropertyList(products)); + properties.putValue("products", products); return this; } @@ -112,7 +96,7 @@ public Builder products(final @NonNull List products) { * This property is optional and not required to generate a valid OrderCompleted object */ public Builder revenue(final @NonNull Double revenue) { - properties.putValue(REVENUE_KEY, revenue); + properties.putValue("revenue", revenue); return this; } @@ -121,7 +105,7 @@ public Builder revenue(final @NonNull Double revenue) { * This property is optional and not required to generate a valid OrderCompleted object */ public Builder shipping(final @NonNull Double shipping) { - properties.putValue(SHIPPING_KEY, shipping); + properties.putValue("shipping", shipping); return this; } @@ -130,7 +114,7 @@ public Builder shipping(final @NonNull Double shipping) { * This property is optional and not required to generate a valid OrderCompleted object */ public Builder tax(final @NonNull Double tax) { - properties.putValue(TAX_KEY, tax); + properties.putValue("tax", tax); return this; } @@ -142,7 +126,7 @@ public Builder tax(final @NonNull Double tax) { * This property is optional and not required to generate a valid OrderCompleted object */ public Builder total(final @NonNull Double total) { - properties.putValue(TOTAL_KEY, total); + properties.putValue("total", total); return this; } @@ -152,7 +136,7 @@ public Builder total(final @NonNull Double total) { * - orderID */ public OrderCompleted build() { - if (properties.get(ORDER_ID_KEY) == null) { + if (properties.get("order_id") == null) { throw new IllegalArgumentException("OrderCompleted missing required property: orderID"); } diff --git a/examples/gen-android/java/app/src/main/java/com/segment/analytics/Product.java b/examples/gen-android/java/app/src/main/java/com/segment/analytics/Product.java index feb0e132..415e20a1 100644 --- a/examples/gen-android/java/app/src/main/java/com/segment/analytics/Product.java +++ b/examples/gen-android/java/app/src/main/java/com/segment/analytics/Product.java @@ -1,14 +1,10 @@ // This code is auto-generated by Segment Typewriter. Do not edit. package com.segment.analytics; +import java.util.*; import android.support.annotation.NonNull; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public final class Product extends PropertiesSerializable { +public final class Product { private Properties properties; private Product(Properties properties) { @@ -23,19 +19,6 @@ protected Properties toProperties() { * Builder for {@link Product} */ public static class Builder { - private static String BRAND_KEY = "brand"; - private static String CATEGORY_KEY = "category"; - private static String COUPON_KEY = "coupon"; - private static String IMAGE_URL_KEY = "image_url"; - private static String NAME_KEY = "name"; - private static String POSITION_KEY = "position"; - private static String PRICE_KEY = "price"; - private static String PRODUCT_ID_KEY = "product_id"; - private static String QUANTITY_KEY = "quantity"; - private static String SKU_KEY = "sku"; - private static String URL_KEY = "url"; - private static String VARIANT_KEY = "variant"; - private Properties properties; /** @@ -50,7 +33,7 @@ public Builder() { * This property is optional and not required to generate a valid Product object */ public Builder brand(final @NonNull String brand) { - properties.putValue(BRAND_KEY, brand); + properties.putValue("brand", brand); return this; } @@ -59,7 +42,7 @@ public Builder brand(final @NonNull String brand) { * This property is optional and not required to generate a valid Product object */ public Builder category(final @NonNull String category) { - properties.putValue(CATEGORY_KEY, category); + properties.putValue("category", category); return this; } @@ -68,7 +51,7 @@ public Builder category(final @NonNull String category) { * This property is optional and not required to generate a valid Product object */ public Builder coupon(final @NonNull String coupon) { - properties.putValue(COUPON_KEY, coupon); + properties.putValue("coupon", coupon); return this; } @@ -77,7 +60,7 @@ public Builder coupon(final @NonNull String coupon) { * This property is optional and not required to generate a valid Product object */ public Builder imageURL(final @NonNull String imageURL) { - properties.putValue(IMAGE_URL_KEY, imageURL); + properties.putValue("image_url", imageURL); return this; } @@ -86,7 +69,7 @@ public Builder imageURL(final @NonNull String imageURL) { * This property is optional and not required to generate a valid Product object */ public Builder name(final @NonNull String name) { - properties.putValue(NAME_KEY, name); + properties.putValue("name", name); return this; } @@ -95,7 +78,7 @@ public Builder name(final @NonNull String name) { * This property is optional and not required to generate a valid Product object */ public Builder position(final @NonNull Long position) { - properties.putValue(POSITION_KEY, position); + properties.putValue("position", position); return this; } @@ -104,7 +87,7 @@ public Builder position(final @NonNull Long position) { * This property is optional and not required to generate a valid Product object */ public Builder price(final @NonNull Double price) { - properties.putValue(PRICE_KEY, price); + properties.putValue("price", price); return this; } @@ -113,7 +96,7 @@ public Builder price(final @NonNull Double price) { * This property is optional and not required to generate a valid Product object */ public Builder productID(final @NonNull String productID) { - properties.putValue(PRODUCT_ID_KEY, productID); + properties.putValue("product_id", productID); return this; } @@ -122,7 +105,7 @@ public Builder productID(final @NonNull String productID) { * This property is optional and not required to generate a valid Product object */ public Builder quantity(final @NonNull Double quantity) { - properties.putValue(QUANTITY_KEY, quantity); + properties.putValue("quantity", quantity); return this; } @@ -131,7 +114,7 @@ public Builder quantity(final @NonNull Double quantity) { * This property is optional and not required to generate a valid Product object */ public Builder sku(final @NonNull String sku) { - properties.putValue(SKU_KEY, sku); + properties.putValue("sku", sku); return this; } @@ -140,7 +123,7 @@ public Builder sku(final @NonNull String sku) { * This property is optional and not required to generate a valid Product object */ public Builder url(final @NonNull String url) { - properties.putValue(URL_KEY, url); + properties.putValue("url", url); return this; } @@ -149,7 +132,7 @@ public Builder url(final @NonNull String url) { * This property is optional and not required to generate a valid Product object */ public Builder variant(final @NonNull String variant) { - properties.putValue(VARIANT_KEY, variant); + properties.putValue("variant", variant); return this; } diff --git a/examples/gen-android/java/app/src/main/java/com/segment/analytics/PropertiesSerializable.java b/examples/gen-android/java/app/src/main/java/com/segment/analytics/PropertiesSerializable.java deleted file mode 100644 index 96312ec4..00000000 --- a/examples/gen-android/java/app/src/main/java/com/segment/analytics/PropertiesSerializable.java +++ /dev/null @@ -1,17 +0,0 @@ -// This code is auto-generated by Segment Typewriter. Do not edit. -package com.segment.analytics; - -import java.util.ArrayList; -import java.util.List; - -abstract class PropertiesSerializable { - abstract Properties toProperties(); - - static List toPropertyList(List list) { - List properties = new ArrayList<>(list.size()); - for (PropertiesSerializable item : list) { - properties.add(item.toProperties()); - } - return properties; - } -} diff --git a/src/commands/gen-android.ts b/src/commands/gen-android.ts index c8adc3d2..26d3962b 100644 --- a/src/commands/gen-android.ts +++ b/src/commands/gen-android.ts @@ -1,7 +1,5 @@ import { quicktypeMultiFile, - InputData, - JSONSchemaInput, JavaRenderer, JavaTargetLanguage, RenderContext, @@ -14,7 +12,7 @@ import { import { modifySource, SerializedRenderResult } from 'quicktype-core/dist/Source' import { OptionValues, BooleanOption, StringOption } from 'quicktype-core/dist/RendererOptions' -import { javaNameStyle, javaOptions } from 'quicktype-core/dist/language/Java' +import { javaOptions } from 'quicktype-core/dist/language/Java' import { getTypedTrackHandler, @@ -24,9 +22,10 @@ import { } from '../lib/cli' import * as fs from 'fs' import * as util from 'util' -import { get, map, camelCase, upperFirst } from 'lodash' +import { map, camelCase, upperFirst } from 'lodash' import { AcronymStyleOptions } from 'quicktype-core/dist/support/Acronyms' import { getRawName } from '../lib/naming' +import { processEventsForQuickType } from '../lib/rules' const writeFile = util.promisify(fs.writeFile) @@ -37,19 +36,19 @@ export const builder = { package: { type: 'string', required: true, - description: 'Package name to use for generated classes' + description: 'Used as the package name in generated classes' }, trackingPlan: { type: 'string', required: false, - description: 'Tracking Plan name to use for generated Analytics class' + description: 'Used to name the exported Analytics class' }, language: { type: 'string', required: false, default: 'java', choices: ['java'], - description: 'Which Android language bindings to output' + description: 'Which Android language bindings to generate' } } export type Params = DefaultParams & { @@ -63,9 +62,6 @@ declare type analyticsJavaOptions = typeof javaOptions & { trackingPlan: StringOption } -function toKeyName(name: string) { - return javaNameStyle(true, true, `${name}_KEY`) -} class AnalyticsJavaTargetLanguage extends JavaTargetLanguage { public packageName: string public trackingPlan: string @@ -107,23 +103,9 @@ class AnalyticsJavaWrapperRenderer extends JavaRenderer { this.emitCommentLines(['This code is auto-generated by Segment Typewriter. Do not edit.']) } - protected emitFileHeader(importGroups: string[][]): void { + protected emitPackageAndImports(imports: string[]): void { this.emitAutogeneratedFileWarning() - this.emitLine('package ', this.options.packageName, ';') - this.ensureBlankLine() - - for (const imports of importGroups) { - for (const pkg of imports) { - this.emitLine('import ', pkg, ';') - } - this.ensureBlankLine() - } - } - - protected emitBuilderKeys(c: ClassType): void { - this.forEachClassProperty(c, 'none', (_, jsonName) => { - this.emitLine('private static String ', toKeyName(jsonName), ' = "', jsonName, '";') - }) + super.emitPackageAndImports(imports) } protected emitBuilderSetters(c: ClassType, className: Name): void { @@ -140,12 +122,7 @@ class AnalyticsJavaWrapperRenderer extends JavaRenderer { ]) const type = this.javaType(true, p.type) this.emitBlock(['public Builder ', name, '(final @NonNull ', type, ' ', name, ')'], () => { - // TODO: Is there a better way to check if this type is an array? It's really a UnionType - const value = - type instanceof Array && type[0] === 'List<' - ? ['PropertiesSerializable.toPropertyList(', name, ')'] - : [name] - this.emitLine(['properties.putValue(', toKeyName(jsonName), ', ', ...value, ');']) + this.emitLine(['properties.putValue("', jsonName, '", ', name, ');']) this.emitLine('return this;') }) }) @@ -154,7 +131,7 @@ class AnalyticsJavaWrapperRenderer extends JavaRenderer { protected emitRuntimeValidation(c: ClassType, className: Name): void { this.forEachClassProperty(c, 'none', (name, jsonName, p) => { if (!p.isOptional) { - this.emitBlock(['if (properties.get(', toKeyName(jsonName), ') == null)'], () => { + this.emitBlock(['if (properties.get("', jsonName, '") == null)'], () => { this.emitLine([ 'throw new IllegalArgumentException("', className, @@ -171,9 +148,6 @@ class AnalyticsJavaWrapperRenderer extends JavaRenderer { protected emitClassBuilderDefinition(c: ClassType, className: Name): void { this.emitDescriptionBlock([['Builder for {@link ', className, '}']]) this.emitBlock(['public static class Builder'], () => { - this.emitBuilderKeys(c) - this.ensureBlankLine() - this.emitLine('private Properties properties;') this.ensureBlankLine() @@ -208,7 +182,7 @@ class AnalyticsJavaWrapperRenderer extends JavaRenderer { }) } - protected emitPropertiesSerializableImplementation(className: Name): void { + protected emitPropertiesGetterSetter(className: Name): void { this.emitLine('private Properties properties;') this.ensureBlankLine() this.emitBlock(['private ', className, '(Properties properties)'], () => { @@ -221,44 +195,18 @@ class AnalyticsJavaWrapperRenderer extends JavaRenderer { } protected emitClassDefinition(c: ClassType, className: Name): void { - this.startFile(className) - const importGroups: string[][] = [ - ['android.support.annotation.NonNull'], - ['java.util.ArrayList', 'java.util.List', 'java.util.Map', 'java.util.stream.Collectors'] - ] - this.emitFileHeader(importGroups) + this.emitFileHeader(className, ['android.support.annotation.NonNull']) // TODO: Emit class description, once we support top-level event descriptions in JSON Schema // this.emitDescription(this.descriptionForType(c)); this.emitClassAttributes(c, className) - this.emitBlock(['public final class ', className, ' extends PropertiesSerializable'], () => { - this.emitPropertiesSerializableImplementation(className) + this.emitBlock(['public final class ', className], () => { + this.emitPropertiesGetterSetter(className) this.ensureBlankLine() this.emitClassBuilderDefinition(c, className) }) this.finishFile() } - protected emitPropertiesSerializableInterface() { - this.startFile('PropertiesSerializable') - const importGroups: string[][] = [['java.util.ArrayList', 'java.util.List']] - this.emitFileHeader(importGroups) - this.emitBlock('abstract class PropertiesSerializable', () => { - this.emitLine('abstract Properties toProperties();') - this.ensureBlankLine() - this.emitBlock( - 'static List toPropertyList(List list)', - () => { - this.emitLine('List properties = new ArrayList<>(list.size());') - this.emitBlock('for (PropertiesSerializable item : list)', () => { - this.emitLine('properties.add(item.toProperties());') - }) - this.emitLine('return properties;') - } - ) - }) - this.finishFile() - } - protected emitAnalyticsEventWrapper( name: Name, hasProperties: boolean, @@ -303,15 +251,12 @@ class AnalyticsJavaWrapperRenderer extends JavaRenderer { protected emitAnalyticsWrapper(): void { const className = upperFirst(camelCase(`${this.options.trackingPlan || ''}Analytics`)) - this.startFile(className) - this.emitFileHeader([ - [ - 'com.segment.analytics.Analytics', - 'com.segment.analytics.Options', - 'android.content.Context', - 'android.support.annotation.NonNull', - 'android.support.annotation.Nullable' - ] + this.emitFileHeader(className, [ + 'com.segment.analytics.Analytics', + 'com.segment.analytics.Options', + 'android.content.Context', + 'android.support.annotation.NonNull', + 'android.support.annotation.Nullable' ]) this.emitBlock(['public class ', className], () => { this.emitLine('private Analytics analytics;') @@ -344,7 +289,6 @@ class AnalyticsJavaWrapperRenderer extends JavaRenderer { protected emitSourceStructure(): void { super.emitSourceStructure() - this.emitPropertiesSerializableInterface() this.emitAnalyticsWrapper() } } @@ -353,26 +297,10 @@ export async function genJava( events: TrackedEvent[], { package: packageName, trackingPlan }: Params ) { - const inputData = new InputData() - - events.forEach(({ name, rules }) => { - const schema = { - $schema: rules.$schema || 'http://json-schema.org/draft-07/schema#', - title: rules.title, - description: rules.description, - ...get(rules, 'properties.properties', {}) - } - - inputData.addSource( - 'schema', - { name, uris: [name], schema: JSON.stringify(schema) }, - () => new JSONSchemaInput(undefined) - ) + return quicktypeMultiFile({ + lang: new AnalyticsJavaTargetLanguage(packageName, trackingPlan), + inputData: processEventsForQuickType(events) }) - - const lang = new AnalyticsJavaTargetLanguage(packageName, trackingPlan) - - return await quicktypeMultiFile({ lang, inputData }) } export const handler = getTypedTrackHandler(async (params: Params, { events }) => { @@ -384,8 +312,21 @@ export const handler = getTypedTrackHandler(async (params: Params, { events }) = throw new Error(`Invalid language: ${params.language}`) } + // Handle filename naming collisions. Note that many filesystems are case-insensitive, + // so CheckIn.java === Checkin.java + // This is a temporary solution, until an upstream PR can be made to QuickType. + // See: https://quicktype.slack.com/archives/C68E91E8J/p1551486779009600 + const seenFilenames: Set = new Set() + return Promise.all( map([...files.keys()], (fileName: string) => { + if (seenFilenames.has(fileName.toLowerCase())) { + console.warn( + `Multiple events in your Tracking Plan map to the same filename (${fileName}). Consider removing or changing one of these events. If this is a blocker, please open an issue: https://github.com/segmentio/typewriter/issues/new` + ) + } + seenFilenames.add(fileName.toLowerCase()) + return writeFile(`${params.outputPath}/${fileName}`, files.get(fileName)!.lines.join('\n')) }) ) diff --git a/src/commands/gen-ios.ts b/src/commands/gen-ios.ts index 09756a08..caaa7216 100644 --- a/src/commands/gen-ios.ts +++ b/src/commands/gen-ios.ts @@ -1,7 +1,5 @@ import { quicktypeMultiFile, - InputData, - JSONSchemaInput, ObjectiveCTargetLanguage, ObjectiveCRenderer, RenderContext, @@ -27,7 +25,8 @@ import { getRawName } from '../lib/naming' import { version } from '../../package.json' import * as fs from 'fs' import * as util from 'util' -import { map, camelCase, upperFirst, get } from 'lodash' +import { map, camelCase, upperFirst } from 'lodash' +import { processEventsForQuickType } from '../lib/rules' const writeFile = util.promisify(fs.writeFile) @@ -571,27 +570,10 @@ class AnalyticsObjectiveCWrapperRenderer extends ObjectiveCRenderer { } export async function genObjC(events: TrackedEvent[], { trackingPlan, classPrefix }: Params) { - const inputData = new InputData() - - events.forEach(({ name, rules }) => { - const schema = { - $schema: rules.$schema || 'http://json-schema.org/draft-07/schema#', - title: rules.title, - description: rules.description, - ...get(rules, 'properties.properties', {}) - } - - inputData.addSource( - 'schema', - { name, uris: [name], schema: JSON.stringify(schema) }, - () => new JSONSchemaInput(undefined) - ) + return quicktypeMultiFile({ + lang: new AnalyticsObjectiveCTargetLanguage(trackingPlan, classPrefix), + inputData: processEventsForQuickType(events) }) - - const lang = new AnalyticsObjectiveCTargetLanguage(trackingPlan, classPrefix) - - const files = await quicktypeMultiFile({ lang, inputData }) - return files } export const handler = getTypedTrackHandler(async (params: Params, { events }) => { diff --git a/src/commands/gen-js/typescript.ts b/src/commands/gen-js/typescript.ts index 849e4d09..0160bbf1 100644 --- a/src/commands/gen-js/typescript.ts +++ b/src/commands/gen-js/typescript.ts @@ -23,6 +23,7 @@ import { isES3IdentifierStart } from 'quicktype-core/dist/language/JavaScriptUni import { AcronymStyleOptions } from 'quicktype-core/dist/support/Acronyms' import { Client } from '.' +import { processEventsForQuickType } from '../../lib/rules' declare interface Options { client: Client @@ -352,28 +353,9 @@ export async function genTSDeclarations( events: TrackedEvent[], client = Client.js ): Promise { - const inputData = new InputData() - - events.forEach(({ name, rules }) => { - const schema = { - $schema: rules.$schema || 'http://json-schema.org/draft-07/schema#', - title: rules.title, - description: rules.description, - ...get(rules, 'properties.properties', {}) - } - - inputData.addSource( - 'schema', - { name, uris: [name], schema: JSON.stringify(schema) }, - () => new JSONSchemaInput(undefined) - ) - }) - - const lang = new AJSTSDeclarationsTargetLanguage(client) - const { lines } = await quicktype({ - lang, - inputData, + lang: new AJSTSDeclarationsTargetLanguage(client), + inputData: processEventsForQuickType(events), rendererOptions: { 'nice-property-names': 'true' } }) diff --git a/src/lib/rules.ts b/src/lib/rules.ts index 3f692616..683106e0 100644 --- a/src/lib/rules.ts +++ b/src/lib/rules.ts @@ -1,6 +1,8 @@ import * as omitDeep from 'omit-deep-lodash' import * as sortKeys from 'sort-keys' -import { flow } from 'lodash' +import { flow, get } from 'lodash' +import { InputData, JSONSchemaInput } from 'quicktype-core' +import { TrackedEvent } from './api' /** * Remove all instances of `required: []` from a JSON Schema. @@ -44,3 +46,28 @@ export const preprocessRules = flow( (rules: any) => sortKeys(rules, { deep: true }), (rules: any) => omitDeep(rules, 'id') ) + +/** + * Generates a QuickType InputData object that contains all JSON Schemas + * from a set of Events. + */ +export const processEventsForQuickType = (events: TrackedEvent[]) => { + const inputData = new InputData() + + events.forEach(({ name, rules }) => { + const schema = { + $schema: rules.$schema || 'http://json-schema.org/draft-07/schema#', + title: rules.title, + description: rules.description, + ...get(rules, 'properties.properties', {}) + } + + inputData.addSource( + 'schema', + { name, uris: [name], schema: JSON.stringify(schema) }, + () => new JSONSchemaInput(undefined) + ) + }) + + return inputData +} diff --git a/tests/__fixtures__/tracking-plan-fixture.json b/tests/__fixtures__/tracking-plan-fixture.json index 14990321..70dfedbc 100644 --- a/tests/__fixtures__/tracking-plan-fixture.json +++ b/tests/__fixtures__/tracking-plan-fixture.json @@ -12,6 +12,9 @@ "0000---terrible-property-name~!3": { "description": "Really, don't do this." }, + "identifierId": { + "description": "Duplicate key error in Android" + }, "identifier_id": { "description": "AcronymStyle bug fixed in v5.0.1", "key": "identifier_id" @@ -24,6 +27,34 @@ "type": "object" } }, + { + "description": "This is JSON Schema draft-04 event.", + "name": "Draft-04 Event", + "rules": { + "$schema": "http://json-schema.org/draft-04/schema#", + "properties": { + "context": {}, + "properties": { "type": "object" }, + "traits": {} + }, + "required": ["properties"], + "type": "object" + } + }, + { + "description": "This is JSON Schema draft-06 event.", + "name": "Draft-06 Event", + "rules": { + "$schema": "http://json-schema.org/draft-06/schema#", + "properties": { + "context": {}, + "properties": { "type": "object" }, + "traits": {} + }, + "required": ["properties"], + "type": "object" + } + }, { "description": "This is an empty event.", "name": "Empty Event", @@ -79,10 +110,18 @@ "description": "Optional integer property", "type": "integer" }, + "optional nullable string": { + "description": "", + "type": ["string", "null"] + }, "optional number": { "description": "Optional number property", "type": "number" }, + "optional number or string": { + "description": "", + "type": ["number", "string"] + }, "optional object": { "description": "Optional object property", "key": "optional object", @@ -152,11 +191,19 @@ "description": "Required integer property", "type": "integer" }, + "required nullable string": { + "description": "", + "type": ["string", "null"] + }, "required number": { "description": "Required number property", "key": "required number", "type": "number" }, + "required number or string": { + "description": "", + "type": ["number", "string"] + }, "required object": { "description": "Required object property", "key": "required object", @@ -198,7 +245,9 @@ "required array (empty)", "required array", "required object (empty)", - "required object" + "required object", + "required number or string", + "required nullable string" ], "type": "object" }, @@ -209,30 +258,30 @@ } }, { - "description": "This is JSON Schema draft-04 event.", - "name": "Draft-04 Event", + "description": "checkin != check_in bug", + "name": "check_in", "rules": { - "$schema": "http://json-schema.org/draft-04/schema#", + "$schema": "http://json-schema.org/draft-07/schema#", + "labels": {}, "properties": { "context": {}, "properties": { "type": "object" }, "traits": {} }, - "required": ["properties"], "type": "object" } }, { - "description": "This is JSON Schema draft-06 event.", - "name": "Draft-06 Event", + "description": "checkin != check_in bug", + "name": "checkin", "rules": { - "$schema": "http://json-schema.org/draft-06/schema#", + "$schema": "http://json-schema.org/draft-07/schema#", + "labels": {}, "properties": { "context": {}, "properties": { "type": "object" }, "traits": {} }, - "required": ["properties"], "type": "object" } } diff --git a/tests/commands/gen-android/__snapshots__/ExampleEvent.java b/tests/commands/gen-android/__snapshots__/ExampleEvent.java index c04407e1..5145fc9a 100644 --- a/tests/commands/gen-android/__snapshots__/ExampleEvent.java +++ b/tests/commands/gen-android/__snapshots__/ExampleEvent.java @@ -1,14 +1,10 @@ // This code is auto-generated by Segment Typewriter. Do not edit. package com.segment.analytics; +import java.util.*; import android.support.annotation.NonNull; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public final class ExampleEvent extends PropertiesSerializable { +public final class ExampleEvent { private Properties properties; private ExampleEvent(Properties properties) { @@ -23,27 +19,6 @@ protected Properties toProperties() { * Builder for {@link ExampleEvent} */ public static class Builder { - private static String OPTIONAL_ANY_KEY = "optional any"; - private static String OPTIONAL_ARRAY_KEY = "optional array"; - private static String OPTIONAL_ARRAY_EMPTY_KEY = "optional array (empty)"; - private static String OPTIONAL_BOOLEAN_KEY = "optional boolean"; - private static String OPTIONAL_INT_KEY = "optional int"; - private static String OPTIONAL_NUMBER_KEY = "optional number"; - private static String OPTIONAL_OBJECT_KEY = "optional object"; - private static String OPTIONAL_OBJECT_EMPTY_KEY = "optional object (empty)"; - private static String OPTIONAL_STRING_KEY = "optional string"; - private static String OPTIONAL_STRING_REGEX_KEY = "optional string regex"; - private static String REQUIRED_ANY_KEY = "required any"; - private static String REQUIRED_ARRAY_KEY = "required array"; - private static String REQUIRED_ARRAY_EMPTY_KEY = "required array (empty)"; - private static String REQUIRED_BOOLEAN_KEY = "required boolean"; - private static String REQUIRED_INT_KEY = "required int"; - private static String REQUIRED_NUMBER_KEY = "required number"; - private static String REQUIRED_OBJECT_KEY = "required object"; - private static String REQUIRED_OBJECT_EMPTY_KEY = "required object (empty)"; - private static String REQUIRED_STRING_KEY = "required string"; - private static String REQUIRED_STRING_REGEX_KEY = "required string regex"; - private Properties properties; /** @@ -58,7 +33,7 @@ public Builder() { * This property is optional and not required to generate a valid ExampleEvent object */ public Builder optionalAny(final @NonNull Object optionalAny) { - properties.putValue(OPTIONAL_ANY_KEY, optionalAny); + properties.putValue("optional any", optionalAny); return this; } @@ -67,7 +42,7 @@ public Builder optionalAny(final @NonNull Object optionalAny) { * This property is optional and not required to generate a valid ExampleEvent object */ public Builder optionalArray(final @NonNull List optionalArray) { - properties.putValue(OPTIONAL_ARRAY_KEY, PropertiesSerializable.toPropertyList(optionalArray)); + properties.putValue("optional array", optionalArray); return this; } @@ -76,7 +51,7 @@ public Builder optionalArray(final @NonNull List optionalArray) { * This property is optional and not required to generate a valid ExampleEvent object */ public Builder optionalArrayEmpty(final @NonNull List optionalArrayEmpty) { - properties.putValue(OPTIONAL_ARRAY_EMPTY_KEY, PropertiesSerializable.toPropertyList(optionalArrayEmpty)); + properties.putValue("optional array (empty)", optionalArrayEmpty); return this; } @@ -85,7 +60,7 @@ public Builder optionalArrayEmpty(final @NonNull List optionalArrayEmpty * This property is optional and not required to generate a valid ExampleEvent object */ public Builder optionalBoolean(final @NonNull Boolean optionalBoolean) { - properties.putValue(OPTIONAL_BOOLEAN_KEY, optionalBoolean); + properties.putValue("optional boolean", optionalBoolean); return this; } @@ -94,7 +69,15 @@ public Builder optionalBoolean(final @NonNull Boolean optionalBoolean) { * This property is optional and not required to generate a valid ExampleEvent object */ public Builder optionalInt(final @NonNull Long optionalInt) { - properties.putValue(OPTIONAL_INT_KEY, optionalInt); + properties.putValue("optional int", optionalInt); + return this; + } + + /** + * This property is optional and not required to generate a valid ExampleEvent object + */ + public Builder optionalNullableString(final @NonNull String optionalNullableString) { + properties.putValue("optional nullable string", optionalNullableString); return this; } @@ -103,7 +86,15 @@ public Builder optionalInt(final @NonNull Long optionalInt) { * This property is optional and not required to generate a valid ExampleEvent object */ public Builder optionalNumber(final @NonNull Double optionalNumber) { - properties.putValue(OPTIONAL_NUMBER_KEY, optionalNumber); + properties.putValue("optional number", optionalNumber); + return this; + } + + /** + * This property is optional and not required to generate a valid ExampleEvent object + */ + public Builder optionalNumberOrString(final @NonNull NumberOrString optionalNumberOrString) { + properties.putValue("optional number or string", optionalNumberOrString); return this; } @@ -112,7 +103,7 @@ public Builder optionalNumber(final @NonNull Double optionalNumber) { * This property is optional and not required to generate a valid ExampleEvent object */ public Builder optionalObject(final @NonNull OptionalObject optionalObject) { - properties.putValue(OPTIONAL_OBJECT_KEY, optionalObject); + properties.putValue("optional object", optionalObject); return this; } @@ -121,7 +112,7 @@ public Builder optionalObject(final @NonNull OptionalObject optionalObject) { * This property is optional and not required to generate a valid ExampleEvent object */ public Builder optionalObjectEmpty(final @NonNull Map optionalObjectEmpty) { - properties.putValue(OPTIONAL_OBJECT_EMPTY_KEY, optionalObjectEmpty); + properties.putValue("optional object (empty)", optionalObjectEmpty); return this; } @@ -130,7 +121,7 @@ public Builder optionalObjectEmpty(final @NonNull Map optionalOb * This property is optional and not required to generate a valid ExampleEvent object */ public Builder optionalString(final @NonNull String optionalString) { - properties.putValue(OPTIONAL_STRING_KEY, optionalString); + properties.putValue("optional string", optionalString); return this; } @@ -139,7 +130,7 @@ public Builder optionalString(final @NonNull String optionalString) { * This property is optional and not required to generate a valid ExampleEvent object */ public Builder optionalStringRegex(final @NonNull String optionalStringRegex) { - properties.putValue(OPTIONAL_STRING_REGEX_KEY, optionalStringRegex); + properties.putValue("optional string regex", optionalStringRegex); return this; } @@ -148,7 +139,7 @@ public Builder optionalStringRegex(final @NonNull String optionalStringRegex) { * This property is required to generate a valid ExampleEvent object */ public Builder requiredAny(final @NonNull Object requiredAny) { - properties.putValue(REQUIRED_ANY_KEY, requiredAny); + properties.putValue("required any", requiredAny); return this; } @@ -157,7 +148,7 @@ public Builder requiredAny(final @NonNull Object requiredAny) { * This property is required to generate a valid ExampleEvent object */ public Builder requiredArray(final @NonNull List requiredArray) { - properties.putValue(REQUIRED_ARRAY_KEY, PropertiesSerializable.toPropertyList(requiredArray)); + properties.putValue("required array", requiredArray); return this; } @@ -166,7 +157,7 @@ public Builder requiredArray(final @NonNull List requiredArray) { * This property is required to generate a valid ExampleEvent object */ public Builder requiredArrayEmpty(final @NonNull List requiredArrayEmpty) { - properties.putValue(REQUIRED_ARRAY_EMPTY_KEY, PropertiesSerializable.toPropertyList(requiredArrayEmpty)); + properties.putValue("required array (empty)", requiredArrayEmpty); return this; } @@ -175,7 +166,7 @@ public Builder requiredArrayEmpty(final @NonNull List requiredArrayEmpty * This property is required to generate a valid ExampleEvent object */ public Builder requiredBoolean(final @NonNull Boolean requiredBoolean) { - properties.putValue(REQUIRED_BOOLEAN_KEY, requiredBoolean); + properties.putValue("required boolean", requiredBoolean); return this; } @@ -184,7 +175,15 @@ public Builder requiredBoolean(final @NonNull Boolean requiredBoolean) { * This property is required to generate a valid ExampleEvent object */ public Builder requiredInt(final @NonNull Long requiredInt) { - properties.putValue(REQUIRED_INT_KEY, requiredInt); + properties.putValue("required int", requiredInt); + return this; + } + + /** + * This property is required to generate a valid ExampleEvent object + */ + public Builder requiredNullableString(final @NonNull String requiredNullableString) { + properties.putValue("required nullable string", requiredNullableString); return this; } @@ -193,7 +192,15 @@ public Builder requiredInt(final @NonNull Long requiredInt) { * This property is required to generate a valid ExampleEvent object */ public Builder requiredNumber(final @NonNull Double requiredNumber) { - properties.putValue(REQUIRED_NUMBER_KEY, requiredNumber); + properties.putValue("required number", requiredNumber); + return this; + } + + /** + * This property is required to generate a valid ExampleEvent object + */ + public Builder requiredNumberOrString(final @NonNull NumberOrString requiredNumberOrString) { + properties.putValue("required number or string", requiredNumberOrString); return this; } @@ -202,7 +209,7 @@ public Builder requiredNumber(final @NonNull Double requiredNumber) { * This property is required to generate a valid ExampleEvent object */ public Builder requiredObject(final @NonNull RequiredObject requiredObject) { - properties.putValue(REQUIRED_OBJECT_KEY, requiredObject); + properties.putValue("required object", requiredObject); return this; } @@ -211,7 +218,7 @@ public Builder requiredObject(final @NonNull RequiredObject requiredObject) { * This property is required to generate a valid ExampleEvent object */ public Builder requiredObjectEmpty(final @NonNull Map requiredObjectEmpty) { - properties.putValue(REQUIRED_OBJECT_EMPTY_KEY, requiredObjectEmpty); + properties.putValue("required object (empty)", requiredObjectEmpty); return this; } @@ -220,7 +227,7 @@ public Builder requiredObjectEmpty(final @NonNull Map requiredOb * This property is required to generate a valid ExampleEvent object */ public Builder requiredString(final @NonNull String requiredString) { - properties.putValue(REQUIRED_STRING_KEY, requiredString); + properties.putValue("required string", requiredString); return this; } @@ -229,7 +236,7 @@ public Builder requiredString(final @NonNull String requiredString) { * This property is required to generate a valid ExampleEvent object */ public Builder requiredStringRegex(final @NonNull String requiredStringRegex) { - properties.putValue(REQUIRED_STRING_REGEX_KEY, requiredStringRegex); + properties.putValue("required string regex", requiredStringRegex); return this; } @@ -241,50 +248,60 @@ public Builder requiredStringRegex(final @NonNull String requiredStringRegex) { * - requiredArrayEmpty * - requiredBoolean * - requiredInt + * - requiredNullableString * - requiredNumber + * - requiredNumberOrString * - requiredObject * - requiredObjectEmpty * - requiredString * - requiredStringRegex */ public ExampleEvent build() { - if (properties.get(REQUIRED_ANY_KEY) == null) { + if (properties.get("required any") == null) { throw new IllegalArgumentException("ExampleEvent missing required property: requiredAny"); } - if (properties.get(REQUIRED_ARRAY_KEY) == null) { + if (properties.get("required array") == null) { throw new IllegalArgumentException("ExampleEvent missing required property: requiredArray"); } - if (properties.get(REQUIRED_ARRAY_EMPTY_KEY) == null) { + if (properties.get("required array (empty)") == null) { throw new IllegalArgumentException("ExampleEvent missing required property: requiredArrayEmpty"); } - if (properties.get(REQUIRED_BOOLEAN_KEY) == null) { + if (properties.get("required boolean") == null) { throw new IllegalArgumentException("ExampleEvent missing required property: requiredBoolean"); } - if (properties.get(REQUIRED_INT_KEY) == null) { + if (properties.get("required int") == null) { throw new IllegalArgumentException("ExampleEvent missing required property: requiredInt"); } - if (properties.get(REQUIRED_NUMBER_KEY) == null) { + if (properties.get("required nullable string") == null) { + throw new IllegalArgumentException("ExampleEvent missing required property: requiredNullableString"); + } + + if (properties.get("required number") == null) { throw new IllegalArgumentException("ExampleEvent missing required property: requiredNumber"); } - if (properties.get(REQUIRED_OBJECT_KEY) == null) { + if (properties.get("required number or string") == null) { + throw new IllegalArgumentException("ExampleEvent missing required property: requiredNumberOrString"); + } + + if (properties.get("required object") == null) { throw new IllegalArgumentException("ExampleEvent missing required property: requiredObject"); } - if (properties.get(REQUIRED_OBJECT_EMPTY_KEY) == null) { + if (properties.get("required object (empty)") == null) { throw new IllegalArgumentException("ExampleEvent missing required property: requiredObjectEmpty"); } - if (properties.get(REQUIRED_STRING_KEY) == null) { + if (properties.get("required string") == null) { throw new IllegalArgumentException("ExampleEvent missing required property: requiredString"); } - if (properties.get(REQUIRED_STRING_REGEX_KEY) == null) { + if (properties.get("required string regex") == null) { throw new IllegalArgumentException("ExampleEvent missing required property: requiredStringRegex"); } diff --git a/tests/commands/gen-android/__snapshots__/NumberOrString.java b/tests/commands/gen-android/__snapshots__/NumberOrString.java new file mode 100644 index 00000000..b275b847 --- /dev/null +++ b/tests/commands/gen-android/__snapshots__/NumberOrString.java @@ -0,0 +1,10 @@ +// This code is auto-generated by Segment Typewriter. Do not edit. +package com.segment.analytics; + +import java.util.*; +import java.io.IOException; + +public class NumberOrString { + public Double doubleValue; + public String stringValue; +} diff --git a/tests/commands/gen-android/__snapshots__/OptionalArray.java b/tests/commands/gen-android/__snapshots__/OptionalArray.java index 66aecb44..8d6e27ed 100644 --- a/tests/commands/gen-android/__snapshots__/OptionalArray.java +++ b/tests/commands/gen-android/__snapshots__/OptionalArray.java @@ -1,14 +1,10 @@ // This code is auto-generated by Segment Typewriter. Do not edit. package com.segment.analytics; +import java.util.*; import android.support.annotation.NonNull; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public final class OptionalArray extends PropertiesSerializable { +public final class OptionalArray { private Properties properties; private OptionalArray(Properties properties) { @@ -23,9 +19,6 @@ protected Properties toProperties() { * Builder for {@link OptionalArray} */ public static class Builder { - private static String OPTIONAL_SUB_PROPERTY_KEY = "optional sub-property"; - private static String REQUIRED_SUB_PROPERTY_KEY = "required sub-property"; - private Properties properties; /** @@ -40,7 +33,7 @@ public Builder() { * This property is optional and not required to generate a valid OptionalArray object */ public Builder optionalSubProperty(final @NonNull String optionalSubProperty) { - properties.putValue(OPTIONAL_SUB_PROPERTY_KEY, optionalSubProperty); + properties.putValue("optional sub-property", optionalSubProperty); return this; } @@ -49,7 +42,7 @@ public Builder optionalSubProperty(final @NonNull String optionalSubProperty) { * This property is required to generate a valid OptionalArray object */ public Builder requiredSubProperty(final @NonNull String requiredSubProperty) { - properties.putValue(REQUIRED_SUB_PROPERTY_KEY, requiredSubProperty); + properties.putValue("required sub-property", requiredSubProperty); return this; } @@ -59,7 +52,7 @@ public Builder requiredSubProperty(final @NonNull String requiredSubProperty) { * - requiredSubProperty */ public OptionalArray build() { - if (properties.get(REQUIRED_SUB_PROPERTY_KEY) == null) { + if (properties.get("required sub-property") == null) { throw new IllegalArgumentException("OptionalArray missing required property: requiredSubProperty"); } diff --git a/tests/commands/gen-android/__snapshots__/OptionalObject.java b/tests/commands/gen-android/__snapshots__/OptionalObject.java index 24a9a18b..a0d552a2 100644 --- a/tests/commands/gen-android/__snapshots__/OptionalObject.java +++ b/tests/commands/gen-android/__snapshots__/OptionalObject.java @@ -1,14 +1,10 @@ // This code is auto-generated by Segment Typewriter. Do not edit. package com.segment.analytics; +import java.util.*; import android.support.annotation.NonNull; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public final class OptionalObject extends PropertiesSerializable { +public final class OptionalObject { private Properties properties; private OptionalObject(Properties properties) { @@ -23,9 +19,6 @@ protected Properties toProperties() { * Builder for {@link OptionalObject} */ public static class Builder { - private static String OPTIONAL_SUB_PROPERTY_KEY = "optional sub-property"; - private static String REQUIRED_SUB_PROPERTY_KEY = "required sub-property"; - private Properties properties; /** @@ -40,7 +33,7 @@ public Builder() { * This property is optional and not required to generate a valid OptionalObject object */ public Builder optionalSubProperty(final @NonNull String optionalSubProperty) { - properties.putValue(OPTIONAL_SUB_PROPERTY_KEY, optionalSubProperty); + properties.putValue("optional sub-property", optionalSubProperty); return this; } @@ -49,7 +42,7 @@ public Builder optionalSubProperty(final @NonNull String optionalSubProperty) { * This property is required to generate a valid OptionalObject object */ public Builder requiredSubProperty(final @NonNull String requiredSubProperty) { - properties.putValue(REQUIRED_SUB_PROPERTY_KEY, requiredSubProperty); + properties.putValue("required sub-property", requiredSubProperty); return this; } @@ -59,7 +52,7 @@ public Builder requiredSubProperty(final @NonNull String requiredSubProperty) { * - requiredSubProperty */ public OptionalObject build() { - if (properties.get(REQUIRED_SUB_PROPERTY_KEY) == null) { + if (properties.get("required sub-property") == null) { throw new IllegalArgumentException("OptionalObject missing required property: requiredSubProperty"); } diff --git a/tests/commands/gen-android/__snapshots__/PropertiesSerializable.java b/tests/commands/gen-android/__snapshots__/PropertiesSerializable.java deleted file mode 100644 index 96312ec4..00000000 --- a/tests/commands/gen-android/__snapshots__/PropertiesSerializable.java +++ /dev/null @@ -1,17 +0,0 @@ -// This code is auto-generated by Segment Typewriter. Do not edit. -package com.segment.analytics; - -import java.util.ArrayList; -import java.util.List; - -abstract class PropertiesSerializable { - abstract Properties toProperties(); - - static List toPropertyList(List list) { - List properties = new ArrayList<>(list.size()); - for (PropertiesSerializable item : list) { - properties.add(item.toProperties()); - } - return properties; - } -} diff --git a/tests/commands/gen-android/__snapshots__/RequiredArray.java b/tests/commands/gen-android/__snapshots__/RequiredArray.java index 94bd3103..5bec7c90 100644 --- a/tests/commands/gen-android/__snapshots__/RequiredArray.java +++ b/tests/commands/gen-android/__snapshots__/RequiredArray.java @@ -1,14 +1,10 @@ // This code is auto-generated by Segment Typewriter. Do not edit. package com.segment.analytics; +import java.util.*; import android.support.annotation.NonNull; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public final class RequiredArray extends PropertiesSerializable { +public final class RequiredArray { private Properties properties; private RequiredArray(Properties properties) { @@ -23,9 +19,6 @@ protected Properties toProperties() { * Builder for {@link RequiredArray} */ public static class Builder { - private static String OPTIONAL_SUB_PROPERTY_KEY = "optional sub-property"; - private static String REQUIRED_SUB_PROPERTY_KEY = "required sub-property"; - private Properties properties; /** @@ -40,7 +33,7 @@ public Builder() { * This property is optional and not required to generate a valid RequiredArray object */ public Builder optionalSubProperty(final @NonNull String optionalSubProperty) { - properties.putValue(OPTIONAL_SUB_PROPERTY_KEY, optionalSubProperty); + properties.putValue("optional sub-property", optionalSubProperty); return this; } @@ -49,7 +42,7 @@ public Builder optionalSubProperty(final @NonNull String optionalSubProperty) { * This property is required to generate a valid RequiredArray object */ public Builder requiredSubProperty(final @NonNull String requiredSubProperty) { - properties.putValue(REQUIRED_SUB_PROPERTY_KEY, requiredSubProperty); + properties.putValue("required sub-property", requiredSubProperty); return this; } @@ -59,7 +52,7 @@ public Builder requiredSubProperty(final @NonNull String requiredSubProperty) { * - requiredSubProperty */ public RequiredArray build() { - if (properties.get(REQUIRED_SUB_PROPERTY_KEY) == null) { + if (properties.get("required sub-property") == null) { throw new IllegalArgumentException("RequiredArray missing required property: requiredSubProperty"); } diff --git a/tests/commands/gen-android/__snapshots__/RequiredObject.java b/tests/commands/gen-android/__snapshots__/RequiredObject.java index 886f1377..2add360a 100644 --- a/tests/commands/gen-android/__snapshots__/RequiredObject.java +++ b/tests/commands/gen-android/__snapshots__/RequiredObject.java @@ -1,14 +1,10 @@ // This code is auto-generated by Segment Typewriter. Do not edit. package com.segment.analytics; +import java.util.*; import android.support.annotation.NonNull; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public final class RequiredObject extends PropertiesSerializable { +public final class RequiredObject { private Properties properties; private RequiredObject(Properties properties) { @@ -23,9 +19,6 @@ protected Properties toProperties() { * Builder for {@link RequiredObject} */ public static class Builder { - private static String OPTIONAL_SUB_PROPERTY_KEY = "optional sub-property"; - private static String REQUIRED_SUB_PROPERTY_KEY = "required sub-property"; - private Properties properties; /** @@ -40,7 +33,7 @@ public Builder() { * This property is optional and not required to generate a valid RequiredObject object */ public Builder optionalSubProperty(final @NonNull String optionalSubProperty) { - properties.putValue(OPTIONAL_SUB_PROPERTY_KEY, optionalSubProperty); + properties.putValue("optional sub-property", optionalSubProperty); return this; } @@ -49,7 +42,7 @@ public Builder optionalSubProperty(final @NonNull String optionalSubProperty) { * This property is required to generate a valid RequiredObject object */ public Builder requiredSubProperty(final @NonNull String requiredSubProperty) { - properties.putValue(REQUIRED_SUB_PROPERTY_KEY, requiredSubProperty); + properties.putValue("required sub-property", requiredSubProperty); return this; } @@ -59,7 +52,7 @@ public Builder requiredSubProperty(final @NonNull String requiredSubProperty) { * - requiredSubProperty */ public RequiredObject build() { - if (properties.get(REQUIRED_SUB_PROPERTY_KEY) == null) { + if (properties.get("required sub-property") == null) { throw new IllegalArgumentException("RequiredObject missing required property: requiredSubProperty"); } diff --git a/tests/commands/gen-android/__snapshots__/TestTrackingPlanAnalytics.java b/tests/commands/gen-android/__snapshots__/TestTrackingPlanAnalytics.java index 66281a22..87c710d2 100644 --- a/tests/commands/gen-android/__snapshots__/TestTrackingPlanAnalytics.java +++ b/tests/commands/gen-android/__snapshots__/TestTrackingPlanAnalytics.java @@ -1,6 +1,7 @@ // This code is auto-generated by Segment Typewriter. Do not edit. package com.segment.analytics; +import java.util.*; import com.segment.analytics.Analytics; import com.segment.analytics.Options; import android.content.Context; @@ -35,6 +36,34 @@ public void the42TerribleEventName3(final @Nullable The42_TerribleEventName3 pro this.analytics.track("42_--terrible==\"event'++name~!3", props.toProperties(), options); } + /** + * @see Track Documentation + */ + public void draft04Event() { + this.analytics.track("Draft-04 Event", new Properties()); + } + + /** + * @see Track Documentation + */ + public void draft04Event(final @Nullable Options options) { + this.analytics.track("Draft-04 Event", new Properties(), options); + } + + /** + * @see Track Documentation + */ + public void draft06Event() { + this.analytics.track("Draft-06 Event", new Properties()); + } + + /** + * @see Track Documentation + */ + public void draft06Event(final @Nullable Options options) { + this.analytics.track("Draft-06 Event", new Properties(), options); + } + /** * @see Track Documentation */ @@ -68,28 +97,28 @@ public void exampleEvent(final @Nullable ExampleEvent props, final @Nullable Opt /** * @see Track Documentation */ - public void draft04Event() { - this.analytics.track("Draft-04 Event", new Properties()); + public void checkIn() { + this.analytics.track("check_in", new Properties()); } /** * @see Track Documentation */ - public void draft04Event(final @Nullable Options options) { - this.analytics.track("Draft-04 Event", new Properties(), options); + public void checkIn(final @Nullable Options options) { + this.analytics.track("check_in", new Properties(), options); } /** * @see Track Documentation */ - public void draft06Event() { - this.analytics.track("Draft-06 Event", new Properties()); + public void checkin() { + this.analytics.track("checkin", new Properties()); } /** * @see Track Documentation */ - public void draft06Event(final @Nullable Options options) { - this.analytics.track("Draft-06 Event", new Properties(), options); + public void checkin(final @Nullable Options options) { + this.analytics.track("checkin", new Properties(), options); } } diff --git a/tests/commands/gen-android/__snapshots__/The42_TerribleEventName3.java b/tests/commands/gen-android/__snapshots__/The42_TerribleEventName3.java index afd08de6..eb9cc89c 100644 --- a/tests/commands/gen-android/__snapshots__/The42_TerribleEventName3.java +++ b/tests/commands/gen-android/__snapshots__/The42_TerribleEventName3.java @@ -1,14 +1,10 @@ // This code is auto-generated by Segment Typewriter. Do not edit. package com.segment.analytics; +import java.util.*; import android.support.annotation.NonNull; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public final class The42_TerribleEventName3 extends PropertiesSerializable { +public final class The42_TerribleEventName3 { private Properties properties; private The42_TerribleEventName3(Properties properties) { @@ -23,9 +19,6 @@ protected Properties toProperties() { * Builder for {@link The42_TerribleEventName3} */ public static class Builder { - private static String THE_0000_TERRIBLE_PROPERTY_NAME_3__KEY = "0000---terrible-property-name~!3"; - private static String IDENTIFIER_ID_KEY = "identifier_id"; - private Properties properties; /** @@ -40,7 +33,7 @@ public Builder() { * This property is optional and not required to generate a valid The42_TerribleEventName3 object */ public Builder the0000TerriblePropertyName3(final @NonNull Object the0000TerriblePropertyName3) { - properties.putValue(THE_0000_TERRIBLE_PROPERTY_NAME_3__KEY, the0000TerriblePropertyName3); + properties.putValue("0000---terrible-property-name~!3", the0000TerriblePropertyName3); return this; } @@ -48,8 +41,17 @@ public Builder the0000TerriblePropertyName3(final @NonNull Object the0000Terribl * AcronymStyle bug fixed in v5.0.1 * This property is optional and not required to generate a valid The42_TerribleEventName3 object */ + public Builder the42_TerribleEventName3_IdentifierID(final @NonNull Object the42_TerribleEventName3_IdentifierID) { + properties.putValue("identifier_id", the42_TerribleEventName3_IdentifierID); + return this; + } + + /** + * Duplicate key error in Android + * This property is optional and not required to generate a valid The42_TerribleEventName3 object + */ public Builder identifierID(final @NonNull Object identifierID) { - properties.putValue(IDENTIFIER_ID_KEY, identifierID); + properties.putValue("identifierId", identifierID); return this; } diff --git a/tests/commands/gen-ios/__snapshots__/SEGTestTrackingPlanAnalytics.h b/tests/commands/gen-ios/__snapshots__/SEGTestTrackingPlanAnalytics.h index 8e3838c9..8bc4f6f3 100644 --- a/tests/commands/gen-ios/__snapshots__/SEGTestTrackingPlanAnalytics.h +++ b/tests/commands/gen-ios/__snapshots__/SEGTestTrackingPlanAnalytics.h @@ -27,6 +27,8 @@ NS_ASSUME_NONNULL_BEGIN /// Really, don't do this. @property (nonatomic, nullable, copy) id the0000TerriblePropertyName3; /// AcronymStyle bug fixed in v5.0.1 +@property (nonatomic, nullable, copy) id the42_TerribleEventName3_IdentifierID; +/// Duplicate key error in Android @property (nonatomic, nullable, copy) id identifierID; @end @@ -36,6 +38,8 @@ typedef void (^ SEGThe42_TerribleEventName3BuilderBlock)(SEGThe42_TerribleEventN /// Really, don't do this. @property (nonatomic, nullable, copy) id the0000TerriblePropertyName3; /// AcronymStyle bug fixed in v5.0.1 +@property (nonatomic, nullable, copy) id the42_TerribleEventName3_IdentifierID; +/// Duplicate key error in Android @property (nonatomic, nullable, copy) id identifierID; @end @@ -50,8 +54,10 @@ typedef void (^ SEGThe42_TerribleEventName3BuilderBlock)(SEGThe42_TerribleEventN @property (nonatomic, nullable, assign) NSNumber *isOptionalBoolean; /// Optional integer property @property (nonatomic, nullable, assign) NSNumber *optionalInt; +@property (nonatomic, nullable, copy) NSString *optionalNullableString; /// Optional number property @property (nonatomic, nullable, assign) NSNumber *optionalNumber; +@property (nonatomic, nullable, copy) id optionalNumberOrString; /// Optional object property @property (nonatomic, nullable, strong) SEGOptionalObject *optionalObject; /// Optional object (empty) property @@ -70,8 +76,10 @@ typedef void (^ SEGThe42_TerribleEventName3BuilderBlock)(SEGThe42_TerribleEventN @property (nonatomic, assign) NSNumber *isRequiredBoolean; /// Required integer property @property (nonatomic, assign) NSNumber *requiredInt; +@property (nonatomic, copy) NSString *requiredNullableString; /// Required number property @property (nonatomic, assign) NSNumber *requiredNumber; +@property (nonatomic, copy) id requiredNumberOrString; /// Required object property @property (nonatomic, strong) SEGRequiredObject *requiredObject; /// Required object (empty) property @@ -95,8 +103,10 @@ typedef void (^ SEGExampleEventBuilderBlock)(SEGExampleEventBuilder *); @property (nonatomic, nullable, assign) NSNumber *isOptionalBoolean; /// Optional integer property @property (nonatomic, nullable, assign) NSNumber *optionalInt; +@property (nonatomic, nullable, copy) NSString *optionalNullableString; /// Optional number property @property (nonatomic, nullable, assign) NSNumber *optionalNumber; +@property (nonatomic, nullable, copy) id optionalNumberOrString; /// Optional object property @property (nonatomic, nullable, strong) SEGOptionalObject *optionalObject; /// Optional object (empty) property @@ -115,8 +125,10 @@ typedef void (^ SEGExampleEventBuilderBlock)(SEGExampleEventBuilder *); @property (nonatomic, assign) NSNumber *isRequiredBoolean; /// Required integer property @property (nonatomic, assign) NSNumber *requiredInt; +@property (nonatomic, copy) NSString *requiredNullableString; /// Required number property @property (nonatomic, assign) NSNumber *requiredNumber; +@property (nonatomic, copy) id requiredNumberOrString; /// Required object property @property (nonatomic, strong) SEGRequiredObject *requiredObject; /// Required object (empty) property @@ -197,6 +209,18 @@ typedef void (^ SEGRequiredObjectBuilderBlock)(SEGRequiredObjectBuilder *); - (void)the42TerribleEventName3:(SEGThe42_TerribleEventName3 *)props; - (void)the42TerribleEventName3:(SEGThe42_TerribleEventName3 *)props withOptions:(NSDictionary *_Nullable)options; +/// Optional object (empty) property +/// +/// Required object (empty) property +- (void)draft04Event; +- (void)draft04Event:(NSDictionary *_Nullable)options; + +/// Optional object (empty) property +/// +/// Required object (empty) property +- (void)draft06Event; +- (void)draft06Event:(NSDictionary *_Nullable)options; + /// Optional object (empty) property /// /// Required object (empty) property @@ -209,14 +233,14 @@ typedef void (^ SEGRequiredObjectBuilderBlock)(SEGRequiredObjectBuilder *); /// Optional object (empty) property /// /// Required object (empty) property -- (void)draft04Event; -- (void)draft04Event:(NSDictionary *_Nullable)options; +- (void)checkIn; +- (void)checkIn:(NSDictionary *_Nullable)options; /// Optional object (empty) property /// /// Required object (empty) property -- (void)draft06Event; -- (void)draft06Event:(NSDictionary *_Nullable)options; +- (void)checkin; +- (void)checkin:(NSDictionary *_Nullable)options; @end NS_ASSUME_NONNULL_END diff --git a/tests/commands/gen-ios/__snapshots__/SEGTestTrackingPlanAnalytics.m b/tests/commands/gen-ios/__snapshots__/SEGTestTrackingPlanAnalytics.m index e77d3108..074473a9 100644 --- a/tests/commands/gen-ios/__snapshots__/SEGTestTrackingPlanAnalytics.m +++ b/tests/commands/gen-ios/__snapshots__/SEGTestTrackingPlanAnalytics.m @@ -89,7 +89,8 @@ @implementation SEGThe42_TerribleEventName3 static NSDictionary *properties; return properties = properties ? properties : @{ @"0000---terrible-property-name~!3": @"the0000TerriblePropertyName3", - @"identifier_id": @"identifierID", + @"identifier_id": @"the42_TerribleEventName3_IdentifierID", + @"identifierId": @"identifierID", }; } @@ -125,6 +126,7 @@ + (SEGThe42_TerribleEventName3 *)initWithBlock:(SEGThe42_TerribleEventName3Build SEGThe42_TerribleEventName3 *the42TerribleEventName3 = [[SEGThe42_TerribleEventName3 alloc] init]; the42TerribleEventName3.the0000TerriblePropertyName3 = builder.the0000TerriblePropertyName3; + the42TerribleEventName3.the42_TerribleEventName3_IdentifierID = builder.the42_TerribleEventName3_IdentifierID; the42TerribleEventName3.identifierID = builder.identifierID; return the42TerribleEventName3; } @@ -140,7 +142,9 @@ @implementation SEGExampleEvent @"optional array (empty)": @"optionalArrayEmpty", @"optional boolean": @"isOptionalBoolean", @"optional int": @"optionalInt", + @"optional nullable string": @"optionalNullableString", @"optional number": @"optionalNumber", + @"optional number or string": @"optionalNumberOrString", @"optional object": @"optionalObject", @"optional object (empty)": @"optionalObjectEmpty", @"optional string": @"optionalString", @@ -150,7 +154,9 @@ @implementation SEGExampleEvent @"required array (empty)": @"requiredArrayEmpty", @"required boolean": @"isRequiredBoolean", @"required int": @"requiredInt", + @"required nullable string": @"requiredNullableString", @"required number": @"requiredNumber", + @"required number or string": @"requiredNumberOrString", @"required object": @"requiredObject", @"required object (empty)": @"requiredObjectEmpty", @"required string": @"requiredString", @@ -217,10 +223,18 @@ + (SEGExampleEvent *)initWithBlock:(SEGExampleEventBuilderBlock)block @throw [NSException exceptionWithName:@"Missing Required Property" reason:@"SEGExampleEvent is missing a required property: requiredInt" userInfo:NULL]; } + if (builder.requiredNullableString == NULL) { + @throw [NSException exceptionWithName:@"Missing Required Property" reason:@"SEGExampleEvent is missing a required property: requiredNullableString" userInfo:NULL]; + } + if (builder.requiredNumber == NULL) { @throw [NSException exceptionWithName:@"Missing Required Property" reason:@"SEGExampleEvent is missing a required property: requiredNumber" userInfo:NULL]; } + if (builder.requiredNumberOrString == NULL) { + @throw [NSException exceptionWithName:@"Missing Required Property" reason:@"SEGExampleEvent is missing a required property: requiredNumberOrString" userInfo:NULL]; + } + if (builder.requiredObject == NULL) { @throw [NSException exceptionWithName:@"Missing Required Property" reason:@"SEGExampleEvent is missing a required property: requiredObject" userInfo:NULL]; } @@ -243,7 +257,9 @@ + (SEGExampleEvent *)initWithBlock:(SEGExampleEventBuilderBlock)block exampleEvent.optionalArrayEmpty = builder.optionalArrayEmpty; exampleEvent.isOptionalBoolean = builder.isOptionalBoolean; exampleEvent.optionalInt = builder.optionalInt; + exampleEvent.optionalNullableString = builder.optionalNullableString; exampleEvent.optionalNumber = builder.optionalNumber; + exampleEvent.optionalNumberOrString = builder.optionalNumberOrString; exampleEvent.optionalObject = builder.optionalObject; exampleEvent.optionalObjectEmpty = builder.optionalObjectEmpty; exampleEvent.optionalString = builder.optionalString; @@ -253,7 +269,9 @@ + (SEGExampleEvent *)initWithBlock:(SEGExampleEventBuilderBlock)block exampleEvent.requiredArrayEmpty = builder.requiredArrayEmpty; exampleEvent.isRequiredBoolean = builder.isRequiredBoolean; exampleEvent.requiredInt = builder.requiredInt; + exampleEvent.requiredNullableString = builder.requiredNullableString; exampleEvent.requiredNumber = builder.requiredNumber; + exampleEvent.requiredNumberOrString = builder.requiredNumberOrString; exampleEvent.requiredObject = builder.requiredObject; exampleEvent.requiredObjectEmpty = builder.requiredObjectEmpty; exampleEvent.requiredString = builder.requiredString; @@ -485,6 +503,24 @@ - (void)the42TerribleEventName3:(SEGThe42_TerribleEventName3 *)props withOptions [self.analytics track:@"42_--terrible==\"event'++name~!3" properties:[props JSONDictionary] options:addTypewriterContextFields(options)]; } +- (void)draft04Event +{ + [self draft04Event:@{}]; +} +- (void)draft04Event:(NSDictionary *_Nullable)options +{ + [self.analytics track:@"Draft-04 Event" properties:@{} options:addTypewriterContextFields(options)]; +} + +- (void)draft06Event +{ + [self draft06Event:@{}]; +} +- (void)draft06Event:(NSDictionary *_Nullable)options +{ + [self.analytics track:@"Draft-06 Event" properties:@{} options:addTypewriterContextFields(options)]; +} + - (void)emptyEvent { [self emptyEvent:@{}]; @@ -503,22 +539,22 @@ - (void)exampleEvent:(SEGExampleEvent *)props withOptions:(NSDictionary *_Nullable)options +- (void)checkIn:(NSDictionary *_Nullable)options { - [self.analytics track:@"Draft-04 Event" properties:@{} options:addTypewriterContextFields(options)]; + [self.analytics track:@"check_in" properties:@{} options:addTypewriterContextFields(options)]; } -- (void)draft06Event +- (void)checkin { - [self draft06Event:@{}]; + [self checkin:@{}]; } -- (void)draft06Event:(NSDictionary *_Nullable)options +- (void)checkin:(NSDictionary *_Nullable)options { - [self.analytics track:@"Draft-06 Event" properties:@{} options:addTypewriterContextFields(options)]; + [self.analytics track:@"checkin" properties:@{} options:addTypewriterContextFields(options)]; } @end diff --git a/tests/commands/gen-js/__snapshots__/index.amd.js b/tests/commands/gen-js/__snapshots__/index.amd.js index 24b3a9d4..6588f2c0 100644 --- a/tests/commands/gen-js/__snapshots__/index.amd.js +++ b/tests/commands/gen-js/__snapshots__/index.amd.js @@ -95,6 +95,156 @@ define(["require", "exports"], function(require, exports) { callback ); } + draft04Event(props = {}, options = {}, callback) { + var validate = function( + data, + dataPath, + parentData, + parentDataProperty, + rootData + ) { + "use strict"; + var vErrors = null; + var errors = 0; + if (data && typeof data === "object" && !Array.isArray(data)) { + var errs__0 = errors; + var valid1 = true; + var data1 = data.properties; + if (data1 === undefined) { + valid1 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + "", + schemaPath: "#/required", + params: { missingProperty: "properties" }, + message: "should have required property 'properties'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_1 = errors; + if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { + var err = { + keyword: "type", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid1 = errors === errs_1; + } + } else { + var err = { + keyword: "type", + dataPath: (dataPath || "") + "", + schemaPath: "#/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + validate.errors = vErrors; + return errors === 0; + }; + if (!validate({ properties: props })) { + this.onError({ + eventName: "Draft-04 Event", + validationErrors: validate.errors + }); + return; + } + this.analytics.track( + "Draft-04 Event", + props, + { + ...options, + context: this.addTypewriterContext(options.context) + }, + callback + ); + } + draft06Event(props = {}, options = {}, callback) { + var validate = function( + data, + dataPath, + parentData, + parentDataProperty, + rootData + ) { + "use strict"; + var vErrors = null; + var errors = 0; + if (data && typeof data === "object" && !Array.isArray(data)) { + var errs__0 = errors; + var valid1 = true; + var data1 = data.properties; + if (data1 === undefined) { + valid1 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + "", + schemaPath: "#/required", + params: { missingProperty: "properties" }, + message: "should have required property 'properties'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_1 = errors; + if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { + var err = { + keyword: "type", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid1 = errors === errs_1; + } + } else { + var err = { + keyword: "type", + dataPath: (dataPath || "") + "", + schemaPath: "#/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + validate.errors = vErrors; + return errors === 0; + }; + if (!validate({ properties: props })) { + this.onError({ + eventName: "Draft-06 Event", + validationErrors: validate.errors + }); + return; + } + this.analytics.track( + "Draft-06 Event", + props, + { + ...options, + context: this.addTypewriterContext(options.context) + }, + callback + ); + } emptyEvent(props = {}, options = {}, callback) { var validate = function( data, @@ -385,6 +535,26 @@ define(["require", "exports"], function(require, exports) { } var valid2 = errors === errs_2; } + var data2 = data1["optional nullable string"]; + if (data2 !== undefined) { + var errs_2 = errors; + if (typeof data2 !== "string" && data2 !== null) { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['optional nullable string']", + schemaPath: + "#/properties/properties/properties/optional%20nullable%20string/type", + params: { type: "string,null" }, + message: "should be string,null" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } if (data1["optional number"] !== undefined) { var errs_2 = errors; if (typeof data1["optional number"] !== "number") { @@ -403,6 +573,26 @@ define(["require", "exports"], function(require, exports) { } var valid2 = errors === errs_2; } + var data2 = data1["optional number or string"]; + if (data2 !== undefined) { + var errs_2 = errors; + if (typeof data2 !== "number" && typeof data2 !== "string") { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['optional number or string']", + schemaPath: + "#/properties/properties/properties/optional%20number%20or%20string/type", + params: { type: "number,string" }, + message: "should be number,string" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } var data2 = data1["optional object"]; if (data2 !== undefined) { var errs_2 = errors; @@ -778,6 +968,39 @@ define(["require", "exports"], function(require, exports) { } var valid2 = errors === errs_2; } + var data2 = data1["required nullable string"]; + if (data2 === undefined) { + valid2 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/required", + params: { missingProperty: "required nullable string" }, + message: + "should have required property 'required nullable string'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_2 = errors; + if (typeof data2 !== "string" && data2 !== null) { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['required nullable string']", + schemaPath: + "#/properties/properties/properties/required%20nullable%20string/type", + params: { type: "string,null" }, + message: "should be string,null" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } if (data1["required number"] === undefined) { valid2 = false; var err = { @@ -808,6 +1031,39 @@ define(["require", "exports"], function(require, exports) { } var valid2 = errors === errs_2; } + var data2 = data1["required number or string"]; + if (data2 === undefined) { + valid2 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/required", + params: { missingProperty: "required number or string" }, + message: + "should have required property 'required number or string'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_2 = errors; + if (typeof data2 !== "number" && typeof data2 !== "string") { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['required number or string']", + schemaPath: + "#/properties/properties/properties/required%20number%20or%20string/type", + params: { type: "number,string" }, + message: "should be number,string" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } var data2 = data1["required object"]; if (data2 === undefined) { valid2 = false; @@ -1060,7 +1316,7 @@ define(["require", "exports"], function(require, exports) { callback ); } - draft04Event(props = {}, options = {}, callback) { + checkIn(props = {}, options = {}, callback) { var validate = function( data, dataPath, @@ -1075,19 +1331,7 @@ define(["require", "exports"], function(require, exports) { var errs__0 = errors; var valid1 = true; var data1 = data.properties; - if (data1 === undefined) { - valid1 = false; - var err = { - keyword: "required", - dataPath: (dataPath || "") + "", - schemaPath: "#/required", - params: { missingProperty: "properties" }, - message: "should have required property 'properties'" - }; - if (vErrors === null) vErrors = [err]; - else vErrors.push(err); - errors++; - } else { + if (data1 !== undefined) { var errs_1 = errors; if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { var err = { @@ -1120,13 +1364,13 @@ define(["require", "exports"], function(require, exports) { }; if (!validate({ properties: props })) { this.onError({ - eventName: "Draft-04 Event", + eventName: "check_in", validationErrors: validate.errors }); return; } this.analytics.track( - "Draft-04 Event", + "check_in", props, { ...options, @@ -1135,7 +1379,7 @@ define(["require", "exports"], function(require, exports) { callback ); } - draft06Event(props = {}, options = {}, callback) { + checkin(props = {}, options = {}, callback) { var validate = function( data, dataPath, @@ -1150,19 +1394,7 @@ define(["require", "exports"], function(require, exports) { var errs__0 = errors; var valid1 = true; var data1 = data.properties; - if (data1 === undefined) { - valid1 = false; - var err = { - keyword: "required", - dataPath: (dataPath || "") + "", - schemaPath: "#/required", - params: { missingProperty: "properties" }, - message: "should have required property 'properties'" - }; - if (vErrors === null) vErrors = [err]; - else vErrors.push(err); - errors++; - } else { + if (data1 !== undefined) { var errs_1 = errors; if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { var err = { @@ -1195,13 +1427,13 @@ define(["require", "exports"], function(require, exports) { }; if (!validate({ properties: props })) { this.onError({ - eventName: "Draft-06 Event", + eventName: "checkin", validationErrors: validate.errors }); return; } this.analytics.track( - "Draft-06 Event", + "checkin", props, { ...options, diff --git a/tests/commands/gen-js/__snapshots__/index.d.ts b/tests/commands/gen-js/__snapshots__/index.d.ts index 3a0fd667..5753de09 100644 --- a/tests/commands/gen-js/__snapshots__/index.d.ts +++ b/tests/commands/gen-js/__snapshots__/index.d.ts @@ -102,6 +102,10 @@ export interface The42_TerribleEventName3 { * AcronymStyle bug fixed in v5.0.1 */ identifier_id?: any; + /** + * Duplicate key error in Android + */ + identifierId?: any; } export interface ExampleEvent { @@ -125,10 +129,12 @@ export interface ExampleEvent { * Optional integer property */ "optional int"?: number; + "optional nullable string"?: null | string; /** * Optional number property */ "optional number"?: number; + "optional number or string"?: NumberOrString; /** * Optional object property */ @@ -165,10 +171,12 @@ export interface ExampleEvent { * Required integer property */ "required int": number; + "required nullable string": null | string; /** * Required number property */ "required number": number; + "required number or string": NumberOrString; /** * Required object property */ @@ -198,6 +206,8 @@ export interface OptionalArray { "required sub-property": string; } +export type NumberOrString = number | string; + /** * Optional object property */ @@ -274,6 +284,28 @@ export default class Analytics { callback?: AnalyticsJSCallback ): void; + /** + * Optional object (empty) property + * + * Required object (empty) property + */ + draft04Event( + props?: {}, + options?: SegmentOptions, + callback?: AnalyticsJSCallback + ): void; + + /** + * Optional object (empty) property + * + * Required object (empty) property + */ + draft06Event( + props?: {}, + options?: SegmentOptions, + callback?: AnalyticsJSCallback + ): void; + /** * Optional object (empty) property * @@ -296,7 +328,7 @@ export default class Analytics { * * Required object (empty) property */ - draft04Event( + checkIn( props?: {}, options?: SegmentOptions, callback?: AnalyticsJSCallback @@ -307,7 +339,7 @@ export default class Analytics { * * Required object (empty) property */ - draft06Event( + checkin( props?: {}, options?: SegmentOptions, callback?: AnalyticsJSCallback diff --git a/tests/commands/gen-js/__snapshots__/index.es5.js b/tests/commands/gen-js/__snapshots__/index.es5.js index 213909e7..849b2bd0 100644 --- a/tests/commands/gen-js/__snapshots__/index.es5.js +++ b/tests/commands/gen-js/__snapshots__/index.es5.js @@ -123,6 +123,166 @@ var Analytics = /** @class */ (function() { callback ); }; + Analytics.prototype.draft04Event = function(props, options, callback) { + if (props === void 0) { + props = {}; + } + if (options === void 0) { + options = {}; + } + var validate = function( + data, + dataPath, + parentData, + parentDataProperty, + rootData + ) { + "use strict"; + var vErrors = null; + var errors = 0; + if (data && typeof data === "object" && !Array.isArray(data)) { + var errs__0 = errors; + var valid1 = true; + var data1 = data.properties; + if (data1 === undefined) { + valid1 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + "", + schemaPath: "#/required", + params: { missingProperty: "properties" }, + message: "should have required property 'properties'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_1 = errors; + if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { + var err = { + keyword: "type", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid1 = errors === errs_1; + } + } else { + var err = { + keyword: "type", + dataPath: (dataPath || "") + "", + schemaPath: "#/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + validate.errors = vErrors; + return errors === 0; + }; + if (!validate({ properties: props })) { + this.onError({ + eventName: "Draft-04 Event", + validationErrors: validate.errors + }); + return; + } + this.analytics.track( + "Draft-04 Event", + props, + __assign({}, options, { + context: this.addTypewriterContext(options.context) + }), + callback + ); + }; + Analytics.prototype.draft06Event = function(props, options, callback) { + if (props === void 0) { + props = {}; + } + if (options === void 0) { + options = {}; + } + var validate = function( + data, + dataPath, + parentData, + parentDataProperty, + rootData + ) { + "use strict"; + var vErrors = null; + var errors = 0; + if (data && typeof data === "object" && !Array.isArray(data)) { + var errs__0 = errors; + var valid1 = true; + var data1 = data.properties; + if (data1 === undefined) { + valid1 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + "", + schemaPath: "#/required", + params: { missingProperty: "properties" }, + message: "should have required property 'properties'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_1 = errors; + if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { + var err = { + keyword: "type", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid1 = errors === errs_1; + } + } else { + var err = { + keyword: "type", + dataPath: (dataPath || "") + "", + schemaPath: "#/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + validate.errors = vErrors; + return errors === 0; + }; + if (!validate({ properties: props })) { + this.onError({ + eventName: "Draft-06 Event", + validationErrors: validate.errors + }); + return; + } + this.analytics.track( + "Draft-06 Event", + props, + __assign({}, options, { + context: this.addTypewriterContext(options.context) + }), + callback + ); + }; Analytics.prototype.emptyEvent = function(props, options, callback) { if (props === void 0) { props = {}; @@ -418,6 +578,26 @@ var Analytics = /** @class */ (function() { } var valid2 = errors === errs_2; } + var data2 = data1["optional nullable string"]; + if (data2 !== undefined) { + var errs_2 = errors; + if (typeof data2 !== "string" && data2 !== null) { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['optional nullable string']", + schemaPath: + "#/properties/properties/properties/optional%20nullable%20string/type", + params: { type: "string,null" }, + message: "should be string,null" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } if (data1["optional number"] !== undefined) { var errs_2 = errors; if (typeof data1["optional number"] !== "number") { @@ -435,6 +615,26 @@ var Analytics = /** @class */ (function() { } var valid2 = errors === errs_2; } + var data2 = data1["optional number or string"]; + if (data2 !== undefined) { + var errs_2 = errors; + if (typeof data2 !== "number" && typeof data2 !== "string") { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['optional number or string']", + schemaPath: + "#/properties/properties/properties/optional%20number%20or%20string/type", + params: { type: "number,string" }, + message: "should be number,string" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } var data2 = data1["optional object"]; if (data2 !== undefined) { var errs_2 = errors; @@ -792,6 +992,39 @@ var Analytics = /** @class */ (function() { } var valid2 = errors === errs_2; } + var data2 = data1["required nullable string"]; + if (data2 === undefined) { + valid2 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/required", + params: { missingProperty: "required nullable string" }, + message: + "should have required property 'required nullable string'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_2 = errors; + if (typeof data2 !== "string" && data2 !== null) { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['required nullable string']", + schemaPath: + "#/properties/properties/properties/required%20nullable%20string/type", + params: { type: "string,null" }, + message: "should be string,null" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } if (data1["required number"] === undefined) { valid2 = false; var err = { @@ -821,6 +1054,39 @@ var Analytics = /** @class */ (function() { } var valid2 = errors === errs_2; } + var data2 = data1["required number or string"]; + if (data2 === undefined) { + valid2 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/required", + params: { missingProperty: "required number or string" }, + message: + "should have required property 'required number or string'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_2 = errors; + if (typeof data2 !== "number" && typeof data2 !== "string") { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['required number or string']", + schemaPath: + "#/properties/properties/properties/required%20number%20or%20string/type", + params: { type: "number,string" }, + message: "should be number,string" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } var data2 = data1["required object"]; if (data2 === undefined) { valid2 = false; @@ -1059,7 +1325,7 @@ var Analytics = /** @class */ (function() { callback ); }; - Analytics.prototype.draft04Event = function(props, options, callback) { + Analytics.prototype.checkIn = function(props, options, callback) { if (props === void 0) { props = {}; } @@ -1080,19 +1346,7 @@ var Analytics = /** @class */ (function() { var errs__0 = errors; var valid1 = true; var data1 = data.properties; - if (data1 === undefined) { - valid1 = false; - var err = { - keyword: "required", - dataPath: (dataPath || "") + "", - schemaPath: "#/required", - params: { missingProperty: "properties" }, - message: "should have required property 'properties'" - }; - if (vErrors === null) vErrors = [err]; - else vErrors.push(err); - errors++; - } else { + if (data1 !== undefined) { var errs_1 = errors; if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { var err = { @@ -1125,13 +1379,13 @@ var Analytics = /** @class */ (function() { }; if (!validate({ properties: props })) { this.onError({ - eventName: "Draft-04 Event", + eventName: "check_in", validationErrors: validate.errors }); return; } this.analytics.track( - "Draft-04 Event", + "check_in", props, __assign({}, options, { context: this.addTypewriterContext(options.context) @@ -1139,7 +1393,7 @@ var Analytics = /** @class */ (function() { callback ); }; - Analytics.prototype.draft06Event = function(props, options, callback) { + Analytics.prototype.checkin = function(props, options, callback) { if (props === void 0) { props = {}; } @@ -1160,19 +1414,7 @@ var Analytics = /** @class */ (function() { var errs__0 = errors; var valid1 = true; var data1 = data.properties; - if (data1 === undefined) { - valid1 = false; - var err = { - keyword: "required", - dataPath: (dataPath || "") + "", - schemaPath: "#/required", - params: { missingProperty: "properties" }, - message: "should have required property 'properties'" - }; - if (vErrors === null) vErrors = [err]; - else vErrors.push(err); - errors++; - } else { + if (data1 !== undefined) { var errs_1 = errors; if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { var err = { @@ -1204,14 +1446,11 @@ var Analytics = /** @class */ (function() { return errors === 0; }; if (!validate({ properties: props })) { - this.onError({ - eventName: "Draft-06 Event", - validationErrors: validate.errors - }); + this.onError({ eventName: "checkin", validationErrors: validate.errors }); return; } this.analytics.track( - "Draft-06 Event", + "checkin", props, __assign({}, options, { context: this.addTypewriterContext(options.context) diff --git a/tests/commands/gen-js/__snapshots__/index.es5.node.js b/tests/commands/gen-js/__snapshots__/index.es5.node.js index cf1a1a77..6967e412 100644 --- a/tests/commands/gen-js/__snapshots__/index.es5.node.js +++ b/tests/commands/gen-js/__snapshots__/index.es5.node.js @@ -117,6 +117,154 @@ var Analytics = /** @class */ (function() { }); this.analytics.track(message, callback); }; + Analytics.prototype.draft04Event = function(message, callback) { + if (message === void 0) { + message = {}; + } + var validate = function( + data, + dataPath, + parentData, + parentDataProperty, + rootData + ) { + "use strict"; + var vErrors = null; + var errors = 0; + if (data && typeof data === "object" && !Array.isArray(data)) { + var errs__0 = errors; + var valid1 = true; + var data1 = data.properties; + if (data1 === undefined) { + valid1 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + "", + schemaPath: "#/required", + params: { missingProperty: "properties" }, + message: "should have required property 'properties'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_1 = errors; + if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { + var err = { + keyword: "type", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid1 = errors === errs_1; + } + } else { + var err = { + keyword: "type", + dataPath: (dataPath || "") + "", + schemaPath: "#/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + validate.errors = vErrors; + return errors === 0; + }; + if (!validate(message)) { + this.onError({ + eventName: "Draft-04 Event", + validationErrors: validate.errors + }); + return; + } + message = __assign({}, message, { + context: this.addTypewriterContext(message.context), + event: "Draft-04 Event" + }); + this.analytics.track(message, callback); + }; + Analytics.prototype.draft06Event = function(message, callback) { + if (message === void 0) { + message = {}; + } + var validate = function( + data, + dataPath, + parentData, + parentDataProperty, + rootData + ) { + "use strict"; + var vErrors = null; + var errors = 0; + if (data && typeof data === "object" && !Array.isArray(data)) { + var errs__0 = errors; + var valid1 = true; + var data1 = data.properties; + if (data1 === undefined) { + valid1 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + "", + schemaPath: "#/required", + params: { missingProperty: "properties" }, + message: "should have required property 'properties'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_1 = errors; + if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { + var err = { + keyword: "type", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid1 = errors === errs_1; + } + } else { + var err = { + keyword: "type", + dataPath: (dataPath || "") + "", + schemaPath: "#/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + validate.errors = vErrors; + return errors === 0; + }; + if (!validate(message)) { + this.onError({ + eventName: "Draft-06 Event", + validationErrors: validate.errors + }); + return; + } + message = __assign({}, message, { + context: this.addTypewriterContext(message.context), + event: "Draft-06 Event" + }); + this.analytics.track(message, callback); + }; Analytics.prototype.emptyEvent = function(message, callback) { if (message === void 0) { message = {}; @@ -403,6 +551,26 @@ var Analytics = /** @class */ (function() { } var valid2 = errors === errs_2; } + var data2 = data1["optional nullable string"]; + if (data2 !== undefined) { + var errs_2 = errors; + if (typeof data2 !== "string" && data2 !== null) { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['optional nullable string']", + schemaPath: + "#/properties/properties/properties/optional%20nullable%20string/type", + params: { type: "string,null" }, + message: "should be string,null" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } if (data1["optional number"] !== undefined) { var errs_2 = errors; if (typeof data1["optional number"] !== "number") { @@ -420,6 +588,26 @@ var Analytics = /** @class */ (function() { } var valid2 = errors === errs_2; } + var data2 = data1["optional number or string"]; + if (data2 !== undefined) { + var errs_2 = errors; + if (typeof data2 !== "number" && typeof data2 !== "string") { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['optional number or string']", + schemaPath: + "#/properties/properties/properties/optional%20number%20or%20string/type", + params: { type: "number,string" }, + message: "should be number,string" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } var data2 = data1["optional object"]; if (data2 !== undefined) { var errs_2 = errors; @@ -777,6 +965,39 @@ var Analytics = /** @class */ (function() { } var valid2 = errors === errs_2; } + var data2 = data1["required nullable string"]; + if (data2 === undefined) { + valid2 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/required", + params: { missingProperty: "required nullable string" }, + message: + "should have required property 'required nullable string'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_2 = errors; + if (typeof data2 !== "string" && data2 !== null) { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['required nullable string']", + schemaPath: + "#/properties/properties/properties/required%20nullable%20string/type", + params: { type: "string,null" }, + message: "should be string,null" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } if (data1["required number"] === undefined) { valid2 = false; var err = { @@ -806,6 +1027,39 @@ var Analytics = /** @class */ (function() { } var valid2 = errors === errs_2; } + var data2 = data1["required number or string"]; + if (data2 === undefined) { + valid2 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/required", + params: { missingProperty: "required number or string" }, + message: + "should have required property 'required number or string'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_2 = errors; + if (typeof data2 !== "number" && typeof data2 !== "string") { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['required number or string']", + schemaPath: + "#/properties/properties/properties/required%20number%20or%20string/type", + params: { type: "number,string" }, + message: "should be number,string" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } var data2 = data1["required object"]; if (data2 === undefined) { valid2 = false; @@ -1041,7 +1295,7 @@ var Analytics = /** @class */ (function() { }); this.analytics.track(message, callback); }; - Analytics.prototype.draft04Event = function(message, callback) { + Analytics.prototype.checkIn = function(message, callback) { if (message === void 0) { message = {}; } @@ -1059,19 +1313,7 @@ var Analytics = /** @class */ (function() { var errs__0 = errors; var valid1 = true; var data1 = data.properties; - if (data1 === undefined) { - valid1 = false; - var err = { - keyword: "required", - dataPath: (dataPath || "") + "", - schemaPath: "#/required", - params: { missingProperty: "properties" }, - message: "should have required property 'properties'" - }; - if (vErrors === null) vErrors = [err]; - else vErrors.push(err); - errors++; - } else { + if (data1 !== undefined) { var errs_1 = errors; if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { var err = { @@ -1104,18 +1346,18 @@ var Analytics = /** @class */ (function() { }; if (!validate(message)) { this.onError({ - eventName: "Draft-04 Event", + eventName: "check_in", validationErrors: validate.errors }); return; } message = __assign({}, message, { context: this.addTypewriterContext(message.context), - event: "Draft-04 Event" + event: "check_in" }); this.analytics.track(message, callback); }; - Analytics.prototype.draft06Event = function(message, callback) { + Analytics.prototype.checkin = function(message, callback) { if (message === void 0) { message = {}; } @@ -1133,19 +1375,7 @@ var Analytics = /** @class */ (function() { var errs__0 = errors; var valid1 = true; var data1 = data.properties; - if (data1 === undefined) { - valid1 = false; - var err = { - keyword: "required", - dataPath: (dataPath || "") + "", - schemaPath: "#/required", - params: { missingProperty: "properties" }, - message: "should have required property 'properties'" - }; - if (vErrors === null) vErrors = [err]; - else vErrors.push(err); - errors++; - } else { + if (data1 !== undefined) { var errs_1 = errors; if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { var err = { @@ -1177,15 +1407,12 @@ var Analytics = /** @class */ (function() { return errors === 0; }; if (!validate(message)) { - this.onError({ - eventName: "Draft-06 Event", - validationErrors: validate.errors - }); + this.onError({ eventName: "checkin", validationErrors: validate.errors }); return; } message = __assign({}, message, { context: this.addTypewriterContext(message.context), - event: "Draft-06 Event" + event: "checkin" }); this.analytics.track(message, callback); }; diff --git a/tests/commands/gen-js/__snapshots__/index.js b/tests/commands/gen-js/__snapshots__/index.js index 85be0889..7e57f5df 100644 --- a/tests/commands/gen-js/__snapshots__/index.js +++ b/tests/commands/gen-js/__snapshots__/index.js @@ -92,6 +92,156 @@ export default class Analytics { callback ); } + draft04Event(props = {}, options = {}, callback) { + var validate = function( + data, + dataPath, + parentData, + parentDataProperty, + rootData + ) { + "use strict"; + var vErrors = null; + var errors = 0; + if (data && typeof data === "object" && !Array.isArray(data)) { + var errs__0 = errors; + var valid1 = true; + var data1 = data.properties; + if (data1 === undefined) { + valid1 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + "", + schemaPath: "#/required", + params: { missingProperty: "properties" }, + message: "should have required property 'properties'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_1 = errors; + if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { + var err = { + keyword: "type", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid1 = errors === errs_1; + } + } else { + var err = { + keyword: "type", + dataPath: (dataPath || "") + "", + schemaPath: "#/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + validate.errors = vErrors; + return errors === 0; + }; + if (!validate({ properties: props })) { + this.onError({ + eventName: "Draft-04 Event", + validationErrors: validate.errors + }); + return; + } + this.analytics.track( + "Draft-04 Event", + props, + { + ...options, + context: this.addTypewriterContext(options.context) + }, + callback + ); + } + draft06Event(props = {}, options = {}, callback) { + var validate = function( + data, + dataPath, + parentData, + parentDataProperty, + rootData + ) { + "use strict"; + var vErrors = null; + var errors = 0; + if (data && typeof data === "object" && !Array.isArray(data)) { + var errs__0 = errors; + var valid1 = true; + var data1 = data.properties; + if (data1 === undefined) { + valid1 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + "", + schemaPath: "#/required", + params: { missingProperty: "properties" }, + message: "should have required property 'properties'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_1 = errors; + if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { + var err = { + keyword: "type", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid1 = errors === errs_1; + } + } else { + var err = { + keyword: "type", + dataPath: (dataPath || "") + "", + schemaPath: "#/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + validate.errors = vErrors; + return errors === 0; + }; + if (!validate({ properties: props })) { + this.onError({ + eventName: "Draft-06 Event", + validationErrors: validate.errors + }); + return; + } + this.analytics.track( + "Draft-06 Event", + props, + { + ...options, + context: this.addTypewriterContext(options.context) + }, + callback + ); + } emptyEvent(props = {}, options = {}, callback) { var validate = function( data, @@ -376,6 +526,26 @@ export default class Analytics { } var valid2 = errors === errs_2; } + var data2 = data1["optional nullable string"]; + if (data2 !== undefined) { + var errs_2 = errors; + if (typeof data2 !== "string" && data2 !== null) { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['optional nullable string']", + schemaPath: + "#/properties/properties/properties/optional%20nullable%20string/type", + params: { type: "string,null" }, + message: "should be string,null" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } if (data1["optional number"] !== undefined) { var errs_2 = errors; if (typeof data1["optional number"] !== "number") { @@ -393,6 +563,26 @@ export default class Analytics { } var valid2 = errors === errs_2; } + var data2 = data1["optional number or string"]; + if (data2 !== undefined) { + var errs_2 = errors; + if (typeof data2 !== "number" && typeof data2 !== "string") { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['optional number or string']", + schemaPath: + "#/properties/properties/properties/optional%20number%20or%20string/type", + params: { type: "number,string" }, + message: "should be number,string" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } var data2 = data1["optional object"]; if (data2 !== undefined) { var errs_2 = errors; @@ -750,6 +940,39 @@ export default class Analytics { } var valid2 = errors === errs_2; } + var data2 = data1["required nullable string"]; + if (data2 === undefined) { + valid2 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/required", + params: { missingProperty: "required nullable string" }, + message: + "should have required property 'required nullable string'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_2 = errors; + if (typeof data2 !== "string" && data2 !== null) { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['required nullable string']", + schemaPath: + "#/properties/properties/properties/required%20nullable%20string/type", + params: { type: "string,null" }, + message: "should be string,null" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } if (data1["required number"] === undefined) { valid2 = false; var err = { @@ -779,6 +1002,39 @@ export default class Analytics { } var valid2 = errors === errs_2; } + var data2 = data1["required number or string"]; + if (data2 === undefined) { + valid2 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/required", + params: { missingProperty: "required number or string" }, + message: + "should have required property 'required number or string'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_2 = errors; + if (typeof data2 !== "number" && typeof data2 !== "string") { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['required number or string']", + schemaPath: + "#/properties/properties/properties/required%20number%20or%20string/type", + params: { type: "number,string" }, + message: "should be number,string" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } var data2 = data1["required object"]; if (data2 === undefined) { valid2 = false; @@ -1018,7 +1274,7 @@ export default class Analytics { callback ); } - draft04Event(props = {}, options = {}, callback) { + checkIn(props = {}, options = {}, callback) { var validate = function( data, dataPath, @@ -1033,19 +1289,7 @@ export default class Analytics { var errs__0 = errors; var valid1 = true; var data1 = data.properties; - if (data1 === undefined) { - valid1 = false; - var err = { - keyword: "required", - dataPath: (dataPath || "") + "", - schemaPath: "#/required", - params: { missingProperty: "properties" }, - message: "should have required property 'properties'" - }; - if (vErrors === null) vErrors = [err]; - else vErrors.push(err); - errors++; - } else { + if (data1 !== undefined) { var errs_1 = errors; if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { var err = { @@ -1078,13 +1322,13 @@ export default class Analytics { }; if (!validate({ properties: props })) { this.onError({ - eventName: "Draft-04 Event", + eventName: "check_in", validationErrors: validate.errors }); return; } this.analytics.track( - "Draft-04 Event", + "check_in", props, { ...options, @@ -1093,7 +1337,7 @@ export default class Analytics { callback ); } - draft06Event(props = {}, options = {}, callback) { + checkin(props = {}, options = {}, callback) { var validate = function( data, dataPath, @@ -1108,19 +1352,7 @@ export default class Analytics { var errs__0 = errors; var valid1 = true; var data1 = data.properties; - if (data1 === undefined) { - valid1 = false; - var err = { - keyword: "required", - dataPath: (dataPath || "") + "", - schemaPath: "#/required", - params: { missingProperty: "properties" }, - message: "should have required property 'properties'" - }; - if (vErrors === null) vErrors = [err]; - else vErrors.push(err); - errors++; - } else { + if (data1 !== undefined) { var errs_1 = errors; if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { var err = { @@ -1152,14 +1384,11 @@ export default class Analytics { return errors === 0; }; if (!validate({ properties: props })) { - this.onError({ - eventName: "Draft-06 Event", - validationErrors: validate.errors - }); + this.onError({ eventName: "checkin", validationErrors: validate.errors }); return; } this.analytics.track( - "Draft-06 Event", + "checkin", props, { ...options, diff --git a/tests/commands/gen-js/__snapshots__/index.node.d.ts b/tests/commands/gen-js/__snapshots__/index.node.d.ts index 667a80f5..1e18402f 100644 --- a/tests/commands/gen-js/__snapshots__/index.node.d.ts +++ b/tests/commands/gen-js/__snapshots__/index.node.d.ts @@ -141,6 +141,10 @@ export interface The42_TerribleEventName3 { * AcronymStyle bug fixed in v5.0.1 */ identifier_id?: any; + /** + * Duplicate key error in Android + */ + identifierId?: any; } export interface ExampleEvent { @@ -164,10 +168,12 @@ export interface ExampleEvent { * Optional integer property */ "optional int"?: number; + "optional nullable string"?: null | string; /** * Optional number property */ "optional number"?: number; + "optional number or string"?: NumberOrString; /** * Optional object property */ @@ -204,10 +210,12 @@ export interface ExampleEvent { * Required integer property */ "required int": number; + "required nullable string": null | string; /** * Required number property */ "required number": number; + "required number or string": NumberOrString; /** * Required object property */ @@ -237,6 +245,8 @@ export interface OptionalArray { "required sub-property": string; } +export type NumberOrString = number | string; + /** * Optional object property */ @@ -317,22 +327,17 @@ export default class Analytics { * * Required object (empty) property */ - emptyEvent( + draft04Event( message?: TrackMessage<{}>, callback?: AnalyticsNodeCallback ): void; - exampleEvent( - message?: TrackMessage, - callback?: AnalyticsNodeCallback - ): void; - /** * Optional object (empty) property * * Required object (empty) property */ - draft04Event( + draft06Event( message?: TrackMessage<{}>, callback?: AnalyticsNodeCallback ): void; @@ -342,8 +347,27 @@ export default class Analytics { * * Required object (empty) property */ - draft06Event( + emptyEvent( message?: TrackMessage<{}>, callback?: AnalyticsNodeCallback ): void; + + exampleEvent( + message?: TrackMessage, + callback?: AnalyticsNodeCallback + ): void; + + /** + * Optional object (empty) property + * + * Required object (empty) property + */ + checkIn(message?: TrackMessage<{}>, callback?: AnalyticsNodeCallback): void; + + /** + * Optional object (empty) property + * + * Required object (empty) property + */ + checkin(message?: TrackMessage<{}>, callback?: AnalyticsNodeCallback): void; } diff --git a/tests/commands/gen-js/__snapshots__/index.node.js b/tests/commands/gen-js/__snapshots__/index.node.js index 3a64e02e..b9913217 100644 --- a/tests/commands/gen-js/__snapshots__/index.node.js +++ b/tests/commands/gen-js/__snapshots__/index.node.js @@ -89,6 +89,148 @@ class Analytics { }); this.analytics.track(message, callback); } + draft04Event(message = {}, callback) { + var validate = function( + data, + dataPath, + parentData, + parentDataProperty, + rootData + ) { + "use strict"; + var vErrors = null; + var errors = 0; + if (data && typeof data === "object" && !Array.isArray(data)) { + var errs__0 = errors; + var valid1 = true; + var data1 = data.properties; + if (data1 === undefined) { + valid1 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + "", + schemaPath: "#/required", + params: { missingProperty: "properties" }, + message: "should have required property 'properties'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_1 = errors; + if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { + var err = { + keyword: "type", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid1 = errors === errs_1; + } + } else { + var err = { + keyword: "type", + dataPath: (dataPath || "") + "", + schemaPath: "#/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + validate.errors = vErrors; + return errors === 0; + }; + if (!validate(message)) { + this.onError({ + eventName: "Draft-04 Event", + validationErrors: validate.errors + }); + return; + } + message = Object.assign({}, message, { + context: this.addTypewriterContext(message.context), + event: "Draft-04 Event" + }); + this.analytics.track(message, callback); + } + draft06Event(message = {}, callback) { + var validate = function( + data, + dataPath, + parentData, + parentDataProperty, + rootData + ) { + "use strict"; + var vErrors = null; + var errors = 0; + if (data && typeof data === "object" && !Array.isArray(data)) { + var errs__0 = errors; + var valid1 = true; + var data1 = data.properties; + if (data1 === undefined) { + valid1 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + "", + schemaPath: "#/required", + params: { missingProperty: "properties" }, + message: "should have required property 'properties'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_1 = errors; + if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { + var err = { + keyword: "type", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid1 = errors === errs_1; + } + } else { + var err = { + keyword: "type", + dataPath: (dataPath || "") + "", + schemaPath: "#/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + validate.errors = vErrors; + return errors === 0; + }; + if (!validate(message)) { + this.onError({ + eventName: "Draft-06 Event", + validationErrors: validate.errors + }); + return; + } + message = Object.assign({}, message, { + context: this.addTypewriterContext(message.context), + event: "Draft-06 Event" + }); + this.analytics.track(message, callback); + } emptyEvent(message = {}, callback) { var validate = function( data, @@ -369,6 +511,26 @@ class Analytics { } var valid2 = errors === errs_2; } + var data2 = data1["optional nullable string"]; + if (data2 !== undefined) { + var errs_2 = errors; + if (typeof data2 !== "string" && data2 !== null) { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['optional nullable string']", + schemaPath: + "#/properties/properties/properties/optional%20nullable%20string/type", + params: { type: "string,null" }, + message: "should be string,null" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } if (data1["optional number"] !== undefined) { var errs_2 = errors; if (typeof data1["optional number"] !== "number") { @@ -386,6 +548,26 @@ class Analytics { } var valid2 = errors === errs_2; } + var data2 = data1["optional number or string"]; + if (data2 !== undefined) { + var errs_2 = errors; + if (typeof data2 !== "number" && typeof data2 !== "string") { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['optional number or string']", + schemaPath: + "#/properties/properties/properties/optional%20number%20or%20string/type", + params: { type: "number,string" }, + message: "should be number,string" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } var data2 = data1["optional object"]; if (data2 !== undefined) { var errs_2 = errors; @@ -743,6 +925,39 @@ class Analytics { } var valid2 = errors === errs_2; } + var data2 = data1["required nullable string"]; + if (data2 === undefined) { + valid2 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/required", + params: { missingProperty: "required nullable string" }, + message: + "should have required property 'required nullable string'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_2 = errors; + if (typeof data2 !== "string" && data2 !== null) { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['required nullable string']", + schemaPath: + "#/properties/properties/properties/required%20nullable%20string/type", + params: { type: "string,null" }, + message: "should be string,null" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } if (data1["required number"] === undefined) { valid2 = false; var err = { @@ -772,6 +987,39 @@ class Analytics { } var valid2 = errors === errs_2; } + var data2 = data1["required number or string"]; + if (data2 === undefined) { + valid2 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/required", + params: { missingProperty: "required number or string" }, + message: + "should have required property 'required number or string'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_2 = errors; + if (typeof data2 !== "number" && typeof data2 !== "string") { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['required number or string']", + schemaPath: + "#/properties/properties/properties/required%20number%20or%20string/type", + params: { type: "number,string" }, + message: "should be number,string" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } var data2 = data1["required object"]; if (data2 === undefined) { valid2 = false; @@ -1007,7 +1255,7 @@ class Analytics { }); this.analytics.track(message, callback); } - draft04Event(message = {}, callback) { + checkIn(message = {}, callback) { var validate = function( data, dataPath, @@ -1022,19 +1270,7 @@ class Analytics { var errs__0 = errors; var valid1 = true; var data1 = data.properties; - if (data1 === undefined) { - valid1 = false; - var err = { - keyword: "required", - dataPath: (dataPath || "") + "", - schemaPath: "#/required", - params: { missingProperty: "properties" }, - message: "should have required property 'properties'" - }; - if (vErrors === null) vErrors = [err]; - else vErrors.push(err); - errors++; - } else { + if (data1 !== undefined) { var errs_1 = errors; if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { var err = { @@ -1067,18 +1303,18 @@ class Analytics { }; if (!validate(message)) { this.onError({ - eventName: "Draft-04 Event", + eventName: "check_in", validationErrors: validate.errors }); return; } message = Object.assign({}, message, { context: this.addTypewriterContext(message.context), - event: "Draft-04 Event" + event: "check_in" }); this.analytics.track(message, callback); } - draft06Event(message = {}, callback) { + checkin(message = {}, callback) { var validate = function( data, dataPath, @@ -1093,19 +1329,7 @@ class Analytics { var errs__0 = errors; var valid1 = true; var data1 = data.properties; - if (data1 === undefined) { - valid1 = false; - var err = { - keyword: "required", - dataPath: (dataPath || "") + "", - schemaPath: "#/required", - params: { missingProperty: "properties" }, - message: "should have required property 'properties'" - }; - if (vErrors === null) vErrors = [err]; - else vErrors.push(err); - errors++; - } else { + if (data1 !== undefined) { var errs_1 = errors; if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { var err = { @@ -1137,15 +1361,12 @@ class Analytics { return errors === 0; }; if (!validate(message)) { - this.onError({ - eventName: "Draft-06 Event", - validationErrors: validate.errors - }); + this.onError({ eventName: "checkin", validationErrors: validate.errors }); return; } message = Object.assign({}, message, { context: this.addTypewriterContext(message.context), - event: "Draft-06 Event" + event: "checkin" }); this.analytics.track(message, callback); } diff --git a/tests/commands/gen-js/__snapshots__/index.prod.js b/tests/commands/gen-js/__snapshots__/index.prod.js index 324a3fc6..c7fbc20c 100644 --- a/tests/commands/gen-js/__snapshots__/index.prod.js +++ b/tests/commands/gen-js/__snapshots__/index.prod.js @@ -29,6 +29,28 @@ export default class Analytics { callback ); } + draft04Event(props = {}, options = {}, callback) { + this.analytics.track( + "Draft-04 Event", + props, + { + ...options, + context: this.addTypewriterContext(options.context) + }, + callback + ); + } + draft06Event(props = {}, options = {}, callback) { + this.analytics.track( + "Draft-06 Event", + props, + { + ...options, + context: this.addTypewriterContext(options.context) + }, + callback + ); + } emptyEvent(props = {}, options = {}, callback) { this.analytics.track( "Empty Event", @@ -51,9 +73,9 @@ export default class Analytics { callback ); } - draft04Event(props = {}, options = {}, callback) { + checkIn(props = {}, options = {}, callback) { this.analytics.track( - "Draft-04 Event", + "check_in", props, { ...options, @@ -62,9 +84,9 @@ export default class Analytics { callback ); } - draft06Event(props = {}, options = {}, callback) { + checkin(props = {}, options = {}, callback) { this.analytics.track( - "Draft-06 Event", + "checkin", props, { ...options, diff --git a/tests/commands/gen-js/__snapshots__/index.prod.node.js b/tests/commands/gen-js/__snapshots__/index.prod.node.js index 0b1ebdb3..91e48437 100644 --- a/tests/commands/gen-js/__snapshots__/index.prod.node.js +++ b/tests/commands/gen-js/__snapshots__/index.prod.node.js @@ -26,6 +26,20 @@ class Analytics { }); this.analytics.track(message, callback); } + draft04Event(message = {}, callback) { + message = Object.assign({}, message, { + context: this.addTypewriterContext(message.context), + event: "Draft-04 Event" + }); + this.analytics.track(message, callback); + } + draft06Event(message = {}, callback) { + message = Object.assign({}, message, { + context: this.addTypewriterContext(message.context), + event: "Draft-06 Event" + }); + this.analytics.track(message, callback); + } emptyEvent(message = {}, callback) { message = Object.assign({}, message, { context: this.addTypewriterContext(message.context), @@ -40,17 +54,17 @@ class Analytics { }); this.analytics.track(message, callback); } - draft04Event(message = {}, callback) { + checkIn(message = {}, callback) { message = Object.assign({}, message, { context: this.addTypewriterContext(message.context), - event: "Draft-04 Event" + event: "check_in" }); this.analytics.track(message, callback); } - draft06Event(message = {}, callback) { + checkin(message = {}, callback) { message = Object.assign({}, message, { context: this.addTypewriterContext(message.context), - event: "Draft-06 Event" + event: "checkin" }); this.analytics.track(message, callback); } diff --git a/tests/commands/gen-js/__snapshots__/index.system.js b/tests/commands/gen-js/__snapshots__/index.system.js index 8b016905..1ffeacdd 100644 --- a/tests/commands/gen-js/__snapshots__/index.system.js +++ b/tests/commands/gen-js/__snapshots__/index.system.js @@ -103,6 +103,164 @@ System.register([], function(exports_1, context_1) { callback ); } + draft04Event(props = {}, options = {}, callback) { + var validate = function( + data, + dataPath, + parentData, + parentDataProperty, + rootData + ) { + "use strict"; + var vErrors = null; + var errors = 0; + if (data && typeof data === "object" && !Array.isArray(data)) { + var errs__0 = errors; + var valid1 = true; + var data1 = data.properties; + if (data1 === undefined) { + valid1 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + "", + schemaPath: "#/required", + params: { missingProperty: "properties" }, + message: "should have required property 'properties'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_1 = errors; + if ( + !data1 || + typeof data1 !== "object" || + Array.isArray(data1) + ) { + var err = { + keyword: "type", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid1 = errors === errs_1; + } + } else { + var err = { + keyword: "type", + dataPath: (dataPath || "") + "", + schemaPath: "#/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + validate.errors = vErrors; + return errors === 0; + }; + if (!validate({ properties: props })) { + this.onError({ + eventName: "Draft-04 Event", + validationErrors: validate.errors + }); + return; + } + this.analytics.track( + "Draft-04 Event", + props, + { + ...options, + context: this.addTypewriterContext(options.context) + }, + callback + ); + } + draft06Event(props = {}, options = {}, callback) { + var validate = function( + data, + dataPath, + parentData, + parentDataProperty, + rootData + ) { + "use strict"; + var vErrors = null; + var errors = 0; + if (data && typeof data === "object" && !Array.isArray(data)) { + var errs__0 = errors; + var valid1 = true; + var data1 = data.properties; + if (data1 === undefined) { + valid1 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + "", + schemaPath: "#/required", + params: { missingProperty: "properties" }, + message: "should have required property 'properties'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_1 = errors; + if ( + !data1 || + typeof data1 !== "object" || + Array.isArray(data1) + ) { + var err = { + keyword: "type", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid1 = errors === errs_1; + } + } else { + var err = { + keyword: "type", + dataPath: (dataPath || "") + "", + schemaPath: "#/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + validate.errors = vErrors; + return errors === 0; + }; + if (!validate({ properties: props })) { + this.onError({ + eventName: "Draft-06 Event", + validationErrors: validate.errors + }); + return; + } + this.analytics.track( + "Draft-06 Event", + props, + { + ...options, + context: this.addTypewriterContext(options.context) + }, + callback + ); + } emptyEvent(props = {}, options = {}, callback) { var validate = function( data, @@ -408,6 +566,26 @@ System.register([], function(exports_1, context_1) { } var valid2 = errors === errs_2; } + var data2 = data1["optional nullable string"]; + if (data2 !== undefined) { + var errs_2 = errors; + if (typeof data2 !== "string" && data2 !== null) { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['optional nullable string']", + schemaPath: + "#/properties/properties/properties/optional%20nullable%20string/type", + params: { type: "string,null" }, + message: "should be string,null" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } if (data1["optional number"] !== undefined) { var errs_2 = errors; if (typeof data1["optional number"] !== "number") { @@ -426,6 +604,29 @@ System.register([], function(exports_1, context_1) { } var valid2 = errors === errs_2; } + var data2 = data1["optional number or string"]; + if (data2 !== undefined) { + var errs_2 = errors; + if ( + typeof data2 !== "number" && + typeof data2 !== "string" + ) { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['optional number or string']", + schemaPath: + "#/properties/properties/properties/optional%20number%20or%20string/type", + params: { type: "number,string" }, + message: "should be number,string" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } var data2 = data1["optional object"]; if (data2 !== undefined) { var errs_2 = errors; @@ -814,6 +1015,39 @@ System.register([], function(exports_1, context_1) { } var valid2 = errors === errs_2; } + var data2 = data1["required nullable string"]; + if (data2 === undefined) { + valid2 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/required", + params: { missingProperty: "required nullable string" }, + message: + "should have required property 'required nullable string'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_2 = errors; + if (typeof data2 !== "string" && data2 !== null) { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['required nullable string']", + schemaPath: + "#/properties/properties/properties/required%20nullable%20string/type", + params: { type: "string,null" }, + message: "should be string,null" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } if (data1["required number"] === undefined) { valid2 = false; var err = { @@ -844,6 +1078,42 @@ System.register([], function(exports_1, context_1) { } var valid2 = errors === errs_2; } + var data2 = data1["required number or string"]; + if (data2 === undefined) { + valid2 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/required", + params: { missingProperty: "required number or string" }, + message: + "should have required property 'required number or string'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_2 = errors; + if ( + typeof data2 !== "number" && + typeof data2 !== "string" + ) { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['required number or string']", + schemaPath: + "#/properties/properties/properties/required%20number%20or%20string/type", + params: { type: "number,string" }, + message: "should be number,string" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } var data2 = data1["required object"]; if (data2 === undefined) { valid2 = false; @@ -1101,7 +1371,7 @@ System.register([], function(exports_1, context_1) { callback ); } - draft04Event(props = {}, options = {}, callback) { + checkIn(props = {}, options = {}, callback) { var validate = function( data, dataPath, @@ -1116,19 +1386,7 @@ System.register([], function(exports_1, context_1) { var errs__0 = errors; var valid1 = true; var data1 = data.properties; - if (data1 === undefined) { - valid1 = false; - var err = { - keyword: "required", - dataPath: (dataPath || "") + "", - schemaPath: "#/required", - params: { missingProperty: "properties" }, - message: "should have required property 'properties'" - }; - if (vErrors === null) vErrors = [err]; - else vErrors.push(err); - errors++; - } else { + if (data1 !== undefined) { var errs_1 = errors; if ( !data1 || @@ -1165,13 +1423,13 @@ System.register([], function(exports_1, context_1) { }; if (!validate({ properties: props })) { this.onError({ - eventName: "Draft-04 Event", + eventName: "check_in", validationErrors: validate.errors }); return; } this.analytics.track( - "Draft-04 Event", + "check_in", props, { ...options, @@ -1180,7 +1438,7 @@ System.register([], function(exports_1, context_1) { callback ); } - draft06Event(props = {}, options = {}, callback) { + checkin(props = {}, options = {}, callback) { var validate = function( data, dataPath, @@ -1195,19 +1453,7 @@ System.register([], function(exports_1, context_1) { var errs__0 = errors; var valid1 = true; var data1 = data.properties; - if (data1 === undefined) { - valid1 = false; - var err = { - keyword: "required", - dataPath: (dataPath || "") + "", - schemaPath: "#/required", - params: { missingProperty: "properties" }, - message: "should have required property 'properties'" - }; - if (vErrors === null) vErrors = [err]; - else vErrors.push(err); - errors++; - } else { + if (data1 !== undefined) { var errs_1 = errors; if ( !data1 || @@ -1244,13 +1490,13 @@ System.register([], function(exports_1, context_1) { }; if (!validate({ properties: props })) { this.onError({ - eventName: "Draft-06 Event", + eventName: "checkin", validationErrors: validate.errors }); return; } this.analytics.track( - "Draft-06 Event", + "checkin", props, { ...options, diff --git a/tests/commands/gen-js/__snapshots__/index.umd.js b/tests/commands/gen-js/__snapshots__/index.umd.js index 40eb3609..723945eb 100644 --- a/tests/commands/gen-js/__snapshots__/index.umd.js +++ b/tests/commands/gen-js/__snapshots__/index.umd.js @@ -102,6 +102,156 @@ callback ); } + draft04Event(props = {}, options = {}, callback) { + var validate = function( + data, + dataPath, + parentData, + parentDataProperty, + rootData + ) { + "use strict"; + var vErrors = null; + var errors = 0; + if (data && typeof data === "object" && !Array.isArray(data)) { + var errs__0 = errors; + var valid1 = true; + var data1 = data.properties; + if (data1 === undefined) { + valid1 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + "", + schemaPath: "#/required", + params: { missingProperty: "properties" }, + message: "should have required property 'properties'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_1 = errors; + if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { + var err = { + keyword: "type", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid1 = errors === errs_1; + } + } else { + var err = { + keyword: "type", + dataPath: (dataPath || "") + "", + schemaPath: "#/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + validate.errors = vErrors; + return errors === 0; + }; + if (!validate({ properties: props })) { + this.onError({ + eventName: "Draft-04 Event", + validationErrors: validate.errors + }); + return; + } + this.analytics.track( + "Draft-04 Event", + props, + { + ...options, + context: this.addTypewriterContext(options.context) + }, + callback + ); + } + draft06Event(props = {}, options = {}, callback) { + var validate = function( + data, + dataPath, + parentData, + parentDataProperty, + rootData + ) { + "use strict"; + var vErrors = null; + var errors = 0; + if (data && typeof data === "object" && !Array.isArray(data)) { + var errs__0 = errors; + var valid1 = true; + var data1 = data.properties; + if (data1 === undefined) { + valid1 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + "", + schemaPath: "#/required", + params: { missingProperty: "properties" }, + message: "should have required property 'properties'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_1 = errors; + if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { + var err = { + keyword: "type", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid1 = errors === errs_1; + } + } else { + var err = { + keyword: "type", + dataPath: (dataPath || "") + "", + schemaPath: "#/type", + params: { type: "object" }, + message: "should be object" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + validate.errors = vErrors; + return errors === 0; + }; + if (!validate({ properties: props })) { + this.onError({ + eventName: "Draft-06 Event", + validationErrors: validate.errors + }); + return; + } + this.analytics.track( + "Draft-06 Event", + props, + { + ...options, + context: this.addTypewriterContext(options.context) + }, + callback + ); + } emptyEvent(props = {}, options = {}, callback) { var validate = function( data, @@ -392,6 +542,26 @@ } var valid2 = errors === errs_2; } + var data2 = data1["optional nullable string"]; + if (data2 !== undefined) { + var errs_2 = errors; + if (typeof data2 !== "string" && data2 !== null) { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['optional nullable string']", + schemaPath: + "#/properties/properties/properties/optional%20nullable%20string/type", + params: { type: "string,null" }, + message: "should be string,null" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } if (data1["optional number"] !== undefined) { var errs_2 = errors; if (typeof data1["optional number"] !== "number") { @@ -410,6 +580,26 @@ } var valid2 = errors === errs_2; } + var data2 = data1["optional number or string"]; + if (data2 !== undefined) { + var errs_2 = errors; + if (typeof data2 !== "number" && typeof data2 !== "string") { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['optional number or string']", + schemaPath: + "#/properties/properties/properties/optional%20number%20or%20string/type", + params: { type: "number,string" }, + message: "should be number,string" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } var data2 = data1["optional object"]; if (data2 !== undefined) { var errs_2 = errors; @@ -785,6 +975,39 @@ } var valid2 = errors === errs_2; } + var data2 = data1["required nullable string"]; + if (data2 === undefined) { + valid2 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/required", + params: { missingProperty: "required nullable string" }, + message: + "should have required property 'required nullable string'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_2 = errors; + if (typeof data2 !== "string" && data2 !== null) { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['required nullable string']", + schemaPath: + "#/properties/properties/properties/required%20nullable%20string/type", + params: { type: "string,null" }, + message: "should be string,null" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } if (data1["required number"] === undefined) { valid2 = false; var err = { @@ -815,6 +1038,39 @@ } var valid2 = errors === errs_2; } + var data2 = data1["required number or string"]; + if (data2 === undefined) { + valid2 = false; + var err = { + keyword: "required", + dataPath: (dataPath || "") + ".properties", + schemaPath: "#/properties/properties/required", + params: { missingProperty: "required number or string" }, + message: + "should have required property 'required number or string'" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } else { + var errs_2 = errors; + if (typeof data2 !== "number" && typeof data2 !== "string") { + var err = { + keyword: "type", + dataPath: + (dataPath || "") + + ".properties['required number or string']", + schemaPath: + "#/properties/properties/properties/required%20number%20or%20string/type", + params: { type: "number,string" }, + message: "should be number,string" + }; + if (vErrors === null) vErrors = [err]; + else vErrors.push(err); + errors++; + } + var valid2 = errors === errs_2; + } var data2 = data1["required object"]; if (data2 === undefined) { valid2 = false; @@ -1067,7 +1323,7 @@ callback ); } - draft04Event(props = {}, options = {}, callback) { + checkIn(props = {}, options = {}, callback) { var validate = function( data, dataPath, @@ -1082,19 +1338,7 @@ var errs__0 = errors; var valid1 = true; var data1 = data.properties; - if (data1 === undefined) { - valid1 = false; - var err = { - keyword: "required", - dataPath: (dataPath || "") + "", - schemaPath: "#/required", - params: { missingProperty: "properties" }, - message: "should have required property 'properties'" - }; - if (vErrors === null) vErrors = [err]; - else vErrors.push(err); - errors++; - } else { + if (data1 !== undefined) { var errs_1 = errors; if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { var err = { @@ -1127,13 +1371,13 @@ }; if (!validate({ properties: props })) { this.onError({ - eventName: "Draft-04 Event", + eventName: "check_in", validationErrors: validate.errors }); return; } this.analytics.track( - "Draft-04 Event", + "check_in", props, { ...options, @@ -1142,7 +1386,7 @@ callback ); } - draft06Event(props = {}, options = {}, callback) { + checkin(props = {}, options = {}, callback) { var validate = function( data, dataPath, @@ -1157,19 +1401,7 @@ var errs__0 = errors; var valid1 = true; var data1 = data.properties; - if (data1 === undefined) { - valid1 = false; - var err = { - keyword: "required", - dataPath: (dataPath || "") + "", - schemaPath: "#/required", - params: { missingProperty: "properties" }, - message: "should have required property 'properties'" - }; - if (vErrors === null) vErrors = [err]; - else vErrors.push(err); - errors++; - } else { + if (data1 !== undefined) { var errs_1 = errors; if (!data1 || typeof data1 !== "object" || Array.isArray(data1)) { var err = { @@ -1202,13 +1434,13 @@ }; if (!validate({ properties: props })) { this.onError({ - eventName: "Draft-06 Event", + eventName: "checkin", validationErrors: validate.errors }); return; } this.analytics.track( - "Draft-06 Event", + "checkin", props, { ...options,