Skip to content

Commit

Permalink
feat: make responding service calls generic (#36)
Browse files Browse the repository at this point in the history
* feat: make all service calls generic to allow for responses

Defaults to void to maintain the same behavior

* feat: add override for weather.get_forecasts to the created interface

* feat: only change to new generic version if the service might return a response
  • Loading branch information
allout58 committed Sep 10, 2024
1 parent a4e2a3b commit e771067
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/build.extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export function BuildTypes({ logger, hass, type_build, config, internal }: TServ
` AppleNotificationData,`,
` NotificationData,`,
` PICK_ENTITY,`,
` WeatherGetForecasts,`,
`} from "./helpers";`,
``,
PICK_FROM_PLATFORM,
Expand Down
43 changes: 38 additions & 5 deletions src/i-call-service.extension.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DOWN, is, TServiceParams, UP } from "@digital-alchemy/core";
import { HassServiceDTO, ServiceListField, ServiceListServiceTarget } from "@digital-alchemy/hass";
import { factory, SyntaxKind, TypeElement } from "typescript";
import { factory, SyntaxKind, TypeElement, TypeNode, TypeParameterDeclaration } from "typescript";

export async function ICallServiceExtension({ hass, type_build }: TServiceParams) {
return async function () {
Expand Down Expand Up @@ -49,16 +49,49 @@ export async function ICallServiceExtension({ hass, type_build }: TServiceParams
// > [service_name]: (service_data) => Promise<void | unknown>
// > }
// > }
const isReturnResponse = is.boolean(value.response?.optional);
const genericIdent = "T";

// Override default return type for some known cases
let defaultReturnType: TypeNode = factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword);
if (domain === "weather" && key === "get_forecasts") {
defaultReturnType = factory.createTypeReferenceNode(
factory.createIdentifier("WeatherGetForecasts"),
undefined,
);
}

// Set up for the default case of (service_data) => Promise<void>
let generic: TypeParameterDeclaration[] | undefined = undefined;
let returnType: TypeNode | undefined = factory.createTypeReferenceNode(
factory.createIdentifier("Promise"),
[factory.createKeywordTypeNode(SyntaxKind.VoidKeyword)],
);

// If the service might return a response, change instead to <T = unknown>(service_data) => Promise<T>
if (isReturnResponse) {
generic = [
factory.createTypeParameterDeclaration(
undefined,
factory.createIdentifier(genericIdent),
undefined,
defaultReturnType,
),
];
returnType = factory.createExpressionWithTypeArguments(
factory.createIdentifier("Promise"),
[factory.createTypeReferenceNode(factory.createIdentifier(genericIdent), undefined)],
);
}

return type_build.tsdoc.serviceComment(
factory.createMethodSignature(
undefined,
factory.createIdentifier(key),
undefined,
undefined,
generic,
serviceParameters(domain, key, value),
factory.createTypeReferenceNode(factory.createIdentifier("Promise"), [
factory.createKeywordTypeNode(SyntaxKind.VoidKeyword),
]),
returnType,
),
key,
value,
Expand Down

0 comments on commit e771067

Please sign in to comment.