Skip to content

Commit

Permalink
Add item type for array types and tags for endpoints to overwrite wha…
Browse files Browse the repository at this point in the history
…tever module is (#7)

Issue: none
Reviewer: wyattmufson
  • Loading branch information
RandolfTjandra authored Sep 6, 2024
1 parent 98f2a71 commit 8de512a
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 32 deletions.
2 changes: 1 addition & 1 deletion __tests__/api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ afterAll(async () => {
describe('Using rio.get, rio.put, rio.post, rio.patch, and rio.delete', () => {
test('Checking endpoints', async () => {
const { routes } = rio.utils.getEndpoints(app, rio.paths);
expect(routes.length).toBe(17);
expect(routes.length).toBe(29);
});

test('Get sum', async () => {
Expand Down
3 changes: 2 additions & 1 deletion src/api/argument.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
class Argument {
constructor(name, type, required = false, description = null, exampleValue = null) {
constructor(name, type, required = false, description = null, exampleValue = null, itemType = undefined) {
this.name = name;
this.type = type;
this.required = required;
this.description = description;
this.exampleValue = exampleValue || type.example;
this.itemType = itemType;
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/api/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const rioExampleResultOfEndpoint = {};
const rioStatusOfEndpoint = {};
const rioAvailabilityOfEndpoint = {};
const rioIgnoreGlobalsForEndpoint = {};
const rioTagsForEndpoint = {};

function invalidType(providedArg, res) {
const result = JSON.stringify({ error: `Argument ${providedArg.name} was not of the specified type ${providedArg.type.name}` });
Expand Down Expand Up @@ -88,7 +89,7 @@ function handleListener(handler, method, endpoint, callback) {
}
}

function addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, method, status, availability, routerName = '') {
function addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, method, status, availability, routerName = '', tags = []) {
const key = `${method}${routerName}${endpoint}`;
rioArgsForEndpoint[key] = args;
rioTypeOfEndpoint[key] = method;
Expand All @@ -97,6 +98,7 @@ function addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, descripti
rioStatusOfEndpoint[key] = status;
rioAvailabilityOfEndpoint[key] = availability;
rioIgnoreGlobalsForEndpoint[key] = ignoreGlobals;
rioTagsForEndpoint[key] = tags;

let handler = rio.app;

Expand Down Expand Up @@ -130,4 +132,5 @@ module.exports = {
rioStatusOfEndpoint,
rioAvailabilityOfEndpoint,
rioIgnoreGlobalsForEndpoint,
rioTagsForEndpoint,
};
47 changes: 24 additions & 23 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const {
rioStatusOfEndpoint,
rioAvailabilityOfEndpoint,
rioIgnoreGlobalsForEndpoint,
rioTagsForEndpoint,
} = http;

const rio = {
Expand All @@ -38,44 +39,44 @@ rio.router.init = (expressRouter, routerName) => {
rio.routers[routerName] = expressRouter;
};

rio.get = (endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'GET', status, availability);
rio.get = (endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false, tags = []) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'GET', status, availability, tags);
};

rio.post = (endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'POST', status, availability);
rio.post = (endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false, tags = []) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'POST', status, availability, tags);
};

rio.put = (endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'PUT', status, availability);
rio.put = (endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false, tags = []) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'PUT', status, availability, tags);
};

rio.patch = (endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'PATCH', status, availability);
rio.patch = (endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false, tags = []) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'PATCH', status, availability, tags);
};

rio.delete = (endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'DELETE', status, availability);
rio.delete = (endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false, tags = []) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'DELETE', status, availability, tags);
};

rio.router.get = (routerName, endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'GET', status, availability, routerName);
rio.router.get = (routerName, endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false, tags = []) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'GET', status, availability, routerName, tags);
};

rio.router.post = (routerName, endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'POST', status, availability, routerName);
rio.router.post = (routerName, endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false, tags = []) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'POST', status, availability, routerName, tags);
};

rio.router.put = (routerName, endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'PUT', status, availability, routerName);
rio.router.put = (routerName, endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false, tags = []) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'PUT', status, availability, routerName, tags);
};

rio.router.patch = (routerName, endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'PATCH', status, availability, routerName);
rio.router.patch = (routerName, endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false, tags = []) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'PATCH', status, availability, routerName, tags);
};

rio.router.delete = (routerName, endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'DELETE', status, availability, routerName);
rio.router.delete = (routerName, endpoint, callback, args = [], description = null, exampleResult = null, status = Status.live, availability = Availability.public, ignoreGlobals = false, tags = []) => {
addHTTPListener(rio, endpoint, ignoreGlobals, callback, args, description, exampleResult, 'DELETE', status, availability, routerName, tags);
};

rio.writeREADME = (path, isPublic = true) => {
Expand All @@ -91,7 +92,7 @@ rio.oasGenerate = (path, isPublic = true) => {
if (pathToUse == null) {
pathToUse = process.cwd();
}
utils.oasGenerate(pathToUse, isPublic, rio.paths, rio.app, rio.appName, rio.globalArgs, rioArgsForEndpoint, rioTypeOfEndpoint, rioDescriptionOfEndpoint, rioExampleResultOfEndpoint, rioStatusOfEndpoint, rioAvailabilityOfEndpoint, rioIgnoreGlobalsForEndpoint);
utils.oasGenerate(pathToUse, isPublic, rio.paths, rio.app, rio.appName, rio.globalArgs, rioArgsForEndpoint, rioTypeOfEndpoint, rioDescriptionOfEndpoint, rioExampleResultOfEndpoint, rioStatusOfEndpoint, rioAvailabilityOfEndpoint, rioIgnoreGlobalsForEndpoint, rioTagsForEndpoint);
};

rio.init = (app, name = null, globalArgs = []) => {
Expand All @@ -116,14 +117,14 @@ rio.RequiredString = (name, description = null, exampleValue = null) => new rio.
rio.RequiredFloat = (name, description = null, exampleValue = null) => new rio.Argument(name, rio.ArgumentType.Float, true, description, exampleValue);
rio.RequiredBoolean = (name, description = null, exampleValue = null) => new rio.Argument(name, rio.ArgumentType.Boolean, true, description, exampleValue);
rio.RequiredMap = (name, description = null, exampleValue = null) => new rio.Argument(name, rio.ArgumentType.Map, true, description, exampleValue);
rio.RequiredArray = (name, description = null, exampleValue = null) => new rio.Argument(name, rio.ArgumentType.Array, true, description, exampleValue);
rio.RequiredArray = (name, description = null, exampleValue = null, itemType = undefined) => new rio.Argument(name, rio.ArgumentType.Array, true, description, exampleValue, itemType);

rio.OptionalInteger = (name, description = null, exampleValue = null) => new rio.Argument(name, rio.ArgumentType.Integer, false, description, exampleValue);
rio.OptionalString = (name, description = null, exampleValue = null) => new rio.Argument(name, rio.ArgumentType.String, false, description, exampleValue);
rio.OptionalFloat = (name, description = null, exampleValue = null) => new rio.Argument(name, rio.ArgumentType.Float, false, description, exampleValue);
rio.OptionalBoolean = (name, description = null, exampleValue = null) => new rio.Argument(name, rio.ArgumentType.Boolean, false, description, exampleValue);
rio.OptionalMap = (name, description = null, exampleValue = null) => new rio.Argument(name, rio.ArgumentType.Map, false, description, exampleValue);
rio.OptionalArray = (name, description = null, exampleValue = null) => new rio.Argument(name, rio.ArgumentType.Array, false, description, exampleValue);
rio.OptionalArray = (name, description = null, exampleValue = null, itemType = undefined) => new rio.Argument(name, rio.ArgumentType.Array, false, description, exampleValue, itemType);

rio.rInt = rio.RequiredInteger;
rio.rStr = rio.RequiredString;
Expand Down
88 changes: 82 additions & 6 deletions src/utils/oas.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,20 @@ const {
isInMiscModule,
} = require('./rc');

function writeRoutes(oas, routes, globalArgs, moduleForEndpoints, rioExampleResultOfEndpoint, errorExample, rioTypeOfEndpoint, rioDescriptionOfEndpoint, rioStatusOfEndpoint, rioArgsForEndpoint, rioIgnoreGlobalsForEndpoint) {
function writeRoutes(
oas,
routes,
globalArgs,
moduleForEndpoints,
rioExampleResultOfEndpoint,
errorExample,
rioTypeOfEndpoint,
rioDescriptionOfEndpoint,
rioStatusOfEndpoint,
rioArgsForEndpoint,
rioIgnoreGlobalsForEndpoint,
rioTagsForEndpoint,
) {
const endpointCount = routes.length;
routes.sort((a, b) => {
if (formatEndpoint(a) < formatEndpoint(b)) {
Expand Down Expand Up @@ -54,6 +67,12 @@ function writeRoutes(oas, routes, globalArgs, moduleForEndpoints, rioExampleResu
required: argument.required,
schema: {
type: argument.type.oasType,
...(argument.type.oasType === 'array' && {
items: {
type: argument.itemType,
},
}),

example: argument.exampleValue,
},
};
Expand All @@ -66,6 +85,11 @@ function writeRoutes(oas, routes, globalArgs, moduleForEndpoints, rioExampleResu

properties[argument.name] = {
type: argument.type.oasType,
...(argument.type.oasType === 'array' && {
items: {
type: argument.itemType,
},
}),
description: argument.description,
};

Expand Down Expand Up @@ -101,7 +125,11 @@ function writeRoutes(oas, routes, globalArgs, moduleForEndpoints, rioExampleResu

oas.paths[route][method].deprecated = status.name === 'deprecated';

oas.paths[route][method].tags = [module];
if (rioTagsForEndpoint[endpoint].length > 0) {
oas.paths[route][method].tags = rioTagsForEndpoint[endpoint];
} else {
oas.paths[route][method].tags = [module];
}

if (method === 'get' || method === 'delete') {
oas.paths[route][method].parameters = parameters;
Expand Down Expand Up @@ -232,8 +260,29 @@ function writeRoutes(oas, routes, globalArgs, moduleForEndpoints, rioExampleResu
}
}

function oasGenerate(path, isPublic, paths, app, appName, globalArgs, rioArgsForEndpoint, rioTypeOfEndpoint, rioDescriptionOfEndpoint, rioExampleResultOfEndpoint, rioStatusOfEndpoint, rioAvailabilityOfEndpoint, rioIgnoreGlobalsForEndpoint) {
const { moduleForEndpoints, modules, routes } = router.getEndpoints(app, paths, rioStatusOfEndpoint, rioAvailabilityOfEndpoint, isPublic);
function oasGenerate(
path,
isPublic,
paths,
app,
appName,
globalArgs,
rioArgsForEndpoint,
rioTypeOfEndpoint,
rioDescriptionOfEndpoint,
rioExampleResultOfEndpoint,
rioStatusOfEndpoint,
rioAvailabilityOfEndpoint,
rioIgnoreGlobalsForEndpoint,
rioTagsForEndpoint,
) {
const { moduleForEndpoints, modules, routes } = router.getEndpoints(
app,
paths,
rioStatusOfEndpoint,
rioAvailabilityOfEndpoint,
isPublic,
);
routes.sort();
const rc = getRioRC(path);

Expand Down Expand Up @@ -323,10 +372,37 @@ function oasGenerate(path, isPublic, paths, app, appName, globalArgs, rioArgsFor
for (let i = 0; i < modules.length; i += 1) {
const module = modules[i];
const moduleRoutes = routes.filter((route) => isInModule(route, module));
writeRoutes(oas, moduleRoutes, globalArgs, moduleForEndpoints, rioExampleResultOfEndpoint, errorExample, rioTypeOfEndpoint, rioDescriptionOfEndpoint, rioStatusOfEndpoint, rioArgsForEndpoint, rioIgnoreGlobalsForEndpoint);
writeRoutes(
oas,
moduleRoutes,
globalArgs,
moduleForEndpoints,
rioExampleResultOfEndpoint,
errorExample,
rioTypeOfEndpoint,
rioDescriptionOfEndpoint,
rioStatusOfEndpoint,
rioArgsForEndpoint,
rioIgnoreGlobalsForEndpoint,
rioTagsForEndpoint,
);
}
// This just means that the route is one part like /foo
const miscRoutes = routes.filter((route) => isInMiscModule(route));
writeRoutes(oas, miscRoutes, globalArgs, moduleForEndpoints, rioExampleResultOfEndpoint, errorExample, rioTypeOfEndpoint, rioDescriptionOfEndpoint, rioStatusOfEndpoint, rioArgsForEndpoint, rioIgnoreGlobalsForEndpoint);
writeRoutes(
oas,
miscRoutes,
globalArgs,
moduleForEndpoints,
rioExampleResultOfEndpoint,
errorExample,
rioTypeOfEndpoint,
rioDescriptionOfEndpoint,
rioStatusOfEndpoint,
rioArgsForEndpoint,
rioIgnoreGlobalsForEndpoint,
rioTagsForEndpoint,
);

const fileName = `${isPublic ? 'public-' : ''}swagger.json`;
const formatted = JSON.stringify(oas, null, 2);
Expand Down

0 comments on commit 8de512a

Please sign in to comment.