@ioka-technologies/asyncapi-rust-client-template 0.0.24 → 0.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ioka-technologies/asyncapi-rust-client-template",
3
- "version": "0.0.24",
3
+ "version": "0.0.26",
4
4
  "description": "AsyncAPI template for generating Rust NATS clients",
5
5
  "main": "template/index.js",
6
6
  "keywords": [
@@ -8,7 +8,7 @@ import {
8
8
  resolveTemplateParameters
9
9
  } from './helpers/index.js';
10
10
 
11
- module.exports = function ({ asyncapi, params }) {
11
+ export default function ({ asyncapi, params }) {
12
12
  const asyncApiInfo = extractAsyncApiInfo(asyncapi);
13
13
  const { title, version, description } = asyncApiInfo;
14
14
 
@@ -28,7 +28,7 @@ import {
28
28
  isTemplateVariable,
29
29
  extractAsyncApiInfo,
30
30
  resolveTemplateParameters
31
- } from "../dist/common/index.js";
31
+ } from "../../dist/common/index.js";
32
32
 
33
33
  // Re-export common utilities for backward compatibility
34
34
  export {
package/template/index.js CHANGED
@@ -1,7 +1,14 @@
1
- const { File } = require('@asyncapi/generator-react-sdk');
2
- const React = require('react');
3
-
4
- module.exports = function ({ asyncapi, params }) {
1
+ import { File } from '@asyncapi/generator-react-sdk';
2
+ import React from 'react';
3
+ import LibRs from './src/lib.rs.js';
4
+ import ClientRs from './src/client.rs.js';
5
+ import ErrorsRs from './src/errors.rs.js';
6
+ import EnvelopeRs from './src/envelope.rs.js';
7
+ import ModelsRs from './src/models.rs.js';
8
+ import AuthRs from './src/auth.rs.js';
9
+ import CargoToml from './Cargo.toml.js';
10
+
11
+ export default function ({ asyncapi, params }) {
5
12
  // Extract info from AsyncAPI spec
6
13
  let title, version, description;
7
14
  try {
@@ -55,15 +62,6 @@ module.exports = function ({ asyncapi, params }) {
55
62
  ? params.license
56
63
  : 'Apache-2.0';
57
64
 
58
- // Import the source file generators
59
- const LibRs = require('./src/lib.rs.js');
60
- const ClientRs = require('./src/client.rs.js');
61
- const ErrorsRs = require('./src/errors.rs.js');
62
- const EnvelopeRs = require('./src/envelope.rs.js');
63
- const ModelsRs = require('./src/models.rs.js');
64
- const AuthRs = require('./src/auth.rs.js');
65
- const CargoToml = require('./Cargo.toml.js');
66
-
67
65
  // Generate all files from the main index.js
68
66
  return [
69
67
  // Use the separate Cargo.toml template
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable no-unused-vars */
2
2
  import { File } from '@asyncapi/generator-react-sdk';
3
3
 
4
- module.exports = function ({ asyncapi, params }) {
4
+ export default function ({ asyncapi, params }) {
5
5
  return (
6
6
  <File name="auth.rs">
7
7
  {`//! Authentication support for the NATS client
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable no-unused-vars */
2
2
  import { File } from '@asyncapi/generator-react-sdk';
3
3
 
4
- module.exports = function ({ asyncapi, params }) {
4
+ export default function ({ asyncapi, params }) {
5
5
  return (
6
6
  <File name="envelope.rs">
7
7
  {`//! Message envelope for consistent NATS message format
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable no-unused-vars */
2
2
  import { File } from '@asyncapi/generator-react-sdk';
3
3
 
4
- module.exports = function ({ asyncapi, params }) {
4
+ export default function ({ asyncapi, params }) {
5
5
  return (
6
6
  <File name="errors.rs">
7
7
  {`//! Error types for the NATS client
@@ -7,7 +7,7 @@ import {
7
7
  resolveTemplateParameters
8
8
  } from '../helpers/index.js';
9
9
 
10
- module.exports = function ({ asyncapi, params }) {
10
+ export default function ({ asyncapi, params }) {
11
11
  const asyncApiInfo = extractAsyncApiInfo(asyncapi);
12
12
  const { title, version, description } = asyncApiInfo;
13
13
 
@@ -22,7 +22,10 @@ module.exports = function ({ asyncapi, params }) {
22
22
 
23
23
  return (
24
24
  <File name="lib.rs">
25
- {`//! ${title}
25
+ {`#![allow(clippy::uninlined_format_args)]
26
+ #![allow(clippy::unnecessary_map_or)]
27
+ #![allow(clippy::empty_line_after_doc_comments)]
28
+ //! ${title}
26
29
  //!
27
30
  //! ${formatDescription(description)}
28
31
  //!
@@ -8,7 +8,7 @@ import {
8
8
  toRustEnumVariantWithSerde,
9
9
  generateRustModels,
10
10
  generateMessageEnvelope
11
- } from '../../../common/src/index.js';
11
+ } from "../../dist/common/index.js";
12
12
 
13
13
  export default function ModelsRs({ asyncapi }) {
14
14
  // Generate models using the common helper
@@ -0,0 +1,110 @@
1
+ /* eslint-disable no-unused-vars */
2
+ import { File } from '@asyncapi/generator-react-sdk';
3
+ import {
4
+ toRustIdentifier,
5
+ toRustTypeName,
6
+ toRustFieldName,
7
+ toRustEnumVariant,
8
+ toRustEnumVariantWithSerde,
9
+ generateRustModels,
10
+ generateMessageEnvelope
11
+ } from '../../../common/src/index.js';
12
+
13
+ export default function ModelsRs({ asyncapi }) {
14
+ // Generate models using the common helper
15
+ const models = generateRustModels(asyncapi, {
16
+ toRustTypeName,
17
+ toRustFieldName,
18
+ toRustEnumVariantWithSerde,
19
+ includeAsyncApiTrait: false, // Client doesn't need the AsyncApiMessage trait
20
+ includeEnvelope: false // We'll generate the envelope separately
21
+ });
22
+
23
+ // Generate the unified message envelope
24
+ const envelopeCode = generateMessageEnvelope();
25
+
26
+ return (
27
+ <File name="models.rs">
28
+ {`//! Generated data models from AsyncAPI specification
29
+
30
+ ${envelopeCode}
31
+ ${models.generateComponentSchemas()}
32
+ ${models.generateNestedTypes()}
33
+ ${(() => {
34
+ // Track which types have already had implementations generated
35
+ const implementedTypes = new Set();
36
+ const implementations = [];
37
+
38
+ models.messageSchemas.forEach(schema => {
39
+ const doc = schema.description ? `/// ${schema.description}` : `/// ${schema.name} message`;
40
+
41
+ // Check if the message payload references a component schema
42
+ let payloadRustName = null;
43
+ let isComponentMessage = false;
44
+
45
+ if (schema.rawPayload && schema.rawPayload.$ref) {
46
+ const refName = schema.rawPayload.$ref.split('/').pop();
47
+ payloadRustName = toRustTypeName(refName);
48
+ isComponentMessage = true;
49
+ } else if (schema.payload && schema.payload.$ref) {
50
+ const refName = schema.payload.$ref.split('/').pop();
51
+ payloadRustName = toRustTypeName(refName);
52
+ isComponentMessage = true;
53
+ } else if (schema.payload && schema.payload['x-parser-schema-id']) {
54
+ // Handle resolved $ref references
55
+ const schemaId = schema.payload['x-parser-schema-id'];
56
+ if (models.schemaRegistry.has(schemaId)) {
57
+ payloadRustName = toRustTypeName(schemaId);
58
+ isComponentMessage = true;
59
+ }
60
+ }
61
+
62
+ // For component messages, always generate the message wrapper type
63
+ // even if the payload schema already exists
64
+ if (isComponentMessage && payloadRustName && !implementedTypes.has(schema.rustName)) {
65
+ implementedTypes.add(schema.rustName);
66
+ implementations.push(`
67
+ ${doc}
68
+ #[derive(Debug, Clone, Serialize, Deserialize)]
69
+ pub struct ${schema.rustName} {
70
+ #[serde(flatten)]
71
+ pub payload: ${payloadRustName},
72
+ }`);
73
+ } else if (!models.generatedTypes.has(schema.rustName) && !implementedTypes.has(schema.rustName)) {
74
+ // Generate both struct for inline message schemas
75
+ implementedTypes.add(schema.rustName);
76
+ implementations.push(`
77
+ ${doc}
78
+ #[derive(Debug, Clone, Serialize, Deserialize)]
79
+ pub struct ${schema.rustName} {
80
+ ${models.generateMessageStruct(schema.payload, schema.rustName)}
81
+ }`);
82
+ }
83
+ });
84
+
85
+ return implementations.join('');
86
+ })()}
87
+
88
+ ${models.messageSchemas.length === 0 && models.componentSchemas.length === 0 ? `
89
+ /// Example message structure when no messages are defined in the spec
90
+ #[derive(Debug, Clone, Serialize, Deserialize)]
91
+ pub struct ExampleMessage {
92
+ pub id: String,
93
+ pub content: String,
94
+ pub timestamp: chrono::DateTime<chrono::Utc>,
95
+ }
96
+
97
+ impl ExampleMessage {
98
+ /// Create a new instance with required fields
99
+ pub fn new(id: String, content: String, timestamp: chrono::DateTime<chrono::Utc>) -> Self {
100
+ Self {
101
+ id,
102
+ content,
103
+ timestamp,
104
+ }
105
+ }
106
+ }` : ''}
107
+ `}
108
+ </File>
109
+ );
110
+ }