@ioka-technologies/asyncapi-rust-client-template 0.0.33 → 0.0.35

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.33",
3
+ "version": "0.0.35",
4
4
  "description": "AsyncAPI template for generating Rust NATS clients",
5
5
  "main": "template/index.js",
6
6
  "keywords": [
@@ -26,6 +26,7 @@
26
26
  },
27
27
  "files": [
28
28
  "template/**/*",
29
+ "!template/**/*.dev",
29
30
  "dist/common/**/*",
30
31
  "README.md"
31
32
  ],
@@ -1,116 +0,0 @@
1
- /**
2
- * Template-specific helper functions for Rust client template
3
- *
4
- * Most common utilities have been moved to the shared @common package.
5
- * This file now only contains template-specific functions that are unique
6
- * to the rust-client template.
7
- */
8
-
9
- // Import common utilities for use in local functions
10
- import {
11
- toRustIdentifier,
12
- toRustTypeName,
13
- toRustFieldName,
14
- toRustEnumVariant,
15
- toRustEnumVariantWithSerde,
16
- getMessageTypeName,
17
- getMessageRustTypeName,
18
- getPayloadRustTypeName,
19
- getNatsSubject,
20
- isDynamicChannel,
21
- extractChannelVariables,
22
- getChannelParameters,
23
- resolveChannelAddress,
24
- channelHasParameters,
25
- toPascalCase,
26
- toKebabCase,
27
- toSnakeCase,
28
- isTemplateVariable,
29
- extractAsyncApiInfo,
30
- resolveTemplateParameters
31
- } from '../../../common/src/index.js';
32
-
33
- // Re-export common utilities for backward compatibility
34
- export {
35
- toRustIdentifier,
36
- toRustTypeName,
37
- toRustFieldName,
38
- toRustEnumVariant,
39
- toRustEnumVariantWithSerde,
40
- getMessageTypeName,
41
- getMessageRustTypeName,
42
- getPayloadRustTypeName,
43
- getNatsSubject,
44
- isDynamicChannel,
45
- extractChannelVariables,
46
- getChannelParameters,
47
- resolveChannelAddress,
48
- channelHasParameters,
49
- toPascalCase,
50
- toKebabCase,
51
- toSnakeCase,
52
- isTemplateVariable,
53
- extractAsyncApiInfo,
54
- resolveTemplateParameters
55
- };
56
-
57
- /**
58
- * Analyzes operations to determine client method patterns
59
- * For NATS clients, we need to distinguish between:
60
- * - Request/Reply operations (using NATS request/reply)
61
- * - Publish operations (fire-and-forget)
62
- * - Subscribe operations (message handlers)
63
- *
64
- * This function is specific to the rust-client template's operation analysis needs.
65
- *
66
- * @param {Array} operations - Array of AsyncAPI operations
67
- * @returns {Array} Array of client method patterns
68
- */
69
- export function analyzeClientOperations(operations) {
70
- const patterns = [];
71
-
72
- for (const operation of operations) {
73
- const operationName = operation.id();
74
- const action = operation.action();
75
- const messages = operation.messages();
76
-
77
- if (action === 'send') {
78
- // Client sends messages - this becomes a client method
79
- if (operation.reply && operation.reply()) {
80
- // Request/Reply pattern
81
- patterns.push({
82
- type: 'request_reply',
83
- operation,
84
- operationName,
85
- methodName: toRustFieldName(operationName),
86
- requestMessage: messages[0],
87
- responseMessage: operation.reply().messages()[0],
88
- requestType: getPayloadRustTypeName(messages[0]),
89
- responseType: getPayloadRustTypeName(operation.reply().messages()[0])
90
- });
91
- } else {
92
- // Publish pattern (fire-and-forget)
93
- patterns.push({
94
- type: 'publish',
95
- operation,
96
- operationName,
97
- methodName: toRustFieldName(operationName),
98
- message: messages[0],
99
- payloadType: getPayloadRustTypeName(messages[0])
100
- });
101
- }
102
- } else if (action === 'receive') {
103
- // Client receives messages - this becomes a subscription method
104
- patterns.push({
105
- type: 'subscribe',
106
- operation,
107
- operationName,
108
- methodName: toRustFieldName(operationName.replace(/^receive/, 'subscribe_to_')),
109
- message: messages[0],
110
- payloadType: getPayloadRustTypeName(messages[0])
111
- });
112
- }
113
- }
114
-
115
- return patterns;
116
- }
@@ -1,31 +0,0 @@
1
- /* eslint-disable no-unused-vars */
2
- import { File } from '@asyncapi/generator-react-sdk';
3
- import { generateMessageEnvelope } from '../../../common/src/index.js';
4
-
5
- export default function ({ asyncapi, params }) {
6
- // Generate the unified message envelope with error support
7
- const envelopeCode = generateMessageEnvelope();
8
-
9
- return (
10
- <File name="envelope.rs">
11
- {`//! Message envelope for consistent NATS message format
12
-
13
- use crate::auth::{AuthCredentials, generate_auth_headers};
14
- ${envelopeCode}
15
-
16
- // Client-specific extensions for auth integration
17
- impl MessageEnvelope {
18
- /// Create a new message envelope with authentication headers
19
- pub fn new_with_auth<T: Serialize>(
20
- operation: &str,
21
- payload: T,
22
- auth: &AuthCredentials,
23
- ) -> Result<Self, serde_json::Error> {
24
- let auth_headers = generate_auth_headers(auth);
25
- Self::new(operation, payload).map(|envelope| envelope.with_auth_headers(auth_headers))
26
- }
27
- }
28
- `}
29
- </File>
30
- );
31
- };
@@ -1,110 +0,0 @@
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
- }