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

[REQ] [typescript] Generalize handling of text/* and json-like content-types #17282

Closed
a-ignatov-parc opened this issue Dec 1, 2023 · 0 comments

Comments

@a-ignatov-parc
Copy link
Contributor

Is your feature request related to a problem? Please describe.

Our API requires the use of various json-like content types, including application/vc+ld+json and application/didcomm-plain+json. Regrettably, the typescript generator has a list of supported content types that is hardcoded, without the option to extend it.

const supportedMediaTypes: { [mediaType: string]: number } = {
"application/json": Infinity,
"application/json-patch+json": 1,
"application/merge-patch+json": 1,
"application/strategic-merge-patch+json": 1,
"application/octet-stream": 0,
"application/x-www-form-urlencoded": 0
}

This creates a challenge in generating clients, as we need to modify templates even though all json-like content types utilize the same parse/stringify implementation.

Describe the solution you'd like

Instead of hardcoding content types, we can implement several predicates that will check if we can serialize/parse the provided content type.

type MimeTypeDescriptor = {
    type: string;
    subtype: string;
    subtypeTokens: string[];
};

const simpleMediaTypeRegex = /([^\/]+)\/([^;]+)/;

const parseMimeType = (mimeType: string): MimeTypeDescriptor | undefined => {
    const result = simpleMediaTypeRegex.exec(mimeType);
    if (!result) return undefined;
    const [, type, subtype] = result;
    return {
        type,
        subtype,
        subtypeTokens: subtype.split('+'),
    };
};

type MimeTypePredicate = (mimeType: string) => boolean;

const isJsonLikeMimeType: MimeTypePredicate = (mimeType) => {
    const result = parseMimeType(mimeType);
    if (!result) return false;
    return result.type === 'application' && result.subtypeTokens.includes('json');
}

const isTextLikeMimeType: MimeTypePredicate = (mimeType) => {
    const result = parseMimeType(mimeType);
    if (!result) return false;
    return result.type === 'text';
}

These helpers could then be used as follows

/**
 * Convert data to a string according the given media type
 */
public static stringify(data: any, mediaType: string): string {
    if (isTextLikeMimeType(mediaType)) {
        return String(data);
    }

    if (isJsonLikeMimeType(mediaType)) {
        return JSON.stringify(data);
    }

    throw new Error("The mediaType " + mediaType + " is not supported by ObjectSerializer.stringify.");
}

/**
 * Parse data from a string according to the given media type
 */
public static parse(rawData: string, mediaType: string | undefined) {
    if (mediaType === undefined) {
        throw new Error("Cannot parse content. No Content-Type defined.");
    }

    if (isTextLikeMimeType(mediaType)) {
        return rawData;
    }

    if (isJsonLikeMimeType(mediaType)) {
        return JSON.parse(rawData);
    }

    throw new Error("The mediaType " + mediaType + " is not supported by ObjectSerializer.parse.");
}

Describe alternatives you've considered

The only viable alternative I found is to augment --additional-properties with a mapping of content types to parsers/serializers. This is a more scalable solution, but in my opinion, it should accompany this proposal.

Additional context

None

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant