This is a comprehensive migration of our Node.js library to TypeScript with additional quality-of-life improvements.
All API methods and return types now have full TypeScript type declarations.
All argument properties are optional. We intend to refine this in the future once we have better OpenAPI definitions.
Some API services and methods that were missing are now implemented:
SecondaryDns.*
Zones.updateZoneNsRecords
Some deprecated methods have been removed:
Collaborators.*
Registrar.disableAutoRenewal
Registrar.enableAutoRenewal
Class names have changed.
Dnsimple => DNSimple
Oauth => OAuth
Method names have currently not been changed for easier migration, even when they differ from their OpenAPI operation ID.
Most method signatures are identical, but some have changed.
For example, account IDs are now integers, as that's the OpenAPI definition.
Argument names have changed but they are not part of the signature.
The options argument on every API method has been renamed to params and now takes a flat object of query parameters. query and filter are no longer special properties, as internally they were simply unpacked into the parent object (overwriting anything existing) and did nothing special.
Parameter values can be strings, numbers, booleans, null, or undefined. If they are false, null, or undefined, they will be omitted. If they are true, they will be provided in the query string with no value.
All API methods now call request directly with the method instead of a method wrapper (e.g. get(), post(), patch()). The request method has been moved to DNSimple, which allows both users and internals to make authenticated requests using the same code and interface.
Request errors are now dedicated classes that inherit from the RequestError base class, instead of being plain objects and strings. This is more standard JS and allows for matching on error types. Errors thrown elsewhere (e.g. HTTP request library) are passed through instead of only providing its error message so that they can be handled as required by the user.
The HTTP requester function has been abstracted as the Fetcher type, allowing the use of this library from both Node.js (https.request()) and the browser (fetch()). This also allows users to use their own logic, such as other libraries, retry strategies, intercepting and mutating, or logging and tracing.
We don't use node-fetch or any other Node.js library as we have very basic needs and most libraries bring a lot of extra unused features (forms, streams, cookies, etc.). It would also be another dependency to manage, learn, document, and migrate on breaking changes. It also increases the bundle size and makes it harder to build for browsers and Node.js, as we have to ensure no Node.js code runs when in a browser and vice versa.
The DNSimple class has been simplified:
All configuration properties (including timeout) can be directly accessed and assigned to.
The VERSION instance property does not exist; use DNSimple.VERSION, which continues to exist.
The services static property does not exist. This should not be necessary as all service classes are instantiated as properties on DNSimple. If necessary, import the class and instantiate directly.
It's a JS class instead of a function, so new must be used when calling the constructor.
The single constructor argument can be omitted.
JSDoc comments for API methods now contain the OpenAPI description and REST API method and path. It no longer has any custom comment. The types are moved to the TypeScript code. Parameter descriptions also now come from the OpenAPI description.
API methods are now arrow functions and their this value is always bound to their instance object, so there is no need to use a closure or bind/provide this when getting the method function.
The OAuth class methods have all arguments moved to a single object for consistency. Arbitrary query parameters cannot be provided, as they will be rejected/ignored by the server.
For the authorizeUrl method, the redirect_uri property has been renamed to redirectUri for consistency with exchangeAuthorizationForToken.
All required options are now typed as such.
All lib and test source code files are now flattened. Also, the main file has been renamed from dnsimple to main to emphasise that it is the entrypoint. These are internal details, so it's not a public interface change.
For APIs with pagination, their method has two submethods called iterateAll that returns an async iterator over all individual items across all pages, and collectAll which pushes them into an array and returns the array. These make as many paginated requests as necessary in the background. The Paginate class has now been deleted, replaced with a much simpler paginate async generator function. Dedicated pagination methods have been removed:
Certificates.allCertificates
Contacts.allContacts
Domains.allDelegationSignerRecords
Domains.allDomains
Domains.allEmailForwards
Services.allAppliedServices
Services.allServices
Templates.allTemplateRecords
Templates.allTemplates
Tlds.allTlds
Webhooks.allWebhooks
Zones.allZoneRecords
Zones.allZones
Imports and exports now use ESM syntax instead of CommonJS. It's the newest standard and works better for build tools, tree shaking, and browsers. The built output is still CommonJS, however, as ESM is still not widely supported and used from Node.js.
We use named exports instead of default exports as the syntax is more similar when importing for both CommonJS and ESM, and the syntax is clearer when importing multiple items:
Default imports: import DNSimple from "dnsimple"; import {Fetcher, QueryParams} from "dnsimple" and const {default: DNSimple, Fetcher, QueryParams} = require("dnsimple").
Named exports: import {DNSimple, Fetcher, QueryParams} from "dnsimple" and const {DNSimple, Fetcher, QueryParams} = require("dnsimple").
We dropped the use of the querystring Node.js module in favour of a simple toQueryString function in main.ts. This drops our dependency on Node.js, useful for shipping to browsers.
The @types/node version has been set to 14.x as that's the minimum Node.js version we support and it's important we don't use any newer functionality.
As we are now using TypeScript, we need to build our code before we publish it. Run npm run build to build into the dist directory, which is ignored by Git. The package.json has been updated to use dist.
Dropped our JS linter and added a formatter (Prettier). We can investigate adding a TS linter in the future. We now check the formatting as part of CI.
Removed package-lock.json as this is a library package.
Updated our CI to not use the lockfile.
Tests have also been migrated to TypeScript. We use ts-node to run the tests.
This is a comprehensive migration of our Node.js library to TypeScript with additional quality-of-life improvements.
SecondaryDns.*
Zones.updateZoneNsRecords
Collaborators.*
Registrar.disableAutoRenewal
Registrar.enableAutoRenewal
Dnsimple
=>DNSimple
Oauth
=>OAuth
options
argument on every API method has been renamed toparams
and now takes a flat object of query parameters.query
andfilter
are no longer special properties, as internally they were simply unpacked into the parent object (overwriting anything existing) and did nothing special.null
, orundefined
. If they arefalse
,null
, orundefined
, they will be omitted. If they aretrue
, they will be provided in the query string with no value.request
directly with the method instead of a method wrapper (e.g.get()
,post()
,patch()
). Therequest
method has been moved toDNSimple
, which allows both users and internals to make authenticated requests using the same code and interface.RequestError
base class, instead of being plain objects and strings. This is more standard JS and allows for matching on error types. Errors thrown elsewhere (e.g. HTTP request library) are passed through instead of only providing its error message so that they can be handled as required by the user.Fetcher
type, allowing the use of this library from both Node.js (https.request()
) and the browser (fetch()
). This also allows users to use their own logic, such as other libraries, retry strategies, intercepting and mutating, or logging and tracing.node-fetch
or any other Node.js library as we have very basic needs and most libraries bring a lot of extra unused features (forms, streams, cookies, etc.). It would also be another dependency to manage, learn, document, and migrate on breaking changes. It also increases the bundle size and makes it harder to build for browsers and Node.js, as we have to ensure no Node.js code runs when in a browser and vice versa.DNSimple
class has been simplified:timeout
) can be directly accessed and assigned to.VERSION
instance property does not exist; useDNSimple.VERSION
, which continues to exist.services
static property does not exist. This should not be necessary as all service classes are instantiated as properties onDNSimple
. If necessary, import the class and instantiate directly.new
must be used when calling the constructor.this
value is always bound to their instance object, so there is no need to use a closure or bind/providethis
when getting the method function.OAuth
class methods have all arguments moved to a single object for consistency. Arbitrary query parameters cannot be provided, as they will be rejected/ignored by the server.authorizeUrl
method, theredirect_uri
property has been renamed toredirectUri
for consistency withexchangeAuthorizationForToken
.lib
andtest
source code files are now flattened. Also, the main file has been renamed fromdnsimple
tomain
to emphasise that it is the entrypoint. These are internal details, so it's not a public interface change.iterateAll
that returns an async iterator over all individual items across all pages, andcollectAll
which pushes them into an array and returns the array. These make as many paginated requests as necessary in the background. ThePaginate
class has now been deleted, replaced with a much simplerpaginate
async generator function. Dedicated pagination methods have been removed:Certificates.allCertificates
Contacts.allContacts
Domains.allDelegationSignerRecords
Domains.allDomains
Domains.allEmailForwards
Services.allAppliedServices
Services.allServices
Templates.allTemplateRecords
Templates.allTemplates
Tlds.allTlds
Webhooks.allWebhooks
Zones.allZoneRecords
Zones.allZones
import DNSimple from "dnsimple"; import {Fetcher, QueryParams} from "dnsimple"
andconst {default: DNSimple, Fetcher, QueryParams} = require("dnsimple")
.import {DNSimple, Fetcher, QueryParams} from "dnsimple"
andconst {DNSimple, Fetcher, QueryParams} = require("dnsimple")
.querystring
Node.js module in favour of a simpletoQueryString
function inmain.ts
. This drops our dependency on Node.js, useful for shipping to browsers.@types/node
version has been set to14.x
as that's the minimum Node.js version we support and it's important we don't use any newer functionality.npm run build
to build into thedist
directory, which is ignored by Git. Thepackage.json
has been updated to usedist
.package-lock.json
as this is a library package.ts-node
to run the tests.Some OpenAPI definition bugs were found during this migration (https://github.com/dnsimple/dnsimple-developer/pull/472, https://github.com/dnsimple/dnsimple-developer/pull/474).