Skip to content

Commit

Permalink
Merge pull request #89 from palantir/ea/prototype-dynamic-loading-obj…
Browse files Browse the repository at this point in the history
…ect-defs

Dynamic ontology data loading
  • Loading branch information
ericanderson authored Feb 28, 2024
2 parents 4e8ff21 + 88aeb9a commit 8b0c295
Show file tree
Hide file tree
Showing 54 changed files with 1,109 additions and 267 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
* limitations under the License.
*/

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

export async function fetchAggregationForEmployeesGroupedThin(
clientCtx: ClientContext<Ontology>,
clientCtx: MinimalClient,
) {
const result = await aggregateOrThrow(
clientCtx,
Expand All @@ -46,21 +46,6 @@ export async function fetchAggregationForEmployeesGroupedThin(
result[0].employeeNumber.avg;
result[0].$group.locationType;

// const {action, authorized, lastResultIsValid, loading} = useOsdkAction(client.actions.doFoo);
// isOk(result) && result.value.validation.result;
// await client.ontology.actions.foo({
// ...
// })
// geo types in actions suck
// for (const {
// group,
// values: { employeeNumber },
// } of result) {
// console.log(employeeNumber.avg);
// }
// for (const [group, { employeeNumber }] of result) {
// console.log(employeeNumber.avg);
// }
console.log("fetchAggregationForEmployeesGroupedThin()");
console.log(JSON.stringify(result, undefined, 2));
console.log();
Expand Down
4 changes: 1 addition & 3 deletions examples/basic/cli/src/examples/fetchEmployeePageThin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,14 @@
*/

import * as OsdkApi from "@osdk/client";
import type { ClientContext } from "@osdk/client";
import { Objects } from "@osdk/client";
import { fetchPageOrThrow } from "@osdk/client/objects";
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>,
clientCtx: OsdkApi.MinimalClient,
) {
let result = await fetchPageOrThrow(clientCtx, Employee, {
select: ["adUsername", "businessTitle", "employeeNumber"],
Expand Down
50 changes: 46 additions & 4 deletions examples/basic/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
* limitations under the License.
*/

import { createClient, createClientContext } from "@osdk/client";
import { createClient, createMinimalClient } from "@osdk/client";
import {
assignEmployee1,
BoundariesUsState,
Employee,
Ontology,
Venture,
WeatherStation,
} from "@osdk/examples.basic.sdk";
import invariant from "tiny-invariant";
Expand Down Expand Up @@ -51,11 +54,10 @@ export const client = createClient(
() => process.env.FOUNDRY_USER_TOKEN!,
);

export const clientCtx = createClientContext(
Ontology,
export const clientCtx = createMinimalClient(
Ontology.metadata,
process.env.FOUNDRY_STACK,
() => process.env.FOUNDRY_USER_TOKEN!,
`typescript-sdk/dev osdk-cli/dev`,
);

const runOld = false;
Expand Down Expand Up @@ -181,6 +183,8 @@ async function runTests() {

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

await checkLinksAndActionsForVentures();

const testAggregateCountNoGroup = await client.objects.BoundariesUsState
.aggregateOrThrow({
select: { $count: true, latitude: ["min", "max", "avg"] },
Expand Down Expand Up @@ -215,3 +219,41 @@ async function runTests() {
}

runTests();

async function checkLinksAndActionsForVentures() {
let didValidateOnce = false;
for await (const emp of client(Employee).asyncIter()) {
console.log(`Employee: ${emp.id}`);

// TODO: when links are objectsets switch to asyncIter
const { data: ventures } = await emp.$link.ventures
.fetchPageOrThrow();

for (const venture of ventures) {
console.log(` - Venture: ${venture.ventureId} ${venture.ventureName}`);
}

if (ventures.length === 0) {
console.log(" - No ventures. ");

if (!didValidateOnce) {
console.log(" - Validating assignEmployee1");
didValidateOnce = true;

const { data: [venture] } = await client(Venture).fetchPageOrThrow();

const r = await client(assignEmployee1)({
"employee-1": emp,
"venture-1": venture,
}, {
validateOnly: true,
});

console.log(r);
}
} else if (didValidateOnce) {
// once we are sure a single action can work and we got some ventures we are good here
break;
}
}
}
5 changes: 5 additions & 0 deletions packages/cli/changelog/@unreleased/pr-89.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type: improvement
improvement:
description: Dynamic ontology data loading
links:
- https://github.com/palantir/osdk-ts/pull/89
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
import { createClientContext, createOpenApiRequest } from "@osdk/shared.net";
import { consola } from "consola";
import * as fs from "node:fs";
import { ExitProcessError } from "../../../ExitProcessError.js";
import { YargsCheckError } from "../../../YargsCheckError.js";
import invokeLoginFlow from "../../auth/login/loginFlow.js";
import type { TypescriptGenerateArgs } from "./TypescriptGenerateArgs.js";
Expand All @@ -46,6 +47,8 @@ export default async function handleGenerate(args: TypescriptGenerateArgs) {

if (success) {
consola.info("OSDK Generated!");
} else {
throw new ExitProcessError(1, "Failed to generate the TypeScript SDK");
}
}

Expand Down Expand Up @@ -144,7 +147,12 @@ async function generateClientSdk(
);
}
} catch (e) {
consola.error("OSDK generation failed", (e as Error).message);
consola.error(
"OSDK generation failed",
(e as Error).message,
(e as Error).stack,
);

return false;
}
return true;
Expand Down
5 changes: 5 additions & 0 deletions packages/client/changelog/@unreleased/pr-89.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type: improvement
improvement:
description: Dynamic ontology data loading
links:
- https://github.com/palantir/osdk-ts/pull/89
4 changes: 3 additions & 1 deletion packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@
"dependencies": {
"@osdk/api": "workspace:*",
"@osdk/gateway": "workspace:*",
"@osdk/generator-converters": "workspace:*",
"@osdk/shared.net": "workspace:*",
"conjure-lite": "^0.3.3",
"fast-deep-equal": "^3.1.3",
"fetch-retry": "^5.0.6",
"isomorphic-ws": "^5.0.0",
"tiny-invariant": "^1.3.1",
Expand All @@ -53,7 +55,7 @@
"publishConfig": {
"access": "public"
},
"keywords": [ ],
"keywords": [],
"files": [
"build/types",
"build/js",
Expand Down
19 changes: 12 additions & 7 deletions packages/client/src/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,9 @@ import type { Actions, ActionSignatureFromDef } from "./actions/Actions.js";
import type { BaseObjectSet, 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;

export interface Client<O extends OntologyDefinition<any>>
extends FutureClient
{
/** @deprecated use client(MyType) */
objectSet: <const K extends ObjectOrInterfaceKeysFrom<O>>(
type: K,
Expand All @@ -49,3 +45,12 @@ export interface Client<O extends OntologyDefinition<any>> {
rid: string,
): ObjectSet<ObjectOrInterfaceDefinitionFrom<O, K>>;
}

// Once we migrate everyone off of using the deprecated parts of `Client` we can rename this to `Client`.
export interface FutureClient {
<
Q extends ObjectOrInterfaceDefinition | ActionDefinition<any, any, any>,
>(o: Q): Q extends ObjectOrInterfaceDefinition ? ObjectSet<Q>
: Q extends ActionDefinition<any, any, any> ? ActionSignatureFromDef<Q>
: never;
}
36 changes: 36 additions & 0 deletions packages/client/src/MinimalClientContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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 { ClientContext } from "@osdk/shared.net";
import type { OntologyProvider } from "./ontology/OntologyProvider.js";

/*
* We don't yet know exactly what the client context will look like,
* so for now its a subset of the full ontology shape. This will change.
*/
export interface MinimalClient extends ClientContext<MinimalClientParams> {}

export type MinimalClientParams = {
metadata: {
userAgent: string;
ontologyApiName: string;

/** @deprecated this is only for transitional code. Do not rely on this for production */
ontologyRid: string;
};

provider: OntologyProvider;
};
16 changes: 10 additions & 6 deletions packages/client/src/ObjectSetCreator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import type {
ObjectOrInterfaceKeysFrom,
OntologyDefinition,
} from "@osdk/api";
import type { ClientContext } from "@osdk/shared.net";
import type { Client } from "./Client.js";
import type { BaseObjectSet } from "./objectSet/ObjectSet.js";

Expand All @@ -34,6 +33,9 @@ export type ObjectSetCreator<O extends OntologyDefinition<any>> = {

/**
* Create a proxy for the object set creator.
*
* @deprecated will be removed when we complete switch to full client(Type) syntax
*
* @param client The client to use to create the object sets.
* @returns A proxy for the object set creator.
*/
Expand All @@ -42,27 +44,29 @@ export function createObjectSetCreator<
D extends OntologyDefinition<any>,
>(
client: T,
clientContext: ClientContext<D>,
ontology: D,
) {
return new Proxy(
{},
{
get: (target, p, receiver) => {
if (typeof p === "string") return client.objectSet(p);
if (typeof p === "string") {
return client(ontology.objects[p] ?? ontology.interfaces?.[p]);
}

return undefined;
},

ownKeys(target) {
return Object.keys(clientContext.ontology.objects);
return Object.keys(ontology.objects);
},

getOwnPropertyDescriptor(target, p) {
if (typeof p === "string") {
return {
enumerable: clientContext.ontology.objects[p] != null,
enumerable: ontology.objects[p] != null,
configurable: true,
value: client.objectSet(p),
get: () => client(ontology.objects[p] ?? ontology.interfaces?.[p]),
};
}
},
Expand Down
4 changes: 2 additions & 2 deletions packages/client/src/actions/actions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import type {
ActionValidationResponse,
} from "./Actions.js";
import { ActionValidationError } from "./ActionValidationError.js";
import { createActionInvoker } from "./createActionInvoker.js";
import { createOldActionInvoker } from "./createActionInvoker.js";

describe("actions", () => {
let client: Client<typeof MockOntology>;
Expand All @@ -50,7 +50,7 @@ describe("actions", () => {
apiServer.close();
});

describe(createActionInvoker, () => {
describe(createOldActionInvoker, () => {
it("has an enumerable list of actions", () => {
expect(Object.getOwnPropertyNames(client.actions)).toMatchInlineSnapshot(`
[
Expand Down
4 changes: 2 additions & 2 deletions packages/client/src/actions/applyAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
import type { ActionDefinition } from "@osdk/api";
import { applyActionV2 } from "@osdk/gateway/requests";
import type { DataValue } from "@osdk/gateway/types";
import type { ClientContext } from "@osdk/shared.net";
import { createOpenApiRequest } from "@osdk/shared.net";
import type { MinimalClient } from "../MinimalClientContext.js";
import { toDataValue } from "../util/toDataValue.js";
import type {
ActionEditResponse,
Expand All @@ -39,7 +39,7 @@ export async function applyAction<
AD extends ActionDefinition<any, any>,
Op extends ApplyActionOptions,
>(
client: ClientContext<any>,
client: MinimalClient,
action: AD,
parameters?: OsdkActionParameters<AD["parameters"]>,
options: Op = {} as Op,
Expand Down
Loading

0 comments on commit 8b0c295

Please sign in to comment.