Skip to content

Commit

Permalink
Documentation of migration structures
Browse files Browse the repository at this point in the history
  • Loading branch information
samchon committed Jun 27, 2024
1 parent 4598a53 commit 543f95d
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 19 deletions.
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ OpenAPI definitions and converters (for [typia](https://github.com/samchon/typia
2. [OpenAPI v3.0](https://github.com/samchon/openapi/blob/master/src/OpenApiV3.ts)
3. [OpenAPI v3.1](https://github.com/samchon/openapi/blob/master/src/OpenApiV3_1.ts)

Also, `@samchon/openapi` provides emended OpenAPI v3.1 definition and its converter/inverter from above versions for convenient development. The keyword "emended" means that [`OpenApi`](https://github.com/samchon/openapi/blob/master/src/OpenApi.ts) is not a direct OpenAPI v3.1 specification (OpenApiV3_1), but a little bit shrinked to remove ambiguous and duplicated expressions of OpenAPI v3.1 for the convenience of typia and nestia
Also, `@samchon/openapi` provides emended OpenAPI v3.1 definition and its converter/inverter from above versions for convenient development. The keyword "emended" means that [`OpenApi`](https://github.com/samchon/openapi/blob/master/src/OpenApi.ts) is not a direct OpenAPI v3.1 specification ([`OpenApiV3_1`](https://github.com/samchon/openapi/blob/master/src/OpenApiV3_1.ts)), but a little bit shrinked to remove ambiguous and duplicated expressions of OpenAPI v3.1 for the convenience of `typia` and `nestia`.

For example, when representing nullable type, OpenAPI v3.1 supports three ways. In that case, OpenApi remains only the third way, so that makes `typia` and `nestia` (especially [`@nestia/editor`](https://nestia.io/docs/editor/)) to be simple and easy to implement.

Expand All @@ -37,6 +37,9 @@ Here is the entire list of differences between OpenAPI v3.1 and emended OpenApi.
- Merge `OpenApiV3_1.IJsonSchema.IRecursiveReference` to `OpenApi.IJsonSchema.IReference`
- Merge `OpenApiV3_1.IJsonSchema.IAllOf` to `OpenApi.IJsonSchema.IObject`

Additionally, `@samchon/openapi` provides [`IMigrateDocument`](https://github.com/samchon/openapi/blob/master/src/IMigrateDocument.ts) for OpenAPI generators.




## How to use
Expand Down Expand Up @@ -71,10 +74,8 @@ const v3: OpenApiV3 = OpenApi.downgrade(output, "3.0");
OpenApi.downgrade(OpenApi.convert(v2), "3.0");
OpenApi.downgrade(OpenApi.convert(v3), "2.0");

// also supports openapi generator libraries
const migrate: IMigrateDocument = OpenApi.migrate(
OpenApi.convert(input),
);
// also helps openapi generator libraries
const migrate: IMigrateDocument = OpenApi.migrate(output);
```


Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@samchon/openapi",
"version": "0.2.1",
"version": "0.2.2",
"description": "OpenAPI definitions and converters for 'typia' and 'nestia'.",
"main": "./lib/index.js",
"typings": "./lib/index.d.ts",
Expand Down Expand Up @@ -33,10 +33,10 @@
"@types/node": "^20.12.7",
"prettier": "^3.2.5",
"rimraf": "^5.0.5",
"ts-patch": "^3.1.2",
"typescript": "5.4.5",
"ts-patch": "^3.2.1",
"typescript": "^5.5.2",
"typescript-transform-paths": "^3.4.7",
"typia": "^6.2.2"
"typia": "^6.3.1"
},
"files": [
"lib",
Expand Down
42 changes: 42 additions & 0 deletions src/IMigrateDocument.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,57 @@
import { IMigrateRoute } from "./IMigrateRoute";
import { OpenApi } from "./OpenApi";

/**
* Document of migration.
*
* The `IMigrateDocument` interface is a document of migration from
* {@link OpenAPI.IDocument OpenAPI document} to RPC (Remote Procedure Call)
* functions; {@link IMigrateRoute}.
*
* As the `IMigrateDocument` and {@link IMigrateRoute} have a lot of special
* stories, when you're developing OpenAPI generator library, please read
* their descriptions carefully including the description of properties.
*
* @author Jeongho Nam - https://github.com/samchon
*/
export interface IMigrateDocument {
/**
* List of routes for migration.
*/
routes: IMigrateRoute[];

/**
* List of errors occurred during the migration.
*/
errors: IMigrateDocument.IError[];
}
export namespace IMigrateDocument {
/**
* Error of migration in the operation level.
*/
export interface IError {
/**
* Target operation causing the error.
*/
operation: () => OpenApi.IOperation;

/**
* Method of the operation.
*
* If the {@link OpenApi.IOperation.method} is not one of below type
* values, the operation would be ignored in the migration process for
* the RPC (Remote Procedure Call) function.
*/
method: "head" | "get" | "post" | "put" | "patch" | "delete";

/**
* Original path from the OpenAPI document.
*/
path: string;

/**
* List of error messages (reasons).
*/
messages: string[];
}
}
168 changes: 161 additions & 7 deletions src/IMigrateRoute.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,171 @@
import { OpenApi } from "./OpenApi";

/**
* Route information for migration.
*
* The `IMigrateRoute` is a structure representing a route information for
* OpenAPI generated RPC (Remote Procedure Call) function composed from the
* {@link OpenApi.IOperation OpenAPI operation}.
*
* As the `IMigrateRoute` has a lot of speical stories, when you're developing
* OpenAPI generator library, please read its description carefully including
* the description of its properties.
*
* @author Jeongho Nam - https://github.com/samchon
*/
export interface IMigrateRoute {
/**
* Method of the route.
*
* If the {@link OpenApi.IOperation.method} is not one of below type
* values, the operation would be ignored in the migration process for
* the RPC (Remote Procedure Call) function.
*/
method: "head" | "get" | "post" | "put" | "patch" | "delete";

/**
* Original path from the OpenAPI document.
*/
path: string;

/**
* Emended path for OpenAPI generator libraries.
*
* The difference between {@link path} is:
*
* 1. Path parameters are replaced with `:param` format.
* 2. Empty sub-paths are removed.
* 3. Do not starts with `/`.
*/
emendedPath: string;
accessor: string[]; // function accessor
parameters: IMigrateRoute.IParameter[]; // path parameters
headers: IMigrateRoute.IHeaders | null; // as an object
query: IMigrateRoute.IQuery | null; // as an object
body: IMigrateRoute.IBody | null; // request body
success: IMigrateRoute.IBody | null; // 200 or 201 status case
exceptions: Record<string, IMigrateRoute.IException>; // other status cases

/**
* Accessor for the route.
*
* The `accessor` is a list of string values that are representing how to
* access to the OpenAPI generated RPC (Remote Procedure Call) function
* through namespace(s).
*
* The `accessor` is composed with the following rules. At first, namespaces
* are composed by static directory names in the {@link path}. Parametric
* symbols represented by `:param` or `{param}` cannot be a part of the
* namespace.
*
* Instead, they would be a part of the function name. The function
* name is composed with the {@link method HTTP method} and parametric symbols
* like `getByParam` or `postByParam`. If there are multiple path parameters,
* they would be concatenated by `And` like `getByParam1AndParam2`.
*
* For refefence, if the {@link operation}'s {@link method} is `delete`, the
* function name would be replaced to `erase` instead of `delete`. It is
* the reason why the `delete` is a reserved keyword in many programming
* languages.
*
* - Exxample 1
* - path: `POST /shopping/sellers/sales`
* - accessor: `shopping.sellers.sales.post`
* - Example 2
* - endpoint: `GET /shoppings/sellers/sales/:saleId/reviews/:reviewId/comments/:id
* - accessor: `shoppings.sellers.sales.reviews.getBySaleIdAndReviewIdAndCommentId`
*/
accessor: string[];

/**
* List of path parameters.
*/
parameters: IMigrateRoute.IParameter[];

/**
* Metadata of headers.
*
* The `headers` property is a metadata of HTTP request headers for RPC function,
* including the parameter variable name and schema.
*
* Also, its {@link IMigrateRoute.IHeaders.schema} is always object or reference
* to object. Even though the original {@link OpenApi.IOperation OpenAPI operation}'s
* headers are separated to atomic typed properties, the `headers` property forcibly
* combines them into a single object type.
*
* For reference, if the `headers` property has been converted to an object type
* forcibly, its property {@link IMigrateRoute.IHeaders.name name} and
* {@link IMigrateRoute.IHeaders.key key} are always "headers".
*/
headers: IMigrateRoute.IHeaders | null;

/**
* Metadata of query values.
*
* The `query` property is a metadata of HTTP request query values for RPC function,
* including the parameter variable name and schema.
*
* Also, its {@link IMigrateRoute.IQuery.schema} is always object or reference
* to object. Even though the original {@link OpenApi.IOperation OpenAPI operation}'s
* query parameters are separated to atomic typed properties, the `query` property
* forcibly combines them into a single object type.
*
* For reference, if the `query` property has been converted to an object type
* forcibly, its property {@link IMigrateRoute.IQuery.name name} and
* {@link IMigrateRoute.IQuery.key key} are always "headers".
*/
query: IMigrateRoute.IQuery | null;

/**
* Metadata of request body.
*
* The `body` property is a metadata of HTTP request body for RPC function,
* including the parameter variable name, content type, and schema.
*
* If the `body` property is `null`, it means the operation does not require
* the request body data.
*/
body: IMigrateRoute.IBody | null;

/**
* Metadata of response body for success case.
*
* The `success` property is a metadata of HTTP response body for RPC function,
* including content type, and schema when status code is `200` or `201`.
*
* If the `success` property is `null`, it means the operation does not have
* the response body data. In other words, the RPC function would return `void`.
*/
success: IMigrateRoute.IBody | null;

/**
* Metadata of response body for exceptional status cases.
*
* The `exceptions` property is a metadata of HTTP response body for RPC
* function, including content type, and schema when status code is not `200`
* or `201`.
*
* The key of the `exceptions` property is the status code. It may be a
* stringified number, but sometimes it could be a string like "default",
* because the OpenAPI document allows the status code to be a string.
*/
exceptions: Record<string, IMigrateRoute.IException>;

/**
* Description comment for the route function.
*
* The `comment` is a function returning description comment for the
* RPC function of OpenAPI generated. The comment is composed with the
* following rules:
*
* 1. Starts from the {@link OpenApi.IOperation.summary} paragraph.
* 2. The next paragraphs are filled with {@link OpenApi.IOperation.description}.
* 3. Parameter descriptions are added with `@param` tag.
* 4. Security requirements are added with `@security` tag.
* 5. Tag names are added with `@tag` tag.
* 6. If {@link OpenApi.IOperation.deprecated}, `@deprecated` tag is added.
*/
comment: () => string;

/**
* Original operation from the OpenAPI document.
*
* The `operation` is a function returning the original
* {@link OpenApi.IOperation} from the {@link OpenAPI} document.
*/
operation: () => OpenApi.IOperation;
}
export namespace IMigrateRoute {
Expand Down
4 changes: 2 additions & 2 deletions src/internal/MigrateConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { IMigrateRoute } from "../IMigrateRoute";
import { IMigrateDocument } from "../IMigrateDocument";
import { OpenApi } from "../OpenApi";
import { StringUtil } from "../utils/StringUtil";
import { MigrateOperationConverter } from "./MigrateOperationConverter";
import { MigrateRouteConverter } from "./MigrateRouteConverter";
import { MigrateRouteAccessor } from "./MigrateRouteAccessor";

export namespace MigrateConverter {
Expand All @@ -18,7 +18,7 @@ export namespace MigrateConverter {
.map((method) => {
const operation: OpenApi.IOperation = collection[method]!;
const migrated: IMigrateRoute | string[] =
MigrateOperationConverter.convert({
MigrateRouteConverter.convert({
document,
method,
path,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Escaper } from "../utils/Escaper";
import { StringUtil } from "../utils/StringUtil";
import { OpenApiTypeChecker } from "./OpenApiTypeChecker";

export namespace MigrateOperationConverter {
export namespace MigrateRouteConverter {
export interface IProps {
document: OpenApi.IDocument;
method: "head" | "get" | "post" | "put" | "patch" | "delete";
Expand Down

0 comments on commit 543f95d

Please sign in to comment.