zod-openapi 5.0.0 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -51,6 +51,58 @@ z.string().meta({
51
51
  });
52
52
  ```
53
53
 
54
+ You can set additional metadata to the rendered schema in a few different ways. Zod's `.meta()` method allows you to directly set OpenAPI directly to the schema. However, if you wanted to override any field that Zod generates, this may not work as expected. In this case, you can use the `override` option to customize the rendered OpenAPI schema.
55
+
56
+ eg.
57
+
58
+ ```typescript
59
+ z.string().datetime().meta({
60
+ description: 'A date field',
61
+ format: 'MY-FORMAT',
62
+ 'x-custom-field': 'custom value',
63
+ });
64
+ ```
65
+
66
+ Would render the following OpenAPI schema. Note that format is not overridden with our custom format value.
67
+
68
+ ```json
69
+ {
70
+ "type": "string",
71
+ "format": "date-time",
72
+ "description": "A date field",
73
+ "x-custom-field": "custom value"
74
+ }
75
+ ```
76
+
77
+ In order to override fields which are generated by Zod or this library, you can use the `override` option in the `.meta()` method. This allows you to customize the rendered OpenAPI schema after we have both processed it.
78
+
79
+ ##### override object
80
+
81
+ This does a naive merge of the override object with the rendered OpenAPI schema. This is useful for simple overrides where you want to add or modify properties without complex logic.
82
+
83
+ ```typescript
84
+ z.string.datetime().meta({
85
+ description: 'A date field',
86
+ override: {
87
+ format: 'MY-FORMAT',
88
+ },
89
+ });
90
+ ```
91
+
92
+ ##### override function
93
+
94
+ The `override` function allows you to deeply customize the rendered OpenAPI schema. Eg. if you wanted to render a Zod union as a `oneOf` instead of `anyOf` for a single schema, you can do so by using the `override` function. View the documentation for `override` in the [CreateDocumentOptions](#createdocumentoptions) section for more information.
95
+
96
+ ```typescript
97
+ z.union([z.string(), z.number()]).meta({
98
+ description: 'A union of string and number',
99
+ override: ({ jsonSchema }) => {
100
+ jsonSchema.anyOf = jsonSchema.oneOf;
101
+ delete jsonSchema.oneOf;
102
+ },
103
+ });
104
+ ```
105
+
54
106
  ### `createDocument`
55
107
 
56
108
  Generates an OpenAPI documentation object.
@@ -183,25 +235,89 @@ const document = createDocument({
183
235
  ```typescript
184
236
  createDocument(doc, {
185
237
  override: ({ jsonSchema, zodSchema, io }) => {
186
- // Customize the schema generation
187
- if (io === 'output') {
238
+ const def = zodSchema._zod.def;
239
+ if (def.type === 'date' && io === 'output') {
188
240
  jsonSchema.type = 'string';
241
+ jsonSchema.format = 'date-time';
189
242
  }
190
243
  },
244
+ allowEmptySchema: {
245
+ custom: true,
246
+ },
191
247
  });
192
248
  ```
193
249
 
194
250
  #### CreateDocumentOptions
195
251
 
196
- | Option | Type | Default | Description |
197
- | ------------------ | ------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------- |
198
- | `override` | `Function` | `undefined` | Override rendered schema with a function`` |
199
- | `outputIdSuffix` | `string` | `'Output'` | Suffix for output schema IDs when the schema is used in both a request and response |
200
- | `allowEmptySchema` | `Object` | `undefined` | Control whether empty schemas are allowed. |
201
- | `cycles` | `'ref' \| 'throw'` | `'ref'` | How to handle cycles in schemas.<br>- `'ref'` — Break cycles using $defs<br>- `'throw'` — Error on cycles |
202
- | `reused` | `'ref' \| 'inline'` | `'inline'` | How to handle reused schemas.<br>- `'ref'` — Reused schemas as references<br>- `'inline'` — Inline reused schemas |
252
+ | Option | Type | Description |
253
+ | ------------------ | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
254
+ | `override` | `Function` | Override rendered schema with a function`` |
255
+ | `outputIdSuffix` | `string` | Suffix for output schema IDs when the schema is used in both a request and response. Defaults to ``'Output'` |
256
+ | `allowEmptySchema` | `Object` | Control whether empty schemas are allowed for specific Zod schema types |
257
+ | `cycles` | `'ref' \| 'throw'` | How to handle cycles in schemas.<br>- `'ref'` — Break cycles using $defs<br>- `'throw'` — Error on cycles. Defaults to `'ref'` |
258
+ | `reused` | `'ref' \| 'inline'` | How to handle reused schemas.<br>- `'ref'` — Reused schemas as references<br>- `'inline'` — Inline reused schemas. Defaults to `'inline'` |
203
259
  | |
204
260
 
261
+ ##### `override`
262
+
263
+ The `override` function allows you to customize the rendered OpenAPI schema. It receives an object with the following properties:
264
+
265
+ | Property | Type | Description |
266
+ | ------------ | --------------------- | ----------------------------------------------------------------------------------------------------------------- |
267
+ | `jsonSchema` | `Object` | The OpenAPI schema object being generated. You can modify this object to change the rendered schema. |
268
+ | `zodSchema` | `ZodType` | The original Zod schema being converted to OpenAPI. You can use this to access Zod-specific properties. |
269
+ | `io` | `'input' \| 'output'` | The context in which the schema is being rendered. `'input'` for request bodies/params, `'output'` for responses. |
270
+
271
+ This allows you to transform the schema based on your own rules or requirements. For example, if you
272
+
273
+ 1. Wanted to change how dates are rendered in the output context because a typical JSON serializer will transform them to a string
274
+ 2. Change all union outputs to be oneOf instead of anyOf
275
+
276
+ ```typescript
277
+ createDocument(doc, {
278
+ override: ({ jsonSchema, zodSchema, io }) => {
279
+ const def = zodSchema._zod.def;
280
+ if (def.type === 'date' && io === 'output') {
281
+ jsonSchema.type = 'string';
282
+ jsonSchema.format = 'date-time';
283
+ return;
284
+ }
285
+ if (def.type === 'union') {
286
+ jsonSchema.oneOf = jsonSchema.anyOf;
287
+ delete jsonSchema.anyOf;
288
+ return;
289
+ }
290
+ },
291
+ });
292
+ ```
293
+
294
+ ##### `outputIdSuffix`
295
+
296
+ The `outputIdSuffix` option allows you to set a suffix for output schema IDs when the schema is used in both a request and response context. This is useful for distinguishing between input and output schemas.
297
+
298
+ ##### `allowEmptySchema`
299
+
300
+ The `allowEmptySchema` option allows you to control whether or not this library will throw when it encounters an empty schema. By default this library will not throw if it encounters an `z.any()` or `z.unknown()` schema.
301
+
302
+ This allows you to customize how this library handles [unrepresentable](https://zod.dev/json-schema?id=unrepresentable) Zod schemas.
303
+
304
+ eg. If you wanted to allow `z.custom()` to be rendered as an empty schema, you can set the `allowEmptySchema` option as follows:
305
+
306
+ ```typescript
307
+ createDocument(doc, {
308
+ allowEmptySchema: {
309
+ custom: true, // Allow empty schemas for `z.custom()` in all contexts
310
+ set: { output: true }, // Allow empty schemas for `z.set()` only in an output context
311
+ },
312
+ });
313
+ ```
314
+
315
+ ##### `cycles` and `reused`
316
+
317
+ These options are exposed directly from the Zod. Read the [documentation](https://zod.dev/json-schema?id=unrepresentable#cycles) for more information on how to use these options.
318
+
319
+ #####
320
+
205
321
  ### `createSchema`
206
322
 
207
323
  Creates an OpenAPI Schema Object along with any registered components. OpenAPI 3.1.0 Schema Objects are fully compatible with JSON Schema.
@@ -895,21 +1011,3 @@ pnpm format
895
1011
  # Check for issues
896
1012
  pnpm lint
897
1013
  ```
898
-
899
- ### Release
900
-
901
- To release a new version
902
-
903
- 1. Create a [new GitHub Release](https://github.com/samchungy/zod-openapi/releases/new)
904
- 2. Select `🏷️ Choose a tag`, enter a version number. eg. `v1.2.0` and click `+ Create new tag: vX.X.X on publish`.
905
- 3. Click the `Generate release notes` button and adjust the description.
906
- 4. Tick the `Set as the latest release` box and click `Publish release`. This will trigger the `Release` workflow.
907
- 5. Check the `Pull Requests` tab for a PR labelled `Release vX.X.X`.
908
- 6. Click `Merge Pull Request` on that Pull Request to update master with the new package version.
909
-
910
- To release a new beta version
911
-
912
- 1. Create a [new GitHub Release](https://github.com/samchungy/zod-openapi/releases/new)
913
- 2. Select `🏷️ Choose a tag`, enter a version number with a `-beta.X` suffix eg. `v1.2.0-beta.1` and click `+ Create new tag: vX.X.X-beta.X on publish`.
914
- 3. Click the `Generate release notes` button and adjust the description.
915
- 4. Tick the `Set as a pre-release` box and click `Publish release`. This will trigger the `Prerelease` workflow.
package/dist/api.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { ComponentRegistry, Override, ZodOpenApiBaseMetadata, ZodOpenApiMetadata, createComponents, createRegistry } from "./components-Dus8apcN.mjs";
1
+ import { ComponentRegistry, Override, ZodOpenApiBaseMetadata, ZodOpenApiMetadata, createComponents, createRegistry } from "./components-CCPXuBcU.mjs";
2
2
  import { $ZodObject, $ZodType, $ZodTypes } from "zod/v4/core";
3
3
  import { core } from "zod/v4";
4
4
 
package/dist/api.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ComponentRegistry, Override, ZodOpenApiBaseMetadata, ZodOpenApiMetadata, createComponents, createRegistry } from "./components-T2U31sZh.js";
1
+ import { ComponentRegistry, Override, ZodOpenApiBaseMetadata, ZodOpenApiMetadata, createComponents, createRegistry } from "./components-D8Br4Oqx.js";
2
2
  import { $ZodObject, $ZodType, $ZodTypes } from "zod/v4/core";
3
3
  import { core } from "zod/v4";
4
4
 
package/dist/api.js CHANGED
@@ -1,4 +1,4 @@
1
- const require_components = require('./components-BRLB21IO.js');
1
+ const require_components = require('./components-DpACv95L.js');
2
2
 
3
3
  exports.createComponents = require_components.createComponents;
4
4
  exports.createRegistry = require_components.createRegistry;
package/dist/api.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { createComponents, createRegistry, isAnyZodType, unwrapZodObject } from "./components-DuIz-WUQ.mjs";
1
+ import { createComponents, createRegistry, isAnyZodType, unwrapZodObject } from "./components-CUMu4QeI.mjs";
2
2
 
3
3
  export { createComponents, createRegistry, isAnyZodType, unwrapZodObject };
@@ -366,6 +366,10 @@ interface ZodOpenApiBaseMetadata {
366
366
  }
367
367
  interface ZodOpenApiMetadata extends ZodOpenApiBaseMetadata, core.JSONSchemaMeta {
368
368
  examples?: unknown[];
369
+ /**
370
+ * @deprecated - Use `examples` instead.
371
+ * Use of `example` is discouraged, and later versions of OpenAPI specification may remove it.
372
+ */
369
373
  example?: unknown;
370
374
  }
371
375
  declare module 'zod/v4' {
@@ -27,7 +27,7 @@ const createMediaTypeObject = (mediaType, ctx, path) => {
27
27
  source: { type: "mediaType" }
28
28
  });
29
29
  mediaTypeObject.schema = schemaObject;
30
- }
30
+ } else mediaTypeObject.schema = schema;
31
31
  if (examples) mediaTypeObject.examples = createExamples(examples, ctx.registry, [...path, "examples"]);
32
32
  return mediaTypeObject;
33
33
  };
@@ -366,6 +366,10 @@ interface ZodOpenApiBaseMetadata {
366
366
  }
367
367
  interface ZodOpenApiMetadata extends ZodOpenApiBaseMetadata, core.JSONSchemaMeta {
368
368
  examples?: unknown[];
369
+ /**
370
+ * @deprecated - Use `examples` instead.
371
+ * Use of `example` is discouraged, and later versions of OpenAPI specification may remove it.
372
+ */
369
373
  example?: unknown;
370
374
  }
371
375
  declare module 'zod/v4' {
@@ -50,7 +50,7 @@ const createMediaTypeObject = (mediaType, ctx, path) => {
50
50
  source: { type: "mediaType" }
51
51
  });
52
52
  mediaTypeObject.schema = schemaObject;
53
- }
53
+ } else mediaTypeObject.schema = schema;
54
54
  if (examples) mediaTypeObject.examples = createExamples(examples, ctx.registry, [...path, "examples"]);
55
55
  return mediaTypeObject;
56
56
  };
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { BaseParameterObject, CallbackObject, CallbacksObject, ComponentRegistry, ComponentsObject, ContactObject, ContentObject, CreateDocumentOptions, DiscriminatorObject, EncodingObject, EncodingPropertyObject, ExampleObject, ExamplesObject, ExternalDocumentationObject, HeaderObject, HeadersObject, IExtensionName, IExtensionType, ISpecificationExtension, InfoObject, LicenseObject, LinkObject, LinkParametersObject, LinksObject, MediaTypeObject, OAuthFlowObject, OAuthFlowsObject, OpenAPIObject, OperationObject, Override, ParameterLocation, ParameterObject, ParameterStyle, PathItemObject, PathObject, PathsObject, ReferenceObject, RequestBodyObject, ResponseObject, ResponsesObject, SchemaObject, SchemaObjectType, SchemasObject, ScopesObject, SecurityRequirementObject, SecuritySchemeObject, SecuritySchemeType, ServerObject, ServerVariableObject, TagObject, XmlObject, ZodObjectInput, ZodOpenApiBaseMetadata, ZodOpenApiCallbackObject, ZodOpenApiCallbacksObject, ZodOpenApiComponentsObject, ZodOpenApiContentObject, ZodOpenApiExampleObject, ZodOpenApiExamplesObject, ZodOpenApiHeaderObject, ZodOpenApiHeadersObject, ZodOpenApiLinkObject, ZodOpenApiLinksObject, ZodOpenApiMediaTypeObject, ZodOpenApiMetadata, ZodOpenApiObject, ZodOpenApiOperationObject, ZodOpenApiParameterObject, ZodOpenApiParameters, ZodOpenApiPathItemObject, ZodOpenApiPathsObject, ZodOpenApiRequestBodyObject, ZodOpenApiResponseObject, ZodOpenApiResponsesObject, ZodOpenApiSchemaObject, ZodOpenApiSecuritySchemeObject, ZodOpenApiVersion, createDocument } from "./components-Dus8apcN.mjs";
1
+ import { BaseParameterObject, CallbackObject, CallbacksObject, ComponentRegistry, ComponentsObject, ContactObject, ContentObject, CreateDocumentOptions, DiscriminatorObject, EncodingObject, EncodingPropertyObject, ExampleObject, ExamplesObject, ExternalDocumentationObject, HeaderObject, HeadersObject, IExtensionName, IExtensionType, ISpecificationExtension, InfoObject, LicenseObject, LinkObject, LinkParametersObject, LinksObject, MediaTypeObject, OAuthFlowObject, OAuthFlowsObject, OpenAPIObject, OperationObject, Override, ParameterLocation, ParameterObject, ParameterStyle, PathItemObject, PathObject, PathsObject, ReferenceObject, RequestBodyObject, ResponseObject, ResponsesObject, SchemaObject, SchemaObjectType, SchemasObject, ScopesObject, SecurityRequirementObject, SecuritySchemeObject, SecuritySchemeType, ServerObject, ServerVariableObject, TagObject, XmlObject, ZodObjectInput, ZodOpenApiBaseMetadata, ZodOpenApiCallbackObject, ZodOpenApiCallbacksObject, ZodOpenApiComponentsObject, ZodOpenApiContentObject, ZodOpenApiExampleObject, ZodOpenApiExamplesObject, ZodOpenApiHeaderObject, ZodOpenApiHeadersObject, ZodOpenApiLinkObject, ZodOpenApiLinksObject, ZodOpenApiMediaTypeObject, ZodOpenApiMetadata, ZodOpenApiObject, ZodOpenApiOperationObject, ZodOpenApiParameterObject, ZodOpenApiParameters, ZodOpenApiPathItemObject, ZodOpenApiPathsObject, ZodOpenApiRequestBodyObject, ZodOpenApiResponseObject, ZodOpenApiResponsesObject, ZodOpenApiSchemaObject, ZodOpenApiSecuritySchemeObject, ZodOpenApiVersion, createDocument } from "./components-CCPXuBcU.mjs";
2
2
  import { core } from "zod/v4";
3
3
 
4
4
  //#region rolldown:runtime
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { BaseParameterObject, CallbackObject, CallbacksObject, ComponentRegistry, ComponentsObject, ContactObject, ContentObject, CreateDocumentOptions, DiscriminatorObject, EncodingObject, EncodingPropertyObject, ExampleObject, ExamplesObject, ExternalDocumentationObject, HeaderObject, HeadersObject, IExtensionName, IExtensionType, ISpecificationExtension, InfoObject, LicenseObject, LinkObject, LinkParametersObject, LinksObject, MediaTypeObject, OAuthFlowObject, OAuthFlowsObject, OpenAPIObject, OperationObject, Override, ParameterLocation, ParameterObject, ParameterStyle, PathItemObject, PathObject, PathsObject, ReferenceObject, RequestBodyObject, ResponseObject, ResponsesObject, SchemaObject, SchemaObjectType, SchemasObject, ScopesObject, SecurityRequirementObject, SecuritySchemeObject, SecuritySchemeType, ServerObject, ServerVariableObject, TagObject, XmlObject, ZodObjectInput, ZodOpenApiBaseMetadata, ZodOpenApiCallbackObject, ZodOpenApiCallbacksObject, ZodOpenApiComponentsObject, ZodOpenApiContentObject, ZodOpenApiExampleObject, ZodOpenApiExamplesObject, ZodOpenApiHeaderObject, ZodOpenApiHeadersObject, ZodOpenApiLinkObject, ZodOpenApiLinksObject, ZodOpenApiMediaTypeObject, ZodOpenApiMetadata, ZodOpenApiObject, ZodOpenApiOperationObject, ZodOpenApiParameterObject, ZodOpenApiParameters, ZodOpenApiPathItemObject, ZodOpenApiPathsObject, ZodOpenApiRequestBodyObject, ZodOpenApiResponseObject, ZodOpenApiResponsesObject, ZodOpenApiSchemaObject, ZodOpenApiSecuritySchemeObject, ZodOpenApiVersion, createDocument } from "./components-T2U31sZh.js";
1
+ import { BaseParameterObject, CallbackObject, CallbacksObject, ComponentRegistry, ComponentsObject, ContactObject, ContentObject, CreateDocumentOptions, DiscriminatorObject, EncodingObject, EncodingPropertyObject, ExampleObject, ExamplesObject, ExternalDocumentationObject, HeaderObject, HeadersObject, IExtensionName, IExtensionType, ISpecificationExtension, InfoObject, LicenseObject, LinkObject, LinkParametersObject, LinksObject, MediaTypeObject, OAuthFlowObject, OAuthFlowsObject, OpenAPIObject, OperationObject, Override, ParameterLocation, ParameterObject, ParameterStyle, PathItemObject, PathObject, PathsObject, ReferenceObject, RequestBodyObject, ResponseObject, ResponsesObject, SchemaObject, SchemaObjectType, SchemasObject, ScopesObject, SecurityRequirementObject, SecuritySchemeObject, SecuritySchemeType, ServerObject, ServerVariableObject, TagObject, XmlObject, ZodObjectInput, ZodOpenApiBaseMetadata, ZodOpenApiCallbackObject, ZodOpenApiCallbacksObject, ZodOpenApiComponentsObject, ZodOpenApiContentObject, ZodOpenApiExampleObject, ZodOpenApiExamplesObject, ZodOpenApiHeaderObject, ZodOpenApiHeadersObject, ZodOpenApiLinkObject, ZodOpenApiLinksObject, ZodOpenApiMediaTypeObject, ZodOpenApiMetadata, ZodOpenApiObject, ZodOpenApiOperationObject, ZodOpenApiParameterObject, ZodOpenApiParameters, ZodOpenApiPathItemObject, ZodOpenApiPathsObject, ZodOpenApiRequestBodyObject, ZodOpenApiResponseObject, ZodOpenApiResponsesObject, ZodOpenApiSchemaObject, ZodOpenApiSecuritySchemeObject, ZodOpenApiVersion, createDocument } from "./components-D8Br4Oqx.js";
2
2
  import { core } from "zod/v4";
3
3
 
4
4
  //#region rolldown:runtime
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- const require_components = require('./components-BRLB21IO.js');
1
+ const require_components = require('./components-DpACv95L.js');
2
2
 
3
3
  //#region src/create/document.ts
4
4
  const createDocument = (zodOpenApiObject, opts = {}) => {
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { createComponents, createPaths, createRegistry, createSchema } from "./components-DuIz-WUQ.mjs";
1
+ import { createComponents, createPaths, createRegistry, createSchema } from "./components-CUMu4QeI.mjs";
2
2
 
3
3
  //#region src/create/document.ts
4
4
  const createDocument = (zodOpenApiObject, opts = {}) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zod-openapi",
3
- "version": "5.0.0",
3
+ "version": "5.0.1",
4
4
  "description": "Convert Zod Schemas to OpenAPI v3.x documentation",
5
5
  "keywords": [
6
6
  "typescript",
@@ -19,6 +19,7 @@
19
19
  "type": "git",
20
20
  "url": "git+ssh://git@github.com/samchungy/zod-openapi.git"
21
21
  },
22
+ "funding": "https://github.com/samchungy/zod-openapi?sponsor=1",
22
23
  "license": "MIT",
23
24
  "sideEffects": false,
24
25
  "exports": {
@@ -39,20 +40,10 @@
39
40
  "dist",
40
41
  "api"
41
42
  ],
42
- "scripts": {
43
- "build": "pnpm copy:types && tsdown",
44
- "copy:types": "skuba node scripts/copyTypes.ts",
45
- "create:docs": " skuba node examples/simple/createSchema.ts && redocly build-docs examples/simple/openapi.yml --output=examples/simple/redoc-static.html",
46
- "format": "skuba format",
47
- "lint": "skuba lint",
48
- "prepare": "pnpm build",
49
- "test": "skuba test",
50
- "test:ci": "skuba test --coverage",
51
- "test:watch": "skuba test --watch"
52
- },
53
43
  "devDependencies": {
54
- "@arethetypeswrong/cli": "0.18.1",
55
- "@redocly/cli": "1.34.3",
44
+ "@arethetypeswrong/cli": "0.18.2",
45
+ "@changesets/cli": "2.29.5",
46
+ "@redocly/cli": "1.34.4",
56
47
  "@types/node": "22.15.21",
57
48
  "ajv": "8.17.1",
58
49
  "eslint-plugin-import-zod": "1.0.3",
@@ -66,7 +57,6 @@
66
57
  "peerDependencies": {
67
58
  "zod": "^3.25.74"
68
59
  },
69
- "packageManager": "pnpm@10.11.0",
70
60
  "engines": {
71
61
  "node": ">=20"
72
62
  },
@@ -79,5 +69,16 @@
79
69
  "template": "oss-npm-package",
80
70
  "type": "package",
81
71
  "version": "11.0.0"
72
+ },
73
+ "scripts": {
74
+ "build": "pnpm copy:types && tsdown",
75
+ "copy:types": "skuba node scripts/copyTypes.ts",
76
+ "create:docs": " skuba node examples/simple/createSchema.ts && redocly build-docs examples/simple/openapi.yml --output=examples/simple/redoc-static.html",
77
+ "format": "skuba format",
78
+ "lint": "skuba lint",
79
+ "release": "pnpm build && changeset publish",
80
+ "test": "skuba test",
81
+ "test:ci": "skuba test --coverage",
82
+ "test:watch": "skuba test --watch"
82
83
  }
83
- }
84
+ }