@c7-digital/ledger 0.0.6 → 0.0.7
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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Auto-generated file - do not edit manually
|
|
2
|
-
// Generated from /Users/stefanpla/Development/c7/
|
|
2
|
+
// Generated from /Users/stefanpla/Development/c7/c7_ledger/c7_ledger/ledger/specs/asyncapi_3.4.7.yaml
|
|
3
3
|
export const ASYNCAPI_SCHEMA = `asyncapi: 2.6.0
|
|
4
4
|
info:
|
|
5
5
|
title: JSON Ledger API WebSocket endpoints
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Auto-generated file - do not edit manually
|
|
2
|
-
// Generated from /Users/stefanpla/Development/c7/
|
|
2
|
+
// Generated from /Users/stefanpla/Development/c7/c7_ledger/c7_ledger/ledger/specs/openapi_3.4.7.yaml
|
|
3
3
|
export const OPENAPI_SCHEMA = `openapi: 3.0.3
|
|
4
4
|
info:
|
|
5
5
|
title: JSON Ledger API HTTP endpoints
|
package/lib/src/validation.d.ts
CHANGED
|
@@ -15,6 +15,11 @@ export declare class SchemaValidator {
|
|
|
15
15
|
* Helper function to handle errors based on the validation mode
|
|
16
16
|
*/
|
|
17
17
|
private handleError;
|
|
18
|
+
/**
|
|
19
|
+
* Transform schema to allow null values for non-required fields
|
|
20
|
+
* This handles the common OpenAPI pattern where optional fields can be null
|
|
21
|
+
*/
|
|
22
|
+
private makeOptionalFieldsNullable;
|
|
18
23
|
private loadSchemasFromContent;
|
|
19
24
|
/**
|
|
20
25
|
* Validate an array of items against a schema
|
package/lib/src/validation.js
CHANGED
|
@@ -95,6 +95,61 @@ export class SchemaValidator {
|
|
|
95
95
|
throw error instanceof Error ? error : new Error(message);
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Transform schema to allow null values for non-required fields
|
|
100
|
+
* This handles the common OpenAPI pattern where optional fields can be null
|
|
101
|
+
*/
|
|
102
|
+
makeOptionalFieldsNullable(schema) {
|
|
103
|
+
if (!schema || typeof schema !== "object")
|
|
104
|
+
return schema;
|
|
105
|
+
// Handle arrays - recursively transform each element
|
|
106
|
+
if (Array.isArray(schema)) {
|
|
107
|
+
return schema.map((item) => this.makeOptionalFieldsNullable(item));
|
|
108
|
+
}
|
|
109
|
+
const transformed = { ...schema };
|
|
110
|
+
// If this is an object schema with properties
|
|
111
|
+
if (transformed.type === "object" && transformed.properties) {
|
|
112
|
+
const required = new Set(transformed.required || []);
|
|
113
|
+
// For each property that's not required, allow null values
|
|
114
|
+
for (const [propName, propSchema] of Object.entries(transformed.properties)) {
|
|
115
|
+
if (!required.has(propName) && typeof propSchema === "object" && !Array.isArray(propSchema)) {
|
|
116
|
+
// If it has a simple type and isn't already allowing null
|
|
117
|
+
if (propSchema.type && typeof propSchema.type === "string" && propSchema.type !== "null") {
|
|
118
|
+
// Make it accept both the original type and null
|
|
119
|
+
transformed.properties[propName] = {
|
|
120
|
+
...propSchema,
|
|
121
|
+
anyOf: [
|
|
122
|
+
{ ...propSchema, type: propSchema.type },
|
|
123
|
+
{ type: "null" }
|
|
124
|
+
]
|
|
125
|
+
};
|
|
126
|
+
// Remove the type field as it's now in anyOf
|
|
127
|
+
delete transformed.properties[propName].type;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Recursively transform nested schemas
|
|
131
|
+
const nestedSchema = transformed.properties[propName];
|
|
132
|
+
if (nestedSchema) {
|
|
133
|
+
transformed.properties[propName] = this.makeOptionalFieldsNullable(nestedSchema);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Handle $ref - don't transform, let AJV resolve it
|
|
138
|
+
if (transformed.$ref) {
|
|
139
|
+
return transformed;
|
|
140
|
+
}
|
|
141
|
+
// Recursively handle nested schemas in allOf, anyOf, oneOf
|
|
142
|
+
if (transformed.allOf) {
|
|
143
|
+
transformed.allOf = transformed.allOf.map((s) => this.makeOptionalFieldsNullable(s));
|
|
144
|
+
}
|
|
145
|
+
if (transformed.anyOf) {
|
|
146
|
+
transformed.anyOf = transformed.anyOf.map((s) => this.makeOptionalFieldsNullable(s));
|
|
147
|
+
}
|
|
148
|
+
if (transformed.oneOf) {
|
|
149
|
+
transformed.oneOf = transformed.oneOf.map((s) => this.makeOptionalFieldsNullable(s));
|
|
150
|
+
}
|
|
151
|
+
return transformed;
|
|
152
|
+
}
|
|
98
153
|
async loadSchemasFromContent(yamlContent) {
|
|
99
154
|
if (!this.ajv)
|
|
100
155
|
return;
|
|
@@ -104,6 +159,23 @@ export class SchemaValidator {
|
|
|
104
159
|
const spec = yaml.parse(yamlContent);
|
|
105
160
|
// Load the complete schema document first to enable reference resolution
|
|
106
161
|
if (spec?.components?.schemas) {
|
|
162
|
+
// Transform schemas to allow null for optional fields
|
|
163
|
+
for (const [schemaName, schemaDefinition] of Object.entries(spec.components.schemas)) {
|
|
164
|
+
const transformed = this.makeOptionalFieldsNullable(schemaDefinition);
|
|
165
|
+
// Schemas in the components should always be objects, not arrays
|
|
166
|
+
if (transformed) {
|
|
167
|
+
if (Array.isArray(transformed)) {
|
|
168
|
+
// Arrays shouldn't appear at the schema root level, but handle gracefully
|
|
169
|
+
const firstItem = transformed[0];
|
|
170
|
+
if (firstItem) {
|
|
171
|
+
spec.components.schemas[schemaName] = firstItem;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
spec.components.schemas[schemaName] = transformed;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
107
179
|
// Add the full schema document with an ID so references can be resolved
|
|
108
180
|
this.ajv.addSchema(spec, "#");
|
|
109
181
|
logger.debug(`Added full schema document with ID "#"`);
|
|
@@ -168,7 +240,10 @@ export class SchemaValidator {
|
|
|
168
240
|
}
|
|
169
241
|
const isValid = this.ajv.validate(schemaName, data);
|
|
170
242
|
if (!isValid) {
|
|
171
|
-
|
|
243
|
+
const errorDetails = this.ajv.errorsText();
|
|
244
|
+
logger.warn(`Validation errors: ${errorDetails}`);
|
|
245
|
+
logger.debug(`Full validation errors:`, this.ajv.errors);
|
|
246
|
+
this.handleError(`Schema validation failed for ${schemaName}: ${errorDetails}`, new Error(`Schema validation failed for ${schemaName}: ${errorDetails}`));
|
|
172
247
|
}
|
|
173
248
|
else {
|
|
174
249
|
logger.debug(`Validation successful for "${schemaName}"`);
|