Skip to content

Commit

Permalink
chore: token api simplification (#4600)
Browse files Browse the repository at this point in the history
## About the changes
We found a problem generating the Go SDK client for the tokens API that
makes use of `oneOf`, combined with `allOf`. The generator doesn't know
how to map this type and leaves it as an object. This PR simplifies the spec and therefore the code generated after it
  • Loading branch information
gastonfournier authored Sep 4, 2023
1 parent 53f90d3 commit 19ec66a
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 21 deletions.
38 changes: 17 additions & 21 deletions src/lib/openapi/spec/create-api-token-schema.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FromSchema } from 'json-schema-to-ts';

import { mergeAllOfs } from '../util/all-of';
const adminSchema = {
required: ['type'],
type: 'object',
Expand Down Expand Up @@ -74,6 +74,18 @@ const clientFrontendSchema = {
},
} as const;

const expireSchema = {
type: 'object',
properties: {
expiresAt: {
type: 'string',
format: 'date-time',
description: 'The time when this token should expire.',
example: '2023-07-04T11:26:24+02:00',
},
},
} as const;

// TODO: (openapi) this schema isn't entirely correct: `project` and `projects`
// are mutually exclusive.
//
Expand All @@ -88,27 +100,11 @@ export const createApiTokenSchema = {
type: 'object',
description:
'The data required to create an [Unleash API token](https://docs.getunleash.io/reference/api-tokens-and-client-keys).',
properties: {
expiresAt: {
type: 'string',
format: 'date-time',
description: 'The time when this token should expire.',
example: '2023-07-04T11:26:24+02:00',
},
},
oneOf: [
{
allOf: [adminSchema, tokenNameSchema],
},
{
allOf: [adminSchema, usernameSchema],
},
{
allOf: [clientFrontendSchema, tokenNameSchema],
},
{
allOf: [clientFrontendSchema, usernameSchema],
},
mergeAllOfs([expireSchema, adminSchema, tokenNameSchema]),
mergeAllOfs([expireSchema, adminSchema, usernameSchema]),
mergeAllOfs([expireSchema, clientFrontendSchema, tokenNameSchema]),
mergeAllOfs([expireSchema, clientFrontendSchema, usernameSchema]),
],
components: {},
} as const;
Expand Down
43 changes: 43 additions & 0 deletions src/lib/openapi/util/all-of.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { JSONSchema } from 'json-schema-to-ts';

// this function simplifies simple schemas and return allOf schema if it
// doesn't know how to simplify it. It's a proof of concept but it can be extended
export function mergeAllOf(a: JSONSchema, b: JSONSchema): JSONSchema {
if (typeof a !== 'boolean' && typeof b !== 'boolean') {
const {
required: aRequired,
properties: aProperties,
type: aType,
...aRest
} = a;
const {
required: bRequired,
properties: bProperties,
type: bType,
...bRest
} = b;
if (
Object.keys(aRest).length === 0 &&
Object.keys(bRest).length === 0 &&
aType === 'object' &&
bType === 'object'
) {
return {
required: [...(aRequired ?? []), ...(bRequired ?? [])],
type: 'object',
properties: { ...aProperties, ...bProperties },
};
}
}
return {
allOf: [a, b],
};
}

export function mergeAllOfs(schemas: JSONSchema[]): JSONSchema {
if (schemas.length === 1) {
return schemas[0];
}
const [a, b, ...rest] = schemas;
return mergeAllOfs([mergeAllOf(a, b), ...rest]);
}

0 comments on commit 19ec66a

Please sign in to comment.