Skip to content

Commit

Permalink
chore(services): Switches MeshService/MeshExternalService to use Open…
Browse files Browse the repository at this point in the history
…API specs (#2748)

First PR converting our Typescript types to use auto generated types using an OpenAPI spec as the source of truth.

This means far less handwriting Typescript 🎉 

We also use the `openapi-fetch` package as our HTTP client.

---

Rough roadmap in relation to this:

- We currently just expect `kuma-hq/kuma` to be a sibling on your file system in our to auto generate the types. We could do something more automated at some point in the, probably distant, future.
- Slowly but surely move all that we can over to use our autogenerated types and new HTTP client.
- Any missing types should be temporarily handwritten as OpenAPI YAML and an issue created over in `kumahq/kuma` so folks are aware we need these types.
- Once we are completely on OpenApi we can switch the `sources.ts`  dependencies to be `fetch` instead of the full `api`/`kumaApi` client.
- Lastly remove `kumaApi` entirely and all the old handwritten types.

Signed-off-by: John Cowen <john.cowen@konghq.com>
  • Loading branch information
johncowen authored Jul 15, 2024
1 parent 5d9c5df commit 27f17bb
Show file tree
Hide file tree
Showing 14 changed files with 7,552 additions and 121 deletions.
1 change: 1 addition & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ const INLINE_NON_VOID_ELEMENTS = [
ignorePatterns: [
'node_modules',
'dist',
'src/types/auto-generated.d.ts',
],
plugins: ['vue', 'import', '@typescript-eslint'],
extends: ['eslint:recommended', 'plugin:vue/vue3-recommended', 'standard', '@vue/typescript', 'plugin:import/recommended', 'plugin:import/typescript'],
Expand Down
4 changes: 4 additions & 0 deletions mk/build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,7 @@ deploy/preview:
@$(MAKE) build/preview
@$(MAKE) deploy/test

build/types:
@npx openapi-typescript \
../kuma/docs/generated/openapi.yaml \
-o src/types/auto-generated.d.ts
83 changes: 83 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"deepmerge": "^4.3.1",
"js-yaml": "^4.1.0",
"object.groupby": "^1.0.3",
"openapi-fetch": "^0.9.8",
"path-to-regexp": "^7.0.0",
"pretty-bytes": "^6.1.1",
"prismjs": "^1.29.0",
Expand Down Expand Up @@ -71,6 +72,7 @@
"marked": "^13.0.1",
"msw": "^2.3.1",
"postcss": "^8.4.39",
"openapi-typescript": "^6.7.6",
"postcss-html": "^1.7.0",
"sass": "^1.77.6",
"shiki": "^1.10.3",
Expand Down
6 changes: 6 additions & 0 deletions src/app/application/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import type { ServiceDefinition } from '@/services/utils'
import { token, createInjections, constant } from '@/services/utils'
import type { Component } from 'vue'
export * from './services/can'
export { defineSources } from './services/data-source'

// temporary simple "JSON data only" structuredClone polyfill for cloning JSON
// data
Expand Down Expand Up @@ -61,6 +62,7 @@ const $ = {
env: token<Env['var']>('application.env'),
EnvVars: token<EnvVars>('EnvVars'),

fetch: token<typeof fetch>('application.fetch'),
can: token<Can>('application.can'),
features: token('application.can.features'),

Expand Down Expand Up @@ -124,6 +126,10 @@ export const services = (app: Record<string, Token>): ServiceDefinition[] => {
],
}],

[$.fetch, {
service: () => fetch,
}],

[$.can, {
service: can,
arguments: [
Expand Down
18 changes: 11 additions & 7 deletions src/app/common/code-block/ResourceCodeBlock.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
if (expanded) {
toggle()
}
cb((text: Entity) => copy(toYamlRepresentation(text)), (e: unknown) => console.error(e))
cb((text: Object) => copy(toYamlRepresentation(text)), (e: unknown) => console.error(e))
}"
:copying="expanded"
/>
Expand All @@ -51,17 +51,16 @@
import { computed } from 'vue'
import CodeBlock from './CodeBlock.vue'
import type { Entity } from '@/types/index.d'
import { useI18n } from '@/utilities'
import { toYaml } from '@/utilities/toYaml'
type Resolve = (data: Entity) => void
type Resolve = (data: Object) => void
type CopyCallback = (resolve: Resolve, reject: (e: unknown) => void) => void
const { t } = useI18n()
const props = withDefaults(defineProps<{
resource: Entity
resource: Object
codeMaxHeight?: string
isSearchable?: boolean
query?: string
Expand All @@ -82,8 +81,13 @@ const emit = defineEmits<{
}>()
const yamlUniversal = computed(() => toYamlRepresentation(props.resource))
function toYamlRepresentation(resource: Entity): string {
const { creationTime, modificationTime, ...resourceWithoutTimes } = resource
return toYaml(resourceWithoutTimes)
function toYamlRepresentation(resource: Object): string {
if ('creationTime' in resource) {
delete resource.creationTime
}
if ('modificationTime' in resource) {
delete resource.modificationTime
}
return toYaml(resource)
}
</script>
2 changes: 1 addition & 1 deletion src/app/kuma/services/kuma-api/Api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type Env from '@/app/application/services/env/Env'

export class Api {
constructor(
protected client: RestClient,
public client: RestClient,
protected env: Env['var'],
) { }

Expand Down
36 changes: 36 additions & 0 deletions src/app/services/data/MeshExternalService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { components } from '@/types/auto-generated.d'
type GeneratedMeshExternalService = components['schemas']['MeshExternalServiceItem']
type GeneratedMeshExternalServiceList = components['responses']['MeshExternalServiceList']['content']['application/json']

export const MeshExternalService = {
fromObject(item: GeneratedMeshExternalService) {
const labels = item.labels ?? {}
const name = labels['kuma.io/display-name'] ?? item.name
const namespace = labels['k8s.kuma.io/namespace'] ?? ''
return {
...item,
config: item,
id: item.name,
name,
namespace,
labels,
status: ((item = {}) => {
return {
...item,
addresses: Array.isArray(item.addresses) ? item.addresses : [],
}
})(item.status),

}
},

fromCollection(collection: GeneratedMeshExternalServiceList) {
const items = Array.isArray(collection.items) ? collection.items.map(MeshExternalService.fromObject) : []
return {
...collection,
items,
total: collection.total ?? items.length,
}
},
}
export type MeshExternalService = ReturnType<typeof MeshExternalService['fromObject']>
46 changes: 46 additions & 0 deletions src/app/services/data/MeshService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { components } from '@/types/auto-generated.d'
type GeneratedMeshService = components['schemas']['MeshServiceItem']
type GeneratedMeshServiceList = components['responses']['MeshServiceList']['content']['application/json']

export const MeshService = {
fromObject(item: GeneratedMeshService) {
const labels = item.labels ?? {}
const name = labels['kuma.io/display-name'] ?? item.name
const namespace = labels['k8s.kuma.io/namespace'] ?? ''
return {
...item,
id: item.name,
name,
namespace,
labels,
spec: ((item = {}) => {
return {
ports: Array.isArray(item.ports) ? item.ports : [],
selector: ((item = {}) => {
return {
dataplaneTags: Object.keys(item.dataplaneTags ?? {}).length > 0 ? item.dataplaneTags! : {},
}
})(item.selector),
}
})(item.spec),
status: ((item = {}) => {
return {
tls: typeof item.tls !== 'undefined' ? item.tls : { status: 'NotReady' },
vips: Array.isArray(item.vips) ? item.vips : [],
addresses: Array.isArray(item.addresses) ? item.addresses : [],
}
})(item.status),
config: item,
}
},

fromCollection(collection: GeneratedMeshServiceList) {
const items = Array.isArray(collection.items) ? collection.items.map(MeshService.fromObject) : []
return {
...collection,
items,
total: collection.total ?? items.length,
}
},
}
export type MeshService = ReturnType<typeof MeshService['fromObject']>
Loading

0 comments on commit 27f17bb

Please sign in to comment.