@ioka-technologies/asyncapi-rust-client-template 0.0.34 → 0.0.36

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.34",
3
+ "version": "0.0.36",
4
4
  "description": "AsyncAPI template for generating Rust NATS clients",
5
5
  "main": "template/index.js",
6
6
  "keywords": [
@@ -24,6 +24,12 @@
24
24
  "test:nats": "asyncapi generate fromTemplate ../examples/nats/asyncapi.yaml ./ -o test-output-nats --force-write && echo 'Generated library files:' && ls -la test-output-nats/ && cd test-output-nats && cargo build --lib",
25
25
  "clean": "rm -rf dist test-output-*"
26
26
  },
27
+ "files": [
28
+ "template/**/*",
29
+ "!template/**/*.dev",
30
+ "dist/common/**/*",
31
+ "README.md"
32
+ ],
27
33
  "generator": {
28
34
  "renderer": "react",
29
35
  "apiVersion": "v3",
@@ -38,48 +38,67 @@ ${(() => {
38
38
  models.messageSchemas.forEach(schema => {
39
39
  const doc = schema.description ? `/// ${schema.description}` : `/// ${schema.name} message`;
40
40
 
41
+ // Skip if already implemented
42
+ if (implementedTypes.has(schema.rustName)) {
43
+ return;
44
+ }
45
+
41
46
  // Check if the message payload references a component schema
42
- let payloadRustName = null;
43
- let isComponentMessage = false;
47
+ let payloadSchemaName = null;
48
+ let payloadSchema = null;
44
49
 
45
50
  if (schema.rawPayload && schema.rawPayload.$ref) {
46
- const refName = schema.rawPayload.$ref.split('/').pop();
47
- payloadRustName = toRustTypeName(refName);
48
- isComponentMessage = true;
51
+ payloadSchemaName = schema.rawPayload.$ref.split('/').pop();
49
52
  } else if (schema.payload && schema.payload.$ref) {
50
- const refName = schema.payload.$ref.split('/').pop();
51
- payloadRustName = toRustTypeName(refName);
52
- isComponentMessage = true;
53
+ payloadSchemaName = schema.payload.$ref.split('/').pop();
53
54
  } else if (schema.payload && schema.payload['x-parser-schema-id']) {
54
55
  // Handle resolved $ref references
55
56
  const schemaId = schema.payload['x-parser-schema-id'];
56
57
  if (models.schemaRegistry.has(schemaId)) {
57
- payloadRustName = toRustTypeName(schemaId);
58
- isComponentMessage = true;
58
+ payloadSchemaName = schemaId;
59
59
  }
60
60
  }
61
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(`
62
+ // If we have a payload schema reference, resolve it and flatten the fields
63
+ // The message type should use the MESSAGE name (e.g., BootstrapDeviceRequest),
64
+ // NOT the payload schema name (e.g., BootstrapDevicePayload)
65
+ if (payloadSchemaName && models.schemaRegistry.has(payloadSchemaName)) {
66
+ payloadSchema = models.schemaRegistry.get(payloadSchemaName);
67
+
68
+ // Follow $ref chains - if the schema is just a $ref, resolve it
69
+ // This handles cases like: ConfigureDeviceResponsePayload: { $ref: 'common.yaml#/BaseResponse' }
70
+ while (payloadSchema && payloadSchema.$ref && !payloadSchema.properties && !payloadSchema.allOf) {
71
+ const refName = payloadSchema.$ref.split('/').pop();
72
+ if (models.schemaRegistry.has(refName)) {
73
+ payloadSchema = models.schemaRegistry.get(refName);
74
+ } else {
75
+ // Can't resolve further, break
76
+ break;
77
+ }
78
+ }
79
+ }
80
+
81
+ implementedTypes.add(schema.rustName);
82
+
83
+ // Generate the message struct with flattened payload fields
84
+ let fields;
85
+ if (payloadSchema) {
86
+ // Use the resolved payload schema to generate fields
87
+ fields = models.generateMessageStruct(payloadSchema, schema.rustName);
88
+ } else if (schema.payload) {
89
+ // Fallback to the parsed payload
90
+ fields = models.generateMessageStruct(schema.payload, schema.rustName);
91
+ } else {
92
+ // No payload - generate empty struct with data field
93
+ fields = ' pub data: serde_json::Value,';
94
+ }
95
+
96
+ implementations.push(`
77
97
  ${doc}
78
98
  #[derive(Debug, Clone, Serialize, Deserialize)]
79
99
  pub struct ${schema.rustName} {
80
- ${models.generateMessageStruct(schema.payload, schema.rustName)}
100
+ ${fields}
81
101
  }`);
82
- }
83
102
  });
84
103
 
85
104
  return implementations.join('');