Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/wicked-states-wish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@redocly/openapi-core": patch
---

Updated @redocly/config to v0.36.0.
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
],
"dependencies": {
"@redocly/ajv": "^8.11.2",
"@redocly/config": "^0.31.0",
"@redocly/config": "^0.36.0",
"ajv-formats": "^2.1.1",
"colorette": "^1.2.0",
"js-levenshtein": "^1.1.6",
Expand Down
10 changes: 9 additions & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,14 @@ export {
} from './walk.js';
export { getAstNodeByPointer, getLineColLocation, getCodeframe } from './format/codeframes.js';
export { formatProblems, getTotals, type OutputFormat, type Totals } from './format/format.js';
export { lint, lint as validate, lintDocument, lintFromString, lintConfig } from './lint.js';
export {
lint,
lint as validate,
lintDocument,
lintFromString,
lintConfig,
lintEntityFile,
} from './lint.js';
export {
bundle,
bundleDocument,
Expand All @@ -118,6 +125,7 @@ export { type Assertions, type Assertion } from './rules/common/assertions/index
export { logger, type LoggerInterface } from './logger.js';
export { HandledError } from './utils/error.js';
export { isBrowser } from './env.js';
export { EntityTypes, createEntityTypes } from './types/entity-yaml.js';

export type {
Oas3Definition,
Expand Down
58 changes: 58 additions & 0 deletions packages/core/src/lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,61 @@ export async function lintConfig(opts: {

return ctx.problems;
}

export async function lintEntityFile(opts: {
document: Document;
entityTypes: Record<string, NodeType>;
severity?: ProblemSeverity;
externalRefResolver?: BaseResolver;
}) {
const { document, entityTypes, severity, externalRefResolver = new BaseResolver() } = opts;

const ctx: WalkContext = {
problems: [],
specVersion: 'oas3_0', // Not used for entity validation but required by context
visitorsData: {},
};

const types = normalizeTypes(entityTypes);

const rules: (RuleInstanceConfig & {
visitor: NestedVisitObject<
unknown,
| Oas3Visitor
| Oas3Visitor[]
| Oas2Visitor
| Oas2Visitor[]
| Async2Visitor
| Async2Visitor[]
| Async3Visitor
| Async3Visitor[]
| Arazzo1Visitor
| Arazzo1Visitor[]
| Overlay1Visitor
| Overlay1Visitor[]
>;
})[] = [
{
severity: severity || 'error',
ruleId: 'entity struct',
visitor: Struct({ severity: 'error' }),
},
];

const normalizedVisitors = normalizeVisitors(rules, types);
const resolvedRefMap = await resolveDocument({
rootDocument: document,
rootType: types.EntityFileTypes,
externalRefResolver,
});

walkDocument({
document,
rootType: types.EntityFileTypes,
normalizedVisitors,
resolvedRefMap,
ctx,
});

return ctx.problems;
}
15 changes: 15 additions & 0 deletions packages/core/src/types/entity-yaml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { entityFileSchema } from '@redocly/config';
import { getNodeTypesFromJSONSchema } from './json-schema-adapter.js';

import type { JSONSchema } from 'json-schema-to-ts';
import type { NodeType } from './index.js';

export function createEntityTypes(entityFileSchema: JSONSchema) {
const entityFileSchemaTypes = getNodeTypesFromJSONSchema('entityFileSchema', entityFileSchema);

return {
EntityFileTypes: entityFileSchemaTypes.entityFileSchema,
};
}

export const EntityTypes: Record<string, NodeType> = createEntityTypes(entityFileSchema);
86 changes: 64 additions & 22 deletions packages/core/src/types/json-schema-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
}

if (schema.type instanceof Array) {
throw new Error(

Check failure on line 52 in packages/core/src/types/json-schema-adapter.ts

View workflow job for this annotation

GitHub Actions / build-and-unit

packages/cli/src/__tests__/commands/build-docs.test.ts

Error: Unexpected array schema type in entityFileSchema_summary schema. Try using oneOf instead. ❯ transformJSONSchemaToNodeType packages/core/src/types/json-schema-adapter.ts:52:11 ❯ transformJSONSchemaToNodeType packages/core/src/types/json-schema-adapter.ts:142:39 ❯ getNodeTypesFromJSONSchema packages/core/src/types/json-schema-adapter.ts:257:3 ❯ createEntityTypes packages/core/src/types/entity-yaml.ts:8:59 ❯ packages/core/src/types/entity-yaml.ts:15:54

Check failure on line 52 in packages/core/src/types/json-schema-adapter.ts

View workflow job for this annotation

GitHub Actions / build-and-unit

packages/cli/src/__tests__/spinner.test.ts

Error: Unexpected array schema type in entityFileSchema_summary schema. Try using oneOf instead. ❯ transformJSONSchemaToNodeType packages/core/src/types/json-schema-adapter.ts:52:11 ❯ transformJSONSchemaToNodeType packages/core/src/types/json-schema-adapter.ts:142:39 ❯ getNodeTypesFromJSONSchema packages/core/src/types/json-schema-adapter.ts:257:3 ❯ createEntityTypes packages/core/src/types/entity-yaml.ts:8:59 ❯ packages/core/src/types/entity-yaml.ts:15:54
`Unexpected array schema type in ${propertyName} schema. Try using oneOf instead.`
);
}
Expand All @@ -69,10 +69,13 @@
return { type: 'object' };
} else if (schema.additionalProperties === false) {
return { type: 'object', properties: {} };
} else {
// Handle case where additionalProperties is a schema
return { type: 'object' };
}
}

if (schema.allOf) {

Check failure on line 78 in packages/core/src/types/json-schema-adapter.ts

View workflow job for this annotation

GitHub Actions / build-and-unit

packages/core/src/__tests__/walk.test.ts

Error: Unexpected array schema type in entityFileSchema_summary schema. Try using oneOf instead. ❯ transformJSONSchemaToNodeType packages/core/src/types/json-schema-adapter.ts:78:7 ❯ transformJSONSchemaToNodeType packages/core/src/types/json-schema-adapter.ts:208:28 ❯ getNodeTypesFromJSONSchema packages/core/src/types/json-schema-adapter.ts:3558:3 ❯ createEntityTypes packages/core/src/types/entity-yaml.ts:13:1 ❯ packages/core/src/types/entity-yaml.ts:112:47

Check failure on line 78 in packages/core/src/types/json-schema-adapter.ts

View workflow job for this annotation

GitHub Actions / build-and-unit

packages/core/src/__tests__/resolve.test.ts

Error: Unexpected array schema type in entityFileSchema_summary schema. Try using oneOf instead. ❯ transformJSONSchemaToNodeType packages/core/src/types/json-schema-adapter.ts:78:7 ❯ transformJSONSchemaToNodeType packages/core/src/types/json-schema-adapter.ts:208:28 ❯ getNodeTypesFromJSONSchema packages/core/src/types/json-schema-adapter.ts:3558:3 ❯ createEntityTypes packages/core/src/types/entity-yaml.ts:13:1 ❯ packages/core/src/types/entity-yaml.ts:112:47

Check failure on line 78 in packages/core/src/types/json-schema-adapter.ts

View workflow job for this annotation

GitHub Actions / build-and-unit

packages/core/src/__tests__/resolve-http.test.ts

Error: Unexpected array schema type in entityFileSchema_summary schema. Try using oneOf instead. ❯ transformJSONSchemaToNodeType packages/core/src/types/json-schema-adapter.ts:78:7 ❯ transformJSONSchemaToNodeType packages/core/src/types/json-schema-adapter.ts:208:28 ❯ getNodeTypesFromJSONSchema packages/core/src/types/json-schema-adapter.ts:3558:3 ❯ createEntityTypes packages/core/src/types/entity-yaml.ts:13:1 ❯ packages/core/src/types/entity-yaml.ts:112:47

Check failure on line 78 in packages/core/src/types/json-schema-adapter.ts

View workflow job for this annotation

GitHub Actions / build-and-unit

packages/core/src/__tests__/ref-utils.test.ts

Error: Unexpected array schema type in entityFileSchema_summary schema. Try using oneOf instead. ❯ transformJSONSchemaToNodeType packages/core/src/types/json-schema-adapter.ts:78:7 ❯ transformJSONSchemaToNodeType packages/core/src/types/json-schema-adapter.ts:208:28 ❯ getNodeTypesFromJSONSchema packages/core/src/types/json-schema-adapter.ts:3558:3 ❯ createEntityTypes packages/core/src/types/entity-yaml.ts:13:1 ❯ packages/core/src/types/entity-yaml.ts:112:47

Check failure on line 78 in packages/core/src/types/json-schema-adapter.ts

View workflow job for this annotation

GitHub Actions / build-and-unit

packages/core/src/__tests__/lint.test.ts

Error: Unexpected array schema type in entityFileSchema_summary schema. Try using oneOf instead. ❯ transformJSONSchemaToNodeType packages/core/src/types/json-schema-adapter.ts:78:7 ❯ transformJSONSchemaToNodeType packages/core/src/types/json-schema-adapter.ts:208:28 ❯ getNodeTypesFromJSONSchema packages/core/src/types/json-schema-adapter.ts:3558:3 ❯ createEntityTypes packages/core/src/types/entity-yaml.ts:13:1 ❯ packages/core/src/types/entity-yaml.ts:112:47

Check failure on line 78 in packages/core/src/types/json-schema-adapter.ts

View workflow job for this annotation

GitHub Actions / build-and-unit

packages/core/src/__tests__/bundle.test.ts

Error: Unexpected array schema type in entityFileSchema_summary schema. Try using oneOf instead. ❯ transformJSONSchemaToNodeType packages/core/src/types/json-schema-adapter.ts:78:7 ❯ transformJSONSchemaToNodeType packages/core/src/types/json-schema-adapter.ts:208:28 ❯ getNodeTypesFromJSONSchema packages/core/src/types/json-schema-adapter.ts:3558:3 ❯ createEntityTypes packages/core/src/types/entity-yaml.ts:13:1 ❯ packages/core/src/types/entity-yaml.ts:112:47
throw new Error(`Unexpected allOf in ${propertyName}.`);
}

Expand All @@ -97,31 +100,70 @@
if (!discriminatedPropertyName) {
throw new Error(`Unexpected discriminator without a propertyName in ${propertyName}.`);
}
const oneOfs = schema.oneOf.map((option, i) => {
if (typeof option === 'boolean') {
throw new Error(
`Unexpected boolean schema in ${propertyName} at position ${i} in oneOf.`
);
}
const discriminatedProperty = option?.properties?.[discriminatedPropertyName];
if (!discriminatedProperty || typeof discriminatedProperty === 'boolean') {
throw new Error(
`Unexpected property '${discriminatedProperty}' schema in ${propertyName} at position ${i} in oneOf.`
);
}
const name = discriminatedProperty.const as string;
return transformJSONSchemaToNodeType(name, option, ctx);
});

return (value: unknown, key: string) => {
if (isPlainObject(value)) {
const discriminatedTypeName = value[discriminatedPropertyName];
if (typeof discriminatedTypeName === 'string' && ctx[discriminatedTypeName]) {
return discriminatedTypeName;

// Create a NodeType that represents the discriminated union
// Extract common properties from all oneOf options
const commonProperties: Record<string, PropType | ResolveTypeFn> = {};

// Find properties that exist in all oneOf options
if (schema.oneOf && schema.oneOf.length > 0) {
const firstOption = schema.oneOf[0] as any;
if (firstOption && firstOption.properties) {
for (const [propName, propSchema] of Object.entries(firstOption.properties)) {
// Check if this property exists in all oneOf options
const existsInAll = schema.oneOf.every(
(option: any) => option && option.properties && option.properties[propName]
);

if (existsInAll) {
// Special handling for the discriminator property - it should resolve to specific types
if (propName === discriminatedPropertyName) {
commonProperties[propName] = (value: any) => {
if (
isPlainObject(value) &&
typeof value[discriminatedPropertyName] === 'string'
) {
const typeName = value[discriminatedPropertyName];
if (ctx[typeName]) {
return typeName;
}
}
// Fallback to the property schema
const fallbackType = transformJSONSchemaToNodeType(
`${propertyName}.${propName}`,
propSchema as JSONSchema,
ctx
);
return typeof fallbackType === 'string' ? fallbackType : (propSchema as PropType);
};
} else {
// For other common properties, we need to process them inline
// rather than creating separate type references to avoid "Unknown type" errors
const processedType = transformJSONSchemaToNodeType(
`${propertyName}_${propName}`, // Use a unique name that won't conflict
propSchema as JSONSchema,
ctx
);

// If it returned a type name, we need to use that reference
// If it returned an inline type, use that directly
if (typeof processedType === 'string') {
commonProperties[propName] = processedType;
} else {
// For inline types (like arrays, primitives), use them directly
commonProperties[propName] = processedType;
}
}
}
}
}
return findOneOf(schema.oneOf as JSONSchema[], oneOfs)(value, key);
}

ctx[propertyName] = {
properties: commonProperties,
};

return propertyName;
} else {
const oneOfs = schema.oneOf.map((option, i) =>
transformJSONSchemaToNodeType(propertyName + '_' + i, option, ctx)
Expand Down
Loading