@cdwr/core v1.4.1
Contents
Installation
npm install -D @cdwr/coreUsage
The core package provides a set of utilities that can be used in any Node.js project depending on the use case. Development of these utilities are opinionated to the needs of Codeware projects. However, they are designed to be flexible and aims to be easy to use in other projects as well.
!TIP The package comes with both ESM and CommonJS support
Actions
import { ... } from '@cdwr/core/actions';Utilities to use when developing GitHub Actions.
Release
import { release, ... } from '@cdwr/core/release';A programmatic CLI for the Nx release process.
Powered by clack to provide a guided release process.
Example usage
// run-release.ts
import { release } from '@cdwr/core/release';
(async () => {
process.exit(await release());
})();npx tsx ./path/to/run-release.tsTesting
import { createSchemaTests, ... } from '@cdwr/core/testing';Create an automated test suite for your Zod schemas and fixture data.
Verify the correctness of your schema transformations by comparing the output to your API responses or other data sources.
Enable snapshot testing to visually inspect the generated output and catch unintended changes to either your schema or fixture data. The snapshots also serves as reference for the expected output structure.
Example usage
!TIP It's recommended to create a separate file for each schema definition, but it's not required
For each schema you want to test must be registered to the test suite by calling register function.
!WARNING Schema definition and registration is kept together here but it's only to make it easier to understand. In a real project, the schema definition and registration should be kept separate. Otherwise, you risk adding test utilities to the production bundle.
To be on the safe side, add all registrations to test files since they're always kept away from the production bundle.
// schemas/page.ts
import { SchemaRegistry } from '@cdwr/core/testing';
const PageSchema = z.object({ ... });
// PageSchema expects to have fixture file `__fixtures__/page.json`
SchemaRegistry.register('page', PageSchema, { name: 'PageSchema'});// equivalent in schemas/user.ts
const UserSchema = z.object({ ... });
// UserSchema expects to have fixture file `__fixtures__/api/user.json`
SchemaRegistry.register('api/user', UserSchema, { name: 'UserSchema'});Create a test file that will run the tests, for example schemas.spec.ts.
// schemas.spec.ts
import { createSchemaTests } from '@cdwr/core/testing';
// Run tests for all registered schemas in the `schemas` directory
createSchemaTests({
schemaDir: join(__dirname, 'schemas'),
description: 'Schema validation',
snapshots: true
});Test rules
!IMPORTANT Dangling fixtures without a matching schema will be reported as failures, hence tests will fail.
Schemas without a fixture will be skipped and reported as warnings, hence tests will pass.
Options
!NOTE Fixtures are expected to be in the same directory as the
schemaDir, named__fixtures__. This can be overridden by providing thefixtureDiroption.When snapshots are enabled, the output will follow how your test runner is configured. For example, if you are using
jestorvitest, the snapshots will be saved in the__snapshots__directory.
Utils
import { ... } from '@cdwr/core/utils';A set of utility functions for common tasks.
Zod
import { withCamelCase, ... } from '@cdwr/core/zod';A set of Zod schemas and opininated transformers.
withCamelCase
Transform data properties from PascalCase or snake_case to camelCase.
// target.schema.ts
const ServiceSchema = z.object({
id: z.string(),
apiKey: z.string(),
userId: z.string(),
machines: z.array(
z.object({
config: z.object({
env: z.record(z.string())
})
})
),
machineToken: z.string()
});
// Expected API response
const apiResponse = {
ID: 'random',
APIKey: 'qwerty',
UserID: '123',
Machines: [
{
config: {
env: { NODE_ENV: 'test', IS_CI: 'true' }
}
}
],
machine_token: 'abc123'
};Default transformation generates output where we might see some unintended changes to the data.
withCamelCase(ServiceSchema).parse(apiResponse);
// {
// id: 'random',
// aPIKey: 'qwerty',
// userId: '123',
// machines: [{
// config: {
// env: { nodeEnv: 'test', isCi: 'true' }
// }
// }],
// machineToken: 'abc123'
// }For example, the APIKey property is transformed to aPIKey and environment variables are treated as normal JSON keys.
preserve- apply dot notation paths to keep certain path values to the original casing.specialCases- add mappings between the original keys and the target keys.
withCamelCase(ServiceSchema, {
preserve: ['machines.config.env'],
specialCases: { APIKey: 'apiKey' }
}).parse(apiResponse);
// {
// id: 'random',
// apiKey: 'qwerty',
// userId: '123',
// machines: [{
// config: {
// env: { NODE_ENV: 'test', IS_CI: 'true' }
// }
// }],
// machineToken: 'abc123'
// }!IMPORTANT These issues are the only ones that can be resolved by providing custom transformation rules.
This transformer has no intention to do more than just the necessary to comply to Fly.io naming conventions.