Releases: segmentio/typewriter
v7.4.0
v7.3.0
This release pulls in a number of dependency upgrades.
- chore(deps): update yargs dependency to latest to fix vulnerability (#145) 9f2055c
- chore: upgrade example directory dependencies to latest to patch vulnerabilites and make current (#149) b95776d
- chore(deps): update handlebars dependency to latest to fix vulnerability (#144) 9eb4fba
- chore(deps): update lodash dependency to latest to fix vulnerability (#143) cdee6c8
v7.2.1
v7.1.0
Android Support
Bug Fixes
Documentation
Development
v7.0.1
Bug Fixes
- iOS: Nullable or optional booleans now generate as
NSNumber *
(PR) (e1aacd6) - iOS: Nullable or optional integers now generate as
NSNumber *
. Added e2e tests for large integers/numbers. (PR) (ed6f267) - All Clients: Added analytics calls as reserved words (
track/identify/group/page/screen/set
) (PR) (b3c2c32) - CLI (
version
): New pre-release versions are only shown if currently running a pre-release (PR) (8c55a22) - Deps: Bump dependencies via
snyk wizard
(PR) (5feb3ea)
Other
v7.0.0
This release is a complete rebuild of typewriter (called 2.0
or v7) that focuses on improving:
- Developer experience (DX)
- Reliability
- Ease of contribution
Developer Experience
Typewriter is now built around the idea of a configuration file (typewriter.yml
) that is used by the CLI to understand how to build your clients. This means that users no longer need to set 4-5 different flags (Tracking Plan ID, directory, workspace slug, etc.) each time they invoke the CLI (without which, the CLI tended to surface difficult-to-understand errors).
To get started, all a user has to know is a single command:
npx typewriter init
This will launch a wizard that walks a user through creating a typewriter.yml
and then builds their first client.
From then on, a user can just run npx typewriter
to pull down their latest Tracking Plan and rebuild their clients.
Through this config file, we are able to provide saner defaults, which in Segment's case, allowed us to remove ~30-50 lines of Makefile
from every typewriter-enabled project.
The entire typewriter CLI was also rebuilt in Ink so we can provide a user-friendly CLI with a special focus on easy-to-remedy error handling (f.e., no stack traces).
We've also launched documentation on the Segment Docs site for typewriter: https://segment.com/docs/protocols/typewriter
Reliability
Previously, when we pushed out new typewriter builds, we would use a combination of snapshot testing on the generated clients and manual testing via a series of example apps in the typewriter repo. We could run the app, which would send off an event or two to Segment, and then we could verify that event showed up correctly in the Segment Debugger.
However, this was problematic because a) it wasn't automated, and therefore didn't always happen and b) it only tested 1-2 example events, so it wasn't exhaustive by any means.
Instead, we now ship a full suite of end-to-end tests that use segmentio/mock
to capture analytics events fired by an example app, and then a standardized test suite (suite.test.ts
) that inspects all of the captured events to verify they match a set of Joi schemas.
This suite, besides verifying that typewriter generates clients that successfully build, also tests for scenarios that have previously caused issues with new releases of typewriter such as:
- What happens if two events have event names that collide?
- What happens if an event has no explicit properties?
- Is
null
sent to Segment for nullable properties? - ... etc.
A large benefit of this setup is that the suite itself is language-agnostic, so a new end-to-end test suite can just be an arbitrary app with the Tracking API address updated to localhost:8765
(segmentio/mock
). It otherwise requires no testing logic within the example app itself. 🎉
We've built out an e2e test suite for all supported languages, including analytics.js
(in JS and TS), analytics-node
(also in JS + TS) and analytics-ios
(in Objective-C and Swift).
Ease of contribution
Adding support for a new language or SDK is now much more straightforward. We've overhauled how client generation works by moving off of QuickType (a powerful library for generating JSON serialization/deserialization clients). QuickType was a great starting point for us, but we had to extend their generators in fairly non-obvious ways to customize what code was generated (subclassing fields/logic that was split across the typewriter and QuickType repos, f.e.). This made our generators long, such as the iOS generator which was previously 600 lines (now <300!), and hard to follow -- especially for new contributors.
We decided to take a different approach to generation in favor of readability and reducing the amount of work+context each generator required. With this, we returned to generators based on Handlebars templates. Building a new generator simply involves implementing the various methods of a Generator
to produce a set of objects that will be passed into your templates.
As part of removing QuickType, we had to roll our own implementations of a few components, specifically:
- AST: Previously, we interacted with QuickType's AST which is generalized to support multiple types of schemas (GraphQL, arbitrary JSON, etc.). In our case, we only need to support JSON Schema, so we built our own JSON Schema parser that is opinionated about what fields are relevant to code generation. This produces an easier-to-use type-safe AST, which allows us to separate certain kinds of logic (such as handling unions) into the AST parser rather than in the generators themselves.
- Namer: QuickType did a fairly good job of handling name collisions in events and properties, though we did hit some quirks, such as not handling case-insensitive name collisions for files. We now use our own namer for handling name collisions.
With all of this functionality together, adding a new language looks like this:
- Build the generator by implementing the various
Generator
methods - Add an example app to
tests/e2e
that fires off the standard suite of events (seesuite.test.ts
) - Document it! Add it to the
README
+ theinit
command + Segment docs
Fixes / New Features
We've also resolved a handful of other issues we've encountered with typewriter, such as:
- Better sane defaults, such as using shared analytics clients by default (
window.analytics
, iOS shared analytics instance, etc.). This means some languages require zero configuration. - A lack of visibility into typewriter usage, due to a lack of analytics.
- Support for JS Proxies, to avoid program crashes caused by missing analytics methods (f.e., if an event is removed from the Tracking Plan and someone mistakenly syncs it). When this happens, an
Unknown Analytics Event Fired
event will fire that allows teams to alert on this. - Support for tree-shaking in JS/TS. Resolves #41
Backwards Compatibility
We haven't ported Android support to this version yet, but will be shipping it soon. For now, we recommend using the Android clients generated by [email protected]
.
The underlying generation logic has heavily changed, so expect the clients to be nearly, but not entirely, compatible with each other. It'll depend on what kind of generated functionality you are using.
Notes
For more context, see: https://paper.dropbox.com/doc/typewriter-Typewriter-2.0-Vision--AnFffUqElJQQOUHtVLGaWnzbAg-FtUl1rmfXyuoVcI8uS5yM
Release 6.1.4
Release 6.1.3
Release 6.1.2
- refactor: remove unused dependencies (#55)