diff --git a/README.md b/README.md index 2c6173a3..7aeb84ed 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ # Core Features - 📃 From your [AsyncAPI v2 and v3](https://the-codegen-project.org/docs/inputs/asyncapi) documents, generate [payloads](https://the-codegen-project.org/docs/generators/payloads), [headers](https://the-codegen-project.org/docs/generators/headers), [parameters](https://the-codegen-project.org/docs/generators/parameters), [protocol helpers](https://the-codegen-project.org/docs/generators/channels), [full clients](https://the-codegen-project.org/docs/generators/client), [models](https://the-codegen-project.org/docs/generators/models), [simple types](https://the-codegen-project.org/docs/generators/types), or all of the above. -- 📃 From your [Swagger 2.0, or OpenAPI 3.0, and 3.1](https://the-codegen-project.org/docs/inputs/openapi) documents, generate [payloads](https://the-codegen-project.org/docs/generators/payloads), [headers](https://the-codegen-project.org/docs/generators/headers), [parameters](https://the-codegen-project.org/docs/generators/parameters), [models](https://the-codegen-project.org/docs/generators/models), [simple types](https://the-codegen-project.org/docs/generators/types), or all of the above. +- 📃 From your [Swagger 2.0, or OpenAPI 3.0, and 3.1](https://the-codegen-project.org/docs/inputs/openapi) documents, generate [payloads](https://the-codegen-project.org/docs/generators/payloads), [headers](https://the-codegen-project.org/docs/generators/headers), [parameters](https://the-codegen-project.org/docs/generators/parameters), [protocol helpers](https://the-codegen-project.org/docs/generators/channels), [full clients](https://the-codegen-project.org/docs/generators/client), [models](https://the-codegen-project.org/docs/generators/models), [simple types](https://the-codegen-project.org/docs/generators/types), or all of the above. - 📃 From your [JSON Schema Draft-4, Draft-6 and Draft-7](https://the-codegen-project.org/docs/inputs/jsonschema) schemas, generate [models](https://the-codegen-project.org/docs/generators/models) or [completely customize it](https://the-codegen-project.org/docs/generators/custom). - 📊 Every generator fully customizable to fit your hearts desire - 👀 Integrate it into any project (Demos in [Next.JS](./examples/typescript-nextjs), [TypeScript Libraries](./examples/typescript-library)) diff --git a/docs/generators/channels.md b/docs/generators/channels.md index e276f671..a1608eaf 100644 --- a/docs/generators/channels.md +++ b/docs/generators/channels.md @@ -18,11 +18,11 @@ export default { }; ``` -`channels` preset with `asyncapi` input generates support functions for each operation based on the selected protocol. +`channels` preset generates support functions for each operation based on the selected protocol. This generator uses [`payloads`](./payloads.md), [`headers`](./headers.md) and [`parameters`](./parameters.md) generators, in case you dont have any defined, it will automatically include them with default values. -This is supported through the following inputs: [`asyncapi`](../inputs/asyncapi.md) +This is supported through the following inputs: [`asyncapi`](../inputs/asyncapi.md), [`openapi`](../inputs/openapi.md) It supports the following languages; [`typescript`](#typescript) @@ -43,6 +43,7 @@ These are the available options for the `channels` generator; ## TypeScript Regardless of protocol, these are the dependencies: - If validation enabled, [ajv](https://ajv.js.org/guide/getting-started.html): ^8.17.1 +- If validation enabled, [ajv-formats](https://github.com/ajv-validator/ajv-formats): ^3.0.1 Depending on which protocol, these are the dependencies: - `NATS`: https://github.com/nats-io/nats.js v2 diff --git a/docs/generators/client.md b/docs/generators/client.md index 48bb78c0..65ad8406 100644 --- a/docs/generators/client.md +++ b/docs/generators/client.md @@ -53,8 +53,7 @@ export {Payload}; import {Parameters} from './parameters/Parameters'; //Import channel functions -import { Protocols } from './channels/index'; -const { nats } = Protocols; +import { nats } from './channels/index'; import * as Nats from 'nats'; @@ -96,15 +95,22 @@ export class NatsClient { /** * Try to connect to the NATS server with the different payloads. */ - connect(options: Nats.ConnectionOptions, codec?: Nats.Codec): Promise { + connect( + options: Nats.ConnectionOptions, + codec?: Nats.Codec + ): Promise<{nc: Nats.NatsConnection, js: Nats.JetStreamClient}> { ... } - - public async jetStreamPublishToChannel( - message: Payload, - parameters: Parameters, - options: Partial = {} - ): Promise { + + public async jetStreamPublishToChannel({ + message, + parameters, + options = {} + }: { + message: PayloadInterface | Payload, + parameters: Parameters, + options?: Partial + }): Promise { ... } jetStreamPullSubscribeToChannel diff --git a/docs/generators/custom.md b/docs/generators/custom.md index 30fc77d1..dd9985a1 100644 --- a/docs/generators/custom.md +++ b/docs/generators/custom.md @@ -18,8 +18,7 @@ export default { { preset: 'custom', ... - renderFunction: ({generator, inputType, asyncapiDocument, openapiDocument, dependencyOutputs}) - { + renderFunction: ({generator, inputType, asyncapiDocument, openapiDocument, jsonSchemaDocument, dependencyOutputs}) => { const modelinaGenerator = new JavaFileGenerator({}); modelinaGenerator.generateCompleteModels(...) } @@ -71,4 +70,5 @@ In the `renderFunction` you have access to a bunch of arguments to help you crea - `inputType` - is the root `inputType` for the input document - `asyncapiDocument` - is the parsed AsyncAPI document input (according to the [AsyncAPI parser](https://github.com/asyncapi/parser-js/)), undefined if the `inputType` is not `asyncapi` - `openapiDocument` - is the parsed OpenAPI document input (according to the [readme/openapi-parser](https://github.com/readmeio/oas)), undefined if the `inputType` is not `openapi` +- `jsonSchemaDocument` - is the parsed JSON Schema document input, undefined if the `inputType` is not `jsonschema` - `dependencyOutputs` - if you have defined any `dependencies`, this is where you can access the output. Checkout the [dependency documentation](#dependencies) for more information. \ No newline at end of file diff --git a/docs/generators/headers.md b/docs/generators/headers.md index 0a9a9aa1..1a78a179 100644 --- a/docs/generators/headers.md +++ b/docs/generators/headers.md @@ -37,9 +37,21 @@ The `headers` preset with `openapi` input generates all the headers for each pat The return type is a map of paths and the model that represent the headers. +## Options +These are the available options for the `headers` generator; + +| **Option** | Default | Type | Description | +|---|---|---|---| +| id | `'headers-typescript'` | String | Unique identifier for this generator instance. The `channels`/`client` generators reference it as their `headerGeneratorId`. | +| dependencies | `[]` | String[] | IDs of other generators that must run before this one. | +| outputPath | `'src/__gen__/headers'` | String | Directory the generated header models are written to. | +| serializationType | `'json'` | `'json'` | Serialization format used by the generated models. Only `json` is supported. | +| includeValidation | `true` | Boolean | Include the built-in JSON Schema `validate`/`createValidator` methods. Requires `ajv` and `ajv-formats` (see [Dependencies](#typescript)). | + ## Typescript Dependencies: - If validation enabled, [ajv](https://ajv.js.org/guide/getting-started.html): ^8.17.1 +- If validation enabled, [ajv-formats](https://github.com/ajv-validator/ajv-formats): ^3.0.1 ### Validation Each generated class includes built-in JSON Schema validation capabilities through two static methods: diff --git a/docs/generators/models.md b/docs/generators/models.md index 8092ba33..223f7bdd 100644 --- a/docs/generators/models.md +++ b/docs/generators/models.md @@ -213,10 +213,11 @@ The TypeScript implementation provides full access to Modelina's TypeScript gene |--------|------|---------|-------------| | `modelType` | `'class' \| 'interface'` | `'class'` | Type of models to generate | | `enumType` | `'enum' \| 'union'` | `'enum'` | How to render enum types | -| `mapType` | `'indexedObject' \| 'record'` | `'record'` | How to render map/dictionary types | +| `mapType` | `'indexedObject' \| 'map' \| 'record'` | `'map'` | How to render map/dictionary types | | `moduleSystem` | `'CJS' \| 'ESM'` | `'ESM'` | Module system to use | | `rawPropertyNames` | `boolean` | `false` | Use raw property names without transformation | | `useJavascriptReservedKeywords` | `boolean` | `true` | Allow JavaScript reserved keywords | +| `isolatedModules` | `boolean` | `false` | Emit `export type` / `import type` for type-only models. Required for projects using TypeScript's `isolatedModules` (Next.js, SWC, esbuild) | **Common Presets**: diff --git a/docs/generators/payloads.md b/docs/generators/payloads.md index 9ab2375b..7685cbee 100644 --- a/docs/generators/payloads.md +++ b/docs/generators/payloads.md @@ -56,6 +56,23 @@ free-function marshalling — they have no companion interface and are exported a single symbol. See the [protocols documentation](../protocols) for how each channel accepts payloads. +## Options +These are the available options for the `payloads` generator; + +| **Option** | Default | Type | Description | +|---|---|---|---| +| id | `'payloads-typescript'` | String | Unique identifier for this generator instance. Other generators reference it as a dependency, and the `channels`/`client` generators use it as their `payloadGeneratorId`. | +| dependencies | `[]` | String[] | IDs of other generators that must run before this one. | +| outputPath | `'src/__gen__/payloads'` | String | Directory the generated payload models are written to. | +| serializationType | `'json'` | `'json'` | Serialization format used by the generated models. Only `json` is supported. | +| enum | `'enum'` | `'enum' \| 'union'` | Render enums as TypeScript `enum`s, or as string/number union types. | +| map | `'record'` | `'indexedObject' \| 'map' \| 'record'` | Render dictionary/map types as `Record`, the `Map` class, or an index signature. | +| useForJavaScript | `true` | Boolean | Apply JavaScript restrictions so the models stay valid when transpiled to JavaScript (for example avoiding reserved keywords as identifiers). | +| includeValidation | `true` | Boolean | Include the built-in JSON Schema `validate`/`createValidator` methods. Requires `ajv` and `ajv-formats` (see [Dependencies](#typescript)). | +| rawPropertyNames | `false` | Boolean | Keep the raw property names from the input schema. Consumers then access them with `obj["propertyName"]` instead of `obj.propertyName`. | + +The global [`importExtension`](../configurations.md#import-extensions-node16nodenextverbatimmodulesyntax) option also applies to the imports between generated payload models. + ## Languages Each language has a set of constraints which means that some typed model types are either supported or not, or it might just be the code generation library that does not yet support it. @@ -67,6 +84,12 @@ Each language has a set of constraints which means that some typed model types a Dependencies: - If validation enabled, [ajv](https://ajv.js.org/guide/getting-started.html): ^8.17.1 +- If validation enabled, [ajv-formats](https://github.com/ajv-validator/ajv-formats): ^3.0.1 + +> `ajv-formats` v3 follows RFC 3339 more strictly than v2 did. Most notably, +> `format: time` now requires a time offset, so `"10:30:00"` is rejected while +> `"10:30:00Z"` and `"10:30:00+02:00"` are accepted. Pin `ajv-formats@^2` if you +> need the previous, more lenient behaviour. #### Validation Each generated class includes built-in JSON Schema validation capabilities through two static methods: diff --git a/docs/getting-started/generators.md b/docs/getting-started/generators.md index cff7dec1..48e1b7df 100644 --- a/docs/getting-started/generators.md +++ b/docs/getting-started/generators.md @@ -36,7 +36,10 @@ Generators take your specifications (AsyncAPI, OpenAPI, or JSON Schema) and extr ```js export default { inputType: 'asyncapi', - inputPath: './my-api.yaml' + inputPath: './my-api.yaml', + generators: [ + { preset: 'payloads', outputPath: './src/__gen__/payloads' } + ] }; ``` @@ -65,27 +68,29 @@ Each generator produces different code, so have a look at each generator to get **Payload Generator** produces: ```typescript +// A companion interface is exported alongside the class, so you can construct +// a payload from a plain object. +export interface UserSignupInterface { /* ... */ } export class UserSignup { - constructor(data: UserSignupData) { /* ... */ } + constructor(input: UserSignupInterface) { /* ... */ } marshal(): string { /* ... */ } - static unmarshal(json: string): UserSignup { /* ... */ } + static unmarshal(json: string | object): UserSignup { /* ... */ } } ``` **Channels Generator** produces: ```typescript -export const Protocols = { - nats: { - publishToUserSignup: ..., - subscribeToUserSignup: ..., - jetStreamPublishToUserSignup: ... - }, - kafka: { - publishToUserSignup: ..., - subscribeToUserSignup: ... - }, - // ... other protocols -}; +// One module per protocol, re-exported from the generated barrel file +import * as nats from './nats'; +import * as kafka from './kafka'; + +export { nats, kafka }; + +// nats.publishToUserSignup({ message, nc }) +// nats.subscribeToUserSignup({ onDataCallback, nc }) +// nats.jetStreamPublishToUserSignup({ message, js }) +// kafka.produceToUserSignup({ message, kafka }) +// kafka.consumeFromUserSignup({ onDataCallback, kafka, options }) ``` ## Input Type Support diff --git a/docs/getting-started/protocols.md b/docs/getting-started/protocols.md index 544ea7a3..a879e6e2 100644 --- a/docs/getting-started/protocols.md +++ b/docs/getting-started/protocols.md @@ -50,20 +50,29 @@ export default { The `channels` generator creates protocol-specific functions for each channel in your AsyncAPI specification: -```typescript -import { Protocols } from './src/__gen__/index'; +Each protocol is exported as its own namespace from the generated barrel file, +and every generated function takes a single object argument: -const { nats, kafka } = Protocols; +```typescript +import { nats, kafka } from './src/__gen__/channels'; // NATS functions -await nats.publishToUserSignup(connection, message); -await nats.subscribeToUserSignup(connection, callback); - -// Kafka functions -await kafka.publishToUserSignup(producer, message); -await kafka.subscribeToUserSignup(consumer, callback); +await nats.publishToUserSignup({ message, nc: connection }); +await nats.subscribeToUserSignup({ onDataCallback: callback, nc: connection }); + +// Kafka functions — note Kafka uses produceTo/consumeFrom +await kafka.produceToUserSignup({ message, kafka: kafkaClient }); +await kafka.consumeFromUserSignup({ + onDataCallback: callback, + kafka: kafkaClient, + options: { fromBeginning: true, groupId: 'my-group' } +}); ``` +The exact parameters depend on the channel — channels with parameters also take +`parameters`, and channels with headers accept `headers`. See each protocol's +page for the full generated signatures. + Each protocol has unique features that are reflected in the generated code: **NATS** supports: diff --git a/docs/inputs/asyncapi.md b/docs/inputs/asyncapi.md index f8daf402..0008b37a 100644 --- a/docs/inputs/asyncapi.md +++ b/docs/inputs/asyncapi.md @@ -737,7 +737,7 @@ Generate AMQP producers and consumers for message queuing. } }, "x-the-codegen-project": { - "functionTypeMapping": ["amqp_publish"] + "functionTypeMapping": ["amqp_queue_publish"] } }, "consumeOrders": { @@ -756,7 +756,7 @@ Generate AMQP producers and consumers for message queuing. } }, "x-the-codegen-project": { - "functionTypeMapping": ["amqp_consume"] + "functionTypeMapping": ["amqp_queue_subscribe"] } } }, diff --git a/docs/migrations/v0.md b/docs/migrations/v0.md index 5e3a9895..17de6031 100644 --- a/docs/migrations/v0.md +++ b/docs/migrations/v0.md @@ -56,7 +56,7 @@ await jetStreamPublishToSendUserSignedup({ await publishToSendUserSignedup({ message, parameters, - connection + nc }); // Subscribing @@ -248,5 +248,6 @@ import * as NodeFetch from 'node-fetch'; + diff --git a/docs/protocols/amqp.md b/docs/protocols/amqp.md index ff6d6afa..b6ba1509 100644 --- a/docs/protocols/amqp.md +++ b/docs/protocols/amqp.md @@ -70,8 +70,7 @@ import * as Amqp from 'amqplib'; // Location depends on the payload generator configurations import { UserSignedup } from './__gen__/payloads/UserSignedup'; // Location depends on the channel generator configurations -import { Protocols } from './__gen__/channels'; -const { amqp } = Protocols; +import { amqp } from './__gen__/channels'; const { publishToPublishUserSignupsExchange, publishToPublishUserSignupsQueue, subscribeToConsumeUserSignupsQueue } = amqp; /** @@ -81,13 +80,20 @@ const client = await Amqp.connect('amqp://localhost'); const myPayload = new UserSignedup({displayName: 'test', email: 'test@test.dk'}); // Use exchange -await publishToPublishUserSignupsExchange(myPayload, client); +await publishToPublishUserSignupsExchange({ message: myPayload, amqp: client }); // Use queue -await publishToPublishUserSignupsQueue(myPayload, client); -await subscribeToConsumeUserSignupsQueue((message) => { - console.log(`Received message: ${message.displayName}, ${message.email}`); -}, client); +await publishToPublishUserSignupsQueue({ message: myPayload, amqp: client }); +await subscribeToConsumeUserSignupsQueue({ + onDataCallback: ({ err, msg, headers, amqpMsg }) => { + if (err) { + console.error('Error receiving message:', err); + return; + } + console.log(`Received message: ${msg?.displayName}, ${msg?.email}`); + }, + amqp: client +}); ``` diff --git a/docs/protocols/eventsource.md b/docs/protocols/eventsource.md index f86e7fcb..e0bc41e1 100644 --- a/docs/protocols/eventsource.md +++ b/docs/protocols/eventsource.md @@ -75,28 +75,31 @@ import express, { Router } from 'express' // Location depends on the payload generator configurations import { UserSignedup } from './__gen__/payloads/UserSignedup'; // Location depends on the channel generator configurations -import { Protocols } from './__gen__/channels'; -const { event_source_client } = Protocols; -const { listenForUserSignedup } = event_source_client; -const listenCallback = async ( - messageEvent: UserSignedUp | null, - parameters: UserSignedUpParameters | null, - error?: string -) => { - // Do stuff once you receive the event from the server -}; -listenForUserSignedup(listenCallback, {baseUrl: 'http://localhost:3000'}) +import { event_source } from './__gen__/channels'; +const { listenForUserSignedup, registerSendUserSignedup } = event_source; -// Use express to listen for clients registering for events +// The client-side listener takes an object callback +listenForUserSignedup({ + callback: ({ error, messageEvent }) => { + // Do stuff once you receive the event from the server + }, + options: { baseUrl: 'http://localhost:3000' } +}) + +// Use express to listen for clients registering for events. The Express +// handler keeps Express' own positional (req, res, next) convention. const router = Router() const app = express() app.use(express.json({ limit: '3000kb' })) app.use(express.urlencoded({ extended: true })) -registerSendUserSignedup(router, (req, res, next, parameters, sendEvent) => { - //Do stuff when client starts listening to the event. - //For example send a message to the client - const testMessage = new UserSignedup({displayName: 'test', email: 'test@test.dk'}); - sendEvent(testMessage); +registerSendUserSignedup({ + router, + callback: (req, res, next, parameters, sendEvent) => { + //Do stuff when client starts listening to the event. + //For example send a message to the client + const testMessage = new UserSignedup({displayName: 'test', email: 'test@test.dk'}); + sendEvent(testMessage); + } }) app.use(router) app.listen(3000) diff --git a/docs/protocols/http_client.md b/docs/protocols/http_client.md index 28e718cb..d5541281 100644 --- a/docs/protocols/http_client.md +++ b/docs/protocols/http_client.md @@ -101,18 +101,17 @@ components: ```ts // Location depends on the payload generator configurations -import { Ping } from './__gen__/payloads/Ping'; -import { Pong } from './__gen__/payloads/Pong'; +import { PingRequest } from './__gen__/payloads/PingRequest'; +import { PongResponse } from './__gen__/payloads/PongResponse'; // Location depends on the channel generator configurations -import { Protocols } from './__gen__/channels'; -const { http_client } = Protocols; -const { postPingPostRequest } = http_client; +import { http_client } from './__gen__/channels'; +const { postPostPing } = http_client; // Create a request payload -const pingMessage = new Ping({ message: 'Hello!' }); +const pingMessage = new PingRequest({ message: 'Hello!' }); // Make a simple request -const response = await postPingPostRequest({ +const response = await postPostPing({ payload: pingMessage, baseUrl: 'https://api.example.com' }); @@ -175,7 +174,7 @@ The HTTP client uses a discriminated union for authentication, providing excelle ### Bearer Token ```typescript -const response = await postPingPostRequest({ +const response = await postPostPing({ payload: message, baseUrl: 'https://api.example.com', auth: { @@ -188,7 +187,7 @@ const response = await postPingPostRequest({ ### Basic Authentication ```typescript -const response = await postPingPostRequest({ +const response = await postPostPing({ payload: message, baseUrl: 'https://api.example.com', auth: { @@ -203,7 +202,7 @@ const response = await postPingPostRequest({ ```typescript // API Key in header (default) -const response = await postPingPostRequest({ +const response = await postPostPing({ payload: message, baseUrl: 'https://api.example.com', auth: { @@ -215,7 +214,7 @@ const response = await postPingPostRequest({ }); // API Key in query parameter -const response = await postPingPostRequest({ +const response = await postPostPing({ payload: message, baseUrl: 'https://api.example.com', auth: { @@ -232,7 +231,7 @@ const response = await postPingPostRequest({ For server-to-server authentication: ```typescript -const response = await postPingPostRequest({ +const response = await postPostPing({ payload: message, baseUrl: 'https://api.example.com', auth: { @@ -255,7 +254,7 @@ const response = await postPingPostRequest({ For legacy applications requiring username/password: ```typescript -const response = await postPingPostRequest({ +const response = await postPostPing({ payload: message, baseUrl: 'https://api.example.com', auth: { @@ -281,7 +280,7 @@ For tokens obtained via browser-based flows (implicit, authorization code): // Token obtained from browser OAuth flow const accessToken = getTokenFromBrowserFlow(); -const response = await postPingPostRequest({ +const response = await postPostPing({ payload: message, baseUrl: 'https://api.example.com', auth: { @@ -303,7 +302,7 @@ const response = await postPingPostRequest({ Configure automatic retry for failed requests: ```typescript -const response = await postPingPostRequest({ +const response = await postPostPing({ payload: message, baseUrl: 'https://api.example.com', retry: { @@ -354,7 +353,7 @@ try { Customize request behavior with hooks: ```typescript -const response = await postPingPostRequest({ +const response = await postPostPing({ payload: message, baseUrl: 'https://api.example.com', hooks: { @@ -449,7 +448,7 @@ const response = await putUpdateUserItem({ Add custom headers or query parameters to any request: ```typescript -const response = await postPingPostRequest({ +const response = await postPostPing({ payload: message, baseUrl: 'https://api.example.com', additionalHeaders: { diff --git a/docs/protocols/kafka.md b/docs/protocols/kafka.md index de1bf35f..ccee224e 100644 --- a/docs/protocols/kafka.md +++ b/docs/protocols/kafka.md @@ -70,8 +70,7 @@ import { Kafka } from 'kafkajs'; // Location depends on the payload generator configurations import { UserSignedup } from './__gen__/payloads/UserSignedup'; // Location depends on the channel generator configurations -import { Protocols } from './__gen__/channels'; -const { kafka } = Protocols; +import { kafka } from './__gen__/channels'; const { consumeFromConsumeUserSignups, produceToPublishUserSignups } = kafka; /** @@ -85,26 +84,31 @@ const kafkaClient = new Kafka({ const myPayload = new UserSignedup({displayName: 'test', email: 'test@test.dk'}); // Consume the messages with the generated channel function -const consumerCallback = async ( - err, - msg: UserSignedUp | undefined, - parameters: UserSignedUpParameters | undefined, - kafkaMsg: EachMessagePayload | undefined +const consumerCallback = ( + err?: Error, + msg?: UserSignedup, + parameters?: UserSignedupParameters, + headers?: UserSignedupHeaders, + kafkaMsg?: EachMessagePayload ) => { - // Do stuff once you consumer from the topic + // Do stuff once you consume from the topic }; -const consumer = await consumeFromConsumeUserSignups( - consumerCallback, - myParameters, - kafkaClient, - { - fromBeginning: true, +const consumer = await consumeFromConsumeUserSignups({ + onDataCallback: consumerCallback, + parameters: myParameters, + kafka: kafkaClient, + options: { + fromBeginning: true, groupId: 'testId1' } -); +}); // Produce the messages with the generated channel function -const producer = await produceToPublishUserSignups(myPayload, kafkaClient); +const producer = await produceToPublishUserSignups({ + message: myPayload, + parameters: myParameters, + kafka: kafkaClient +}); ``` diff --git a/docs/protocols/mqtt.md b/docs/protocols/mqtt.md index db89e699..042cdd5c 100644 --- a/docs/protocols/mqtt.md +++ b/docs/protocols/mqtt.md @@ -92,8 +92,7 @@ import { UserSignedup } from './__gen__/payloads/UserSignedup'; // Location depends on the header generator configurations (if using headers) import { UserSignedUpHeaders } from './__gen__/headers/UserSignedUpHeaders'; // Location depends on the channel generator configurations -import { Protocols } from './__gen__/channels'; -const { mqtt } = Protocols; +import { mqtt } from './__gen__/channels'; const { publishToUserSignedup, subscribeToConsumeUserSignups } = mqtt; /** diff --git a/docs/protocols/websocket.md b/docs/protocols/websocket.md index ee22c2f5..a99aed35 100644 --- a/docs/protocols/websocket.md +++ b/docs/protocols/websocket.md @@ -103,14 +103,13 @@ const ws = new WebSocket('ws://localhost:8080/user/events/user123'); await ws.on('open', async () => { // Use generated publish function + // Channel parameters are part of the connection URL, so the publish + // function only takes the message and the socket. await publishToSendUserEvent({ message: new UserSignedUp({ userId: 'user123', email: 'user@example.com' }), - parameters: new UserEventsParameters({ - userId: 'user123' - }), ws }); }); diff --git a/examples/ecommerce-asyncapi-channels/package-lock.json b/examples/ecommerce-asyncapi-channels/package-lock.json index 1ddb67a8..1b2c675a 100644 --- a/examples/ecommerce-asyncapi-channels/package-lock.json +++ b/examples/ecommerce-asyncapi-channels/package-lock.json @@ -8,6 +8,8 @@ "name": "ecommerce-asyncapi-channels", "version": "1.0.0", "dependencies": { + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", "kafkajs": "^2.2.4", "nats": "^2.26.0" }, @@ -429,6 +431,39 @@ "undici-types": "~6.19.2" } }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/esbuild": { "version": "0.25.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", @@ -469,6 +504,28 @@ "@esbuild/win32-x64": "0.25.5" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -495,6 +552,12 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, "node_modules/kafkajs": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/kafkajs/-/kafkajs-2.2.4.tgz", @@ -525,6 +588,15 @@ "node": ">=10.0.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", diff --git a/examples/ecommerce-asyncapi-channels/package.json b/examples/ecommerce-asyncapi-channels/package.json index 1a437edb..795b9dce 100644 --- a/examples/ecommerce-asyncapi-channels/package.json +++ b/examples/ecommerce-asyncapi-channels/package.json @@ -21,7 +21,9 @@ ], "dependencies": { "kafkajs": "^2.2.4", - "nats": "^2.26.0" + "nats": "^2.26.0", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1" }, "devDependencies": { "@types/node": "^20.0.0", diff --git a/examples/ecommerce-asyncapi-channels/src/generated/headers/OrderCancelledHeaders.ts b/examples/ecommerce-asyncapi-channels/src/generated/headers/OrderCancelledHeaders.ts index a31e61e3..83ea276b 100644 --- a/examples/ecommerce-asyncapi-channels/src/generated/headers/OrderCancelledHeaders.ts +++ b/examples/ecommerce-asyncapi-channels/src/generated/headers/OrderCancelledHeaders.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class OrderCancelledHeaders { private _xCorrelationId: string; private _xOrderId: string; @@ -107,6 +107,9 @@ class OrderCancelledHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-channels/src/generated/headers/OrderCreatedHeaders.ts b/examples/ecommerce-asyncapi-channels/src/generated/headers/OrderCreatedHeaders.ts index ccac000b..cd63efe8 100644 --- a/examples/ecommerce-asyncapi-channels/src/generated/headers/OrderCreatedHeaders.ts +++ b/examples/ecommerce-asyncapi-channels/src/generated/headers/OrderCreatedHeaders.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class OrderCreatedHeaders { private _xCorrelationId: string; private _xOrderId: string; @@ -107,6 +107,9 @@ class OrderCreatedHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-channels/src/generated/headers/OrderLifecycleHeaders.ts b/examples/ecommerce-asyncapi-channels/src/generated/headers/OrderLifecycleHeaders.ts index e2b9df98..6347916b 100644 --- a/examples/ecommerce-asyncapi-channels/src/generated/headers/OrderLifecycleHeaders.ts +++ b/examples/ecommerce-asyncapi-channels/src/generated/headers/OrderLifecycleHeaders.ts @@ -1,5 +1,50 @@ import {OrderCreatedHeaders} from './OrderCreatedHeaders'; import {OrderUpdatedHeaders} from './OrderUpdatedHeaders'; import {OrderCancelledHeaders} from './OrderCancelledHeaders'; +import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; +import addFormatsModule from 'ajv-formats'; type OrderLifecycleHeaders = OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders; + +export function unmarshal(json: any): OrderLifecycleHeaders { + + return JSON.parse(json); +} +export function marshal(payload: OrderLifecycleHeaders) { + if(payload instanceof OrderCreatedHeaders) { +return payload.marshal(); +} +if(payload instanceof OrderUpdatedHeaders) { +return payload.marshal(); +} +if(payload instanceof OrderCancelledHeaders) { +return payload.marshal(); +} + return JSON.stringify(payload); +} + +export const theCodeGenSchema = {"$id":"OrderLifecycleHeaders","$schema":"http://json-schema.org/draft-07/schema","oneOf":[{"type":"object","required":["x-correlation-id","x-order-id","x-customer-id"],"properties":{"x-correlation-id":{"type":"string","format":"uuid"},"x-order-id":{"type":"string","format":"uuid"},"x-customer-id":{"type":"string","format":"uuid"},"x-source-service":{"type":"string"}},"$id":"OrderCreatedHeaders","$schema":"http://json-schema.org/draft-07/schema"},{"type":"object","required":["x-correlation-id","x-order-id","x-customer-id"],"properties":{"x-correlation-id":{"type":"string","format":"uuid"},"x-order-id":{"type":"string","format":"uuid"},"x-customer-id":{"type":"string","format":"uuid"},"x-source-service":{"type":"string"}},"$id":"OrderUpdatedHeaders","$schema":"http://json-schema.org/draft-07/schema"},{"type":"object","required":["x-correlation-id","x-order-id","x-customer-id"],"properties":{"x-correlation-id":{"type":"string","format":"uuid"},"x-order-id":{"type":"string","format":"uuid"},"x-customer-id":{"type":"string","format":"uuid"},"x-source-service":{"type":"string"}},"$id":"OrderCancelledHeaders","$schema":"http://json-schema.org/draft-07/schema"}]}; +export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFunction, ajvInstance?: Ajv, ajvOptions?: AjvOptions}): { valid: boolean; errors?: ErrorObject[]; } { + const {data, ajvValidatorFunction} = context ?? {}; + // Intentionally parse JSON strings to support validation of marshalled output. + // Example: validate({data: marshal(obj)}) works because marshal returns JSON string. + // Note: String 'true' will be coerced to boolean true due to JSON.parse. + const parsedData = typeof data === 'string' ? JSON.parse(data) : data; + const validate = ajvValidatorFunction ?? createValidator(context) + return { + valid: validate(parsedData), + errors: validate.errors ?? undefined, + }; +} +export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { + const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; + addFormats(ajvInstance); + + const validate = ajvInstance.compile(theCodeGenSchema); + return validate; +} + + export { OrderLifecycleHeaders }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-channels/src/generated/headers/OrderUpdatedHeaders.ts b/examples/ecommerce-asyncapi-channels/src/generated/headers/OrderUpdatedHeaders.ts index 000c6cfb..51245693 100644 --- a/examples/ecommerce-asyncapi-channels/src/generated/headers/OrderUpdatedHeaders.ts +++ b/examples/ecommerce-asyncapi-channels/src/generated/headers/OrderUpdatedHeaders.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class OrderUpdatedHeaders { private _xCorrelationId: string; private _xOrderId: string; @@ -107,6 +107,9 @@ class OrderUpdatedHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-channels/src/generated/kafka.ts b/examples/ecommerce-asyncapi-channels/src/generated/kafka.ts index 86afeed5..cfaace3b 100644 --- a/examples/ecommerce-asyncapi-channels/src/generated/kafka.ts +++ b/examples/ecommerce-asyncapi-channels/src/generated/kafka.ts @@ -9,7 +9,7 @@ import {Currency} from './payload/Currency'; import {Address, AddressInterface} from './payload/Address'; import {OrderStatus} from './payload/OrderStatus'; import {OrderLifecycleParameters, OrderLifecycleParametersInterface} from './parameter/OrderLifecycleParameters'; -import {OrderLifecycleHeaders} from './headers/OrderLifecycleHeaders'; +import * as OrderLifecycleHeadersModule from './headers/OrderLifecycleHeaders'; import * as Kafka from 'kafkajs'; /** @@ -28,7 +28,7 @@ function produceToPublishOrderCreated({ }: { message: OrderCreatedInterface | OrderCreated, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, - headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, + headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, kafka: Kafka.Kafka }): Promise { return new Promise(async (resolve, reject) => { @@ -81,7 +81,7 @@ function produceToPublishOrderUpdated({ }: { message: OrderUpdatedInterface | OrderUpdated, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, - headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, + headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, kafka: Kafka.Kafka }): Promise { return new Promise(async (resolve, reject) => { @@ -134,7 +134,7 @@ function produceToPublishOrderCancelled({ }: { message: OrderCancelledInterface | OrderCancelled, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, - headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, + headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, kafka: Kafka.Kafka }): Promise { return new Promise(async (resolve, reject) => { @@ -198,7 +198,7 @@ function consumeFromSubscribeToOrderEvents({ options = {fromBeginning: true, groupId: ''}, skipMessageValidation = false }: { - onDataCallback: (err?: Error, msg?: SubscribeToOrderEventsPayloadModule.SubscribeToOrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, kafkaMsg?: Kafka.EachMessagePayload) => void, + onDataCallback: (err?: Error, msg?: SubscribeToOrderEventsPayloadModule.SubscribeToOrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, kafkaMsg?: Kafka.EachMessagePayload) => void, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, kafka: Kafka.Kafka, options: {fromBeginning: boolean, groupId: string}, @@ -221,7 +221,7 @@ function consumeFromSubscribeToOrderEvents({ const parameters = OrderLifecycleParameters.createFromChannel(topic, 'orders.{action}', /^orders.([^.]*)$/); // Extract headers if present - let extractedHeaders: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders | undefined = undefined; + let extractedHeaders: OrderLifecycleHeadersModule.OrderLifecycleHeaders | undefined = undefined; if (message.headers) { const headerObj: Record = {}; for (const [key, value] of Object.entries(message.headers)) { @@ -229,7 +229,7 @@ function consumeFromSubscribeToOrderEvents({ headerObj[key] = value.toString(); } } - extractedHeaders = OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders.unmarshal(headerObj); + extractedHeaders = OrderLifecycleHeadersModule.unmarshal(headerObj); } if(!skipMessageValidation) { const {valid, errors} = SubscribeToOrderEventsPayloadModule.validate({data: receivedData, ajvValidatorFunction: validator}); diff --git a/examples/ecommerce-asyncapi-channels/src/generated/nats.ts b/examples/ecommerce-asyncapi-channels/src/generated/nats.ts index e101d374..050e25df 100644 --- a/examples/ecommerce-asyncapi-channels/src/generated/nats.ts +++ b/examples/ecommerce-asyncapi-channels/src/generated/nats.ts @@ -9,7 +9,7 @@ import {Currency} from './payload/Currency'; import {Address, AddressInterface} from './payload/Address'; import {OrderStatus} from './payload/OrderStatus'; import {OrderLifecycleParameters, OrderLifecycleParametersInterface} from './parameter/OrderLifecycleParameters'; -import {OrderLifecycleHeaders} from './headers/OrderLifecycleHeaders'; +import * as OrderLifecycleHeadersModule from './headers/OrderLifecycleHeaders'; import * as Nats from 'nats'; /** @@ -32,7 +32,7 @@ function publishToPublishOrderCreated({ }: { message: OrderCreatedInterface | OrderCreated, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, - headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, + headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, nc: Nats.NatsConnection, codec?: Nats.Codec, options?: Nats.PublishOptions @@ -81,7 +81,7 @@ function jetStreamPublishToPublishOrderCreated({ }: { message: OrderCreatedInterface | OrderCreated, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, - headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, + headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, js: Nats.JetStreamClient, codec?: Nats.Codec, options?: Partial @@ -130,7 +130,7 @@ function publishToPublishOrderUpdated({ }: { message: OrderUpdatedInterface | OrderUpdated, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, - headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, + headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, nc: Nats.NatsConnection, codec?: Nats.Codec, options?: Nats.PublishOptions @@ -179,7 +179,7 @@ function jetStreamPublishToPublishOrderUpdated({ }: { message: OrderUpdatedInterface | OrderUpdated, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, - headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, + headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, js: Nats.JetStreamClient, codec?: Nats.Codec, options?: Partial @@ -228,7 +228,7 @@ function publishToPublishOrderCancelled({ }: { message: OrderCancelledInterface | OrderCancelled, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, - headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, + headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, nc: Nats.NatsConnection, codec?: Nats.Codec, options?: Nats.PublishOptions @@ -277,7 +277,7 @@ function jetStreamPublishToPublishOrderCancelled({ }: { message: OrderCancelledInterface | OrderCancelled, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, - headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, + headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, js: Nats.JetStreamClient, codec?: Nats.Codec, options?: Partial @@ -335,7 +335,7 @@ function subscribeToSubscribeToOrderEvents({ options, skipMessageValidation = false }: { - onDataCallback: (err?: Error, msg?: SubscribeToOrderEventsPayloadModule.SubscribeToOrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, natsMsg?: Nats.Msg) => void, + onDataCallback: (err?: Error, msg?: SubscribeToOrderEventsPayloadModule.SubscribeToOrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, natsMsg?: Nats.Msg) => void, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, nc: Nats.NatsConnection, codec?: Nats.Codec, @@ -351,7 +351,7 @@ function subscribeToSubscribeToOrderEvents({ const parameters = OrderLifecycleParameters.createFromChannel(msg.subject, 'orders.{action}', /^orders.([^.]*)$/) let receivedData: any = codec.decode(msg.data); // Extract headers if present - let extractedHeaders: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders | undefined = undefined; + let extractedHeaders: OrderLifecycleHeadersModule.OrderLifecycleHeaders | undefined = undefined; if (msg.headers) { const headerObj: Record = {}; // NATS headers support both iteration and get() method @@ -366,7 +366,7 @@ function subscribeToSubscribeToOrderEvents({ headerObj[key] = value; } } - extractedHeaders = OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders.unmarshal(headerObj); + extractedHeaders = OrderLifecycleHeadersModule.unmarshal(headerObj); } if(!skipMessageValidation) { const {valid, errors} = SubscribeToOrderEventsPayloadModule.validate({data: receivedData, ajvValidatorFunction: validator}); @@ -413,7 +413,7 @@ function jetStreamPullSubscribeToSubscribeToOrderEvents({ codec = Nats.JSONCodec(), skipMessageValidation = false }: { - onDataCallback: (err?: Error, msg?: SubscribeToOrderEventsPayloadModule.SubscribeToOrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, jetstreamMsg?: Nats.JsMsg) => void, + onDataCallback: (err?: Error, msg?: SubscribeToOrderEventsPayloadModule.SubscribeToOrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, jetstreamMsg?: Nats.JsMsg) => void, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, js: Nats.JetStreamClient, options: Nats.ConsumerOptsBuilder | Partial, @@ -429,7 +429,7 @@ function jetStreamPullSubscribeToSubscribeToOrderEvents({ const parameters = OrderLifecycleParameters.createFromChannel(msg.subject, 'orders.{action}', /^orders.([^.]*)$/) let receivedData: any = codec.decode(msg.data); // Extract headers if present - let extractedHeaders: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders | undefined = undefined; + let extractedHeaders: OrderLifecycleHeadersModule.OrderLifecycleHeaders | undefined = undefined; if (msg.headers) { const headerObj: Record = {}; // NATS headers support both iteration and get() method @@ -444,7 +444,7 @@ function jetStreamPullSubscribeToSubscribeToOrderEvents({ headerObj[key] = value; } } - extractedHeaders = OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders.unmarshal(headerObj); + extractedHeaders = OrderLifecycleHeadersModule.unmarshal(headerObj); } if(!skipMessageValidation) { const {valid, errors} = SubscribeToOrderEventsPayloadModule.validate({data: receivedData, ajvValidatorFunction: validator}); @@ -491,7 +491,7 @@ function jetStreamPushSubscriptionFromSubscribeToOrderEvents({ codec = Nats.JSONCodec(), skipMessageValidation = false }: { - onDataCallback: (err?: Error, msg?: SubscribeToOrderEventsPayloadModule.SubscribeToOrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, jetstreamMsg?: Nats.JsMsg) => void, + onDataCallback: (err?: Error, msg?: SubscribeToOrderEventsPayloadModule.SubscribeToOrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, jetstreamMsg?: Nats.JsMsg) => void, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, js: Nats.JetStreamClient, options: Nats.ConsumerOptsBuilder | Partial, @@ -507,7 +507,7 @@ function jetStreamPushSubscriptionFromSubscribeToOrderEvents({ const parameters = OrderLifecycleParameters.createFromChannel(msg.subject, 'orders.{action}', /^orders.([^.]*)$/) let receivedData: any = codec.decode(msg.data); // Extract headers if present - let extractedHeaders: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders | undefined = undefined; + let extractedHeaders: OrderLifecycleHeadersModule.OrderLifecycleHeaders | undefined = undefined; if (msg.headers) { const headerObj: Record = {}; // NATS headers support both iteration and get() method @@ -522,7 +522,7 @@ function jetStreamPushSubscriptionFromSubscribeToOrderEvents({ headerObj[key] = value; } } - extractedHeaders = OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders.unmarshal(headerObj); + extractedHeaders = OrderLifecycleHeadersModule.unmarshal(headerObj); } if(!skipMessageValidation) { const {valid, errors} = SubscribeToOrderEventsPayloadModule.validate({data: receivedData, ajvValidatorFunction: validator}); diff --git a/examples/ecommerce-asyncapi-channels/src/generated/parameter/OrderLifecycleParameters.ts b/examples/ecommerce-asyncapi-channels/src/generated/parameter/OrderLifecycleParameters.ts index f73eafe2..8b251091 100644 --- a/examples/ecommerce-asyncapi-channels/src/generated/parameter/OrderLifecycleParameters.ts +++ b/examples/ecommerce-asyncapi-channels/src/generated/parameter/OrderLifecycleParameters.ts @@ -42,4 +42,5 @@ class OrderLifecycleParameters { return parameters; } } -export { OrderLifecycleParameters, OrderLifecycleParametersInterface }; \ No newline at end of file +export { OrderLifecycleParameters }; +export type { OrderLifecycleParametersInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-channels/src/generated/payload/Address.ts b/examples/ecommerce-asyncapi-channels/src/generated/payload/Address.ts index d4b5a267..3bdbb653 100644 --- a/examples/ecommerce-asyncapi-channels/src/generated/payload/Address.ts +++ b/examples/ecommerce-asyncapi-channels/src/generated/payload/Address.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface AddressInterface { street: string city: string @@ -120,6 +120,9 @@ class Address { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -127,4 +130,5 @@ class Address { } } -export { Address, AddressInterface }; \ No newline at end of file +export { Address }; +export type { AddressInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-channels/src/generated/payload/Money.ts b/examples/ecommerce-asyncapi-channels/src/generated/payload/Money.ts index 72c26296..ccdaef6f 100644 --- a/examples/ecommerce-asyncapi-channels/src/generated/payload/Money.ts +++ b/examples/ecommerce-asyncapi-channels/src/generated/payload/Money.ts @@ -1,6 +1,6 @@ import {Currency} from './Currency'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface MoneyInterface { amount: number currency: Currency @@ -88,6 +88,9 @@ class Money { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -95,4 +98,5 @@ class Money { } } -export { Money, MoneyInterface }; \ No newline at end of file +export { Money }; +export type { MoneyInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderCancelled.ts b/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderCancelled.ts index 9dcfacc6..de3c4372 100644 --- a/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderCancelled.ts +++ b/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderCancelled.ts @@ -1,6 +1,6 @@ import {Money} from './Money'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface OrderCancelledInterface { orderId: string reason: string @@ -109,6 +109,9 @@ class OrderCancelled { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -116,4 +119,5 @@ class OrderCancelled { } } -export { OrderCancelled, OrderCancelledInterface }; \ No newline at end of file +export { OrderCancelled }; +export type { OrderCancelledInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderCreated.ts b/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderCreated.ts index ccc37a23..b78947b7 100644 --- a/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderCreated.ts +++ b/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderCreated.ts @@ -2,7 +2,7 @@ import {OrderItem} from './OrderItem'; import {Money} from './Money'; import {Address} from './Address'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface OrderCreatedInterface { orderId: string customerId: string @@ -139,6 +139,9 @@ class OrderCreated { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -146,4 +149,5 @@ class OrderCreated { } } -export { OrderCreated, OrderCreatedInterface }; \ No newline at end of file +export { OrderCreated }; +export type { OrderCreatedInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderItem.ts b/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderItem.ts index b4972a02..b6384a37 100644 --- a/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderItem.ts +++ b/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderItem.ts @@ -1,6 +1,6 @@ import {Money} from './Money'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface OrderItemInterface { productId: string quantity: number @@ -121,6 +121,9 @@ class OrderItem { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -128,4 +131,5 @@ class OrderItem { } } -export { OrderItem, OrderItemInterface }; \ No newline at end of file +export { OrderItem }; +export type { OrderItemInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderLifecyclePayload.ts b/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderLifecyclePayload.ts index dfd62abb..1edce78e 100644 --- a/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderLifecyclePayload.ts +++ b/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderLifecyclePayload.ts @@ -3,7 +3,7 @@ import {OrderUpdated} from './OrderUpdated'; import {OrderCancelled} from './OrderCancelled'; import {OrderStatus} from './OrderStatus'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type OrderLifecyclePayload = OrderCreated | OrderUpdated | OrderCancelled; export function unmarshal(json: any): OrderLifecyclePayload { @@ -42,6 +42,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderUpdated.ts b/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderUpdated.ts index c7dca941..47f5651b 100644 --- a/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderUpdated.ts +++ b/examples/ecommerce-asyncapi-channels/src/generated/payload/OrderUpdated.ts @@ -1,6 +1,6 @@ import {OrderStatus} from './OrderStatus'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface OrderUpdatedInterface { orderId: string status: OrderStatus @@ -121,6 +121,9 @@ class OrderUpdated { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -128,4 +131,5 @@ class OrderUpdated { } } -export { OrderUpdated, OrderUpdatedInterface }; \ No newline at end of file +export { OrderUpdated }; +export type { OrderUpdatedInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-channels/src/generated/payload/SubscribeToOrderEventsPayload.ts b/examples/ecommerce-asyncapi-channels/src/generated/payload/SubscribeToOrderEventsPayload.ts index 7281d4fa..a0ed3be1 100644 --- a/examples/ecommerce-asyncapi-channels/src/generated/payload/SubscribeToOrderEventsPayload.ts +++ b/examples/ecommerce-asyncapi-channels/src/generated/payload/SubscribeToOrderEventsPayload.ts @@ -3,7 +3,7 @@ import {OrderUpdated} from './OrderUpdated'; import {OrderCancelled} from './OrderCancelled'; import {OrderStatus} from './OrderStatus'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type SubscribeToOrderEventsPayload = OrderCreated | OrderUpdated | OrderCancelled; export function unmarshal(json: any): SubscribeToOrderEventsPayload { @@ -42,6 +42,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-channels/src/index.ts b/examples/ecommerce-asyncapi-channels/src/index.ts index b319e683..f2759de9 100644 --- a/examples/ecommerce-asyncapi-channels/src/index.ts +++ b/examples/ecommerce-asyncapi-channels/src/index.ts @@ -3,7 +3,7 @@ */ // Import the generated protocols and types -import { Protocols } from './generated/index'; +import { nats, kafka } from './generated/index'; import { OrderCreated } from './generated/payload/OrderCreated'; import { OrderUpdated } from './generated/payload/OrderUpdated'; import { OrderCancelled } from './generated/payload/OrderCancelled'; @@ -99,7 +99,7 @@ async function demonstrateProtocolFunctions() { const orderCreatedParams = new OrderLifecycleParameters({ action: 'created' }); // Publish order created with NATS - await Protocols.nats.publishToPublishOrderCreated({ + await nats.publishToPublishOrderCreated({ message: orderCreatedMessage, parameters: orderCreatedParams, nc: natsConnection @@ -119,7 +119,7 @@ async function demonstrateProtocolFunctions() { const orderUpdatedParams = new OrderLifecycleParameters({ action: 'updated' }); // Publish order updated with Kafka - await Protocols.kafka.produceToPublishOrderUpdated({ + await kafka.produceToPublishOrderUpdated({ message: orderUpdatedMessage, parameters: orderUpdatedParams, kafka: kafkaClient @@ -141,7 +141,7 @@ async function demonstrateProtocolFunctions() { const orderCancelledParams = new OrderLifecycleParameters({ action: 'cancelled' }); // Publish order cancelled with NATS - await Protocols.nats.publishToPublishOrderCancelled({ + await nats.publishToPublishOrderCancelled({ message: orderCancelledMessage, parameters: orderCancelledParams, nc: natsConnection @@ -151,7 +151,7 @@ async function demonstrateProtocolFunctions() { // Subscribe to order events with NATS (for real-time processing) const orderSubscriptionParams = new OrderLifecycleParameters({ action: 'created' }); - await Protocols.nats.subscribeToSubscribeToOrderEvents({ + await nats.subscribeToSubscribeToOrderEvents({ onDataCallback: (err, message, parameters, natsMsg) => { if (err) { console.error('[NATS Handler] Error processing order event:', err.message); @@ -180,7 +180,7 @@ async function demonstrateProtocolFunctions() { // Subscribe to order events with Kafka (for analytics and reporting) const kafkaSubscriptionParams = new OrderLifecycleParameters({ action: 'created' }); - await Protocols.kafka.consumeFromSubscribeToOrderEvents({ + await kafka.consumeFromSubscribeToOrderEvents({ onDataCallback: (err, message, parameters, kafkaMsg) => { if (err) { console.error('[Kafka Handler] Error processing order event:', err.message); diff --git a/examples/ecommerce-asyncapi-client/package-lock.json b/examples/ecommerce-asyncapi-client/package-lock.json index d5082f90..320364d2 100644 --- a/examples/ecommerce-asyncapi-client/package-lock.json +++ b/examples/ecommerce-asyncapi-client/package-lock.json @@ -8,6 +8,8 @@ "name": "ecommerce-asyncapi-client", "version": "1.0.0", "dependencies": { + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", "nats": "^2.26.0" }, "devDependencies": { @@ -428,6 +430,39 @@ "undici-types": "~6.19.2" } }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/esbuild": { "version": "0.25.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", @@ -468,6 +503,28 @@ "@esbuild/win32-x64": "0.25.5" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -494,6 +551,12 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, "node_modules/nats": { "version": "2.29.3", "resolved": "https://registry.npmjs.org/nats/-/nats-2.29.3.tgz", @@ -516,6 +579,15 @@ "node": ">=10.0.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", diff --git a/examples/ecommerce-asyncapi-client/package.json b/examples/ecommerce-asyncapi-client/package.json index 93e78614..bede4c9b 100644 --- a/examples/ecommerce-asyncapi-client/package.json +++ b/examples/ecommerce-asyncapi-client/package.json @@ -12,7 +12,7 @@ }, "keywords": [ "asyncapi", - "codegen", + "codegen", "client", "sdk", "messaging", @@ -21,7 +21,9 @@ "lifecycle-events" ], "dependencies": { - "nats": "^2.26.0" + "nats": "^2.26.0", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1" }, "devDependencies": { "@types/node": "^20.0.0", @@ -31,4 +33,4 @@ "engines": { "node": ">=18.0.0" } -} \ No newline at end of file +} diff --git a/examples/ecommerce-asyncapi-client/src/generated/NatsClient.ts b/examples/ecommerce-asyncapi-client/src/generated/NatsClient.ts index ff9ecc9a..df39c007 100644 --- a/examples/ecommerce-asyncapi-client/src/generated/NatsClient.ts +++ b/examples/ecommerce-asyncapi-client/src/generated/NatsClient.ts @@ -20,6 +20,7 @@ export {Address}; export {OrderStatus}; import {OrderLifecycleParameters, OrderLifecycleParametersInterface} from './channels/parameter/OrderLifecycleParameters'; export {OrderLifecycleParameters}; +import * as OrderLifecycleHeadersModule from './channels/headers/OrderLifecycleHeaders'; //Import channel functions import * as nats from './channels/nats'; @@ -309,7 +310,7 @@ export class NatsClient { options, flush }: { - onDataCallback: (err?: Error, msg?: OrderEventsPayloadModule.OrderEventsPayload, parameters?: OrderLifecycleParameters, natsMsg?: Nats.Msg) => void, + onDataCallback: (err?: Error, msg?: OrderEventsPayloadModule.OrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, natsMsg?: Nats.Msg) => void, parameters: OrderLifecycleParameters, options?: Nats.SubscriptionOptions, flush?: boolean @@ -349,7 +350,7 @@ export class NatsClient { parameters, options = {} }: { - onDataCallback: (err?: Error, msg?: OrderEventsPayloadModule.OrderEventsPayload, parameters?: OrderLifecycleParameters, jetstreamMsg?: Nats.JsMsg) => void, + onDataCallback: (err?: Error, msg?: OrderEventsPayloadModule.OrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, jetstreamMsg?: Nats.JsMsg) => void, parameters: OrderLifecycleParameters, options: Nats.ConsumerOptsBuilder | Partial }): Promise { @@ -386,7 +387,7 @@ export class NatsClient { parameters, options = {} }: { - onDataCallback: (err?: Error, msg?: OrderEventsPayloadModule.OrderEventsPayload, parameters?: OrderLifecycleParameters, jetstreamMsg?: Nats.JsMsg) => void, + onDataCallback: (err?: Error, msg?: OrderEventsPayloadModule.OrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, jetstreamMsg?: Nats.JsMsg) => void, parameters: OrderLifecycleParameters, options: Nats.ConsumerOptsBuilder | Partial }): Promise { diff --git a/examples/ecommerce-asyncapi-client/src/generated/channels/headers/OrderCancelledHeaders.ts b/examples/ecommerce-asyncapi-client/src/generated/channels/headers/OrderCancelledHeaders.ts index a31e61e3..83ea276b 100644 --- a/examples/ecommerce-asyncapi-client/src/generated/channels/headers/OrderCancelledHeaders.ts +++ b/examples/ecommerce-asyncapi-client/src/generated/channels/headers/OrderCancelledHeaders.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class OrderCancelledHeaders { private _xCorrelationId: string; private _xOrderId: string; @@ -107,6 +107,9 @@ class OrderCancelledHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-client/src/generated/channels/headers/OrderCreatedHeaders.ts b/examples/ecommerce-asyncapi-client/src/generated/channels/headers/OrderCreatedHeaders.ts index ccac000b..cd63efe8 100644 --- a/examples/ecommerce-asyncapi-client/src/generated/channels/headers/OrderCreatedHeaders.ts +++ b/examples/ecommerce-asyncapi-client/src/generated/channels/headers/OrderCreatedHeaders.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class OrderCreatedHeaders { private _xCorrelationId: string; private _xOrderId: string; @@ -107,6 +107,9 @@ class OrderCreatedHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-client/src/generated/channels/headers/OrderLifecycleHeaders.ts b/examples/ecommerce-asyncapi-client/src/generated/channels/headers/OrderLifecycleHeaders.ts index e2b9df98..6347916b 100644 --- a/examples/ecommerce-asyncapi-client/src/generated/channels/headers/OrderLifecycleHeaders.ts +++ b/examples/ecommerce-asyncapi-client/src/generated/channels/headers/OrderLifecycleHeaders.ts @@ -1,5 +1,50 @@ import {OrderCreatedHeaders} from './OrderCreatedHeaders'; import {OrderUpdatedHeaders} from './OrderUpdatedHeaders'; import {OrderCancelledHeaders} from './OrderCancelledHeaders'; +import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; +import addFormatsModule from 'ajv-formats'; type OrderLifecycleHeaders = OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders; + +export function unmarshal(json: any): OrderLifecycleHeaders { + + return JSON.parse(json); +} +export function marshal(payload: OrderLifecycleHeaders) { + if(payload instanceof OrderCreatedHeaders) { +return payload.marshal(); +} +if(payload instanceof OrderUpdatedHeaders) { +return payload.marshal(); +} +if(payload instanceof OrderCancelledHeaders) { +return payload.marshal(); +} + return JSON.stringify(payload); +} + +export const theCodeGenSchema = {"$id":"OrderLifecycleHeaders","$schema":"http://json-schema.org/draft-07/schema","oneOf":[{"type":"object","required":["x-correlation-id","x-order-id","x-customer-id"],"properties":{"x-correlation-id":{"type":"string","format":"uuid"},"x-order-id":{"type":"string","format":"uuid"},"x-customer-id":{"type":"string","format":"uuid"},"x-source-service":{"type":"string"}},"$id":"OrderCreatedHeaders","$schema":"http://json-schema.org/draft-07/schema"},{"type":"object","required":["x-correlation-id","x-order-id","x-customer-id"],"properties":{"x-correlation-id":{"type":"string","format":"uuid"},"x-order-id":{"type":"string","format":"uuid"},"x-customer-id":{"type":"string","format":"uuid"},"x-source-service":{"type":"string"}},"$id":"OrderUpdatedHeaders","$schema":"http://json-schema.org/draft-07/schema"},{"type":"object","required":["x-correlation-id","x-order-id","x-customer-id"],"properties":{"x-correlation-id":{"type":"string","format":"uuid"},"x-order-id":{"type":"string","format":"uuid"},"x-customer-id":{"type":"string","format":"uuid"},"x-source-service":{"type":"string"}},"$id":"OrderCancelledHeaders","$schema":"http://json-schema.org/draft-07/schema"}]}; +export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFunction, ajvInstance?: Ajv, ajvOptions?: AjvOptions}): { valid: boolean; errors?: ErrorObject[]; } { + const {data, ajvValidatorFunction} = context ?? {}; + // Intentionally parse JSON strings to support validation of marshalled output. + // Example: validate({data: marshal(obj)}) works because marshal returns JSON string. + // Note: String 'true' will be coerced to boolean true due to JSON.parse. + const parsedData = typeof data === 'string' ? JSON.parse(data) : data; + const validate = ajvValidatorFunction ?? createValidator(context) + return { + valid: validate(parsedData), + errors: validate.errors ?? undefined, + }; +} +export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { + const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; + addFormats(ajvInstance); + + const validate = ajvInstance.compile(theCodeGenSchema); + return validate; +} + + export { OrderLifecycleHeaders }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-client/src/generated/channels/headers/OrderUpdatedHeaders.ts b/examples/ecommerce-asyncapi-client/src/generated/channels/headers/OrderUpdatedHeaders.ts index 000c6cfb..51245693 100644 --- a/examples/ecommerce-asyncapi-client/src/generated/channels/headers/OrderUpdatedHeaders.ts +++ b/examples/ecommerce-asyncapi-client/src/generated/channels/headers/OrderUpdatedHeaders.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class OrderUpdatedHeaders { private _xCorrelationId: string; private _xOrderId: string; @@ -107,6 +107,9 @@ class OrderUpdatedHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-client/src/generated/channels/nats.ts b/examples/ecommerce-asyncapi-client/src/generated/channels/nats.ts index 4613e172..6a926374 100644 --- a/examples/ecommerce-asyncapi-client/src/generated/channels/nats.ts +++ b/examples/ecommerce-asyncapi-client/src/generated/channels/nats.ts @@ -9,7 +9,7 @@ import {Currency} from './payload/Currency'; import {Address, AddressInterface} from './payload/Address'; import {OrderStatus} from './payload/OrderStatus'; import {OrderLifecycleParameters, OrderLifecycleParametersInterface} from './parameter/OrderLifecycleParameters'; -import {OrderLifecycleHeaders} from './headers/OrderLifecycleHeaders'; +import * as OrderLifecycleHeadersModule from './headers/OrderLifecycleHeaders'; import * as Nats from 'nats'; /** @@ -32,7 +32,7 @@ function publishToOrderCreated({ }: { message: OrderCreatedInterface | OrderCreated, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, - headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, + headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, nc: Nats.NatsConnection, codec?: Nats.Codec, options?: Nats.PublishOptions @@ -81,7 +81,7 @@ function jetStreamPublishToOrderCreated({ }: { message: OrderCreatedInterface | OrderCreated, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, - headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, + headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, js: Nats.JetStreamClient, codec?: Nats.Codec, options?: Partial @@ -130,7 +130,7 @@ function publishToOrderUpdated({ }: { message: OrderUpdatedInterface | OrderUpdated, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, - headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, + headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, nc: Nats.NatsConnection, codec?: Nats.Codec, options?: Nats.PublishOptions @@ -179,7 +179,7 @@ function jetStreamPublishToOrderUpdated({ }: { message: OrderUpdatedInterface | OrderUpdated, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, - headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, + headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, js: Nats.JetStreamClient, codec?: Nats.Codec, options?: Partial @@ -228,7 +228,7 @@ function publishToOrderCancelled({ }: { message: OrderCancelledInterface | OrderCancelled, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, - headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, + headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, nc: Nats.NatsConnection, codec?: Nats.Codec, options?: Nats.PublishOptions @@ -277,7 +277,7 @@ function jetStreamPublishToOrderCancelled({ }: { message: OrderCancelledInterface | OrderCancelled, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, - headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, + headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, js: Nats.JetStreamClient, codec?: Nats.Codec, options?: Partial @@ -335,7 +335,7 @@ function subscribeToOrderEvents({ options, skipMessageValidation = false }: { - onDataCallback: (err?: Error, msg?: OrderEventsPayloadModule.OrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, natsMsg?: Nats.Msg) => void, + onDataCallback: (err?: Error, msg?: OrderEventsPayloadModule.OrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, natsMsg?: Nats.Msg) => void, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, nc: Nats.NatsConnection, codec?: Nats.Codec, @@ -351,7 +351,7 @@ function subscribeToOrderEvents({ const parameters = OrderLifecycleParameters.createFromChannel(msg.subject, 'orders.{action}', /^orders.([^.]*)$/) let receivedData: any = codec.decode(msg.data); // Extract headers if present - let extractedHeaders: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders | undefined = undefined; + let extractedHeaders: OrderLifecycleHeadersModule.OrderLifecycleHeaders | undefined = undefined; if (msg.headers) { const headerObj: Record = {}; // NATS headers support both iteration and get() method @@ -366,7 +366,7 @@ function subscribeToOrderEvents({ headerObj[key] = value; } } - extractedHeaders = OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders.unmarshal(headerObj); + extractedHeaders = OrderLifecycleHeadersModule.unmarshal(headerObj); } if(!skipMessageValidation) { const {valid, errors} = OrderEventsPayloadModule.validate({data: receivedData, ajvValidatorFunction: validator}); @@ -413,7 +413,7 @@ function jetStreamPullSubscribeToOrderEvents({ codec = Nats.JSONCodec(), skipMessageValidation = false }: { - onDataCallback: (err?: Error, msg?: OrderEventsPayloadModule.OrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, jetstreamMsg?: Nats.JsMsg) => void, + onDataCallback: (err?: Error, msg?: OrderEventsPayloadModule.OrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, jetstreamMsg?: Nats.JsMsg) => void, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, js: Nats.JetStreamClient, options: Nats.ConsumerOptsBuilder | Partial, @@ -429,7 +429,7 @@ function jetStreamPullSubscribeToOrderEvents({ const parameters = OrderLifecycleParameters.createFromChannel(msg.subject, 'orders.{action}', /^orders.([^.]*)$/) let receivedData: any = codec.decode(msg.data); // Extract headers if present - let extractedHeaders: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders | undefined = undefined; + let extractedHeaders: OrderLifecycleHeadersModule.OrderLifecycleHeaders | undefined = undefined; if (msg.headers) { const headerObj: Record = {}; // NATS headers support both iteration and get() method @@ -444,7 +444,7 @@ function jetStreamPullSubscribeToOrderEvents({ headerObj[key] = value; } } - extractedHeaders = OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders.unmarshal(headerObj); + extractedHeaders = OrderLifecycleHeadersModule.unmarshal(headerObj); } if(!skipMessageValidation) { const {valid, errors} = OrderEventsPayloadModule.validate({data: receivedData, ajvValidatorFunction: validator}); @@ -491,7 +491,7 @@ function jetStreamPushSubscriptionFromOrderEvents({ codec = Nats.JSONCodec(), skipMessageValidation = false }: { - onDataCallback: (err?: Error, msg?: OrderEventsPayloadModule.OrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders, jetstreamMsg?: Nats.JsMsg) => void, + onDataCallback: (err?: Error, msg?: OrderEventsPayloadModule.OrderEventsPayload, parameters?: OrderLifecycleParameters, headers?: OrderLifecycleHeadersModule.OrderLifecycleHeaders, jetstreamMsg?: Nats.JsMsg) => void, parameters: OrderLifecycleParametersInterface | OrderLifecycleParameters, js: Nats.JetStreamClient, options: Nats.ConsumerOptsBuilder | Partial, @@ -507,7 +507,7 @@ function jetStreamPushSubscriptionFromOrderEvents({ const parameters = OrderLifecycleParameters.createFromChannel(msg.subject, 'orders.{action}', /^orders.([^.]*)$/) let receivedData: any = codec.decode(msg.data); // Extract headers if present - let extractedHeaders: OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders | undefined = undefined; + let extractedHeaders: OrderLifecycleHeadersModule.OrderLifecycleHeaders | undefined = undefined; if (msg.headers) { const headerObj: Record = {}; // NATS headers support both iteration and get() method @@ -522,7 +522,7 @@ function jetStreamPushSubscriptionFromOrderEvents({ headerObj[key] = value; } } - extractedHeaders = OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders.unmarshal(headerObj); + extractedHeaders = OrderLifecycleHeadersModule.unmarshal(headerObj); } if(!skipMessageValidation) { const {valid, errors} = OrderEventsPayloadModule.validate({data: receivedData, ajvValidatorFunction: validator}); diff --git a/examples/ecommerce-asyncapi-client/src/generated/channels/parameter/OrderLifecycleParameters.ts b/examples/ecommerce-asyncapi-client/src/generated/channels/parameter/OrderLifecycleParameters.ts index f73eafe2..8b251091 100644 --- a/examples/ecommerce-asyncapi-client/src/generated/channels/parameter/OrderLifecycleParameters.ts +++ b/examples/ecommerce-asyncapi-client/src/generated/channels/parameter/OrderLifecycleParameters.ts @@ -42,4 +42,5 @@ class OrderLifecycleParameters { return parameters; } } -export { OrderLifecycleParameters, OrderLifecycleParametersInterface }; \ No newline at end of file +export { OrderLifecycleParameters }; +export type { OrderLifecycleParametersInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-client/src/generated/channels/payload/Address.ts b/examples/ecommerce-asyncapi-client/src/generated/channels/payload/Address.ts index d4b5a267..3bdbb653 100644 --- a/examples/ecommerce-asyncapi-client/src/generated/channels/payload/Address.ts +++ b/examples/ecommerce-asyncapi-client/src/generated/channels/payload/Address.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface AddressInterface { street: string city: string @@ -120,6 +120,9 @@ class Address { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -127,4 +130,5 @@ class Address { } } -export { Address, AddressInterface }; \ No newline at end of file +export { Address }; +export type { AddressInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-client/src/generated/channels/payload/Money.ts b/examples/ecommerce-asyncapi-client/src/generated/channels/payload/Money.ts index 72c26296..ccdaef6f 100644 --- a/examples/ecommerce-asyncapi-client/src/generated/channels/payload/Money.ts +++ b/examples/ecommerce-asyncapi-client/src/generated/channels/payload/Money.ts @@ -1,6 +1,6 @@ import {Currency} from './Currency'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface MoneyInterface { amount: number currency: Currency @@ -88,6 +88,9 @@ class Money { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -95,4 +98,5 @@ class Money { } } -export { Money, MoneyInterface }; \ No newline at end of file +export { Money }; +export type { MoneyInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderCancelled.ts b/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderCancelled.ts index 9dcfacc6..de3c4372 100644 --- a/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderCancelled.ts +++ b/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderCancelled.ts @@ -1,6 +1,6 @@ import {Money} from './Money'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface OrderCancelledInterface { orderId: string reason: string @@ -109,6 +109,9 @@ class OrderCancelled { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -116,4 +119,5 @@ class OrderCancelled { } } -export { OrderCancelled, OrderCancelledInterface }; \ No newline at end of file +export { OrderCancelled }; +export type { OrderCancelledInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderCreated.ts b/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderCreated.ts index ccc37a23..b78947b7 100644 --- a/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderCreated.ts +++ b/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderCreated.ts @@ -2,7 +2,7 @@ import {OrderItem} from './OrderItem'; import {Money} from './Money'; import {Address} from './Address'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface OrderCreatedInterface { orderId: string customerId: string @@ -139,6 +139,9 @@ class OrderCreated { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -146,4 +149,5 @@ class OrderCreated { } } -export { OrderCreated, OrderCreatedInterface }; \ No newline at end of file +export { OrderCreated }; +export type { OrderCreatedInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderEventsPayload.ts b/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderEventsPayload.ts index 3a3806ab..8ca03228 100644 --- a/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderEventsPayload.ts +++ b/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderEventsPayload.ts @@ -3,7 +3,7 @@ import {OrderUpdated} from './OrderUpdated'; import {OrderCancelled} from './OrderCancelled'; import {OrderStatus} from './OrderStatus'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type OrderEventsPayload = OrderCreated | OrderUpdated | OrderCancelled; export function unmarshal(json: any): OrderEventsPayload { @@ -42,6 +42,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderItem.ts b/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderItem.ts index b4972a02..b6384a37 100644 --- a/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderItem.ts +++ b/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderItem.ts @@ -1,6 +1,6 @@ import {Money} from './Money'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface OrderItemInterface { productId: string quantity: number @@ -121,6 +121,9 @@ class OrderItem { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -128,4 +131,5 @@ class OrderItem { } } -export { OrderItem, OrderItemInterface }; \ No newline at end of file +export { OrderItem }; +export type { OrderItemInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderLifecyclePayload.ts b/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderLifecyclePayload.ts index dfd62abb..1edce78e 100644 --- a/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderLifecyclePayload.ts +++ b/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderLifecyclePayload.ts @@ -3,7 +3,7 @@ import {OrderUpdated} from './OrderUpdated'; import {OrderCancelled} from './OrderCancelled'; import {OrderStatus} from './OrderStatus'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type OrderLifecyclePayload = OrderCreated | OrderUpdated | OrderCancelled; export function unmarshal(json: any): OrderLifecyclePayload { @@ -42,6 +42,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderUpdated.ts b/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderUpdated.ts index c7dca941..47f5651b 100644 --- a/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderUpdated.ts +++ b/examples/ecommerce-asyncapi-client/src/generated/channels/payload/OrderUpdated.ts @@ -1,6 +1,6 @@ import {OrderStatus} from './OrderStatus'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface OrderUpdatedInterface { orderId: string status: OrderStatus @@ -121,6 +121,9 @@ class OrderUpdated { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -128,4 +131,5 @@ class OrderUpdated { } } -export { OrderUpdated, OrderUpdatedInterface }; \ No newline at end of file +export { OrderUpdated }; +export type { OrderUpdatedInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-client/src/index.ts b/examples/ecommerce-asyncapi-client/src/index.ts index e22cb77f..17dbd0bb 100644 --- a/examples/ecommerce-asyncapi-client/src/index.ts +++ b/examples/ecommerce-asyncapi-client/src/index.ts @@ -42,7 +42,7 @@ function createSampleOrder() { country: 'US', postalCode: '94102' }), - createdAt: new Date().toISOString() + createdAt: new Date() }); } @@ -94,7 +94,7 @@ class OrderService { const orderUpdate = new OrderUpdated({ orderId, status, - updatedAt: new Date().toISOString(), + updatedAt: new Date(), reason: `Order status changed to ${status}`, updatedFields: ['status'] }); @@ -115,7 +115,7 @@ class OrderService { const orderCancellation = new OrderCancelled({ orderId, reason, - cancelledAt: new Date().toISOString(), + cancelledAt: new Date(), refundAmount: new Money({ amount: 309895, // $3098.95 in cents currency: Currency.USD @@ -254,7 +254,7 @@ class DurableOrderProcessor { const updateMessage = new OrderUpdated({ orderId: order?.orderId || 'unknown', status: OrderStatus.PROCESSING, - updatedAt: new Date().toISOString(), + updatedAt: new Date(), reason: 'Order processing started by fulfillment system', updatedFields: ['status'] }); diff --git a/examples/ecommerce-asyncapi-headers/package-lock.json b/examples/ecommerce-asyncapi-headers/package-lock.json index ab2614bb..feb37ae4 100644 --- a/examples/ecommerce-asyncapi-headers/package-lock.json +++ b/examples/ecommerce-asyncapi-headers/package-lock.json @@ -8,6 +8,10 @@ "name": "ecommerce-asyncapi-headers", "version": "1.0.0", "license": "Apache-2.0", + "dependencies": { + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1" + }, "devDependencies": { "rimraf": "^5.0.5", "tsx": "^4.19.4" @@ -440,6 +444,39 @@ "node": ">=14" } }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/ansi-regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", @@ -563,6 +600,28 @@ "@esbuild/win32-x64": "0.25.5" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/foreground-child": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", @@ -655,6 +714,12 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", @@ -716,6 +781,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", diff --git a/examples/ecommerce-asyncapi-headers/package.json b/examples/ecommerce-asyncapi-headers/package.json index 78ccb60d..7a34c88e 100644 --- a/examples/ecommerce-asyncapi-headers/package.json +++ b/examples/ecommerce-asyncapi-headers/package.json @@ -8,7 +8,10 @@ "demo": "tsx src/index.ts", "clean": "rimraf src/generated" }, - "dependencies": {}, + "dependencies": { + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1" + }, "devDependencies": { "rimraf": "^5.0.5", "tsx": "^4.19.4" @@ -25,4 +28,4 @@ ], "author": "The Codegen Project", "license": "Apache-2.0" -} \ No newline at end of file +} diff --git a/examples/ecommerce-asyncapi-headers/src/generated/headers/AdminActionPerformedHeaders.ts b/examples/ecommerce-asyncapi-headers/src/generated/headers/AdminActionPerformedHeaders.ts index 51df54d1..a421e534 100644 --- a/examples/ecommerce-asyncapi-headers/src/generated/headers/AdminActionPerformedHeaders.ts +++ b/examples/ecommerce-asyncapi-headers/src/generated/headers/AdminActionPerformedHeaders.ts @@ -2,7 +2,7 @@ import {AdminActionType} from './AdminActionType'; import {PermissionLevel} from './PermissionLevel'; import {AuditLevel} from './AuditLevel'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class AdminActionPerformedHeaders { private _xCorrelationId: string; private _xTenantId: string; @@ -242,6 +242,9 @@ class AdminActionPerformedHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-headers/src/generated/headers/InventoryUpdatedHeaders.ts b/examples/ecommerce-asyncapi-headers/src/generated/headers/InventoryUpdatedHeaders.ts index 2266e5b7..8a8f3f25 100644 --- a/examples/ecommerce-asyncapi-headers/src/generated/headers/InventoryUpdatedHeaders.ts +++ b/examples/ecommerce-asyncapi-headers/src/generated/headers/InventoryUpdatedHeaders.ts @@ -1,6 +1,6 @@ import {InventoryUpdateType} from './InventoryUpdateType'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class InventoryUpdatedHeaders { private _xCorrelationId: string; private _xTenantId: string; @@ -195,6 +195,9 @@ class InventoryUpdatedHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-headers/src/generated/headers/NotificationSentHeaders.ts b/examples/ecommerce-asyncapi-headers/src/generated/headers/NotificationSentHeaders.ts index bc20b3e4..fa2f003c 100644 --- a/examples/ecommerce-asyncapi-headers/src/generated/headers/NotificationSentHeaders.ts +++ b/examples/ecommerce-asyncapi-headers/src/generated/headers/NotificationSentHeaders.ts @@ -2,7 +2,7 @@ import {NotificationType} from './NotificationType'; import {NotificationChannel} from './NotificationChannel'; import {NotificationProvider} from './NotificationProvider'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class NotificationSentHeaders { private _xCorrelationId: string; private _xTenantId: string; @@ -212,6 +212,9 @@ class NotificationSentHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-headers/src/generated/headers/OrderCreatedHeaders.ts b/examples/ecommerce-asyncapi-headers/src/generated/headers/OrderCreatedHeaders.ts index e7af1f98..1256bc8a 100644 --- a/examples/ecommerce-asyncapi-headers/src/generated/headers/OrderCreatedHeaders.ts +++ b/examples/ecommerce-asyncapi-headers/src/generated/headers/OrderCreatedHeaders.ts @@ -1,6 +1,6 @@ import {SourceService} from './SourceService'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class OrderCreatedHeaders { private _xCorrelationId: string; private _xTenantId: string; @@ -180,6 +180,9 @@ class OrderCreatedHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-headers/src/generated/headers/OrderEventsHeaders.ts b/examples/ecommerce-asyncapi-headers/src/generated/headers/OrderEventsHeaders.ts index adac64e3..298ccb20 100644 --- a/examples/ecommerce-asyncapi-headers/src/generated/headers/OrderEventsHeaders.ts +++ b/examples/ecommerce-asyncapi-headers/src/generated/headers/OrderEventsHeaders.ts @@ -1,4 +1,55 @@ import {OrderCreatedHeaders} from './OrderCreatedHeaders'; import {OrderStatusChangedHeaders} from './OrderStatusChangedHeaders'; +import {SourceService} from './SourceService'; +import {ActorType} from './ActorType'; +import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; +import addFormatsModule from 'ajv-formats'; type OrderEventsHeaders = OrderCreatedHeaders | OrderStatusChangedHeaders; + +export function unmarshal(json: any): OrderEventsHeaders { + if(typeof json === 'object') { + if(json.x-source-service === SourceService.WEB_MINUS_APP) { + return OrderCreatedHeaders.unmarshal(json); + } + if(json.x-actor-type === ActorType.USER) { + return OrderStatusChangedHeaders.unmarshal(json); + } + } + return JSON.parse(json); +} +export function marshal(payload: OrderEventsHeaders) { + if(payload instanceof OrderCreatedHeaders) { +return payload.marshal(); +} +if(payload instanceof OrderStatusChangedHeaders) { +return payload.marshal(); +} + return JSON.stringify(payload); +} + +export const theCodeGenSchema = {"$id":"OrderEventsHeaders","$schema":"http://json-schema.org/draft-07/schema","oneOf":[{"type":"object","allOf":[{"type":"object","required":["x-correlation-id","x-tenant-id"],"properties":{"x-correlation-id":{"type":"string","format":"uuid","description":"Unique correlation ID for request tracing"},"x-tenant-id":{"type":"string","description":"Multi-tenant identifier"},"x-timestamp":{"type":"string","format":"date-time","description":"Event creation timestamp"}}},{"type":"object","properties":{"authorization":{"type":"string","pattern":"^Bearer [A-Za-z0-9\\-\\._~\\+\\/]+=*$","description":"JWT token for authentication"}}},{"type":"object","properties":{"x-source-service":{"type":"string","enum":["web-app","mobile-app","admin-panel"],"description":"Service that originated the event"},"x-api-version":{"type":"string","pattern":"^v[0-9]+$","description":"API version used","default":"v1"},"x-request-id":{"type":"string","format":"uuid","description":"Original request ID from the client"}}},{"type":"object","required":["x-user-id"],"properties":{"x-user-id":{"type":"string","format":"uuid","description":"ID of the user who created the order"}}}],"$id":"OrderCreatedHeaders","$schema":"http://json-schema.org/draft-07/schema"},{"type":"object","allOf":[{"type":"object","required":["x-correlation-id","x-tenant-id"],"properties":{"x-correlation-id":{"type":"string","format":"uuid","description":"Unique correlation ID for request tracing"},"x-tenant-id":{"type":"string","description":"Multi-tenant identifier"},"x-timestamp":{"type":"string","format":"date-time","description":"Event creation timestamp"}}},{"type":"object","properties":{"x-actor-id":{"type":"string","format":"uuid","description":"ID of user/system that triggered the change"},"x-actor-type":{"type":"string","enum":["user","system","admin"],"description":"Type of actor that triggered the change"}}},{"type":"object","required":["x-event-type"],"properties":{"x-event-type":{"type":"string","enum":["status-change","cancellation","refund"],"description":"Type of status change event"},"x-previous-status":{"type":"string","enum":["pending","confirmed","processing","shipped","delivered","cancelled"],"description":"Order status values"},"x-reason-code":{"type":"string","enum":["customer-request","payment-failed","inventory-unavailable","fraud-detected"],"description":"Reason code for status change"},"x-priority":{"type":"string","enum":["low","normal","high","urgent"],"default":"normal","description":"Processing priority"}}}],"$id":"OrderStatusChangedHeaders","$schema":"http://json-schema.org/draft-07/schema"}]}; +export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFunction, ajvInstance?: Ajv, ajvOptions?: AjvOptions}): { valid: boolean; errors?: ErrorObject[]; } { + const {data, ajvValidatorFunction} = context ?? {}; + // Intentionally parse JSON strings to support validation of marshalled output. + // Example: validate({data: marshal(obj)}) works because marshal returns JSON string. + // Note: String 'true' will be coerced to boolean true due to JSON.parse. + const parsedData = typeof data === 'string' ? JSON.parse(data) : data; + const validate = ajvValidatorFunction ?? createValidator(context) + return { + valid: validate(parsedData), + errors: validate.errors ?? undefined, + }; +} +export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { + const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; + addFormats(ajvInstance); + + const validate = ajvInstance.compile(theCodeGenSchema); + return validate; +} + + export { OrderEventsHeaders }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-headers/src/generated/headers/OrderStatusChangedHeaders.ts b/examples/ecommerce-asyncapi-headers/src/generated/headers/OrderStatusChangedHeaders.ts index fef8a7dc..76465d57 100644 --- a/examples/ecommerce-asyncapi-headers/src/generated/headers/OrderStatusChangedHeaders.ts +++ b/examples/ecommerce-asyncapi-headers/src/generated/headers/OrderStatusChangedHeaders.ts @@ -4,7 +4,7 @@ import {OrderStatus} from './OrderStatus'; import {OrderReasonCode} from './OrderReasonCode'; import {Priority} from './Priority'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class OrderStatusChangedHeaders { private _xCorrelationId: string; private _xTenantId: string; @@ -199,6 +199,9 @@ class OrderStatusChangedHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-headers/src/generated/headers/PaymentProcessedHeaders.ts b/examples/ecommerce-asyncapi-headers/src/generated/headers/PaymentProcessedHeaders.ts index d77d4d96..5cbd7acd 100644 --- a/examples/ecommerce-asyncapi-headers/src/generated/headers/PaymentProcessedHeaders.ts +++ b/examples/ecommerce-asyncapi-headers/src/generated/headers/PaymentProcessedHeaders.ts @@ -1,7 +1,7 @@ import {PaymentProvider} from './PaymentProvider'; import {PaymentMethod} from './PaymentMethod'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class PaymentProcessedHeaders { private _xCorrelationId: string; private _xTenantId: string; @@ -226,6 +226,9 @@ class PaymentProcessedHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-headers/src/generated/headers/UserBehaviorTrackedHeaders.ts b/examples/ecommerce-asyncapi-headers/src/generated/headers/UserBehaviorTrackedHeaders.ts index 632d9bce..6404e533 100644 --- a/examples/ecommerce-asyncapi-headers/src/generated/headers/UserBehaviorTrackedHeaders.ts +++ b/examples/ecommerce-asyncapi-headers/src/generated/headers/UserBehaviorTrackedHeaders.ts @@ -1,7 +1,7 @@ import {DeviceType} from './DeviceType'; import {Platform} from './Platform'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class UserBehaviorTrackedHeaders { private _xCorrelationId: string; private _xTenantId: string; @@ -226,6 +226,9 @@ class UserBehaviorTrackedHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-parameters/src/generated/parameters/InventoryUpdatesParameters.ts b/examples/ecommerce-asyncapi-parameters/src/generated/parameters/InventoryUpdatesParameters.ts index bf46ff76..134ada0b 100644 --- a/examples/ecommerce-asyncapi-parameters/src/generated/parameters/InventoryUpdatesParameters.ts +++ b/examples/ecommerce-asyncapi-parameters/src/generated/parameters/InventoryUpdatesParameters.ts @@ -77,4 +77,5 @@ class InventoryUpdatesParameters { return parameters; } } -export { InventoryUpdatesParameters, InventoryUpdatesParametersInterface }; \ No newline at end of file +export { InventoryUpdatesParameters }; +export type { InventoryUpdatesParametersInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-parameters/src/generated/parameters/OrderEventsParameters.ts b/examples/ecommerce-asyncapi-parameters/src/generated/parameters/OrderEventsParameters.ts index 586a432d..8d17514b 100644 --- a/examples/ecommerce-asyncapi-parameters/src/generated/parameters/OrderEventsParameters.ts +++ b/examples/ecommerce-asyncapi-parameters/src/generated/parameters/OrderEventsParameters.ts @@ -59,4 +59,5 @@ class OrderEventsParameters { return parameters; } } -export { OrderEventsParameters, OrderEventsParametersInterface }; \ No newline at end of file +export { OrderEventsParameters }; +export type { OrderEventsParametersInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-parameters/src/generated/parameters/ProductUpdatesParameters.ts b/examples/ecommerce-asyncapi-parameters/src/generated/parameters/ProductUpdatesParameters.ts index 0880f726..9d0527d8 100644 --- a/examples/ecommerce-asyncapi-parameters/src/generated/parameters/ProductUpdatesParameters.ts +++ b/examples/ecommerce-asyncapi-parameters/src/generated/parameters/ProductUpdatesParameters.ts @@ -59,4 +59,5 @@ class ProductUpdatesParameters { return parameters; } } -export { ProductUpdatesParameters, ProductUpdatesParametersInterface }; \ No newline at end of file +export { ProductUpdatesParameters }; +export type { ProductUpdatesParametersInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-parameters/src/generated/parameters/SupportTicketsParameters.ts b/examples/ecommerce-asyncapi-parameters/src/generated/parameters/SupportTicketsParameters.ts index 4bbeb8da..31cbf381 100644 --- a/examples/ecommerce-asyncapi-parameters/src/generated/parameters/SupportTicketsParameters.ts +++ b/examples/ecommerce-asyncapi-parameters/src/generated/parameters/SupportTicketsParameters.ts @@ -76,4 +76,5 @@ class SupportTicketsParameters { return parameters; } } -export { SupportTicketsParameters, SupportTicketsParametersInterface }; \ No newline at end of file +export { SupportTicketsParameters }; +export type { SupportTicketsParametersInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-parameters/src/generated/parameters/TenantAnalyticsParameters.ts b/examples/ecommerce-asyncapi-parameters/src/generated/parameters/TenantAnalyticsParameters.ts index fa046f88..861742b3 100644 --- a/examples/ecommerce-asyncapi-parameters/src/generated/parameters/TenantAnalyticsParameters.ts +++ b/examples/ecommerce-asyncapi-parameters/src/generated/parameters/TenantAnalyticsParameters.ts @@ -93,4 +93,5 @@ class TenantAnalyticsParameters { return parameters; } } -export { TenantAnalyticsParameters, TenantAnalyticsParametersInterface }; \ No newline at end of file +export { TenantAnalyticsParameters }; +export type { TenantAnalyticsParametersInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-parameters/src/generated/parameters/UserActivityParameters.ts b/examples/ecommerce-asyncapi-parameters/src/generated/parameters/UserActivityParameters.ts index 05dbf459..24d8084e 100644 --- a/examples/ecommerce-asyncapi-parameters/src/generated/parameters/UserActivityParameters.ts +++ b/examples/ecommerce-asyncapi-parameters/src/generated/parameters/UserActivityParameters.ts @@ -43,4 +43,5 @@ class UserActivityParameters { return parameters; } } -export { UserActivityParameters, UserActivityParametersInterface }; \ No newline at end of file +export { UserActivityParameters }; +export type { UserActivityParametersInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-parameters/src/generated/parameters/UserNotificationsParameters.ts b/examples/ecommerce-asyncapi-parameters/src/generated/parameters/UserNotificationsParameters.ts index 66eaef18..b7d31b13 100644 --- a/examples/ecommerce-asyncapi-parameters/src/generated/parameters/UserNotificationsParameters.ts +++ b/examples/ecommerce-asyncapi-parameters/src/generated/parameters/UserNotificationsParameters.ts @@ -76,4 +76,5 @@ class UserNotificationsParameters { return parameters; } } -export { UserNotificationsParameters, UserNotificationsParametersInterface }; \ No newline at end of file +export { UserNotificationsParameters }; +export type { UserNotificationsParametersInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-payload/src/generated/models/Address.ts b/examples/ecommerce-asyncapi-payload/src/generated/models/Address.ts index 2d3d7393..8f89bc0d 100644 --- a/examples/ecommerce-asyncapi-payload/src/generated/models/Address.ts +++ b/examples/ecommerce-asyncapi-payload/src/generated/models/Address.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface AddressInterface { street: string city: string @@ -123,6 +123,9 @@ class Address { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -130,4 +133,5 @@ class Address { } } -export { Address, AddressInterface }; \ No newline at end of file +export { Address }; +export type { AddressInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-payload/src/generated/models/Attachment.ts b/examples/ecommerce-asyncapi-payload/src/generated/models/Attachment.ts index b2665eca..2ea711de 100644 --- a/examples/ecommerce-asyncapi-payload/src/generated/models/Attachment.ts +++ b/examples/ecommerce-asyncapi-payload/src/generated/models/Attachment.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface AttachmentInterface { filename?: string contentType?: string @@ -96,6 +96,9 @@ class Attachment { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -103,4 +106,5 @@ class Attachment { } } -export { Attachment, AttachmentInterface }; \ No newline at end of file +export { Attachment }; +export type { AttachmentInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-payload/src/generated/models/EmailNotification.ts b/examples/ecommerce-asyncapi-payload/src/generated/models/EmailNotification.ts index 59ba2f39..3c7b4626 100644 --- a/examples/ecommerce-asyncapi-payload/src/generated/models/EmailNotification.ts +++ b/examples/ecommerce-asyncapi-payload/src/generated/models/EmailNotification.ts @@ -1,6 +1,6 @@ import {Attachment} from './Attachment'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface EmailNotificationInterface { recipientId: string subject: string @@ -121,6 +121,9 @@ class EmailNotification { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -128,4 +131,5 @@ class EmailNotification { } } -export { EmailNotification, EmailNotificationInterface }; \ No newline at end of file +export { EmailNotification }; +export type { EmailNotificationInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-payload/src/generated/models/NotificationSent.ts b/examples/ecommerce-asyncapi-payload/src/generated/models/NotificationSent.ts index fc6dd656..7b6ece2e 100644 --- a/examples/ecommerce-asyncapi-payload/src/generated/models/NotificationSent.ts +++ b/examples/ecommerce-asyncapi-payload/src/generated/models/NotificationSent.ts @@ -2,7 +2,7 @@ import {EmailNotification} from './EmailNotification'; import {SmsNotification} from './SmsNotification'; import {PushNotification} from './PushNotification'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type NotificationSent = EmailNotification | SmsNotification | PushNotification; export function unmarshal(json: any): NotificationSent { @@ -47,6 +47,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-payload/src/generated/models/OrderCreated.ts b/examples/ecommerce-asyncapi-payload/src/generated/models/OrderCreated.ts index 04731593..c24f9532 100644 --- a/examples/ecommerce-asyncapi-payload/src/generated/models/OrderCreated.ts +++ b/examples/ecommerce-asyncapi-payload/src/generated/models/OrderCreated.ts @@ -2,7 +2,7 @@ import {OrderItem} from './OrderItem'; import {Currency} from './Currency'; import {Address} from './Address'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface OrderCreatedInterface { orderId: string customerId: string @@ -172,6 +172,9 @@ class OrderCreated { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -179,4 +182,5 @@ class OrderCreated { } } -export { OrderCreated, OrderCreatedInterface }; \ No newline at end of file +export { OrderCreated }; +export type { OrderCreatedInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-payload/src/generated/models/OrderEventsPayload.ts b/examples/ecommerce-asyncapi-payload/src/generated/models/OrderEventsPayload.ts index 8eef81a2..f2c05843 100644 --- a/examples/ecommerce-asyncapi-payload/src/generated/models/OrderEventsPayload.ts +++ b/examples/ecommerce-asyncapi-payload/src/generated/models/OrderEventsPayload.ts @@ -3,7 +3,7 @@ import {OrderStatusChanged} from './OrderStatusChanged'; import {Currency} from './Currency'; import {OrderStatus} from './OrderStatus'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type OrderEventsPayload = OrderCreated | OrderStatusChanged; export function unmarshal(json: any): OrderEventsPayload { @@ -42,6 +42,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/examples/ecommerce-asyncapi-payload/src/generated/models/OrderItem.ts b/examples/ecommerce-asyncapi-payload/src/generated/models/OrderItem.ts index 43ec4a96..c3d10889 100644 --- a/examples/ecommerce-asyncapi-payload/src/generated/models/OrderItem.ts +++ b/examples/ecommerce-asyncapi-payload/src/generated/models/OrderItem.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface OrderItemInterface { productId: string quantity: number @@ -126,6 +126,9 @@ class OrderItem { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -133,4 +136,5 @@ class OrderItem { } } -export { OrderItem, OrderItemInterface }; \ No newline at end of file +export { OrderItem }; +export type { OrderItemInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-payload/src/generated/models/OrderStatusChanged.ts b/examples/ecommerce-asyncapi-payload/src/generated/models/OrderStatusChanged.ts index e5c9cbe3..e7673e9a 100644 --- a/examples/ecommerce-asyncapi-payload/src/generated/models/OrderStatusChanged.ts +++ b/examples/ecommerce-asyncapi-payload/src/generated/models/OrderStatusChanged.ts @@ -1,6 +1,6 @@ import {OrderStatus} from './OrderStatus'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface OrderStatusChangedInterface { orderId: string previousStatus: OrderStatus @@ -124,6 +124,9 @@ class OrderStatusChanged { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -131,4 +134,5 @@ class OrderStatusChanged { } } -export { OrderStatusChanged, OrderStatusChangedInterface }; \ No newline at end of file +export { OrderStatusChanged }; +export type { OrderStatusChangedInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-payload/src/generated/models/PaymentProcessed.ts b/examples/ecommerce-asyncapi-payload/src/generated/models/PaymentProcessed.ts index d1b45ae6..beb6219d 100644 --- a/examples/ecommerce-asyncapi-payload/src/generated/models/PaymentProcessed.ts +++ b/examples/ecommerce-asyncapi-payload/src/generated/models/PaymentProcessed.ts @@ -1,7 +1,7 @@ import {Currency} from './Currency'; import {PaymentStatus} from './PaymentStatus'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface PaymentProcessedInterface { paymentId: string orderId: string @@ -149,6 +149,9 @@ class PaymentProcessed { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -156,4 +159,5 @@ class PaymentProcessed { } } -export { PaymentProcessed, PaymentProcessedInterface }; \ No newline at end of file +export { PaymentProcessed }; +export type { PaymentProcessedInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-payload/src/generated/models/PushNotification.ts b/examples/ecommerce-asyncapi-payload/src/generated/models/PushNotification.ts index 096ccb15..842a2d47 100644 --- a/examples/ecommerce-asyncapi-payload/src/generated/models/PushNotification.ts +++ b/examples/ecommerce-asyncapi-payload/src/generated/models/PushNotification.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface PushNotificationInterface { recipientId: string title: string @@ -114,6 +114,9 @@ class PushNotification { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -121,4 +124,5 @@ class PushNotification { } } -export { PushNotification, PushNotificationInterface }; \ No newline at end of file +export { PushNotification }; +export type { PushNotificationInterface }; \ No newline at end of file diff --git a/examples/ecommerce-asyncapi-payload/src/generated/models/SmsNotification.ts b/examples/ecommerce-asyncapi-payload/src/generated/models/SmsNotification.ts index 82a471aa..7f7dd321 100644 --- a/examples/ecommerce-asyncapi-payload/src/generated/models/SmsNotification.ts +++ b/examples/ecommerce-asyncapi-payload/src/generated/models/SmsNotification.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface SmsNotificationInterface { recipientId: string message: string @@ -90,6 +90,9 @@ class SmsNotification { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -97,4 +100,5 @@ class SmsNotification { } } -export { SmsNotification, SmsNotificationInterface }; \ No newline at end of file +export { SmsNotification }; +export type { SmsNotificationInterface }; \ No newline at end of file diff --git a/examples/openapi-http-client/src/generated/parameter/GetV2ConnectReferenceIdParameters.ts b/examples/openapi-http-client/src/generated/parameter/GetV2ConnectReferenceIdParameters.ts index 7a73074a..43fd94be 100644 --- a/examples/openapi-http-client/src/generated/parameter/GetV2ConnectReferenceIdParameters.ts +++ b/examples/openapi-http-client/src/generated/parameter/GetV2ConnectReferenceIdParameters.ts @@ -118,4 +118,5 @@ class GetV2ConnectReferenceIdParameters { return result; } } -export { GetV2ConnectReferenceIdParameters, GetV2ConnectReferenceIdParametersInterface }; \ No newline at end of file +export { GetV2ConnectReferenceIdParameters }; +export type { GetV2ConnectReferenceIdParametersInterface }; \ No newline at end of file diff --git a/examples/openapi-http-client/src/generated/parameter/GetV2UsersSafepayAccountIdBankAccountsParameters.ts b/examples/openapi-http-client/src/generated/parameter/GetV2UsersSafepayAccountIdBankAccountsParameters.ts index 971de2cb..b6bcf988 100644 --- a/examples/openapi-http-client/src/generated/parameter/GetV2UsersSafepayAccountIdBankAccountsParameters.ts +++ b/examples/openapi-http-client/src/generated/parameter/GetV2UsersSafepayAccountIdBankAccountsParameters.ts @@ -118,4 +118,5 @@ class GetV2UsersSafepayAccountIdBankAccountsParameters { return result; } } -export { GetV2UsersSafepayAccountIdBankAccountsParameters, GetV2UsersSafepayAccountIdBankAccountsParametersInterface }; \ No newline at end of file +export { GetV2UsersSafepayAccountIdBankAccountsParameters }; +export type { GetV2UsersSafepayAccountIdBankAccountsParametersInterface }; \ No newline at end of file diff --git a/examples/openapi-http-client/src/generated/payload/BankAccount.ts b/examples/openapi-http-client/src/generated/payload/BankAccount.ts index 7a5a699f..0e604d38 100644 --- a/examples/openapi-http-client/src/generated/payload/BankAccount.ts +++ b/examples/openapi-http-client/src/generated/payload/BankAccount.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface BankAccountInterface { id?: string iban?: string @@ -96,6 +96,9 @@ class BankAccount { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -103,4 +106,5 @@ class BankAccount { } } -export { BankAccount, BankAccountInterface }; \ No newline at end of file +export { BankAccount }; +export type { BankAccountInterface }; \ No newline at end of file diff --git a/examples/openapi-http-client/src/generated/payload/GetConnectModel.ts b/examples/openapi-http-client/src/generated/payload/GetConnectModel.ts index 4b973dd0..518b5a9b 100644 --- a/examples/openapi-http-client/src/generated/payload/GetConnectModel.ts +++ b/examples/openapi-http-client/src/generated/payload/GetConnectModel.ts @@ -1,6 +1,6 @@ import {Status} from './Status'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface GetConnectModelInterface { referenceId?: string safepayAccountId?: string @@ -97,6 +97,9 @@ class GetConnectModel { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -104,4 +107,5 @@ class GetConnectModel { } } -export { GetConnectModel, GetConnectModelInterface }; \ No newline at end of file +export { GetConnectModel }; +export type { GetConnectModelInterface }; \ No newline at end of file diff --git a/examples/openapi-http-client/src/generated/payload/GetV2ConnectReferenceIdResponse_200.ts b/examples/openapi-http-client/src/generated/payload/GetV2ConnectReferenceIdResponse_200.ts index f1b9bf12..5c1035df 100644 --- a/examples/openapi-http-client/src/generated/payload/GetV2ConnectReferenceIdResponse_200.ts +++ b/examples/openapi-http-client/src/generated/payload/GetV2ConnectReferenceIdResponse_200.ts @@ -1,6 +1,6 @@ import {Status} from './Status'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface GetV2ConnectReferenceIdResponse_200Interface { referenceId?: string safepayAccountId?: string @@ -97,6 +97,9 @@ class GetV2ConnectReferenceIdResponse_200 { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -104,4 +107,5 @@ class GetV2ConnectReferenceIdResponse_200 { } } -export { GetV2ConnectReferenceIdResponse_200, GetV2ConnectReferenceIdResponse_200Interface }; \ No newline at end of file +export { GetV2ConnectReferenceIdResponse_200 }; +export type { GetV2ConnectReferenceIdResponse_200Interface }; \ No newline at end of file diff --git a/examples/openapi-http-client/src/generated/payload/GetV2UsersSafepayAccountIdBankAccountsResponse_200.ts b/examples/openapi-http-client/src/generated/payload/GetV2UsersSafepayAccountIdBankAccountsResponse_200.ts index 80cb4534..bd065a4d 100644 --- a/examples/openapi-http-client/src/generated/payload/GetV2UsersSafepayAccountIdBankAccountsResponse_200.ts +++ b/examples/openapi-http-client/src/generated/payload/GetV2UsersSafepayAccountIdBankAccountsResponse_200.ts @@ -1,6 +1,6 @@ import {BankAccount} from './BankAccount'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface GetV2UsersSafepayAccountIdBankAccountsResponse_200Interface { bankAccounts?: BankAccount[] additionalProperties?: Record @@ -79,6 +79,9 @@ class GetV2UsersSafepayAccountIdBankAccountsResponse_200 { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -86,4 +89,5 @@ class GetV2UsersSafepayAccountIdBankAccountsResponse_200 { } } -export { GetV2UsersSafepayAccountIdBankAccountsResponse_200, GetV2UsersSafepayAccountIdBankAccountsResponse_200Interface }; \ No newline at end of file +export { GetV2UsersSafepayAccountIdBankAccountsResponse_200 }; +export type { GetV2UsersSafepayAccountIdBankAccountsResponse_200Interface }; \ No newline at end of file diff --git a/examples/openapi-http-client/src/generated/payload/InitializeModel.ts b/examples/openapi-http-client/src/generated/payload/InitializeModel.ts index dce7b9c9..e2bea5cf 100644 --- a/examples/openapi-http-client/src/generated/payload/InitializeModel.ts +++ b/examples/openapi-http-client/src/generated/payload/InitializeModel.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface InitializeModelInterface { referenceId?: string connectUrl?: string @@ -84,6 +84,9 @@ class InitializeModel { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -91,4 +94,5 @@ class InitializeModel { } } -export { InitializeModel, InitializeModelInterface }; \ No newline at end of file +export { InitializeModel }; +export type { InitializeModelInterface }; \ No newline at end of file diff --git a/examples/openapi-http-client/src/generated/payload/InitializeRequest.ts b/examples/openapi-http-client/src/generated/payload/InitializeRequest.ts index af34d425..09cc1282 100644 --- a/examples/openapi-http-client/src/generated/payload/InitializeRequest.ts +++ b/examples/openapi-http-client/src/generated/payload/InitializeRequest.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface InitializeRequestInterface { returnUrl: string skipKyc?: boolean @@ -84,6 +84,9 @@ class InitializeRequest { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -91,4 +94,5 @@ class InitializeRequest { } } -export { InitializeRequest, InitializeRequestInterface }; \ No newline at end of file +export { InitializeRequest }; +export type { InitializeRequestInterface }; \ No newline at end of file diff --git a/examples/openapi-http-client/src/generated/payload/PostV2ConnectRequest.ts b/examples/openapi-http-client/src/generated/payload/PostV2ConnectRequest.ts index e2caea1b..61c66c1d 100644 --- a/examples/openapi-http-client/src/generated/payload/PostV2ConnectRequest.ts +++ b/examples/openapi-http-client/src/generated/payload/PostV2ConnectRequest.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface PostV2ConnectRequestInterface { returnUrl: string skipKyc?: boolean @@ -84,6 +84,9 @@ class PostV2ConnectRequest { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -91,4 +94,5 @@ class PostV2ConnectRequest { } } -export { PostV2ConnectRequest, PostV2ConnectRequestInterface }; \ No newline at end of file +export { PostV2ConnectRequest }; +export type { PostV2ConnectRequestInterface }; \ No newline at end of file diff --git a/examples/openapi-http-client/src/generated/payload/PostV2ConnectResponse_200.ts b/examples/openapi-http-client/src/generated/payload/PostV2ConnectResponse_200.ts index a2e05fbc..93fb84eb 100644 --- a/examples/openapi-http-client/src/generated/payload/PostV2ConnectResponse_200.ts +++ b/examples/openapi-http-client/src/generated/payload/PostV2ConnectResponse_200.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface PostV2ConnectResponse_200Interface { referenceId?: string connectUrl?: string @@ -84,6 +84,9 @@ class PostV2ConnectResponse_200 { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -91,4 +94,5 @@ class PostV2ConnectResponse_200 { } } -export { PostV2ConnectResponse_200, PostV2ConnectResponse_200Interface }; \ No newline at end of file +export { PostV2ConnectResponse_200 }; +export type { PostV2ConnectResponse_200Interface }; \ No newline at end of file diff --git a/examples/typescript-library/package-lock.json b/examples/typescript-library/package-lock.json index 8d2296c4..80af52ba 100644 --- a/examples/typescript-library/package-lock.json +++ b/examples/typescript-library/package-lock.json @@ -8,6 +8,10 @@ "name": "typescript-library", "version": "1.0.0", "license": "Apache-2.0", + "dependencies": { + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1" + }, "devDependencies": { "@the-codegen-project/cli": "^0", "rimraf": "5.0.5", @@ -17,26 +21,34 @@ }, "../..": { "name": "@the-codegen-project/cli", - "version": "0.7.0", + "version": "0.80.0", "dev": true, "license": "Apache-2.0", "dependencies": { - "@asyncapi/avro-schema-parser": "^3.0.22", - "@asyncapi/modelina": "^4.0.0-next.35", - "@asyncapi/openapi-schema-parser": "^3.0.22", - "@asyncapi/parser": "^3.0.14", - "@asyncapi/protobuf-schema-parser": "^3.2.12", - "@asyncapi/raml-dt-schema-parser": "^4.0.22", + "@apidevtools/json-schema-ref-parser": "^14.2.0", + "@asyncapi/avro-schema-parser": "^3.0.24", + "@asyncapi/modelina": "^6.0.0-next.14", + "@asyncapi/openapi-schema-parser": "^3.0.24", + "@asyncapi/parser": "^3.6.0", + "@asyncapi/protobuf-schema-parser": "^3.5.1", + "@asyncapi/raml-dt-schema-parser": "^4.0.24", "@oclif/core": "^3.26.3", "@oclif/errors": "^1.3.6", - "@oclif/plugin-autocomplete": "^3.0.16", + "@oclif/plugin-autocomplete": "^3.2.45", "@oclif/plugin-help": "^6.0.21", "@oclif/plugin-version": "^2.0.17", - "graphology": "^0.25.4", + "@readme/openapi-parser": "^5.0.1", + "chokidar": "^4.0.3", + "comment-json": "^4.6.2", + "cosmiconfig": "^9.0.0", + "graphology": "^0.26.0", "inquirer": "^8.2.6", - "supports-esm": "1.0.0", - "yaml": "^2.4.5", - "zod": "^3.23.8" + "openapi-types": "^12.1.3", + "picocolors": "^1.1.1", + "uuid": "^11.1.0", + "yaml": "^2.8.0", + "zod": "^3.25.76", + "zod-validation-error": "^3.3.0" }, "bin": { "codegen": "bin/run.mjs" @@ -48,19 +60,24 @@ "@swc/jest": "^0.2.23", "@types/inquirer": "^9.0.7", "@types/jest": "^29.5.12", - "@types/node": "^18", + "@types/node": "^22", "@types/rimraf": "^4.0.5", - "@typescript-eslint/eslint-plugin": "^6.7.5", - "@typescript-eslint/parser": "^6.7.5", + "@types/uuid": "^10.0.0", + "@typescript-eslint/eslint-plugin": "^8.58.0", + "@typescript-eslint/parser": "^8.58.0", + "concurrently": "^9.0.1", + "esbuild": "^0.20.2", + "esbuild-plugin-polyfill-node": "^0.3.0", "eslint": "^8.51.0", "eslint-config-prettier": "9.0.0", "eslint-plugin-github": "^4.10.1", - "eslint-plugin-jest": "^27.2.1", + "eslint-plugin-jest": "^29.15.1", "eslint-plugin-prettier": "^5.0.1", - "eslint-plugin-security": "^1.7.1", + "eslint-plugin-security": "^4.0.0", "eslint-plugin-sonarjs": "^0.19.0", - "eslint-plugin-unused-imports": "^3.0.0", + "eslint-plugin-unused-imports": "^4.4.1", "graphology-types": "^0.24.7", + "lodash-es": "^4.18.1", "markdown-toc": "1.2.0", "oclif": "^4.8.5", "rimraf": "^5.0.5", @@ -68,10 +85,10 @@ "ts-jest": "^29.1.3", "ts-node": "^10.9.2", "typescript": "^5.4.5", - "zod-to-json-schema": "^3.23.0" + "zod-to-json-schema": "^3.25.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=22.0.0" } }, "node_modules/@cspotcode/source-map-support": { @@ -200,6 +217,39 @@ "node": ">=0.4.0" } }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", @@ -304,6 +354,28 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -375,6 +447,12 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, "node_modules/lru-cache": { "version": "10.2.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", @@ -439,6 +517,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/rimraf": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", diff --git a/examples/typescript-library/package.json b/examples/typescript-library/package.json index e713b6d0..0a8726c5 100644 --- a/examples/typescript-library/package.json +++ b/examples/typescript-library/package.json @@ -9,10 +9,14 @@ "dev": "codegen generate --watch" }, "license": "Apache-2.0", + "dependencies": { + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1" + }, "devDependencies": { "typescript": "5.4.5", "rimraf": "5.0.5", "@the-codegen-project/cli": "^0", "ts-node": "10.9.2" } -} \ No newline at end of file +} diff --git a/examples/typescript-library/src/__gen__/payloads/UserSignedUp.ts b/examples/typescript-library/src/__gen__/payloads/UserSignedUp.ts index ce77fc5e..2d521c70 100644 --- a/examples/typescript-library/src/__gen__/payloads/UserSignedUp.ts +++ b/examples/typescript-library/src/__gen__/payloads/UserSignedUp.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface UserSignedUpInterface { displayName?: string email?: string @@ -90,6 +90,9 @@ class UserSignedUp { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -97,4 +100,5 @@ class UserSignedUp { } } -export { UserSignedUp, UserSignedUpInterface }; \ No newline at end of file +export { UserSignedUp }; +export type { UserSignedUpInterface }; \ No newline at end of file diff --git a/examples/typescript-nextjs/package-lock.json b/examples/typescript-nextjs/package-lock.json index 19389220..68954a1f 100644 --- a/examples/typescript-nextjs/package-lock.json +++ b/examples/typescript-nextjs/package-lock.json @@ -9,6 +9,8 @@ "version": "0.1.0", "dependencies": { "@t3-oss/env-nextjs": "^0.10.1", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", "geist": "^1.3.0", "next": "^14.2.1", "react": "^18.3.0", @@ -89,22 +91,6 @@ "js-yaml": "^3.13.1" } }, - "node_modules/@apidevtools/swagger-parser/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@apidevtools/swagger-parser/node_modules/ajv-draft-04": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", @@ -141,12 +127,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@apidevtools/swagger-parser/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/@asyncapi/avro-schema-parser": { "version": "3.0.24", "resolved": "https://registry.npmjs.org/@asyncapi/avro-schema-parser/-/avro-schema-parser-3.0.24.tgz", @@ -195,22 +175,6 @@ "ajv-formats": "^2.1.1" } }, - "node_modules/@asyncapi/openapi-schema-parser/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@asyncapi/openapi-schema-parser/node_modules/ajv-errors": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", @@ -220,11 +184,23 @@ "ajv": "^8.0.1" } }, - "node_modules/@asyncapi/openapi-schema-parser/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "node_modules/@asyncapi/openapi-schema-parser/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } }, "node_modules/@asyncapi/parser": { "version": "3.1.0", @@ -253,22 +229,6 @@ "node-fetch": "2.6.7" } }, - "node_modules/@asyncapi/parser/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@asyncapi/parser/node_modules/ajv-errors": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", @@ -278,11 +238,23 @@ "ajv": "^8.0.1" } }, - "node_modules/@asyncapi/parser/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "node_modules/@asyncapi/parser/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } }, "node_modules/@asyncapi/protobuf-schema-parser": { "version": "3.2.14", @@ -391,6 +363,23 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1749,22 +1738,6 @@ "node": "^12.20 || >=14.13" } }, - "node_modules/@stoplight/spectral-core/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@stoplight/spectral-core/node_modules/ajv-errors": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", @@ -1774,6 +1747,24 @@ "ajv": "^8.0.1" } }, + "node_modules/@stoplight/spectral-core/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/@stoplight/spectral-core/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1784,12 +1775,6 @@ "concat-map": "0.0.1" } }, - "node_modules/@stoplight/spectral-core/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, "node_modules/@stoplight/spectral-core/node_modules/jsonpath-plus": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-7.1.0.tgz", @@ -1864,22 +1849,6 @@ "ajv": ">=8" } }, - "node_modules/@stoplight/spectral-functions/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@stoplight/spectral-functions/node_modules/ajv-draft-04": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", @@ -1903,11 +1872,23 @@ "ajv": "^8.0.1" } }, - "node_modules/@stoplight/spectral-functions/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "node_modules/@stoplight/spectral-functions/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } }, "node_modules/@stoplight/spectral-parsers": { "version": "1.0.4", @@ -2749,16 +2730,15 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -2766,10 +2746,10 @@ } }, "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", "dependencies": { "ajv": "^8.0.0" }, @@ -2782,27 +2762,11 @@ } } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "node_modules/ajv/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "license": "MIT" }, "node_modules/alterschema": { "version": "1.1.3", @@ -4593,6 +4557,23 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -4716,7 +4697,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-glob": { @@ -4769,6 +4749,22 @@ "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==", "dev": true }, + "node_modules/fast-uri": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fastest-stable-stringify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz", @@ -9342,22 +9338,6 @@ "@types/json-schema": "^7.0.11" } }, - "node_modules/parserapiv1/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/parserapiv1/node_modules/ajv-errors": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", @@ -9367,11 +9347,23 @@ "ajv": "^8.0.1" } }, - "node_modules/parserapiv1/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "node_modules/parserapiv1/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } }, "node_modules/parserapiv2": { "name": "@asyncapi/parser", @@ -9399,22 +9391,6 @@ "webapi-parser": "^0.5.0" } }, - "node_modules/parserapiv2/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/parserapiv2/node_modules/ajv-errors": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", @@ -9424,11 +9400,23 @@ "ajv": "^8.0.1" } }, - "node_modules/parserapiv2/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "node_modules/parserapiv2/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } }, "node_modules/parserapiv3": { "name": "@asyncapi/parser", @@ -9458,22 +9446,6 @@ "node-fetch": "2.6.7" } }, - "node_modules/parserapiv3/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/parserapiv3/node_modules/ajv-errors": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz", @@ -9483,11 +9455,23 @@ "ajv": "^8.0.1" } }, - "node_modules/parserapiv3/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "node_modules/parserapiv3/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } }, "node_modules/pascal-case": { "version": "3.1.2", @@ -9887,7 +9871,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, "engines": { "node": ">=0.10.0" } diff --git a/examples/typescript-nextjs/package.json b/examples/typescript-nextjs/package.json index 52163825..3d21ef9b 100644 --- a/examples/typescript-nextjs/package.json +++ b/examples/typescript-nextjs/package.json @@ -17,7 +17,9 @@ "next": "^14.2.1", "react": "^18.3.0", "react-dom": "^18.3.0", - "zod": "^3.23.3" + "zod": "^3.23.3", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1" }, "devDependencies": { "@types/eslint": "^8.56.2", diff --git a/examples/typescript-nextjs/src/__gen__/payloads/UserSignedUp.ts b/examples/typescript-nextjs/src/__gen__/payloads/UserSignedUp.ts index ce77fc5e..2d521c70 100644 --- a/examples/typescript-nextjs/src/__gen__/payloads/UserSignedUp.ts +++ b/examples/typescript-nextjs/src/__gen__/payloads/UserSignedUp.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface UserSignedUpInterface { displayName?: string email?: string @@ -90,6 +90,9 @@ class UserSignedUp { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -97,4 +100,5 @@ class UserSignedUp { } } -export { UserSignedUp, UserSignedUpInterface }; \ No newline at end of file +export { UserSignedUp }; +export type { UserSignedUpInterface }; \ No newline at end of file diff --git a/src/codegen/generators/typescript/channels/index.ts b/src/codegen/generators/typescript/channels/index.ts index 53ea3eac..8cad104a 100644 --- a/src/codegen/generators/typescript/channels/index.ts +++ b/src/codegen/generators/typescript/channels/index.ts @@ -93,7 +93,8 @@ export async function generateTypeScriptChannels( protocolCodeFunctions, externalProtocolFunctionInformation, parameters, - payloads + payloads, + headers ); } @@ -106,7 +107,8 @@ async function finalizeGeneration( TypeScriptChannelRenderedFunctionType[] >, parameters: TypeScriptParameterRenderType, - payloads: TypeScriptPayloadRenderType + payloads: TypeScriptPayloadRenderType, + headers: TypeScriptHeadersRenderType ): Promise { const files: GeneratedFile[] = []; const generatedProtocols: string[] = []; @@ -169,6 +171,7 @@ async function finalizeGeneration( return { parameterRender: parameters, payloadRender: payloads, + headerRender: headers, generator: context.generator, renderedFunctions: externalProtocolFunctionInformation, result: indexContent, diff --git a/src/codegen/generators/typescript/channels/protocols/amqp/publishExchange.ts b/src/codegen/generators/typescript/channels/protocols/amqp/publishExchange.ts index f357d4b8..d72c2a1f 100644 --- a/src/codegen/generators/typescript/channels/protocols/amqp/publishExchange.ts +++ b/src/codegen/generators/typescript/channels/protocols/amqp/publishExchange.ts @@ -4,6 +4,7 @@ import {SingleFunctionRenderType} from '../../../../../types'; import {pascalCase} from '../../../utils'; import {RenderRegularParameters} from '../../types'; import { + getHeaderTypeAndModule, parameterInstanceExpression, parameterUnionType, payloadInstanceExpression, @@ -63,6 +64,7 @@ const routingKey = ${addressToUse}; ${headersHandling} channel.publish(exchange, routingKey, Buffer.from(dataToSend), publishOptions);`; + const {headerType} = getHeaderTypeAndModule(channelHeaders); const functionParameters = [ { parameter: `message`, @@ -82,7 +84,7 @@ channel.publish(exchange, routingKey, Buffer.from(dataToSend), publishOptions);` ? [ { parameter: `headers`, - parameterType: `headers?: ${channelHeaders.type}`, + parameterType: `headers?: ${headerType}`, jsDoc: ' * @param headers optional headers to include with the message' } diff --git a/src/codegen/generators/typescript/channels/protocols/amqp/publishQueue.ts b/src/codegen/generators/typescript/channels/protocols/amqp/publishQueue.ts index ca3dc70f..2778e76c 100644 --- a/src/codegen/generators/typescript/channels/protocols/amqp/publishQueue.ts +++ b/src/codegen/generators/typescript/channels/protocols/amqp/publishQueue.ts @@ -4,6 +4,7 @@ import {SingleFunctionRenderType} from '../../../../../types'; import {pascalCase} from '../../../utils'; import {RenderRegularParameters} from '../../types'; import { + getHeaderTypeAndModule, parameterInstanceExpression, parameterUnionType, payloadInstanceExpression, @@ -60,6 +61,7 @@ const queue = ${addressToUse}; ${headersHandling} channel.sendToQueue(queue, Buffer.from(dataToSend), publishOptions);`; + const {headerType} = getHeaderTypeAndModule(channelHeaders); const functionParameters = [ { parameter: `message`, @@ -79,7 +81,7 @@ channel.sendToQueue(queue, Buffer.from(dataToSend), publishOptions);`; ? [ { parameter: `headers`, - parameterType: `headers?: ${channelHeaders.type}`, + parameterType: `headers?: ${headerType}`, jsDoc: ' * @param headers optional headers to include with the message' } diff --git a/src/codegen/generators/typescript/channels/protocols/amqp/subscribeQueue.ts b/src/codegen/generators/typescript/channels/protocols/amqp/subscribeQueue.ts index 6ed2e6ed..64735750 100644 --- a/src/codegen/generators/typescript/channels/protocols/amqp/subscribeQueue.ts +++ b/src/codegen/generators/typescript/channels/protocols/amqp/subscribeQueue.ts @@ -3,6 +3,7 @@ import {SingleFunctionRenderType} from '../../../../../types'; import {pascalCase} from '../../../utils'; import {RenderRegularParameters} from '../../types'; import { + getHeaderTypeAndModule, getValidationFunctions, parameterInstanceExpression, parameterUnionType, @@ -21,6 +22,7 @@ export function renderSubscribeQueue({ description, deprecated }: RenderRegularParameters): SingleFunctionRenderType { + const {headerType, headerModule} = getHeaderTypeAndModule(channelHeaders); const includeValidation = payloadGenerator.generator.includeValidation; const addressToUse = channelParameters ? `${parameterInstanceExpression({modelName: channelParameters.type, source: 'parameters'})}.getChannelWithParameters('${topic}')` @@ -45,7 +47,7 @@ channel.consume(queue, (msg) => { ${ channelHeaders ? `// Extract headers if present - let extractedHeaders: ${channelHeaders.type} | undefined = undefined; + let extractedHeaders: ${headerType} | undefined = undefined; if (msg.properties && msg.properties.headers) { const headerObj: Record = {}; for (const [key, value] of Object.entries(msg.properties.headers)) { @@ -53,7 +55,7 @@ channel.consume(queue, (msg) => { headerObj[key] = value; } } - extractedHeaders = ${channelHeaders.type}.unmarshal(headerObj); + extractedHeaders = ${headerModule ?? headerType}.unmarshal(headerObj); }` : '' } @@ -75,7 +77,7 @@ channel.consume(queue, (msg) => { ...(channelHeaders ? [ { - parameter: `headers?: ${channelHeaders.type}`, + parameter: `headers?: ${headerType}`, jsDoc: ' * @param headers that was received with the message' } ] diff --git a/src/codegen/generators/typescript/channels/protocols/eventsource/fetch.ts b/src/codegen/generators/typescript/channels/protocols/eventsource/fetch.ts index 8c5b4e8b..6a995dfa 100644 --- a/src/codegen/generators/typescript/channels/protocols/eventsource/fetch.ts +++ b/src/codegen/generators/typescript/channels/protocols/eventsource/fetch.ts @@ -7,6 +7,7 @@ import { RenderRegularParameters } from '../../types'; import { + getHeaderTypeAndModule, getValidationFunctions, parameterInstanceExpression, parameterUnionType, @@ -44,6 +45,7 @@ export function renderFetch({ messageType, onValidationFail: `return callback({error: new Error(\`Invalid message payload received; $\{JSON.stringify({cause: errors})}\`), messageEvent: undefined});` }); + const {headerType} = getHeaderTypeAndModule(channelHeaders); const functionParameters = [ { parameter: `callback`, @@ -63,7 +65,7 @@ export function renderFetch({ ? [ { parameter: `headers`, - parameterType: `headers?: ${channelHeaders.type}`, + parameterType: `headers?: ${headerType}`, jsDoc: ' * @param headers optional headers to include with the EventSource connection' } diff --git a/src/codegen/generators/typescript/channels/protocols/http/client.ts b/src/codegen/generators/typescript/channels/protocols/http/client.ts index 457c4767..f2515785 100644 --- a/src/codegen/generators/typescript/channels/protocols/http/client.ts +++ b/src/codegen/generators/typescript/channels/protocols/http/client.ts @@ -6,6 +6,7 @@ import {HttpRenderType} from '../../../../../types'; import {pascalCase} from '../../../utils'; import {ChannelFunctionTypes, RenderHttpParameters} from '../../types'; import { + getHeaderTypeAndModule, parameterUnionType, payloadUnionType, renderParameterNormalization, @@ -64,7 +65,7 @@ export function renderHttpFetchClient({ contextInterfaceName, payloadInputType, channelParameters?.type, - channelHeaders?.type, + getHeaderTypeAndModule(channelHeaders).headerType, method ); @@ -89,7 +90,7 @@ export function renderHttpFetchClient({ hasParameters, parameterModelName: channelParameters?.name, hasHeaders, - headersType: channelHeaders?.type, + headersType: getHeaderTypeAndModule(channelHeaders).headerType, hasSerializeHeaders, method, servers, diff --git a/src/codegen/generators/typescript/channels/protocols/kafka/publish.ts b/src/codegen/generators/typescript/channels/protocols/kafka/publish.ts index e925b7aa..bd323d79 100644 --- a/src/codegen/generators/typescript/channels/protocols/kafka/publish.ts +++ b/src/codegen/generators/typescript/channels/protocols/kafka/publish.ts @@ -4,6 +4,7 @@ import {SingleFunctionRenderType} from '../../../../../types'; import {pascalCase} from '../../../utils'; import {RenderRegularParameters} from '../../types'; import { + getHeaderTypeAndModule, parameterInstanceExpression, parameterUnionType, payloadInstanceExpression, @@ -43,6 +44,7 @@ export function renderPublish({ ? `let dataToSend: any = null;` : `let dataToSend: any = ${messageMarshalling};`; + const {headerType} = getHeaderTypeAndModule(channelHeaders); const functionParameters = [ { parameter: `message`, @@ -62,7 +64,7 @@ export function renderPublish({ ? [ { parameter: `headers`, - parameterType: `headers?: ${channelHeaders.type}`, + parameterType: `headers?: ${headerType}`, jsDoc: ' * @param headers optional headers to include with the message' } diff --git a/src/codegen/generators/typescript/channels/protocols/kafka/subscribe.ts b/src/codegen/generators/typescript/channels/protocols/kafka/subscribe.ts index 2e75b2a3..c3cd9497 100644 --- a/src/codegen/generators/typescript/channels/protocols/kafka/subscribe.ts +++ b/src/codegen/generators/typescript/channels/protocols/kafka/subscribe.ts @@ -11,6 +11,7 @@ import { renderChannelJSDoc } from '../../utils'; import {generateKafkaMessageReceivingCode} from './utils'; +import {getHeaderTypeAndModule} from '../../utils'; export function renderSubscribe({ topic, @@ -46,6 +47,7 @@ export function renderSubscribe({ : `return onDataCallback(new Error(\`Invalid message payload received; $\{JSON.stringify({cause: errors})}\`), undefined, kafkaMessage);` }); + const {headerType} = getHeaderTypeAndModule(channelHeaders); const callbackFunctionParameters = [ { parameter: 'err?: Error', @@ -66,7 +68,7 @@ export function renderSubscribe({ ...(channelHeaders ? [ { - parameter: `headers?: ${channelHeaders.type}`, + parameter: `headers?: ${headerType}`, jsDoc: ' * @param headers that was received with the message' } ] diff --git a/src/codegen/generators/typescript/channels/protocols/kafka/utils.ts b/src/codegen/generators/typescript/channels/protocols/kafka/utils.ts index 561f7c00..6214501a 100644 --- a/src/codegen/generators/typescript/channels/protocols/kafka/utils.ts +++ b/src/codegen/generators/typescript/channels/protocols/kafka/utils.ts @@ -1,4 +1,5 @@ import {ConstrainedObjectModel} from '@asyncapi/modelina'; +import {getHeaderTypeAndModule} from '../../utils'; /** * Generates the message receiving code for Kafka subscribe functions @@ -16,11 +17,12 @@ export function generateKafkaMessageReceivingCode({ messageUnmarshalling: string; potentialValidationFunction: string; }): string { + const {headerType, headerModule} = getHeaderTypeAndModule(channelHeaders); // Generate header extraction code const headerExtraction = channelHeaders ? ` // Extract headers if present - let extractedHeaders: ${channelHeaders.type} | undefined = undefined; + let extractedHeaders: ${headerType} | undefined = undefined; if (message.headers) { const headerObj: Record = {}; for (const [key, value] of Object.entries(message.headers)) { @@ -28,7 +30,7 @@ export function generateKafkaMessageReceivingCode({ headerObj[key] = value.toString(); } } - extractedHeaders = ${channelHeaders.type}.unmarshal(headerObj); + extractedHeaders = ${headerModule ?? headerType}.unmarshal(headerObj); }` : ''; diff --git a/src/codegen/generators/typescript/channels/protocols/mqtt/publish.ts b/src/codegen/generators/typescript/channels/protocols/mqtt/publish.ts index d1109b6d..87cf1c48 100644 --- a/src/codegen/generators/typescript/channels/protocols/mqtt/publish.ts +++ b/src/codegen/generators/typescript/channels/protocols/mqtt/publish.ts @@ -4,6 +4,7 @@ import {SingleFunctionRenderType} from '../../../../../types'; import {pascalCase} from '../../../utils'; import {RenderRegularParameters} from '../../types'; import { + getHeaderTypeAndModule, parameterInstanceExpression, parameterUnionType, payloadInstanceExpression, @@ -63,6 +64,7 @@ export function renderPublish({ ${headersHandling} mqtt.publish(${addressToUse}, dataToSend, publishOptions);`; + const {headerType} = getHeaderTypeAndModule(channelHeaders); const functionParameters = [ { parameter: `message`, @@ -82,7 +84,7 @@ export function renderPublish({ ? [ { parameter: `headers`, - parameterType: `headers?: ${channelHeaders.type}`, + parameterType: `headers?: ${headerType}`, jsDoc: ' * @param headers optional headers to include with the message as MQTT user properties' } diff --git a/src/codegen/generators/typescript/channels/protocols/mqtt/subscribe.ts b/src/codegen/generators/typescript/channels/protocols/mqtt/subscribe.ts index 6923230d..e38d54ec 100644 --- a/src/codegen/generators/typescript/channels/protocols/mqtt/subscribe.ts +++ b/src/codegen/generators/typescript/channels/protocols/mqtt/subscribe.ts @@ -5,6 +5,7 @@ import {SingleFunctionRenderType} from '../../../../../types'; import {findRegexFromChannel, pascalCase} from '../../../utils'; import {RenderRegularParameters} from '../../types'; import { + getHeaderTypeAndModule, getValidationFunctions, parameterInstanceExpression, parameterUnionType, @@ -24,6 +25,7 @@ export function renderSubscribe({ description, deprecated }: RenderRegularParameters): SingleFunctionRenderType { + const {headerType, headerModule} = getHeaderTypeAndModule(channelHeaders); const includeValidation = payloadGenerator.generator.includeValidation; const addressToUse = channelParameters ? `${parameterInstanceExpression({modelName: channelParameters.type, source: 'parameters'})}.getChannelWithParameters('${topic}')` @@ -86,7 +88,7 @@ export function renderSubscribe({ ...(channelHeaders ? [ { - parameter: `headers?: ${channelHeaders.type}`, + parameter: `headers?: ${headerType}`, jsDoc: ' * @param headers that was received with the message as MQTT user properties' } @@ -141,10 +143,10 @@ export function renderSubscribe({ channelHeaders ? ` // Extract headers from MQTT v5 user properties - let extractedHeaders: ${channelHeaders.type} | undefined; + let extractedHeaders: ${headerType} | undefined; if (packet.properties && packet.properties.userProperties) { try { - extractedHeaders = ${channelHeaders.type}.unmarshal(packet.properties.userProperties); + extractedHeaders = ${headerModule ?? headerType}.unmarshal(packet.properties.userProperties); } catch (headerError) { onDataCallback({err: new Error(\`${PARSE_HEADERS_ERROR}\`), msg: undefined${channelParameters ? PARAMETERS_PARAM : ''}${channelHeaders ? HEADERS_UNDEFINED_PARAM : ''}, mqttMsg: packet}); return; diff --git a/src/codegen/generators/typescript/channels/protocols/nats/coreReply.ts b/src/codegen/generators/typescript/channels/protocols/nats/coreReply.ts index 8c5c0ef3..bf8c19ed 100644 --- a/src/codegen/generators/typescript/channels/protocols/nats/coreReply.ts +++ b/src/codegen/generators/typescript/channels/protocols/nats/coreReply.ts @@ -39,8 +39,8 @@ export function renderCoreReply({ messageModule: requestMessageModule, messageType: requestMessageType, onValidationFail: channelParameters - ? `onDataCallback(new Error('Invalid request payload received', JSON.stringify({cause: errors})), undefined, parameters); continue;` - : `onDataCallback(new Error('Invalid request payload received', JSON.stringify({cause: errors})), undefined); continue;` + ? `onDataCallback(new Error(\`Invalid request payload received; $\{JSON.stringify({cause: errors})}\`), undefined, parameters); continue;` + : `onDataCallback(new Error(\`Invalid request payload received; $\{JSON.stringify({cause: errors})}\`), undefined); continue;` }); const callbackFunctionParameters = [ diff --git a/src/codegen/generators/typescript/channels/protocols/nats/coreSubscribe.ts b/src/codegen/generators/typescript/channels/protocols/nats/coreSubscribe.ts index 948bcaea..0b829358 100644 --- a/src/codegen/generators/typescript/channels/protocols/nats/coreSubscribe.ts +++ b/src/codegen/generators/typescript/channels/protocols/nats/coreSubscribe.ts @@ -5,6 +5,7 @@ import {SingleFunctionRenderType} from '../../../../../types'; import {findRegexFromChannel, pascalCase} from '../../../utils'; import {RenderRegularParameters} from '../../types'; import { + getHeaderTypeAndModule, getValidationFunctions, parameterInstanceExpression, parameterUnionType, @@ -170,6 +171,7 @@ function ${functionName}({ code, functionName, dependencies: [`import * as Nats from 'nats';`], + headerType: getHeaderTypeAndModule(channelHeaders).headerType, functionType: ChannelFunctionTypes.NATS_SUBSCRIBE }; } diff --git a/src/codegen/generators/typescript/channels/protocols/nats/jetstreamPullSubscribe.ts b/src/codegen/generators/typescript/channels/protocols/nats/jetstreamPullSubscribe.ts index 3e2944e7..828a2c82 100644 --- a/src/codegen/generators/typescript/channels/protocols/nats/jetstreamPullSubscribe.ts +++ b/src/codegen/generators/typescript/channels/protocols/nats/jetstreamPullSubscribe.ts @@ -5,6 +5,7 @@ import {SingleFunctionRenderType} from '../../../../../types'; import {findRegexFromChannel, pascalCase} from '../../../utils'; import {RenderRegularParameters} from '../../types'; import { + getHeaderTypeAndModule, getValidationFunctions, parameterInstanceExpression, parameterUnionType, @@ -45,6 +46,7 @@ export function renderJetstreamPullSubscribe({ onValidationFail: `onDataCallback(new Error(\`Invalid message payload received; $\{JSON.stringify({cause: errors})}\`), undefined,${channelParameters ? 'parameters, ' : ''}${channelHeaders ? 'extractedHeaders, ' : ''} msg); continue;` }); + const {headerType} = getHeaderTypeAndModule(channelHeaders); const callbackFunctionParameters = [ { parameter: 'err?: Error', @@ -65,7 +67,7 @@ export function renderJetstreamPullSubscribe({ ...(channelHeaders ? [ { - parameter: `headers?: ${channelHeaders.type}`, + parameter: `headers?: ${headerType}`, jsDoc: ' * @param headers that was received with the message' } ] @@ -171,6 +173,7 @@ function ${functionName}({ code, functionName, dependencies: [`import * as Nats from 'nats';`], + headerType: getHeaderTypeAndModule(channelHeaders).headerType, functionType: ChannelFunctionTypes.NATS_JETSTREAM_PULL_SUBSCRIBE }; } diff --git a/src/codegen/generators/typescript/channels/protocols/nats/jetstreamPushSubscription.ts b/src/codegen/generators/typescript/channels/protocols/nats/jetstreamPushSubscription.ts index 7f8e5472..2a282edb 100644 --- a/src/codegen/generators/typescript/channels/protocols/nats/jetstreamPushSubscription.ts +++ b/src/codegen/generators/typescript/channels/protocols/nats/jetstreamPushSubscription.ts @@ -5,6 +5,7 @@ import {SingleFunctionRenderType} from '../../../../../types'; import {findRegexFromChannel, pascalCase} from '../../../utils'; import {RenderRegularParameters} from '../../types'; import { + getHeaderTypeAndModule, getValidationFunctions, parameterInstanceExpression, parameterUnionType, @@ -45,6 +46,7 @@ export function renderJetstreamPushSubscription({ onValidationFail: `onDataCallback(new Error(\`Invalid message payload received; $\{JSON.stringify({cause: errors})}\`), undefined,${channelParameters ? 'parameters, ' : ''}${channelHeaders ? 'extractedHeaders, ' : ''} msg); continue;` }); + const {headerType} = getHeaderTypeAndModule(channelHeaders); const callbackFunctionParameters = [ { parameter: 'err?: Error', @@ -65,7 +67,7 @@ export function renderJetstreamPushSubscription({ ...(channelHeaders ? [ { - parameter: `headers?: ${channelHeaders.type}`, + parameter: `headers?: ${headerType}`, jsDoc: ' * @param headers that was received with the message' } ] @@ -174,6 +176,7 @@ function ${functionName}({ code, functionName, dependencies: [`import * as Nats from 'nats';`], + headerType: getHeaderTypeAndModule(channelHeaders).headerType, functionType: ChannelFunctionTypes.NATS_JETSTREAM_PUSH_SUBSCRIBE }; } diff --git a/src/codegen/generators/typescript/channels/protocols/nats/utils.ts b/src/codegen/generators/typescript/channels/protocols/nats/utils.ts index ac9086c0..ad928c21 100644 --- a/src/codegen/generators/typescript/channels/protocols/nats/utils.ts +++ b/src/codegen/generators/typescript/channels/protocols/nats/utils.ts @@ -1,4 +1,5 @@ import {ConstrainedObjectModel} from '@asyncapi/modelina'; +import {getHeaderTypeAndModule} from '../../utils'; /** * Generates the header setup code for NATS publish operations @@ -34,8 +35,9 @@ export function generateHeaderExtractionCode( return ''; } + const {headerType, headerModule} = getHeaderTypeAndModule(channelHeaders); return `// Extract headers if present - let extractedHeaders: ${channelHeaders.type} | undefined = undefined; + let extractedHeaders: ${headerType} | undefined = undefined; if (msg.headers) { const headerObj: Record = {}; // NATS headers support both iteration and get() method @@ -50,7 +52,7 @@ export function generateHeaderExtractionCode( headerObj[key] = value; } } - extractedHeaders = ${channelHeaders.type}.unmarshal(headerObj); + extractedHeaders = ${headerModule ?? headerType}.unmarshal(headerObj); }`; } @@ -68,9 +70,10 @@ export function generateHeaderParameter( return null; } + const {headerType} = getHeaderTypeAndModule(channelHeaders); return { parameter: 'headers', - parameterType: `headers?: ${channelHeaders.type}`, + parameterType: `headers?: ${headerType}`, jsDoc: ' * @param headers optional headers to include with the message' }; } @@ -88,8 +91,9 @@ export function generateHeaderCallbackParameter( return null; } + const {headerType} = getHeaderTypeAndModule(channelHeaders); return { - parameter: `headers?: ${channelHeaders.type}`, + parameter: `headers?: ${headerType}`, jsDoc: ' * @param headers that were received with the message' }; } diff --git a/src/codegen/generators/typescript/channels/types.ts b/src/codegen/generators/typescript/channels/types.ts index 67342b26..e5369055 100644 --- a/src/codegen/generators/typescript/channels/types.ts +++ b/src/codegen/generators/typescript/channels/types.ts @@ -4,6 +4,7 @@ import {zodImportExtension} from '../../../utils'; import {AsyncAPIDocumentInterface} from '@asyncapi/parser'; import {TypeScriptPayloadRenderType} from '../payloads'; import {TypeScriptParameterRenderType} from '../parameters'; +import {TypeScriptHeadersRenderType} from '../headers'; import {ConstrainedObjectModel} from '@asyncapi/modelina'; import {OpenAPIV2, OpenAPIV3, OpenAPIV3_1} from 'openapi-types'; import {SecuritySchemeOptions} from '../../../inputs/openapi/security'; @@ -214,6 +215,12 @@ export type TypeScriptChannelRenderedFunctionType = { * ergonomic plain object the channel functions accept. */ messageUnionType?: string; + /** + * The header type used in the channel function's callback, when the channel + * has headers. Read by the client generator so its wrapper subscribe methods + * declare the same callback signature as the channel function they delegate to. + */ + headerType?: string; replyType?: string; parameterType?: string; /** @@ -229,6 +236,12 @@ export type TypeScriptChannelRenderedFunctionType = { export interface TypeScriptChannelRenderType { payloadRender: TypeScriptPayloadRenderType; parameterRender: TypeScriptParameterRenderType; + /** + * The headers render this channels render was built from. Exposed so the + * client generator can import the same header models its wrapper subscribe + * methods reference in their callback signatures. + */ + headerRender: TypeScriptHeadersRenderType; generator: TypeScriptChannelsGeneratorInternal; /** * All the rendered functions based on type. diff --git a/src/codegen/generators/typescript/channels/utils.ts b/src/codegen/generators/typescript/channels/utils.ts index ccd2b541..133dcae4 100644 --- a/src/codegen/generators/typescript/channels/utils.ts +++ b/src/codegen/generators/typescript/channels/utils.ts @@ -1,6 +1,7 @@ import { ConstrainedEnumModel, ConstrainedObjectModel, + ConstrainedMetaModel, OutputModel } from '@asyncapi/modelina'; import {ChannelPayload, SingleFunctionRenderType} from '../../../types'; @@ -246,6 +247,14 @@ export function addHeadersToDependencies( importExtension ); + if (!(header.model instanceof ConstrainedObjectModel)) { + // Union header model — namespace import, matching payload unions. + dependencies.push( + `import * as ${header.modelName}Module from '${importPath}';` + ); + return; + } + const fns = headerFunctions?.[header.modelName] ?? []; const importNames = fns.length > 0 @@ -254,6 +263,30 @@ export function addHeadersToDependencies( dependencies.push(`import {${importNames}} from '${importPath}';`); }); } +/** + * Resolve how a channel's header model is referenced in generated code. + * + * A channel whose messages each declare their own headers produces a `oneOf` + * union model. Its `type` is the expanded union (`A | B | C`), which neither + * resolves (the members are not imported) nor carries the static `unmarshal` + * the receive paths call. Union models are therefore imported as a namespace — + * exactly like payload unions — so the type is `Module.` and the + * runtime helpers live on `Module`. + */ +export function getHeaderTypeAndModule(headers?: ConstrainedMetaModel): { + headerType?: string; + headerModule?: string; +} { + if (!headers) { + return {headerType: undefined, headerModule: undefined}; + } + if (headers instanceof ConstrainedObjectModel) { + return {headerType: headers.type, headerModule: undefined}; + } + const headerModule = `${headers.name}Module`; + return {headerType: `${headerModule}.${headers.name}`, headerModule}; +} + export function getMessageTypeAndModule(payload: ChannelPayload) { if (payload === undefined) { return { @@ -550,6 +583,7 @@ type RenderForExternal = Pick< > & { messageType?: string; messageUnionType?: string; + headerType?: string; replyType?: string; parameterType?: string; }; @@ -591,6 +625,7 @@ export function addRendersToExternal({ functionName: value.functionName, messageType: value.messageType ?? '', messageUnionType: value.messageUnionType ?? value.messageType ?? '', + headerType: value.headerType, replyType: value.replyType, parameterType: value.parameterType ?? parameter?.type, tags: value.tags, diff --git a/src/codegen/generators/typescript/client/protocols/nats.ts b/src/codegen/generators/typescript/client/protocols/nats.ts index e3ef3545..9198f348 100644 --- a/src/codegen/generators/typescript/client/protocols/nats.ts +++ b/src/codegen/generators/typescript/client/protocols/nats.ts @@ -19,6 +19,7 @@ import {renderJetStreamPullSubscription} from './nats/jetStreamPullSubscription' import {renderJetStreamPushSubscription} from './nats/jetstreamPushSubscription'; import { addParametersToDependencies, + addHeadersToDependencies, addParametersToExports, addPayloadsToDependencies, addPayloadsToExports @@ -59,6 +60,7 @@ export async function generateNatsClient( const payloads = channels.payloadRender; const parameters = channels.parameterRender; + const headers = channels.headerRender; const dependencies: string[] = []; const importExtension = resolveImportExtension( @@ -86,12 +88,22 @@ export async function generateNatsClient( importExtension ); addParametersToExports(parameters.channelModels, dependencies); + // The wrapper subscribe methods reference the channel header types in their + // callback signatures, so those models have to be imported here too. + addHeadersToDependencies( + headers.channelModels, + headers.generator, + context.generator, + dependencies, + importExtension + ); const natsFunctions: string[] = []; for (const func of renderedNatsFunctions) { const context = { channelName: func.functionName, channelParameterType: func.parameterType, + channelHeaderType: func.headerType, description: '', messageType: func.messageType, // Publish wrappers accept the widened `Interface | Class` union so callers diff --git a/src/codegen/generators/typescript/client/protocols/nats/coreSubscribe.ts b/src/codegen/generators/typescript/client/protocols/nats/coreSubscribe.ts index 25a3e855..81050d54 100644 --- a/src/codegen/generators/typescript/client/protocols/nats/coreSubscribe.ts +++ b/src/codegen/generators/typescript/client/protocols/nats/coreSubscribe.ts @@ -1,98 +1,108 @@ -export function renderCoreSubscribe({ - description, - messageType, - channelParameterType, - channelName -}: { - description: string; - messageType: string; - channelParameterType?: string; - channelName: string; -}) { - const callbackFunctionParameters = [ - { - parameter: 'err?: Error', - jsDoc: ' * @param err if any error occurred this will be sat' - }, - { - parameter: `msg?: ${messageType}`, - jsDoc: ' * @param msg that was received' - }, - ...(channelParameterType - ? [ - { - parameter: `parameters?: ${channelParameterType}`, - jsDoc: ' * @param parameters that was received in the topic' - } - ] - : []), - { - parameter: `natsMsg?: Nats.Msg`, - jsDoc: ' * @param natsMsg' - } - ]; - - const functionParameters = [ - { - parameter: `onDataCallback`, - parameterType: `onDataCallback: (${callbackFunctionParameters.map((param) => param.parameter).join(', ')}) => void`, - jsDoc: ` * @param {${channelName}Callback} onDataCallback to call when messages are received` - }, - ...(channelParameterType - ? [ - { - parameter: `parameters`, - parameterType: `parameters: ${channelParameterType}`, - jsDoc: ' * @param parameters for topic substitution' - } - ] - : []), - { - parameter: 'options', - parameterType: 'options?: Nats.SubscriptionOptions', - jsDoc: ' * @param options when setting up the subscription' - }, - { - parameter: 'flush', - parameterType: 'flush?: boolean', - jsDoc: ' * @param options when setting up the subscription' - } - ]; - - const functionCallParameters = [ - 'onDataCallback', - ...(channelParameterType ? ['parameters'] : []), - 'nc: this.nc', - 'codec: this.codec', - 'options' - ]; - return ` - /** - * ${description} - * - ${functionParameters.map((param) => param.jsDoc).join('\n ')} - */ - public ${channelName}({ - ${functionParameters.map((param) => param.parameter).join(', \n ')} - }: { - ${functionParameters.map((param) => param.parameterType).join(', \n ')} - }): Promise { - return new Promise(async (resolve, reject) => { - if(!this.isClosed() && this.nc !== undefined && this.codec !== undefined){ - try { - const sub = await nats.${channelName}({ - ${functionCallParameters.join(', \n ')} - }); - if(flush){ - await this.nc.flush(); - } - resolve(sub); - }catch(e: any){ - reject(e); - } - } else { - Promise.reject('Nats client not available yet, please connect or set the client'); - } - }); -}`; -} +export function renderCoreSubscribe({ + description, + messageType, + channelParameterType, + channelHeaderType, + channelName +}: { + description: string; + messageType: string; + channelParameterType?: string; + channelHeaderType?: string; + channelName: string; +}) { + const callbackFunctionParameters = [ + { + parameter: 'err?: Error', + jsDoc: ' * @param err if any error occurred this will be sat' + }, + { + parameter: `msg?: ${messageType}`, + jsDoc: ' * @param msg that was received' + }, + ...(channelParameterType + ? [ + { + parameter: `parameters?: ${channelParameterType}`, + jsDoc: ' * @param parameters that was received in the topic' + } + ] + : []), + ...(channelHeaderType + ? [ + { + parameter: `headers?: ${channelHeaderType}`, + jsDoc: ' * @param headers that was received with the message' + } + ] + : []), + { + parameter: `natsMsg?: Nats.Msg`, + jsDoc: ' * @param natsMsg' + } + ]; + + const functionParameters = [ + { + parameter: `onDataCallback`, + parameterType: `onDataCallback: (${callbackFunctionParameters.map((param) => param.parameter).join(', ')}) => void`, + jsDoc: ` * @param {${channelName}Callback} onDataCallback to call when messages are received` + }, + ...(channelParameterType + ? [ + { + parameter: `parameters`, + parameterType: `parameters: ${channelParameterType}`, + jsDoc: ' * @param parameters for topic substitution' + } + ] + : []), + { + parameter: 'options', + parameterType: 'options?: Nats.SubscriptionOptions', + jsDoc: ' * @param options when setting up the subscription' + }, + { + parameter: 'flush', + parameterType: 'flush?: boolean', + jsDoc: ' * @param options when setting up the subscription' + } + ]; + + const functionCallParameters = [ + 'onDataCallback', + ...(channelParameterType ? ['parameters'] : []), + 'nc: this.nc', + 'codec: this.codec', + 'options' + ]; + return ` + /** + * ${description} + * + ${functionParameters.map((param) => param.jsDoc).join('\n ')} + */ + public ${channelName}({ + ${functionParameters.map((param) => param.parameter).join(', \n ')} + }: { + ${functionParameters.map((param) => param.parameterType).join(', \n ')} + }): Promise { + return new Promise(async (resolve, reject) => { + if(!this.isClosed() && this.nc !== undefined && this.codec !== undefined){ + try { + const sub = await nats.${channelName}({ + ${functionCallParameters.join(', \n ')} + }); + if(flush){ + await this.nc.flush(); + } + resolve(sub); + }catch(e: any){ + reject(e); + } + } else { + Promise.reject('Nats client not available yet, please connect or set the client'); + } + }); +}`; +} diff --git a/src/codegen/generators/typescript/client/protocols/nats/jetStreamPullSubscription.ts b/src/codegen/generators/typescript/client/protocols/nats/jetStreamPullSubscription.ts index 0e25b486..e6f3ae34 100644 --- a/src/codegen/generators/typescript/client/protocols/nats/jetStreamPullSubscription.ts +++ b/src/codegen/generators/typescript/client/protocols/nats/jetStreamPullSubscription.ts @@ -1,92 +1,102 @@ -export function renderJetStreamPullSubscription({ - description, - messageType, - channelParameterType, - channelName -}: { - description: string; - messageType: string; - channelParameterType?: string; - channelName: string; -}) { - const callbackFunctionParameters = [ - { - parameter: 'err?: Error', - jsDoc: ' * @param err if any error occurred this will be sat' - }, - { - parameter: `msg?: ${messageType}`, - jsDoc: ' * @param msg that was received' - }, - ...(channelParameterType - ? [ - { - parameter: `parameters?: ${channelParameterType}`, - jsDoc: ' * @param parameters that was received in the topic' - } - ] - : []), - { - parameter: `jetstreamMsg?: Nats.JsMsg`, - jsDoc: ' * @param jetstreamMsg' - } - ]; - - const functionParameters = [ - { - parameter: `onDataCallback`, - parameterType: `onDataCallback: (${callbackFunctionParameters.map((param) => param.parameter).join(', ')}) => void`, - jsDoc: ` * @param {${channelName}Callback} onDataCallback to call when messages are received` - }, - ...(channelParameterType - ? [ - { - parameter: `parameters`, - parameterType: `parameters: ${channelParameterType}`, - jsDoc: ' * @param parameters for topic substitution' - } - ] - : []), - { - parameter: 'options = {}', - parameterType: - 'options: Nats.ConsumerOptsBuilder | Partial', - jsDoc: ' * @param options when setting up the subscription' - } - ]; - - const functionCallParameters = [ - 'onDataCallback', - ...(channelParameterType ? ['parameters'] : []), - 'js: this.js', - 'codec: this.codec', - 'options' - ]; - return ` - /** - * ${description} - * - ${functionParameters.map((param) => param.jsDoc).join('\n ')} - */ - public ${channelName}({ - ${functionParameters.map((param) => param.parameter).join(', \n ')} - }: { - ${functionParameters.map((param) => param.parameterType).join(', \n ')} - }): Promise { - return new Promise(async (resolve, reject) => { - if (!this.isClosed() && this.nc !== undefined && this.codec !== undefined && this.js !== undefined) { - try { - const sub = await nats.${channelName}({ - ${functionCallParameters.join(', \n ')} - }); - resolve(sub); - } catch (e: any) { - reject(e); - } - } else { - Promise.reject('Nats client not available yet, please connect or set the client'); - } - }); - } - `; -} +export function renderJetStreamPullSubscription({ + description, + messageType, + channelParameterType, + channelHeaderType, + channelName +}: { + description: string; + messageType: string; + channelParameterType?: string; + channelHeaderType?: string; + channelName: string; +}) { + const callbackFunctionParameters = [ + { + parameter: 'err?: Error', + jsDoc: ' * @param err if any error occurred this will be sat' + }, + { + parameter: `msg?: ${messageType}`, + jsDoc: ' * @param msg that was received' + }, + ...(channelParameterType + ? [ + { + parameter: `parameters?: ${channelParameterType}`, + jsDoc: ' * @param parameters that was received in the topic' + } + ] + : []), + ...(channelHeaderType + ? [ + { + parameter: `headers?: ${channelHeaderType}`, + jsDoc: ' * @param headers that was received with the message' + } + ] + : []), + { + parameter: `jetstreamMsg?: Nats.JsMsg`, + jsDoc: ' * @param jetstreamMsg' + } + ]; + + const functionParameters = [ + { + parameter: `onDataCallback`, + parameterType: `onDataCallback: (${callbackFunctionParameters.map((param) => param.parameter).join(', ')}) => void`, + jsDoc: ` * @param {${channelName}Callback} onDataCallback to call when messages are received` + }, + ...(channelParameterType + ? [ + { + parameter: `parameters`, + parameterType: `parameters: ${channelParameterType}`, + jsDoc: ' * @param parameters for topic substitution' + } + ] + : []), + { + parameter: 'options = {}', + parameterType: + 'options: Nats.ConsumerOptsBuilder | Partial', + jsDoc: ' * @param options when setting up the subscription' + } + ]; + + const functionCallParameters = [ + 'onDataCallback', + ...(channelParameterType ? ['parameters'] : []), + 'js: this.js', + 'codec: this.codec', + 'options' + ]; + return ` + /** + * ${description} + * + ${functionParameters.map((param) => param.jsDoc).join('\n ')} + */ + public ${channelName}({ + ${functionParameters.map((param) => param.parameter).join(', \n ')} + }: { + ${functionParameters.map((param) => param.parameterType).join(', \n ')} + }): Promise { + return new Promise(async (resolve, reject) => { + if (!this.isClosed() && this.nc !== undefined && this.codec !== undefined && this.js !== undefined) { + try { + const sub = await nats.${channelName}({ + ${functionCallParameters.join(', \n ')} + }); + resolve(sub); + } catch (e: any) { + reject(e); + } + } else { + Promise.reject('Nats client not available yet, please connect or set the client'); + } + }); + } + `; +} diff --git a/src/codegen/generators/typescript/client/protocols/nats/jetstreamPushSubscription.ts b/src/codegen/generators/typescript/client/protocols/nats/jetstreamPushSubscription.ts index efbbed77..f680a3ba 100644 --- a/src/codegen/generators/typescript/client/protocols/nats/jetstreamPushSubscription.ts +++ b/src/codegen/generators/typescript/client/protocols/nats/jetstreamPushSubscription.ts @@ -1,91 +1,101 @@ -export function renderJetStreamPushSubscription({ - description, - messageType, - channelParameterType, - channelName -}: { - description: string; - messageType: string; - channelParameterType?: string; - channelName: string; -}) { - const callbackFunctionParameters = [ - { - parameter: 'err?: Error', - jsDoc: ' * @param err if any error occurred this will be sat' - }, - { - parameter: `msg?: ${messageType}`, - jsDoc: ' * @param msg that was received' - }, - ...(channelParameterType - ? [ - { - parameter: `parameters?: ${channelParameterType}`, - jsDoc: ' * @param parameters that was received in the topic' - } - ] - : []), - { - parameter: `jetstreamMsg?: Nats.JsMsg`, - jsDoc: ' * @param jetstreamMsg' - } - ]; - - const functionParameters = [ - { - parameter: `onDataCallback`, - parameterType: `onDataCallback: (${callbackFunctionParameters.map((param) => param.parameter).join(', ')}) => void`, - jsDoc: ` * @param {${channelName}Callback} onDataCallback to call when messages are received` - }, - ...(channelParameterType - ? [ - { - parameter: `parameters`, - parameterType: `parameters: ${channelParameterType}`, - jsDoc: ' * @param parameters for topic substitution' - } - ] - : []), - { - parameter: 'options = {}', - parameterType: - 'options: Nats.ConsumerOptsBuilder | Partial', - jsDoc: ' * @param options when setting up the subscription' - } - ]; - const functionCallParameters = [ - 'onDataCallback', - ...(channelParameterType ? ['parameters'] : []), - 'js: this.js', - 'codec: this.codec', - 'options' - ]; - - return ` - /** - * ${description} - * - ${functionParameters.map((param) => param.jsDoc).join('\n ')} - */ - public ${channelName}({ - ${functionParameters.map((param) => param.parameter).join(', \n ')} - }: { - ${functionParameters.map((param) => param.parameterType).join(', \n ')} - }): Promise { - return new Promise(async (resolve, reject) => { - if (!this.isClosed() && this.nc !== undefined && this.codec !== undefined && this.js !== undefined) { - try { - const sub = await nats.${channelName}({ - ${functionCallParameters.join(', \n ')} - }); - resolve(sub); - } catch (e: any) { - reject(e); - } - } else { - Promise.reject('Nats client not available yet, please connect or set the client'); - } - }); - }`; -} +export function renderJetStreamPushSubscription({ + description, + messageType, + channelParameterType, + channelHeaderType, + channelName +}: { + description: string; + messageType: string; + channelParameterType?: string; + channelHeaderType?: string; + channelName: string; +}) { + const callbackFunctionParameters = [ + { + parameter: 'err?: Error', + jsDoc: ' * @param err if any error occurred this will be sat' + }, + { + parameter: `msg?: ${messageType}`, + jsDoc: ' * @param msg that was received' + }, + ...(channelParameterType + ? [ + { + parameter: `parameters?: ${channelParameterType}`, + jsDoc: ' * @param parameters that was received in the topic' + } + ] + : []), + ...(channelHeaderType + ? [ + { + parameter: `headers?: ${channelHeaderType}`, + jsDoc: ' * @param headers that was received with the message' + } + ] + : []), + { + parameter: `jetstreamMsg?: Nats.JsMsg`, + jsDoc: ' * @param jetstreamMsg' + } + ]; + + const functionParameters = [ + { + parameter: `onDataCallback`, + parameterType: `onDataCallback: (${callbackFunctionParameters.map((param) => param.parameter).join(', ')}) => void`, + jsDoc: ` * @param {${channelName}Callback} onDataCallback to call when messages are received` + }, + ...(channelParameterType + ? [ + { + parameter: `parameters`, + parameterType: `parameters: ${channelParameterType}`, + jsDoc: ' * @param parameters for topic substitution' + } + ] + : []), + { + parameter: 'options = {}', + parameterType: + 'options: Nats.ConsumerOptsBuilder | Partial', + jsDoc: ' * @param options when setting up the subscription' + } + ]; + const functionCallParameters = [ + 'onDataCallback', + ...(channelParameterType ? ['parameters'] : []), + 'js: this.js', + 'codec: this.codec', + 'options' + ]; + + return ` + /** + * ${description} + * + ${functionParameters.map((param) => param.jsDoc).join('\n ')} + */ + public ${channelName}({ + ${functionParameters.map((param) => param.parameter).join(', \n ')} + }: { + ${functionParameters.map((param) => param.parameterType).join(', \n ')} + }): Promise { + return new Promise(async (resolve, reject) => { + if (!this.isClosed() && this.nc !== undefined && this.codec !== undefined && this.js !== undefined) { + try { + const sub = await nats.${channelName}({ + ${functionCallParameters.join(', \n ')} + }); + resolve(sub); + } catch (e: any) { + reject(e); + } + } else { + Promise.reject('Nats client not available yet, please connect or set the client'); + } + }); + }`; +} diff --git a/src/codegen/generators/typescript/headers.ts b/src/codegen/generators/typescript/headers.ts index a4dd4d88..461f6898 100644 --- a/src/codegen/generators/typescript/headers.ts +++ b/src/codegen/generators/typescript/headers.ts @@ -21,9 +21,13 @@ import { TS_COMMON_PRESET, typeScriptDefaultPropertyKeyConstraints } from '@asyncapi/modelina'; -import {createValidationPreset} from '../../modelina/presets'; +import { + createValidationPreset, + createUnionPreset +} from '../../modelina/presets'; import {createMissingInputDocumentError} from '../../errors'; import {generateModels} from '../../output'; +import {resolveImportExtension} from '../../utils'; export const zodTypescriptHeadersGenerator = z.object({ id: z @@ -123,6 +127,13 @@ function createAsyncAPIHeadersGenerator( createValidationPreset( {includeValidation: generator.includeValidation}, context + ), + // A channel whose messages each declare their own headers produces a + // `oneOf` union model; the union preset gives it module-level + // `unmarshal`/`marshal`, the same way payload unions get them. + createUnionPreset( + {includeValidation: generator.includeValidation}, + context ) ] }); @@ -189,6 +200,8 @@ export async function generateTypescriptHeadersCore({ const channelModels: Record = {}; const allFiles: GeneratedFile[] = []; const headerFunctions: Record = {}; + // Headers have no per-generator override, so the global setting applies. + const importExtension = resolveImportExtension({}, context.config); for (const [channelId, headerData] of Object.entries( processedData.channelHeaders @@ -200,7 +213,8 @@ export async function generateTypescriptHeadersCore({ const result = await generateModels({ generator: modelinaGenerator, input: headerData.schema, - outputPath: generator.outputPath + outputPath: generator.outputPath, + importExtension }); if (isOpenAPI) { appendOpenAPISerializerFunctions(result, headerFunctions); diff --git a/src/codegen/generators/typescript/models.ts b/src/codegen/generators/typescript/models.ts index 86dda4f5..9b3cb565 100644 --- a/src/codegen/generators/typescript/models.ts +++ b/src/codegen/generators/typescript/models.ts @@ -12,6 +12,7 @@ import {zodTypeScriptOptions, zodTypeScriptPresets} from '../../modelina'; import {JsonSchemaDocument} from '../../inputs/jsonschema'; import {CodegenError, ErrorType} from '../../errors'; import {generateModels} from '../../output'; +import {resolveImportExtension} from '../../utils'; export const zodTypescriptModelsGenerator = z.object({ id: z @@ -102,7 +103,9 @@ export async function generateTypescriptModels( const result = await generateModels({ generator: modelGenerator, input: inputDocument, - outputPath: generator.outputPath + outputPath: generator.outputPath, + // Models have no per-generator override, so the global setting applies. + importExtension: resolveImportExtension({}, context.config) }); return { diff --git a/src/codegen/generators/typescript/parameters.ts b/src/codegen/generators/typescript/parameters.ts index 59b4f004..da37ffac 100644 --- a/src/codegen/generators/typescript/parameters.ts +++ b/src/codegen/generators/typescript/parameters.ts @@ -18,7 +18,8 @@ import { processOpenAPIParameters } from '../../inputs/openapi/generators/parameters'; import {createMissingInputDocumentError} from '../../errors'; -import {generateModels} from '../../output'; +import {applyImportExtension, generateModels} from '../../output'; +import {resolveImportExtension} from '../../utils'; import {withCompanionInterfaceExport} from './utils'; export const zodTypescriptParametersGenerator = z.object({ @@ -89,6 +90,8 @@ export async function generateTypescriptParameters( const channelModels: Record = {}; const files: GeneratedFile[] = []; + // Parameters have no per-generator override, so the global setting applies. + const importExtension = resolveImportExtension({}, context.config); let processedSchemaData: ProcessedParameterSchemaData; let parameterGenerator: TypeScriptFileGenerator; @@ -130,7 +133,8 @@ export async function generateTypescriptParameters( const result = await generateModels({ generator: parameterGenerator, input: schemaData.schema, - outputPath: generator.outputPath + outputPath: generator.outputPath, + importExtension }); const mainModel = result.models.length > 0 @@ -141,7 +145,15 @@ export async function generateTypescriptParameters( if (mainModel && file.path.endsWith(`/${mainModel.modelName}.ts`)) { // The parameter model's own file carries the companion interface, // so re-export both symbols from its (rewritten) content. - files.push({path: file.path, content: mainModel.result}); + // Rebuilding from the rewritten model discards what `generateModels` + // already applied, so re-apply the import extension here. + files.push({ + path: file.path, + content: applyImportExtension({ + content: mainModel.result, + extension: importExtension + }) + }); } else { files.push(file); } diff --git a/src/codegen/generators/typescript/payloads.ts b/src/codegen/generators/typescript/payloads.ts index 43bafbe0..7926257a 100644 --- a/src/codegen/generators/typescript/payloads.ts +++ b/src/codegen/generators/typescript/payloads.ts @@ -29,7 +29,8 @@ import { createPrimitivesPreset } from '../../modelina/presets'; import {createMissingInputDocumentError} from '../../errors'; -import {generateModels} from '../../output'; +import {applyImportExtension, generateModels} from '../../output'; +import {ImportExtension, resolveImportExtension} from '../../utils'; export const zodTypeScriptPayloadGenerator = z.object({ id: z @@ -163,16 +164,29 @@ export async function generateTypescriptPayloadsCore( * onto each model's own file. Non-object payloads have no companion interface, * so {@link withCompanionInterfaceExport} returns them unchanged. */ -function applyCompanionInterfaceExports(result: { - models: OutputModel[]; - files: GeneratedFile[]; -}): {models: OutputModel[]; files: GeneratedFile[]} { +function applyCompanionInterfaceExports( + result: { + models: OutputModel[]; + files: GeneratedFile[]; + }, + importExtension: ImportExtension +): {models: OutputModel[]; files: GeneratedFile[]} { const models = result.models.map(withCompanionInterfaceExport); const files = result.files.map((file) => { const model = models.find((candidate) => file.path.endsWith(`/${candidate.modelName}.ts`) ); - return model ? {path: file.path, content: model.result} : file; + // Rebuilding the content from the rewritten model discards what + // `generateModels` already applied, so re-apply the import extension here. + return model + ? { + path: file.path, + content: applyImportExtension({ + content: model.result, + extension: importExtension + }) + } + : file; }); return {models, files}; } @@ -187,6 +201,8 @@ export async function generateTypescriptPayloadsCoreFromSchemas({ context: TypeScriptPayloadContext; }): Promise { const generator = context.generator; + // Payloads have no per-generator override, so the global setting applies. + const importExtension = resolveImportExtension({}, context.config); const modelinaGenerator = new TypeScriptFileGenerator({ ...defaultCodegenTypescriptModelinaOptions, @@ -248,8 +264,10 @@ export async function generateTypescriptPayloadsCoreFromSchemas({ await generateModels({ generator: modelinaGenerator, input: schemaData.schema, - outputPath: generator.outputPath - }) + outputPath: generator.outputPath, + importExtension + }), + importExtension ); const models = result.models; files.push(...result.files); @@ -287,8 +305,10 @@ export async function generateTypescriptPayloadsCoreFromSchemas({ await generateModels({ generator: modelinaGenerator, input: schemaData.schema, - outputPath: generator.outputPath - }) + outputPath: generator.outputPath, + importExtension + }), + importExtension ); const models = result.models; files.push(...result.files); @@ -323,8 +343,10 @@ export async function generateTypescriptPayloadsCoreFromSchemas({ await generateModels({ generator: modelinaGenerator, input: schemaData.schema, - outputPath: generator.outputPath - }) + outputPath: generator.outputPath, + importExtension + }), + importExtension ); files.push(...result.files); diff --git a/src/codegen/generators/typescript/utils.ts b/src/codegen/generators/typescript/utils.ts index c2596cba..6ad7b3bd 100644 --- a/src/codegen/generators/typescript/utils.ts +++ b/src/codegen/generators/typescript/utils.ts @@ -147,9 +147,12 @@ export function withCompanionInterfaceExport(model: OutputModel): OutputModel { ) { return model; } + // The companion is a type, so it must be re-exported with `export type` — + // bundling it into the value export breaks under `isolatedModules: true` + // (TS1205), which Next.js, SWC and esbuild projects enable. const rewritten = model.result.replace( originalExport, - `export { ${model.modelName}, ${interfaceName} };` + `export { ${model.modelName} };\nexport type { ${interfaceName} };` ); return OutputModel.toOutputModel({ result: rewritten, diff --git a/src/codegen/index.ts b/src/codegen/index.ts index 32244476..04198fe8 100644 --- a/src/codegen/index.ts +++ b/src/codegen/index.ts @@ -1,6 +1,7 @@ export {loadAsyncapi, loadAsyncapiFromMemory} from './inputs/asyncapi'; export {loadOpenapi, loadOpenapiFromMemory} from './inputs/openapi'; export {loadJsonSchema, loadJsonSchemaFromMemory} from './inputs/jsonschema'; +export {writeGeneratedFiles, generateModels} from './output'; export { defaultTypeScriptChannelsGenerator, diff --git a/src/codegen/modelina/presets/validation.ts b/src/codegen/modelina/presets/validation.ts index d18378b9..d73e9749 100644 --- a/src/codegen/modelina/presets/validation.ts +++ b/src/codegen/modelina/presets/validation.ts @@ -115,10 +115,12 @@ export function generateTypescriptValidationCode({ '{Ajv, Options as AjvOptions, ErrorObject, ValidateFunction}', 'ajv' ); - // Use named import with default alias for compatibility without esModuleInterop - // This works with both esModuleInterop: true and verbatimModuleSyntax: true + // Import the module rather than its `default` binding directly. `ajv-formats` + // ships as CommonJS, and under `moduleResolution: node16`/`nodenext` a + // `{default as addFormats}` (or plain default) import resolves to the module + // namespace, which is not callable. The call site unwraps `.default` instead. renderer.dependencyManager.addTypeScriptDependency( - '{default as addFormats}', + 'addFormatsModule', 'ajv-formats' ); @@ -156,6 +158,9 @@ ${methodPrefix}validate(context?: {data: any, ajvValidatorFunction?: ValidateFun } ${methodPrefix}createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // \`ajv-formats\` is CommonJS; its default import is the module namespace under + // \`moduleResolution: node16\`/\`nodenext\`, so unwrap \`.default\` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ${vocabularies} const validate = ajvInstance.compile(${compileCall}); diff --git a/src/codegen/output/index.ts b/src/codegen/output/index.ts index 667ec262..157f7cf9 100644 --- a/src/codegen/output/index.ts +++ b/src/codegen/output/index.ts @@ -10,7 +10,7 @@ import {FileSystemAdapter} from './filesystem'; export * from './types'; export {FileSystemAdapter} from './filesystem'; export {MemoryAdapter} from './memory'; -export {generateModels} from './modelina'; +export {generateModels, applyImportExtension} from './modelina'; export type {GenerateModelsArgs, GenerateModelsResult} from './modelina'; // Re-export GeneratedFile type for convenience diff --git a/src/codegen/output/modelina.ts b/src/codegen/output/modelina.ts index e02f41b2..d4e0d0a3 100644 --- a/src/codegen/output/modelina.ts +++ b/src/codegen/output/modelina.ts @@ -10,6 +10,7 @@ import { OutputModel } from '@asyncapi/modelina'; import {GeneratedFile} from '../types'; +import {ImportExtension} from '../utils'; export interface GenerateModelsArgs { /** The Modelina generator instance */ @@ -20,6 +21,47 @@ export interface GenerateModelsArgs { outputPath: string; /** Optional render options */ options?: Partial; + /** + * Extension to append to the relative imports Modelina renders between models + * (for example the enum a model was split into). Modelina has no option for + * this, so it is applied to the rendered output here. + */ + importExtension?: ImportExtension; +} + +/** + * Matches the module specifier of a relative import/export/require that Modelina + * renders between models, e.g. `from './Address'` or `require('./Address')`. + * Specifiers that already carry an extension are left alone. + */ +const RELATIVE_MODULE_SPECIFIER = + /(from\s+|require\(\s*)(['"])(\.{1,2}\/[^'"]*)\2/g; + +/** + * Appends `extension` to every extensionless relative module specifier in a + * rendered model file. Modelina always renders cross-model dependencies as + * `./` with no extension, which does not compile under + * `moduleResolution: node16`/`nodenext`. + */ +export function applyImportExtension({ + content, + extension +}: { + content: string; + extension: ImportExtension; +}): string { + if (extension === 'none') { + return content; + } + return content.replace( + RELATIVE_MODULE_SPECIFIER, + (match, keyword, quote, specifier) => { + if (/\.[a-zA-Z0-9]+$/.test(specifier)) { + return match; + } + return `${keyword}${quote}${specifier}${extension}${quote}`; + } + ); } export interface GenerateModelsResult { @@ -39,7 +81,8 @@ export async function generateModels({ generator, input, outputPath, - options = {} + options = {}, + importExtension = 'none' }: GenerateModelsArgs): Promise { const files: GeneratedFile[] = []; @@ -57,7 +100,13 @@ export async function generateModels({ const fileName = `${model.modelName}.ts`; const filePath = `${outputPath}/${fileName}`; - files.push({path: filePath, content: model.result}); + files.push({ + path: filePath, + content: applyImportExtension({ + content: model.result, + extension: importExtension + }) + }); } return { diff --git a/src/codegen/types.ts b/src/codegen/types.ts index e2b75791..fe0593ec 100644 --- a/src/codegen/types.ts +++ b/src/codegen/types.ts @@ -206,6 +206,13 @@ export interface SingleFunctionRenderType { * methods accept the same ergonomic plain object the channel functions do. */ messageUnionType?: string; + /** + * The header type used in the channel function's callback, when the channel + * has headers. Consumed by the client generator so its wrapper subscribe + * methods declare the same callback signature as the channel function they + * delegate to. + */ + headerType?: string; replyType?: string; /** * Grouping metadata used by the channels generator's `organization` option. diff --git a/src/index.ts b/src/index.ts index 3bae4c92..a214f843 100644 --- a/src/index.ts +++ b/src/index.ts @@ -30,6 +30,7 @@ export { SingleFunctionRenderType, runGenerators, loadAsyncapi, + loadOpenapi, loadJsonSchema, getDefaultConfiguration, renderGenerator, @@ -41,6 +42,7 @@ export { loadOpenapiFromMemory, loadAsyncapiFromMemory, loadJsonSchemaFromMemory, + writeGeneratedFiles, ChannelFunctionTypes } from './codegen'; diff --git a/test/blackbox/projects/typescript/package.json b/test/blackbox/projects/typescript/package.json index 63661750..126712d2 100644 --- a/test/blackbox/projects/typescript/package.json +++ b/test/blackbox/projects/typescript/package.json @@ -2,6 +2,8 @@ "name": "temp", "version": "0.0.0", "dependencies": { + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", "nats": "2.28.2", "kafkajs": "^2.2.4", "mqtt": "^5.10.3", diff --git a/test/blackbox/typescript.spec.ts b/test/blackbox/typescript.spec.ts index de00550d..4a05430e 100644 --- a/test/blackbox/typescript.spec.ts +++ b/test/blackbox/typescript.spec.ts @@ -1,7 +1,7 @@ import * as path from 'path'; import * as fs from 'fs'; import {filesToTest, typescriptConfig, isKnownFailing } from './test_files'; -import {loadAsyncapi, loadJsonSchema, loadConfigFile, realizeConfiguration, RunGeneratorContext, runGenerators } from '../../src'; +import {loadAsyncapi, loadOpenapi, loadJsonSchema, loadConfigFile, realizeConfiguration, RunGeneratorContext, runGenerators, writeGeneratedFiles } from '../../src'; import { execCommand } from './utils'; jest.setTimeout(100000); @@ -43,7 +43,7 @@ describe.each(typescriptConfig)( const newConfig = {...config} const newGens = [...newConfig.generators] newConfig.generators = [] - newConfig.inputPath = path.resolve('./', schemaFile.file); + newConfig.inputPath = path.resolve('./test/blackbox/', schemaFile.file); const outputDirectoryPath = outputPath; for (let [index, generator] of Object.entries(newGens)) { @@ -59,13 +59,27 @@ describe.each(typescriptConfig)( if (newConfig.inputType === 'asyncapi') { const document = await loadAsyncapi(context); context.asyncapiDocument = document; + } else if (newConfig.inputType === 'openapi') { + const document = await loadOpenapi(context); + context.openapiDocument = document; } else if (newConfig.inputType === 'jsonschema') { const document = await loadJsonSchema(context); context.jsonSchemaDocument = document; } - await runGenerators(context); + const result = await runGenerators(context); + // `runGenerators` is pure and returns the files in memory; writing them + // is the caller's job (see the `generate` command). Without this step the + // suite compiles an empty project and passes no matter what was generated. + await writeGeneratedFiles(result.files, path.dirname(filePath)); + // Everything that was generated must reach the compiler below. + for (const file of result.files) { + expect(fs.existsSync(file.path)).toEqual(true); + } fs.cpSync(path.resolve(__dirname, './projects/typescript'), path.resolve(outputDirectoryPath), {recursive: true}); const srcDirectory = path.resolve(outputDirectoryPath, './src'); + // Some config/document pairs legitimately generate nothing (a parameters + // config against a document with no channel parameters, for example), so + // give `tsc` an entry point rather than failing the pair. if(!fs.existsSync(srcDirectory)) { fs.mkdirSync(srcDirectory) fs.writeFileSync(path.resolve(srcDirectory, './index.ts'), '') diff --git a/test/codegen/generators/typescript/__snapshots__/headers.spec.ts.snap b/test/codegen/generators/typescript/__snapshots__/headers.spec.ts.snap index 78dfcaa8..c1c50c6a 100644 --- a/test/codegen/generators/typescript/__snapshots__/headers.spec.ts.snap +++ b/test/codegen/generators/typescript/__snapshots__/headers.spec.ts.snap @@ -26,7 +26,7 @@ export { DeletePetHeaders };" exports[`headers typescript should work with basic AsyncAPI inputs 1`] = ` "import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class SimpleObjectHeaders { private _displayName?: string; private _email?: string; @@ -116,6 +116,9 @@ class SimpleObjectHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // \`ajv-formats\` is CommonJS; its default import is the module namespace under + // \`moduleResolution: node16\`/\`nodenext\`, so unwrap \`.default\` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/test/codegen/generators/typescript/__snapshots__/parameters.spec.ts.snap b/test/codegen/generators/typescript/__snapshots__/parameters.spec.ts.snap index d638d4c2..f9603ed9 100644 --- a/test/codegen/generators/typescript/__snapshots__/parameters.spec.ts.snap +++ b/test/codegen/generators/typescript/__snapshots__/parameters.spec.ts.snap @@ -42,7 +42,8 @@ class SingleParameterParameters { return parameters; } } -export { SingleParameterParameters, SingleParameterParametersInterface };" +export { SingleParameterParameters }; +export type { SingleParameterParametersInterface };" `; exports[`parameters typescript asyncapi should work with AsyncAPI that contains parameters 2`] = ` @@ -100,7 +101,8 @@ class MultipleParameterParameters { return parameters; } } -export { MultipleParameterParameters, MultipleParameterParametersInterface };" +export { MultipleParameterParameters }; +export type { MultipleParameterParametersInterface };" `; exports[`parameters typescript asyncapi should work with AsyncAPI v2 that contains parameters and const parameters 1`] = ` @@ -145,7 +147,8 @@ class SingleParameterParameters { return parameters; } } -export { SingleParameterParameters, SingleParameterParametersInterface };" +export { SingleParameterParameters }; +export type { SingleParameterParametersInterface };" `; exports[`parameters typescript asyncapi should work with AsyncAPI v2 that contains parameters and const parameters 2`] = ` @@ -200,7 +203,8 @@ class MultipleParameterParameters { return parameters; } } -export { MultipleParameterParameters, MultipleParameterParametersInterface };" +export { MultipleParameterParameters }; +export type { MultipleParameterParametersInterface };" `; exports[`parameters typescript openapi should use constrained property names and skip deserializeUrl without query parameters 1`] = ` @@ -324,7 +328,8 @@ class GetDocumentParameters { return result; } } -export { GetDocumentParameters, GetDocumentParametersInterface };" +export { GetDocumentParameters }; +export type { GetDocumentParametersInterface };" `; exports[`parameters typescript openapi should use constrained property names and skip deserializeUrl without query parameters 2`] = ` @@ -467,7 +472,8 @@ class GetTransactionsParameters { return instance; } } -export { GetTransactionsParameters, GetTransactionsParametersInterface };" +export { GetTransactionsParameters }; +export type { GetTransactionsParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 2.0 that contains parameters 1`] = ` @@ -594,7 +600,8 @@ class DeleteOrderParameters { return result; } } -export { DeleteOrderParameters, DeleteOrderParametersInterface };" +export { DeleteOrderParameters }; +export type { DeleteOrderParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 2.0 that contains parameters 2`] = ` @@ -721,7 +728,8 @@ class DeletePetParameters { return result; } } -export { DeletePetParameters, DeletePetParametersInterface };" +export { DeletePetParameters }; +export type { DeletePetParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 2.0 that contains parameters 3`] = ` @@ -848,7 +856,8 @@ class DeleteUserParameters { return result; } } -export { DeleteUserParameters, DeleteUserParametersInterface };" +export { DeleteUserParameters }; +export type { DeleteUserParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 2.0 that contains parameters 4`] = ` @@ -967,7 +976,8 @@ class FindPetsByStatusParameters { return instance; } } -export { FindPetsByStatusParameters, FindPetsByStatusParametersInterface };" +export { FindPetsByStatusParameters }; +export type { FindPetsByStatusParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 2.0 that contains parameters 5`] = ` @@ -1086,7 +1096,8 @@ class FindPetsByTagsParameters { return instance; } } -export { FindPetsByTagsParameters, FindPetsByTagsParametersInterface };" +export { FindPetsByTagsParameters }; +export type { FindPetsByTagsParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 2.0 that contains parameters 6`] = ` @@ -1213,7 +1224,8 @@ class GetOrderByIdParameters { return result; } } -export { GetOrderByIdParameters, GetOrderByIdParametersInterface };" +export { GetOrderByIdParameters }; +export type { GetOrderByIdParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 2.0 that contains parameters 7`] = ` @@ -1340,7 +1352,8 @@ class GetPetByIdParameters { return result; } } -export { GetPetByIdParameters, GetPetByIdParametersInterface };" +export { GetPetByIdParameters }; +export type { GetPetByIdParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 2.0 that contains parameters 8`] = ` @@ -1467,7 +1480,8 @@ class GetUserByNameParameters { return result; } } -export { GetUserByNameParameters, GetUserByNameParametersInterface };" +export { GetUserByNameParameters }; +export type { GetUserByNameParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 2.0 that contains parameters 9`] = ` @@ -1614,7 +1628,8 @@ class LoginUserParameters { return instance; } } -export { LoginUserParameters, LoginUserParametersInterface };" +export { LoginUserParameters }; +export type { LoginUserParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 2.0 that contains parameters 10`] = ` @@ -1741,7 +1756,8 @@ class UpdatePetWithFormParameters { return result; } } -export { UpdatePetWithFormParameters, UpdatePetWithFormParametersInterface };" +export { UpdatePetWithFormParameters }; +export type { UpdatePetWithFormParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 2.0 that contains parameters 11`] = ` @@ -1868,7 +1884,8 @@ class UpdateUserParameters { return result; } } -export { UpdateUserParameters, UpdateUserParametersInterface };" +export { UpdateUserParameters }; +export type { UpdateUserParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 2.0 that contains parameters 12`] = ` @@ -1995,7 +2012,8 @@ class UploadFileParameters { return result; } } -export { UploadFileParameters, UploadFileParametersInterface };" +export { UploadFileParameters }; +export type { UploadFileParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.0 that contains parameters 1`] = ` @@ -2122,7 +2140,8 @@ class DeleteOrderParameters { return result; } } -export { DeleteOrderParameters, DeleteOrderParametersInterface };" +export { DeleteOrderParameters }; +export type { DeleteOrderParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.0 that contains parameters 2`] = ` @@ -2249,7 +2268,8 @@ class DeletePetParameters { return result; } } -export { DeletePetParameters, DeletePetParametersInterface };" +export { DeletePetParameters }; +export type { DeletePetParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.0 that contains parameters 3`] = ` @@ -2376,7 +2396,8 @@ class DeleteUserParameters { return result; } } -export { DeleteUserParameters, DeleteUserParametersInterface };" +export { DeleteUserParameters }; +export type { DeleteUserParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.0 that contains parameters 4`] = ` @@ -2497,7 +2518,8 @@ class FindPetsByStatusParameters { return instance; } } -export { FindPetsByStatusParameters, FindPetsByStatusParametersInterface };" +export { FindPetsByStatusParameters }; +export type { FindPetsByStatusParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.0 that contains parameters 5`] = ` @@ -2618,7 +2640,8 @@ class FindPetsByTagsParameters { return instance; } } -export { FindPetsByTagsParameters, FindPetsByTagsParametersInterface };" +export { FindPetsByTagsParameters }; +export type { FindPetsByTagsParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.0 that contains parameters 6`] = ` @@ -2745,7 +2768,8 @@ class GetOrderByIdParameters { return result; } } -export { GetOrderByIdParameters, GetOrderByIdParametersInterface };" +export { GetOrderByIdParameters }; +export type { GetOrderByIdParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.0 that contains parameters 7`] = ` @@ -2872,7 +2896,8 @@ class GetPetByIdParameters { return result; } } -export { GetPetByIdParameters, GetPetByIdParametersInterface };" +export { GetPetByIdParameters }; +export type { GetPetByIdParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.0 that contains parameters 8`] = ` @@ -2999,7 +3024,8 @@ class GetUserByNameParameters { return result; } } -export { GetUserByNameParameters, GetUserByNameParametersInterface };" +export { GetUserByNameParameters }; +export type { GetUserByNameParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.0 that contains parameters 9`] = ` @@ -3146,7 +3172,8 @@ class LoginUserParameters { return instance; } } -export { LoginUserParameters, LoginUserParametersInterface };" +export { LoginUserParameters }; +export type { LoginUserParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.0 that contains parameters 10`] = ` @@ -3273,7 +3300,8 @@ class UpdatePetWithFormParameters { return result; } } -export { UpdatePetWithFormParameters, UpdatePetWithFormParametersInterface };" +export { UpdatePetWithFormParameters }; +export type { UpdatePetWithFormParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.0 that contains parameters 11`] = ` @@ -3400,7 +3428,8 @@ class UpdateUserParameters { return result; } } -export { UpdateUserParameters, UpdateUserParametersInterface };" +export { UpdateUserParameters }; +export type { UpdateUserParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.0 that contains parameters 12`] = ` @@ -3527,7 +3556,8 @@ class UploadFileParameters { return result; } } -export { UploadFileParameters, UploadFileParametersInterface };" +export { UploadFileParameters }; +export type { UploadFileParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.1 that contains parameters 1`] = ` @@ -3654,7 +3684,8 @@ class DeleteOrderParameters { return result; } } -export { DeleteOrderParameters, DeleteOrderParametersInterface };" +export { DeleteOrderParameters }; +export type { DeleteOrderParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.1 that contains parameters 2`] = ` @@ -3781,7 +3812,8 @@ class DeletePetParameters { return result; } } -export { DeletePetParameters, DeletePetParametersInterface };" +export { DeletePetParameters }; +export type { DeletePetParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.1 that contains parameters 3`] = ` @@ -3908,7 +3940,8 @@ class DeleteUserParameters { return result; } } -export { DeleteUserParameters, DeleteUserParametersInterface };" +export { DeleteUserParameters }; +export type { DeleteUserParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.1 that contains parameters 4`] = ` @@ -4029,7 +4062,8 @@ class FindPetsByStatusParameters { return instance; } } -export { FindPetsByStatusParameters, FindPetsByStatusParametersInterface };" +export { FindPetsByStatusParameters }; +export type { FindPetsByStatusParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.1 that contains parameters 5`] = ` @@ -4150,7 +4184,8 @@ class FindPetsByTagsParameters { return instance; } } -export { FindPetsByTagsParameters, FindPetsByTagsParametersInterface };" +export { FindPetsByTagsParameters }; +export type { FindPetsByTagsParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.1 that contains parameters 6`] = ` @@ -4277,7 +4312,8 @@ class GetOrderByIdParameters { return result; } } -export { GetOrderByIdParameters, GetOrderByIdParametersInterface };" +export { GetOrderByIdParameters }; +export type { GetOrderByIdParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.1 that contains parameters 7`] = ` @@ -4404,7 +4440,8 @@ class GetPetByIdParameters { return result; } } -export { GetPetByIdParameters, GetPetByIdParametersInterface };" +export { GetPetByIdParameters }; +export type { GetPetByIdParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.1 that contains parameters 8`] = ` @@ -4531,7 +4568,8 @@ class GetUserByNameParameters { return result; } } -export { GetUserByNameParameters, GetUserByNameParametersInterface };" +export { GetUserByNameParameters }; +export type { GetUserByNameParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.1 that contains parameters 9`] = ` @@ -4678,7 +4716,8 @@ class LoginUserParameters { return instance; } } -export { LoginUserParameters, LoginUserParametersInterface };" +export { LoginUserParameters }; +export type { LoginUserParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.1 that contains parameters 10`] = ` @@ -4805,7 +4844,8 @@ class UpdatePetWithFormParameters { return result; } } -export { UpdatePetWithFormParameters, UpdatePetWithFormParametersInterface };" +export { UpdatePetWithFormParameters }; +export type { UpdatePetWithFormParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.1 that contains parameters 11`] = ` @@ -4932,7 +4972,8 @@ class UpdateUserParameters { return result; } } -export { UpdateUserParameters, UpdateUserParametersInterface };" +export { UpdateUserParameters }; +export type { UpdateUserParametersInterface };" `; exports[`parameters typescript openapi should work with OpenAPI 3.1 that contains parameters 12`] = ` @@ -5059,5 +5100,6 @@ class UploadFileParameters { return result; } } -export { UploadFileParameters, UploadFileParametersInterface };" +export { UploadFileParameters }; +export type { UploadFileParametersInterface };" `; diff --git a/test/codegen/generators/typescript/__snapshots__/payload.spec.ts.snap b/test/codegen/generators/typescript/__snapshots__/payload.spec.ts.snap index b59c01f8..f2fa490f 100644 --- a/test/codegen/generators/typescript/__snapshots__/payload.spec.ts.snap +++ b/test/codegen/generators/typescript/__snapshots__/payload.spec.ts.snap @@ -104,13 +104,14 @@ class SimpleObject2 { return SimpleObject2.fromJson(obj as Record); } } -export { SimpleObject2, SimpleObject2Interface };" +export { SimpleObject2 }; +export type { SimpleObject2Interface };" `; exports[`payloads typescript should work with basic AsyncAPI inputs 1`] = ` "import {SimpleObject} from './SimpleObject'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type UnionPayload = SimpleObject | boolean | string; export function unmarshal(json: any): UnionPayload { @@ -145,6 +146,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // \`ajv-formats\` is CommonJS; its default import is the module namespace under + // \`moduleResolution: node16\`/\`nodenext\`, so unwrap \`.default\` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); @@ -157,7 +161,7 @@ export { UnionPayload };" exports[`payloads typescript should work with basic AsyncAPI inputs 2`] = ` "import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface SimpleObject2Interface { displayName?: string email?: string @@ -248,6 +252,9 @@ class SimpleObject2 { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // \`ajv-formats\` is CommonJS; its default import is the module namespace under + // \`moduleResolution: node16\`/\`nodenext\`, so unwrap \`.default\` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -255,12 +262,13 @@ class SimpleObject2 { } } -export { SimpleObject2, SimpleObject2Interface };" +export { SimpleObject2 }; +export type { SimpleObject2Interface };" `; exports[`payloads typescript should work with no channels 1`] = ` "import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface SimpleObjectInterface { displayName?: string email?: string @@ -357,6 +365,9 @@ class SimpleObject { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // \`ajv-formats\` is CommonJS; its default import is the module namespace under + // \`moduleResolution: node16\`/\`nodenext\`, so unwrap \`.default\` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -364,5 +375,6 @@ class SimpleObject { } } -export { SimpleObject, SimpleObjectInterface };" +export { SimpleObject }; +export type { SimpleObjectInterface };" `; diff --git a/test/codegen/generators/typescript/channels/header-union.spec.ts b/test/codegen/generators/typescript/channels/header-union.spec.ts new file mode 100644 index 00000000..e4f39b02 --- /dev/null +++ b/test/codegen/generators/typescript/channels/header-union.spec.ts @@ -0,0 +1,135 @@ +/** + * Tests for how channel header models are referenced in generated code. + * + * A channel whose messages each declare their own headers produces a `oneOf` + * union model. Its `type` is the expanded union (`A | B | C`) — referencing it + * directly emits identifiers the generated file never imports, and there is no + * static `unmarshal` on a type alias for the receive paths to call. Union + * header models are therefore imported as a namespace, the same way payload + * unions are. + */ +import { + addHeadersToDependencies, + getHeaderTypeAndModule +} from '../../../../../src/codegen/generators/typescript/channels/utils'; +import { + ConstrainedObjectModel, + ConstrainedUnionModel, + OutputModel +} from '@asyncapi/modelina'; + +const objectHeaders = new ConstrainedObjectModel( + 'UserSignedUpHeaders', + undefined, + {}, + 'UserSignedUpHeaders', + {} +); + +const unionHeaders = new ConstrainedUnionModel( + 'OrderLifecycleHeaders', + undefined, + {}, + 'OrderCreatedHeaders | OrderUpdatedHeaders | OrderCancelledHeaders', + [ + new ConstrainedObjectModel( + 'OrderCreatedHeaders', + undefined, + {}, + 'OrderCreatedHeaders', + {} + ), + new ConstrainedObjectModel( + 'OrderUpdatedHeaders', + undefined, + {}, + 'OrderUpdatedHeaders', + {} + ) + ] +); + +const asOutputModel = (model: ConstrainedObjectModel | ConstrainedUnionModel) => + new OutputModel( + '', + model, + model.name, + {models: {}, originalInput: undefined}, + [] + ); + +describe('getHeaderTypeAndModule', () => { + it('returns undefined for a channel without headers', () => { + expect(getHeaderTypeAndModule(undefined)).toEqual({ + headerType: undefined, + headerModule: undefined + }); + }); + + it('uses the model type directly for a single-message header model', () => { + expect(getHeaderTypeAndModule(objectHeaders)).toEqual({ + headerType: 'UserSignedUpHeaders', + headerModule: undefined + }); + }); + + it('routes a union header model through its namespace module', () => { + // Not the expanded `A | B | C` — those members are never imported, and the + // runtime helpers live on the module. + expect(getHeaderTypeAndModule(unionHeaders)).toEqual({ + headerType: 'OrderLifecycleHeadersModule.OrderLifecycleHeaders', + headerModule: 'OrderLifecycleHeadersModule' + }); + }); +}); + +describe('addHeadersToDependencies', () => { + const headerGenerator = {outputPath: './src/__gen__/channels/headers'}; + const currentGenerator = {outputPath: './src/__gen__/channels'}; + + it('emits a named import for a single-message header model', () => { + const dependencies: string[] = []; + + addHeadersToDependencies( + {channel: asOutputModel(objectHeaders)}, + headerGenerator, + currentGenerator, + dependencies + ); + + expect(dependencies).toEqual([ + `import {UserSignedUpHeaders} from './headers/UserSignedUpHeaders';` + ]); + }); + + it('emits a namespace import for a union header model', () => { + const dependencies: string[] = []; + + addHeadersToDependencies( + {channel: asOutputModel(unionHeaders)}, + headerGenerator, + currentGenerator, + dependencies + ); + + expect(dependencies).toEqual([ + `import * as OrderLifecycleHeadersModule from './headers/OrderLifecycleHeaders';` + ]); + }); + + it('applies the import extension to the namespace import', () => { + const dependencies: string[] = []; + + addHeadersToDependencies( + {channel: asOutputModel(unionHeaders)}, + headerGenerator, + currentGenerator, + dependencies, + '.js' + ); + + expect(dependencies).toEqual([ + `import * as OrderLifecycleHeadersModule from './headers/OrderLifecycleHeaders.js';` + ]); + }); +}); diff --git a/test/codegen/generators/typescript/client.spec.ts b/test/codegen/generators/typescript/client.spec.ts index 63c3b7a1..1479dcd7 100644 --- a/test/codegen/generators/typescript/client.spec.ts +++ b/test/codegen/generators/typescript/client.spec.ts @@ -1,5 +1,6 @@ import path from "node:path"; import { defaultTypeScriptClientGenerator, generateTypeScriptClient, TypeScriptParameterRenderType } from "../../../../src/codegen/generators"; +import { TypeScriptHeadersRenderType } from "../../../../src/codegen/generators/typescript/headers"; import { loadAsyncapiDocument } from "../../../../src/codegen/inputs/asyncapi"; import { ConstrainedAnyModel, ConstrainedObjectModel, OutputModel } from "@asyncapi/modelina"; import { ChannelFunctionTypes, defaultTypeScriptChannelsGenerator, TypeScriptChannelRenderType } from "../../../../src/codegen/generators/typescript/channels"; @@ -31,10 +32,17 @@ describe('client', () => { generator: {outputPath: './test'} as any, files: [] }; + const headersDependency: TypeScriptHeadersRenderType = { + channelModels: {}, + generator: {outputPath: './test'} as any, + headerFunctions: {}, + files: [] + }; const channelsDependency: TypeScriptChannelRenderType = { payloadRender: payloadsDependency, result: '', parameterRender: parametersDependency, + headerRender: headersDependency, renderedFunctions: { nats: [ { @@ -105,10 +113,17 @@ describe('client', () => { generator: {outputPath: './test'} as any, files: [] }; + const headersDependency: TypeScriptHeadersRenderType = { + channelModels: {}, + generator: {outputPath: './test'} as any, + headerFunctions: {}, + files: [] + }; const channelsDependency: TypeScriptChannelRenderType = { payloadRender: payloadsDependency, result: '', parameterRender: parametersDependency, + headerRender: headersDependency, renderedFunctions: { http_client: [ { @@ -153,10 +168,17 @@ describe('client', () => { generator: {outputPath: './test'} as any, files: [] }; + const headersDependency: TypeScriptHeadersRenderType = { + channelModels: {}, + generator: {outputPath: './test'} as any, + headerFunctions: {}, + files: [] + }; const channelsDependency: TypeScriptChannelRenderType = { payloadRender: payloadsDependency, result: '', parameterRender: parametersDependency, + headerRender: headersDependency, renderedFunctions: {http_client: []}, generator: defaultTypeScriptChannelsGenerator, protocolFiles: {}, diff --git a/test/codegen/generators/typescript/payload.spec.ts b/test/codegen/generators/typescript/payload.spec.ts index 53bdeb01..c23404a8 100644 --- a/test/codegen/generators/typescript/payload.spec.ts +++ b/test/codegen/generators/typescript/payload.spec.ts @@ -380,7 +380,10 @@ describe('payloads', () => { expect(result).toContain('interface SimpleObject2Interface {'); expect(result).toContain('constructor(input: SimpleObject2Interface)'); - expect(result).toContain('export { SimpleObject2, SimpleObject2Interface };'); + // The companion is a type, so it is re-exported with `export type` — + // a combined value export breaks under `isolatedModules: true` (TS1205). + expect(result).toContain('export { SimpleObject2 };'); + expect(result).toContain('export type { SimpleObject2Interface };'); }); it('includes every accepted ctor property (including additionalProperties) in the companion interface', async () => { diff --git a/test/codegen/modelina/presets/validation.spec.ts b/test/codegen/modelina/presets/validation.spec.ts index 71c2ced5..bb0892da 100644 --- a/test/codegen/modelina/presets/validation.spec.ts +++ b/test/codegen/modelina/presets/validation.spec.ts @@ -33,7 +33,7 @@ const createMockModel = () => ({ describe('Validation Preset', () => { describe('ajv-formats import', () => { - it('should use named import with default alias for ajv-formats', () => { + it('should import the ajv-formats module, not its default binding', () => { const mockRenderer = createMockRenderer(); const mockModel = createMockModel(); const context = { @@ -54,14 +54,14 @@ describe('Validation Preset', () => { (d) => d.from === 'ajv-formats' ); expect(ajvFormatsDep).toBeDefined(); - // Should use named import pattern that works without esModuleInterop - // Either: `{default as addFormats}` or `* as addFormatsModule` - expect(ajvFormatsDep?.what).toMatch( - /(\{default as addFormats\})|(\* as \w+)/ - ); + // `ajv-formats` is CommonJS. Under `moduleResolution: node16`/`nodenext` + // both `addFormats` and `{default as addFormats}` resolve to the module + // namespace, which is not callable (TS2349), so the module itself is + // imported and the call site unwraps `.default`. + expect(ajvFormatsDep?.what).toBe('addFormatsModule'); }); - it('should not use bare default import for ajv-formats', () => { + it('should not import the default binding directly for ajv-formats', () => { const mockRenderer = createMockRenderer(); const mockModel = createMockModel(); const context = { @@ -81,8 +81,9 @@ describe('Validation Preset', () => { const ajvFormatsDep = mockRenderer.dependencies.find( (d) => d.from === 'ajv-formats' ); - // Should NOT be a bare default import + // Neither of these is callable under node16/nodenext resolution. expect(ajvFormatsDep?.what).not.toBe('addFormats'); + expect(ajvFormatsDep?.what).not.toBe('{default as addFormats}'); }); }); diff --git a/test/codegen/output/modelina-import-extension.spec.ts b/test/codegen/output/modelina-import-extension.spec.ts new file mode 100644 index 00000000..9ffa1018 --- /dev/null +++ b/test/codegen/output/modelina-import-extension.spec.ts @@ -0,0 +1,70 @@ +/** + * Tests for the import-extension pass applied to Modelina's rendered models. + * + * Modelina renders the imports between models (an object model and the enum it + * was split into, for example) as `./` with no extension, and it has + * no option to change that. Those imports do not compile under + * `moduleResolution: node16`/`nodenext`, so the extension is applied to the + * rendered output instead. + */ +import {applyImportExtension} from '../../../src/codegen/output/modelina'; + +describe('applyImportExtension', () => { + it('leaves content untouched when the extension is "none"', () => { + const content = `import {Command} from './Command';\nexport {Thing};`; + + expect(applyImportExtension({content, extension: 'none'})).toEqual(content); + }); + + it('appends the extension to relative cross-model imports', () => { + const content = `import {Command} from './Command';\nimport {Money} from './nested/Money';`; + + expect(applyImportExtension({content, extension: '.js'})).toEqual( + `import {Command} from './Command.js';\nimport {Money} from './nested/Money.js';` + ); + }); + + it('supports the .ts extension', () => { + const content = `import {Command} from './Command';`; + + expect(applyImportExtension({content, extension: '.ts'})).toEqual( + `import {Command} from './Command.ts';` + ); + }); + + it('leaves bare module specifiers untouched', () => { + const content = `import {Ajv} from 'ajv';\nimport addFormatsModule from 'ajv-formats';`; + + expect(applyImportExtension({content, extension: '.js'})).toEqual(content); + }); + + it('does not double-append when a specifier already has an extension', () => { + const content = `import {Command} from './Command.js';`; + + expect(applyImportExtension({content, extension: '.js'})).toEqual(content); + }); + + it('handles parent-relative specifiers and double quotes', () => { + const content = `import {Money} from "../payloads/Money";`; + + expect(applyImportExtension({content, extension: '.js'})).toEqual( + `import {Money} from "../payloads/Money.js";` + ); + }); + + it('handles type-only imports and exports', () => { + const content = `import type {Command} from './Command';\nexport type {Command} from './Command';`; + + expect(applyImportExtension({content, extension: '.js'})).toEqual( + `import type {Command} from './Command.js';\nexport type {Command} from './Command.js';` + ); + }); + + it('handles CommonJS require specifiers', () => { + const content = `const {Command} = require('./Command');`; + + expect(applyImportExtension({content, extension: '.js'})).toEqual( + `const {Command} = require('./Command.js');` + ); + }); +}); diff --git a/test/runtime/typescript/package-lock.json b/test/runtime/typescript/package-lock.json index 2b2c4bb7..b29192e6 100644 --- a/test/runtime/typescript/package-lock.json +++ b/test/runtime/typescript/package-lock.json @@ -9,6 +9,7 @@ "@swc/core": "^1.3.5", "@swc/jest": "^0.2.23", "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", "amqplib": "^0.10.5", "body-parser": "^1.20.2", "express": "^4.21.0", @@ -1522,6 +1523,23 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/amqplib": { "version": "0.10.5", "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.10.5.tgz", diff --git a/test/runtime/typescript/package.json b/test/runtime/typescript/package.json index 554e67f1..f14131e1 100644 --- a/test/runtime/typescript/package.json +++ b/test/runtime/typescript/package.json @@ -13,7 +13,7 @@ "test:websocket": "jest -- ./test/channels/regular/websocket.spec.ts", "test:http": "jest -- ./test/channels/request_reply/http_client/", "test:payload-types": "jest -- ./test/payload-types/", - "generate": "npm run generate:regular && npm run generate:request:reply && npm run generate:openapi && npm run generate:openapi-primitive && npm run generate:payload-types && npm run generate:organization", + "generate": "npm run generate:regular && npm run generate:request:reply && npm run generate:openapi && npm run generate:openapi-primitive && npm run generate:payload-types && npm run generate:organization && npm run generate:node16", "generate:organization": "npm run generate:organization:openapi-tag && npm run generate:organization:openapi-path && npm run generate:organization:asyncapi-tag && npm run generate:organization:asyncapi-path", "generate:organization:openapi-tag": "cross-env CODEGEN_TELEMETRY_DISABLED=1 node ../../../bin/run.mjs generate ./codegen-openapi-tag.mjs", "generate:organization:openapi-path": "cross-env CODEGEN_TELEMETRY_DISABLED=1 node ../../../bin/run.mjs generate ./codegen-openapi-path.mjs", @@ -24,6 +24,7 @@ "generate:openapi": "cross-env CODEGEN_TELEMETRY_DISABLED=1 node ../../../bin/run.mjs generate ./codegen-openapi.mjs", "generate:openapi-primitive": "cross-env CODEGEN_TELEMETRY_DISABLED=1 node ../../../bin/run.mjs generate ./codegen-openapi-primitive.mjs", "generate:payload-types": "cross-env CODEGEN_TELEMETRY_DISABLED=1 node ../../../bin/run.mjs generate ./codegen-payload-types.mjs", + "generate:node16": "cross-env CODEGEN_TELEMETRY_DISABLED=1 node ../../../bin/run.mjs generate ./codegen-node16.mjs", "debug:generate": "node --inspect-brk ../../../bin/run.mjs generate" }, "dependencies": { @@ -31,6 +32,7 @@ "@swc/core": "^1.3.5", "@swc/jest": "^0.2.23", "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", "amqplib": "^0.10.5", "body-parser": "^1.20.2", "express": "^4.21.0", diff --git a/test/runtime/typescript/src/asyncapi-path-organization/channels/headers/UserSignedUpHeaders.ts b/test/runtime/typescript/src/asyncapi-path-organization/channels/headers/UserSignedUpHeaders.ts index d20d9d5a..c7ca7593 100644 --- a/test/runtime/typescript/src/asyncapi-path-organization/channels/headers/UserSignedUpHeaders.ts +++ b/test/runtime/typescript/src/asyncapi-path-organization/channels/headers/UserSignedUpHeaders.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class UserSignedUpHeaders { private _xTestHeader?: string; private _additionalProperties?: Map; @@ -74,6 +74,9 @@ class UserSignedUpHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/test/runtime/typescript/src/asyncapi-path-organization/channels/parameter/UserSignedupParameters.ts b/test/runtime/typescript/src/asyncapi-path-organization/channels/parameter/UserSignedupParameters.ts index 4195c425..db0c02ca 100644 --- a/test/runtime/typescript/src/asyncapi-path-organization/channels/parameter/UserSignedupParameters.ts +++ b/test/runtime/typescript/src/asyncapi-path-organization/channels/parameter/UserSignedupParameters.ts @@ -58,4 +58,5 @@ class UserSignedupParameters { return parameters; } } -export { UserSignedupParameters, UserSignedupParametersInterface }; \ No newline at end of file +export { UserSignedupParameters }; +export type { UserSignedupParametersInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/ArrayMessage.ts b/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/ArrayMessage.ts index e3d8a41c..14959285 100644 --- a/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/ArrayMessage.ts +++ b/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/ArrayMessage.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * An array of strings payload */ @@ -29,6 +29,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/LegacyNotification.ts b/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/LegacyNotification.ts index 8295e7c0..0dc0a368 100644 --- a/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/LegacyNotification.ts +++ b/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/LegacyNotification.ts @@ -1,6 +1,6 @@ import {LegacyNotificationPayloadLevelEnum} from './LegacyNotificationPayloadLevelEnum'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface LegacyNotificationInterface { message?: string level?: LegacyNotificationPayloadLevelEnum @@ -94,6 +94,9 @@ class LegacyNotification { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -101,4 +104,5 @@ class LegacyNotification { } } -export { LegacyNotification, LegacyNotificationInterface }; \ No newline at end of file +export { LegacyNotification }; +export type { LegacyNotificationInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/StringMessage.ts b/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/StringMessage.ts index b4efe734..443c9709 100644 --- a/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/StringMessage.ts +++ b/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/StringMessage.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * A simple string payload */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/UnionMessage.ts b/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/UnionMessage.ts index f2545d83..e8955759 100644 --- a/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/UnionMessage.ts +++ b/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/UnionMessage.ts @@ -1,6 +1,6 @@ import {UnionPayloadOneOfOption2} from './UnionPayloadOneOfOption2'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * A union type payload */ @@ -34,6 +34,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/UnionPayloadOneOfOption2.ts b/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/UnionPayloadOneOfOption2.ts index 7ed8cb00..1c3bb054 100644 --- a/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/UnionPayloadOneOfOption2.ts +++ b/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/UnionPayloadOneOfOption2.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface UnionPayloadOneOfOption2Interface { name?: string additionalProperties?: Record @@ -72,6 +72,9 @@ class UnionPayloadOneOfOption2 { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -79,4 +82,5 @@ class UnionPayloadOneOfOption2 { } } -export { UnionPayloadOneOfOption2, UnionPayloadOneOfOption2Interface }; \ No newline at end of file +export { UnionPayloadOneOfOption2 }; +export type { UnionPayloadOneOfOption2Interface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/UserSignedUp.ts b/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/UserSignedUp.ts index fa5f3407..1dabff95 100644 --- a/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/UserSignedUp.ts +++ b/test/runtime/typescript/src/asyncapi-path-organization/channels/payload/UserSignedUp.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface UserSignedUpInterface { displayName?: string email?: string @@ -93,6 +93,9 @@ class UserSignedUp { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -100,4 +103,5 @@ class UserSignedUp { } } -export { UserSignedUp, UserSignedUpInterface }; \ No newline at end of file +export { UserSignedUp }; +export type { UserSignedUpInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/asyncapi-tag-organization/channels/parameter/UserSignedupParameters.ts b/test/runtime/typescript/src/asyncapi-tag-organization/channels/parameter/UserSignedupParameters.ts index 1cd5731e..eaefe59b 100644 --- a/test/runtime/typescript/src/asyncapi-tag-organization/channels/parameter/UserSignedupParameters.ts +++ b/test/runtime/typescript/src/asyncapi-tag-organization/channels/parameter/UserSignedupParameters.ts @@ -42,4 +42,5 @@ class UserSignedupParameters { return parameters; } } -export { UserSignedupParameters, UserSignedupParametersInterface }; \ No newline at end of file +export { UserSignedupParameters }; +export type { UserSignedupParametersInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/asyncapi-tag-organization/channels/payload/AdminAlert.ts b/test/runtime/typescript/src/asyncapi-tag-organization/channels/payload/AdminAlert.ts index f1cbf645..dc933bd8 100644 --- a/test/runtime/typescript/src/asyncapi-tag-organization/channels/payload/AdminAlert.ts +++ b/test/runtime/typescript/src/asyncapi-tag-organization/channels/payload/AdminAlert.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface AdminAlertInterface { message?: string } @@ -56,6 +56,9 @@ class AdminAlert { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -63,4 +66,5 @@ class AdminAlert { } } -export { AdminAlert, AdminAlertInterface }; \ No newline at end of file +export { AdminAlert }; +export type { AdminAlertInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/asyncapi-tag-organization/channels/payload/SystemPing.ts b/test/runtime/typescript/src/asyncapi-tag-organization/channels/payload/SystemPing.ts index 270a8f08..0fc0e6d4 100644 --- a/test/runtime/typescript/src/asyncapi-tag-organization/channels/payload/SystemPing.ts +++ b/test/runtime/typescript/src/asyncapi-tag-organization/channels/payload/SystemPing.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface SystemPingInterface { timestamp?: Date } @@ -56,6 +56,9 @@ class SystemPing { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -63,4 +66,5 @@ class SystemPing { } } -export { SystemPing, SystemPingInterface }; \ No newline at end of file +export { SystemPing }; +export type { SystemPingInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/asyncapi-tag-organization/channels/payload/UserSignedUp.ts b/test/runtime/typescript/src/asyncapi-tag-organization/channels/payload/UserSignedUp.ts index f4cd3d94..a96e1ca5 100644 --- a/test/runtime/typescript/src/asyncapi-tag-organization/channels/payload/UserSignedUp.ts +++ b/test/runtime/typescript/src/asyncapi-tag-organization/channels/payload/UserSignedUp.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface UserSignedUpInterface { displayName?: string email?: string @@ -68,6 +68,9 @@ class UserSignedUp { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -75,4 +78,5 @@ class UserSignedUp { } } -export { UserSignedUp, UserSignedUpInterface }; \ No newline at end of file +export { UserSignedUp }; +export type { UserSignedUpInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/client/NatsClient.ts b/test/runtime/typescript/src/client/NatsClient.ts index 149eb794..116ebdef 100644 --- a/test/runtime/typescript/src/client/NatsClient.ts +++ b/test/runtime/typescript/src/client/NatsClient.ts @@ -14,6 +14,7 @@ export {UnionPayloadOneOfOption2}; export {LegacyNotificationPayloadLevelEnum}; import {UserSignedupParameters, UserSignedupParametersInterface} from './../parameters/UserSignedupParameters'; export {UserSignedupParameters}; +import {UserSignedUpHeaders} from './../headers/UserSignedUpHeaders'; //Import channel functions import * as nats from './../channels/nats'; @@ -185,7 +186,7 @@ export class NatsClient { options, flush }: { - onDataCallback: (err?: Error, msg?: UserSignedUp, parameters?: UserSignedupParameters, natsMsg?: Nats.Msg) => void, + onDataCallback: (err?: Error, msg?: UserSignedUp, parameters?: UserSignedupParameters, headers?: UserSignedUpHeaders, natsMsg?: Nats.Msg) => void, parameters: UserSignedupParameters, options?: Nats.SubscriptionOptions, flush?: boolean @@ -225,7 +226,7 @@ export class NatsClient { parameters, options = {} }: { - onDataCallback: (err?: Error, msg?: UserSignedUp, parameters?: UserSignedupParameters, jetstreamMsg?: Nats.JsMsg) => void, + onDataCallback: (err?: Error, msg?: UserSignedUp, parameters?: UserSignedupParameters, headers?: UserSignedUpHeaders, jetstreamMsg?: Nats.JsMsg) => void, parameters: UserSignedupParameters, options: Nats.ConsumerOptsBuilder | Partial }): Promise { @@ -262,7 +263,7 @@ export class NatsClient { parameters, options = {} }: { - onDataCallback: (err?: Error, msg?: UserSignedUp, parameters?: UserSignedupParameters, jetstreamMsg?: Nats.JsMsg) => void, + onDataCallback: (err?: Error, msg?: UserSignedUp, parameters?: UserSignedupParameters, headers?: UserSignedUpHeaders, jetstreamMsg?: Nats.JsMsg) => void, parameters: UserSignedupParameters, options: Nats.ConsumerOptsBuilder | Partial }): Promise { @@ -323,7 +324,7 @@ export class NatsClient { options, flush }: { - onDataCallback: (err?: Error, msg?: UserSignedUp, natsMsg?: Nats.Msg) => void, + onDataCallback: (err?: Error, msg?: UserSignedUp, headers?: UserSignedUpHeaders, natsMsg?: Nats.Msg) => void, options?: Nats.SubscriptionOptions, flush?: boolean }): Promise { @@ -359,7 +360,7 @@ export class NatsClient { onDataCallback, options = {} }: { - onDataCallback: (err?: Error, msg?: UserSignedUp, jetstreamMsg?: Nats.JsMsg) => void, + onDataCallback: (err?: Error, msg?: UserSignedUp, headers?: UserSignedUpHeaders, jetstreamMsg?: Nats.JsMsg) => void, options: Nats.ConsumerOptsBuilder | Partial }): Promise { return new Promise(async (resolve, reject) => { @@ -392,7 +393,7 @@ export class NatsClient { onDataCallback, options = {} }: { - onDataCallback: (err?: Error, msg?: UserSignedUp, jetstreamMsg?: Nats.JsMsg) => void, + onDataCallback: (err?: Error, msg?: UserSignedUp, headers?: UserSignedUpHeaders, jetstreamMsg?: Nats.JsMsg) => void, options: Nats.ConsumerOptsBuilder | Partial }): Promise { return new Promise(async (resolve, reject) => { diff --git a/test/runtime/typescript/src/headers/UserSignedUpHeaders.ts b/test/runtime/typescript/src/headers/UserSignedUpHeaders.ts index d20d9d5a..c7ca7593 100644 --- a/test/runtime/typescript/src/headers/UserSignedUpHeaders.ts +++ b/test/runtime/typescript/src/headers/UserSignedUpHeaders.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class UserSignedUpHeaders { private _xTestHeader?: string; private _additionalProperties?: Map; @@ -74,6 +74,9 @@ class UserSignedUpHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/test/runtime/typescript/src/node16/channels/nats.ts b/test/runtime/typescript/src/node16/channels/nats.ts index 81fe632b..fe73fc12 100644 --- a/test/runtime/typescript/src/node16/channels/nats.ts +++ b/test/runtime/typescript/src/node16/channels/nats.ts @@ -1,9 +1,9 @@ -import {UserSignedUp} from './../payloads/UserSignedUp.ts'; +import {UserSignedUp, UserSignedUpInterface} from './../payloads/UserSignedUp.ts'; import * as StringMessageModule from './../payloads/StringMessage.ts'; import * as ArrayMessageModule from './../payloads/ArrayMessage.ts'; import * as UnionMessageModule from './../payloads/UnionMessage.ts'; -import {LegacyNotification} from './../payloads/LegacyNotification.ts'; -import {UnionPayloadOneOfOption2} from './../payloads/UnionPayloadOneOfOption2.ts'; +import {LegacyNotification, LegacyNotificationInterface} from './../payloads/LegacyNotification.ts'; +import {UnionPayloadOneOfOption2, UnionPayloadOneOfOption2Interface} from './../payloads/UnionPayloadOneOfOption2.ts'; import {LegacyNotificationPayloadLevelEnum} from './../payloads/LegacyNotificationPayloadLevelEnum.ts'; import {UserSignedupParameters, UserSignedupParametersInterface} from './../parameters/UserSignedupParameters.ts'; import {UserSignedUpHeaders} from './../headers/UserSignedUpHeaders.ts'; @@ -27,7 +27,7 @@ function publishToSendUserSignedup({ codec = Nats.JSONCodec(), options }: { - message: UserSignedUp, + message: UserSignedUpInterface | UserSignedUp, parameters: UserSignedupParametersInterface | UserSignedupParameters, headers?: UserSignedUpHeaders, nc: Nats.NatsConnection, @@ -36,7 +36,7 @@ function publishToSendUserSignedup({ }): Promise { return new Promise(async (resolve, reject) => { try { - let dataToSend: any = message.marshal(); + let dataToSend: any = (message instanceof UserSignedUp ? message : new UserSignedUp(message)).marshal(); // Set up headers if provided if (headers) { const natsHeaders = Nats.headers(); @@ -76,7 +76,7 @@ function jetStreamPublishToSendUserSignedup({ codec = Nats.JSONCodec(), options = {} }: { - message: UserSignedUp, + message: UserSignedUpInterface | UserSignedUp, parameters: UserSignedupParametersInterface | UserSignedupParameters, headers?: UserSignedUpHeaders, js: Nats.JetStreamClient, @@ -85,7 +85,7 @@ function jetStreamPublishToSendUserSignedup({ }): Promise { return new Promise(async (resolve, reject) => { try { - let dataToSend: any = message.marshal(); + let dataToSend: any = (message instanceof UserSignedUp ? message : new UserSignedUp(message)).marshal(); // Set up headers if provided if (headers) { const natsHeaders = Nats.headers(); @@ -357,7 +357,7 @@ function publishToNoParameter({ codec = Nats.JSONCodec(), options }: { - message: UserSignedUp, + message: UserSignedUpInterface | UserSignedUp, headers?: UserSignedUpHeaders, nc: Nats.NatsConnection, codec?: Nats.Codec, @@ -365,7 +365,7 @@ function publishToNoParameter({ }): Promise { return new Promise(async (resolve, reject) => { try { - let dataToSend: any = message.marshal(); + let dataToSend: any = (message instanceof UserSignedUp ? message : new UserSignedUp(message)).marshal(); // Set up headers if provided if (headers) { const natsHeaders = Nats.headers(); @@ -625,7 +625,7 @@ function jetStreamPublishToNoParameter({ codec = Nats.JSONCodec(), options = {} }: { - message: UserSignedUp, + message: UserSignedUpInterface | UserSignedUp, headers?: UserSignedUpHeaders, js: Nats.JetStreamClient, codec?: Nats.Codec, @@ -633,7 +633,7 @@ function jetStreamPublishToNoParameter({ }): Promise { return new Promise(async (resolve, reject) => { try { - let dataToSend: any = message.marshal(); + let dataToSend: any = (message instanceof UserSignedUp ? message : new UserSignedUp(message)).marshal(); // Set up headers if provided if (headers) { const natsHeaders = Nats.headers(); @@ -1358,14 +1358,14 @@ function publishToSendLegacyNotification({ codec = Nats.JSONCodec(), options }: { - message: LegacyNotification, + message: LegacyNotificationInterface | LegacyNotification, nc: Nats.NatsConnection, codec?: Nats.Codec, options?: Nats.PublishOptions }): Promise { return new Promise(async (resolve, reject) => { try { - let dataToSend: any = message.marshal(); + let dataToSend: any = (message instanceof LegacyNotification ? message : new LegacyNotification(message)).marshal(); dataToSend = codec.encode(dataToSend); nc.publish('legacy.notification', dataToSend, options); @@ -1392,14 +1392,14 @@ function jetStreamPublishToSendLegacyNotification({ codec = Nats.JSONCodec(), options = {} }: { - message: LegacyNotification, + message: LegacyNotificationInterface | LegacyNotification, js: Nats.JetStreamClient, codec?: Nats.Codec, options?: Partial }): Promise { return new Promise(async (resolve, reject) => { try { - let dataToSend: any = message.marshal(); + let dataToSend: any = (message instanceof LegacyNotification ? message : new LegacyNotification(message)).marshal(); dataToSend = codec.encode(dataToSend); await js.publish('legacy.notification', dataToSend, options); diff --git a/test/runtime/typescript/src/node16/headers/UserSignedUpHeaders.ts b/test/runtime/typescript/src/node16/headers/UserSignedUpHeaders.ts index e15ff250..c7ca7593 100644 --- a/test/runtime/typescript/src/node16/headers/UserSignedUpHeaders.ts +++ b/test/runtime/typescript/src/node16/headers/UserSignedUpHeaders.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class UserSignedUpHeaders { private _xTestHeader?: string; private _additionalProperties?: Map; @@ -21,30 +21,32 @@ class UserSignedUpHeaders { get additionalProperties(): Map | undefined { return this._additionalProperties; } set additionalProperties(additionalProperties: Map | undefined) { this._additionalProperties = additionalProperties; } - public marshal() : string { - let json = '{' + public toJson(): Record { + const json: Record = {}; if(this.xTestHeader !== undefined) { - json += `"x-test-header": ${typeof this.xTestHeader === 'number' || typeof this.xTestHeader === 'boolean' ? this.xTestHeader : JSON.stringify(this.xTestHeader)},`; + json["x-test-header"] = this.xTestHeader; } - if(this.additionalProperties !== undefined) { + if(this.additionalProperties !== undefined) { for (const [key, value] of this.additionalProperties.entries()) { //Only unwrap those that are not already a property in the JSON object if(["x-test-header","additionalProperties"].includes(String(key))) continue; - json += `"${key}": ${typeof value === 'number' || typeof value === 'boolean' ? value : JSON.stringify(value)},`; + json[key] = value; } } - //Remove potential last comma - return `${json.charAt(json.length-1) === ',' ? json.slice(0, json.length-1) : json}}`; + return json; } - public static unmarshal(json: string | object): UserSignedUpHeaders { - const obj = typeof json === "object" ? json : JSON.parse(json); + public marshal(): string { + return JSON.stringify(this.toJson()); + } + + public static fromJson(obj: Record): UserSignedUpHeaders { const instance = new UserSignedUpHeaders({} as any); if (obj["x-test-header"] !== undefined) { - instance.xTestHeader = obj["x-test-header"]; + instance.xTestHeader = obj["x-test-header"] as string; } - + instance.additionalProperties = new Map(); const propsToCheck = Object.entries(obj).filter((([key,]) => {return !["x-test-header","additionalProperties"].includes(key);})); for (const [key, value] of propsToCheck) { @@ -52,6 +54,11 @@ class UserSignedUpHeaders { } return instance; } + + public static unmarshal(json: string | object): UserSignedUpHeaders { + const obj = typeof json === "object" ? json : JSON.parse(json); + return UserSignedUpHeaders.fromJson(obj as Record); + } public static theCodeGenSchema = {"type":"object","properties":{"x-test-header":{"type":"string","description":"Test header"}},"$id":"UserSignedUpHeaders","$schema":"http://json-schema.org/draft-07/schema"}; public static validate(context?: {data: any, ajvValidatorFunction?: ValidateFunction, ajvInstance?: Ajv, ajvOptions?: AjvOptions}): { valid: boolean; errors?: ErrorObject[]; } { const {data, ajvValidatorFunction} = context ?? {}; @@ -67,6 +74,9 @@ class UserSignedUpHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/test/runtime/typescript/src/node16/parameters/UserSignedupParameters.ts b/test/runtime/typescript/src/node16/parameters/UserSignedupParameters.ts index 4195c425..8052340b 100644 --- a/test/runtime/typescript/src/node16/parameters/UserSignedupParameters.ts +++ b/test/runtime/typescript/src/node16/parameters/UserSignedupParameters.ts @@ -1,4 +1,4 @@ -import {EnumParameter} from './EnumParameter'; +import {EnumParameter} from './EnumParameter.ts'; interface UserSignedupParametersInterface { myParameter: string enumParameter: EnumParameter @@ -58,4 +58,5 @@ class UserSignedupParameters { return parameters; } } -export { UserSignedupParameters, UserSignedupParametersInterface }; \ No newline at end of file +export { UserSignedupParameters }; +export type { UserSignedupParametersInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/node16/payloads/ArrayMessage.ts b/test/runtime/typescript/src/node16/payloads/ArrayMessage.ts index e3d8a41c..14959285 100644 --- a/test/runtime/typescript/src/node16/payloads/ArrayMessage.ts +++ b/test/runtime/typescript/src/node16/payloads/ArrayMessage.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * An array of strings payload */ @@ -29,6 +29,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/node16/payloads/LegacyNotification.ts b/test/runtime/typescript/src/node16/payloads/LegacyNotification.ts index 7a50dcf7..0d64c3d9 100644 --- a/test/runtime/typescript/src/node16/payloads/LegacyNotification.ts +++ b/test/runtime/typescript/src/node16/payloads/LegacyNotification.ts @@ -1,6 +1,11 @@ -import {LegacyNotificationPayloadLevelEnum} from './LegacyNotificationPayloadLevelEnum'; +import {LegacyNotificationPayloadLevelEnum} from './LegacyNotificationPayloadLevelEnum.ts'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; +interface LegacyNotificationInterface { + message?: string + level?: LegacyNotificationPayloadLevelEnum + additionalProperties?: Record +} /** * Legacy notification payload - use NewNotificationPayload instead */ @@ -9,11 +14,7 @@ class LegacyNotification { private _level?: LegacyNotificationPayloadLevelEnum; private _additionalProperties?: Record; - constructor(input: { - message?: string, - level?: LegacyNotificationPayloadLevelEnum, - additionalProperties?: Record, - }) { + constructor(input: LegacyNotificationInterface) { this._message = input.message; this._level = input.level; this._additionalProperties = input.additionalProperties; @@ -34,43 +35,50 @@ class LegacyNotification { get additionalProperties(): Record | undefined { return this._additionalProperties; } set additionalProperties(additionalProperties: Record | undefined) { this._additionalProperties = additionalProperties; } - public marshal() : string { - let json = '{' + public toJson(): Record { + const json: Record = {}; if(this.message !== undefined) { - json += `"message": ${typeof this.message === 'number' || typeof this.message === 'boolean' ? this.message : JSON.stringify(this.message)},`; + json["message"] = this.message; } if(this.level !== undefined) { - json += `"level": ${typeof this.level === 'number' || typeof this.level === 'boolean' ? this.level : JSON.stringify(this.level)},`; + json["level"] = this.level; } - if(this.additionalProperties !== undefined) { - for (const [key, value] of this.additionalProperties.entries()) { + if(this.additionalProperties !== undefined) { + for (const [key, value] of Object.entries(this.additionalProperties)) { //Only unwrap those that are not already a property in the JSON object if(["message","level","additionalProperties"].includes(String(key))) continue; - json += `"${key}": ${typeof value === 'number' || typeof value === 'boolean' ? value : JSON.stringify(value)},`; + json[key] = value; } } - //Remove potential last comma - return `${json.charAt(json.length-1) === ',' ? json.slice(0, json.length-1) : json}}`; + return json; } - public static unmarshal(json: string | object): LegacyNotification { - const obj = typeof json === "object" ? json : JSON.parse(json); + public marshal(): string { + return JSON.stringify(this.toJson()); + } + + public static fromJson(obj: Record): LegacyNotification { const instance = new LegacyNotification({} as any); if (obj["message"] !== undefined) { - instance.message = obj["message"]; + instance.message = obj["message"] as string; } if (obj["level"] !== undefined) { - instance.level = obj["level"]; + instance.level = obj["level"] as LegacyNotificationPayloadLevelEnum; } - - instance.additionalProperties = new Map(); + + instance.additionalProperties = {}; const propsToCheck = Object.entries(obj).filter((([key,]) => {return !["message","level","additionalProperties"].includes(key);})); for (const [key, value] of propsToCheck) { - instance.additionalProperties.set(key, value as any); + instance.additionalProperties[key] = value as any; } return instance; } + + public static unmarshal(json: string | object): LegacyNotification { + const obj = typeof json === "object" ? json : JSON.parse(json); + return LegacyNotification.fromJson(obj as Record); + } public static theCodeGenSchema = {"type":"object","$schema":"http://json-schema.org/draft-07/schema","description":"Legacy notification payload - use NewNotificationPayload instead","deprecated":true,"properties":{"message":{"type":"string","description":"The notification message"},"level":{"type":"string","enum":["info","warning","error"],"description":"Notification severity level"}},"$id":"LegacyNotification"}; public static validate(context?: {data: any, ajvValidatorFunction?: ValidateFunction, ajvInstance?: Ajv, ajvOptions?: AjvOptions}): { valid: boolean; errors?: ErrorObject[]; } { const {data, ajvValidatorFunction} = context ?? {}; @@ -86,6 +94,9 @@ class LegacyNotification { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -93,4 +104,5 @@ class LegacyNotification { } } -export { LegacyNotification }; \ No newline at end of file +export { LegacyNotification }; +export type { LegacyNotificationInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/node16/payloads/StringMessage.ts b/test/runtime/typescript/src/node16/payloads/StringMessage.ts index b4efe734..443c9709 100644 --- a/test/runtime/typescript/src/node16/payloads/StringMessage.ts +++ b/test/runtime/typescript/src/node16/payloads/StringMessage.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * A simple string payload */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/node16/payloads/UnionMessage.ts b/test/runtime/typescript/src/node16/payloads/UnionMessage.ts index f2545d83..93957fc2 100644 --- a/test/runtime/typescript/src/node16/payloads/UnionMessage.ts +++ b/test/runtime/typescript/src/node16/payloads/UnionMessage.ts @@ -1,6 +1,6 @@ -import {UnionPayloadOneOfOption2} from './UnionPayloadOneOfOption2'; +import {UnionPayloadOneOfOption2} from './UnionPayloadOneOfOption2.ts'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * A union type payload */ @@ -34,6 +34,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/node16/payloads/UnionPayloadOneOfOption2.ts b/test/runtime/typescript/src/node16/payloads/UnionPayloadOneOfOption2.ts index d166bc77..1c3bb054 100644 --- a/test/runtime/typescript/src/node16/payloads/UnionPayloadOneOfOption2.ts +++ b/test/runtime/typescript/src/node16/payloads/UnionPayloadOneOfOption2.ts @@ -1,13 +1,14 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; +interface UnionPayloadOneOfOption2Interface { + name?: string + additionalProperties?: Record +} class UnionPayloadOneOfOption2 { private _name?: string; private _additionalProperties?: Record; - constructor(input: { - name?: string, - additionalProperties?: Record, - }) { + constructor(input: UnionPayloadOneOfOption2Interface) { this._name = input.name; this._additionalProperties = input.additionalProperties; } @@ -18,37 +19,44 @@ class UnionPayloadOneOfOption2 { get additionalProperties(): Record | undefined { return this._additionalProperties; } set additionalProperties(additionalProperties: Record | undefined) { this._additionalProperties = additionalProperties; } - public marshal() : string { - let json = '{' + public toJson(): Record { + const json: Record = {}; if(this.name !== undefined) { - json += `"name": ${typeof this.name === 'number' || typeof this.name === 'boolean' ? this.name : JSON.stringify(this.name)},`; + json["name"] = this.name; } - if(this.additionalProperties !== undefined) { - for (const [key, value] of this.additionalProperties.entries()) { + if(this.additionalProperties !== undefined) { + for (const [key, value] of Object.entries(this.additionalProperties)) { //Only unwrap those that are not already a property in the JSON object if(["name","additionalProperties"].includes(String(key))) continue; - json += `"${key}": ${typeof value === 'number' || typeof value === 'boolean' ? value : JSON.stringify(value)},`; + json[key] = value; } } - //Remove potential last comma - return `${json.charAt(json.length-1) === ',' ? json.slice(0, json.length-1) : json}}`; + return json; } - public static unmarshal(json: string | object): UnionPayloadOneOfOption2 { - const obj = typeof json === "object" ? json : JSON.parse(json); + public marshal(): string { + return JSON.stringify(this.toJson()); + } + + public static fromJson(obj: Record): UnionPayloadOneOfOption2 { const instance = new UnionPayloadOneOfOption2({} as any); if (obj["name"] !== undefined) { - instance.name = obj["name"]; + instance.name = obj["name"] as string; } - - instance.additionalProperties = new Map(); + + instance.additionalProperties = {}; const propsToCheck = Object.entries(obj).filter((([key,]) => {return !["name","additionalProperties"].includes(key);})); for (const [key, value] of propsToCheck) { - instance.additionalProperties.set(key, value as any); + instance.additionalProperties[key] = value as any; } return instance; } + + public static unmarshal(json: string | object): UnionPayloadOneOfOption2 { + const obj = typeof json === "object" ? json : JSON.parse(json); + return UnionPayloadOneOfOption2.fromJson(obj as Record); + } public static theCodeGenSchema = {"type":"object","properties":{"name":{"type":"string"}}}; public static validate(context?: {data: any, ajvValidatorFunction?: ValidateFunction, ajvInstance?: Ajv, ajvOptions?: AjvOptions}): { valid: boolean; errors?: ErrorObject[]; } { const {data, ajvValidatorFunction} = context ?? {}; @@ -64,6 +72,9 @@ class UnionPayloadOneOfOption2 { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -71,4 +82,5 @@ class UnionPayloadOneOfOption2 { } } -export { UnionPayloadOneOfOption2 }; \ No newline at end of file +export { UnionPayloadOneOfOption2 }; +export type { UnionPayloadOneOfOption2Interface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/node16/payloads/UserSignedUp.ts b/test/runtime/typescript/src/node16/payloads/UserSignedUp.ts index 13f2c67a..1dabff95 100644 --- a/test/runtime/typescript/src/node16/payloads/UserSignedUp.ts +++ b/test/runtime/typescript/src/node16/payloads/UserSignedUp.ts @@ -1,5 +1,10 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; +interface UserSignedUpInterface { + displayName?: string + email?: string + additionalProperties?: Record +} /** * Payload for user signup events containing user registration details */ @@ -8,11 +13,7 @@ class UserSignedUp { private _email?: string; private _additionalProperties?: Record; - constructor(input: { - displayName?: string, - email?: string, - additionalProperties?: Record, - }) { + constructor(input: UserSignedUpInterface) { this._displayName = input.displayName; this._email = input.email; this._additionalProperties = input.additionalProperties; @@ -33,43 +34,50 @@ class UserSignedUp { get additionalProperties(): Record | undefined { return this._additionalProperties; } set additionalProperties(additionalProperties: Record | undefined) { this._additionalProperties = additionalProperties; } - public marshal() : string { - let json = '{' + public toJson(): Record { + const json: Record = {}; if(this.displayName !== undefined) { - json += `"display_name": ${typeof this.displayName === 'number' || typeof this.displayName === 'boolean' ? this.displayName : JSON.stringify(this.displayName)},`; + json["display_name"] = this.displayName; } if(this.email !== undefined) { - json += `"email": ${typeof this.email === 'number' || typeof this.email === 'boolean' ? this.email : JSON.stringify(this.email)},`; + json["email"] = this.email; } - if(this.additionalProperties !== undefined) { - for (const [key, value] of this.additionalProperties.entries()) { + if(this.additionalProperties !== undefined) { + for (const [key, value] of Object.entries(this.additionalProperties)) { //Only unwrap those that are not already a property in the JSON object if(["display_name","email","additionalProperties"].includes(String(key))) continue; - json += `"${key}": ${typeof value === 'number' || typeof value === 'boolean' ? value : JSON.stringify(value)},`; + json[key] = value; } } - //Remove potential last comma - return `${json.charAt(json.length-1) === ',' ? json.slice(0, json.length-1) : json}}`; + return json; } - public static unmarshal(json: string | object): UserSignedUp { - const obj = typeof json === "object" ? json : JSON.parse(json); + public marshal(): string { + return JSON.stringify(this.toJson()); + } + + public static fromJson(obj: Record): UserSignedUp { const instance = new UserSignedUp({} as any); if (obj["display_name"] !== undefined) { - instance.displayName = obj["display_name"]; + instance.displayName = obj["display_name"] as string; } if (obj["email"] !== undefined) { - instance.email = obj["email"]; + instance.email = obj["email"] as string; } - - instance.additionalProperties = new Map(); + + instance.additionalProperties = {}; const propsToCheck = Object.entries(obj).filter((([key,]) => {return !["display_name","email","additionalProperties"].includes(key);})); for (const [key, value] of propsToCheck) { - instance.additionalProperties.set(key, value as any); + instance.additionalProperties[key] = value as any; } return instance; } + + public static unmarshal(json: string | object): UserSignedUp { + const obj = typeof json === "object" ? json : JSON.parse(json); + return UserSignedUp.fromJson(obj as Record); + } public static theCodeGenSchema = {"type":"object","$schema":"http://json-schema.org/draft-07/schema","description":"Payload for user signup events containing user registration details","properties":{"display_name":{"type":"string","description":"Name of the user"},"email":{"type":"string","format":"email","description":"Email of the user"}},"$id":"UserSignedUp"}; public static validate(context?: {data: any, ajvValidatorFunction?: ValidateFunction, ajvInstance?: Ajv, ajvOptions?: AjvOptions}): { valid: boolean; errors?: ErrorObject[]; } { const {data, ajvValidatorFunction} = context ?? {}; @@ -85,6 +93,9 @@ class UserSignedUp { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -92,4 +103,5 @@ class UserSignedUp { } } -export { UserSignedUp }; \ No newline at end of file +export { UserSignedUp }; +export type { UserSignedUpInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi-path-organization/channels/parameter/FindPetsByStatusAndCategoryParameters.ts b/test/runtime/typescript/src/openapi-path-organization/channels/parameter/FindPetsByStatusAndCategoryParameters.ts index d978dc08..60c3951e 100644 --- a/test/runtime/typescript/src/openapi-path-organization/channels/parameter/FindPetsByStatusAndCategoryParameters.ts +++ b/test/runtime/typescript/src/openapi-path-organization/channels/parameter/FindPetsByStatusAndCategoryParameters.ts @@ -389,4 +389,5 @@ class FindPetsByStatusAndCategoryParameters { return result; } } -export { FindPetsByStatusAndCategoryParameters, FindPetsByStatusAndCategoryParametersInterface }; \ No newline at end of file +export { FindPetsByStatusAndCategoryParameters }; +export type { FindPetsByStatusAndCategoryParametersInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi-path-organization/channels/payload/APet.ts b/test/runtime/typescript/src/openapi-path-organization/channels/payload/APet.ts index a1fe03de..cf97761e 100644 --- a/test/runtime/typescript/src/openapi-path-organization/channels/payload/APet.ts +++ b/test/runtime/typescript/src/openapi-path-organization/channels/payload/APet.ts @@ -2,7 +2,7 @@ import {PetCategory} from './PetCategory'; import {PetTag} from './PetTag'; import {Status} from './Status'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface APetInterface { id?: number category?: PetCategory @@ -150,6 +150,9 @@ class APet { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -157,4 +160,5 @@ class APet { } } -export { APet, APetInterface }; \ No newline at end of file +export { APet }; +export type { APetInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi-path-organization/channels/payload/AUser.ts b/test/runtime/typescript/src/openapi-path-organization/channels/payload/AUser.ts index 48ed2ebf..2e2bd007 100644 --- a/test/runtime/typescript/src/openapi-path-organization/channels/payload/AUser.ts +++ b/test/runtime/typescript/src/openapi-path-organization/channels/payload/AUser.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface AUserInterface { id?: number username?: string @@ -162,6 +162,9 @@ class AUser { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -169,4 +172,5 @@ class AUser { } } -export { AUser, AUserInterface }; \ No newline at end of file +export { AUser }; +export type { AUserInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi-path-organization/channels/payload/AnUploadedResponse.ts b/test/runtime/typescript/src/openapi-path-organization/channels/payload/AnUploadedResponse.ts index 1bd74e80..52e26695 100644 --- a/test/runtime/typescript/src/openapi-path-organization/channels/payload/AnUploadedResponse.ts +++ b/test/runtime/typescript/src/openapi-path-organization/channels/payload/AnUploadedResponse.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface AnUploadedResponseInterface { code?: number type?: string @@ -99,6 +99,9 @@ class AnUploadedResponse { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -106,4 +109,5 @@ class AnUploadedResponse { } } -export { AnUploadedResponse, AnUploadedResponseInterface }; \ No newline at end of file +export { AnUploadedResponse }; +export type { AnUploadedResponseInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi-path-organization/channels/payload/FindPetsByStatusAndCategoryResponse_200.ts b/test/runtime/typescript/src/openapi-path-organization/channels/payload/FindPetsByStatusAndCategoryResponse_200.ts index 316729c0..6792b23f 100644 --- a/test/runtime/typescript/src/openapi-path-organization/channels/payload/FindPetsByStatusAndCategoryResponse_200.ts +++ b/test/runtime/typescript/src/openapi-path-organization/channels/payload/FindPetsByStatusAndCategoryResponse_200.ts @@ -1,6 +1,6 @@ import {APet} from './APet'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type FindPetsByStatusAndCategoryResponse_200 = APet[]; export function unmarshal(json: string | any[]): FindPetsByStatusAndCategoryResponse_200 { @@ -35,6 +35,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/openapi-path-organization/channels/payload/PetCategory.ts b/test/runtime/typescript/src/openapi-path-organization/channels/payload/PetCategory.ts index 4d62020c..4e6363d8 100644 --- a/test/runtime/typescript/src/openapi-path-organization/channels/payload/PetCategory.ts +++ b/test/runtime/typescript/src/openapi-path-organization/channels/payload/PetCategory.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface PetCategoryInterface { id?: number name?: string @@ -87,6 +87,9 @@ class PetCategory { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -94,4 +97,5 @@ class PetCategory { } } -export { PetCategory, PetCategoryInterface }; \ No newline at end of file +export { PetCategory }; +export type { PetCategoryInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi-path-organization/channels/payload/PetOrder.ts b/test/runtime/typescript/src/openapi-path-organization/channels/payload/PetOrder.ts index 89ec5be1..46f10b36 100644 --- a/test/runtime/typescript/src/openapi-path-organization/channels/payload/PetOrder.ts +++ b/test/runtime/typescript/src/openapi-path-organization/channels/payload/PetOrder.ts @@ -1,6 +1,6 @@ import {Status} from './Status'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface PetOrderInterface { id?: number petId?: number @@ -139,6 +139,9 @@ class PetOrder { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -146,4 +149,5 @@ class PetOrder { } } -export { PetOrder, PetOrderInterface }; \ No newline at end of file +export { PetOrder }; +export type { PetOrderInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi-path-organization/channels/payload/PetTag.ts b/test/runtime/typescript/src/openapi-path-organization/channels/payload/PetTag.ts index 50071c6b..2c7e4e42 100644 --- a/test/runtime/typescript/src/openapi-path-organization/channels/payload/PetTag.ts +++ b/test/runtime/typescript/src/openapi-path-organization/channels/payload/PetTag.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface PetTagInterface { id?: number name?: string @@ -87,6 +87,9 @@ class PetTag { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -94,4 +97,5 @@ class PetTag { } } -export { PetTag, PetTagInterface }; \ No newline at end of file +export { PetTag }; +export type { PetTagInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi-primitive/payloads/GetCountResponse_200.ts b/test/runtime/typescript/src/openapi-primitive/payloads/GetCountResponse_200.ts index bd134e4e..87be8184 100644 --- a/test/runtime/typescript/src/openapi-primitive/payloads/GetCountResponse_200.ts +++ b/test/runtime/typescript/src/openapi-primitive/payloads/GetCountResponse_200.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type GetCountResponse_200 = number; export function unmarshal(json: string): GetCountResponse_200 { @@ -23,6 +23,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/openapi-primitive/payloads/GetEchoResponse_200.ts b/test/runtime/typescript/src/openapi-primitive/payloads/GetEchoResponse_200.ts index d5508632..3c5740c7 100644 --- a/test/runtime/typescript/src/openapi-primitive/payloads/GetEchoResponse_200.ts +++ b/test/runtime/typescript/src/openapi-primitive/payloads/GetEchoResponse_200.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type GetEchoResponse_200 = string; export function unmarshal(json: string): GetEchoResponse_200 { @@ -23,6 +23,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/openapi-tag-organization/channels/parameter/FindPetsByStatusAndCategoryParameters.ts b/test/runtime/typescript/src/openapi-tag-organization/channels/parameter/FindPetsByStatusAndCategoryParameters.ts index d978dc08..60c3951e 100644 --- a/test/runtime/typescript/src/openapi-tag-organization/channels/parameter/FindPetsByStatusAndCategoryParameters.ts +++ b/test/runtime/typescript/src/openapi-tag-organization/channels/parameter/FindPetsByStatusAndCategoryParameters.ts @@ -389,4 +389,5 @@ class FindPetsByStatusAndCategoryParameters { return result; } } -export { FindPetsByStatusAndCategoryParameters, FindPetsByStatusAndCategoryParametersInterface }; \ No newline at end of file +export { FindPetsByStatusAndCategoryParameters }; +export type { FindPetsByStatusAndCategoryParametersInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi-tag-organization/channels/payload/APet.ts b/test/runtime/typescript/src/openapi-tag-organization/channels/payload/APet.ts index a1fe03de..cf97761e 100644 --- a/test/runtime/typescript/src/openapi-tag-organization/channels/payload/APet.ts +++ b/test/runtime/typescript/src/openapi-tag-organization/channels/payload/APet.ts @@ -2,7 +2,7 @@ import {PetCategory} from './PetCategory'; import {PetTag} from './PetTag'; import {Status} from './Status'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface APetInterface { id?: number category?: PetCategory @@ -150,6 +150,9 @@ class APet { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -157,4 +160,5 @@ class APet { } } -export { APet, APetInterface }; \ No newline at end of file +export { APet }; +export type { APetInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi-tag-organization/channels/payload/AUser.ts b/test/runtime/typescript/src/openapi-tag-organization/channels/payload/AUser.ts index 48ed2ebf..2e2bd007 100644 --- a/test/runtime/typescript/src/openapi-tag-organization/channels/payload/AUser.ts +++ b/test/runtime/typescript/src/openapi-tag-organization/channels/payload/AUser.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface AUserInterface { id?: number username?: string @@ -162,6 +162,9 @@ class AUser { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -169,4 +172,5 @@ class AUser { } } -export { AUser, AUserInterface }; \ No newline at end of file +export { AUser }; +export type { AUserInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi-tag-organization/channels/payload/AnUploadedResponse.ts b/test/runtime/typescript/src/openapi-tag-organization/channels/payload/AnUploadedResponse.ts index 1bd74e80..52e26695 100644 --- a/test/runtime/typescript/src/openapi-tag-organization/channels/payload/AnUploadedResponse.ts +++ b/test/runtime/typescript/src/openapi-tag-organization/channels/payload/AnUploadedResponse.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface AnUploadedResponseInterface { code?: number type?: string @@ -99,6 +99,9 @@ class AnUploadedResponse { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -106,4 +109,5 @@ class AnUploadedResponse { } } -export { AnUploadedResponse, AnUploadedResponseInterface }; \ No newline at end of file +export { AnUploadedResponse }; +export type { AnUploadedResponseInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi-tag-organization/channels/payload/FindPetsByStatusAndCategoryResponse_200.ts b/test/runtime/typescript/src/openapi-tag-organization/channels/payload/FindPetsByStatusAndCategoryResponse_200.ts index 316729c0..6792b23f 100644 --- a/test/runtime/typescript/src/openapi-tag-organization/channels/payload/FindPetsByStatusAndCategoryResponse_200.ts +++ b/test/runtime/typescript/src/openapi-tag-organization/channels/payload/FindPetsByStatusAndCategoryResponse_200.ts @@ -1,6 +1,6 @@ import {APet} from './APet'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type FindPetsByStatusAndCategoryResponse_200 = APet[]; export function unmarshal(json: string | any[]): FindPetsByStatusAndCategoryResponse_200 { @@ -35,6 +35,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/openapi-tag-organization/channels/payload/PetCategory.ts b/test/runtime/typescript/src/openapi-tag-organization/channels/payload/PetCategory.ts index 4d62020c..4e6363d8 100644 --- a/test/runtime/typescript/src/openapi-tag-organization/channels/payload/PetCategory.ts +++ b/test/runtime/typescript/src/openapi-tag-organization/channels/payload/PetCategory.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface PetCategoryInterface { id?: number name?: string @@ -87,6 +87,9 @@ class PetCategory { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -94,4 +97,5 @@ class PetCategory { } } -export { PetCategory, PetCategoryInterface }; \ No newline at end of file +export { PetCategory }; +export type { PetCategoryInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi-tag-organization/channels/payload/PetOrder.ts b/test/runtime/typescript/src/openapi-tag-organization/channels/payload/PetOrder.ts index 89ec5be1..46f10b36 100644 --- a/test/runtime/typescript/src/openapi-tag-organization/channels/payload/PetOrder.ts +++ b/test/runtime/typescript/src/openapi-tag-organization/channels/payload/PetOrder.ts @@ -1,6 +1,6 @@ import {Status} from './Status'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface PetOrderInterface { id?: number petId?: number @@ -139,6 +139,9 @@ class PetOrder { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -146,4 +149,5 @@ class PetOrder { } } -export { PetOrder, PetOrderInterface }; \ No newline at end of file +export { PetOrder }; +export type { PetOrderInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi-tag-organization/channels/payload/PetTag.ts b/test/runtime/typescript/src/openapi-tag-organization/channels/payload/PetTag.ts index 50071c6b..2c7e4e42 100644 --- a/test/runtime/typescript/src/openapi-tag-organization/channels/payload/PetTag.ts +++ b/test/runtime/typescript/src/openapi-tag-organization/channels/payload/PetTag.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface PetTagInterface { id?: number name?: string @@ -87,6 +87,9 @@ class PetTag { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -94,4 +97,5 @@ class PetTag { } } -export { PetTag, PetTagInterface }; \ No newline at end of file +export { PetTag }; +export type { PetTagInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi/parameters/FindPetsByStatusAndCategoryParameters.ts b/test/runtime/typescript/src/openapi/parameters/FindPetsByStatusAndCategoryParameters.ts index d978dc08..60c3951e 100644 --- a/test/runtime/typescript/src/openapi/parameters/FindPetsByStatusAndCategoryParameters.ts +++ b/test/runtime/typescript/src/openapi/parameters/FindPetsByStatusAndCategoryParameters.ts @@ -389,4 +389,5 @@ class FindPetsByStatusAndCategoryParameters { return result; } } -export { FindPetsByStatusAndCategoryParameters, FindPetsByStatusAndCategoryParametersInterface }; \ No newline at end of file +export { FindPetsByStatusAndCategoryParameters }; +export type { FindPetsByStatusAndCategoryParametersInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi/payloads/APet.ts b/test/runtime/typescript/src/openapi/payloads/APet.ts index a1fe03de..cf97761e 100644 --- a/test/runtime/typescript/src/openapi/payloads/APet.ts +++ b/test/runtime/typescript/src/openapi/payloads/APet.ts @@ -2,7 +2,7 @@ import {PetCategory} from './PetCategory'; import {PetTag} from './PetTag'; import {Status} from './Status'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface APetInterface { id?: number category?: PetCategory @@ -150,6 +150,9 @@ class APet { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -157,4 +160,5 @@ class APet { } } -export { APet, APetInterface }; \ No newline at end of file +export { APet }; +export type { APetInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi/payloads/AUser.ts b/test/runtime/typescript/src/openapi/payloads/AUser.ts index 48ed2ebf..2e2bd007 100644 --- a/test/runtime/typescript/src/openapi/payloads/AUser.ts +++ b/test/runtime/typescript/src/openapi/payloads/AUser.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface AUserInterface { id?: number username?: string @@ -162,6 +162,9 @@ class AUser { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -169,4 +172,5 @@ class AUser { } } -export { AUser, AUserInterface }; \ No newline at end of file +export { AUser }; +export type { AUserInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi/payloads/AnUploadedResponse.ts b/test/runtime/typescript/src/openapi/payloads/AnUploadedResponse.ts index 1bd74e80..52e26695 100644 --- a/test/runtime/typescript/src/openapi/payloads/AnUploadedResponse.ts +++ b/test/runtime/typescript/src/openapi/payloads/AnUploadedResponse.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface AnUploadedResponseInterface { code?: number type?: string @@ -99,6 +99,9 @@ class AnUploadedResponse { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -106,4 +109,5 @@ class AnUploadedResponse { } } -export { AnUploadedResponse, AnUploadedResponseInterface }; \ No newline at end of file +export { AnUploadedResponse }; +export type { AnUploadedResponseInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi/payloads/FindPetsByStatusAndCategoryResponse_200.ts b/test/runtime/typescript/src/openapi/payloads/FindPetsByStatusAndCategoryResponse_200.ts index 316729c0..6792b23f 100644 --- a/test/runtime/typescript/src/openapi/payloads/FindPetsByStatusAndCategoryResponse_200.ts +++ b/test/runtime/typescript/src/openapi/payloads/FindPetsByStatusAndCategoryResponse_200.ts @@ -1,6 +1,6 @@ import {APet} from './APet'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type FindPetsByStatusAndCategoryResponse_200 = APet[]; export function unmarshal(json: string | any[]): FindPetsByStatusAndCategoryResponse_200 { @@ -35,6 +35,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/openapi/payloads/PetCategory.ts b/test/runtime/typescript/src/openapi/payloads/PetCategory.ts index 4d62020c..4e6363d8 100644 --- a/test/runtime/typescript/src/openapi/payloads/PetCategory.ts +++ b/test/runtime/typescript/src/openapi/payloads/PetCategory.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface PetCategoryInterface { id?: number name?: string @@ -87,6 +87,9 @@ class PetCategory { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -94,4 +97,5 @@ class PetCategory { } } -export { PetCategory, PetCategoryInterface }; \ No newline at end of file +export { PetCategory }; +export type { PetCategoryInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi/payloads/PetOrder.ts b/test/runtime/typescript/src/openapi/payloads/PetOrder.ts index 89ec5be1..46f10b36 100644 --- a/test/runtime/typescript/src/openapi/payloads/PetOrder.ts +++ b/test/runtime/typescript/src/openapi/payloads/PetOrder.ts @@ -1,6 +1,6 @@ import {Status} from './Status'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface PetOrderInterface { id?: number petId?: number @@ -139,6 +139,9 @@ class PetOrder { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -146,4 +149,5 @@ class PetOrder { } } -export { PetOrder, PetOrderInterface }; \ No newline at end of file +export { PetOrder }; +export type { PetOrderInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/openapi/payloads/PetTag.ts b/test/runtime/typescript/src/openapi/payloads/PetTag.ts index 50071c6b..2c7e4e42 100644 --- a/test/runtime/typescript/src/openapi/payloads/PetTag.ts +++ b/test/runtime/typescript/src/openapi/payloads/PetTag.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface PetTagInterface { id?: number name?: string @@ -87,6 +87,9 @@ class PetTag { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); ajvInstance.addVocabulary(["xml", "example"]) const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -94,4 +97,5 @@ class PetTag { } } -export { PetTag, PetTagInterface }; \ No newline at end of file +export { PetTag }; +export type { PetTagInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/parameters/UserSignedupParameters.ts b/test/runtime/typescript/src/parameters/UserSignedupParameters.ts index 4195c425..db0c02ca 100644 --- a/test/runtime/typescript/src/parameters/UserSignedupParameters.ts +++ b/test/runtime/typescript/src/parameters/UserSignedupParameters.ts @@ -58,4 +58,5 @@ class UserSignedupParameters { return parameters; } } -export { UserSignedupParameters, UserSignedupParametersInterface }; \ No newline at end of file +export { UserSignedupParameters }; +export type { UserSignedupParametersInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/AllOfThreeTypes.ts b/test/runtime/typescript/src/payload-types/payloads/AllOfThreeTypes.ts index 1f2bf814..18f2e5c9 100644 --- a/test/runtime/typescript/src/payload-types/payloads/AllOfThreeTypes.ts +++ b/test/runtime/typescript/src/payload-types/payloads/AllOfThreeTypes.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface AllOfThreeTypesInterface { id: string name?: string @@ -135,6 +135,9 @@ class AllOfThreeTypes { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -142,4 +145,5 @@ class AllOfThreeTypes { } } -export { AllOfThreeTypes, AllOfThreeTypesInterface }; \ No newline at end of file +export { AllOfThreeTypes }; +export type { AllOfThreeTypesInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/AllOfTwoTypes.ts b/test/runtime/typescript/src/payload-types/payloads/AllOfTwoTypes.ts index 0e18d1b6..e25b385d 100644 --- a/test/runtime/typescript/src/payload-types/payloads/AllOfTwoTypes.ts +++ b/test/runtime/typescript/src/payload-types/payloads/AllOfTwoTypes.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface AllOfTwoTypesInterface { id: string name?: string @@ -111,6 +111,9 @@ class AllOfTwoTypes { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -118,4 +121,5 @@ class AllOfTwoTypes { } } -export { AllOfTwoTypes, AllOfTwoTypesInterface }; \ No newline at end of file +export { AllOfTwoTypes }; +export type { AllOfTwoTypesInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/AnyOfTwoTypes.ts b/test/runtime/typescript/src/payload-types/payloads/AnyOfTwoTypes.ts index 94ad1a78..c9477c83 100644 --- a/test/runtime/typescript/src/payload-types/payloads/AnyOfTwoTypes.ts +++ b/test/runtime/typescript/src/payload-types/payloads/AnyOfTwoTypes.ts @@ -1,7 +1,7 @@ import {AnyOfTwoTypesAnyOfOption0} from './AnyOfTwoTypesAnyOfOption0'; import {AnyOfTwoTypesAnyOfOption1} from './AnyOfTwoTypesAnyOfOption1'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * AnyOf with two object schemas */ @@ -36,6 +36,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/AnyOfTwoTypesAnyOfOption0.ts b/test/runtime/typescript/src/payload-types/payloads/AnyOfTwoTypesAnyOfOption0.ts index d51a0ff1..46550189 100644 --- a/test/runtime/typescript/src/payload-types/payloads/AnyOfTwoTypesAnyOfOption0.ts +++ b/test/runtime/typescript/src/payload-types/payloads/AnyOfTwoTypesAnyOfOption0.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface AnyOfTwoTypesAnyOfOption0Interface { name?: string additionalProperties?: Record @@ -72,6 +72,9 @@ class AnyOfTwoTypesAnyOfOption0 { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -79,4 +82,5 @@ class AnyOfTwoTypesAnyOfOption0 { } } -export { AnyOfTwoTypesAnyOfOption0, AnyOfTwoTypesAnyOfOption0Interface }; \ No newline at end of file +export { AnyOfTwoTypesAnyOfOption0 }; +export type { AnyOfTwoTypesAnyOfOption0Interface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/AnyOfTwoTypesAnyOfOption1.ts b/test/runtime/typescript/src/payload-types/payloads/AnyOfTwoTypesAnyOfOption1.ts index c1a2e6ad..fde4de59 100644 --- a/test/runtime/typescript/src/payload-types/payloads/AnyOfTwoTypesAnyOfOption1.ts +++ b/test/runtime/typescript/src/payload-types/payloads/AnyOfTwoTypesAnyOfOption1.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface AnyOfTwoTypesAnyOfOption1Interface { id?: number additionalProperties?: Record @@ -72,6 +72,9 @@ class AnyOfTwoTypesAnyOfOption1 { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -79,4 +82,5 @@ class AnyOfTwoTypesAnyOfOption1 { } } -export { AnyOfTwoTypesAnyOfOption1, AnyOfTwoTypesAnyOfOption1Interface }; \ No newline at end of file +export { AnyOfTwoTypesAnyOfOption1 }; +export type { AnyOfTwoTypesAnyOfOption1Interface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/ArrayWithMaxItems.ts b/test/runtime/typescript/src/payload-types/payloads/ArrayWithMaxItems.ts index ed67f615..7aa4ec76 100644 --- a/test/runtime/typescript/src/payload-types/payloads/ArrayWithMaxItems.ts +++ b/test/runtime/typescript/src/payload-types/payloads/ArrayWithMaxItems.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * Array with maximum 5 items */ @@ -29,6 +29,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/ArrayWithMinItems.ts b/test/runtime/typescript/src/payload-types/payloads/ArrayWithMinItems.ts index b7e1656b..2c41008b 100644 --- a/test/runtime/typescript/src/payload-types/payloads/ArrayWithMinItems.ts +++ b/test/runtime/typescript/src/payload-types/payloads/ArrayWithMinItems.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * Array with minimum 1 item */ @@ -29,6 +29,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/ArrayWithUniqueItems.ts b/test/runtime/typescript/src/payload-types/payloads/ArrayWithUniqueItems.ts index f7560351..6e708135 100644 --- a/test/runtime/typescript/src/payload-types/payloads/ArrayWithUniqueItems.ts +++ b/test/runtime/typescript/src/payload-types/payloads/ArrayWithUniqueItems.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * Array requiring unique items */ @@ -29,6 +29,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/BooleanPlain.ts b/test/runtime/typescript/src/payload-types/payloads/BooleanPlain.ts index 5d05b408..a45dc34f 100644 --- a/test/runtime/typescript/src/payload-types/payloads/BooleanPlain.ts +++ b/test/runtime/typescript/src/payload-types/payloads/BooleanPlain.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * A plain boolean type */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/CatPayload.ts b/test/runtime/typescript/src/payload-types/payloads/CatPayload.ts index b9d1c292..563da215 100644 --- a/test/runtime/typescript/src/payload-types/payloads/CatPayload.ts +++ b/test/runtime/typescript/src/payload-types/payloads/CatPayload.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface CatPayloadInterface { breed?: string meowPitch?: string @@ -90,6 +90,9 @@ class CatPayload { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -97,4 +100,5 @@ class CatPayload { } } -export { CatPayload, CatPayloadInterface }; \ No newline at end of file +export { CatPayload }; +export type { CatPayloadInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/DeeplyNestedObject.ts b/test/runtime/typescript/src/payload-types/payloads/DeeplyNestedObject.ts index 63f8a41c..d13496f2 100644 --- a/test/runtime/typescript/src/payload-types/payloads/DeeplyNestedObject.ts +++ b/test/runtime/typescript/src/payload-types/payloads/DeeplyNestedObject.ts @@ -1,6 +1,6 @@ import {DeeplyNestedObjectLevel1} from './DeeplyNestedObjectLevel1'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface DeeplyNestedObjectInterface { level1?: DeeplyNestedObjectLevel1 additionalProperties?: Record @@ -76,6 +76,9 @@ class DeeplyNestedObject { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -83,4 +86,5 @@ class DeeplyNestedObject { } } -export { DeeplyNestedObject, DeeplyNestedObjectInterface }; \ No newline at end of file +export { DeeplyNestedObject }; +export type { DeeplyNestedObjectInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/DeeplyNestedObjectLevel1.ts b/test/runtime/typescript/src/payload-types/payloads/DeeplyNestedObjectLevel1.ts index b0f03245..28f6ec2f 100644 --- a/test/runtime/typescript/src/payload-types/payloads/DeeplyNestedObjectLevel1.ts +++ b/test/runtime/typescript/src/payload-types/payloads/DeeplyNestedObjectLevel1.ts @@ -1,6 +1,6 @@ import {DeeplyNestedObjectLevel1Level2} from './DeeplyNestedObjectLevel1Level2'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface DeeplyNestedObjectLevel1Interface { level2?: DeeplyNestedObjectLevel1Level2 additionalProperties?: Record @@ -73,6 +73,9 @@ class DeeplyNestedObjectLevel1 { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -80,4 +83,5 @@ class DeeplyNestedObjectLevel1 { } } -export { DeeplyNestedObjectLevel1, DeeplyNestedObjectLevel1Interface }; \ No newline at end of file +export { DeeplyNestedObjectLevel1 }; +export type { DeeplyNestedObjectLevel1Interface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/DeeplyNestedObjectLevel1Level2.ts b/test/runtime/typescript/src/payload-types/payloads/DeeplyNestedObjectLevel1Level2.ts index 253780bd..db56130f 100644 --- a/test/runtime/typescript/src/payload-types/payloads/DeeplyNestedObjectLevel1Level2.ts +++ b/test/runtime/typescript/src/payload-types/payloads/DeeplyNestedObjectLevel1Level2.ts @@ -1,6 +1,6 @@ import {DeeplyNestedObjectLevel1Level2Level3} from './DeeplyNestedObjectLevel1Level2Level3'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface DeeplyNestedObjectLevel1Level2Interface { level3?: DeeplyNestedObjectLevel1Level2Level3 additionalProperties?: Record @@ -73,6 +73,9 @@ class DeeplyNestedObjectLevel1Level2 { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -80,4 +83,5 @@ class DeeplyNestedObjectLevel1Level2 { } } -export { DeeplyNestedObjectLevel1Level2, DeeplyNestedObjectLevel1Level2Interface }; \ No newline at end of file +export { DeeplyNestedObjectLevel1Level2 }; +export type { DeeplyNestedObjectLevel1Level2Interface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/DeeplyNestedObjectLevel1Level2Level3.ts b/test/runtime/typescript/src/payload-types/payloads/DeeplyNestedObjectLevel1Level2Level3.ts index be65d2cc..f4ca44a5 100644 --- a/test/runtime/typescript/src/payload-types/payloads/DeeplyNestedObjectLevel1Level2Level3.ts +++ b/test/runtime/typescript/src/payload-types/payloads/DeeplyNestedObjectLevel1Level2Level3.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface DeeplyNestedObjectLevel1Level2Level3Interface { value?: string additionalProperties?: Record @@ -72,6 +72,9 @@ class DeeplyNestedObjectLevel1Level2Level3 { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -79,4 +82,5 @@ class DeeplyNestedObjectLevel1Level2Level3 { } } -export { DeeplyNestedObjectLevel1Level2Level3, DeeplyNestedObjectLevel1Level2Level3Interface }; \ No newline at end of file +export { DeeplyNestedObjectLevel1Level2Level3 }; +export type { DeeplyNestedObjectLevel1Level2Level3Interface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/DogPayload.ts b/test/runtime/typescript/src/payload-types/payloads/DogPayload.ts index 628fef66..b668367c 100644 --- a/test/runtime/typescript/src/payload-types/payloads/DogPayload.ts +++ b/test/runtime/typescript/src/payload-types/payloads/DogPayload.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface DogPayloadInterface { breed?: string barkVolume?: number @@ -90,6 +90,9 @@ class DogPayload { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -97,4 +100,5 @@ class DogPayload { } } -export { DogPayload, DogPayloadInterface }; \ No newline at end of file +export { DogPayload }; +export type { DogPayloadInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/FormatDate.ts b/test/runtime/typescript/src/payload-types/payloads/FormatDate.ts index 5fe2175e..0e8d36e4 100644 --- a/test/runtime/typescript/src/payload-types/payloads/FormatDate.ts +++ b/test/runtime/typescript/src/payload-types/payloads/FormatDate.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * String with date format (YYYY-MM-DD) */ @@ -27,6 +27,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/FormatDateTime.ts b/test/runtime/typescript/src/payload-types/payloads/FormatDateTime.ts index 5163284f..85ef0a2a 100644 --- a/test/runtime/typescript/src/payload-types/payloads/FormatDateTime.ts +++ b/test/runtime/typescript/src/payload-types/payloads/FormatDateTime.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * String with date-time format (ISO 8601) */ @@ -27,6 +27,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/FormatEmail.ts b/test/runtime/typescript/src/payload-types/payloads/FormatEmail.ts index bf0a805f..6e269b97 100644 --- a/test/runtime/typescript/src/payload-types/payloads/FormatEmail.ts +++ b/test/runtime/typescript/src/payload-types/payloads/FormatEmail.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * String with email format */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/FormatHostname.ts b/test/runtime/typescript/src/payload-types/payloads/FormatHostname.ts index 4b5c1151..0813c214 100644 --- a/test/runtime/typescript/src/payload-types/payloads/FormatHostname.ts +++ b/test/runtime/typescript/src/payload-types/payloads/FormatHostname.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * String with hostname format */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/FormatIpv4.ts b/test/runtime/typescript/src/payload-types/payloads/FormatIpv4.ts index 6605a818..1c59921a 100644 --- a/test/runtime/typescript/src/payload-types/payloads/FormatIpv4.ts +++ b/test/runtime/typescript/src/payload-types/payloads/FormatIpv4.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * String with IPv4 format */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/FormatIpv6.ts b/test/runtime/typescript/src/payload-types/payloads/FormatIpv6.ts index 3d3be40e..89e92a37 100644 --- a/test/runtime/typescript/src/payload-types/payloads/FormatIpv6.ts +++ b/test/runtime/typescript/src/payload-types/payloads/FormatIpv6.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * String with IPv6 format */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/FormatTime.ts b/test/runtime/typescript/src/payload-types/payloads/FormatTime.ts index e4ed87b0..892d07f8 100644 --- a/test/runtime/typescript/src/payload-types/payloads/FormatTime.ts +++ b/test/runtime/typescript/src/payload-types/payloads/FormatTime.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * String with time format (HH:MM:SS) */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/FormatUri.ts b/test/runtime/typescript/src/payload-types/payloads/FormatUri.ts index 4d9a0365..5129a637 100644 --- a/test/runtime/typescript/src/payload-types/payloads/FormatUri.ts +++ b/test/runtime/typescript/src/payload-types/payloads/FormatUri.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * String with URI format */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/FormatUuid.ts b/test/runtime/typescript/src/payload-types/payloads/FormatUuid.ts index 7a752b7b..df205195 100644 --- a/test/runtime/typescript/src/payload-types/payloads/FormatUuid.ts +++ b/test/runtime/typescript/src/payload-types/payloads/FormatUuid.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * String with UUID format */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/IntegerPlain.ts b/test/runtime/typescript/src/payload-types/payloads/IntegerPlain.ts index 511b0919..8bd1e86b 100644 --- a/test/runtime/typescript/src/payload-types/payloads/IntegerPlain.ts +++ b/test/runtime/typescript/src/payload-types/payloads/IntegerPlain.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * A plain integer type */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/IntegerWithRange.ts b/test/runtime/typescript/src/payload-types/payloads/IntegerWithRange.ts index cf4d0996..5e869d76 100644 --- a/test/runtime/typescript/src/payload-types/payloads/IntegerWithRange.ts +++ b/test/runtime/typescript/src/payload-types/payloads/IntegerWithRange.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * Integer between 1 and 10 */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/NestedArray.ts b/test/runtime/typescript/src/payload-types/payloads/NestedArray.ts index 8a063257..8f70d1d6 100644 --- a/test/runtime/typescript/src/payload-types/payloads/NestedArray.ts +++ b/test/runtime/typescript/src/payload-types/payloads/NestedArray.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * 2D array (array of string arrays) */ @@ -34,6 +34,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/NestedObject.ts b/test/runtime/typescript/src/payload-types/payloads/NestedObject.ts index c4a5f1af..e12e6895 100644 --- a/test/runtime/typescript/src/payload-types/payloads/NestedObject.ts +++ b/test/runtime/typescript/src/payload-types/payloads/NestedObject.ts @@ -1,6 +1,6 @@ import {NestedObjectOuter} from './NestedObjectOuter'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface NestedObjectInterface { outer?: NestedObjectOuter additionalProperties?: Record @@ -76,6 +76,9 @@ class NestedObject { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -83,4 +86,5 @@ class NestedObject { } } -export { NestedObject, NestedObjectInterface }; \ No newline at end of file +export { NestedObject }; +export type { NestedObjectInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/NestedObjectOuter.ts b/test/runtime/typescript/src/payload-types/payloads/NestedObjectOuter.ts index dcea8e7d..fcb426e7 100644 --- a/test/runtime/typescript/src/payload-types/payloads/NestedObjectOuter.ts +++ b/test/runtime/typescript/src/payload-types/payloads/NestedObjectOuter.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface NestedObjectOuterInterface { inner?: string additionalProperties?: Record @@ -72,6 +72,9 @@ class NestedObjectOuter { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -79,4 +82,5 @@ class NestedObjectOuter { } } -export { NestedObjectOuter, NestedObjectOuterInterface }; \ No newline at end of file +export { NestedObjectOuter }; +export type { NestedObjectOuterInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/NullPlain.ts b/test/runtime/typescript/src/payload-types/payloads/NullPlain.ts index 32cab9bc..b0144809 100644 --- a/test/runtime/typescript/src/payload-types/payloads/NullPlain.ts +++ b/test/runtime/typescript/src/payload-types/payloads/NullPlain.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * A null type */ @@ -30,6 +30,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/NumberPlain.ts b/test/runtime/typescript/src/payload-types/payloads/NumberPlain.ts index db2317d7..05ed0919 100644 --- a/test/runtime/typescript/src/payload-types/payloads/NumberPlain.ts +++ b/test/runtime/typescript/src/payload-types/payloads/NumberPlain.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * A plain number type */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/NumberWithMaximum.ts b/test/runtime/typescript/src/payload-types/payloads/NumberWithMaximum.ts index 95dbb0a6..e09590a7 100644 --- a/test/runtime/typescript/src/payload-types/payloads/NumberWithMaximum.ts +++ b/test/runtime/typescript/src/payload-types/payloads/NumberWithMaximum.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * Number with maximum of 100 */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/NumberWithMinimum.ts b/test/runtime/typescript/src/payload-types/payloads/NumberWithMinimum.ts index 946cdda3..599eb582 100644 --- a/test/runtime/typescript/src/payload-types/payloads/NumberWithMinimum.ts +++ b/test/runtime/typescript/src/payload-types/payloads/NumberWithMinimum.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * Number with minimum of 0 */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/NumberWithRange.ts b/test/runtime/typescript/src/payload-types/payloads/NumberWithRange.ts index f1dff0ad..0ffd47dd 100644 --- a/test/runtime/typescript/src/payload-types/payloads/NumberWithRange.ts +++ b/test/runtime/typescript/src/payload-types/payloads/NumberWithRange.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * Number strictly between 0 and 100 */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/ObjectAdditionalPropsFalse.ts b/test/runtime/typescript/src/payload-types/payloads/ObjectAdditionalPropsFalse.ts index 9496b091..a8985133 100644 --- a/test/runtime/typescript/src/payload-types/payloads/ObjectAdditionalPropsFalse.ts +++ b/test/runtime/typescript/src/payload-types/payloads/ObjectAdditionalPropsFalse.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface ObjectAdditionalPropsFalseInterface { known?: string } @@ -59,6 +59,9 @@ class ObjectAdditionalPropsFalse { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -66,4 +69,5 @@ class ObjectAdditionalPropsFalse { } } -export { ObjectAdditionalPropsFalse, ObjectAdditionalPropsFalseInterface }; \ No newline at end of file +export { ObjectAdditionalPropsFalse }; +export type { ObjectAdditionalPropsFalseInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/ObjectAdditionalPropsSchema.ts b/test/runtime/typescript/src/payload-types/payloads/ObjectAdditionalPropsSchema.ts index a7d3a7f9..a2d0c0d5 100644 --- a/test/runtime/typescript/src/payload-types/payloads/ObjectAdditionalPropsSchema.ts +++ b/test/runtime/typescript/src/payload-types/payloads/ObjectAdditionalPropsSchema.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface ObjectAdditionalPropsSchemaInterface { known?: string additionalProperties?: Record @@ -75,6 +75,9 @@ class ObjectAdditionalPropsSchema { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -82,4 +85,5 @@ class ObjectAdditionalPropsSchema { } } -export { ObjectAdditionalPropsSchema, ObjectAdditionalPropsSchemaInterface }; \ No newline at end of file +export { ObjectAdditionalPropsSchema }; +export type { ObjectAdditionalPropsSchemaInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/ObjectAdditionalPropsTrue.ts b/test/runtime/typescript/src/payload-types/payloads/ObjectAdditionalPropsTrue.ts index ccd27557..7ae56c18 100644 --- a/test/runtime/typescript/src/payload-types/payloads/ObjectAdditionalPropsTrue.ts +++ b/test/runtime/typescript/src/payload-types/payloads/ObjectAdditionalPropsTrue.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface ObjectAdditionalPropsTrueInterface { known?: string additionalProperties?: Record @@ -75,6 +75,9 @@ class ObjectAdditionalPropsTrue { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -82,4 +85,5 @@ class ObjectAdditionalPropsTrue { } } -export { ObjectAdditionalPropsTrue, ObjectAdditionalPropsTrueInterface }; \ No newline at end of file +export { ObjectAdditionalPropsTrue }; +export type { ObjectAdditionalPropsTrueInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/ObjectArray.ts b/test/runtime/typescript/src/payload-types/payloads/ObjectArray.ts index 6936584e..a8376bde 100644 --- a/test/runtime/typescript/src/payload-types/payloads/ObjectArray.ts +++ b/test/runtime/typescript/src/payload-types/payloads/ObjectArray.ts @@ -1,6 +1,6 @@ import {ObjectArrayItem} from './ObjectArrayItem'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * Array of objects */ @@ -38,6 +38,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/ObjectArrayItem.ts b/test/runtime/typescript/src/payload-types/payloads/ObjectArrayItem.ts index 629fafc4..9b70ccd4 100644 --- a/test/runtime/typescript/src/payload-types/payloads/ObjectArrayItem.ts +++ b/test/runtime/typescript/src/payload-types/payloads/ObjectArrayItem.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface ObjectArrayItemInterface { id?: number name?: string @@ -84,6 +84,9 @@ class ObjectArrayItem { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -91,4 +94,5 @@ class ObjectArrayItem { } } -export { ObjectArrayItem, ObjectArrayItemInterface }; \ No newline at end of file +export { ObjectArrayItem }; +export type { ObjectArrayItemInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/ObjectWithDefaults.ts b/test/runtime/typescript/src/payload-types/payloads/ObjectWithDefaults.ts index 93be8ba4..12efa523 100644 --- a/test/runtime/typescript/src/payload-types/payloads/ObjectWithDefaults.ts +++ b/test/runtime/typescript/src/payload-types/payloads/ObjectWithDefaults.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface ObjectWithDefaultsInterface { status?: string count?: number @@ -99,6 +99,9 @@ class ObjectWithDefaults { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -106,4 +109,5 @@ class ObjectWithDefaults { } } -export { ObjectWithDefaults, ObjectWithDefaultsInterface }; \ No newline at end of file +export { ObjectWithDefaults }; +export type { ObjectWithDefaultsInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/ObjectWithFormats.ts b/test/runtime/typescript/src/payload-types/payloads/ObjectWithFormats.ts index 4d6ddfcb..64989e7b 100644 --- a/test/runtime/typescript/src/payload-types/payloads/ObjectWithFormats.ts +++ b/test/runtime/typescript/src/payload-types/payloads/ObjectWithFormats.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface ObjectWithFormatsInterface { email?: string website?: string @@ -135,6 +135,9 @@ class ObjectWithFormats { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -142,4 +145,5 @@ class ObjectWithFormats { } } -export { ObjectWithFormats, ObjectWithFormatsInterface }; \ No newline at end of file +export { ObjectWithFormats }; +export type { ObjectWithFormatsInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/ObjectWithOptional.ts b/test/runtime/typescript/src/payload-types/payloads/ObjectWithOptional.ts index 6e1d04b3..c253eb28 100644 --- a/test/runtime/typescript/src/payload-types/payloads/ObjectWithOptional.ts +++ b/test/runtime/typescript/src/payload-types/payloads/ObjectWithOptional.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface ObjectWithOptionalInterface { field1?: string field2?: string @@ -99,6 +99,9 @@ class ObjectWithOptional { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -106,4 +109,5 @@ class ObjectWithOptional { } } -export { ObjectWithOptional, ObjectWithOptionalInterface }; \ No newline at end of file +export { ObjectWithOptional }; +export type { ObjectWithOptionalInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/ObjectWithRequired.ts b/test/runtime/typescript/src/payload-types/payloads/ObjectWithRequired.ts index 3822faca..f072eb63 100644 --- a/test/runtime/typescript/src/payload-types/payloads/ObjectWithRequired.ts +++ b/test/runtime/typescript/src/payload-types/payloads/ObjectWithRequired.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface ObjectWithRequiredInterface { id: string name: string @@ -99,6 +99,9 @@ class ObjectWithRequired { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -106,4 +109,5 @@ class ObjectWithRequired { } } -export { ObjectWithRequired, ObjectWithRequiredInterface }; \ No newline at end of file +export { ObjectWithRequired }; +export type { ObjectWithRequiredInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/OneOfThreeTypes.ts b/test/runtime/typescript/src/payload-types/payloads/OneOfThreeTypes.ts index bd9ba123..bf05bfab 100644 --- a/test/runtime/typescript/src/payload-types/payloads/OneOfThreeTypes.ts +++ b/test/runtime/typescript/src/payload-types/payloads/OneOfThreeTypes.ts @@ -1,6 +1,6 @@ import {OneOfThreeTypesOneOfOption2} from './OneOfThreeTypesOneOfOption2'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * OneOf with three type options */ @@ -34,6 +34,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/OneOfThreeTypesOneOfOption2.ts b/test/runtime/typescript/src/payload-types/payloads/OneOfThreeTypesOneOfOption2.ts index 892952e7..29f9e916 100644 --- a/test/runtime/typescript/src/payload-types/payloads/OneOfThreeTypesOneOfOption2.ts +++ b/test/runtime/typescript/src/payload-types/payloads/OneOfThreeTypesOneOfOption2.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface OneOfThreeTypesOneOfOption2Interface { value?: string additionalProperties?: Record @@ -72,6 +72,9 @@ class OneOfThreeTypesOneOfOption2 { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -79,4 +82,5 @@ class OneOfThreeTypesOneOfOption2 { } } -export { OneOfThreeTypesOneOfOption2, OneOfThreeTypesOneOfOption2Interface }; \ No newline at end of file +export { OneOfThreeTypesOneOfOption2 }; +export type { OneOfThreeTypesOneOfOption2Interface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/OneOfTwoTypes.ts b/test/runtime/typescript/src/payload-types/payloads/OneOfTwoTypes.ts index 53bb0896..689824fd 100644 --- a/test/runtime/typescript/src/payload-types/payloads/OneOfTwoTypes.ts +++ b/test/runtime/typescript/src/payload-types/payloads/OneOfTwoTypes.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * OneOf with string or integer */ @@ -30,6 +30,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/OneOfWithDiscriminator.ts b/test/runtime/typescript/src/payload-types/payloads/OneOfWithDiscriminator.ts index 434ef527..725ee89a 100644 --- a/test/runtime/typescript/src/payload-types/payloads/OneOfWithDiscriminator.ts +++ b/test/runtime/typescript/src/payload-types/payloads/OneOfWithDiscriminator.ts @@ -1,7 +1,7 @@ import {DogPayload} from './DogPayload'; import {CatPayload} from './CatPayload'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * OneOf with discriminator property */ @@ -43,6 +43,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/SimpleObject.ts b/test/runtime/typescript/src/payload-types/payloads/SimpleObject.ts index ad5f7d49..ba873254 100644 --- a/test/runtime/typescript/src/payload-types/payloads/SimpleObject.ts +++ b/test/runtime/typescript/src/payload-types/payloads/SimpleObject.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface SimpleObjectInterface { name?: string age?: number @@ -87,6 +87,9 @@ class SimpleObject { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -94,4 +97,5 @@ class SimpleObject { } } -export { SimpleObject, SimpleObjectInterface }; \ No newline at end of file +export { SimpleObject }; +export type { SimpleObjectInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payload-types/payloads/StringArray.ts b/test/runtime/typescript/src/payload-types/payloads/StringArray.ts index 1a7e094d..510f9ae5 100644 --- a/test/runtime/typescript/src/payload-types/payloads/StringArray.ts +++ b/test/runtime/typescript/src/payload-types/payloads/StringArray.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * Array of strings */ @@ -29,6 +29,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/StringPlain.ts b/test/runtime/typescript/src/payload-types/payloads/StringPlain.ts index 60608c65..8b8b0675 100644 --- a/test/runtime/typescript/src/payload-types/payloads/StringPlain.ts +++ b/test/runtime/typescript/src/payload-types/payloads/StringPlain.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * A plain string type */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/StringWithMaxLength.ts b/test/runtime/typescript/src/payload-types/payloads/StringWithMaxLength.ts index 915c79b5..b3c404fe 100644 --- a/test/runtime/typescript/src/payload-types/payloads/StringWithMaxLength.ts +++ b/test/runtime/typescript/src/payload-types/payloads/StringWithMaxLength.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * String with maximum length of 50 */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/StringWithMinLength.ts b/test/runtime/typescript/src/payload-types/payloads/StringWithMinLength.ts index 99057f0a..4cd86ec9 100644 --- a/test/runtime/typescript/src/payload-types/payloads/StringWithMinLength.ts +++ b/test/runtime/typescript/src/payload-types/payloads/StringWithMinLength.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * String with minimum length of 3 */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/StringWithPattern.ts b/test/runtime/typescript/src/payload-types/payloads/StringWithPattern.ts index b45ba329..125d180a 100644 --- a/test/runtime/typescript/src/payload-types/payloads/StringWithPattern.ts +++ b/test/runtime/typescript/src/payload-types/payloads/StringWithPattern.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * String matching capitalized word pattern */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payload-types/payloads/TupleArray.ts b/test/runtime/typescript/src/payload-types/payloads/TupleArray.ts index 7c771716..8c271b52 100644 --- a/test/runtime/typescript/src/payload-types/payloads/TupleArray.ts +++ b/test/runtime/typescript/src/payload-types/payloads/TupleArray.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * Tuple with fixed position types */ @@ -34,6 +34,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payloads/ArrayMessage.ts b/test/runtime/typescript/src/payloads/ArrayMessage.ts index e3d8a41c..14959285 100644 --- a/test/runtime/typescript/src/payloads/ArrayMessage.ts +++ b/test/runtime/typescript/src/payloads/ArrayMessage.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * An array of strings payload */ @@ -29,6 +29,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payloads/LegacyNotification.ts b/test/runtime/typescript/src/payloads/LegacyNotification.ts index 8295e7c0..0dc0a368 100644 --- a/test/runtime/typescript/src/payloads/LegacyNotification.ts +++ b/test/runtime/typescript/src/payloads/LegacyNotification.ts @@ -1,6 +1,6 @@ import {LegacyNotificationPayloadLevelEnum} from './LegacyNotificationPayloadLevelEnum'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface LegacyNotificationInterface { message?: string level?: LegacyNotificationPayloadLevelEnum @@ -94,6 +94,9 @@ class LegacyNotification { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -101,4 +104,5 @@ class LegacyNotification { } } -export { LegacyNotification, LegacyNotificationInterface }; \ No newline at end of file +export { LegacyNotification }; +export type { LegacyNotificationInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payloads/StringMessage.ts b/test/runtime/typescript/src/payloads/StringMessage.ts index b4efe734..443c9709 100644 --- a/test/runtime/typescript/src/payloads/StringMessage.ts +++ b/test/runtime/typescript/src/payloads/StringMessage.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * A simple string payload */ @@ -26,6 +26,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payloads/UnionMessage.ts b/test/runtime/typescript/src/payloads/UnionMessage.ts index f2545d83..e8955759 100644 --- a/test/runtime/typescript/src/payloads/UnionMessage.ts +++ b/test/runtime/typescript/src/payloads/UnionMessage.ts @@ -1,6 +1,6 @@ import {UnionPayloadOneOfOption2} from './UnionPayloadOneOfOption2'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; /** * A union type payload */ @@ -34,6 +34,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/payloads/UnionPayloadOneOfOption2.ts b/test/runtime/typescript/src/payloads/UnionPayloadOneOfOption2.ts index 7ed8cb00..1c3bb054 100644 --- a/test/runtime/typescript/src/payloads/UnionPayloadOneOfOption2.ts +++ b/test/runtime/typescript/src/payloads/UnionPayloadOneOfOption2.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface UnionPayloadOneOfOption2Interface { name?: string additionalProperties?: Record @@ -72,6 +72,9 @@ class UnionPayloadOneOfOption2 { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -79,4 +82,5 @@ class UnionPayloadOneOfOption2 { } } -export { UnionPayloadOneOfOption2, UnionPayloadOneOfOption2Interface }; \ No newline at end of file +export { UnionPayloadOneOfOption2 }; +export type { UnionPayloadOneOfOption2Interface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/payloads/UserSignedUp.ts b/test/runtime/typescript/src/payloads/UserSignedUp.ts index fa5f3407..1dabff95 100644 --- a/test/runtime/typescript/src/payloads/UserSignedUp.ts +++ b/test/runtime/typescript/src/payloads/UserSignedUp.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface UserSignedUpInterface { displayName?: string email?: string @@ -93,6 +93,9 @@ class UserSignedUp { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -100,4 +103,5 @@ class UserSignedUp { } } -export { UserSignedUp, UserSignedUpInterface }; \ No newline at end of file +export { UserSignedUp }; +export type { UserSignedUpInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/request-reply/channels/nats.ts b/test/runtime/typescript/src/request-reply/channels/nats.ts index a58f59f3..573399f0 100644 --- a/test/runtime/typescript/src/request-reply/channels/nats.ts +++ b/test/runtime/typescript/src/request-reply/channels/nats.ts @@ -97,7 +97,7 @@ function replyToRegularReply({ if(!skipMessageValidation) { const {valid, errors} = Pong.validate({data: receivedData, ajvValidatorFunction: validator}); if(!valid) { - onDataCallback(new Error('Invalid request payload received', JSON.stringify({cause: errors})), undefined); continue; + onDataCallback(new Error(`Invalid request payload received; ${JSON.stringify({cause: errors})}`), undefined); continue; } } const replyMessage = await onDataCallback(undefined, Pong.unmarshal(receivedData) ); diff --git a/test/runtime/typescript/src/request-reply/client/NatsClient.ts b/test/runtime/typescript/src/request-reply/client/NatsClient.ts index dd11eeaf..0380bba5 100644 --- a/test/runtime/typescript/src/request-reply/client/NatsClient.ts +++ b/test/runtime/typescript/src/request-reply/client/NatsClient.ts @@ -20,6 +20,7 @@ export {NotFound}; export {ItemResponse}; import {UserItemsParameters, UserItemsParametersInterface} from './../parameters/UserItemsParameters'; export {UserItemsParameters}; +import {ItemRequestHeaders} from './../headers/ItemRequestHeaders'; //Import channel functions import * as nats from './../channels/nats'; diff --git a/test/runtime/typescript/src/request-reply/headers/ItemRequestHeaders.ts b/test/runtime/typescript/src/request-reply/headers/ItemRequestHeaders.ts index df55332e..a927f91d 100644 --- a/test/runtime/typescript/src/request-reply/headers/ItemRequestHeaders.ts +++ b/test/runtime/typescript/src/request-reply/headers/ItemRequestHeaders.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; class ItemRequestHeaders { private _xCorrelationId: string; private _xRequestId?: string; @@ -89,6 +89,9 @@ class ItemRequestHeaders { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); diff --git a/test/runtime/typescript/src/request-reply/parameters/UserItemsParameters.ts b/test/runtime/typescript/src/request-reply/parameters/UserItemsParameters.ts index bfd07942..550bda37 100644 --- a/test/runtime/typescript/src/request-reply/parameters/UserItemsParameters.ts +++ b/test/runtime/typescript/src/request-reply/parameters/UserItemsParameters.ts @@ -58,4 +58,5 @@ class UserItemsParameters { return parameters; } } -export { UserItemsParameters, UserItemsParametersInterface }; \ No newline at end of file +export { UserItemsParameters }; +export type { UserItemsParametersInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/request-reply/payloads/GetUserItemReplyPayload.ts b/test/runtime/typescript/src/request-reply/payloads/GetUserItemReplyPayload.ts index 1d93d9fc..ada517e1 100644 --- a/test/runtime/typescript/src/request-reply/payloads/GetUserItemReplyPayload.ts +++ b/test/runtime/typescript/src/request-reply/payloads/GetUserItemReplyPayload.ts @@ -1,7 +1,7 @@ import {ItemResponse} from './ItemResponse'; import {NotFound} from './NotFound'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type GetUserItemReplyPayload = ItemResponse | NotFound; export function unmarshal(json: any): GetUserItemReplyPayload { @@ -42,6 +42,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/request-reply/payloads/ItemRequest.ts b/test/runtime/typescript/src/request-reply/payloads/ItemRequest.ts index 25961227..48459f81 100644 --- a/test/runtime/typescript/src/request-reply/payloads/ItemRequest.ts +++ b/test/runtime/typescript/src/request-reply/payloads/ItemRequest.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface ItemRequestInterface { name: string description?: string @@ -105,6 +105,9 @@ class ItemRequest { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -112,4 +115,5 @@ class ItemRequest { } } -export { ItemRequest, ItemRequestInterface }; \ No newline at end of file +export { ItemRequest }; +export type { ItemRequestInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/request-reply/payloads/ItemResponse.ts b/test/runtime/typescript/src/request-reply/payloads/ItemResponse.ts index d4266b4a..224bb195 100644 --- a/test/runtime/typescript/src/request-reply/payloads/ItemResponse.ts +++ b/test/runtime/typescript/src/request-reply/payloads/ItemResponse.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface ItemResponseInterface { id?: string userId?: string @@ -135,6 +135,9 @@ class ItemResponse { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -142,4 +145,5 @@ class ItemResponse { } } -export { ItemResponse, ItemResponseInterface }; \ No newline at end of file +export { ItemResponse }; +export type { ItemResponseInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/request-reply/payloads/MultiStatusResponseReplyPayload.ts b/test/runtime/typescript/src/request-reply/payloads/MultiStatusResponseReplyPayload.ts index 14c3a859..ad580b5d 100644 --- a/test/runtime/typescript/src/request-reply/payloads/MultiStatusResponseReplyPayload.ts +++ b/test/runtime/typescript/src/request-reply/payloads/MultiStatusResponseReplyPayload.ts @@ -1,7 +1,7 @@ import {Pong} from './Pong'; import {NotFound} from './NotFound'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type MultiStatusResponseReplyPayload = Pong | NotFound; export function unmarshal(json: any): MultiStatusResponseReplyPayload { @@ -42,6 +42,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/request-reply/payloads/NotFound.ts b/test/runtime/typescript/src/request-reply/payloads/NotFound.ts index 7322b86b..b06a8ae0 100644 --- a/test/runtime/typescript/src/request-reply/payloads/NotFound.ts +++ b/test/runtime/typescript/src/request-reply/payloads/NotFound.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface NotFoundInterface { error?: string code?: string @@ -90,6 +90,9 @@ class NotFound { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -97,4 +100,5 @@ class NotFound { } } -export { NotFound, NotFoundInterface }; \ No newline at end of file +export { NotFound }; +export type { NotFoundInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/request-reply/payloads/Ping.ts b/test/runtime/typescript/src/request-reply/payloads/Ping.ts index 8c70e899..13607cca 100644 --- a/test/runtime/typescript/src/request-reply/payloads/Ping.ts +++ b/test/runtime/typescript/src/request-reply/payloads/Ping.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface PingInterface { ping?: string additionalProperties?: Record @@ -75,6 +75,9 @@ class Ping { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -82,4 +85,5 @@ class Ping { } } -export { Ping, PingInterface }; \ No newline at end of file +export { Ping }; +export type { PingInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/request-reply/payloads/PingPayload.ts b/test/runtime/typescript/src/request-reply/payloads/PingPayload.ts index 84481591..a819985c 100644 --- a/test/runtime/typescript/src/request-reply/payloads/PingPayload.ts +++ b/test/runtime/typescript/src/request-reply/payloads/PingPayload.ts @@ -2,7 +2,7 @@ import {Ping} from './Ping'; import {Pong} from './Pong'; import {NotFound} from './NotFound'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type PingPayload = Ping | Pong | NotFound; export function unmarshal(json: any): PingPayload { @@ -46,6 +46,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/request-reply/payloads/Pong.ts b/test/runtime/typescript/src/request-reply/payloads/Pong.ts index 6f6194ce..9d943c8f 100644 --- a/test/runtime/typescript/src/request-reply/payloads/Pong.ts +++ b/test/runtime/typescript/src/request-reply/payloads/Pong.ts @@ -1,5 +1,5 @@ import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; interface PongInterface { pong?: string additionalProperties?: Record @@ -75,6 +75,9 @@ class Pong { } public static createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(this.theCodeGenSchema); @@ -82,4 +85,5 @@ class Pong { } } -export { Pong, PongInterface }; \ No newline at end of file +export { Pong }; +export type { PongInterface }; \ No newline at end of file diff --git a/test/runtime/typescript/src/request-reply/payloads/UpdateUserItemReplyPayload.ts b/test/runtime/typescript/src/request-reply/payloads/UpdateUserItemReplyPayload.ts index 02ba0736..681e274e 100644 --- a/test/runtime/typescript/src/request-reply/payloads/UpdateUserItemReplyPayload.ts +++ b/test/runtime/typescript/src/request-reply/payloads/UpdateUserItemReplyPayload.ts @@ -1,7 +1,7 @@ import {ItemResponse} from './ItemResponse'; import {NotFound} from './NotFound'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type UpdateUserItemReplyPayload = ItemResponse | NotFound; export function unmarshal(json: any): UpdateUserItemReplyPayload { @@ -42,6 +42,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/src/request-reply/payloads/UserItemsPayload.ts b/test/runtime/typescript/src/request-reply/payloads/UserItemsPayload.ts index 1bf1e0cb..ca68472d 100644 --- a/test/runtime/typescript/src/request-reply/payloads/UserItemsPayload.ts +++ b/test/runtime/typescript/src/request-reply/payloads/UserItemsPayload.ts @@ -2,7 +2,7 @@ import {ItemRequest} from './ItemRequest'; import {ItemResponse} from './ItemResponse'; import {NotFound} from './NotFound'; import {Ajv, Options as AjvOptions, ErrorObject, ValidateFunction} from 'ajv'; -import {default as addFormats} from 'ajv-formats'; +import addFormatsModule from 'ajv-formats'; type UserItemsPayload = ItemRequest | ItemResponse | NotFound; export function unmarshal(json: any): UserItemsPayload { @@ -46,6 +46,9 @@ export function validate(context?: {data: any, ajvValidatorFunction?: ValidateFu } export function createValidator(context?: {ajvInstance?: Ajv, ajvOptions?: AjvOptions}): ValidateFunction { const {ajvInstance} = {...context ?? {}, ajvInstance: new Ajv(context?.ajvOptions ?? {})}; + // `ajv-formats` is CommonJS; its default import is the module namespace under + // `moduleResolution: node16`/`nodenext`, so unwrap `.default` when present. + const addFormats = ((addFormatsModule as unknown as {default?: unknown}).default ?? addFormatsModule) as (ajv: Ajv) => Ajv; addFormats(ajvInstance); const validate = ajvInstance.compile(theCodeGenSchema); diff --git a/test/runtime/typescript/test/payload-types/formats.spec.ts b/test/runtime/typescript/test/payload-types/formats.spec.ts index f0553edc..3edf640a 100644 --- a/test/runtime/typescript/test/payload-types/formats.spec.ts +++ b/test/runtime/typescript/test/payload-types/formats.spec.ts @@ -226,26 +226,33 @@ describe('Format Validation', () => { expect(result).toBe('10:30:00'); }); + // ajv-formats v3 follows RFC 3339 `full-time`, which requires a time + // offset. A bare local time is rejected — v2 accepted it. test('should validate correct time', () => { - const result = FormatTime.validate({ data: '"10:30:00"' }); + const result = FormatTime.validate({ data: '"10:30:00Z"' }); expect(result.valid).toBe(true); }); test('should validate midnight', () => { - const result = FormatTime.validate({ data: '"00:00:00"' }); + const result = FormatTime.validate({ data: '"00:00:00Z"' }); expect(result.valid).toBe(true); }); test('should validate end of day', () => { - const result = FormatTime.validate({ data: '"23:59:59"' }); + const result = FormatTime.validate({ data: '"23:59:59Z"' }); expect(result.valid).toBe(true); }); - test('should validate time with timezone', () => { - const result = FormatTime.validate({ data: '"10:30:00Z"' }); + test('should validate time with a numeric offset', () => { + const result = FormatTime.validate({ data: '"10:30:00+02:00"' }); expect(result.valid).toBe(true); }); + test('should invalidate a time without an offset', () => { + const result = FormatTime.validate({ data: '"10:30:00"' }); + expect(result.valid).toBe(false); + }); + test('should invalidate 24:00:00', () => { const result = FormatTime.validate({ data: '"24:00:00"' }); expect(result.valid).toBe(false);