From fd6bf12d0bc049e6dbceae48b102f488923d09b8 Mon Sep 17 00:00:00 2001 From: Pagan Gazzard Date: Mon, 28 Oct 2024 14:58:20 +0000 Subject: [PATCH] Improve typings of reverse navigation properties Change-type: patch --- src/models/organization-invite.ts | 2 +- src/models/service.ts | 2 +- src/types/models.ts | 116 +++++++++++++++--------------- typing_tests/pine-params.ts | 2 +- typings/pinejs-client-core.d.ts | 13 +++- typings/utils.d.ts | 4 +- 6 files changed, 73 insertions(+), 66 deletions(-) diff --git a/src/models/organization-invite.ts b/src/models/organization-invite.ts index 7debb6b5b..aadb24243 100644 --- a/src/models/organization-invite.ts +++ b/src/models/organization-invite.ts @@ -154,7 +154,7 @@ const getOrganizationInviteModel = function ( name: roleName, }, }, - }) + } as const) : undefined, ]); type OrganizationInviteBase = Omit; diff --git a/src/models/service.ts b/src/models/service.ts index 195abcc1b..2955e1f58 100644 --- a/src/models/service.ts +++ b/src/models/service.ts @@ -97,7 +97,7 @@ const getServiceModel = ({ const { service } = await sdkInstance.models.application.get( slugOrUuidOrId, { - $select: 'service', + $select: 'id', $expand: { service: options, }, diff --git a/src/types/models.ts b/src/types/models.ts index 148b6cd02..d5162fd6b 100644 --- a/src/types/models.ts +++ b/src/types/models.ts @@ -87,14 +87,14 @@ export interface Organization { is_using__billing_version: 'v1' | 'v2'; logo_image: WebResource; - application: ReverseNavigationResource; + application?: ReverseNavigationResource; /** includes__organization_membership */ - organization_membership: ReverseNavigationResource; - owns__credit_bundle: ReverseNavigationResource; - owns__team: ReverseNavigationResource; - organization__has_private_access_to__device_type: ReverseNavigationResource; - organization_credit_notification: ReverseNavigationResource; - identity_provider_membership: ReverseNavigationResource; + organization_membership?: ReverseNavigationResource; + owns__credit_bundle?: ReverseNavigationResource; + owns__team?: ReverseNavigationResource; + organization__has_private_access_to__device_type?: ReverseNavigationResource; + organization_credit_notification?: ReverseNavigationResource; + identity_provider_membership?: ReverseNavigationResource; } export interface OrganizationCreditNotification { @@ -113,9 +113,9 @@ export interface Team { belongs_to__organization: NavigationResource; /** includes__user */ - team_membership: ReverseNavigationResource; + team_membership?: ReverseNavigationResource; /** grants_access_to__application */ - team_application_access: ReverseNavigationResource; + team_application_access?: ReverseNavigationResource; } export interface RecoveryTwoFactor { @@ -141,11 +141,11 @@ export interface User { created_at: string; username: string; - organization_membership: ReverseNavigationResource; - user_application_membership: ReverseNavigationResource; - team_membership: ReverseNavigationResource; - has_direct_access_to__application: ReverseNavigationResource; - user_profile: ReverseNavigationResource; + organization_membership?: ReverseNavigationResource; + user_application_membership?: ReverseNavigationResource; + team_membership?: ReverseNavigationResource; + has_direct_access_to__application?: ReverseNavigationResource; + user_profile?: ReverseNavigationResource; } export interface UserProfile { @@ -180,7 +180,7 @@ export interface OrganizationMembership { organization_membership_role: NavigationResource; effective_seat_role: string; - organization_membership_tag: ReverseNavigationResource; + organization_membership_tag?: ReverseNavigationResource; } export interface TeamMembership { @@ -224,19 +224,19 @@ export interface Application { organization: NavigationResource; should_be_running__release: OptionalNavigationResource; - application_config_variable: ReverseNavigationResource; - application_environment_variable: ReverseNavigationResource; - build_environment_variable: ReverseNavigationResource; - application_tag: ReverseNavigationResource; - owns__device: ReverseNavigationResource; - owns__public_device: ReverseNavigationResource; - owns__release: ReverseNavigationResource; - service: ReverseNavigationResource; - is_depended_on_by__application: ReverseNavigationResource; - is_directly_accessible_by__user: ReverseNavigationResource; - user_application_membership: ReverseNavigationResource; - team_application_access: ReverseNavigationResource; - can_use__application_as_host: ReverseNavigationResource; + application_config_variable?: ReverseNavigationResource; + application_environment_variable?: ReverseNavigationResource; + build_environment_variable?: ReverseNavigationResource; + application_tag?: ReverseNavigationResource; + owns__device?: ReverseNavigationResource; + owns__public_device?: ReverseNavigationResource; + owns__release?: ReverseNavigationResource; + service?: ReverseNavigationResource; + is_depended_on_by__application?: ReverseNavigationResource; + is_directly_accessible_by__user?: ReverseNavigationResource; + user_application_membership?: ReverseNavigationResource; + team_application_access?: ReverseNavigationResource; + can_use__application_as_host?: ReverseNavigationResource; } export interface UserHasDirectAccessToApplication { @@ -379,14 +379,14 @@ export interface Release { belongs_to__application: NavigationResource; /** @deprecated Prefer using the Term Form "release_image" property */ - contains__image: ReverseNavigationResource; - release_image: ReverseNavigationResource; - should_be_running_on__application: ReverseNavigationResource; - is_running_on__device: ReverseNavigationResource; - is_pinned_to__device: ReverseNavigationResource; - should_operate__device: ReverseNavigationResource; - should_manage__device: ReverseNavigationResource; - release_tag: ReverseNavigationResource; + contains__image?: ReverseNavigationResource; + release_image?: ReverseNavigationResource; + should_be_running_on__application?: ReverseNavigationResource; + is_running_on__device?: ReverseNavigationResource; + is_pinned_to__device?: ReverseNavigationResource; + should_operate__device?: ReverseNavigationResource; + should_manage__device?: ReverseNavigationResource; + release_tag?: ReverseNavigationResource; } export interface Device { @@ -460,18 +460,18 @@ export interface Device { /** This is a computed term that works like: `device.is_pinned_on__release ?? device.belongs_to__application[0].should_be_running__release` */ should_be_running__release: OptionalNavigationResource; - device_config_variable: ReverseNavigationResource; - device_environment_variable: ReverseNavigationResource; - device_tag: ReverseNavigationResource; - service_install: ReverseNavigationResource; - image_install: ReverseNavigationResource; + device_config_variable?: ReverseNavigationResource; + device_environment_variable?: ReverseNavigationResource; + device_tag?: ReverseNavigationResource; + service_install?: ReverseNavigationResource; + image_install?: ReverseNavigationResource; } export interface CpuArchitecture { id: number; slug: string; - is_supported_by__device_type: ReverseNavigationResource; + is_supported_by__device_type?: ReverseNavigationResource; } export interface DeviceType { @@ -482,11 +482,11 @@ export interface DeviceType { logo: string | null; contract: Contract | null; belongs_to__device_family: OptionalNavigationResource; - is_default_for__application: ReverseNavigationResource; + is_default_for__application?: ReverseNavigationResource; is_of__cpu_architecture: NavigationResource; - is_accessible_privately_by__organization: ReverseNavigationResource; - describes__device: ReverseNavigationResource; - device_type_alias: ReverseNavigationResource; + is_accessible_privately_by__organization?: ReverseNavigationResource; + describes__device?: ReverseNavigationResource; + device_type_alias?: ReverseNavigationResource; } export interface DeviceTypeAlias { @@ -524,9 +524,9 @@ export interface Service { created_at: string; service_name: string; application: NavigationResource; - is_built_by__image: ReverseNavigationResource; - service_environment_variable: ReverseNavigationResource; - device_service_environment_variable: ReverseNavigationResource; + is_built_by__image?: ReverseNavigationResource; + service_environment_variable?: ReverseNavigationResource; + device_service_environment_variable?: ReverseNavigationResource; } export interface IdentityProvider { @@ -536,8 +536,8 @@ export interface IdentityProvider { issuer: string; certificate: string; requires_signed_authn_response: boolean; - manages__saml_account: ReverseNavigationResource; - identity_provider_membership: ReverseNavigationResource; + manages__saml_account?: ReverseNavigationResource; + identity_provider_membership?: ReverseNavigationResource; } export interface SamlAccount { @@ -571,7 +571,7 @@ export interface Image { dockerfile: string; error_message?: string | null; is_a_build_of__service: NavigationResource; - release_image: ReverseNavigationResource; + release_image?: ReverseNavigationResource; } export interface ReleaseImage { @@ -616,7 +616,7 @@ export interface ServiceInstall { installs__service: NavigationResource; application: NavigationResource; - device_service_environment_variable: ReverseNavigationResource; + device_service_environment_variable?: ReverseNavigationResource; } export interface EnvironmentVariableBase { @@ -723,9 +723,9 @@ export interface Plan { is_valid_from__date: string | null; is_valid_until__date: string | null; - plan_feature: ReverseNavigationResource; - offers__plan_addon: ReverseNavigationResource; - plan__has__discount_code: ReverseNavigationResource; + plan_feature?: ReverseNavigationResource; + offers__plan_addon?: ReverseNavigationResource; + plan__has__discount_code?: ReverseNavigationResource; } export interface PlanAddon { @@ -770,8 +770,8 @@ export interface Subscription { is_for__organization: NavigationResource; is_for__plan: NavigationResource; - subscription_addon_discount: ReverseNavigationResource; - subscription_prepaid_addon: ReverseNavigationResource; + subscription_addon_discount?: ReverseNavigationResource; + subscription_prepaid_addon?: ReverseNavigationResource; } export interface SubscriptionPrepaidAddon { diff --git a/typing_tests/pine-params.ts b/typing_tests/pine-params.ts index b1566d903..e6ae29d78 100644 --- a/typing_tests/pine-params.ts +++ b/typing_tests/pine-params.ts @@ -250,7 +250,7 @@ await (async () => { options: { $select: ['id', 'device_name'], }, - }); + } as const); const checkUndefined: typeof result = undefined; console.log(checkUndefined); diff --git a/typings/pinejs-client-core.d.ts b/typings/pinejs-client-core.d.ts index 734e168f2..cca894339 100644 --- a/typings/pinejs-client-core.d.ts +++ b/typings/pinejs-client-core.d.ts @@ -46,7 +46,14 @@ export type InferAssociatedResourceType = export type SelectableProps = // This allows us to get proper results when T is any/AnyObject, otherwise this returned never PropsOfType> extends StringKeyof - ? StringKeyof + ? StringKeyof extends PropsOfType> + ? // If all of the properties match the reverse navigation resource, return all properties as we assume we're in an `any`/`AnyObject` case + StringKeyof + : // Otherwise return only the properties that are not reverse navigation resources + Exclude< + StringKeyof, + PropsOfType> + > : Exclude< StringKeyof, PropsOfType> @@ -95,14 +102,14 @@ type ExpandedProperty< : never; export type ExpandResultObject = { - [P in Props]: ExpandedProperty; + [P in Props]-?: ExpandedProperty; }; type ExpandResourceExpandObject< T, TResourceExpand extends ResourceExpand, > = { - [P in keyof TResourceExpand]: ExpandedProperty< + [P in keyof TResourceExpand]-?: ExpandedProperty< T, P extends keyof T ? P : never, Exclude diff --git a/typings/utils.d.ts b/typings/utils.d.ts index e18f2697d..cc57a8907 100644 --- a/typings/utils.d.ts +++ b/typings/utils.d.ts @@ -3,11 +3,11 @@ export interface AnyObject { } export type PropsOfType = { - [K in keyof T]: T[K] extends P ? K : never; + [K in keyof T]-?: T[K] extends P ? K : never; }[keyof T]; export type PropsAssignableWithType = { - [K in keyof T]: P extends T[K] ? K : never; + [K in keyof T]-?: P extends T[K] ? K : never; }[keyof T]; // backwards compatible alternative for: Extract