Files
OpenAPI.gg/src/lib/pathHandling.ts
2024-07-04 17:05:59 +00:00

183 lines
5.1 KiB
TypeScript

import { get } from 'svelte/store';
import type { ModalSettings, ModalStore } from '@skeletonlabs/skeleton';
import { pathTemplate } from './pathTemplate';
import type { OpenAPIV3_1 } from './openAPITypes';
import { selectedSpec } from './db';
export const pathVariables = /\{([^}]+)\}/gm;
export const pathRegex = /\/([/]*[{]?[a-zA-Z]+[}]?)*/gm;
/// Adds a new path to the OpenAPI document
export const addPath = (modalStore: ModalStore, startingPoint: string = '/') => {
let userPath: string = startingPoint.trim();
const modal: ModalSettings = {
type: 'prompt',
// Data
title: 'Enter Pathname',
body: 'Wrap path parameters in curly braces. Example: /users/{userId}',
// Populates the input value and attributes
value: userPath,
valueAttr: { type: 'text', minlength: 1, required: true },
// Returns the updated response value
response: (r: string | boolean | undefined) => {
if (r === false) return;
if (typeof r !== 'string') return;
userPath = r;
// Check if path already exists
if (!pathExists(userPath)) {
alert('Path already exists');
return;
}
// Check if path is valid
if (!isValidPath(userPath)) {
alert('Invalid path');
return;
}
// create path object
const store = get(selectedSpec);
if (!store.spec.paths) store.spec.paths = {};
store.spec.paths[userPath] = pathTemplate;
// sort paths alphabetically
sortPathsAlphabetically();
}
};
modalStore.trigger(modal);
};
export const renamePath = (modalStore: ModalStore, oldPath: string) => {
let userPath: string = oldPath;
const modal: ModalSettings = {
type: 'prompt',
// Data
title: 'Rename path',
body: 'Wrap path parameters in curly braces. Example: /users/{userId}',
// Populates the input value and attributes
value: userPath,
valueAttr: { type: 'text', minlength: 1, required: true },
// Returns the updated response value
response: (r: string | boolean | undefined) => {
if (r === false) return;
if (typeof r !== 'string') return;
userPath = r;
// Check if path already exists
if (!pathExists(userPath)) {
alert('Path already exists');
return;
}
// Check if path is valid
if (!isValidPath(userPath)) {
alert('Invalid path');
return;
}
// create path object
const store = get(selectedSpec);
if (!store.spec.paths) store.spec.paths = {};
// copy old path object to new path object
store.spec.paths[userPath] = store.spec.paths[oldPath];
// delete old path object
delete store.spec.paths[oldPath];
// add path to store
selectedSpec.set(store);
// sort paths alphabetically
sortPathsAlphabetically();
}
};
modalStore.trigger(modal);
};
/// Removes a path from the OpenAPI document
export const deletePath = (modalStore: ModalStore, path: string) => {
const modal: ModalSettings = {
type: 'confirm',
// Data
title: `Delete ${path}?`,
body: 'Are you sure you wish to delete the path?',
// TRUE if confirm pressed, FALSE if cancel pressed
response: (r: boolean) => {
if (r === false) return;
const store = get(selectedSpec);
// check if path exists
if (!store.spec.paths) return;
if (!(path in store.spec.paths)) return;
delete store.spec.paths[path];
selectedSpec.set(store);
}
};
modalStore.trigger(modal);
};
/// checks if a given path already exists
export const pathExists = (path: string) => {
const store = get(selectedSpec);
return !(path in store.spec.paths!);
};
/// checks if a given path is valid
export const isValidPath = (path: string) => {
// check if path variables aren't duplicated
const variableRegex = /\{([^}]+)\}/gm;
const variables = path.match(variableRegex);
if (variables) {
const uniqueVariables = new Set(variables);
if (variables.length !== uniqueVariables.size) return false;
}
// check if path is a valid path
const pathWithoutVariables = path.replaceAll('{', '').replaceAll('}', '');
console.log(pathWithoutVariables);
const pathRegex = /(\/[a-zA-Z0-9]+)+|\//gm;
const pathParts = pathWithoutVariables.match(pathRegex);
// the fallback is to return false if the pathParts array is null
return pathParts?.length === 1;
};
/// sorts the paths in the OpenAPI document alphabetically
export const sortPathsAlphabetically = () => {
const tempPathObject = {};
const store = get(selectedSpec);
// @ts-expect-error - we are working with an initially empty object
Object.keys(store.spec.paths)
.sort()
.forEach((key) => {
// @ts-expect-error - we are working with initially empty objects
tempPathObject[key] = store.spec.paths[key];
});
// update path object
selectedSpec.update((data) => {
data.spec.paths = tempPathObject;
return data;
});
};
export const getPathVariables = (path: string) => {
const variables = path.match(pathVariables);
if (!variables) return [];
return variables.map((variable) => variable.replace('{', '').replace('}', ''));
};
export const sortPathParameters = (parameters: OpenAPIV3_1.ParameterObject[]) => {
const tempParameters = parameters;
tempParameters.sort((a, b) => {
if (a.in < b.in) return -1;
if (a.in > b.in) return 1;
return 0;
});
return tempParameters;
};