Skip to content

Commit

Permalink
Add prototype code (#6)
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Nowak <[email protected]>
  • Loading branch information
rynowak authored Dec 24, 2024
1 parent 465ec28 commit e98a642
Show file tree
Hide file tree
Showing 19 changed files with 341 additions and 44 deletions.
8 changes: 8 additions & 0 deletions .github/depdendabot.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: 2
updates:
- package-ecosystem: 'gitsubmodule'
directory: '/'
- package-ecosystem: 'npm'
directory: '/'
schedule:
interval: 'monthly'
22 changes: 14 additions & 8 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,29 @@ on:
- main
- features/*
- release/*
env:
CI_PUBLISH:
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
submodules: true

- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: "18"
node-version: '18'
- name: Enable Corepack
run: |
corepack enable
- name: Install dependencies
run: yarn install --immutable
run: yarn install --no-immutable
env:
YARN_ENABLE_HARDENED_MODE: 0

- name: Build
run: yarn run build:all
Expand All @@ -47,7 +49,9 @@ jobs:
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
submodules: true

- name: Get commit version
shell: bash
Expand All @@ -57,15 +61,17 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: "18"
node-version: '18'
registry-url: 'https://npm.pkg.github.com'
scope: '@radius-project'
- name: Enable Corepack
run: |
corepack enable
- name: Install dependencies
run: yarn install --immutable
run: yarn install --no-immutable
env:
YARN_ENABLE_HARDENED_MODE: 0

- name: Publish
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
Expand Down
10 changes: 7 additions & 3 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,22 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
submodules: true

- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: "18"
node-version: '18'
- name: Enable Corepack
run: |
corepack enable
- name: Install dependencies
run: yarn install --immutable
run: yarn install --no-immutable
env:
YARN_ENABLE_HARDENED_MODE: 0

- name: Run tests
run: yarn run test:all
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "bicep-types"]
path = bicep-types
url = https://github.com/Azure/bicep-types
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bicep-types/
4 changes: 2 additions & 2 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"trailingComma": "es5",
"tabWidth": 4,
"tabWidth": 2,
"semi": false,
"singleQuote": true
}
}
1 change: 1 addition & 0 deletions bicep-types
Submodule bicep-types added at 3676a8
15 changes: 10 additions & 5 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
// @ts-check
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";
import eslint from '@eslint/js'
import tseslint from 'typescript-eslint'

export default tseslint.config(
{
ignores: ["**/jest.config.js", "**/eslint.config.mjs", "**/dist/**"],
ignores: [
'**/jest.config.js',
'**/eslint.config.mjs',
'**/dist/**',
'**/bicep-types/**',
],
},
eslint.configs.recommended,
tseslint.configs.strict,
Expand All @@ -16,5 +21,5 @@ export default tseslint.config(
tsconfigRootDir: import.meta.dirname,
},
},
},
);
}
)
8 changes: 4 additions & 4 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/** @type {import('ts-jest').JestConfigWithTsJest} **/
module.exports = {
projects: ["<rootDir>/packages/*"],
testEnvironment: "node",
projects: ['<rootDir>/packages/*'],
testEnvironment: 'node',
transform: {
"^.+.tsx?$": ["ts-jest", {}],
'^.+.tsx?$': ['ts-jest', {}],
},
};
}
14 changes: 7 additions & 7 deletions packages/manifest-to-bicep-extension/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
module.exports = {
displayName: "manifest-to-bicep-extension",
roots: ["<rootDir>"],
displayName: 'manifest-to-bicep-extension',
roots: ['<rootDir>'],
transform: {
"^.+\\.tsx?$": "ts-jest",
'^.+\\.tsx?$': 'ts-jest',
},
testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$",
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
moduleNameMapper: {
"^src/(.*)": "<rootDir>/src/$1",
'^src/(.*)': '<rootDir>/src/$1',
},
};
}
13 changes: 13 additions & 0 deletions packages/manifest-to-bicep-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,24 @@
"dist/"
],
"main": "dist/src/index.js",
"dependencies": {
"bicep-types": "file:../../bicep-types/src/bicep-types",
"yaml": "^2.6.0",
"yargs": "^17.7.2"
},
"devDependencies": {
"@types/node": "^22.7.5",
"@types/yargs": "^17.0.33"
},
"bundledDependencies": [
"bicep-types"
],
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"publish": "npm publish",
"prepublishOnly": "yarn build",
"preinstall": "cd ../../bicep-types/src/bicep-types && npm ci && npm run build",
"version": "npm pkg set version=${0}"
}
}
148 changes: 148 additions & 0 deletions packages/manifest-to-bicep-extension/src/converter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import {
buildIndex,
ObjectTypeProperty,
ObjectTypePropertyFlags,
ResourceFlags,
ScopeType,
TypeFactory,
TypeFile,
TypeReference,
writeIndexJson,
writeIndexMarkdown,
writeTypesJson,
} from 'bicep-types'
import { ResourceProvider, 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,
{}
)
}
}

const typeFiles: TypeFile[] = []
typeFiles.push({
relativePath: 'types.json',
types: factory.types,
})

const indexContent = buildIndex(typeFiles, (log) => console.log(log), {
name: manifest.name.toLowerCase().replace('.', ''),
version: '0.0.1',
isSingleton: false,
})

return {
typesContent: writeTypesJson(factory.types),
indexContent: writeIndexJson(indexContent),
documentationContent: writeIndexMarkdown(indexContent),
}
}

function schemaProperties(
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)
}
return results
}

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

let flags = ObjectTypePropertyFlags.None
if (parent.required?.includes(key)) {
flags |= ObjectTypePropertyFlags.Required
}
if (property.readOnly === true) {
flags |= ObjectTypePropertyFlags.ReadOnly
}

return {
description: property.description,
type: propertyType,
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}`)
}
}
5 changes: 3 additions & 2 deletions packages/manifest-to-bicep-extension/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
import { add } from './math';
add(9, 3);
// eslint-disable-next-line @typescript-eslint/no-require-imports
const program = require('./program')
program.run()
24 changes: 24 additions & 0 deletions packages/manifest-to-bicep-extension/src/manifest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export interface ResourceProvider {
name: string
types: ResourceType[]
}

export interface ResourceType {
name: string
defaultApiVersion?: string
apiVersions: APIVersion[]
}

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

export interface Schema {
type: 'string' | 'object'
description?: string
properties?: Schema[]
required?: string[]
readOnly?: boolean
}
2 changes: 1 addition & 1 deletion packages/manifest-to-bicep-extension/src/math.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export function add(a: number, b: number): number {
return a + b;
return a + b
}
Loading

0 comments on commit e98a642

Please sign in to comment.