From c8bcae6bf923a1221031d52e1aea73273068d524 Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Fri, 22 Nov 2024 16:55:33 -0500 Subject: [PATCH] Adds @osdk/react (#1008) * Adds @osdk/react * Make @osdk/react a bit more ergonomic * Use @osdk/react in an example * Remove useCombinedPages until we are ready for it * Empty changeset --- .changeset/six-doors-smoke.md | 2 + .monorepolint.config.mjs | 25 +- examples/example-react-sdk-2.x/package.json | 1 + examples/example-react-sdk-2.x/src/Home.tsx | 32 +++ .../src/createClientAndAuth.ts | 49 ++++ examples/example-react-sdk-2.x/src/main.tsx | 26 +-- examples/example-react-sdk-2.x/src/router.tsx | 18 ++ .../templates/package.json.hbs | 3 +- .../templates/src/Home.tsx.hbs | 32 +++ .../templates/src/createClientAndAuth.ts.hbs | 54 +++++ .../templates/src/main.tsx | 26 +-- .../templates/src/router.tsx | 18 ++ packages/example-generator/src/run.ts | 56 +++-- packages/react/CHANGELOG.md | 19 ++ packages/react/package.json | 65 ++++++ packages/react/src/OsdkContext.ts | 34 +++ packages/react/src/OsdkProvider.tsx | 31 +++ packages/react/src/index.ts | 18 ++ packages/react/src/useOsdkClient.ts | 23 ++ packages/react/src/useOsdkMetadata.ts | 51 ++++ packages/react/test/useOsdkClient.test.tsx | 51 ++++ packages/react/test/useOsdkMetadata.test.tsx | 64 +++++ packages/react/tsconfig.json | 12 + packages/react/tsup.config.js | 23 ++ packages/react/vitest.config.mts | 25 ++ pnpm-lock.yaml | 221 +++++++++++++++--- 26 files changed, 885 insertions(+), 94 deletions(-) create mode 100644 .changeset/six-doors-smoke.md create mode 100644 examples/example-react-sdk-2.x/src/createClientAndAuth.ts create mode 100644 examples/example-react-sdk-2.x/src/router.tsx create mode 100644 packages/create-app.template.react.beta/templates/src/createClientAndAuth.ts.hbs create mode 100644 packages/create-app.template.react.beta/templates/src/router.tsx create mode 100644 packages/react/CHANGELOG.md create mode 100644 packages/react/package.json create mode 100644 packages/react/src/OsdkContext.ts create mode 100644 packages/react/src/OsdkProvider.tsx create mode 100644 packages/react/src/index.ts create mode 100644 packages/react/src/useOsdkClient.ts create mode 100644 packages/react/src/useOsdkMetadata.ts create mode 100644 packages/react/test/useOsdkClient.test.tsx create mode 100644 packages/react/test/useOsdkMetadata.test.tsx create mode 100644 packages/react/tsconfig.json create mode 100644 packages/react/tsup.config.js create mode 100644 packages/react/vitest.config.mts diff --git a/.changeset/six-doors-smoke.md b/.changeset/six-doors-smoke.md new file mode 100644 index 000000000..a845151cc --- /dev/null +++ b/.changeset/six-doors-smoke.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/.monorepolint.config.mjs b/.monorepolint.config.mjs index 675a2edb9..13c6d2701 100644 --- a/.monorepolint.config.mjs +++ b/.monorepolint.config.mjs @@ -78,6 +78,10 @@ const consumerCliPackages = [ "@osdk/foundry-sdk-generator", ]; +const testWithHappyDomPackages = [ + "@osdk/react", +]; + /** * We don't want to allow `workspace:^` in our dependencies because our current release branch * strategy only allows for patch changes in the release branch and minors elsewhere. @@ -278,6 +282,7 @@ const formattedGeneratorHelper = (contents, ext) => async (context) => { * outDir: string * commonjs?: boolean * singlePackageName?: string + * react?: boolean * }} opts * @returns {Parameters[0]["options"]} */ @@ -295,6 +300,7 @@ function getTsconfigOptions(baseTsconfigPath, opts) { : {}), rootDir: "src", outDir: opts.outDir, + ...(opts.react ? { jsx: "react" } : {}), ...( opts.singlePackageName ? { @@ -319,6 +325,7 @@ function getTsconfigOptions(baseTsconfigPath, opts) { * esmOnly?: boolean, * customTsconfigExcludes?: string[], * tsVersion?: typeof LATEST_TYPESCRIPT_DEP | "^4.9.5", + * vitestEnvironment?: "happy-dom", * skipTsconfigReferences?: boolean, * aliasConsola?: boolean * }} options @@ -337,6 +344,7 @@ function standardPackageRules(shared, options) { customTsconfigExcludes: options.customTsconfigExcludes, skipTsconfigReferences: options.skipTsconfigReferences, outDir: "build/esm", + react: options.vitestEnvironment === "happy-dom", }, ), }), @@ -497,7 +505,11 @@ function standardPackageRules(shared, options) { : "" } pool: "forks", - exclude: [...configDefaults.exclude, "**/build/**/*"], + exclude: [...configDefaults.exclude, "**/build/**/*"],${ + options.vitestEnvironment + ? `\n environment: "${options.vitestEnvironment}",` + : "" + } }, }); @@ -594,8 +606,19 @@ NOTE: DO NOT EDIT THIS README BY HAND. It is generated by monorepolint. ...standardPackageRules({ excludePackages: [ ...nonStandardPackages, + ...testWithHappyDomPackages, + ], + }, { + esmOnly: true, + tsVersion: LATEST_TYPESCRIPT_DEP, + }), + + ...standardPackageRules({ + includePackages: [ + ...testWithHappyDomPackages, ], }, { + vitestEnvironment: "happy-dom", esmOnly: true, tsVersion: LATEST_TYPESCRIPT_DEP, }), diff --git a/examples/example-react-sdk-2.x/package.json b/examples/example-react-sdk-2.x/package.json index c149f2b0f..cacb117fb 100644 --- a/examples/example-react-sdk-2.x/package.json +++ b/examples/example-react-sdk-2.x/package.json @@ -19,6 +19,7 @@ "@osdk/client": "workspace:*", "@osdk/e2e.generated.catchall": "workspace:*", "@osdk/oauth": "workspace:*", + "@osdk/react": "workspace:*", "react": "^18", "react-dom": "^18", "react-router-dom": "^6.23.1" diff --git a/examples/example-react-sdk-2.x/src/Home.tsx b/examples/example-react-sdk-2.x/src/Home.tsx index fe5d7358c..1aa5bf473 100644 --- a/examples/example-react-sdk-2.x/src/Home.tsx +++ b/examples/example-react-sdk-2.x/src/Home.tsx @@ -2,7 +2,39 @@ import { $Objects, $Actions, $Queries } from "@osdk/e2e.generated.catchall"; import css from "./Home.module.css"; import Layout from "./Layout"; +// import { useOsdkClient } from "@osdk/react"; +// import React from "react"; +// import { Osdk } from "@osdk/client"; + function Home() { + + // const client = useOsdkClient(); + + // const [objects, setObjects] = React.useState<$Objects.Todo.OsdkInstance[]>(); + // const [isLoading, setIsLoading] = React.useState(true); + + // React.useEffect(() => { + // client($Objects.Todo).fetchPage().then((page) => { + // setObjects(page.data); + // setIsLoading(false); + // }); + // }, []); + + // if (isLoading) { + // return Loading...; + // } else { + // return ( + // + //
    + // {objects?.map((o) => ( + //
  • {o.$primaryKey} - {o.$title}
  • + // ))} + //
+ //
+ // ) + // } + + const objectApiNames = Object.keys($Objects); const actionApiNames = Object.keys($Actions); const queryApiNames = Object.keys($Queries); diff --git a/examples/example-react-sdk-2.x/src/createClientAndAuth.ts b/examples/example-react-sdk-2.x/src/createClientAndAuth.ts new file mode 100644 index 000000000..33a9c325d --- /dev/null +++ b/examples/example-react-sdk-2.x/src/createClientAndAuth.ts @@ -0,0 +1,49 @@ +import "./index.css"; +import type { Client } from "@osdk/client"; +import { createClient } from "@osdk/client"; +import { $ontologyRid } from "@osdk/e2e.generated.catchall"; +import { createPublicOauthClient } from "@osdk/oauth"; + +function checkEnv( + value: string | undefined, + name: string, +): asserts value is string { + if (value == null) { + throw new Error(`Missing environment variable: ${name}`); + } +} + +export default function createClientAndAuth() { + const url = import.meta.env.VITE_FOUNDRY_API_URL; + const clientId = import.meta.env.VITE_FOUNDRY_CLIENT_ID; + const redirectUrl = import.meta.env.VITE_FOUNDRY_REDIRECT_URL; + const scopes = [ + "api:ontologies-read", + "api:ontologies-write", + ]; + + checkEnv(url, "VITE_FOUNDRY_API_URL"); + checkEnv(clientId, "VITE_FOUNDRY_CLIENT_ID"); + checkEnv(redirectUrl, "VITE_FOUNDRY_REDIRECT_URL"); + + const auth = createPublicOauthClient( + clientId, + url, + redirectUrl, + true, + undefined, + window.location.toString(), + scopes, + ); + + /** + * Initialize the client to interact with the Ontology SDK + */ + const client: Client = createClient( + url, + $ontologyRid, + auth, + ); + + return { client, auth } +} diff --git a/examples/example-react-sdk-2.x/src/main.tsx b/examples/example-react-sdk-2.x/src/main.tsx index 382a1b1d0..d2f6e0a50 100644 --- a/examples/example-react-sdk-2.x/src/main.tsx +++ b/examples/example-react-sdk-2.x/src/main.tsx @@ -1,24 +1,14 @@ +import { OsdkProvider } from "@osdk/react"; import ReactDOM from "react-dom/client"; -import { createBrowserRouter, RouterProvider } from "react-router-dom"; -import AuthCallback from "./AuthCallback"; -import Home from "./Home"; +import { RouterProvider } from "react-router-dom"; +import createClientAndAuth from "./createClientAndAuth"; import "./index.css"; +import { router } from "./router"; -const router = createBrowserRouter( - [ - { - path: "/", - element: , - }, - { - // This is the route defined in your application's redirect URL - path: "/auth/callback", - element: , - }, - ], - { basename: import.meta.env.BASE_URL }, -); +const { client } = createClientAndAuth(); ReactDOM.createRoot(document.getElementById("root")!).render( - , + + , + , ); diff --git a/examples/example-react-sdk-2.x/src/router.tsx b/examples/example-react-sdk-2.x/src/router.tsx new file mode 100644 index 000000000..6c8a44677 --- /dev/null +++ b/examples/example-react-sdk-2.x/src/router.tsx @@ -0,0 +1,18 @@ +import { createBrowserRouter } from "react-router-dom"; +import AuthCallback from "./AuthCallback"; +import Home from "./Home"; + +export const router = createBrowserRouter( + [ + { + path: "/", + element: , + }, + { + // This is the route defined in your application's redirect URL + path: "/auth/callback", + element: , + }, + ], + { basename: import.meta.env.BASE_URL }, +); diff --git a/packages/create-app.template.react.beta/templates/package.json.hbs b/packages/create-app.template.react.beta/templates/package.json.hbs index eb9f6f45d..b4f92621d 100644 --- a/packages/create-app.template.react.beta/templates/package.json.hbs +++ b/packages/create-app.template.react.beta/templates/package.json.hbs @@ -14,7 +14,8 @@ "dependencies": { "{{osdkPackage}}": "latest", "@osdk/client": "{{clientVersion}}", - "@osdk/oauth": "^1.0.0" + "@osdk/oauth": "^1.0.0", + "@osdk/react": "^0.2.1" }, "devDependencies": { "@types/node": "latest" diff --git a/packages/create-app.template.react.beta/templates/src/Home.tsx.hbs b/packages/create-app.template.react.beta/templates/src/Home.tsx.hbs index b12ae4f4a..96678239a 100644 --- a/packages/create-app.template.react.beta/templates/src/Home.tsx.hbs +++ b/packages/create-app.template.react.beta/templates/src/Home.tsx.hbs @@ -2,7 +2,39 @@ import { $Objects, $Actions, $Queries } from "{{osdkPackage}}"; import css from "./Home.module.css"; import Layout from "./Layout"; +// import { useOsdkClient } from "@osdk/react"; +// import React from "react"; +// import { Osdk } from "@osdk/client"; + function Home() { + + // const client = useOsdkClient(); + + // const [objects, setObjects] = React.useState<$Objects.Todo.OsdkInstance[]>(); + // const [isLoading, setIsLoading] = React.useState(true); + + // React.useEffect(() => { + // client($Objects.Todo).fetchPage().then((page) => { + // setObjects(page.data); + // setIsLoading(false); + // }); + // }, []); + + // if (isLoading) { + // return Loading...; + // } else { + // return ( + // + //
    + // {objects?.map((o) => ( + //
  • {o.$primaryKey} - {o.$title}
  • + // ))} + //
+ //
+ // ) + // } + + const objectApiNames = Object.keys($Objects); const actionApiNames = Object.keys($Actions); const queryApiNames = Object.keys($Queries); diff --git a/packages/create-app.template.react.beta/templates/src/createClientAndAuth.ts.hbs b/packages/create-app.template.react.beta/templates/src/createClientAndAuth.ts.hbs new file mode 100644 index 000000000..37581715d --- /dev/null +++ b/packages/create-app.template.react.beta/templates/src/createClientAndAuth.ts.hbs @@ -0,0 +1,54 @@ +import "./index.css"; +import type { Client } from "@osdk/client"; +import { createClient } from "@osdk/client"; +import { $ontologyRid } from "@osdk/e2e.generated.catchall"; +import { createPublicOauthClient } from "@osdk/oauth"; + +function checkEnv( + value: string | undefined, + name: string, +): asserts value is string { + if (value == null) { + throw new Error(`Missing environment variable: ${name}`); + } +} + +export default function createClientAndAuth() { + const url = import.meta.env.VITE_FOUNDRY_API_URL; + const clientId = import.meta.env.VITE_FOUNDRY_CLIENT_ID; + const redirectUrl = import.meta.env.VITE_FOUNDRY_REDIRECT_URL; + {{#if scopes}} + const scopes = [ + {{#each scopes}} + "{{this}}", + {{/each}} + ]; + {{/if}} + + checkEnv(url, "VITE_FOUNDRY_API_URL"); + checkEnv(clientId, "VITE_FOUNDRY_CLIENT_ID"); + checkEnv(redirectUrl, "VITE_FOUNDRY_REDIRECT_URL"); + + const auth = createPublicOauthClient( + clientId, + url, + redirectUrl, + {{#if scopes}} + true, + undefined, + window.location.toString(), + scopes, + {{/if}} + ); + + /** + * Initialize the client to interact with the Ontology SDK + */ + const client: Client = createClient( + url, + $ontologyRid, + auth, + ); + + return { client, auth } +} diff --git a/packages/create-app.template.react.beta/templates/src/main.tsx b/packages/create-app.template.react.beta/templates/src/main.tsx index 382a1b1d0..d2f6e0a50 100644 --- a/packages/create-app.template.react.beta/templates/src/main.tsx +++ b/packages/create-app.template.react.beta/templates/src/main.tsx @@ -1,24 +1,14 @@ +import { OsdkProvider } from "@osdk/react"; import ReactDOM from "react-dom/client"; -import { createBrowserRouter, RouterProvider } from "react-router-dom"; -import AuthCallback from "./AuthCallback"; -import Home from "./Home"; +import { RouterProvider } from "react-router-dom"; +import createClientAndAuth from "./createClientAndAuth"; import "./index.css"; +import { router } from "./router"; -const router = createBrowserRouter( - [ - { - path: "/", - element: , - }, - { - // This is the route defined in your application's redirect URL - path: "/auth/callback", - element: , - }, - ], - { basename: import.meta.env.BASE_URL }, -); +const { client } = createClientAndAuth(); ReactDOM.createRoot(document.getElementById("root")!).render( - , + + , + , ); diff --git a/packages/create-app.template.react.beta/templates/src/router.tsx b/packages/create-app.template.react.beta/templates/src/router.tsx new file mode 100644 index 000000000..6c8a44677 --- /dev/null +++ b/packages/create-app.template.react.beta/templates/src/router.tsx @@ -0,0 +1,18 @@ +import { createBrowserRouter } from "react-router-dom"; +import AuthCallback from "./AuthCallback"; +import Home from "./Home"; + +export const router = createBrowserRouter( + [ + { + path: "/", + element: , + }, + { + // This is the route defined in your application's redirect URL + path: "/auth/callback", + element: , + }, + ], + { basename: import.meta.env.BASE_URL }, +); diff --git a/packages/example-generator/src/run.ts b/packages/example-generator/src/run.ts index 8ddbb9bd6..1050a98ff 100644 --- a/packages/example-generator/src/run.ts +++ b/packages/example-generator/src/run.ts @@ -255,29 +255,39 @@ const UPDATE_PACKAGE_JSON: Mutator = { filePattern: "package.json", mutate: (template, content, sdkVersion) => ({ type: "modify", - newContent: content.replace( - // Use locally generated SDK in the monorepo - "\"@osdk/e2e.generated.1.1.x\": \"latest\"", - "\"@osdk/e2e.generated.1.1.x\": \"workspace:*\"", - ).replace( - // Use locally generated SDK in the monorepo - "\"@osdk/e2e.generated.catchall\": \"latest\"", - "\"@osdk/e2e.generated.catchall\": \"workspace:*\"", - ).replace( - // Use locally generated SDK in the monorepo - /"@osdk\/client": "[\^~].*?"/, - `"@osdk/client": "workspace:*"`, - ).replace( - // Use locally generated SDK in the monorepo - /"@osdk\/oauth": "\^.*?"/, - `"@osdk/oauth": "workspace:*"`, - ).replace( - // Follow monorepo package naming convention - `"name": "${sdkVersionedTemplateExampleId(template, sdkVersion)}"`, - `"name": "@osdk/examples.${ - sdkVersionedTemplateCanonicalId(template, sdkVersion) - }"`, - ), + newContent: content + .replace( + // Use locally generated SDK in the monorepo + "\"@osdk/e2e.generated.1.1.x\": \"latest\"", + "\"@osdk/e2e.generated.1.1.x\": \"workspace:*\"", + ) + .replace( + // Use locally generated SDK in the monorepo + "\"@osdk/e2e.generated.catchall\": \"latest\"", + "\"@osdk/e2e.generated.catchall\": \"workspace:*\"", + ) + .replace( + // Use locally generated SDK in the monorepo + /"@osdk\/client": "[\^~].*?"/, + `"@osdk/client": "workspace:*"`, + ) + .replace( + // Use locally generated SDK in the monorepo + /"@osdk\/react": "[\^~].*?"/, + `"@osdk/react": "workspace:*"`, + ) + .replace( + // Use locally generated SDK in the monorepo + /"@osdk\/oauth": "\^.*?"/, + `"@osdk/oauth": "workspace:*"`, + ) + .replace( + // Follow monorepo package naming convention + `"name": "${sdkVersionedTemplateExampleId(template, sdkVersion)}"`, + `"name": "@osdk/examples.${ + sdkVersionedTemplateCanonicalId(template, sdkVersion) + }"`, + ), }), }; diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md new file mode 100644 index 000000000..da293c8de --- /dev/null +++ b/packages/react/CHANGELOG.md @@ -0,0 +1,19 @@ +# @osdkkit/react + +## 0.2.1 + +### Patch Changes + +- 0fec606: Code properly compiles under isolatedDeclarations + +## 0.2.0 + +### Minor Changes + +- 03be047: Introduce useOsdkMetadata() + +## 0.1.0 + +### Minor Changes + +- 6a6444f: Removes false browser entry from exports diff --git a/packages/react/package.json b/packages/react/package.json new file mode 100644 index 000000000..bec0c3ff9 --- /dev/null +++ b/packages/react/package.json @@ -0,0 +1,65 @@ +{ + "name": "@osdk/react", + "version": "0.2.1", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "https://github.com/palantir/osdk-ts.git" + }, + "exports": { + ".": { + "browser": "./build/browser/index.js", + "import": "./build/esm/index.js", + "default": "./build/browser/index.js" + }, + "./*": { + "browser": "./build/browser/public/*.js", + "import": "./build/esm/public/*.js", + "default": "./build/browser/public/*.js" + } + }, + "scripts": { + "check-attw": "monorepo.tool.attw esm", + "check-spelling": "cspell --quiet .", + "clean": "rm -rf lib dist types build tsconfig.tsbuildinfo", + "fix-lint": "eslint . --fix && dprint fmt --config $(find-up dprint.json)", + "lint": "eslint . && dprint check --config $(find-up dprint.json)", + "test": "vitest run", + "transpile": "monorepo.tool.transpile" + }, + "peerDependencies": { + "@osdk/api": "^2.0.9", + "@osdk/client": "^2.0.9", + "@types/react": "^18", + "react": "^17 || ^18", + "react-dom": "^17 || ^18" + }, + "devDependencies": { + "@osdk/api": "workspace:*", + "@osdk/client": "workspace:*", + "@osdk/monorepo.api-extractor": "workspace:~", + "@osdk/monorepo.tsconfig": "workspace:~", + "@osdk/monorepo.tsup": "workspace:~", + "@testing-library/react": "^16.0.1", + "@types/react": "^18.3.12", + "happy-dom": "^15.7.4", + "p-defer": "^4.0.1", + "react": "^18.0.0", + "typescript": "~5.5.4" + }, + "publishConfig": { + "access": "public" + }, + "files": [ + "build/cjs", + "build/esm", + "build/browser", + "CHANGELOG.md", + "package.json", + "templates", + "*.d.ts" + ], + "module": "./build/esm/index.js", + "types": "./build/esm/index.d.ts", + "type": "module" +} diff --git a/packages/react/src/OsdkContext.ts b/packages/react/src/OsdkContext.ts new file mode 100644 index 000000000..fd2ae9940 --- /dev/null +++ b/packages/react/src/OsdkContext.ts @@ -0,0 +1,34 @@ +/* + * 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 { Client } from "@osdk/client"; +import React from "react"; + +function fakeClientFn(..._args: any[]) { + throw new Error( + "This is not a real client. Did you forget to ?", + ); +} + +const fakeClient = Object.assign(fakeClientFn, { + fetchMetadata: fakeClientFn, +} as Client); + +export const OsdkContext: React.Context<{ + client: Client; +}> = React.createContext<{ client: Client }>({ + client: fakeClient, +}); diff --git a/packages/react/src/OsdkProvider.tsx b/packages/react/src/OsdkProvider.tsx new file mode 100644 index 000000000..2a2f84640 --- /dev/null +++ b/packages/react/src/OsdkProvider.tsx @@ -0,0 +1,31 @@ +/* + * 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 { Client } from "@osdk/client"; +import React from "react"; +import { OsdkContext } from "./OsdkContext.js"; + +export function OsdkProvider({ + children, + client, +}: { + children: React.ReactNode; + client: Client; +}) { + return ( + {children} + ); +} diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts new file mode 100644 index 000000000..d5f471a82 --- /dev/null +++ b/packages/react/src/index.ts @@ -0,0 +1,18 @@ +/* + * 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. + */ + +export { OsdkProvider } from "./OsdkProvider.js"; +export { useOsdkClient } from "./useOsdkClient.js"; diff --git a/packages/react/src/useOsdkClient.ts b/packages/react/src/useOsdkClient.ts new file mode 100644 index 000000000..b3ec2266e --- /dev/null +++ b/packages/react/src/useOsdkClient.ts @@ -0,0 +1,23 @@ +/* + * 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 { Client } from "@osdk/client"; +import React from "react"; +import { OsdkContext } from "./OsdkContext.js"; + +export function useOsdkClient(): Client { + return React.useContext(OsdkContext).client; +} diff --git a/packages/react/src/useOsdkMetadata.ts b/packages/react/src/useOsdkMetadata.ts new file mode 100644 index 000000000..438396a76 --- /dev/null +++ b/packages/react/src/useOsdkMetadata.ts @@ -0,0 +1,51 @@ +/* + * 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 { + InterfaceDefinition, + InterfaceMetadata, + ObjectMetadata, + ObjectOrInterfaceDefinition, + ObjectTypeDefinition, +} from "@osdk/api"; +import React from "react"; +import { useOsdkClient } from "./useOsdkClient.js"; + +type MetadataFor = T extends + InterfaceDefinition ? InterfaceMetadata + : T extends ObjectTypeDefinition ? ObjectMetadata + : never; + +export function useOsdkMetadata( + type: T, +): { + loading: boolean; + metadata?: MetadataFor; +} { + const client = useOsdkClient(); + const [metadata, setMetadata] = React.useState< + MetadataFor | undefined + >(undefined); + + if (!metadata) { + client.fetchMetadata(type).then((fetchedMetadata) => { + setMetadata(fetchedMetadata as MetadataFor); + }); + return { loading: true }; + } + + return { loading: false, metadata }; +} diff --git a/packages/react/test/useOsdkClient.test.tsx b/packages/react/test/useOsdkClient.test.tsx new file mode 100644 index 000000000..6f4f23c43 --- /dev/null +++ b/packages/react/test/useOsdkClient.test.tsx @@ -0,0 +1,51 @@ +/* + * 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 { Client } from "@osdk/client"; +import { act, renderHook } from "@testing-library/react"; +import pDefer from "p-defer"; +import * as React from "react"; +import { describe, expect, it, vitest } from "vitest"; +import { OsdkContext } from "../src/OsdkContext.js"; +import { useOsdkClient } from "../src/useOsdkClient.js"; +import { useOsdkMetadata } from "../src/useOsdkMetadata.js"; + +describe(useOsdkMetadata, () => { + it("works with just client", () => { + const fakeClient = { + fetchMetadata: vitest.fn((o) => { + return Promise.resolve({ passedIn: o }) as any; + }), + } as any as Client; + + const wrapper = ({ children }: React.PropsWithChildren) => { + return ( + + {children} + + ); + }; + + const { result, rerender } = renderHook( + () => useOsdkClient(), + { wrapper }, + ); + + expect(result.current).toBe(fakeClient); + }); +}); diff --git a/packages/react/test/useOsdkMetadata.test.tsx b/packages/react/test/useOsdkMetadata.test.tsx new file mode 100644 index 000000000..3d4044397 --- /dev/null +++ b/packages/react/test/useOsdkMetadata.test.tsx @@ -0,0 +1,64 @@ +/* + * 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 { Client } from "@osdk/client"; +import { renderHook, waitFor } from "@testing-library/react"; +import pDefer from "p-defer"; +import * as React from "react"; +import { describe, expect, it, vitest } from "vitest"; +import { OsdkContext } from "../src/OsdkContext.js"; +import { useOsdkMetadata } from "../src/useOsdkMetadata.js"; + +describe(useOsdkMetadata, () => { + it("works", async () => { + const deferred = pDefer(); + const fakeClient = { + fetchMetadata: vitest.fn(async (o) => { + return deferred.promise; + }), + } as any as Client; + + const wrapper = ({ children }: React.PropsWithChildren) => { + return ( + + {children} + + ); + }; + + const FooObjectDef = { type: "object", apiName: "foo" } as const; + + const { result, rerender } = renderHook( + () => useOsdkMetadata(FooObjectDef), + { wrapper }, + ); + + expect(result.current).toEqual({ loading: true }); + + deferred.resolve({ passedIn: FooObjectDef }); + + await waitFor(() => + expect(result.current).toEqual({ + loading: false, + metadata: { passedIn: FooObjectDef }, + }) + ); + }); +}); diff --git a/packages/react/tsconfig.json b/packages/react/tsconfig.json new file mode 100644 index 000000000..f229be32f --- /dev/null +++ b/packages/react/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "@osdk/monorepo.tsconfig/base.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "build/esm", + "jsx": "react" + }, + "include": [ + "./src/**/*" + ], + "references": [] +} diff --git a/packages/react/tsup.config.js b/packages/react/tsup.config.js new file mode 100644 index 000000000..cfc2b707b --- /dev/null +++ b/packages/react/tsup.config.js @@ -0,0 +1,23 @@ +/* + * 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 { defineConfig } from "tsup"; + +export default defineConfig(async (options) => + (await import("@osdk/monorepo.tsup")).default(options, { + esmOnly: true, + }) +); diff --git a/packages/react/vitest.config.mts b/packages/react/vitest.config.mts new file mode 100644 index 000000000..d5c170f3a --- /dev/null +++ b/packages/react/vitest.config.mts @@ -0,0 +1,25 @@ +/* + * 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 { configDefaults, defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + pool: "forks", + exclude: [...configDefaults.exclude, "**/build/**/*"], + environment: "happy-dom", + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2cba5bce5..accbe417e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -135,7 +135,7 @@ importers: version: 8.11.0(eslint@9.7.0)(typescript@5.5.4) vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) examples-extra/docs_example: dependencies: @@ -251,7 +251,7 @@ importers: version: 5.5.4 vitest: specifier: ^2.1.3 - version: 2.1.3(@types/node@20.17.0) + version: 2.1.3(@types/node@20.17.0)(happy-dom@15.11.6) examples/example-next-static-export-sdk-2.x: dependencies: @@ -297,7 +297,7 @@ importers: version: 5.5.4 vitest: specifier: ^2.1.3 - version: 2.1.3(@types/node@20.17.0) + version: 2.1.3(@types/node@20.17.0)(happy-dom@15.11.6) examples/example-react-sdk-1.x: dependencies: @@ -367,7 +367,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) examples/example-react-sdk-2.x: dependencies: @@ -380,6 +380,9 @@ importers: '@osdk/oauth': specifier: workspace:* version: link:../../packages/oauth + '@osdk/react': + specifier: workspace:* + version: link:../../packages/react react: specifier: ^18 version: 18.3.1 @@ -452,7 +455,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) examples/example-tutorial-todo-aip-app-sdk-1.x: dependencies: @@ -522,7 +525,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) examples/example-tutorial-todo-aip-app-sdk-2.x: dependencies: @@ -598,7 +601,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.0.5 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) examples/example-tutorial-todo-app-sdk-1.x: dependencies: @@ -668,7 +671,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) examples/example-tutorial-todo-app-sdk-2.x: dependencies: @@ -744,7 +747,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.0.5 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) examples/example-vue-sdk-1.x: dependencies: @@ -769,7 +772,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) vue-tsc: specifier: ^2.1.6 version: 2.1.6(typescript@5.5.4) @@ -806,7 +809,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) vue-tsc: specifier: ^2.1.6 version: 2.1.6(typescript@5.5.4) @@ -1363,7 +1366,7 @@ importers: version: 5.5.4 vitest: specifier: ^2.1.3 - version: 2.1.3(@types/node@20.17.0) + version: 2.1.3(@types/node@20.17.0)(happy-dom@15.11.6) packages/create-app.template.next-static-export.v2: dependencies: @@ -1412,7 +1415,7 @@ importers: version: 5.5.4 vitest: specifier: ^2.1.3 - version: 2.1.3(@types/node@20.17.0) + version: 2.1.3(@types/node@20.17.0)(happy-dom@15.11.6) packages/create-app.template.react: dependencies: @@ -1491,7 +1494,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) packages/create-app.template.react.beta: dependencies: @@ -1579,7 +1582,7 @@ importers: version: 5.4.8(@types/node@22.7.4) vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.4) + version: 2.1.2(@types/node@22.7.4)(happy-dom@15.11.6) packages/create-app.template.tutorial-todo-aip-app: dependencies: @@ -1658,7 +1661,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) packages/create-app.template.tutorial-todo-aip-app.beta: dependencies: @@ -1737,7 +1740,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.0.5 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) packages/create-app.template.tutorial-todo-app: dependencies: @@ -1816,7 +1819,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) packages/create-app.template.tutorial-todo-app.beta: dependencies: @@ -1895,7 +1898,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.0.5 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) packages/create-app.template.vue: dependencies: @@ -1929,7 +1932,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) vue-tsc: specifier: ^2.1.6 version: 2.1.6(typescript@5.5.4) @@ -1966,7 +1969,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) vue-tsc: specifier: ^2.1.6 version: 2.1.6(typescript@5.5.4) @@ -2210,7 +2213,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) packages/e2e.sandbox.todoapp: dependencies: @@ -2344,7 +2347,7 @@ importers: version: 5.4.8(@types/node@22.7.9) vitest: specifier: ^2.1.2 - version: 2.1.3(@types/node@22.7.9) + version: 2.1.3(@types/node@22.7.9)(happy-dom@15.11.6) packages/e2e.test.foundry-sdk-generator: dependencies: @@ -2555,7 +2558,7 @@ importers: version: 5.5.4 vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@18.17.15) + version: 2.1.2(@types/node@18.17.15)(happy-dom@15.11.6) packages/generator-converters: dependencies: @@ -2583,7 +2586,7 @@ importers: version: 5.5.4 vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) packages/generator-utils: dependencies: @@ -2660,7 +2663,7 @@ importers: version: 5.5.4 vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@22.7.9) + version: 2.1.2(@types/node@22.7.9)(happy-dom@15.11.6) packages/monorepo.api-extractor: {} @@ -2722,6 +2725,46 @@ importers: specifier: ~5.5.4 version: 5.5.4 + packages/react: + dependencies: + react-dom: + specifier: ^17 || ^18 + version: 18.3.1(react@18.3.1) + devDependencies: + '@osdk/api': + specifier: workspace:* + version: link:../api + '@osdk/client': + specifier: workspace:* + version: link:../client + '@osdk/monorepo.api-extractor': + specifier: workspace:~ + version: link:../monorepo.api-extractor + '@osdk/monorepo.tsconfig': + specifier: workspace:~ + version: link:../monorepo.tsconfig + '@osdk/monorepo.tsup': + specifier: workspace:~ + version: link:../monorepo.tsup + '@testing-library/react': + specifier: ^16.0.1 + version: 16.0.1(@testing-library/dom@10.4.0)(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@types/react': + specifier: ^18.3.12 + version: 18.3.12 + happy-dom: + specifier: ^15.7.4 + version: 15.11.6 + p-defer: + specifier: ^4.0.1 + version: 4.0.1 + react: + specifier: ^18.0.0 + version: 18.3.1 + typescript: + specifier: ~5.5.4 + version: 5.5.4 + packages/shared.client.impl: dependencies: '@osdk/shared.client': @@ -2971,7 +3014,7 @@ importers: version: 5.5.4 vitest: specifier: ^2.1.2 - version: 2.1.2(@types/node@20.14.10) + version: 2.1.2(@types/node@20.14.10)(happy-dom@15.11.6) packages/version-updater: devDependencies: @@ -5332,6 +5375,25 @@ packages: '@swc/helpers@0.5.13': resolution: {integrity: sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==} + '@testing-library/dom@10.4.0': + resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} + engines: {node: '>=18'} + + '@testing-library/react@16.0.1': + resolution: {integrity: sha512-dSmwJVtJXmku+iocRhWOUFbrERC76TX2Mnf0ATODz8brzAZrMBbzLwQixlBSanZxR6LddK3eiwpSFZgDET1URg==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 + '@types/react-dom': ^18.0.0 + react: ^18.0.0 + react-dom: ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@ts-morph/common@0.20.0': resolution: {integrity: sha512-7uKjByfbPpwuzkstL3L5MQyuXPSKdoNG93Fmi2JoDcTf3pEP731JdRFAduRVkOs8oqxPsXKA+ScrWkdQ8t/I+Q==} @@ -5353,6 +5415,9 @@ packages: '@types/argparse@1.0.38': resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + '@types/aws-lambda@8.10.138': resolution: {integrity: sha512-71EHMl70TPWIAsFuHd85NHq6S6T2OOjiisPTrH7RgcjzpJpPh4RQJv7PvVvIxc6PIp8CLV7F9B+TdjcAES5vcA==} @@ -5784,6 +5849,9 @@ packages: resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==} engines: {node: '>=10'} + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + aria-query@5.3.2: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} @@ -6302,6 +6370,10 @@ packages: resolution: {integrity: sha512-2NJozoOHQ4NuZuVIr5CWd0iiLVIRSDepakaovIN+9eIDHEhdCAEvSy2cuf1DCrPPQLvHmbqTHODlhHg8UCy4zw==} engines: {node: '>=16'} + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + detect-indent@6.1.0: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} @@ -6338,6 +6410,9 @@ packages: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + dprint@0.47.2: resolution: {integrity: sha512-geUcVIIrmLaY+YtuOl4gD7J/QCjsXZa5gUqre9sO6cgH0X/Fa9heBN3l/AWVII6rKPw45ATuCSDWz1pyO+HkPQ==} hasBin: true @@ -6945,6 +7020,10 @@ packages: engines: {node: '>=0.4.7'} hasBin: true + happy-dom@15.11.6: + resolution: {integrity: sha512-elX7iUTu+5+3b2+NGQc0L3eWyq9jKhuJJ4GpOMxxT/c2pg9O3L5H3ty2VECX0XXZgRmmRqXyOK8brA2hDI6LsQ==} + engines: {node: '>=18.0.0'} + has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} @@ -7500,6 +7579,10 @@ packages: resolution: {integrity: sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==} engines: {node: '>=12'} + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + magic-string@0.30.11: resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} @@ -8016,6 +8099,10 @@ packages: engines: {node: '>=14'} hasBin: true + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + pretty-format@29.7.0: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -8080,6 +8167,9 @@ packages: react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-is@18.2.0: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} @@ -9071,6 +9161,14 @@ packages: webidl-conversions@4.0.2: resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-mimetype@3.0.0: + resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} + engines: {node: '>=12'} + whatwg-url@7.1.0: resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} @@ -11660,6 +11758,27 @@ snapshots: dependencies: tslib: 2.7.0 + '@testing-library/dom@10.4.0': + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/runtime': 7.24.5 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + + '@testing-library/react@16.0.1(@testing-library/dom@10.4.0)(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@babel/runtime': 7.24.5 + '@testing-library/dom': 10.4.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 + '@ts-morph/common@0.20.0': dependencies: fast-glob: 3.3.2 @@ -11681,6 +11800,8 @@ snapshots: '@types/argparse@1.0.38': {} + '@types/aria-query@5.0.4': {} + '@types/aws-lambda@8.10.138': {} '@types/babel__core@7.20.5': @@ -12295,6 +12416,10 @@ snapshots: dependencies: tslib: 2.7.0 + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + aria-query@5.3.2: {} array-buffer-byte-length@1.0.1: @@ -12845,6 +12970,8 @@ snapshots: delay@6.0.0: {} + dequal@2.0.3: {} + detect-indent@6.1.0: {} detect-libc@2.0.3: @@ -12873,6 +13000,8 @@ snapshots: dependencies: esutils: 2.0.3 + dom-accessibility-api@0.5.16: {} + dprint@0.47.2: optionalDependencies: '@dprint/darwin-arm64': 0.47.2 @@ -13820,6 +13949,12 @@ snapshots: optionalDependencies: uglify-js: 3.18.0 + happy-dom@15.11.6: + dependencies: + entities: 4.5.0 + webidl-conversions: 7.0.0 + whatwg-mimetype: 3.0.0 + has-bigints@1.0.2: {} has-flag@3.0.0: {} @@ -14295,6 +14430,8 @@ snapshots: luxon@3.4.4: {} + lz-string@1.5.0: {} + magic-string@0.30.11: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -14788,6 +14925,12 @@ snapshots: prettier@3.2.5: {} + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + pretty-format@29.7.0: dependencies: '@jest/schemas': 29.6.3 @@ -14850,6 +14993,8 @@ snapshots: react-is@16.13.1: {} + react-is@17.0.2: {} + react-is@18.2.0: {} react-refresh@0.14.0: {} @@ -15967,7 +16112,7 @@ snapshots: '@types/node': 22.7.9 fsevents: 2.3.3 - vitest@2.1.2(@types/node@18.17.15): + vitest@2.1.2(@types/node@18.17.15)(happy-dom@15.11.6): dependencies: '@vitest/expect': 2.1.2 '@vitest/mocker': 2.1.2(@vitest/spy@2.1.2)(vite@5.4.8(@types/node@18.17.15)) @@ -15990,6 +16135,7 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 18.17.15 + happy-dom: 15.11.6 transitivePeerDependencies: - less - lightningcss @@ -16001,7 +16147,7 @@ snapshots: - supports-color - terser - vitest@2.1.2(@types/node@20.14.10): + vitest@2.1.2(@types/node@20.14.10)(happy-dom@15.11.6): dependencies: '@vitest/expect': 2.1.2 '@vitest/mocker': 2.1.2(@vitest/spy@2.1.2)(vite@5.4.8(@types/node@20.14.10)) @@ -16024,6 +16170,7 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 20.14.10 + happy-dom: 15.11.6 transitivePeerDependencies: - less - lightningcss @@ -16035,7 +16182,7 @@ snapshots: - supports-color - terser - vitest@2.1.2(@types/node@22.7.4): + vitest@2.1.2(@types/node@22.7.4)(happy-dom@15.11.6): dependencies: '@vitest/expect': 2.1.2 '@vitest/mocker': 2.1.2(@vitest/spy@2.1.2)(vite@5.4.8(@types/node@22.7.4)) @@ -16058,6 +16205,7 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.7.4 + happy-dom: 15.11.6 transitivePeerDependencies: - less - lightningcss @@ -16069,7 +16217,7 @@ snapshots: - supports-color - terser - vitest@2.1.2(@types/node@22.7.9): + vitest@2.1.2(@types/node@22.7.9)(happy-dom@15.11.6): dependencies: '@vitest/expect': 2.1.2 '@vitest/mocker': 2.1.2(@vitest/spy@2.1.2)(vite@5.4.8(@types/node@22.7.9)) @@ -16092,6 +16240,7 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.7.9 + happy-dom: 15.11.6 transitivePeerDependencies: - less - lightningcss @@ -16103,7 +16252,7 @@ snapshots: - supports-color - terser - vitest@2.1.3(@types/node@20.17.0): + vitest@2.1.3(@types/node@20.17.0)(happy-dom@15.11.6): dependencies: '@vitest/expect': 2.1.3 '@vitest/mocker': 2.1.3(@vitest/spy@2.1.3)(vite@5.4.8(@types/node@20.17.0)) @@ -16126,6 +16275,7 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 20.17.0 + happy-dom: 15.11.6 transitivePeerDependencies: - less - lightningcss @@ -16137,7 +16287,7 @@ snapshots: - supports-color - terser - vitest@2.1.3(@types/node@22.7.9): + vitest@2.1.3(@types/node@22.7.9)(happy-dom@15.11.6): dependencies: '@vitest/expect': 2.1.3 '@vitest/mocker': 2.1.3(@vitest/spy@2.1.3)(vite@5.4.8(@types/node@22.7.9)) @@ -16160,6 +16310,7 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.7.9 + happy-dom: 15.11.6 transitivePeerDependencies: - less - lightningcss @@ -16199,6 +16350,10 @@ snapshots: webidl-conversions@4.0.2: {} + webidl-conversions@7.0.0: {} + + whatwg-mimetype@3.0.0: {} + whatwg-url@7.1.0: dependencies: lodash.sortby: 4.7.0