Skip to content

Commit

Permalink
Add tests for prototype code
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Nowak <[email protected]>
  • Loading branch information
rynowak committed Dec 28, 2024
1 parent e98a642 commit 7a5d63b
Show file tree
Hide file tree
Showing 10 changed files with 386 additions and 97 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '18'
node-version: '20'
- name: Enable Corepack
run: |
corepack enable
Expand Down Expand Up @@ -61,7 +61,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '18'
node-version: '20'
registry-url: 'https://npm.pkg.github.com'
scope: '@radius-project'
- name: Enable Corepack
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '18'
node-version: '20'
- name: Enable Corepack
run: |
corepack enable
Expand Down
172 changes: 96 additions & 76 deletions packages/manifest-to-bicep-extension/src/converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,71 +11,27 @@ import {
writeIndexMarkdown,
writeTypesJson,
} from 'bicep-types'
import { ResourceProvider, Schema } from './manifest'
import { APIVersion, ResourceProvider, ResourceType, Schema } from './manifest'

export function convert(manifest: ResourceProvider): {
typesContent: string
indexContent: string
documentationContent: string
} {
const factory = new TypeFactory()

for (const resourceType of manifest.types) {
for (const apiVersion of resourceType.apiVersions) {
const qualifiedName = `${manifest.name}/${resourceType.name}@${apiVersion.name}`

const propertyType = factory.addObjectType(
`${resourceType.name}Properties`,
schemaProperties(apiVersion.schema, factory)
)

const bodyType = factory.addObjectType(qualifiedName, {
name: {
type: factory.addStringType(),
flags:
ObjectTypePropertyFlags.Required |
ObjectTypePropertyFlags.Identifier,
description: 'The resource name.',
},
location: {
type: factory.addStringType(),
flags: ObjectTypePropertyFlags.None,
description: 'The resource location.',
},
properties: {
type: propertyType,
flags: ObjectTypePropertyFlags.Required,
description: 'The resource properties.',
},
apiVersion: {
type: factory.addStringLiteralType(apiVersion.name),
flags:
ObjectTypePropertyFlags.ReadOnly |
ObjectTypePropertyFlags.DeployTimeConstant,
description: 'The API version.',
},
type: {
type: factory.addStringLiteralType(
`${manifest.name}/${resourceType.name}`
),
flags:
ObjectTypePropertyFlags.ReadOnly |
ObjectTypePropertyFlags.DeployTimeConstant,
description: 'The resource type.',
},
id: {
type: factory.addStringType(),
flags: ObjectTypePropertyFlags.ReadOnly,
description: 'The resource id.',
},
})
factory.addResourceType(
qualifiedName,
ScopeType.Unknown,
undefined,
bodyType,
ResourceFlags.None,
{}
for (const [resourceTypeName, resourceType] of Object.entries(
manifest.types
)) {
for (const [apiVersionName, apiVersion] of Object.entries(
resourceType.apiVersions
)) {
addResourceTypeForApiVersion(
manifest,
resourceTypeName,
resourceType,
apiVersionName,
apiVersion,
factory
)
}
}
Expand All @@ -99,24 +55,102 @@ export function convert(manifest: ResourceProvider): {
}
}

function schemaProperties(
export function addResourceTypeForApiVersion(
manifest: ResourceProvider,
resourceTypeName: string,
_: ResourceType,
apiVersionName: string,
apiVersion: APIVersion,
factory: TypeFactory
): TypeReference {
const qualifiedName = `${manifest.name}/${resourceTypeName}@${apiVersionName}`

const propertyType = factory.addObjectType(
`${resourceTypeName}Properties`,
addObjectProperties(apiVersion.schema, factory)
)

const bodyType = factory.addObjectType(qualifiedName, {
name: {
type: factory.addStringType(),
flags:
ObjectTypePropertyFlags.Required | ObjectTypePropertyFlags.Identifier,
description: 'The resource name.',
},
location: {
type: factory.addStringType(),
flags: ObjectTypePropertyFlags.None,
description: 'The resource location.',
},
properties: {
type: propertyType,
flags: ObjectTypePropertyFlags.Required,
description: 'The resource properties.',
},
apiVersion: {
type: factory.addStringLiteralType(apiVersionName),
flags:
ObjectTypePropertyFlags.ReadOnly |
ObjectTypePropertyFlags.DeployTimeConstant,
description: 'The API version.',
},
type: {
type: factory.addStringLiteralType(
`${manifest.name}/${resourceTypeName}`
),
flags:
ObjectTypePropertyFlags.ReadOnly |
ObjectTypePropertyFlags.DeployTimeConstant,
description: 'The resource type.',
},
id: {
type: factory.addStringType(),
flags: ObjectTypePropertyFlags.ReadOnly,
description: 'The resource id.',
},
})
return factory.addResourceType(
qualifiedName,
ScopeType.Unknown,
undefined,
bodyType,
ResourceFlags.None,
{}
)
}

export function addSchemaType(
schema: Schema,
name: string,
factory: TypeFactory
): TypeReference {
if (schema.type === 'string') {
return factory.addStringType()
} else if (schema.type === 'object') {
return factory.addObjectType(name, addObjectProperties(schema, factory))
} else {
throw new Error(`Unsupported schema type: ${schema.type}`)
}
}

export function addObjectProperties(
parent: Schema,
factory: TypeFactory
): Record<string, ObjectTypeProperty> {
const results: Record<string, ObjectTypeProperty> = {}
for (const [key, value] of Object.entries(parent.properties ?? {})) {
results[key] = addSchemaProperty(parent, key, value, factory)
results[key] = addObjectProperty(parent, key, value, factory)
}
return results
}

function addSchemaProperty(
export function addObjectProperty(
parent: Schema,
key: string,
property: Schema,
factory: TypeFactory
): ObjectTypeProperty {
const propertyType = addSchema(property, key, factory)
const propertyType = addSchemaType(property, key, factory)

let flags = ObjectTypePropertyFlags.None
if (parent.required?.includes(key)) {
Expand All @@ -132,17 +166,3 @@ function addSchemaProperty(
flags: flags,
}
}

function addSchema(
schema: Schema,
name: string,
factory: TypeFactory
): TypeReference {
if (schema.type === 'string') {
return factory.addStringType()
} else if (schema.type === 'object') {
return factory.addObjectType(name, schemaProperties(schema, factory))
} else {
throw new Error(`Unsupported schema type: ${schema.type}`)
}
}
15 changes: 10 additions & 5 deletions packages/manifest-to-bicep-extension/src/manifest.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
import { parse } from 'yaml'

export interface ResourceProvider {
name: string
types: ResourceType[]
types: Record<string, ResourceType>
}

export interface ResourceType {
name: string
defaultApiVersion?: string
apiVersions: APIVersion[]
apiVersions: Record<string, APIVersion>
}

export interface APIVersion {
name: string
schema: Schema
capabilities?: string[]
}

export interface Schema {
type: 'string' | 'object'
description?: string
properties?: Schema[]
properties?: Record<string, Schema>
required?: string[]
readOnly?: boolean
}

export function parseManifest(input: string): ResourceProvider {
const parsed = parse(input) as ResourceProvider
return parsed
}
3 changes: 0 additions & 3 deletions packages/manifest-to-bicep-extension/src/math.ts

This file was deleted.

4 changes: 2 additions & 2 deletions packages/manifest-to-bicep-extension/src/program.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { parse } from 'yaml'
import yargs from 'yargs'
import { hideBin } from 'yargs/helpers'
import fs from 'node:fs'
import { convert } from './converter'
import { parseManifest } from './manifest'

async function generate(manifest: string, output: string) {
const data = fs.readFileSync(manifest, 'utf8')
const parsed = parse(data)
const parsed = parseManifest(data)
const converted = convert(parsed)

fs.rmSync(`${output}/types.json`, { force: true })
Expand Down
Loading

0 comments on commit 7a5d63b

Please sign in to comment.