diff --git a/examples/basic/cli/src/OntologyType.ts b/examples/basic/cli/src/OntologyType.ts deleted file mode 100644 index 7a758c27f..000000000 --- a/examples/basic/cli/src/OntologyType.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2023 Palantir Technologies, Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { OsdkObjectFrom } from "@osdk/client"; -import type { Ontology } from "@osdk/examples.basic.sdk"; - -// Demo for if you want concrete types -export interface Employee - extends OsdkObjectFrom -{} -export interface Todo extends OsdkObjectFrom {} diff --git a/examples/basic/cli/src/examples/fetchEmployeePage.ts b/examples/basic/cli/src/examples/fetchEmployeePage.ts index 551d36fc0..a9cf1e2e3 100644 --- a/examples/basic/cli/src/examples/fetchEmployeePage.ts +++ b/examples/basic/cli/src/examples/fetchEmployeePage.ts @@ -14,10 +14,9 @@ * limitations under the License. */ -import type { Client } from "@osdk/client"; -import type { Ontology } from "@osdk/examples.basic.sdk"; +import type { Client, Osdk } from "@osdk/client"; +import type { Employee, Ontology } from "@osdk/examples.basic.sdk"; import { expectType } from "ts-expect"; -import type { Employee } from "../OntologyType.js"; export async function fetchEmployeePage(client: Client) { const result = await client.objectSet("Employee").fetchPageOrThrow(); @@ -52,7 +51,7 @@ export async function fetchEmployeePage(client: Client) { console.log(); } -function printEmployees(employees: Employee[]) { +function printEmployees(employees: Osdk[]) { console.table( employees.map(({ adUsername, businessTitle, employeeNumber }) => ({ adUsername, diff --git a/examples/basic/cli/src/typeChecks.ts b/examples/basic/cli/src/typeChecks.ts index 64495172d..7189e7ef3 100644 --- a/examples/basic/cli/src/typeChecks.ts +++ b/examples/basic/cli/src/typeChecks.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { Client, OsdkObjectFrom, PageResult } from "@osdk/client"; +import type { Client, Osdk, PageResult } from "@osdk/client"; import type { Ontology } from "@osdk/examples.basic.sdk"; import type { TypeOf } from "ts-expect"; import { expectType } from "ts-expect"; @@ -81,7 +81,7 @@ export async function typeChecks(client: Client) { // lead is an employee const lead = await employee.$link.lead.get(); expectType< - TypeOf> + TypeOf> >(true); // lead is an employee but we downselect to just their adUsername @@ -99,7 +99,7 @@ export async function typeChecks(client: Client) { TypeOf< typeof peeps, PageResult< - OsdkObjectFrom< + Osdk< Ontology["objects"]["Employee"], "adUsername" | "employeeNumber" > @@ -117,7 +117,7 @@ export async function typeChecks(client: Client) { expectType< TypeOf< typeof peepById, - OsdkObjectFrom + Osdk > >( true, diff --git a/examples/basic/sdk/src/generatedNoCheck/index.ts b/examples/basic/sdk/src/generatedNoCheck/index.ts index 9a2fc2c7f..ff3b88e0c 100644 --- a/examples/basic/sdk/src/generatedNoCheck/index.ts +++ b/examples/basic/sdk/src/generatedNoCheck/index.ts @@ -1 +1,4 @@ export { Ontology } from './Ontology.js'; +export * from './ontology/actions/index.js'; +export * from './ontology/interfaces.js'; +export * from './ontology/objects.js'; diff --git a/examples/basic/sdk/src/generatedNoCheck/ontology/actions/actionTakesAllParameterTypes.ts b/examples/basic/sdk/src/generatedNoCheck/ontology/actions/actionTakesAllParameterTypes.ts index 966771533..e24f42b5c 100644 --- a/examples/basic/sdk/src/generatedNoCheck/ontology/actions/actionTakesAllParameterTypes.ts +++ b/examples/basic/sdk/src/generatedNoCheck/ontology/actions/actionTakesAllParameterTypes.ts @@ -1,38 +1,38 @@ import type { ActionDefinition, ObjectActionDataType, ObjectSetActionDataType } from '@osdk/api'; import type { ActionReturnTypeForOptions, ApplyActionOptions, NOOP, OsdkActionParameters } from '@osdk/client'; -import type { PersonDef, TodoDef } from '../objects.js'; +import type { Person, Todo } from '../objects.js'; // Represents the definition of the parameters for the action export type ActionDef$actionTakesAllParameterTypes$Params = { objectSet: { - type: ObjectSetActionDataType<'Todo', TodoDef>; multiplicity: false; + type: ObjectSetActionDataType<'Todo', Todo>; nullable: false; }; object: { - type: ObjectActionDataType<'Person', PersonDef>; multiplicity: false; + type: ObjectActionDataType<'Person', Person>; nullable: true; description: 'A person Object'; }; string: { - type: 'string'; multiplicity: false; + type: 'string'; nullable: false; }; 'time-stamp': { - type: 'timestamp'; multiplicity: false; + type: 'timestamp'; nullable: false; }; dateArray: { - type: 'datetime'; multiplicity: true; + type: 'datetime'; nullable: true; }; attachmentArray: { - type: 'attachment'; multiplicity: true; + type: 'attachment'; nullable: false; }; }; diff --git a/examples/basic/sdk/src/generatedNoCheck/ontology/objects/BoundariesUsState.ts b/examples/basic/sdk/src/generatedNoCheck/ontology/objects/BoundariesUsState.ts index e90148e51..c3bb3b5fd 100644 --- a/examples/basic/sdk/src/generatedNoCheck/ontology/objects/BoundariesUsState.ts +++ b/examples/basic/sdk/src/generatedNoCheck/ontology/objects/BoundariesUsState.ts @@ -1,27 +1,16 @@ -import type { ObjectTypeDefinition } from '@osdk/api'; +import type { ObjectTypeDefinition, PropertyDef } from '@osdk/api'; -export interface BoundariesUsStateDef extends ObjectTypeDefinition<'BoundariesUsState'> { - type: 'object'; - apiName: 'BoundariesUsState'; +export interface BoundariesUsState extends ObjectTypeDefinition<'BoundariesUsState', BoundariesUsState> { description: 'Boundaries US State'; primaryKeyType: 'string'; links: {}; properties: { - usState: { - multiplicity: false; - type: 'string'; - nullable: false; - }; - geometry10M: { - multiplicity: false; - description: 'geoshape'; - type: 'geoshape'; - nullable: true; - }; + usState: PropertyDef<'string', 'non-nullable', 'single'>; + geometry10M: PropertyDef<'geoshape', 'nullable', 'single'>; }; } -export const BoundariesUsState: BoundariesUsStateDef = { +export const BoundariesUsState: BoundariesUsState = { type: 'object', apiName: 'BoundariesUsState', description: 'Boundaries US State', diff --git a/examples/basic/sdk/src/generatedNoCheck/ontology/objects/Employee.ts b/examples/basic/sdk/src/generatedNoCheck/ontology/objects/Employee.ts index 48532aac1..761f69c81 100644 --- a/examples/basic/sdk/src/generatedNoCheck/ontology/objects/Employee.ts +++ b/examples/basic/sdk/src/generatedNoCheck/ontology/objects/Employee.ts @@ -1,61 +1,26 @@ -import type { ObjectTypeDefinition, ObjectTypeLinkDefinition } from '@osdk/api'; +import type { ObjectTypeDefinition, ObjectTypeLinkDefinition, PropertyDef } from '@osdk/api'; -export interface EmployeeDef extends ObjectTypeDefinition<'Employee'> { - type: 'object'; - apiName: 'Employee'; +export interface Employee extends ObjectTypeDefinition<'Employee', Employee> { description: 'An employee'; primaryKeyType: 'string'; - links: { lead: ObjectTypeLinkDefinition; peeps: ObjectTypeLinkDefinition }; + links: { + lead: ObjectTypeLinkDefinition; + peeps: ObjectTypeLinkDefinition; + }; properties: { - adUsername: { - multiplicity: false; - type: 'string'; - nullable: false; - }; - locationName: { - multiplicity: false; - type: 'string'; - nullable: true; - }; - locationCity: { - multiplicity: false; - type: 'string'; - nullable: true; - }; - firstFullTimeStartDate: { - multiplicity: false; - type: 'datetime'; - nullable: true; - }; - businessTitle: { - multiplicity: false; - type: 'string'; - nullable: true; - }; - employeeNumber: { - multiplicity: false; - type: 'double'; - nullable: true; - }; - jobProfile: { - multiplicity: false; - type: 'string'; - nullable: true; - }; - locationType: { - multiplicity: false; - type: 'string'; - nullable: true; - }; - favPlace: { - multiplicity: false; - type: 'geopoint'; - nullable: true; - }; + adUsername: PropertyDef<'string', 'non-nullable', 'single'>; + locationName: PropertyDef<'string', 'nullable', 'single'>; + locationCity: PropertyDef<'string', 'nullable', 'single'>; + firstFullTimeStartDate: PropertyDef<'datetime', 'nullable', 'single'>; + businessTitle: PropertyDef<'string', 'nullable', 'single'>; + employeeNumber: PropertyDef<'double', 'nullable', 'single'>; + jobProfile: PropertyDef<'string', 'nullable', 'single'>; + locationType: PropertyDef<'string', 'nullable', 'single'>; + favPlace: PropertyDef<'geopoint', 'nullable', 'single'>; }; } -export const Employee: EmployeeDef = { +export const Employee: Employee = { type: 'object', apiName: 'Employee', description: 'An employee', diff --git a/examples/basic/sdk/src/generatedNoCheck/ontology/objects/ObjectTypeWithAllPropertyTypes.ts b/examples/basic/sdk/src/generatedNoCheck/ontology/objects/ObjectTypeWithAllPropertyTypes.ts index caed925be..4a6b31dfb 100644 --- a/examples/basic/sdk/src/generatedNoCheck/ontology/objects/ObjectTypeWithAllPropertyTypes.ts +++ b/examples/basic/sdk/src/generatedNoCheck/ontology/objects/ObjectTypeWithAllPropertyTypes.ts @@ -1,171 +1,46 @@ -import type { ObjectTypeDefinition } from '@osdk/api'; +import type { ObjectTypeDefinition, PropertyDef } from '@osdk/api'; -export interface ObjectTypeWithAllPropertyTypesDef extends ObjectTypeDefinition<'ObjectTypeWithAllPropertyTypes'> { - type: 'object'; - apiName: 'ObjectTypeWithAllPropertyTypes'; +export interface ObjectTypeWithAllPropertyTypes + extends ObjectTypeDefinition<'ObjectTypeWithAllPropertyTypes', ObjectTypeWithAllPropertyTypes> { description: 'A type with all property types'; primaryKeyType: 'integer'; links: {}; properties: { - id: { - multiplicity: false; - type: 'integer'; - nullable: false; - }; - string: { - multiplicity: false; - type: 'string'; - nullable: true; - }; - boolean: { - multiplicity: false; - type: 'boolean'; - nullable: true; - }; - date: { - multiplicity: false; - type: 'datetime'; - nullable: true; - }; - dateTime: { - multiplicity: false; - type: 'timestamp'; - nullable: true; - }; - decimal: { - multiplicity: false; - type: 'decimal'; - nullable: true; - }; - integer: { - multiplicity: false; - type: 'integer'; - nullable: true; - }; - long: { - multiplicity: false; - type: 'long'; - nullable: true; - }; - short: { - multiplicity: false; - type: 'short'; - nullable: true; - }; - float: { - multiplicity: false; - type: 'float'; - nullable: true; - }; - double: { - multiplicity: false; - type: 'double'; - nullable: true; - }; - byte: { - multiplicity: false; - type: 'byte'; - nullable: true; - }; - attachment: { - multiplicity: false; - type: 'attachment'; - nullable: true; - }; - geoPoint: { - multiplicity: false; - type: 'geopoint'; - nullable: true; - }; - geoShape: { - multiplicity: false; - type: 'geoshape'; - nullable: true; - }; - stringArray: { - multiplicity: true; - type: 'string'; - nullable: true; - }; - booleanArray: { - multiplicity: true; - type: 'boolean'; - nullable: true; - }; - dateArray: { - multiplicity: true; - type: 'datetime'; - nullable: true; - }; - dateTimeArray: { - multiplicity: true; - type: 'timestamp'; - nullable: true; - }; - decimalArray: { - multiplicity: true; - type: 'decimal'; - nullable: true; - }; - integerArray: { - multiplicity: true; - type: 'integer'; - nullable: true; - }; - longArray: { - multiplicity: true; - type: 'long'; - nullable: true; - }; - shortArray: { - multiplicity: true; - type: 'short'; - nullable: true; - }; - floatArray: { - multiplicity: true; - type: 'float'; - nullable: true; - }; - doubleArray: { - multiplicity: true; - type: 'double'; - nullable: true; - }; - byteArray: { - multiplicity: true; - type: 'byte'; - nullable: true; - }; - attachmentArray: { - multiplicity: true; - type: 'attachment'; - nullable: true; - }; - geoPointArray: { - multiplicity: true; - type: 'geopoint'; - nullable: true; - }; - geoShapeArray: { - multiplicity: true; - type: 'geoshape'; - nullable: true; - }; - numericTimeseries: { - multiplicity: false; - type: 'numericTimeseries'; - nullable: true; - }; - stringTimeseries: { - multiplicity: false; - type: 'stringTimeseries'; - nullable: true; - }; + id: PropertyDef<'integer', 'non-nullable', 'single'>; + string: PropertyDef<'string', 'nullable', 'single'>; + boolean: PropertyDef<'boolean', 'nullable', 'single'>; + date: PropertyDef<'datetime', 'nullable', 'single'>; + dateTime: PropertyDef<'timestamp', 'nullable', 'single'>; + decimal: PropertyDef<'decimal', 'nullable', 'single'>; + integer: PropertyDef<'integer', 'nullable', 'single'>; + long: PropertyDef<'long', 'nullable', 'single'>; + short: PropertyDef<'short', 'nullable', 'single'>; + float: PropertyDef<'float', 'nullable', 'single'>; + double: PropertyDef<'double', 'nullable', 'single'>; + byte: PropertyDef<'byte', 'nullable', 'single'>; + attachment: PropertyDef<'attachment', 'nullable', 'single'>; + geoPoint: PropertyDef<'geopoint', 'nullable', 'single'>; + geoShape: PropertyDef<'geoshape', 'nullable', 'single'>; + stringArray: PropertyDef<'string', 'nullable', 'array'>; + booleanArray: PropertyDef<'boolean', 'nullable', 'array'>; + dateArray: PropertyDef<'datetime', 'nullable', 'array'>; + dateTimeArray: PropertyDef<'timestamp', 'nullable', 'array'>; + decimalArray: PropertyDef<'decimal', 'nullable', 'array'>; + integerArray: PropertyDef<'integer', 'nullable', 'array'>; + longArray: PropertyDef<'long', 'nullable', 'array'>; + shortArray: PropertyDef<'short', 'nullable', 'array'>; + floatArray: PropertyDef<'float', 'nullable', 'array'>; + doubleArray: PropertyDef<'double', 'nullable', 'array'>; + byteArray: PropertyDef<'byte', 'nullable', 'array'>; + attachmentArray: PropertyDef<'attachment', 'nullable', 'array'>; + geoPointArray: PropertyDef<'geopoint', 'nullable', 'array'>; + geoShapeArray: PropertyDef<'geoshape', 'nullable', 'array'>; + numericTimeseries: PropertyDef<'numericTimeseries', 'nullable', 'single'>; + stringTimeseries: PropertyDef<'stringTimeseries', 'nullable', 'single'>; }; } -export const ObjectTypeWithAllPropertyTypes: ObjectTypeWithAllPropertyTypesDef = { +export const ObjectTypeWithAllPropertyTypes: ObjectTypeWithAllPropertyTypes = { type: 'object', apiName: 'ObjectTypeWithAllPropertyTypes', description: 'A type with all property types', diff --git a/examples/basic/sdk/src/generatedNoCheck/ontology/objects/Person.ts b/examples/basic/sdk/src/generatedNoCheck/ontology/objects/Person.ts index 5914cfff9..e2e70f10f 100644 --- a/examples/basic/sdk/src/generatedNoCheck/ontology/objects/Person.ts +++ b/examples/basic/sdk/src/generatedNoCheck/ontology/objects/Person.ts @@ -1,22 +1,20 @@ -import type { ObjectTypeDefinition, ObjectTypeLinkDefinition } from '@osdk/api'; +import type { ObjectTypeDefinition, ObjectTypeLinkDefinition, PropertyDef } from '@osdk/api'; -import type { TodoDef } from './Todo.js'; -export interface PersonDef extends ObjectTypeDefinition<'Person'> { - type: 'object'; - apiName: 'Person'; +import type { Todo } from './Todo.js'; + +export interface Person extends ObjectTypeDefinition<'Person', Person> { description: 'A person'; primaryKeyType: 'string'; - links: { Todos: ObjectTypeLinkDefinition; Friends: ObjectTypeLinkDefinition }; + links: { + Todos: ObjectTypeLinkDefinition; + Friends: ObjectTypeLinkDefinition; + }; properties: { - email: { - multiplicity: false; - type: 'string'; - nullable: false; - }; + email: PropertyDef<'string', 'non-nullable', 'single'>; }; } -export const Person: PersonDef = { +export const Person: Person = { type: 'object', apiName: 'Person', description: 'A person', diff --git a/examples/basic/sdk/src/generatedNoCheck/ontology/objects/Todo.ts b/examples/basic/sdk/src/generatedNoCheck/ontology/objects/Todo.ts index a43e71f61..406c8050e 100644 --- a/examples/basic/sdk/src/generatedNoCheck/ontology/objects/Todo.ts +++ b/examples/basic/sdk/src/generatedNoCheck/ontology/objects/Todo.ts @@ -1,43 +1,23 @@ -import type { ObjectTypeDefinition, ObjectTypeLinkDefinition } from '@osdk/api'; +import type { ObjectTypeDefinition, ObjectTypeLinkDefinition, PropertyDef } from '@osdk/api'; -import type { PersonDef } from './Person.js'; -export interface TodoDef extends ObjectTypeDefinition<'Todo'> { - type: 'object'; - apiName: 'Todo'; +import type { Person } from './Person.js'; + +export interface Todo extends ObjectTypeDefinition<'Todo', Todo> { description: 'Its a todo item.'; primaryKeyType: 'integer'; - links: { Assignee: ObjectTypeLinkDefinition }; + links: { + Assignee: ObjectTypeLinkDefinition; + }; properties: { - id: { - multiplicity: false; - type: 'integer'; - nullable: false; - }; - body: { - multiplicity: false; - description: 'The text of the todo'; - type: 'string'; - nullable: true; - }; - text: { - multiplicity: false; - type: 'string'; - nullable: true; - }; - priority: { - multiplicity: false; - type: 'integer'; - nullable: true; - }; - complete: { - multiplicity: false; - type: 'boolean'; - nullable: true; - }; + id: PropertyDef<'integer', 'non-nullable', 'single'>; + body: PropertyDef<'string', 'nullable', 'single'>; + text: PropertyDef<'string', 'nullable', 'single'>; + priority: PropertyDef<'integer', 'nullable', 'single'>; + complete: PropertyDef<'boolean', 'nullable', 'single'>; }; } -export const Todo: TodoDef = { +export const Todo: Todo = { type: 'object', apiName: 'Todo', description: 'Its a todo item.', diff --git a/examples/basic/sdk/src/generatedNoCheck/ontology/objects/WeatherStation.ts b/examples/basic/sdk/src/generatedNoCheck/ontology/objects/WeatherStation.ts index c5958dfff..7a31dfb84 100644 --- a/examples/basic/sdk/src/generatedNoCheck/ontology/objects/WeatherStation.ts +++ b/examples/basic/sdk/src/generatedNoCheck/ontology/objects/WeatherStation.ts @@ -1,27 +1,16 @@ -import type { ObjectTypeDefinition } from '@osdk/api'; +import type { ObjectTypeDefinition, PropertyDef } from '@osdk/api'; -export interface WeatherStationDef extends ObjectTypeDefinition<'WeatherStation'> { - type: 'object'; - apiName: 'WeatherStation'; +export interface WeatherStation extends ObjectTypeDefinition<'WeatherStation', WeatherStation> { description: 'Weather Station'; primaryKeyType: 'string'; links: {}; properties: { - stationId: { - multiplicity: false; - type: 'string'; - nullable: false; - }; - geohash: { - multiplicity: false; - description: 'geopoint'; - type: 'geopoint'; - nullable: true; - }; + stationId: PropertyDef<'string', 'non-nullable', 'single'>; + geohash: PropertyDef<'geopoint', 'nullable', 'single'>; }; } -export const WeatherStation: WeatherStationDef = { +export const WeatherStation: WeatherStation = { type: 'object', apiName: 'WeatherStation', description: 'Weather Station', diff --git a/examples/one_dot_one/src/generatedNoCheck/ontology/objects/ObjectTypeWithAllPropertyTypes.ts b/examples/one_dot_one/src/generatedNoCheck/ontology/objects/ObjectTypeWithAllPropertyTypes.ts index 163a3cb79..637a47a56 100644 --- a/examples/one_dot_one/src/generatedNoCheck/ontology/objects/ObjectTypeWithAllPropertyTypes.ts +++ b/examples/one_dot_one/src/generatedNoCheck/ontology/objects/ObjectTypeWithAllPropertyTypes.ts @@ -48,7 +48,8 @@ export interface ObjectTypeWithAllPropertyTypes extends OntologyObject { readonly stringTimeseries: TimeSeries | undefined; } -export interface ObjectTypeWithAllPropertyTypesDef extends ObjectTypeDefinition<'ObjectTypeWithAllPropertyTypes'> { +export interface ObjectTypeWithAllPropertyTypesDef + extends ObjectTypeDefinition<'ObjectTypeWithAllPropertyTypes', ObjectTypeWithAllPropertyTypes> { type: 'object'; apiName: 'ObjectTypeWithAllPropertyTypes'; description: 'A type with all property types'; diff --git a/examples/one_dot_one/src/generatedNoCheck/ontology/objects/Person.ts b/examples/one_dot_one/src/generatedNoCheck/ontology/objects/Person.ts index 13bdc97e0..3cdd88380 100644 --- a/examples/one_dot_one/src/generatedNoCheck/ontology/objects/Person.ts +++ b/examples/one_dot_one/src/generatedNoCheck/ontology/objects/Person.ts @@ -14,12 +14,16 @@ export interface Person extends OntologyObject { } import type { TodoDef } from './Todo'; -export interface PersonDef extends ObjectTypeDefinition<'Person'> { + +export interface PersonDef extends ObjectTypeDefinition<'Person', Person> { type: 'object'; apiName: 'Person'; description: 'A person'; primaryKeyType: 'string'; - links: { Todos: ObjectTypeLinkDefinition; Friends: ObjectTypeLinkDefinition }; + links: { + Todos: ObjectTypeLinkDefinition; + Friends: ObjectTypeLinkDefinition; + }; properties: { email: { multiplicity: false; diff --git a/examples/one_dot_one/src/generatedNoCheck/ontology/objects/Todo.ts b/examples/one_dot_one/src/generatedNoCheck/ontology/objects/Todo.ts index e6c96561e..5f849ebea 100644 --- a/examples/one_dot_one/src/generatedNoCheck/ontology/objects/Todo.ts +++ b/examples/one_dot_one/src/generatedNoCheck/ontology/objects/Todo.ts @@ -18,12 +18,15 @@ export interface Todo extends OntologyObject { } import type { PersonDef } from './Person'; -export interface TodoDef extends ObjectTypeDefinition<'Todo'> { + +export interface TodoDef extends ObjectTypeDefinition<'Todo', Todo> { type: 'object'; apiName: 'Todo'; description: 'Its a todo item.'; primaryKeyType: 'integer'; - links: { Assignee: ObjectTypeLinkDefinition }; + links: { + Assignee: ObjectTypeLinkDefinition; + }; properties: { id: { multiplicity: false; diff --git a/examples/todoapp/src/generatedNoCheck/ontology/objects/Todo.ts b/examples/todoapp/src/generatedNoCheck/ontology/objects/Todo.ts index 1bfe9ad55..ff79d0296 100644 --- a/examples/todoapp/src/generatedNoCheck/ontology/objects/Todo.ts +++ b/examples/todoapp/src/generatedNoCheck/ontology/objects/Todo.ts @@ -15,7 +15,7 @@ export interface Todo extends OntologyObject { readonly title: string | undefined; } -export interface TodoDef extends ObjectTypeDefinition<'Todo'> { +export interface TodoDef extends ObjectTypeDefinition<'Todo', Todo> { type: 'object'; apiName: 'Todo'; description: 'Its a todo item.'; diff --git a/examples/todoapp/src/generatedNoCheck2/index.ts b/examples/todoapp/src/generatedNoCheck2/index.ts index aab4c9c70..eb6457683 100644 --- a/examples/todoapp/src/generatedNoCheck2/index.ts +++ b/examples/todoapp/src/generatedNoCheck2/index.ts @@ -1 +1,4 @@ export { Ontology } from './Ontology'; +export * from './ontology/actions/index'; +export * from './ontology/interfaces'; +export * from './ontology/objects'; diff --git a/examples/todoapp/src/generatedNoCheck2/ontology/actions/completeTodo.ts b/examples/todoapp/src/generatedNoCheck2/ontology/actions/completeTodo.ts index 0bc96a479..13ae050eb 100644 --- a/examples/todoapp/src/generatedNoCheck2/ontology/actions/completeTodo.ts +++ b/examples/todoapp/src/generatedNoCheck2/ontology/actions/completeTodo.ts @@ -1,18 +1,18 @@ import type { ActionDefinition, ObjectActionDataType } from '@osdk/api'; import type { ActionReturnTypeForOptions, ApplyActionOptions, NOOP, OsdkActionParameters } from '@osdk/client'; -import type { TodoDef } from '../objects'; +import type { Todo } from '../objects'; // Represents the definition of the parameters for the action export type ActionDef$completeTodo$Params = { Todo: { - type: ObjectActionDataType<'Todo', TodoDef>; multiplicity: false; + type: ObjectActionDataType<'Todo', Todo>; nullable: false; description: 'A todo Object'; }; is_complete: { - type: 'boolean'; multiplicity: false; + type: 'boolean'; nullable: false; }; }; diff --git a/examples/todoapp/src/generatedNoCheck2/ontology/actions/createTodo.ts b/examples/todoapp/src/generatedNoCheck2/ontology/actions/createTodo.ts index bbbba16ee..9b6dc9343 100644 --- a/examples/todoapp/src/generatedNoCheck2/ontology/actions/createTodo.ts +++ b/examples/todoapp/src/generatedNoCheck2/ontology/actions/createTodo.ts @@ -4,13 +4,13 @@ import type { ActionReturnTypeForOptions, ApplyActionOptions, NOOP, OsdkActionPa // Represents the definition of the parameters for the action export type ActionDef$createTodo$Params = { Todo: { - type: 'string'; multiplicity: false; + type: 'string'; nullable: false; }; is_complete: { - type: 'boolean'; multiplicity: false; + type: 'boolean'; nullable: false; }; }; diff --git a/examples/todoapp/src/generatedNoCheck2/ontology/interfaces.ts b/examples/todoapp/src/generatedNoCheck2/ontology/interfaces.ts index e69de29bb..cb0ff5c3b 100644 --- a/examples/todoapp/src/generatedNoCheck2/ontology/interfaces.ts +++ b/examples/todoapp/src/generatedNoCheck2/ontology/interfaces.ts @@ -0,0 +1 @@ +export {}; diff --git a/examples/todoapp/src/generatedNoCheck2/ontology/objects/Todo.ts b/examples/todoapp/src/generatedNoCheck2/ontology/objects/Todo.ts index b3ae1e1a7..2bc1dbbae 100644 --- a/examples/todoapp/src/generatedNoCheck2/ontology/objects/Todo.ts +++ b/examples/todoapp/src/generatedNoCheck2/ontology/objects/Todo.ts @@ -1,32 +1,17 @@ -import type { ObjectTypeDefinition } from '@osdk/api'; +import type { ObjectTypeDefinition, PropertyDef } from '@osdk/api'; -export interface TodoDef extends ObjectTypeDefinition<'Todo'> { - type: 'object'; - apiName: 'Todo'; +export interface Todo extends ObjectTypeDefinition<'Todo', Todo> { description: 'Its a todo item.'; primaryKeyType: 'string'; links: {}; properties: { - id: { - multiplicity: false; - type: 'string'; - nullable: false; - }; - title: { - multiplicity: false; - description: 'The text of the todo'; - type: 'string'; - nullable: true; - }; - isComplete: { - multiplicity: false; - type: 'boolean'; - nullable: true; - }; + id: PropertyDef<'string', 'non-nullable', 'single'>; + title: PropertyDef<'string', 'nullable', 'single'>; + isComplete: PropertyDef<'boolean', 'nullable', 'single'>; }; } -export const Todo: TodoDef = { +export const Todo: Todo = { type: 'object', apiName: 'Todo', description: 'Its a todo item.', diff --git a/packages/api/changelog/@unreleased/pr-67.v2.yml b/packages/api/changelog/@unreleased/pr-67.v2.yml new file mode 100644 index 000000000..12e67133c --- /dev/null +++ b/packages/api/changelog/@unreleased/pr-67.v2.yml @@ -0,0 +1,5 @@ +type: improvement +improvement: + description: Finish future client types + links: + - https://github.com/palantir/osdk-ts/pull/67 diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index 0c3c514c9..1707857ae 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -52,6 +52,7 @@ export type { ObjectTypePropertyDefinitionFrom2, ObjectTypePropertyDefinitionsFrom, ObjectTypePropertyKeysFrom, + PropertyDef, } from "./ontology/ObjectTypeDefinition"; export type { OntologyDefinition } from "./ontology/OntologyDefinition"; export type { diff --git a/packages/api/src/ontology/InterfaceDefinition.ts b/packages/api/src/ontology/InterfaceDefinition.ts index 22001df2e..7d8247eb6 100644 --- a/packages/api/src/ontology/InterfaceDefinition.ts +++ b/packages/api/src/ontology/InterfaceDefinition.ts @@ -14,10 +14,7 @@ * limitations under the License. */ -import type { - ObjectTypeLinkDefinition, - ObjectTypePropertyDefinition, -} from "./ObjectTypeDefinition"; +import type { ObjectInterfaceBaseDefinition } from "./ObjectTypeDefinition"; import type { OntologyDefinition } from "./OntologyDefinition"; export type InterfaceDefinitionFrom< @@ -50,14 +47,7 @@ export type InterfacePropertyDefinitionFrom< export interface InterfaceDefinition< K extends string, - _L extends string, -> { + N = unknown, +> extends ObjectInterfaceBaseDefinition { type: "interface"; - apiName: K; - description?: string; - properties: Record; - links: Record< - string, - ObjectTypeLinkDefinition - >; } diff --git a/packages/api/src/ontology/ObjectOrInterface.ts b/packages/api/src/ontology/ObjectOrInterface.ts index 8ef66f868..99bfbc243 100644 --- a/packages/api/src/ontology/ObjectOrInterface.ts +++ b/packages/api/src/ontology/ObjectOrInterface.ts @@ -47,7 +47,7 @@ export type ObjectOrInterfacePropertyKeysFrom< : ObjectTypePropertyKeysFrom; export type ObjectOrInterfacePropertyKeysFrom2< - O extends ObjectTypeDefinition | InterfaceDefinition, + O extends ObjectTypeDefinition | InterfaceDefinition, > = keyof O["properties"] & string; export type ObjectOrInterfaceDefinitionFrom< diff --git a/packages/api/src/ontology/ObjectTypeDefinition.ts b/packages/api/src/ontology/ObjectTypeDefinition.ts index cb60cf7b7..da2f36918 100644 --- a/packages/api/src/ontology/ObjectTypeDefinition.ts +++ b/packages/api/src/ontology/ObjectTypeDefinition.ts @@ -47,13 +47,10 @@ export type ObjectTypePropertyDefinitionFrom2< P extends keyof Q["properties"] & string, > = Q["properties"][P]; -export interface ObjectTypeDefinition< - K extends string, -> { - type: "object"; - apiName: K; +export interface ObjectInterfaceBaseDefinition { + type: "object" | "interface"; + apiName: K & { __OsdkType?: N }; description?: string; - primaryKeyType: keyof WirePropertyTypes; properties: Record; links: Record< string, @@ -61,6 +58,14 @@ export interface ObjectTypeDefinition< >; } +export interface ObjectTypeDefinition< + K extends string, + N = unknown, +> extends ObjectInterfaceBaseDefinition { + type: "object"; + primaryKeyType: keyof WirePropertyTypes; +} + export type ObjectTypeLinkKeysFrom< O extends OntologyDefinition, K extends ObjectTypeKeysFrom, @@ -71,10 +76,10 @@ export type ObjectTypeLinkKeysFrom2> = & string; export interface ObjectTypeLinkDefinition< - O extends ObjectTypeDefinition, + O extends ObjectTypeDefinition, M extends boolean, > { - __Mark?: O; + __OsdkLinkTargetType?: O; targetType: O["apiName"]; multiplicity: M; } @@ -99,3 +104,17 @@ export interface ObjectTypePropertyDefinition { multiplicity?: boolean; nullable?: boolean; } + +export type PropertyDef< + T extends keyof WirePropertyTypes, + N extends "nullable" | "non-nullable" = "nullable", + M extends "array" | "single" = "single", + E extends Record = {}, +> = + & { + type: T; + multiplicity: M extends "array" ? true : false; + nullable: N extends "nullable" ? true : false; + } + & E + & ObjectTypePropertyDefinition; diff --git a/packages/client/changelog/@unreleased/pr-67.v2.yml b/packages/client/changelog/@unreleased/pr-67.v2.yml new file mode 100644 index 000000000..12e67133c --- /dev/null +++ b/packages/client/changelog/@unreleased/pr-67.v2.yml @@ -0,0 +1,5 @@ +type: improvement +improvement: + description: Finish future client types + links: + - https://github.com/palantir/osdk-ts/pull/67 diff --git a/packages/client/src/OsdkObjectFrom.ts b/packages/client/src/OsdkObjectFrom.ts index e33fe7e18..a485c6c4f 100644 --- a/packages/client/src/OsdkObjectFrom.ts +++ b/packages/client/src/OsdkObjectFrom.ts @@ -16,8 +16,6 @@ import type { InterfaceDefinition, - InterfacePropertyKeysFrom2, - ObjectOrInterfacePropertyKeysFrom2, ObjectTypeDefinition, WirePropertyTypes, } from "@osdk/api"; @@ -30,20 +28,23 @@ export type OsdkObjectPrimaryKeyType< type OsdkCommonFrom< Q extends ObjectTypeDefinition | InterfaceDefinition, - L extends ObjectOrInterfacePropertyKeysFrom2 = - ObjectOrInterfacePropertyKeysFrom2, + P extends keyof Q["properties"] | "$all" = "$all", R extends boolean = false, > = & { - [P in L]: OsdkObjectPropertyType< - Q["properties"][P] + [ + PP in keyof Q["properties"] as (P extends "$all" ? PP + : PP extends P ? PP + : never) + ]: OsdkObjectPropertyType< + Q["properties"][PP] >; } & { /** @deprecated use $apiName */ - __apiName: Q["apiName"]; + __apiName: Q["apiName"] & { __OsdkType?: Q["apiName"] }; - $apiName: Q["apiName"]; + $apiName: Q["apiName"] & { __OsdkType?: Q["apiName"] }; /** @deprecated use $primaryKey */ __primaryKey: Q extends ObjectTypeDefinition @@ -54,30 +55,64 @@ type OsdkCommonFrom< ? OsdkObjectPrimaryKeyType : unknown; // $uniqueId: string; // will be dynamic + + $link: Q extends ObjectTypeDefinition ? OsdkObjectLinksObject + : never; } & (R extends true ? { $rid: string } : {}); -export type OsdkObjectFrom< - O extends ObjectTypeDefinition, - L extends ObjectOrInterfacePropertyKeysFrom2 = - ObjectOrInterfacePropertyKeysFrom2, - R extends boolean = false, -> = OsdkCommonFrom & { - $link: OsdkObjectLinksObject; -}; // TODO - -export type OsdkInterfaceFrom< - Q extends InterfaceDefinition, - T_PropertyKeys extends InterfacePropertyKeysFrom2 = - InterfacePropertyKeysFrom2, +export type OsdkObjectOrInterfaceFrom< + Q extends ObjectTypeDefinition | InterfaceDefinition, + P extends keyof Q["properties"] | "$all" = "$all", R extends boolean = false, -> = OsdkCommonFrom; +> = Osdk; -export type OsdkObjectOrInterfaceFrom< +export type Osdk< Q extends ObjectTypeDefinition | InterfaceDefinition, - L extends ObjectOrInterfacePropertyKeysFrom2 = - ObjectOrInterfacePropertyKeysFrom2, + P extends keyof Q["properties"] | "$all" = "$all", R extends boolean = false, -> = Q extends InterfaceDefinition ? OsdkInterfaceFrom - : Q extends ObjectTypeDefinition ? OsdkObjectFrom - : never; +> = OsdkCommonFrom; + +// type ObjectShaped = { +// __apiName: string & { __OsdkType?: ObjectTypeDefinition }; +// }; + +// type Q = T extends ObjectTypeDefinition ? number : string; + +// // type Osdk< +// // T extends ObjectShaped, +// // K extends keyof NonNullable["properties"], +// // > = NonNullable extends +// // ObjectTypeDefinition | InterfaceDefinition +// // ? OsdkObjectFrom, K> +// // : never; + +// type Osdk< +// T extends ObjectShaped, +// K extends keyof NonNullable["properties"], +// > = NOOP>; + +// type ObjectShaped = { +// __apiName: T & { __OsdkType?: ObjectTypeDefinition }; +// }; + +// type Q = T extends ObjectTypeDefinition ? L extends string & keyof T["properties"] ? OsdkObjectFrom : string : never; + +// // type Osdk< +// // T extends ObjectShaped, +// // K extends keyof NonNullable["properties"], +// // > = NonNullable extends +// // ObjectTypeDefinition | InterfaceDefinition +// // ? OsdkObjectFrom, K> +// // : never; + +// type Osdk< +// T extends ObjectShaped, +// K extends keyof NonNullable["properties"], +// > = Q, K>; + +// type qq = NOOP>; + +// export interface Employee extends OsdkObjectFrom {} + +// const q: Employee = {} as any; diff --git a/packages/client/src/actions/Actions.ts b/packages/client/src/actions/Actions.ts index e5b860b76..5b9b8f547 100644 --- a/packages/client/src/actions/Actions.ts +++ b/packages/client/src/actions/Actions.ts @@ -27,10 +27,7 @@ import type { } from "@osdk/gateway/types"; import type { ObjectSet } from "../index.js"; import type { Attachment } from "../object/Attachment.js"; -import type { - OsdkObjectFrom, - OsdkObjectPrimaryKeyType, -} from "../OsdkObjectFrom.js"; +import type { Osdk, OsdkObjectPrimaryKeyType } from "../OsdkObjectFrom.js"; import type { NOOP } from "../util/NOOP.js"; import type { NullableProps } from "../util/NullableProps.js"; import type { PartialByNotStrict } from "../util/PartialBy.js"; @@ -50,7 +47,7 @@ interface OverrideWirePropertyTypes extends WirePropertyTypes { type BaseType> = APD["type"] extends ObjectActionDataType ? - | OsdkObjectFrom + | Osdk | OsdkObjectPrimaryKeyType : APD["type"] extends ObjectSetActionDataType ? ObjectSet diff --git a/packages/client/src/definitions/LinkDefinitions.test.ts b/packages/client/src/definitions/LinkDefinitions.test.ts index f41d21672..355122e60 100644 --- a/packages/client/src/definitions/LinkDefinitions.test.ts +++ b/packages/client/src/definitions/LinkDefinitions.test.ts @@ -14,15 +14,27 @@ * limitations under the License. */ +import type { ObjectTypeDefinition } from "@osdk/api"; import { describe, expectTypeOf, it } from "vitest"; +import type { + FetchPageOrThrowArgs, + SelectArg, +} from "../object/fetchPageOrThrow.js"; +import type { Osdk, OsdkObjectPrimaryKeyType } from "../OsdkObjectFrom.js"; +import type { PageResult } from "../PageResult.js"; import type { MockOntology } from "../util/test/mockOntology.js"; import type { - MultitonLinkAccessor, + MultiLinkAccessor, OsdkObjectLinksObject, - SingletonLinkAccessor, + SingleLinkAccessor, } from "./LinkDefinitions.js"; describe("LinkDefinitions", () => { + type Objects = typeof MockOntology["objects"]; + type TaskDef = Objects["Task"]; + type PersonDef = Objects["Person"]; + type TodoDef = Objects["Todo"]; + describe("OsdkObjectLinkObject", () => { it("is correctly absent on types with no links", () => { expectTypeOf< @@ -32,18 +44,133 @@ describe("LinkDefinitions", () => { }); it("populates on types with links", () => { - type Objects = typeof MockOntology["objects"]; - type TaskDef = Objects["Task"]; - type PersonDef = Objects["Person"]; - type TodoDef = Objects["Todo"]; - expectTypeOf>() .toEqualTypeOf< { - Todos: MultitonLinkAccessor; - RP: SingletonLinkAccessor; + Todos: MultiLinkAccessor; + RP: SingleLinkAccessor; } >(); }); + + describe("SingletonLinkAccessor", () => { + it("infers select properly", () => { + // this helper lets us get return types of functions that are generic + class Helper< + T extends ObjectTypeDefinition, + const A extends SelectArg, + > { + constructor(private accessor: SingleLinkAccessor) {} + + public get() { + return this.accessor.get(); + } + } + + // e.g. .lead.get({}); + expectTypeOf["get"]>>>() + .toEqualTypeOf>(); + + // e.g. .lead.get(); + expectTypeOf< + Awaited< + ReturnType>["get"]> + > + >() + .toEqualTypeOf>(); + + // e.g. .lead.get({ select: [] }); + expectTypeOf< + Awaited< + ReturnType["get"]> + > + >() + .toEqualTypeOf>(); + + // e.g. .lead.get({ select: ["name"] }); + expectTypeOf< + Awaited< + ReturnType["get"]> + > + >() + .toEqualTypeOf>(); + }); + }); + + describe("MultitonLinkAccessor", () => { + it("infers select properly", () => { + // this helper lets us get return types of functions that are generic + class Helper< + T extends ObjectTypeDefinition, + const A extends SelectArg, + > { + constructor(private accessor: MultiLinkAccessor) {} + + public fetchPage() { + return this.accessor.fetchPageOrThrow(); + } + + public get(pk: OsdkObjectPrimaryKeyType) { + return this.accessor.get({} as any); + } + } + + // e.g. fetchPageOrThrow({}); + expectTypeOf["fetchPage"]>>>() + .toEqualTypeOf>>(); + + // e.g. fetchPageOrThrow({ select: [] }); + expectTypeOf< + Awaited["fetchPage"]>> + >() + .toEqualTypeOf>>(); + + // e.g. fetchPageOrThrow() + expectTypeOf< + Awaited< + ReturnType< + Helper>["fetchPage"] + > + > + >() + .toEqualTypeOf>>(); + + // e.g. fetchPageOrThrow({ select: ["text"]} + expectTypeOf< + Awaited< + ReturnType["fetchPage"]> + > + >() + .toEqualTypeOf>>(); + + // e.g. .peeps.get("", {}); + expectTypeOf["get"]>>>() + .toEqualTypeOf>(); + + // e.g. .peeps.get(""); + expectTypeOf< + Awaited< + ReturnType>["get"]> + > + >() + .toEqualTypeOf>(); + + // e.g. .peeps.get("", { select: [] }); + expectTypeOf< + Awaited< + ReturnType["get"]> + > + >() + .toEqualTypeOf>(); + + // e.g. .peeps.get("", { select: ["name"] }); + expectTypeOf< + Awaited< + ReturnType["get"]> + > + >() + .toEqualTypeOf>(); + }); + }); }); }); diff --git a/packages/client/src/definitions/LinkDefinitions.ts b/packages/client/src/definitions/LinkDefinitions.ts index f569baebe..2c91ce915 100644 --- a/packages/client/src/definitions/LinkDefinitions.ts +++ b/packages/client/src/definitions/LinkDefinitions.ts @@ -22,12 +22,9 @@ import type { import type { FetchPageOrThrowArgs, SelectArg, + SelectArgToKeys, } from "../object/fetchPageOrThrow.js"; -import type { SelectArgToKeys } from "../object/pageLinkedObjectsOrThrow.js"; -import type { - OsdkObjectFrom, - OsdkObjectPrimaryKeyType, -} from "../OsdkObjectFrom.js"; +import type { Osdk, OsdkObjectPrimaryKeyType } from "../OsdkObjectFrom.js"; import type { PageResult } from "../PageResult.js"; /** The $link container to get from one object type to its linked objects */ @@ -41,24 +38,34 @@ export type OsdkObjectLinksEntry< O extends ObjectTypeDefinition, L extends ObjectTypeLinkKeysFrom2, > = O["links"][L] extends ObjectTypeLinkDefinition ? ( - M extends false ? SingletonLinkAccessor : MultitonLinkAccessor + M extends false ? SingleLinkAccessor : MultiLinkAccessor ) : never; -export interface SingletonLinkAccessor> { +export type SingleLinkReturnType< + T extends ObjectTypeDefinition, + A extends SelectArg, +> = Promise>>; + +export type MultiLinkReturnType< + T extends ObjectTypeDefinition, + A extends SelectArg, +> = Promise>>>; + +export interface SingleLinkAccessor> { /** Load the linked object */ - get: >( + get: >( options?: A, - ) => Promise>>; + ) => SingleLinkReturnType; } -export interface MultitonLinkAccessor> { - get: >( +export interface MultiLinkAccessor> { + get: >( pk: OsdkObjectPrimaryKeyType, options?: A, - ) => Promise>>; + ) => SingleLinkReturnType; fetchPageOrThrow: < - A extends FetchPageOrThrowArgs, - >(options?: A) => Promise>>>; + const A extends FetchPageOrThrowArgs, + >(options?: A) => MultiLinkReturnType; } diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts index 04162dfcb..58d459115 100644 --- a/packages/client/src/index.ts +++ b/packages/client/src/index.ts @@ -23,7 +23,7 @@ export type { PageResult } from "./PageResult.js"; // FIXME: Should this be Objects or Object? export * as Objects from "./object/index.js"; export type { OsdkObject } from "./OsdkObject.js"; -export type { OsdkInterfaceFrom, OsdkObjectFrom } from "./OsdkObjectFrom.js"; +export type { Osdk } from "./OsdkObjectFrom.js"; export { createClientContext } from "@osdk/shared.net"; export { isOk } from "@osdk/shared.net"; diff --git a/packages/client/src/object/convertWireToOsdkObjects.ts b/packages/client/src/object/convertWireToOsdkObjects.ts index 6281d9b1b..268c2f0d2 100644 --- a/packages/client/src/object/convertWireToOsdkObjects.ts +++ b/packages/client/src/object/convertWireToOsdkObjects.ts @@ -60,10 +60,10 @@ function createPrototype< get: >(options?: A) => getLinkedObjectOrThrow( client, - type, + ontology.objects[type], primaryKey, p, - options?.select, + options ?? {}, ), }; } else { @@ -74,22 +74,24 @@ function createPrototype< ) => getLinkedObjectByPkOrThrow( client, - type, + objDef, primaryKey, p, targetPrimaryKey, options, ), fetchPageOrThrow: ( - options?: FetchPageOrThrowArgs< + options: FetchPageOrThrowArgs< O["objects"][typeof linkDef.targetType] - >, + > = {}, ) => - pageLinkedObjectsOrThrow(client, type, primaryKey, p, { - nextPageToken: options?.nextPageToken, - pageSize: options?.pageSize, - select: options?.select, - }), + pageLinkedObjectsOrThrow( + client, + objDef, + primaryKey, + p, + options ?? {}, + ), }; } }, diff --git a/packages/client/src/object/fetchPageOrThrow.test.ts b/packages/client/src/object/fetchPageOrThrow.test.ts new file mode 100644 index 000000000..6f52949fa --- /dev/null +++ b/packages/client/src/object/fetchPageOrThrow.test.ts @@ -0,0 +1,71 @@ +/* + * Copyright 2023 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ObjectTypeDefinition } from "@osdk/api"; +import { describe, expectTypeOf, it } from "vitest"; +import { + fetchPageOrThrow, + type FetchPageOrThrowArgs, + type SelectArg, +} from "../object/fetchPageOrThrow.js"; +import type { Osdk } from "../OsdkObjectFrom.js"; +import type { PageResult } from "../PageResult.js"; +import type { MockOntology } from "../util/test/mockOntology.js"; + +describe(fetchPageOrThrow, () => { + type Objects = typeof MockOntology["objects"]; + type TodoDef = Objects["Todo"]; + + it("infers select properly", () => { + // this helper lets us get return types of functions that are generic + class Helper< + T extends ObjectTypeDefinition, + const A extends SelectArg, + > { + public fetchPage() { + return fetchPageOrThrow({} as any, {} as any, {} as any); + } + } + + // e.g. fetchPageOrThrow({}); + expectTypeOf["fetchPage"]>>>() + .toEqualTypeOf>>(); + + // e.g. fetchPageOrThrow({ select: [] }); + expectTypeOf< + Awaited["fetchPage"]>> + >() + .toEqualTypeOf>>(); + + // e.g. fetchPageOrThrow() + expectTypeOf< + Awaited< + ReturnType< + Helper>["fetchPage"] + > + > + >() + .toEqualTypeOf>>(); + + // e.g. fetchPageOrThrow({ select: ["text"]} + expectTypeOf< + Awaited< + ReturnType["fetchPage"]> + > + >() + .toEqualTypeOf>>(); + }); +}); diff --git a/packages/client/src/object/fetchPageOrThrow.ts b/packages/client/src/object/fetchPageOrThrow.ts index 7aadc318f..28eb2f9e7 100644 --- a/packages/client/src/object/fetchPageOrThrow.ts +++ b/packages/client/src/object/fetchPageOrThrow.ts @@ -17,13 +17,12 @@ import type { ObjectOrInterfaceDefinition, ObjectOrInterfacePropertyKeysFrom2, - ObjectTypeDefinition, } from "@osdk/api"; import { loadObjectSetV2 } from "@osdk/gateway/requests"; import type { LoadObjectSetRequestV2, ObjectSet } from "@osdk/gateway/types"; import { createOpenApiRequest } from "@osdk/shared.net"; import type { ClientContext } from "@osdk/shared.net"; -import type { OsdkObjectFrom } from "../OsdkObjectFrom.js"; +import type { Osdk } from "../OsdkObjectFrom.js"; import type { PageResult } from "../PageResult.js"; import { convertWireToOsdkObjects } from "./convertWireToOsdkObjects.js"; @@ -46,12 +45,19 @@ export interface OrderByArg< }; } +export type SelectArgToKeys< + Q extends ObjectOrInterfaceDefinition, + A extends SelectArg, +> = A extends SelectArg ? "$all" + : A["select"] extends readonly string[] ? A["select"][number] + : "$all"; + export interface FetchPageOrThrowArgs< - Q extends ObjectOrInterfaceDefinition, - L = ObjectOrInterfacePropertyKeysFrom2, + Q extends ObjectOrInterfaceDefinition, + K = ObjectOrInterfacePropertyKeysFrom2, R extends boolean = false, > extends - SelectArg, + SelectArg, OrderByArg> { nextPageToken?: string; @@ -71,10 +77,9 @@ export async function fetchPageOrThrow< }, ): Promise< PageResult< - OsdkObjectFrom< - Q extends ObjectTypeDefinition ? Q : never, - A["select"] extends readonly string[] ? A["select"][number] - : ObjectOrInterfacePropertyKeysFrom2, + Osdk< + Q, + SelectArgToKeys, A["includeRid"] extends true ? true : false > > diff --git a/packages/client/src/object/getLinkedObjectByPkOrThrow.test.ts b/packages/client/src/object/getLinkedObjectByPkOrThrow.test.ts new file mode 100644 index 000000000..9cb199e26 --- /dev/null +++ b/packages/client/src/object/getLinkedObjectByPkOrThrow.test.ts @@ -0,0 +1,73 @@ +/* + * Copyright 2024 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ObjectTypeDefinition } from "@osdk/api"; +import { describe, expectTypeOf, it } from "vitest"; +import type { SelectArg } from "../object/fetchPageOrThrow.js"; +import type { Osdk } from "../OsdkObjectFrom.js"; +import type { MockOntology } from "../util/test/mockOntology.js"; +import { getLinkedObjectByPkOrThrow } from "./getLinkedObjectByPkOrThrow.js"; + +describe(getLinkedObjectByPkOrThrow, () => { + type Objects = typeof MockOntology["objects"]; + type TaskDef = Objects["Task"]; + type PersonDef = Objects["Person"]; + + it("infers select properly", () => { + // this helper lets us get return types of functions that are generic + class Helper< + T extends ObjectTypeDefinition, + const L extends keyof T["links"] & string, + const A extends SelectArg, + > { + public get() { + return getLinkedObjectByPkOrThrow( + {} as any, + {} as any, + {} as any, + {} as any, + {} as any, + ); + } + } + + expectTypeOf["get"]>>>() + .toEqualTypeOf>(); + + expectTypeOf< + Awaited< + ReturnType>["get"]> + > + >() + .toEqualTypeOf>(); + + // e.g. .lead.get({ select: [] }); + expectTypeOf< + Awaited< + ReturnType["get"]> + > + >() + .toEqualTypeOf>(); + + // e.g. .lead.get({ select: ["name"] }); + expectTypeOf< + Awaited< + ReturnType["get"]> + > + >() + .toEqualTypeOf>(); + }); +}); diff --git a/packages/client/src/object/getLinkedObjectByPkOrThrow.ts b/packages/client/src/object/getLinkedObjectByPkOrThrow.ts index 7d5e1e73e..d5b27ccad 100644 --- a/packages/client/src/object/getLinkedObjectByPkOrThrow.ts +++ b/packages/client/src/object/getLinkedObjectByPkOrThrow.ts @@ -14,48 +14,41 @@ * limitations under the License. */ -import type { - ObjectTypeKeysFrom, - ObjectTypeLinkKeysFrom, - ObjectTypeLinkTargetTypeFrom, - OntologyDefinition, -} from "@osdk/api"; +import type { ObjectOrInterfaceDefinition } from "@osdk/api"; import { getLinkedObjectV2 } from "@osdk/gateway/requests"; import type { ClientContext } from "@osdk/shared.net"; import { createOpenApiRequest } from "@osdk/shared.net"; -import type { OsdkObjectFrom } from "../OsdkObjectFrom.js"; +import type { SingleLinkReturnType } from "../definitions/LinkDefinitions.js"; +import type { LinkedType, LinkNames } from "../objectSet/LinkUtils.js"; import { convertWireToOsdkObjects } from "./convertWireToOsdkObjects.js"; import type { SelectArg } from "./fetchPageOrThrow.js"; export async function getLinkedObjectByPkOrThrow< - O extends OntologyDefinition, - T extends ObjectTypeKeysFrom & string, - L extends ObjectTypeLinkKeysFrom & string, - S extends SelectArg> = SelectArg< - ObjectTypeLinkTargetTypeFrom - >, + Q extends ObjectOrInterfaceDefinition, + L extends LinkNames, + const A extends SelectArg, >( - client: ClientContext, - sourceApiName: T, + client: ClientContext, + objectType: Q, primaryKey: any, linkTypeApiName: L, linkedObjectPrimaryKey: any, - options?: S, -) { + selectOpts?: A, +): SingleLinkReturnType, A> { const object = await getLinkedObjectV2( createOpenApiRequest(client.stack, client.fetch), client.ontology.metadata.ontologyApiName, - sourceApiName, + objectType.apiName, primaryKey, linkTypeApiName, linkedObjectPrimaryKey, { - select: (options?.select as string[] | undefined) ?? [], - excludeRid: !options?.includeRid, + select: (selectOpts?.select as string[] | undefined) ?? [], + excludeRid: !selectOpts?.includeRid, }, ); const objects = [object]; convertWireToOsdkObjects(client, objects); - return objects[0] as OsdkObjectFrom; + return objects[0] as any; } diff --git a/packages/client/src/object/getLinkedObjectOrThrow.ts b/packages/client/src/object/getLinkedObjectOrThrow.ts index b8f9f7bf0..66060957e 100644 --- a/packages/client/src/object/getLinkedObjectOrThrow.ts +++ b/packages/client/src/object/getLinkedObjectOrThrow.ts @@ -14,33 +14,30 @@ * limitations under the License. */ -import type { - ObjectTypeKeysFrom, - ObjectTypeLinkKeysFrom2, - OntologyDefinition, -} from "@osdk/api"; +import type { ObjectOrInterfaceDefinition } from "@osdk/api"; import { type ClientContext, PalantirApiError } from "@osdk/shared.net"; +import type { SingleLinkReturnType } from "../definitions/LinkDefinitions.js"; +import type { LinkedType, LinkNames } from "../objectSet/LinkUtils.js"; import type { SelectArg } from "./fetchPageOrThrow.js"; import { pageLinkedObjectsOrThrow } from "./pageLinkedObjectsOrThrow.js"; export async function getLinkedObjectOrThrow< - O extends OntologyDefinition, - T extends ObjectTypeKeysFrom & string, - L extends ObjectTypeLinkKeysFrom2 & string, - S extends SelectArg["select"], + Q extends ObjectOrInterfaceDefinition, + L extends LinkNames, + const A extends SelectArg>, >( - client: ClientContext, - sourceApiName: T, + client: ClientContext, + source: Q, primaryKey: any, linkTypeApiName: L, - select?: S, -) { + options: A, +): SingleLinkReturnType, A> { const result = await pageLinkedObjectsOrThrow( client, - sourceApiName, + source, primaryKey, linkTypeApiName, - { pageSize: 1, select }, + { pageSize: 1, select: options.select }, ); if (result.data.length !== 1 || result.nextPageToken != null) { diff --git a/packages/client/src/object/object.test.ts b/packages/client/src/object/object.test.ts index e68a27b29..9ae6c3931 100644 --- a/packages/client/src/object/object.test.ts +++ b/packages/client/src/object/object.test.ts @@ -56,6 +56,8 @@ describe("OsdkObject", () => { const employee = result.data[0]; expect(employee).toEqual(asV2Object(stubData.employee1)); + employee.startDate; + // it should have the prototype that we assign at hydration time expect(Object.keys(employee.$link.lead)).toBeDefined(); }); diff --git a/packages/client/src/object/pageLinkedObjectsOrThrow.test.ts b/packages/client/src/object/pageLinkedObjectsOrThrow.test.ts new file mode 100644 index 000000000..92cb990a9 --- /dev/null +++ b/packages/client/src/object/pageLinkedObjectsOrThrow.test.ts @@ -0,0 +1,78 @@ +/* + * Copyright 2023 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { ObjectOrInterfaceDefinition } from "@osdk/api"; +import { describe, expectTypeOf, it } from "vitest"; +import { type FetchPageOrThrowArgs } from "../object/fetchPageOrThrow.js"; +import type { Osdk } from "../OsdkObjectFrom.js"; +import type { PageResult } from "../PageResult.js"; +import type { MockOntology } from "../util/test/mockOntology.js"; +import { pageLinkedObjectsOrThrow } from "./pageLinkedObjectsOrThrow.js"; + +describe(pageLinkedObjectsOrThrow, () => { + type Objects = typeof MockOntology["objects"]; + type TaskDef = Objects["Task"]; + type TodoDef = Objects["Todo"]; + + it("infers select properly", () => { + // this helper lets us get return types of functions that are generic + class Helper< + Q extends ObjectOrInterfaceDefinition, + L extends keyof Q["links"] & string, + const A extends FetchPageOrThrowArgs< + NonNullable + >, + > { + public pageLinked() { + return pageLinkedObjectsOrThrow( + {} as any, + {} as any, + {} as any, + {} as any, + {} as any, + ); + } + } + + expectTypeOf< + Awaited["pageLinked"]>> + >() + .toEqualTypeOf>>(); + + expectTypeOf< + Awaited< + ReturnType["pageLinked"]> + > + >() + .toEqualTypeOf>>(); + + expectTypeOf< + Awaited< + ReturnType< + Helper>["pageLinked"] + > + > + >() + .toEqualTypeOf>>(); + + expectTypeOf< + Awaited< + ReturnType["pageLinked"]> + > + >() + .toEqualTypeOf>>(); + }); +}); diff --git a/packages/client/src/object/pageLinkedObjectsOrThrow.ts b/packages/client/src/object/pageLinkedObjectsOrThrow.ts index e5b1cb25e..ab766963d 100644 --- a/packages/client/src/object/pageLinkedObjectsOrThrow.ts +++ b/packages/client/src/object/pageLinkedObjectsOrThrow.ts @@ -14,41 +14,30 @@ * limitations under the License. */ -import type { - ObjectOrInterfacePropertyKeysFrom2, - ObjectTypeKeysFrom, - ObjectTypeLinkKeysFrom2, - OntologyDefinition, -} from "@osdk/api"; +import type { ObjectOrInterfaceDefinition } from "@osdk/api"; import { listLinkedObjectsV2 } from "@osdk/gateway/requests"; import { type ClientContext, createOpenApiRequest } from "@osdk/shared.net"; -import type { OsdkObjectFrom } from "../OsdkObjectFrom.js"; +import type { MultiLinkReturnType } from "../definitions/LinkDefinitions.js"; +import type { LinkedType, LinkNames } from "../objectSet/LinkUtils.js"; import type { PageResult } from "../PageResult.js"; import { convertWireToOsdkObjects } from "./convertWireToOsdkObjects.js"; -import type { FetchPageOrThrowArgs, SelectArg } from "./fetchPageOrThrow.js"; - -export type SelectArgToKeys> = A["select"] extends - readonly string[] ? A["select"][number] - : A extends SelectArg ? ObjectOrInterfacePropertyKeysFrom2 - : never; +import type { FetchPageOrThrowArgs } from "./fetchPageOrThrow.js"; export async function pageLinkedObjectsOrThrow< - O extends OntologyDefinition, - T_SourceTypeKey extends ObjectTypeKeysFrom, - T_LinkApiName extends ObjectTypeLinkKeysFrom2, - Q extends O["objects"][T_SourceTypeKey]["links"][T_LinkApiName]["__Mark"], - const A extends FetchPageOrThrowArgs, + Q extends ObjectOrInterfaceDefinition, + L extends LinkNames, + const A extends FetchPageOrThrowArgs>, >( - client: ClientContext, - sourceApiName: T_SourceTypeKey & string, + client: ClientContext, + source: Q, primaryKey: any, - linkTypeApiName: string, - options: A, -): Promise>>> { + linkTypeApiName: L, + options?: A, +): MultiLinkReturnType, A> { const page = await listLinkedObjectsV2( createOpenApiRequest(client.stack, client.fetch), client.ontology.metadata.ontologyApiName, - sourceApiName, + source.apiName, primaryKey, linkTypeApiName, { @@ -66,6 +55,6 @@ export async function pageLinkedObjectsOrThrow< return { nextPageToken: page.nextPageToken, - data: page.data as OsdkObjectFrom[], - }; + data: page.data as any[], + } as PageResult as any; } diff --git a/packages/client/src/objectSet/LinkTypesFrom.ts b/packages/client/src/objectSet/LinkUtils.ts similarity index 77% rename from packages/client/src/objectSet/LinkTypesFrom.ts rename to packages/client/src/objectSet/LinkUtils.ts index 752e0d5ec..eecaf46ec 100644 --- a/packages/client/src/objectSet/LinkTypesFrom.ts +++ b/packages/client/src/objectSet/LinkUtils.ts @@ -16,6 +16,11 @@ import type { ObjectOrInterfaceDefinition } from "@osdk/api"; -export type LinkTypesFrom< +export type LinkNames = + & keyof Q["links"] + & string; + +export type LinkedType< Q extends ObjectOrInterfaceDefinition, -> = keyof Q["links"]; + L extends keyof Q["links"] & string, +> = NonNullable; diff --git a/packages/client/src/objectSet/ObjectSet.ts b/packages/client/src/objectSet/ObjectSet.ts index e055de3ed..6a6739dba 100644 --- a/packages/client/src/objectSet/ObjectSet.ts +++ b/packages/client/src/objectSet/ObjectSet.ts @@ -23,10 +23,11 @@ import type { } from "@osdk/api"; import type { ObjectSet as WireObjectSet } from "@osdk/gateway/types"; import type { FetchPageOrThrowArgs } from "../object/fetchPageOrThrow.js"; -import type { OsdkObjectOrInterfaceFrom } from "../OsdkObjectFrom.js"; +import type { Osdk } from "../OsdkObjectFrom.js"; import type { PageResult } from "../PageResult.js"; import type { AggregateOpts } from "../query/aggregations/AggregateOpts.js"; import type { AggregationsResults, WhereClause } from "../query/index.js"; +import type { LinkedType, LinkNames } from "./LinkUtils.js"; import type { ObjectSetListener } from "./ObjectSetListener.js"; export type ObjectSet< @@ -42,7 +43,9 @@ export interface BaseObjectSet { >( args?: FetchPageOrThrowArgs, ) => Promise< - PageResult> + ObjectOrInterfacePropertyKeysFrom2 extends L + ? PageResult> + : PageResult> >; // qq: (foo: Q) => ObjectTypePropertyKeysFrom; @@ -50,16 +53,16 @@ export interface BaseObjectSet { // @alpha // fetchPage: >( // args?: FetchPageOrThrowArgs, - // ) => Promise>>>; + // ) => Promise>>>; // @alpha // asyncIter: () => AsyncIterableIterator< - // OsdkObjectFrom> + // Osdk> // >; // @alpha // [Symbol.asyncIterator](): AsyncIterableIterator< - // OsdkObjectFrom> + // Osdk> // >; aggregateOrThrow: >( @@ -87,9 +90,7 @@ export interface BaseObjectSet { ...objectSets: ReadonlyArray> ) => ObjectSet; - pivotTo: ( - type: T & string, - ) => ObjectSet>; + pivotTo: >(type: L) => ObjectSet>; subscribe: (listener: ObjectSetListener) => () => void; } @@ -97,5 +98,5 @@ export interface BaseObjectSet { export type ObjectSetFactory> = < K extends ObjectOrInterfaceKeysFrom, >( - type: K & string, + type: K, ) => ObjectSet>; diff --git a/packages/client/src/objectSet/ObjectSetListenerWebsocket.ts b/packages/client/src/objectSet/ObjectSetListenerWebsocket.ts index b3650e5c5..c739ae23c 100644 --- a/packages/client/src/objectSet/ObjectSetListenerWebsocket.ts +++ b/packages/client/src/objectSet/ObjectSetListenerWebsocket.ts @@ -42,7 +42,7 @@ import { loadOntologyEntities, } from "../generated/ontology-metadata/api/OntologyMetadataService.js"; import { convertWireToOsdkObjects } from "../object/convertWireToOsdkObjects.js"; -import type { OsdkObjectFrom } from "../OsdkObjectFrom.js"; +import type { Osdk } from "../OsdkObjectFrom.js"; import type { ObjectSetListener } from "./ObjectSetListener.js"; import { getObjectSetBaseType, @@ -437,7 +437,7 @@ async function convertFoundryToOsdkObjects< client: ClientContext, ctx: ConjureContext, objects: ReadonlyArray, -): Promise>> { +): Promise>> { const osdkObjects: OntologyObjectV2[] = await Promise.all( objects.map(async object => { const propertyMapping = await getOntologyPropertyMappingForRid( @@ -469,7 +469,7 @@ async function convertFoundryToOsdkObjects< convertWireToOsdkObjects(client, osdkObjects); - return osdkObjects as OsdkObjectFrom[]; + return osdkObjects as Osdk[]; } export type ObjectPropertyMapping = { diff --git a/packages/client/src/objectSet/createObjectSet.ts b/packages/client/src/objectSet/createObjectSet.ts index 96b482305..41bb938ed 100644 --- a/packages/client/src/objectSet/createObjectSet.ts +++ b/packages/client/src/objectSet/createObjectSet.ts @@ -22,14 +22,12 @@ import type { FetchPageOrThrowArgs } from "../object/fetchPageOrThrow.js"; import { aggregateOrThrow, fetchPageOrThrow } from "../object/index.js"; import type { AggregateOpts } from "../query/aggregations/AggregateOpts.js"; import type { AggregationClause, AggregationsResults } from "../query/index.js"; -import type { LinkTypesFrom } from "./LinkTypesFrom.js"; +import type { LinkedType, LinkNames } from "./LinkUtils.js"; import type { BaseObjectSet, ObjectSet } from "./ObjectSet.js"; import { ObjectSetListenerWebsocket } from "./ObjectSetListenerWebsocket.js"; const searchAroundPrefix = "searchAround_"; -export function createObjectSet< - Q extends ObjectOrInterfaceDefinition, ->( +export function createObjectSet( objectType: Q, clientCtx: ClientContext, objectSet: WireObjectSet = { @@ -89,9 +87,9 @@ export function createObjectSet< // throw ""; // }, - pivotTo: function>( - type: T & string, - ): ObjectSet { + pivotTo: function>( + type: L, + ): ObjectSet> { return createSearchAround(type)(); }, @@ -122,7 +120,7 @@ export function createObjectSet< }, }; - function createSearchAround>(link: S & string) { + function createSearchAround>(link: L) { return () => { return createObjectSet( objectType, diff --git a/packages/generator/changelog/@unreleased/pr-67.v2.yml b/packages/generator/changelog/@unreleased/pr-67.v2.yml new file mode 100644 index 000000000..12e67133c --- /dev/null +++ b/packages/generator/changelog/@unreleased/pr-67.v2.yml @@ -0,0 +1,5 @@ +type: improvement +improvement: + description: Finish future client types + links: + - https://github.com/palantir/osdk-ts/pull/67 diff --git a/packages/generator/src/shared/wireActionTypeV2ToSdkActionDefinition.ts b/packages/generator/src/shared/wireActionTypeV2ToSdkActionDefinition.ts index 6aad4ddc5..e7ba951b5 100644 --- a/packages/generator/src/shared/wireActionTypeV2ToSdkActionDefinition.ts +++ b/packages/generator/src/shared/wireActionTypeV2ToSdkActionDefinition.ts @@ -50,32 +50,14 @@ export function wireActionTypeV2ToSdkActionDefinition( function wireActionParameterV2ToSdkParameterDefinition( value: ActionParameterV2, ): ActionParameterDefinition { - switch (value.dataType.type) { - case "string": - case "boolean": - case "object": - case "attachment": - case "date": - case "double": - case "integer": - case "long": - case "objectSet": - case "timestamp": - case "marking": - return { - multiplicity: false, - type: actionPropertyToSdkPropertyDefinition(value.dataType), - nullable: value.required ? false : true, - description: value.description, - }; - case "array": - return { - multiplicity: true, - type: actionPropertyToSdkPropertyDefinition(value.dataType.subType), - nullable: value.required ? false : true, - description: value.description, - }; - } + return { + multiplicity: value.dataType.type === "array", + type: actionPropertyToSdkPropertyDefinition( + value.dataType.type === "array" ? value.dataType.subType : value.dataType, + ), + nullable: !value.required, + description: value.description, + }; } function actionPropertyToSdkPropertyDefinition( diff --git a/packages/generator/src/shared/wireObjectTypeV2ToSdkObjectConst.ts b/packages/generator/src/shared/wireObjectTypeV2ToSdkObjectConst.ts index 84d961deb..db190066d 100644 --- a/packages/generator/src/shared/wireObjectTypeV2ToSdkObjectConst.ts +++ b/packages/generator/src/shared/wireObjectTypeV2ToSdkObjectConst.ts @@ -15,8 +15,14 @@ */ import type { ObjectTypeFullMetadata } from "@osdk/gateway/types"; +import { deleteUndefineds } from "../util/deleteUndefineds"; +import { stringify } from "../util/stringify"; import { wireObjectTypeV2ToSdkObjectDefinition } from "./wireObjectTypeV2ToSdkObjectDefinition"; +export function getObjectDefIdentifier(name: string, v2: boolean) { + return v2 ? name : `${name}Def`; +} + /** @internal */ export function wireObjectTypeV2ToSdkObjectConst( object: ObjectTypeFullMetadata, @@ -27,48 +33,88 @@ export function wireObjectTypeV2ToSdkObjectConst( object.linkTypes.map(a => a.objectTypeApiName), ); - const definition = wireObjectTypeV2ToSdkObjectDefinition( - object, - v2, + const definition = deleteUndefineds( + wireObjectTypeV2ToSdkObjectDefinition( + object, + v2, + ), ); - const imports = Array.from(uniqueLinkTargetTypes).filter(type => - type !== definition.apiName - ).map(type => `import type { ${type}Def } from "./${type}${importExt}";`); + const objectDefIdentifier = getObjectDefIdentifier( + object.objectType.apiName, + v2, + ); - return ` - ${imports.join("\n")} - export interface ${object.objectType.apiName}Def extends ObjectTypeDefinition<"${object.objectType.apiName}"> { - type: "${definition.type}", - apiName: "${definition.apiName}", - ${ - definition.description != null - ? `description: ${JSON.stringify(definition.description)},` - : "" - } - primaryKeyType: ${JSON.stringify(definition.primaryKeyType)}, - links: {${ - Object.entries(definition.links).map( - ( - [linkApiName, definition], - ) => - `${linkApiName}: ObjectTypeLinkDefinition<${definition.targetType}Def, ${definition.multiplicity}>`, - ).join(",\n") + function getV1Types() { + return ` + export interface ${objectDefIdentifier} extends ObjectTypeDefinition<"${object.objectType.apiName}", ${object.objectType.apiName}> { + ${ + stringify(definition, { + links: (_value) => + `{ + ${ + stringify(definition.links, { + "*": (definition) => + `ObjectTypeLinkDefinition<${ + getObjectDefIdentifier(definition.targetType, v2) + }, ${definition.multiplicity}>`, + }) + } + }`, + }) + } + } + `; } - }, - properties: ${JSON.stringify(definition.properties, null, 2)}, + + function getV2Types() { + return ` + export interface ${objectDefIdentifier} extends ObjectTypeDefinition<"${object.objectType.apiName}", ${object.objectType.apiName}> { + ${ + stringify(definition, { + type: () => undefined, + apiName: () => undefined, + links: (_value) => + `{ + ${ + stringify(definition.links, { + "*": (definition) => + `ObjectTypeLinkDefinition<${ + getObjectDefIdentifier(definition.targetType, v2) + }, ${definition.multiplicity}>`, + }) + } + }`, + properties: (_value) => (`{ + ${ + stringify(definition.properties, { + "*": (propertyDefinition) => + `PropertyDef<"${propertyDefinition.type}", "${ + propertyDefinition.nullable ? "nullable" : "non-nullable" + }", "${propertyDefinition.multiplicity ? "array" : "single"}">`, + }) + } + }`), + }) } + } - export const ${object.objectType.apiName}: ${object.objectType.apiName}Def = { - type: "${definition.type}", - apiName: "${definition.apiName}", - ${ - definition.description != null - ? `description: ${JSON.stringify(definition.description)},` - : "" + `; } - primaryKeyType: ${JSON.stringify(definition.primaryKeyType)}, - links: ${JSON.stringify(definition.links, null, 2)}, - properties: ${JSON.stringify(definition.properties, null, 2)}, + + const imports = Array.from(uniqueLinkTargetTypes).filter(type => + type !== definition.apiName + ).map(type => + `import type { ${ + getObjectDefIdentifier(type, v2) + } } from "./${type}${importExt}";` + ); + + return `${imports.join("\n")} + + ${v2 ? getV2Types() : getV1Types()} + + export const ${object.objectType.apiName}: ${objectDefIdentifier} = { + ${stringify(definition)} };`; } diff --git a/packages/generator/src/util/stringify.ts b/packages/generator/src/util/stringify.ts new file mode 100644 index 000000000..6669eab09 --- /dev/null +++ b/packages/generator/src/util/stringify.ts @@ -0,0 +1,74 @@ +/* + * Copyright 2023 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * A function for changing the stringified key/value pairs of an object. + * + * @param value The value of the key/value pair. + * @param defaultValueFormatter The function that would be called if this customizer wasnt used + * @param key The key of the key/value pair. + * @param defaultKeyFormatter The function that would be called if this customizer wasnt used + * + * @returns A string, a tuple of strings, or undefined. + * If a string is returned, it will be used as the value of the key/value pair. + * If a tuple of strings is returned, the first string will be used as the key of the key/value pair + * and the second string will be used as the value of the key/value pair. + * If undefined is returned, the pair will be removed + */ +type Customizer = ( + value: V, + defaultValueFormatter: (value: any) => string, + key: K, + defaultKeyFormatter: (key: string) => string, +) => [string, string] | string | undefined; +const defaultCustomizer: Customizer = ( + value, + defaultValueFormatter, + key, + defaultKeyFormatter, +) => { + return [defaultKeyFormatter(key), defaultValueFormatter(value)]; +}; + +export function stringify>( + obj: T, + customizer: { + [K in keyof T | "*"]?: Customizer; + } = {}, + separator = ",\n", +) { + const defaultKeyFormatter = (key: string) => `${JSON.stringify(key)}`; + const entries: Array = []; + + for (const [key, value] of Object.entries(obj)) { + const res = + (customizer[key as keyof T] ?? customizer["*"] ?? defaultCustomizer)( + value, + (value) => JSON.stringify(value, null, 2), + key as any, + defaultKeyFormatter, + ); + + if (res) { + if (typeof res === "string") { + entries.push(`${defaultKeyFormatter(key)}: ${res}`); + } else { + entries.push(`${res[0]}: ${res[1]}`); + } + } + } + return entries.join(separator); +} diff --git a/packages/generator/src/v1.1/generatePerActionDataFiles.ts b/packages/generator/src/v1.1/generatePerActionDataFiles.ts index 257d4aba9..10df60f9c 100644 --- a/packages/generator/src/v1.1/generatePerActionDataFiles.ts +++ b/packages/generator/src/v1.1/generatePerActionDataFiles.ts @@ -18,15 +18,13 @@ import type { ActionParameterType, ActionTypeV2 } from "@osdk/gateway/types"; import path from "node:path"; import type { MinimalFs } from "../MinimalFs"; import { wireActionTypeV2ToSdkActionDefinition } from "../shared/wireActionTypeV2ToSdkActionDefinition"; +import { getObjectDefIdentifier } from "../shared/wireObjectTypeV2ToSdkObjectConst"; import { deleteUndefineds } from "../util/deleteUndefineds"; +import { stringify } from "../util/stringify"; import { formatTs } from "../util/test/formatTs"; import type { WireOntologyDefinition } from "../WireOntologyDefinition"; import { getDescriptionIfPresent } from "./wireObjectTypeV2ToV1ObjectInterfaceString"; -function stringifyWithoutOuterBraces(obj: any) { - return JSON.stringify(obj, null, 2).replace(/^\{\n/, "").replace(/\n\}$/, ""); -} - export async function generatePerActionDataFiles( ontology: WireOntologyDefinition, fs: MinimalFs, @@ -67,24 +65,27 @@ export async function generatePerActionDataFiles( ${ Object.entries(parameters) .map(([key, value]) => { - const { type, ...remain } = value; - - let q; - - if (typeof type === "string") { - q = JSON.stringify(type); - } else if (type.type === "object") { - q = `ObjectActionDataType<"${type.object}", ${type.object}Def>`; - } else if (type.type === "objectSet") { - q = - `ObjectSetActionDataType<"${type.objectSet}", ${type.objectSet}Def>`; - } - return `"${key}": { - type: ${q}; - ${stringifyWithoutOuterBraces(remain)} - } - `; + ${ + stringify(value, { + description: (value, d) => value ? d(value) : undefined, // trick to remove undefineds + type: (type) => { + if (typeof type === "string") { + return JSON.stringify(type); + } else if (type.type === "object") { + return `ObjectActionDataType<"${type.object}", ${ + getObjectDefIdentifier(type.object, v2) + }>`; + } else if (type.type === "objectSet") { + return `ObjectSetActionDataType<"${type.objectSet}", ${ + getObjectDefIdentifier(type.objectSet, v2) + }>`; + } + return undefined; + }, + }) + } + }`; }) .join(";\n") } @@ -136,8 +137,12 @@ export async function generatePerActionDataFiles( const referencedObjectDefs = new Set(); for (const p of Object.values(action.parameters)) { if (p.dataType.type === "object" || p.dataType.type === "objectSet") { - referencedObjectDefs.add(p.dataType.objectApiName + "Def"); - referencedObjectDefs.add(p.dataType.objectTypeApiName + "Def"); + referencedObjectDefs.add( + getObjectDefIdentifier(p.dataType.objectApiName!, v2), + ); + referencedObjectDefs.add( + getObjectDefIdentifier(p.dataType.objectTypeApiName!, v2), + ); } } diff --git a/packages/generator/src/v1.1/generatePerObjectInterfaceAndDataFiles.ts b/packages/generator/src/v1.1/generatePerObjectInterfaceAndDataFiles.ts index dfd14e324..c4c6ce950 100644 --- a/packages/generator/src/v1.1/generatePerObjectInterfaceAndDataFiles.ts +++ b/packages/generator/src/v1.1/generatePerObjectInterfaceAndDataFiles.ts @@ -35,7 +35,7 @@ export async function generatePerObjectInterfaceAndDataFiles( await fs.writeFile( path.join(outDir, `${object.objectType.apiName}.ts`), await formatTs(` - import type { ObjectTypeDefinition, ObjectTypeLinkDefinition } from "@osdk/api"; + import type { ObjectTypeDefinition, ObjectTypeLinkDefinition, PropertyDef } from "@osdk/api"; ${ wireObjectTypeV2ToObjectInterfaceStringV1( object, diff --git a/packages/generator/src/v2.0/generateClientSdkVersionTwoPointZero.ts b/packages/generator/src/v2.0/generateClientSdkVersionTwoPointZero.ts index 1aaf225c2..97607e67b 100644 --- a/packages/generator/src/v2.0/generateClientSdkVersionTwoPointZero.ts +++ b/packages/generator/src/v2.0/generateClientSdkVersionTwoPointZero.ts @@ -51,6 +51,9 @@ export async function generateClientSdkVersionTwoPointZero( await formatTs( ` export { Ontology } from "./Ontology${importExt}"; + export * from "./ontology/actions/index${importExt}"; + export * from "./ontology/objects${importExt}"; + export * from "./ontology/interfaces${importExt}"; `, ), ); @@ -111,19 +114,11 @@ export async function generateClientSdkVersionTwoPointZero( await fs.writeFile( path.join(outDir, "ontology", `objects`, `${name}.ts`), await formatTs(` - - import type { ObjectTypeDefinition, ObjectTypeLinkDefinition } from "@osdk/api"; - - ${wireObjectTypeV2ToSdkObjectConst(obj, importExt, true)} + import type { ObjectTypeDefinition, ObjectTypeLinkDefinition, PropertyDef } from "@osdk/api"; + import { Osdk } from "@osdk/client"; - ${ - /* TODO: FIXME - // wireObjectTypeV2ToObjectDefinitionInterfaceString( - // obj, - // ) - */ - ""} - `), + ${wireObjectTypeV2ToSdkObjectConst(obj, importExt, true)} + `), ); } @@ -199,6 +194,11 @@ async function generateOntologyInterfaces( `export * from "./interfaces/${apiName}${importExt}";` ).join("\n") } + ${ + Object.keys(ontology.interfaceTypes ?? {}).length === 0 + ? "export {}" + : "" + } `), ); } diff --git a/packages/generator/src/v2.0/wireObjectTypeV2ToObjectDefinitionInterfaceString.ts b/packages/generator/src/v2.0/wireObjectTypeV2ToObjectDefinitionInterfaceString.ts deleted file mode 100644 index 054956941..000000000 --- a/packages/generator/src/v2.0/wireObjectTypeV2ToObjectDefinitionInterfaceString.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2023 Palantir Technologies, Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { ObjectTypeV2 } from "@osdk/gateway/types"; - -export function wireObjectTypeV2ToObjectDefinitionInterfaceString( - input: ObjectTypeV2, -) { - return ` - export interface ${input.apiName} extends ObjectTypeDefinition<"${input.apiName}", "${input.apiName}">{ - type: "interface"; - apiName: "${input.apiName}"; - properties: { - ${ - Object.entries(input.properties).sort((a, b) => a[0].localeCompare(b[0])) - .map(([key, value]) => ` - /** - * ${value.description ?? ""} - **/ - ${key}: { - type: "${value.dataType.type}"; - displayName: "${value.displayName ?? key}"; - } - - `) - } - } - } - `; -} diff --git a/packages/legacy-client/changelog/@unreleased/pr-67.v2.yml b/packages/legacy-client/changelog/@unreleased/pr-67.v2.yml new file mode 100644 index 000000000..12e67133c --- /dev/null +++ b/packages/legacy-client/changelog/@unreleased/pr-67.v2.yml @@ -0,0 +1,5 @@ +type: improvement +improvement: + description: Finish future client types + links: + - https://github.com/palantir/osdk-ts/pull/67 diff --git a/packages/shared.test/changelog/@unreleased/pr-67.v2.yml b/packages/shared.test/changelog/@unreleased/pr-67.v2.yml new file mode 100644 index 000000000..12e67133c --- /dev/null +++ b/packages/shared.test/changelog/@unreleased/pr-67.v2.yml @@ -0,0 +1,5 @@ +type: improvement +improvement: + description: Finish future client types + links: + - https://github.com/palantir/osdk-ts/pull/67