Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check type name that MUST use keys that match the regular expression: ^[a-zA-Z0-9.-_]+$. #5006

Merged
merged 27 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
186930b
errors on invalid parameter keys
Nov 7, 2024
e9a1e97
update change log
Nov 7, 2024
31aa2c8
up
Nov 7, 2024
a2e75fe
revert
Nov 7, 2024
bc15a4c
up
Nov 7, 2024
cee12e4
move to openapi3
Nov 7, 2024
1f6e75e
update cases
Nov 7, 2024
abdea8a
Merge branch 'main' into checkAvailableTypeName
skywing918 Nov 8, 2024
f0c3b03
update
Nov 11, 2024
244ebe8
Merge branch 'main' into checkAvailableTypeName
skywing918 Nov 11, 2024
f3cfdf7
Merge branch 'checkAvailableTypeName' of https://github.com/skywing91…
Nov 11, 2024
257ca8c
Merge branch 'main' into checkAvailableTypeName
skywing918 Nov 12, 2024
ea7f36e
update
Nov 12, 2024
0ed014c
update
Nov 13, 2024
b903868
Merge branch 'main' into checkAvailableTypeName
skywing918 Nov 13, 2024
3e80701
disable error
Nov 13, 2024
c1453aa
Merge branch 'checkAvailableTypeName' of https://github.com/skywing91…
Nov 13, 2024
249ef2f
up
Nov 13, 2024
e3d395d
Merge branch 'main' into checkAvailableTypeName
skywing918 Nov 13, 2024
ad92b11
Merge branch 'main' into checkAvailableTypeName
skywing918 Nov 13, 2024
6ab9112
Merge branch 'main' into checkAvailableTypeName
skywing918 Nov 14, 2024
748f888
Update packages/openapi3/src/lib.ts
skywing918 Nov 14, 2024
0e57a07
Merge branch 'main' into checkAvailableTypeName
skywing918 Nov 14, 2024
d7184cf
Merge branch 'main' into checkAvailableTypeName
skywing918 Nov 14, 2024
3224415
Merge branch 'main' into checkAvailableTypeName
skywing918 Nov 14, 2024
c7f9540
Merge branch 'main' into checkAvailableTypeName
markcowl Nov 14, 2024
e973796
Merge branch 'main' into checkAvailableTypeName
skywing918 Nov 15, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
changeKind: fix
packages:
- "@typespec/openapi3"
---

Illegal characters in component keys
6 changes: 6 additions & 0 deletions packages/openapi3/src/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,12 @@ export const libDef = {
default: paramMessage`XML \`@unwrapped\` can only used on array properties or primitive ones in the OpenAPI 3 emitter, Property '${"name"}' will be ignored.`,
},
},
"invalid-component-fixed-field-key": {
severity: "error",
messages: {
default: paramMessage`Invalid key '${"value"}' used in fixed fields of Component object. Only keys matching the regular expression to ^[a-zA-Z0-9.-_]+$ are allowed.`,
skywing918 marked this conversation as resolved.
Show resolved Hide resolved
},
},
},
emitter: {
options: EmitterOptionsSchema as JSONSchemaType<OpenAPI3EmitterOptions>,
Expand Down
18 changes: 18 additions & 0 deletions packages/openapi3/src/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1540,6 +1540,21 @@ function createOAPIEmitter(
}
}

function validateComponentFixedFieldKey(type: Type, name: string) {
const pattern = /^[a-zA-Z0-9\\.\-\\_]+$/;
skywing918 marked this conversation as resolved.
Show resolved Hide resolved
if (!pattern.test(name)) {
program.reportDiagnostic(
createDiagnostic({
code: "invalid-component-fixed-field-key",
format: {
value: name,
},
target: type,
}),
);
}
}

function emitParameters() {
for (const [property, param] of params) {
const key = getParameterKey(
Expand All @@ -1549,6 +1564,7 @@ function createOAPIEmitter(
root.components!.parameters!,
typeNameOptions,
);
validateComponentFixedFieldKey(property, key);

root.components!.parameters![key] = { ...param };
for (const key of Object.keys(param)) {
Expand All @@ -1573,6 +1589,8 @@ function createOAPIEmitter(
const schemas = root.components!.schemas!;
const declarations = files[0].globalScope.declarations;
for (const declaration of declarations) {
validateComponentFixedFieldKey(serviceNamespace, declaration.name);

schemas[declaration.name] = declaration.value as any;
}
}
Expand Down
54 changes: 54 additions & 0 deletions packages/openapi3/test/models.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,60 @@ describe("openapi3: models", () => {
]);
});

describe("errors on invalid model names", () => {
const symbols = [
"!",
"@",
"#",
"$",
"%",
"^",
"&",
"*",
"(",
")",
"=",
"+",
"[",
"]",
"{",
"}",
"|",
";",
":",
"<",
">",
",",
"/",
"?",
"~",
];
it.each(symbols)("%sName01", async (model) => {
const diagnostics = await diagnoseOpenApiFor(
`
model \`${model}Name01\` { name: string; }
`,
);
expectDiagnostics(diagnostics, [
{
code: "@typespec/openapi3/invalid-component-fixed-field-key",
},
]);
});
});

describe("no errors on valid model names", () => {
const symbols = [".", "-", "_"];
it.each(symbols)("%sName01", async (model) => {
const diagnostics = await diagnoseOpenApiFor(
`
model \`${model}Name01\` { name: string; }
`,
);
expectDiagnostics(diagnostics, []);
});
});

it("doesn't define anonymous models", async () => {
const res = await oapiForModel("{ x: int32 }", "");

Expand Down
41 changes: 23 additions & 18 deletions packages/openapi3/test/parameters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,27 +301,32 @@ describe("query parameters", () => {
]);
});

it("encodes parameter keys in references", async () => {
const oapi = await openApiFor(`
model Pet extends Pet$Id {
name: string;
it("errors on invalid parameter keys", async () => {
const diagnostics = await diagnoseOpenApiFor(
`
model Pet {
@query()
$take?: int32;

@query()
$top?: int32;
}
model Pet$Id {
@path
petId: string;
@service
namespace Endpoints {
op list(...Pet): void;
}

@route("/Pets")
@get()
op get(... Pet$Id): Pet;
`);

ok(oapi.paths["/Pets/{petId}"].get);
strictEqual(
oapi.paths["/Pets/{petId}"].get.parameters[0]["$ref"],
"#/components/parameters/Pet%24Id",
`,
{ "omit-unreachable-types": true },
);
strictEqual(oapi.components.parameters["Pet$Id"].name, "petId");

expectDiagnostics(diagnostics, [
{
code: "@typespec/openapi3/invalid-component-fixed-field-key",
},
{
code: "@typespec/openapi3/invalid-component-fixed-field-key",
},
]);
});

it("inline spread of parameters from anonymous model", async () => {
Expand Down
Loading