Skip to content

Commit

Permalink
Fix: OData V2 Edm.Binary is base64-encoded in JSON payloads (#305)
Browse files Browse the repository at this point in the history
* OData V2 Edm.Binary is base64-encoded -> `format: byte` in OpenAPI 3.0.x
* Bump version to 0.26.1
  • Loading branch information
ralfhandl authored Jul 9, 2024
1 parent d00aabe commit 603285a
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 84 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Changelog

## 0.26.0 - 2024-01-12
## 0.26.1 - 2024-07-09

### Fixed

- OData V2 type `Edm.Binary` is base64-encoded, not base64url

## 0.26.0 - 2024-07-04

### Added

Expand Down
12 changes: 6 additions & 6 deletions examples/Northwind-V3.openapi3.json
Original file line number Diff line number Diff line change
Expand Up @@ -10186,7 +10186,7 @@
},
"Picture": {
"type": "string",
"format": "base64url",
"format": "byte",
"nullable": true
},
"Products": {
Expand Down Expand Up @@ -10218,7 +10218,7 @@
},
"Picture": {
"type": "string",
"format": "base64url",
"format": "byte",
"nullable": true
}
},
Expand All @@ -10240,7 +10240,7 @@
},
"Picture": {
"type": "string",
"format": "base64url",
"format": "byte",
"nullable": true
}
}
Expand Down Expand Up @@ -10739,7 +10739,7 @@
},
"Photo": {
"type": "string",
"format": "base64url",
"format": "byte",
"nullable": true
},
"Notes": {
Expand Down Expand Up @@ -10868,7 +10868,7 @@
},
"Photo": {
"type": "string",
"format": "base64url",
"format": "byte",
"nullable": true
},
"Notes": {
Expand Down Expand Up @@ -10961,7 +10961,7 @@
},
"Photo": {
"type": "string",
"format": "base64url",
"format": "byte",
"nullable": true
},
"Notes": {
Expand Down
10 changes: 8 additions & 2 deletions lib/csdl2openapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -2479,8 +2479,14 @@ module.exports.csdl2openapi = function (
break;
case "Edm.Binary":
s = oas31
? { type: "string", contentEncoding: "base64url" }
: { type: "string", format: "base64url" };
? {
type: "string",
contentEncoding: csdl.$Version < "4.0" ? "base64" : "base64url",
}
: {
type: "string",
format: csdl.$Version < "4.0" ? "byte" : "base64url",
};
if (element.$MaxLength)
s.maxLength = Math.ceil((4 * element.$MaxLength) / 3);
break;
Expand Down
4 changes: 2 additions & 2 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 package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "odata-openapi",
"version": "0.26.0",
"version": "0.26.1",
"description": "Convert OData CSDL XML or CSDL JSON to OpenAPI",
"homepage": "https://github.com/oasis-tcs/odata-openapi/blob/master/lib/README.md",
"bugs": "https://github.com/oasis-tcs/odata-openapi/issues",
Expand Down
133 changes: 132 additions & 1 deletion test/csdl2openapi.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const assert = require("assert");
// (external) annotations on actions, functions, parameters, return types
// control mapping of reference URLs

const { paths, operations } = require("./utilities");
const { paths, operations, schemas } = require("./utilities");

const { csdl2openapi } = require("odata-openapi");

Expand Down Expand Up @@ -1709,6 +1709,137 @@ describe("Edge cases", function () {
);
});

it("OData V2 Edm.Binary, Edm.DateTime, and Edm.Time", function () {
const csdl = {
$Version: "2.0",
$EntityContainer: "this.Container",
this: {
Container: {
fi: {
$Function: "this.f",
},
},
f: [
{
$Kind: "Function",
$Parameter: [],
$ReturnType: { $Type: "this.ct" },
},
],
ct: {
$Kind: "ComplexType",
bin: { $Type: "Edm.Binary" },
date: { $Type: "Edm.DateTime" },
time: { $Type: "Edm.Time" },
timeWithMilliSeconds: { $Type: "Edm.Time", $Precision: 3 },
},
},
};
const expected = {
paths: {
"/$batch": { post: {} },
"/fi": { get: {} },
},
components: {
schemas: {
"this.ct": {
type: "object",
title: "ct",
properties: {
bin: { type: "string", format: "byte" },
date: {
type: "string",
example: "/Date(1492098664000)/",
},
time: {
type: "string",
example: "PT15H51M04S",
},
timeWithMilliSeconds: {
type: "string",
example: "PT15H51M04.000S",
},
},
},
},
},
};
const messages = [];

const actual = csdl2openapi(csdl, { messages });
assert.deepStrictEqual(paths(actual), paths(expected), "Paths");
assert.deepStrictEqual(
operations(actual),
operations(expected),
"Operations",
);
assert.deepStrictEqual(schemas(actual), schemas(expected), "Schemas");
assert.deepStrictEqual(
actual.components.schemas["this.ct"],
expected.components.schemas["this.ct"],
"this.ct",
);
assert.deepStrictEqual(messages, [], "messages");
});

it("OData V2 Edm.Binary in OpenAPI 3.1.0", function () {
const csdl = {
$Version: "2.0",
$EntityContainer: "this.Container",
this: {
Container: {
fi: {
$Function: "this.f",
},
},
f: [
{
$Kind: "Function",
$Parameter: [],
$ReturnType: { $Type: "this.ct" },
},
],
ct: {
$Kind: "ComplexType",
bin: { $Type: "Edm.Binary" },
},
},
};
const expected = {
paths: {
"/$batch": { post: {} },
"/fi": { get: {} },
},
components: {
schemas: {
"this.ct": {
type: "object",
title: "ct",
properties: {
bin: { type: "string", contentEncoding: "base64" },
},
},
},
},
};
const messages = [];

const actual = csdl2openapi(csdl, { messages, openapiVersion: "3.1.0" });
assert.deepStrictEqual(paths(actual), paths(expected), "Paths");
assert.deepStrictEqual(
operations(actual),
operations(expected),
"Operations",
);
assert.deepStrictEqual(schemas(actual), schemas(expected), "Schemas");
assert.deepStrictEqual(
actual.components.schemas["this.ct"],
expected.components.schemas["this.ct"],
"this.ct",
);
assert.deepStrictEqual(messages, [], "messages");
});

it("OpenAPI 3.1.0", function () {
const csdl = {
$Reference: {
Expand Down
71 changes: 0 additions & 71 deletions test/funnyInput.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,75 +177,4 @@ describe("Funny input", function () {
"messages",
);
});

it("OData V2 Edm.DateTime and Edm.Time", function () {
const csdl = {
$Version: "2.0",
$EntityContainer: "this.Container",
this: {
Container: {
fi: {
$Function: "this.f",
},
},
f: [
{
$Kind: "Function",
$Parameter: [],
$ReturnType: { $Type: "this.ct" },
},
],
ct: {
$Kind: "ComplexType",
date: { $Type: "Edm.DateTime" },
time: { $Type: "Edm.Time" },
timeWithMilliSeconds: { $Type: "Edm.Time", $Precision: 3 },
},
},
};
const expected = {
paths: {
"/$batch": { post: {} },
"/fi": { get: {} },
},
components: {
schemas: {
"this.ct": {
type: "object",
title: "ct",
properties: {
date: {
type: "string",
example: "/Date(1492098664000)/",
},
time: {
type: "string",
example: "PT15H51M04S",
},
timeWithMilliSeconds: {
type: "string",
example: "PT15H51M04.000S",
},
},
},
},
},
};
const messages = [];

const actual = csdl2openapi(csdl, { messages });
assert.deepStrictEqual(paths(actual), paths(expected), "Paths");
assert.deepStrictEqual(
operations(actual),
operations(expected),
"Operations",
);
assert.deepStrictEqual(schemas(actual), schemas(expected), "Schemas");
assert.deepStrictEqual(
actual.components.schemas["this.ct"],
expected.components.schemas["this.ct"],
"this.ct",
);
assert.deepStrictEqual(messages, [], "messages");
});
});

0 comments on commit 603285a

Please sign in to comment.