Skip to content

Commit

Permalink
Merge pull request #83 from palantir/ea/add-client-call
Browse files Browse the repository at this point in the history
Add new client invocation syntax
  • Loading branch information
ericanderson authored Feb 21, 2024
2 parents 3e230d0 + 85c2d11 commit 7d5bcef
Show file tree
Hide file tree
Showing 16 changed files with 117 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
*/

import type { Client } from "@osdk/client";
import type { Ontology } from "@osdk/examples.basic.sdk";
import { Employee, type Ontology } from "@osdk/examples.basic.sdk";
import invariant from "tiny-invariant";
import type { TypeOf } from "ts-expect";
import { expectType } from "ts-expect";

export async function fetchAggregationForEmployees(
client: Client<Ontology>,
) {
const result = await client.objectSet("Employee").aggregateOrThrow({
const result = await client(Employee).aggregateOrThrow({
select: {
locationCity: "approximateDistinct",
locationName: "approximateDistinct",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
*/

import type { Client } from "@osdk/client";
import type { Ontology } from "@osdk/examples.basic.sdk";
import { Employee, type Ontology } from "@osdk/examples.basic.sdk";
import invariant from "tiny-invariant";
import type { TypeOf } from "ts-expect";
import { expectType } from "ts-expect";

export async function fetchAggregationForEmployeesGrouped(
client: Client<Ontology>,
) {
const result = await client.objectSet("Employee").aggregateOrThrow({
const result = await client(Employee).aggregateOrThrow({
select: {
locationCity: "approximateDistinct",
locationName: "approximateDistinct",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import type { ClientContext } from "@osdk/client";
import { aggregateOrThrow } from "@osdk/client/objects";
import { Ontology } from "@osdk/examples.basic.sdk";
import { Employee, type Ontology } from "@osdk/examples.basic.sdk";
import invariant from "tiny-invariant";
import type { TypeOf } from "ts-expect";
import { expectType } from "ts-expect";
Expand All @@ -26,7 +26,7 @@ export async function fetchAggregationForEmployeesGroupedThin(
) {
const result = await aggregateOrThrow(
clientCtx,
Ontology.objects.Employee,
Employee,
{
type: "base",
objectType: "Employee",
Expand Down
4 changes: 2 additions & 2 deletions examples/basic/cli/src/examples/fetchEmployeeLead.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
*/

import type { Client } from "@osdk/client";
import type { Ontology } from "@osdk/examples.basic.sdk";
import { Employee, type Ontology } from "@osdk/examples.basic.sdk";
import type { TypeOf } from "ts-expect";
import { expectType } from "ts-expect";

export async function fetchEmployeeLead(
client: Client<Ontology>,
adUsername: string,
) {
const result = await client.objects.Employee.where({
const result = await client(Employee).where({
adUsername,
})
.pivotTo("lead")
Expand Down
5 changes: 3 additions & 2 deletions examples/basic/cli/src/examples/fetchEmployeePage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
*/

import type { Client, Osdk } from "@osdk/client";
import type { Employee, Ontology } from "@osdk/examples.basic.sdk";
import { Employee } from "@osdk/examples.basic.sdk";
import type { Ontology } from "@osdk/examples.basic.sdk";
import { expectType } from "ts-expect";

export async function fetchEmployeePage(client: Client<Ontology>) {
const result = await client.objectSet("Employee").fetchPageOrThrow();
const result = await client(Employee).fetchPageOrThrow();

expectType<string | undefined>(""); // FIXME: this isn't strict enough of a check for below
expectType<string | undefined>(result.data[0].businessTitle);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

import type { Client } from "@osdk/client";
import type { Ontology } from "@osdk/examples.basic.sdk";
import { Employee, type Ontology } from "@osdk/examples.basic.sdk";

/**
* Demonstrates looking up an employee and for fun adds an `AND` and `ne`
Expand All @@ -24,7 +24,7 @@ export async function fetchEmployeePageByAdUsername(
client: Client<Ontology>,
adUsername: string,
) {
const result = await client.objects.Employee.where({
const result = await client(Employee).where({
$and: [{ adUsername }, { employeeNumber: { $ne: 5 } }],
}).fetchPageOrThrow();
// for await (const e of client.objects.Employee.asyncIter()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

import type { Client } from "@osdk/client";
import type { Ontology } from "@osdk/examples.basic.sdk";
import { Employee, type Ontology } from "@osdk/examples.basic.sdk";
import invariant from "tiny-invariant";

/**
Expand All @@ -25,7 +25,7 @@ export async function fetchEmployeePageByAdUsernameAndLimit(
client: Client<Ontology>,
adUsername: string,
) {
const result = await client.objects.Employee.where({
const result = await client(Employee).where({
$and: [
{ adUsername },
{ employeeNumber: { $ne: 5 } },
Expand Down
31 changes: 10 additions & 21 deletions examples/basic/cli/src/examples/fetchEmployeePageThin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ import * as OsdkApi from "@osdk/client";
import type { ClientContext } from "@osdk/client";
import { Objects } from "@osdk/client";
import { fetchPageOrThrow } from "@osdk/client/objects";
import { Ontology } from "@osdk/examples.basic.sdk";
import type { Ontology } from "@osdk/examples.basic.sdk";
import { Employee } from "@osdk/examples.basic.sdk";
import type { TypeOf } from "ts-expect";
import { expectType } from "ts-expect";

export async function fetchEmployeePageThin(
clientCtx: ClientContext<Ontology>,
) {
let result = await fetchPageOrThrow(clientCtx, Ontology.objects.Employee, {
let result = await fetchPageOrThrow(clientCtx, Employee, {
select: ["adUsername", "businessTitle", "employeeNumber"],
});

Expand All @@ -42,29 +43,17 @@ export async function fetchEmployeePageThin(
>(false);

// OR
let result2 = await Objects.fetchPageOrThrow(
clientCtx,
Ontology.objects.Employee,
{
select: ["adUsername", "businessTitle", "employeeNumber"],
},
);
let result2 = await Objects.fetchPageOrThrow(clientCtx, Employee, {
select: ["adUsername", "businessTitle", "employeeNumber"],
});

// or
let result3 = await OsdkApi.Objects.fetchPageOrThrow(
clientCtx,
Ontology.objects.Employee,
{
select: ["adUsername", "businessTitle", "employeeNumber"],
},
);
let result3 = await OsdkApi.Objects.fetchPageOrThrow(clientCtx, Employee, {
select: ["adUsername", "businessTitle", "employeeNumber"],
});

// Quick check to make sure we get everything
let result4 = await fetchPageOrThrow(
clientCtx,
Ontology.objects.Employee,
{},
);
let result4 = await fetchPageOrThrow(clientCtx, Employee, {});

console.log("fetchEmployeePageThin(): ");
console.table(
Expand Down
50 changes: 29 additions & 21 deletions examples/basic/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
*/

import { createClient, createClientContext } from "@osdk/client";
import { Ontology } from "@osdk/examples.basic.sdk";
import {
BoundariesUsState,
Ontology,
WeatherStation,
} from "@osdk/examples.basic.sdk";
import invariant from "tiny-invariant";
import { fetchAggregationForEmployees } from "./examples/fetchAggregationForEmployees.js";
import { fetchAggregationForEmployeesGrouped } from "./examples/fetchAggregationForEmployeesGrouped.js";
Expand Down Expand Up @@ -54,27 +58,31 @@ export const clientCtx = createClientContext(
`typescript-sdk/dev osdk-cli/dev`,
);

const runOld = false;

async function runTests() {
try {
await fetchEmployeePage(client);
await fetchEmployeePageByAdUsername(client, "fish");
await fetchEmployeePageByAdUsernameAndLimit(client, "fish");
await fetchAggregationForEmployees(client);
await fetchAggregationForEmployeesGrouped(client);
await fetchEmployeePageThin(clientCtx);

await fetchAggregationForEmployeesGroupedThin(clientCtx);
await fetchEmployeeLead(client, "bob");

const interfaceImplementationComplete = false;
if (interfaceImplementationComplete) {
const interfaceResults = await client.objects.SimpleInterface
.fetchPageOrThrow();
interfaceResults.data[0].body;
if (runOld) {
await fetchEmployeePage(client);
await fetchEmployeePageByAdUsername(client, "fish");
await fetchEmployeePageByAdUsernameAndLimit(client, "fish");
await fetchAggregationForEmployees(client);
await fetchAggregationForEmployeesGrouped(client);
await fetchEmployeePageThin(clientCtx);

await fetchAggregationForEmployeesGroupedThin(clientCtx);
await fetchEmployeeLead(client, "bob");

const interfaceImplementationComplete = false;
if (interfaceImplementationComplete) {
const interfaceResults = await client.objects.SimpleInterface
.fetchPageOrThrow();
interfaceResults.data[0].body;
}
}

// only works in default ontology
const result = await client.objects.WeatherStation.where({
const result = await client(WeatherStation).where({
geohash: {
$within: {
distance: [1_000, "miles"],
Expand All @@ -86,7 +94,7 @@ async function runTests() {
console.log(result.data[0].geohash);

// drew a polygon that intersects NY, NJ and PA
const intersectResult = await client.objects.BoundariesUsState.where({
const intersectResult = await client(BoundariesUsState).where({
geometry10M: {
$intersects: {
polygon: [
Expand Down Expand Up @@ -120,7 +128,7 @@ async function runTests() {
console.log(intersectResult.data.map(data => data.usState));
console.log(intersectResult.data[0].geometry10M);

const intersectResultGeojson = await client.objects.BoundariesUsState
const intersectResultGeojson = await client(BoundariesUsState)
.where({
$not: {
geometry10M: {
Expand Down Expand Up @@ -159,7 +167,7 @@ async function runTests() {
console.log(intersectResultGeojson.data.map(data => data.usState));

// drew a bbox that intersects NY, NJ and PA
const intersectResultbbox = await client.objects.BoundariesUsState
const intersectResultbbox = await client(BoundariesUsState)
.where({
geometry10M: {
$intersects: [
Expand All @@ -173,7 +181,7 @@ async function runTests() {

console.log(intersectResultbbox.data.map(data => data.usState));

await typeChecks(client);
if (runOld) await typeChecks(client);
} catch (e) {
console.error("Caught an error we did not expect", typeof e);
console.error(e);
Expand Down
11 changes: 6 additions & 5 deletions examples/todoapp/src/useTodos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { foundryClient, foundryClient2 } from "./foundryClient";
import { isOk, ReturnEditsMode, type Result } from "./generatedNoCheck";
import type { Todo } from "./generatedNoCheck/ontology/objects";
import { ActionValidationError } from "@osdk/client";
import * as MyOsdk from "./generatedNoCheck2";

function orThrow<T, E>(result: Result<T, E>) {
if (isOk(result)) {
Expand All @@ -21,7 +22,7 @@ export function useTodos() {
);

useEffect(() => {
const unsubscribe = foundryClient2.objects.Todo.subscribe({
const unsubscribe = foundryClient2(MyOsdk.Todo).subscribe({
onChange(objects) {
// index incoming objects by apiName and then by pk value
const byApiNameByPK = new Map<
Expand Down Expand Up @@ -97,7 +98,7 @@ export function useTodos() {
const actionsV2Ready = true;

if (actionsV2Ready) {
await foundryClient2.actions.completeTodo({
await foundryClient2(MyOsdk.completeTodo)({
is_complete: b,
Todo: todo.__primaryKey,
});
Expand Down Expand Up @@ -126,14 +127,14 @@ export function useTodos() {
[mutate]
);

const createTodo = useCallback(
const createTodoMutator = useCallback(
async (title: string, setError?: (error: string | undefined) => void) => {
await mutate(
async () => {
// Unwrap to get throw behavior on error.
// Don't return because we want to invalidate cache
try {
await foundryClient2.actions.createTodo({
await foundryClient2(MyOsdk.createTodo)({
Todo: title,
is_complete: false,
});
Expand Down Expand Up @@ -181,7 +182,7 @@ export function useTodos() {
error,
isValidating,
toggleComplete,
createTodo,
createTodo: createTodoMutator,
};
}

Expand Down
5 changes: 5 additions & 0 deletions packages/api/changelog/@unreleased/pr-83.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type: feature
feature:
description: Add new client invocation syntax
links:
- https://github.com/palantir/osdk-ts/pull/83
5 changes: 5 additions & 0 deletions packages/client/changelog/@unreleased/pr-83.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type: feature
feature:
description: Add new client invocation syntax
links:
- https://github.com/palantir/osdk-ts/pull/83
13 changes: 12 additions & 1 deletion packages/client/src/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,33 @@
*/

import type {
ActionDefinition,
ObjectOrInterfaceDefinition,
ObjectOrInterfaceDefinitionFrom,
ObjectOrInterfaceKeysFrom,
ObjectTypeKeysFrom,
OntologyDefinition,
} from "@osdk/api";
import type { Actions } from "./actions/Actions.js";
import type { Actions, ActionSignatureFromDef } from "./actions/Actions.js";
import type { ObjectSet } from "./objectSet/ObjectSet.js";
import type { ObjectSetCreator } from "./ObjectSetCreator.js";

export interface Client<O extends OntologyDefinition<any>> {
<
Q extends ObjectOrInterfaceDefinition | ActionDefinition<any, any, any>,
>(o: Q): Q extends ObjectOrInterfaceDefinition ? ObjectSet<Q>
: Q extends ActionDefinition<any, any, any> ? ActionSignatureFromDef<Q>
: never;

/** @deprecated use client(MyType) */
objectSet: <const K extends ObjectOrInterfaceKeysFrom<O>>(
type: K,
) => ObjectSet<ObjectOrInterfaceDefinitionFrom<O, K>>;

/** @deprecated use client(MyType) */
objects: ObjectSetCreator<O>;

/** @deprecated use client(myAction) */
actions: Actions<O>;

__UNSTABLE_preexistingObjectSet<const K extends ObjectTypeKeysFrom<O>>(
Expand Down
11 changes: 7 additions & 4 deletions packages/client/src/actions/Actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

import type {
ActionDefinition,
ActionParameterDefinition,
ObjectActionDataType,
ObjectSetActionDataType,
Expand Down Expand Up @@ -68,11 +69,13 @@ export type OsdkActionParameters<
> = NullableProps<X> extends never ? NotOptionalParams<X>
: PartialByNotStrict<NotOptionalParams<X>, NullableProps<X>>;

export type ActionSignatureFromDef<T extends ActionDefinition<any, any, any>> =
NonNullable<T["__OsdkActionType"]> extends never
? ActionSignature<T["parameters"]>
: NonNullable<T["__OsdkActionType"]>;

export type Actions<O extends OntologyDefinition<any>> = {
[K in keyof O["actions"]]:
NonNullable<O["actions"][K]["__OsdkActionType"]> extends never
? ActionSignature<O["actions"][K]["parameters"]>
: NonNullable<O["actions"][K]["__OsdkActionType"]>;
[K in keyof O["actions"]]: ActionSignatureFromDef<O["actions"][K]>;
};

type ActionParametersDefinition = Record<
Expand Down
Loading

0 comments on commit 7d5bcef

Please sign in to comment.