From f66d39f8d9617a61a245ceb97d9c8b01647d27b3 Mon Sep 17 00:00:00 2001 From: Long Zheng Date: Fri, 16 Feb 2024 02:20:56 +1100 Subject: [PATCH] sdk: calculate required/optional fields from schema (#1321) * Add tsconfig for sdk/types/src * Get property isOptional from schema Use typedoc types --- sdk/types/src/build.ts | 35 ++++++++++++++------------------- sdk/types/src/tsconfig.json | 10 ++++++++++ sdk/types/tsconfig.typedoc.json | 1 + 3 files changed, 26 insertions(+), 20 deletions(-) create mode 100644 sdk/types/src/tsconfig.json diff --git a/sdk/types/src/build.ts b/sdk/types/src/build.ts index 7562f84631..fc85614a0c 100644 --- a/sdk/types/src/build.ts +++ b/sdk/types/src/build.ts @@ -2,12 +2,14 @@ import stringifyObject from 'stringify-object'; import { ScryptedInterface, ScryptedInterfaceDescriptor } from "./types.input"; import path from 'path'; import fs from "fs"; +import packageJson from "../package.json" +import { DeclarationReflection, ProjectReflection, SomeType } from 'typedoc'; -const schema = JSON.parse(fs.readFileSync(path.join(__dirname, '../gen/schema.json')).toString()); -const typesVersion = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json')).toString()).version; +const schema = JSON.parse(fs.readFileSync(path.join(__dirname, '../gen/schema.json')).toString()) as ProjectReflection; +const typesVersion = packageJson.version; const ScryptedInterfaceDescriptors: { [scryptedInterface: string]: ScryptedInterfaceDescriptor } = {}; -const allProperties: { [property: string]: any } = {}; +const allProperties: { [property: string]: DeclarationReflection } = {}; function toTypescriptType(type: any): string { if (type.type === 'literal') @@ -20,39 +22,31 @@ function toTypescriptType(type: any): string { } for (const name of Object.values(ScryptedInterface)) { - const td = schema.children.find((child: any) => child.name === name); + const td = schema.children.find((child) => child.name === name); const children = td.children || []; - const properties = children.filter((child: any) => child.kindString === 'Property').map((child: any) => child.name); - const methods = children.filter((child: any) => child.kindString === 'Method').map((child: any) => child.name); + const properties = children.filter((child) => child.kindString === 'Property').map((child) => child.name); + const methods = children.filter((child) => child.kindString === 'Method').map((child) => child.name); ScryptedInterfaceDescriptors[name] = { name, methods, properties, }; - for (const p of children.filter((child: any) => child.kindString === 'Property')) { - allProperties[p.name] = p.type; + for (const p of children.filter((child) => child.kindString === 'Property')) { + allProperties[p.name] = p; } } const properties = Object.values(ScryptedInterfaceDescriptors).map(d => d.properties).flat(); const methods = Object.values(ScryptedInterfaceDescriptors).map(d => d.methods).flat(); -const requiredProperties = [ - 'id', - 'interfaces', - 'providedInterfaces', - 'pluginId', - 'mixins', -]; - const deviceStateContents = ` export interface DeviceState { -${Object.entries(allProperties).map(([property, type]) => ` ${property}${!requiredProperties.includes(property) ? '?' : ''}: ${toTypescriptType(type)}`).join('\n')}; +${Object.entries(allProperties).map(([property, {type, flags}]) => ` ${property}${flags.isOptional ? '?' : ''}: ${toTypescriptType(type)}`).join('\n')}; } export class DeviceBase implements DeviceState { -${Object.entries(allProperties).map(([property, type]) => ` ${property}${!requiredProperties.includes(property) ? '?' : ''}: ${toTypescriptType(type)}`).join('\n')}; +${Object.entries(allProperties).map(([property, {type, flags}]) => ` ${property}${flags.isOptional ? '?' : ''}: ${toTypescriptType(type)}`).join('\n')}; } `; @@ -237,7 +231,8 @@ class ${e.name}(str, Enum): ${toDocstring(e)} ` for (const val of e.children) { - pythonEnums += ` ${val.name} = "${val.type.value}" + if ('type' in val && 'value' in val.type) + pythonEnums += ` ${val.name} = "${val.type.value}" `; } } @@ -268,7 +263,7 @@ class DeviceState: pass ` -for (const [val, type] of Object.entries(allProperties)) { +for (const [val, {type}] of Object.entries(allProperties)) { if (val === 'nativeId') continue; python += ` diff --git a/sdk/types/src/tsconfig.json b/sdk/types/src/tsconfig.json new file mode 100644 index 0000000000..5ee8bfdbfa --- /dev/null +++ b/sdk/types/src/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "ES2020", + "noImplicitAny": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "noEmit": true + } +} \ No newline at end of file diff --git a/sdk/types/tsconfig.typedoc.json b/sdk/types/tsconfig.typedoc.json index 04dc735cbb..d432f8c2ae 100644 --- a/sdk/types/tsconfig.typedoc.json +++ b/sdk/types/tsconfig.typedoc.json @@ -4,6 +4,7 @@ "target": "ESNext", "noImplicitAny": true, "esModuleInterop": true, + "resolveJsonModule": true, "sourceMap": true, "declaration": true, },