From 555be0d4fb9be7f6e6244ef0b55dd9395ab918c5 Mon Sep 17 00:00:00 2001 From: Marc Zwart Date: Sat, 28 Feb 2026 00:18:11 +0100 Subject: [PATCH 01/18] tags and build order in sample --- sample/Sample.slnx | 1 + sample/TypeShim.Sample.Server/TypeShim.Sample.Server.csproj | 1 + src/TypeShim/TypeShim.csproj | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sample/Sample.slnx b/sample/Sample.slnx index 096add01..e2e31d22 100644 --- a/sample/Sample.slnx +++ b/sample/Sample.slnx @@ -2,6 +2,7 @@ + diff --git a/sample/TypeShim.Sample.Server/TypeShim.Sample.Server.csproj b/sample/TypeShim.Sample.Server/TypeShim.Sample.Server.csproj index 5322e0af..5a3dc3ff 100644 --- a/sample/TypeShim.Sample.Server/TypeShim.Sample.Server.csproj +++ b/sample/TypeShim.Sample.Server/TypeShim.Sample.Server.csproj @@ -8,6 +8,7 @@ + diff --git a/src/TypeShim/TypeShim.csproj b/src/TypeShim/TypeShim.csproj index 7f4afdf2..cfcd4663 100644 --- a/src/TypeShim/TypeShim.csproj +++ b/src/TypeShim/TypeShim.csproj @@ -16,8 +16,8 @@ 0.0.1 ArcadeMode TypeShim - Typesafe .NET ↔︎ TypeScript interop - wasm, csharp, typescript, interop, generator + Seamless, type-safe interop between .NET WebAssembly and TypeScript + wasm, csharp, typescript, interop, code-gen, code-generation, tooling, msbuild https://github.com/ArcadeMode/TypeShim https://github.com/ArcadeMode/TypeShim MIT From e96022ffa1ea1c35d4f886ccc30d1bad4572dcbb Mon Sep 17 00:00:00 2001 From: Marc Zwart Date: Sat, 28 Feb 2026 01:26:55 +0100 Subject: [PATCH 02/18] refactor sample --- .../@typeshim/app/src/App.tsx | 86 ++++++++++--------- .../@typeshim/app/src/pages/People.tsx | 7 +- .../@typeshim/people-ui/src/AppProvider.tsx | 13 +++ .../@typeshim/people-ui/src/PeopleGrid.tsx | 7 +- .../@typeshim/people-ui/src/PeopleList.tsx | 6 +- .../people-ui/src/PeopleRepository.tsx | 16 ++-- .../@typeshim/people-ui/src/appContext.ts | 5 ++ .../@typeshim/people-ui/src/index.ts | 2 + .../wasm-exports/TypeShimProvider.tsx | 40 +++++++++ .../@typeshim/wasm-exports/main.ts | 1 + sample/TypeShim.Sample/MyApp.cs | 33 ++----- sample/TypeShim.Sample/PeopleProvider.cs | 15 ---- 12 files changed, 132 insertions(+), 99 deletions(-) create mode 100644 sample/TypeShim.Sample.Client/@typeshim/people-ui/src/AppProvider.tsx create mode 100644 sample/TypeShim.Sample.Client/@typeshim/people-ui/src/appContext.ts create mode 100644 sample/TypeShim.Sample.Client/@typeshim/wasm-exports/TypeShimProvider.tsx diff --git a/sample/TypeShim.Sample.Client/@typeshim/app/src/App.tsx b/sample/TypeShim.Sample.Client/@typeshim/app/src/App.tsx index e6be545e..83537014 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/app/src/App.tsx +++ b/sample/TypeShim.Sample.Client/@typeshim/app/src/App.tsx @@ -1,52 +1,56 @@ -import { useMemo, useState } from 'react'; +import { useState } from 'react'; import Home from './pages/Home'; import People from './pages/People'; -import { createWasmRuntime, MyApp, TypeShimInitializer } from '@typeshim/wasm-exports'; +import { TypeShimProvider } from '@typeshim/wasm-exports'; +import { AppProvider } from '@typeshim/people-ui'; type Page = 'home' | 'people'; function App() { - const [currentPage, setCurrentPage] = useState('home'); - - useMemo(async () => { - const runtimeInfo = await createWasmRuntime(); - await TypeShimInitializer.initialize(runtimeInfo); - MyApp.Initialize(document.baseURI); - }, []); - return ( - + + + + + ); } +function Content() { + const [currentPage, setCurrentPage] = useState('home'); + + return ( + ) +} + export default App; \ No newline at end of file diff --git a/sample/TypeShim.Sample.Client/@typeshim/app/src/pages/People.tsx b/sample/TypeShim.Sample.Client/@typeshim/app/src/pages/People.tsx index 5075a29e..ad4358d3 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/app/src/pages/People.tsx +++ b/sample/TypeShim.Sample.Client/@typeshim/app/src/pages/People.tsx @@ -5,7 +5,6 @@ import { PeopleRepository } from '@typeshim/people-ui'; export default function People() { const [view, setView] = useState<'list' | 'grid'>('list'); const toggle = () => setView(v => (v === 'list' ? 'grid' : 'list')); - const repository = new PeopleRepository(); return (

@@ -14,7 +13,7 @@ export default function People() {

There are ~1500 interop calls to methods on about 400 dotnet object instances made to render this page. - The impact of this many calls is not noticable (credits to the dotnet/runtime team!), try using your browser's devtools to profile the app. + The impact of this many calls is not noticable (credits to the dotnet/runtime team!).

{view === 'list' ? ( - + ) : ( - + )}

); diff --git a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/AppProvider.tsx b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/AppProvider.tsx new file mode 100644 index 00000000..ab33b1cf --- /dev/null +++ b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/AppProvider.tsx @@ -0,0 +1,13 @@ +import { MyApp } from '@typeshim/wasm-exports'; +import { useMemo, ReactNode } from 'react'; +import AppContext from './appContext'; + +export interface AppProviderProps { + children: ReactNode; +} + +export function AppProvider({ children }: AppProviderProps) { + const myApp = new MyApp(document.baseURI); + const value = useMemo(() => (myApp), [myApp]); + return {children} ; +} \ No newline at end of file diff --git a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/PeopleGrid.tsx b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/PeopleGrid.tsx index f8a4c8a9..01f57e80 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/PeopleGrid.tsx +++ b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/PeopleGrid.tsx @@ -4,17 +4,18 @@ import React, { useEffect, useState } from 'react'; import { PersonCard } from './PersonCard'; import type { Person } from '@typeshim/wasm-exports'; import { PeopleRepository } from './PeopleRepository'; +import AppContext from './appContext'; export interface PeopleGridProps { emptyText?: string; - repository: PeopleRepository; } -export const PeopleGrid: React.FC = ({ emptyText = 'No people found.', repository }) => { +export const PeopleGrid: React.FC = ({ emptyText = 'No people found.' }) => { const [people, setPeople] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - + const app = React.useContext(AppContext); + const repository = new PeopleRepository(app.GetPeopleProvider()); useEffect(() => { const fetchPeople = async () => { try { diff --git a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/PeopleList.tsx b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/PeopleList.tsx index 70e7d7d0..767db1b1 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/PeopleList.tsx +++ b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/PeopleList.tsx @@ -4,17 +4,19 @@ import React, { useEffect, useState } from 'react'; import { PersonCard } from './PersonCard'; import type { Person } from '@typeshim/wasm-exports'; import { PeopleRepository } from './PeopleRepository'; +import AppContext from './appContext'; export interface PeopleListProps { emptyText?: string; - repository: PeopleRepository; } -export const PeopleList: React.FC = ({ emptyText = 'No people found.', repository }) => { +export const PeopleList: React.FC = ({ emptyText = 'No people found.' }) => { const [people, setPeople] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); + const app = React.useContext(AppContext); + const repository = new PeopleRepository(app.GetPeopleProvider()); useEffect(() => { const fetchPeople = async () => { try { diff --git a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/PeopleRepository.tsx b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/PeopleRepository.tsx index 59c02a2f..6e744043 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/PeopleRepository.tsx +++ b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/PeopleRepository.tsx @@ -1,22 +1,18 @@ -import { People, Person, PeopleProvider, TimeoutUnit, MyApp } from '@typeshim/wasm-exports'; +import { People, Person, PeopleProvider } from '@typeshim/wasm-exports'; export class PeopleRepository { - public async getAllPeople(): Promise { - const peopleProvider: PeopleProvider = MyApp.GetPeopleProvider(); - const people: People = await peopleProvider.FetchPeopleAsync(); - return people.All; + constructor(private readonly peopleProvider: PeopleProvider) { } - public SetDelays(jsTimeout: number, csDelay: number) { - const peopleProvider: PeopleProvider = MyApp.GetPeopleProvider(); - const timeoutUnit: TimeoutUnit.Initializer | null = { Timeout: csDelay }; - peopleProvider.DelayTask = new Promise((resolve) => setTimeout(() => resolve(timeoutUnit), jsTimeout)); + public async getAllPeople(): Promise { + const people: People = await this.peopleProvider.FetchPeopleAsync(); + return people.All; } private async PrintAgeMethodUsage() { console.log("Demonstrating Person.IsOlderThan method:"); - const persons: Person[] = (await MyApp.GetPeopleProvider().FetchPeopleAsync()).All; + const persons: Person[] = (await this.peopleProvider.FetchPeopleAsync()).All; const person1 = persons[(Math.random() * persons.length) | 0]; const person2 = persons[(Math.random() * persons.length) | 0]; const p = Person.materialize(person2); diff --git a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/appContext.ts b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/appContext.ts new file mode 100644 index 00000000..0e6063c3 --- /dev/null +++ b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/appContext.ts @@ -0,0 +1,5 @@ +import { MyApp } from '@typeshim/wasm-exports'; +import React from 'react'; + +const AppContext = React.createContext(undefined!); +export default AppContext; diff --git a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/index.ts b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/index.ts index a666acb7..6b0a4429 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/index.ts +++ b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/index.ts @@ -2,3 +2,5 @@ export * from './PeopleList'; export * from './PeopleGrid'; export * from './PeopleRepository'; +export * from './appContext'; +export * from './AppProvider'; \ No newline at end of file diff --git a/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/TypeShimProvider.tsx b/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/TypeShimProvider.tsx new file mode 100644 index 00000000..83e0d847 --- /dev/null +++ b/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/TypeShimProvider.tsx @@ -0,0 +1,40 @@ +import { createWasmRuntime, MyApp, TypeShimInitializer } from '@typeshim/wasm-exports'; +import { useMemo, ReactNode, useEffect, useState } from 'react'; + +export interface AppProviderProps { + children: ReactNode; +} + +export function TypeShimProvider({ children }: AppProviderProps) { + const [runtime, setRuntime] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + let cancelled = false; + setLoading(true); + setError(null); + async function load() { + try { + const runtimeInfo = await createWasmRuntime(); + await TypeShimInitializer.initialize(runtimeInfo); + } catch (err: any) { + if (!cancelled) { + setError(err); + } + } finally { + if (!cancelled) { + setLoading(false); + } + } + } + load(); + + return () => { cancelled = true; }; // cleanup + }, []); + return error + ? (
Error: {error}
) + : loading + ? (
Loading...
) + : <>{children}; +} \ No newline at end of file diff --git a/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/main.ts b/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/main.ts index b895a3ab..badc97d1 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/main.ts +++ b/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/main.ts @@ -1,2 +1,3 @@ export * from './wasm-bootstrap.js' +export * from './TypeShimProvider' export * from './typeshim' \ No newline at end of file diff --git a/sample/TypeShim.Sample/MyApp.cs b/sample/TypeShim.Sample/MyApp.cs index 7d5765af..486b115c 100644 --- a/sample/TypeShim.Sample/MyApp.cs +++ b/sample/TypeShim.Sample/MyApp.cs @@ -9,36 +9,21 @@ namespace TypeShim.Sample; [TSExport] public class MyApp { - private static IHost? _host; + private readonly IHost _host; - public static void Initialize(string baseAddress) + public MyApp(string baseAddress) { - if (_host != null) - { - throw new InvalidOperationException("Module already initialized."); - } - Console.WriteLine($"Initializing {nameof(MyApp)} in .NET..."); - - IConfigurationRoot config = new ConfigurationBuilder() - // if desired, add configuration sources here, may also be passed through parameters - .Build(); - _host = new HostBuilder() - .ConfigureAppConfiguration((context, builder) => - { - builder.AddConfiguration(config); - }) - .ConfigureServices(services => - { - services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(baseAddress) }); - services.AddSingleton(); - services.AddSingleton(); - }) - .Build(); + _host = new HostBuilder().ConfigureServices(services => + { + services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(baseAddress) }); + services.AddSingleton(); + services.AddSingleton(sp => new PeopleProvider(sp.GetRequiredService())); + }).Build(); Console.WriteLine($"Initialized {nameof(MyApp)} in .NET."); } - public static PeopleProvider GetPeopleProvider() + public PeopleProvider GetPeopleProvider() { if (_host == null) { diff --git a/sample/TypeShim.Sample/PeopleProvider.cs b/sample/TypeShim.Sample/PeopleProvider.cs index c41c5920..5815e07b 100644 --- a/sample/TypeShim.Sample/PeopleProvider.cs +++ b/sample/TypeShim.Sample/PeopleProvider.cs @@ -17,18 +17,10 @@ internal PeopleProvider(PeopleApiClient apiClient) _apiClient = apiClient; } - public Person[]? PeopleCache => AllPeople; - public Task? DelayTask { get; set; } = null; - public async Task FetchPeopleAsync() { try { - if (DelayTask != null) - { - await Task.Delay((await DelayTask)?.Timeout ?? 0); - } - if (AllPeople == null) { AllPeople = [.. await _apiClient.GetAllPeopleAsync()]; @@ -46,11 +38,4 @@ public async Task FetchPeopleAsync() throw; // hand over to js } } -} - - -[TSExport] -public class TimeoutUnit -{ - public int Timeout { get; set; } = 0; } \ No newline at end of file From 93c026125ab77653d482ccde895cbb917b3fca76 Mon Sep 17 00:00:00 2001 From: Marc Zwart Date: Sat, 28 Feb 2026 01:34:07 +0100 Subject: [PATCH 03/18] disable fingerprinting for devex --- sample/TypeShim.Sample.Client/@typeshim/app/index.html | 8 ++------ sample/TypeShim.Sample/TypeShim.Sample.csproj | 3 ++- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/sample/TypeShim.Sample.Client/@typeshim/app/index.html b/sample/TypeShim.Sample.Client/@typeshim/app/index.html index 8f199756..78f05e10 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/app/index.html +++ b/sample/TypeShim.Sample.Client/@typeshim/app/index.html @@ -6,12 +6,8 @@ @typeshim/app Demo - - - + +
diff --git a/sample/TypeShim.Sample/TypeShim.Sample.csproj b/sample/TypeShim.Sample/TypeShim.Sample.csproj index 238311ad..914c50f1 100644 --- a/sample/TypeShim.Sample/TypeShim.Sample.csproj +++ b/sample/TypeShim.Sample/TypeShim.Sample.csproj @@ -5,7 +5,8 @@ true enable - true + + false false From 830c2043aff96506e26c20d87f8c5c2b8b2ef41f Mon Sep 17 00:00:00 2001 From: Marc Zwart Date: Sat, 28 Feb 2026 01:47:31 +0100 Subject: [PATCH 04/18] PeopleApp name --- .../@typeshim/people-ui/src/AppProvider.tsx | 6 +++--- .../@typeshim/people-ui/src/appContext.ts | 4 ++-- .../@typeshim/wasm-exports/TypeShimProvider.tsx | 4 ++-- sample/TypeShim.Sample/PeopleApiClient.cs | 2 -- sample/TypeShim.Sample/{MyApp.cs => PeopleApp.cs} | 8 ++++---- sample/TypeShim.Sample/PersonDtoSerializerContext.cs | 2 +- sample/TypeShim.Sample/Program.cs | 2 +- sample/TypeShim.Sample/TypeShim.Sample.csproj | 2 +- 8 files changed, 14 insertions(+), 16 deletions(-) rename sample/TypeShim.Sample/{MyApp.cs => PeopleApp.cs} (80%) diff --git a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/AppProvider.tsx b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/AppProvider.tsx index ab33b1cf..20324d06 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/AppProvider.tsx +++ b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/AppProvider.tsx @@ -1,4 +1,4 @@ -import { MyApp } from '@typeshim/wasm-exports'; +import { PeopleApp } from '@typeshim/wasm-exports'; import { useMemo, ReactNode } from 'react'; import AppContext from './appContext'; @@ -7,7 +7,7 @@ export interface AppProviderProps { } export function AppProvider({ children }: AppProviderProps) { - const myApp = new MyApp(document.baseURI); - const value = useMemo(() => (myApp), [myApp]); + const peopleApp = new PeopleApp(document.baseURI); + const value = useMemo(() => (peopleApp), [peopleApp]); return {children} ; } \ No newline at end of file diff --git a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/appContext.ts b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/appContext.ts index 0e6063c3..fc91afcf 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/appContext.ts +++ b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/appContext.ts @@ -1,5 +1,5 @@ -import { MyApp } from '@typeshim/wasm-exports'; +import { PeopleApp } from '@typeshim/wasm-exports'; import React from 'react'; -const AppContext = React.createContext(undefined!); +const AppContext = React.createContext(undefined!); export default AppContext; diff --git a/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/TypeShimProvider.tsx b/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/TypeShimProvider.tsx index 83e0d847..5ceefaa8 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/TypeShimProvider.tsx +++ b/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/TypeShimProvider.tsx @@ -1,5 +1,5 @@ -import { createWasmRuntime, MyApp, TypeShimInitializer } from '@typeshim/wasm-exports'; -import { useMemo, ReactNode, useEffect, useState } from 'react'; +import { createWasmRuntime, TypeShimInitializer } from '@typeshim/wasm-exports'; +import { ReactNode, useEffect, useState } from 'react'; export interface AppProviderProps { children: ReactNode; diff --git a/sample/TypeShim.Sample/PeopleApiClient.cs b/sample/TypeShim.Sample/PeopleApiClient.cs index 9057fd97..233f37c8 100644 --- a/sample/TypeShim.Sample/PeopleApiClient.cs +++ b/sample/TypeShim.Sample/PeopleApiClient.cs @@ -4,8 +4,6 @@ using System.Net.Http; using System.Net.Http.Json; using System.Threading.Tasks; -using TypeShim; -using VisageNovel; namespace TypeShim.Sample; diff --git a/sample/TypeShim.Sample/MyApp.cs b/sample/TypeShim.Sample/PeopleApp.cs similarity index 80% rename from sample/TypeShim.Sample/MyApp.cs rename to sample/TypeShim.Sample/PeopleApp.cs index 486b115c..8b9189e1 100644 --- a/sample/TypeShim.Sample/MyApp.cs +++ b/sample/TypeShim.Sample/PeopleApp.cs @@ -7,20 +7,20 @@ namespace TypeShim.Sample; [TSExport] -public class MyApp +public class PeopleApp { private readonly IHost _host; - public MyApp(string baseAddress) + public PeopleApp(string baseAddress) { - Console.WriteLine($"Initializing {nameof(MyApp)} in .NET..."); + Console.WriteLine($"Initializing {nameof(PeopleApp)} in .NET..."); _host = new HostBuilder().ConfigureServices(services => { services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(baseAddress) }); services.AddSingleton(); services.AddSingleton(sp => new PeopleProvider(sp.GetRequiredService())); }).Build(); - Console.WriteLine($"Initialized {nameof(MyApp)} in .NET."); + Console.WriteLine($"Initialized {nameof(PeopleApp)} in .NET."); } public PeopleProvider GetPeopleProvider() diff --git a/sample/TypeShim.Sample/PersonDtoSerializerContext.cs b/sample/TypeShim.Sample/PersonDtoSerializerContext.cs index 46a78fed..9382ec45 100644 --- a/sample/TypeShim.Sample/PersonDtoSerializerContext.cs +++ b/sample/TypeShim.Sample/PersonDtoSerializerContext.cs @@ -1,7 +1,7 @@ using System.Text.Json.Serialization; using TypeShim.Sample; -namespace VisageNovel; +namespace TypeShim.Sample; [JsonSourceGenerationOptions( GenerationMode = JsonSourceGenerationMode.Serialization | JsonSourceGenerationMode.Metadata, diff --git a/sample/TypeShim.Sample/Program.cs b/sample/TypeShim.Sample/Program.cs index b41a41da..39c3227e 100644 --- a/sample/TypeShim.Sample/Program.cs +++ b/sample/TypeShim.Sample/Program.cs @@ -19,6 +19,6 @@ public static void Main(string[] args) // this could then be combined with a static accessor to expose certain services to JS. // For this demo however, MyApp has been TSExport'ed and will be initialized from JS. - Console.WriteLine($"{nameof(MyApp)} can be initialized even without calling into Main"); + Console.WriteLine($"{nameof(PeopleApp)} can be initialized even without calling into Main"); } } diff --git a/sample/TypeShim.Sample/TypeShim.Sample.csproj b/sample/TypeShim.Sample/TypeShim.Sample.csproj index 914c50f1..7c2f16ec 100644 --- a/sample/TypeShim.Sample/TypeShim.Sample.csproj +++ b/sample/TypeShim.Sample/TypeShim.Sample.csproj @@ -17,7 +17,7 @@ ../../../../TypeShim.Sample.Client/@typeshim/wasm-exports - High + From b911ad3571aa299591cd8bebaccfd651b9f00440 Mon Sep 17 00:00:00 2001 From: Marc Zwart Date: Sat, 28 Feb 2026 01:57:58 +0100 Subject: [PATCH 05/18] Remove noise --- .../Controllers/PeopleController.cs | 4 +- .../Capabilities/ArraysDemo.cs | 24 -------- .../Capabilities/PrimitivesDemo.cs | 56 ------------------- sample/TypeShim.Sample/PeopleApiClient.cs | 6 -- 4 files changed, 2 insertions(+), 88 deletions(-) delete mode 100644 sample/TypeShim.Sample/Capabilities/ArraysDemo.cs delete mode 100644 sample/TypeShim.Sample/Capabilities/PrimitivesDemo.cs diff --git a/sample/TypeShim.Sample.Server/Controllers/PeopleController.cs b/sample/TypeShim.Sample.Server/Controllers/PeopleController.cs index c6efdccc..c1fc284f 100644 --- a/sample/TypeShim.Sample.Server/Controllers/PeopleController.cs +++ b/sample/TypeShim.Sample.Server/Controllers/PeopleController.cs @@ -11,10 +11,10 @@ public class PeopleController(PersonRepository repository) : ControllerBase [Route("all")] public PeopleDto GetAll() { - IEnumerable elderlyPeople = repository.GetAll(); + IEnumerable people = repository.GetAll(); return new PeopleDto { - People = [.. elderlyPeople.Select(PersonDto.FromPerson)] + People = [.. people.Select(PersonDto.FromPerson)] }; } } diff --git a/sample/TypeShim.Sample/Capabilities/ArraysDemo.cs b/sample/TypeShim.Sample/Capabilities/ArraysDemo.cs deleted file mode 100644 index faa5fa6d..00000000 --- a/sample/TypeShim.Sample/Capabilities/ArraysDemo.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Generic; - -namespace TypeShim.Sample.Capabilities; - -[TSExport] -public class ArraysDemo(int[] initialArray) -{ - public int[] IntArrayProperty { get; private set; } = initialArray; - - public int SumElements() - { - int sum = 0; - foreach (int item in IntArrayProperty) - { - sum += item; - } - return sum; - } - - public void Append(int value) - { - IntArrayProperty = [.. IntArrayProperty, value]; - } -} \ No newline at end of file diff --git a/sample/TypeShim.Sample/Capabilities/PrimitivesDemo.cs b/sample/TypeShim.Sample/Capabilities/PrimitivesDemo.cs deleted file mode 100644 index a7639fdb..00000000 --- a/sample/TypeShim.Sample/Capabilities/PrimitivesDemo.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Runtime.InteropServices.JavaScript; -using System.Text; -using System.Threading.Tasks; - -namespace TypeShim.Sample.Capabilities; - -[TSExport] -public class PrimitivesDemo -{ - public required string InitialStringProperty { get; init; } - public required string StringProperty { get; set; } - - public int GetStringLength() - { - return StringProperty.Length; - } - - public string ToUpperCase() - { - return StringProperty.ToUpper(); - } - - public string Concat(string str1, string str2) - { - return string.Concat(StringProperty, str1, str2); - } - - public bool ContainsUpperCase() - { - return StringProperty.Equals(StringProperty.ToLowerInvariant(), StringComparison.CurrentCultureIgnoreCase); - } - - public void ResetBaseString() - { - StringProperty = InitialStringProperty; - } - - public void MultiplyString(int times) - { - if (times < 0) - { - throw new ArgumentOutOfRangeException(nameof(times), "times must be non-negative"); - } - if (times * InitialStringProperty.Length > 100_000) - { - throw new InvalidOperationException("Resulting string is too long"); - } - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < times; i++) - { - sb.Append(StringProperty); - } - StringProperty = sb.ToString(); - } -} diff --git a/sample/TypeShim.Sample/PeopleApiClient.cs b/sample/TypeShim.Sample/PeopleApiClient.cs index 233f37c8..8762d346 100644 --- a/sample/TypeShim.Sample/PeopleApiClient.cs +++ b/sample/TypeShim.Sample/PeopleApiClient.cs @@ -9,12 +9,6 @@ namespace TypeShim.Sample; public class PeopleApiClient(HttpClient httpClient) { - public async Task> GetElderlyPeopleAsync() - { - PeopleDto? dto = await httpClient.GetFromJsonAsync("/people/elderly", typeof(PeopleDto), PersonDtoSerializerContext.Default) as PeopleDto; - return dto?.People?.Select(dto => dto.ToPerson()) ?? []; - } - public async Task> GetAllPeopleAsync() { PeopleDto? dto = await httpClient.GetFromJsonAsync("/people/all", typeof(PeopleDto), PersonDtoSerializerContext.Default) as PeopleDto; From 830f62e03f677ad5c302780b9c543b9a85b6a4d2 Mon Sep 17 00:00:00 2001 From: Marc Zwart Date: Sat, 28 Feb 2026 17:11:34 +0100 Subject: [PATCH 06/18] show initializer in action --- .../@typeshim/people-ui/src/AppProvider.tsx | 3 ++- sample/TypeShim.Sample/PeopleApp.cs | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/AppProvider.tsx b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/AppProvider.tsx index 20324d06..0aec6541 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/AppProvider.tsx +++ b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/AppProvider.tsx @@ -7,7 +7,8 @@ export interface AppProviderProps { } export function AppProvider({ children }: AppProviderProps) { - const peopleApp = new PeopleApp(document.baseURI); + // TypeShim automatically map the object literal to an PeopleAppOptions instance required for the PeopleApp constructor + const peopleApp = new PeopleApp({ BaseAddress: document.baseURI}); const value = useMemo(() => (peopleApp), [peopleApp]); return {children} ; } \ No newline at end of file diff --git a/sample/TypeShim.Sample/PeopleApp.cs b/sample/TypeShim.Sample/PeopleApp.cs index 8b9189e1..aa2a8453 100644 --- a/sample/TypeShim.Sample/PeopleApp.cs +++ b/sample/TypeShim.Sample/PeopleApp.cs @@ -6,29 +6,31 @@ namespace TypeShim.Sample; +[TSExport] +public class PeopleAppOptions +{ + public required string BaseAddress { get; init; } +} + [TSExport] public class PeopleApp { private readonly IHost _host; - public PeopleApp(string baseAddress) + public PeopleApp(PeopleAppOptions options) { - Console.WriteLine($"Initializing {nameof(PeopleApp)} in .NET..."); + // we dont -need- a servicecollection for this demo but its here to show you can use anything on the .net side _host = new HostBuilder().ConfigureServices(services => { - services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(baseAddress) }); + services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(options.BaseAddress) }); services.AddSingleton(); services.AddSingleton(sp => new PeopleProvider(sp.GetRequiredService())); }).Build(); - Console.WriteLine($"Initialized {nameof(PeopleApp)} in .NET."); + Console.WriteLine($".NET {nameof(PeopleApp)} Constructor completed"); } public PeopleProvider GetPeopleProvider() { - if (_host == null) - { - throw new InvalidOperationException("Module not initialized."); - } return _host.Services.GetRequiredService(); } } \ No newline at end of file From 671212a770802585df107900bf726b518ae58670 Mon Sep 17 00:00:00 2001 From: Marc Zwart Date: Sat, 28 Feb 2026 21:39:18 +0100 Subject: [PATCH 07/18] reduce noise --- .../Controllers/PeopleController.cs | 7 +- sample/TypeShim.Sample/DiagnosticsTest.cs | 105 ------------------ sample/TypeShim.Sample/PeopleApiClient.cs | 11 ++ .../PersonDtoSerializerContext.cs | 14 --- sample/TypeShim.Sample/PersonRepository.cs | 22 ---- sample/TypeShim.Sample/Program.cs | 11 +- ...eGenerator.cs => RandomEntityGenerator.cs} | 0 7 files changed, 19 insertions(+), 151 deletions(-) delete mode 100644 sample/TypeShim.Sample/DiagnosticsTest.cs delete mode 100644 sample/TypeShim.Sample/PersonDtoSerializerContext.cs delete mode 100644 sample/TypeShim.Sample/PersonRepository.cs rename sample/TypeShim.Sample/{PeopleGenerator.cs => RandomEntityGenerator.cs} (100%) diff --git a/sample/TypeShim.Sample.Server/Controllers/PeopleController.cs b/sample/TypeShim.Sample.Server/Controllers/PeopleController.cs index c1fc284f..0ca34245 100644 --- a/sample/TypeShim.Sample.Server/Controllers/PeopleController.cs +++ b/sample/TypeShim.Sample.Server/Controllers/PeopleController.cs @@ -5,16 +5,17 @@ namespace TypeShim.Sample.Server.Controllers; [ApiController] [Route("[controller]")] -public class PeopleController(PersonRepository repository) : ControllerBase +public class PeopleController() : ControllerBase { + private readonly List _people = new RandomEntityGenerator().GeneratePersons(250); + [HttpGet] [Route("all")] public PeopleDto GetAll() { - IEnumerable people = repository.GetAll(); return new PeopleDto { - People = [.. people.Select(PersonDto.FromPerson)] + People = [.. _people.Select(PersonDto.FromPerson)] }; } } diff --git a/sample/TypeShim.Sample/DiagnosticsTest.cs b/sample/TypeShim.Sample/DiagnosticsTest.cs deleted file mode 100644 index 0b2b73b4..00000000 --- a/sample/TypeShim.Sample/DiagnosticsTest.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices.JavaScript; -using System.Text; -using System.Threading.Tasks; - -namespace TypeShim.Sample; - -//[TSExport] -//internal class PublicAccessibilityTest -//{ -//} - -//[TSExport] -//public class PropertyAccessibilityTest -//{ -// public int PublicProperty { get; set; } -// private int PrivateProperty { get; set; } - -// public required int PublicRequiredProperty { get; set; } -// public int PublicGetPrivateSetProperty { get; private set; } -//} - -//[TSExport] -//public class PropertyTypeSupportTest -//{ -// public Dictionary P { get; set; } = []; -//} - -//[TSExport] -//public class OverloadMethodTest -//{ -// public int P() => 0; -// public int P(int i) => 0; -// public int P(int i, int j) => 0; -//} -//[TSExport] -//public class OverloadMethodTest2 -//{ -// public int P() => 0; -// internal int P(int i) => 0; -// public int P(int i, int j) => 0; -//} - -//[TSExport] -//public class OverloadConstructorTest() -//{ -// public OverloadConstructorTest(int i) -// { - -// } -//} - -//[TSExport] -//public class OverloadConstructorTest2 -//{ -// public OverloadConstructorTest2(int i) -// { - -// } -// public OverloadConstructorTest2(bool i) -// { - -// } -//} - -//[TSExport] -//public class OverloadConstructorTest3 -//{ -// public OverloadConstructorTest3(int i) -// { - -// } -// internal OverloadConstructorTest3(bool i) -// { - -// } -//} - -//[TSExport] -//public class MethodTypeSupportTest -//{ -// public Task X() { return Task.FromResult(new int[] { 1, 2, 3 }); } -// public Task Z() { return Task.FromResult(1); } -// public Span Y() { return new Span(); } -// public Span BA() { return new Span(); } -// public IEnumerable BBA() { return []; } -// public IDictionary C() { return new Dictionary(); } -// public IReadOnlyList E() { return []; } -// public Dictionary D() { return new Dictionary(); } -// public void DIn(Dictionary p) { } - -// public ArraySegment W() { return new ArraySegment(new string[] { "a", "b", "c" }); } - -// public Func F() { return (i) => i.ToString(); } -//} - -//[TSExport] -//public class FieldTest -//{ -// public int PublicField; -// private int PrivateField; - -// public required int InternalRequiredField; -//} diff --git a/sample/TypeShim.Sample/PeopleApiClient.cs b/sample/TypeShim.Sample/PeopleApiClient.cs index 8762d346..a72893fe 100644 --- a/sample/TypeShim.Sample/PeopleApiClient.cs +++ b/sample/TypeShim.Sample/PeopleApiClient.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Net.Http; using System.Net.Http.Json; +using System.Text.Json.Serialization; using System.Threading.Tasks; namespace TypeShim.Sample; @@ -15,3 +16,13 @@ public async Task> GetAllPeopleAsync() return dto?.People?.Select(dto => dto.ToPerson()) ?? []; } } + +[JsonSourceGenerationOptions( + GenerationMode = JsonSourceGenerationMode.Serialization | JsonSourceGenerationMode.Metadata, + PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)] +[JsonSerializable(typeof(PeopleDto))] +[JsonSerializable(typeof(PersonDto))] +[JsonSerializable(typeof(PersonDto[]))] +[JsonSerializable(typeof(DogDto))] +[JsonSerializable(typeof(DogDto[]))] +internal partial class PersonDtoSerializerContext : JsonSerializerContext { } diff --git a/sample/TypeShim.Sample/PersonDtoSerializerContext.cs b/sample/TypeShim.Sample/PersonDtoSerializerContext.cs deleted file mode 100644 index 9382ec45..00000000 --- a/sample/TypeShim.Sample/PersonDtoSerializerContext.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Text.Json.Serialization; -using TypeShim.Sample; - -namespace TypeShim.Sample; - -[JsonSourceGenerationOptions( - GenerationMode = JsonSourceGenerationMode.Serialization | JsonSourceGenerationMode.Metadata, - PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)] -[JsonSerializable(typeof(PeopleDto))] -[JsonSerializable(typeof(PersonDto))] -[JsonSerializable(typeof(PersonDto[]))] -[JsonSerializable(typeof(DogDto))] -[JsonSerializable(typeof(DogDto[]))] -internal partial class PersonDtoSerializerContext : JsonSerializerContext { } diff --git a/sample/TypeShim.Sample/PersonRepository.cs b/sample/TypeShim.Sample/PersonRepository.cs deleted file mode 100644 index b07b4347..00000000 --- a/sample/TypeShim.Sample/PersonRepository.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace TypeShim.Sample; - -public class PersonRepository -{ - private readonly RandomEntityGenerator _generator = new(); - - private readonly List _people; - - public PersonRepository() - { - _people = _generator.GeneratePersons(250); - } - - public IEnumerable GetAll() - { - return _people; - } -} diff --git a/sample/TypeShim.Sample/Program.cs b/sample/TypeShim.Sample/Program.cs index 39c3227e..d13ddb6b 100644 --- a/sample/TypeShim.Sample/Program.cs +++ b/sample/TypeShim.Sample/Program.cs @@ -13,12 +13,9 @@ public static void Main(string[] args) { Console.WriteLine("WASM runtime is alive."); - // You can put any startup logic here if needed, like set up DI even a whole host builder. - // even make JSImport calls - - // this could then be combined with a static accessor to expose certain services to JS. - - // For this demo however, MyApp has been TSExport'ed and will be initialized from JS. - Console.WriteLine($"{nameof(PeopleApp)} can be initialized even without calling into Main"); + // You can put any startup logic here like any other .NET application + // alternatively you could expose a class that embodies your app and treat the .NET code as a library. + // For this demo we'll go with the latter, PeopleApp will be constructed from the JS side. + Console.WriteLine($"{nameof(PeopleApp)} will be constructed from the JS side in this demo."); } } diff --git a/sample/TypeShim.Sample/PeopleGenerator.cs b/sample/TypeShim.Sample/RandomEntityGenerator.cs similarity index 100% rename from sample/TypeShim.Sample/PeopleGenerator.cs rename to sample/TypeShim.Sample/RandomEntityGenerator.cs From 1106e4bdb62e32fec2bb8ff11ab42636342b35d4 Mon Sep 17 00:00:00 2001 From: Marc Zwart Date: Sat, 28 Feb 2026 21:46:17 +0100 Subject: [PATCH 08/18] text --- .../@typeshim/people-ui/src/PeopleRepository.tsx | 2 +- sample/TypeShim.Sample/Program.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/PeopleRepository.tsx b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/PeopleRepository.tsx index 6e744043..573f15a2 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/PeopleRepository.tsx +++ b/sample/TypeShim.Sample.Client/@typeshim/people-ui/src/PeopleRepository.tsx @@ -25,7 +25,7 @@ export class PeopleRepository { }); person3.AdoptPet(); console.log(person1.Name, person1.Age, "isOlderThan", person2.Name, person2.Age, ":", person1.IsOlderThan(person2)); - console.log(person1.Name, person1.Age, "isOlderThan (snapshot)", jsPerson.Name, jsPerson.Age, ":", person1.IsOlderThan(jsPerson)); + console.log(person1.Name, person1.Age, "isOlderThan (initializer)", jsPerson.Name, jsPerson.Age, ":", person1.IsOlderThan(jsPerson)); console.log(person1.Name, person1.Age, "isOlderThan (constructor)", person3.Name, person3.Age, ":", person1.IsOlderThan(person3)); } } diff --git a/sample/TypeShim.Sample/Program.cs b/sample/TypeShim.Sample/Program.cs index d13ddb6b..ace2184c 100644 --- a/sample/TypeShim.Sample/Program.cs +++ b/sample/TypeShim.Sample/Program.cs @@ -11,7 +11,7 @@ public partial class Program { public static void Main(string[] args) { - Console.WriteLine("WASM runtime is alive."); + Console.WriteLine(".NET Main method entered."); // You can put any startup logic here like any other .NET application // alternatively you could expose a class that embodies your app and treat the .NET code as a library. From a9eab3f13309380e4478484db7003663cb61dfc4 Mon Sep 17 00:00:00 2001 From: Marc Zwart Date: Sat, 28 Feb 2026 22:03:55 +0100 Subject: [PATCH 09/18] remove unused registration --- .../@typeshim/app/src/pages/People.tsx | 5 +++-- sample/TypeShim.Sample.Server/Program.cs | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sample/TypeShim.Sample.Client/@typeshim/app/src/pages/People.tsx b/sample/TypeShim.Sample.Client/@typeshim/app/src/pages/People.tsx index ad4358d3..f9324e90 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/app/src/pages/People.tsx +++ b/sample/TypeShim.Sample.Client/@typeshim/app/src/pages/People.tsx @@ -1,6 +1,5 @@ -import React, { useState } from 'react'; +import { useState } from 'react'; import { PeopleList, PeopleGrid } from '@typeshim/people-ui'; -import { PeopleRepository } from '@typeshim/people-ui'; export default function People() { const [view, setView] = useState<'list' | 'grid'>('list'); @@ -10,6 +9,8 @@ export default function People() {

All data on this screen is accessed through interop calls to the dotnet runtime. Getting the array of people, getting a Person's name, getting their (optional) Pet or getting the Pet's name, these are all examples of interop calls. + + Try clicking the buttons and pet chips to see state being manipulated in .NET.

There are ~1500 interop calls to methods on about 400 dotnet object instances made to render this page. diff --git a/sample/TypeShim.Sample.Server/Program.cs b/sample/TypeShim.Sample.Server/Program.cs index cd20949c..3675aad1 100644 --- a/sample/TypeShim.Sample.Server/Program.cs +++ b/sample/TypeShim.Sample.Server/Program.cs @@ -5,7 +5,6 @@ builder.Services.AddControllers() .AddApplicationPart(typeof(PeopleController).Assembly); ; -builder.Services.AddSingleton(); var app = builder.Build(); app.UseHttpsRedirection(); From c09708d425f3250fefd3163889f013715ad5f3f1 Mon Sep 17 00:00:00 2001 From: Marc Zwart Date: Sun, 1 Mar 2026 23:34:57 +0100 Subject: [PATCH 10/18] switch to bundler mode --- .../@typeshim/app/package.json | 2 +- .../@typeshim/app/vite.config.ts | 4 ++-- .../@typeshim/wasm-exports/.gitignore | 1 + .../wasm-exports/TypeShimProvider.tsx | 6 ++++-- .../@typeshim/wasm-exports/main.ts | 4 ++-- .../@typeshim/wasm-exports/wasm-bootstrap.d.ts | 1 - .../@typeshim/wasm-exports/wasm-bootstrap.js | 15 --------------- .../@typeshim/wasm-exports/wasm-bootstrap.ts | 18 ++++++++++++++++++ sample/TypeShim.Sample.Server/Program.cs | 6 +++++- sample/TypeShim.Sample/.gitignore | 1 - .../Properties/launchSettings.json | 3 ++- sample/TypeShim.Sample/TypeShim.Sample.csproj | 17 +++++++++++------ .../wwwroot/_framework/dotnet.d.ts | 1 + 13 files changed, 47 insertions(+), 32 deletions(-) create mode 100644 sample/TypeShim.Sample.Client/@typeshim/wasm-exports/.gitignore delete mode 100644 sample/TypeShim.Sample.Client/@typeshim/wasm-exports/wasm-bootstrap.d.ts delete mode 100644 sample/TypeShim.Sample.Client/@typeshim/wasm-exports/wasm-bootstrap.js create mode 100644 sample/TypeShim.Sample.Client/@typeshim/wasm-exports/wasm-bootstrap.ts delete mode 100644 sample/TypeShim.Sample/.gitignore create mode 100644 sample/TypeShim.Sample/wwwroot/_framework/dotnet.d.ts diff --git a/sample/TypeShim.Sample.Client/@typeshim/app/package.json b/sample/TypeShim.Sample.Client/@typeshim/app/package.json index 6d04767e..9c409c9c 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/app/package.json +++ b/sample/TypeShim.Sample.Client/@typeshim/app/package.json @@ -4,7 +4,7 @@ "description": "", "main": "index.js", "scripts": { - "dev": "vite build --watch", + "dev": "vite", "build": "vite build", "preview": "vite preview", "test": "echo \"Error: no test specified\" && exit 1" diff --git a/sample/TypeShim.Sample.Client/@typeshim/app/vite.config.ts b/sample/TypeShim.Sample.Client/@typeshim/app/vite.config.ts index 9b60748d..cfe0feb9 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/app/vite.config.ts +++ b/sample/TypeShim.Sample.Client/@typeshim/app/vite.config.ts @@ -5,10 +5,10 @@ export default defineConfig({ plugins: [ react() ], - assetsInclude: ['**/*.dat', '**/*.wasm'], + assetsInclude: ['**/*.dat', '**/*.wasm', '**/*.pdb'], build: { target: 'es2020', - outDir: '../../../TypeShim.Sample/wwwroot', + outDir: './dist', assetsDir: 'assets', rollupOptions: { external: ['webcil', '/_framework/dotnet.js'], diff --git a/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/.gitignore b/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/.gitignore new file mode 100644 index 00000000..7951405f --- /dev/null +++ b/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/.gitignore @@ -0,0 +1 @@ +lib \ No newline at end of file diff --git a/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/TypeShimProvider.tsx b/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/TypeShimProvider.tsx index 5ceefaa8..5bc219de 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/TypeShimProvider.tsx +++ b/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/TypeShimProvider.tsx @@ -18,7 +18,9 @@ export function TypeShimProvider({ children }: AppProviderProps) { try { const runtimeInfo = await createWasmRuntime(); await TypeShimInitializer.initialize(runtimeInfo); + console.log("WASM Runtime initialized successfully."); } catch (err: any) { + console.error("Error loading WASM runtime:", err); if (!cancelled) { setError(err); } @@ -30,11 +32,11 @@ export function TypeShimProvider({ children }: AppProviderProps) { } load(); - return () => { cancelled = true; }; // cleanup + return () => { cancelled = true; console.log("CANCEL"); }; // cleanup }, []); return error ? (

Error: {error}
) : loading ? (
Loading...
) - : <>{children}; + : (<>{children}); } \ No newline at end of file diff --git a/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/main.ts b/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/main.ts index badc97d1..e84b22ac 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/main.ts +++ b/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/main.ts @@ -1,3 +1,3 @@ -export * from './wasm-bootstrap.js' +export * from './wasm-bootstrap' export * from './TypeShimProvider' -export * from './typeshim' \ No newline at end of file +export * from './lib/wwwroot/typeshim' \ No newline at end of file diff --git a/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/wasm-bootstrap.d.ts b/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/wasm-bootstrap.d.ts deleted file mode 100644 index da5c917b..00000000 --- a/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/wasm-bootstrap.d.ts +++ /dev/null @@ -1 +0,0 @@ -export function createWasmRuntime(args?: string | undefined): Promise; \ No newline at end of file diff --git a/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/wasm-bootstrap.js b/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/wasm-bootstrap.js deleted file mode 100644 index 570449da..00000000 --- a/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/wasm-bootstrap.js +++ /dev/null @@ -1,15 +0,0 @@ -import { dotnet } from '/_framework/dotnet.js' - -let isStarted = null; - -export async function createWasmRuntime(args) { - if (isStarted) { - throw new Error("The .NET WebAssembly runtime has already been started."); - } - isStarted = true; - - const runtimeInfo = await dotnet.withApplicationArguments(args).create(); - const { runMain } = runtimeInfo; - runMain(); - return runtimeInfo; -}; \ No newline at end of file diff --git a/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/wasm-bootstrap.ts b/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/wasm-bootstrap.ts new file mode 100644 index 00000000..44c1434a --- /dev/null +++ b/sample/TypeShim.Sample.Client/@typeshim/wasm-exports/wasm-bootstrap.ts @@ -0,0 +1,18 @@ +import { dotnet } from './lib/wwwroot/_framework/dotnet' + +let runtime: any = null; +let runtimePromise: Promise | null = null; +export async function createWasmRuntime(): Promise { + console.log("Creating WASM runtime..."); + if (runtimePromise) { + console.warn("WASM runtime is already started. Not creating a new instance."); + return runtimePromise; + } else { + runtimePromise = dotnet.create(); + } + const runtimeInfo = await runtimePromise; + console.log("WASM runtime info:", runtimeInfo); + const { runMain } = runtimeInfo; + runMain(); + return runtime = runtimeInfo; +}; \ No newline at end of file diff --git a/sample/TypeShim.Sample.Server/Program.cs b/sample/TypeShim.Sample.Server/Program.cs index 3675aad1..2b559118 100644 --- a/sample/TypeShim.Sample.Server/Program.cs +++ b/sample/TypeShim.Sample.Server/Program.cs @@ -9,8 +9,12 @@ app.UseHttpsRedirection(); app.UseAuthorization(); -app.UseBlazorFrameworkFiles(); +//app.UseBlazorFrameworkFiles(); app.UseWebAssemblyDebugging(); +//app.UseSpa(spa => +//{ +// spa.Options.SourcePath = "ClientApp"; +//}); app.UseDefaultFiles(); app.UseStaticFiles(); diff --git a/sample/TypeShim.Sample/.gitignore b/sample/TypeShim.Sample/.gitignore deleted file mode 100644 index 2493aaf5..00000000 --- a/sample/TypeShim.Sample/.gitignore +++ /dev/null @@ -1 +0,0 @@ -wwwroot \ No newline at end of file diff --git a/sample/TypeShim.Sample/Properties/launchSettings.json b/sample/TypeShim.Sample/Properties/launchSettings.json index 12222cf5..848fa4b2 100644 --- a/sample/TypeShim.Sample/Properties/launchSettings.json +++ b/sample/TypeShim.Sample/Properties/launchSettings.json @@ -7,7 +7,8 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "applicationUrl": "https://localhost:7200;http://localhost:5295", - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}" + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "hotReloadEnabled": false } } } diff --git a/sample/TypeShim.Sample/TypeShim.Sample.csproj b/sample/TypeShim.Sample/TypeShim.Sample.csproj index 7c2f16ec..da1469f7 100644 --- a/sample/TypeShim.Sample/TypeShim.Sample.csproj +++ b/sample/TypeShim.Sample/TypeShim.Sample.csproj @@ -5,9 +5,11 @@ true enable - + true false false + false + false @@ -15,19 +17,22 @@ + ../TypeShim.Sample.Client/@typeshim/wasm-exports/lib - ../../../../TypeShim.Sample.Client/@typeshim/wasm-exports + - - - - + + + + + PreserveNewest +
diff --git a/sample/TypeShim.Sample/wwwroot/_framework/dotnet.d.ts b/sample/TypeShim.Sample/wwwroot/_framework/dotnet.d.ts new file mode 100644 index 00000000..4fccde41 --- /dev/null +++ b/sample/TypeShim.Sample/wwwroot/_framework/dotnet.d.ts @@ -0,0 +1 @@ +export const dotnet: any; \ No newline at end of file From c82f380bf1802af8dc522979eed4f7bf1ee4986a Mon Sep 17 00:00:00 2001 From: Marc Zwart Date: Mon, 2 Mar 2026 21:59:41 +0100 Subject: [PATCH 11/18] update js sdk + spa dev server --- .../TypeShim.Sample.Client.esproj | 2 +- sample/TypeShim.Sample.Server/Program.cs | 8 ++++---- .../TypeShim.Sample.Server.csproj | 2 +- .../TypeShim.Sample/Properties/launchSettings.json | 14 -------------- 4 files changed, 6 insertions(+), 20 deletions(-) delete mode 100644 sample/TypeShim.Sample/Properties/launchSettings.json diff --git a/sample/TypeShim.Sample.Client/TypeShim.Sample.Client.esproj b/sample/TypeShim.Sample.Client/TypeShim.Sample.Client.esproj index 27047a89..e20242bd 100644 --- a/sample/TypeShim.Sample.Client/TypeShim.Sample.Client.esproj +++ b/sample/TypeShim.Sample.Client/TypeShim.Sample.Client.esproj @@ -1,4 +1,4 @@ - + npm run build diff --git a/sample/TypeShim.Sample.Server/Program.cs b/sample/TypeShim.Sample.Server/Program.cs index 2b559118..a6abee7e 100644 --- a/sample/TypeShim.Sample.Server/Program.cs +++ b/sample/TypeShim.Sample.Server/Program.cs @@ -11,10 +11,10 @@ app.UseAuthorization(); //app.UseBlazorFrameworkFiles(); app.UseWebAssemblyDebugging(); -//app.UseSpa(spa => -//{ -// spa.Options.SourcePath = "ClientApp"; -//}); +app.UseSpa(spa => +{ + spa.UseProxyToSpaDevelopmentServer("http://localhost:5173/"); +}); app.UseDefaultFiles(); app.UseStaticFiles(); diff --git a/sample/TypeShim.Sample.Server/TypeShim.Sample.Server.csproj b/sample/TypeShim.Sample.Server/TypeShim.Sample.Server.csproj index 5a3dc3ff..ca0d9b18 100644 --- a/sample/TypeShim.Sample.Server/TypeShim.Sample.Server.csproj +++ b/sample/TypeShim.Sample.Server/TypeShim.Sample.Server.csproj @@ -8,11 +8,11 @@ - + diff --git a/sample/TypeShim.Sample/Properties/launchSettings.json b/sample/TypeShim.Sample/Properties/launchSettings.json deleted file mode 100644 index 848fa4b2..00000000 --- a/sample/TypeShim.Sample/Properties/launchSettings.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "profiles": { - "webassembly standalone": { - "commandName": "Project", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "applicationUrl": "https://localhost:7200;http://localhost:5295", - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "hotReloadEnabled": false - } - } -} From 94047c0f992ad6e94eb045617408e5015179173e Mon Sep 17 00:00:00 2001 From: Marc Zwart Date: Mon, 2 Mar 2026 22:48:17 +0100 Subject: [PATCH 12/18] make controllers work --- sample/TypeShim.Sample.Server/Program.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/sample/TypeShim.Sample.Server/Program.cs b/sample/TypeShim.Sample.Server/Program.cs index a6abee7e..f199b92f 100644 --- a/sample/TypeShim.Sample.Server/Program.cs +++ b/sample/TypeShim.Sample.Server/Program.cs @@ -1,16 +1,17 @@ -using TypeShim.Sample; -using TypeShim.Sample.Server.Controllers; - -var builder = WebApplication.CreateBuilder(args); +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers() - .AddApplicationPart(typeof(PeopleController).Assembly); ; -var app = builder.Build(); + .AddApplicationPart(typeof(Program).Assembly); ; +WebApplication app = builder.Build(); +app.UseRouting(); app.UseHttpsRedirection(); app.UseAuthorization(); -//app.UseBlazorFrameworkFiles(); app.UseWebAssemblyDebugging(); + +#pragma warning disable ASP0014 // Suggest using top level route registrations - not compatible with usespa and spaproxy is a bit of a hassle to use +app.UseEndpoints(ep => ep.MapControllers()); +#pragma warning restore ASP0014 // Suggest using top level route registrations app.UseSpa(spa => { spa.UseProxyToSpaDevelopmentServer("http://localhost:5173/"); @@ -19,6 +20,4 @@ app.UseDefaultFiles(); app.UseStaticFiles(); -app.MapControllers(); - app.Run(); From c488ef1afbf77df585e7e943da27045a1afc720e Mon Sep 17 00:00:00 2001 From: Marc Zwart Date: Mon, 2 Mar 2026 22:52:04 +0100 Subject: [PATCH 13/18] doc --- sample/TypeShim.Sample.Server/Program.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/sample/TypeShim.Sample.Server/Program.cs b/sample/TypeShim.Sample.Server/Program.cs index f199b92f..038805c6 100644 --- a/sample/TypeShim.Sample.Server/Program.cs +++ b/sample/TypeShim.Sample.Server/Program.cs @@ -14,6 +14,7 @@ #pragma warning restore ASP0014 // Suggest using top level route registrations app.UseSpa(spa => { + // run 'npm start' or 'npm run dev' in TypeShim.Sample.Client to start the vite dev server spa.UseProxyToSpaDevelopmentServer("http://localhost:5173/"); }); From e7b1e8fe96cceb351f0be026ff139998537be5a6 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 02:39:31 +0100 Subject: [PATCH 14/18] =?UTF-8?q?Restructure=20sample:=20rename=20projects?= =?UTF-8?q?,=20flatten=20client=20dir,=20@typeshim=E2=86=92@client,=20merg?= =?UTF-8?q?e=20people-ui=20into=20app=20(#94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleans up the sample project layout — flatter structure, consistent naming, fewer npm packages. ## Changes - **Project renames** - `TypeShim.Sample` → `Client.Library` (dir, csproj, C# namespaces) - `TypeShim.Sample.Server` → `Server` (dir, csproj, C# namespaces) - `Sample.slnx` updated; `Server.csproj` project reference updated - **Flatten client directory** - `TypeShim.Sample.Client/` removed; contents (`package.json`, workspaces, `.gitignore`, etc.) lifted into `sample/` root - `.esproj` / `.esproj.user` deleted; removed from `Sample.slnx` - `Client.Library.csproj` `` updated to new path - **`@typeshim` → `@client`** - Directory, all `package.json` names, TypeScript imports, string literals, `.gitignore` glob pattern - **Merge `@client/people-ui` into `@client/app`** - Components moved to `@client/app/src/people/` - `@client/app` no longer depends on `@client/people-ui` - `build:people` script removed; `package-lock.json` and root `tsconfig.json` references cleaned up - `@client/people-ui` package deleted --- ✨ Let Copilot coding agent [set things up for you](https://github.com/ArcadeMode/TypeShim/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: ArcadeMode <5969155+ArcadeMode@users.noreply.github.com> --- .../{TypeShim.Sample.Client => }/.gitignore | 2 +- .../@typeshim => @client}/app/index.html | 2 +- .../@typeshim => @client}/app/package.json | 7 +--- .../@typeshim => @client}/app/src/App.tsx | 6 +-- .../@typeshim => @client}/app/src/index.css | 0 .../@typeshim => @client}/app/src/main.tsx | 0 .../app/src/pages/Home.tsx | 2 +- .../app/src/pages/People.tsx | 2 +- .../app/src/people}/AppProvider.tsx | 2 +- .../app/src/people}/PeopleGrid.tsx | 2 +- .../app/src/people}/PeopleList.tsx | 2 +- .../app/src/people}/PeopleRepository.tsx | 2 +- .../app/src/people}/PersonCard.tsx | 2 +- .../app/src/people}/PetChip.tsx | 2 +- .../app/src/people}/appContext.ts | 2 +- .../src => @client/app/src/people}/index.ts | 0 .../@typeshim => @client}/app/tsconfig.json | 0 .../app/tsconfig.node.json | 0 .../@typeshim => @client}/app/vite.config.ts | 0 .../wasm-exports/.gitignore | 0 .../wasm-exports/TypeShimProvider.tsx | 2 +- .../wasm-exports/main.ts | 0 .../wasm-exports/package.json | 2 +- .../wasm-exports/wasm-bootstrap.ts | 0 .../Client.Library.csproj} | 2 +- .../Dtos.cs | 2 +- .../Models.cs | 2 +- .../PeopleApiClient.cs | 2 +- .../PeopleApp.cs | 2 +- .../PeopleProvider.cs | 2 +- .../Program.cs | 2 +- .../Properties/AssemblyInfo.cs | 0 .../RandomEntityGenerator.cs | 2 +- .../wwwroot/_framework/dotnet.d.ts | 0 sample/Sample.slnx | 9 +--- .../Controllers/PeopleController.cs | 4 +- .../Program.cs | 2 +- .../Properties/launchSettings.json | 0 .../Server.csproj} | 2 +- .../appsettings.Development.json | 0 .../appsettings.json | 0 .../@typeshim/people-ui/package.json | 28 ------------- .../@typeshim/people-ui/tsconfig.json | 19 --------- .../TypeShim.Sample.Client.esproj | 11 ----- .../TypeShim.Sample.Client.esproj.user | 6 --- .../TypeShim.Sample.Server.csproj.user | 6 --- .../package-lock.json | 42 ++++++------------- .../{TypeShim.Sample.Client => }/package.json | 15 ++++--- .../tsconfig.json | 1 - 49 files changed, 51 insertions(+), 149 deletions(-) rename sample/{TypeShim.Sample.Client => }/.gitignore (98%) rename sample/{TypeShim.Sample.Client/@typeshim => @client}/app/index.html (92%) rename sample/{TypeShim.Sample.Client/@typeshim => @client}/app/package.json (71%) rename sample/{TypeShim.Sample.Client/@typeshim => @client}/app/src/App.tsx (89%) rename sample/{TypeShim.Sample.Client/@typeshim => @client}/app/src/index.css (100%) rename sample/{TypeShim.Sample.Client/@typeshim => @client}/app/src/main.tsx (100%) rename sample/{TypeShim.Sample.Client/@typeshim => @client}/app/src/pages/Home.tsx (95%) rename sample/{TypeShim.Sample.Client/@typeshim => @client}/app/src/pages/People.tsx (97%) rename sample/{TypeShim.Sample.Client/@typeshim/people-ui/src => @client/app/src/people}/AppProvider.tsx (91%) rename sample/{TypeShim.Sample.Client/@typeshim/people-ui/src => @client/app/src/people}/PeopleGrid.tsx (96%) rename sample/{TypeShim.Sample.Client/@typeshim/people-ui/src => @client/app/src/people}/PeopleList.tsx (95%) rename sample/{TypeShim.Sample.Client/@typeshim/people-ui/src => @client/app/src/people}/PeopleRepository.tsx (94%) rename sample/{TypeShim.Sample.Client/@typeshim/people-ui/src => @client/app/src/people}/PersonCard.tsx (98%) rename sample/{TypeShim.Sample.Client/@typeshim/people-ui/src => @client/app/src/people}/PetChip.tsx (95%) rename sample/{TypeShim.Sample.Client/@typeshim/people-ui/src => @client/app/src/people}/appContext.ts (69%) rename sample/{TypeShim.Sample.Client/@typeshim/people-ui/src => @client/app/src/people}/index.ts (100%) rename sample/{TypeShim.Sample.Client/@typeshim => @client}/app/tsconfig.json (100%) rename sample/{TypeShim.Sample.Client/@typeshim => @client}/app/tsconfig.node.json (100%) rename sample/{TypeShim.Sample.Client/@typeshim => @client}/app/vite.config.ts (100%) rename sample/{TypeShim.Sample.Client/@typeshim => @client}/wasm-exports/.gitignore (100%) rename sample/{TypeShim.Sample.Client/@typeshim => @client}/wasm-exports/TypeShimProvider.tsx (93%) rename sample/{TypeShim.Sample.Client/@typeshim => @client}/wasm-exports/main.ts (100%) rename sample/{TypeShim.Sample.Client/@typeshim => @client}/wasm-exports/package.json (87%) rename sample/{TypeShim.Sample.Client/@typeshim => @client}/wasm-exports/wasm-bootstrap.ts (100%) rename sample/{TypeShim.Sample/TypeShim.Sample.csproj => Client.Library/Client.Library.csproj} (94%) rename sample/{TypeShim.Sample => Client.Library}/Dtos.cs (97%) rename sample/{TypeShim.Sample => Client.Library}/Models.cs (97%) rename sample/{TypeShim.Sample => Client.Library}/PeopleApiClient.cs (97%) rename sample/{TypeShim.Sample => Client.Library}/PeopleApp.cs (97%) rename sample/{TypeShim.Sample => Client.Library}/PeopleProvider.cs (97%) rename sample/{TypeShim.Sample => Client.Library}/Program.cs (96%) rename sample/{TypeShim.Sample => Client.Library}/Properties/AssemblyInfo.cs (100%) rename sample/{TypeShim.Sample => Client.Library}/RandomEntityGenerator.cs (98%) rename sample/{TypeShim.Sample => Client.Library}/wwwroot/_framework/dotnet.d.ts (100%) rename sample/{TypeShim.Sample.Server => Server}/Controllers/PeopleController.cs (85%) rename sample/{TypeShim.Sample.Server => Server}/Program.cs (88%) rename sample/{TypeShim.Sample.Server => Server}/Properties/launchSettings.json (100%) rename sample/{TypeShim.Sample.Server/TypeShim.Sample.Server.csproj => Server/Server.csproj} (86%) rename sample/{TypeShim.Sample.Server => Server}/appsettings.Development.json (100%) rename sample/{TypeShim.Sample.Server => Server}/appsettings.json (100%) delete mode 100644 sample/TypeShim.Sample.Client/@typeshim/people-ui/package.json delete mode 100644 sample/TypeShim.Sample.Client/@typeshim/people-ui/tsconfig.json delete mode 100644 sample/TypeShim.Sample.Client/TypeShim.Sample.Client.esproj delete mode 100644 sample/TypeShim.Sample.Client/TypeShim.Sample.Client.esproj.user delete mode 100644 sample/TypeShim.Sample.Server/TypeShim.Sample.Server.csproj.user rename sample/{TypeShim.Sample.Client => }/package-lock.json (98%) rename sample/{TypeShim.Sample.Client => }/package.json (58%) rename sample/{TypeShim.Sample.Client => }/tsconfig.json (86%) diff --git a/sample/TypeShim.Sample.Client/.gitignore b/sample/.gitignore similarity index 98% rename from sample/TypeShim.Sample.Client/.gitignore rename to sample/.gitignore index b7447368..da2cd498 100644 --- a/sample/TypeShim.Sample.Client/.gitignore +++ b/sample/.gitignore @@ -97,7 +97,7 @@ temp/ # Preserve root lock !package-lock.json # If individual workspace package-locks accidentally get created (npm -w install inside): -@typeshim/*/package-lock.json +@client/*/package-lock.json # ----------------------------- # Misc bundler artifacts diff --git a/sample/TypeShim.Sample.Client/@typeshim/app/index.html b/sample/@client/app/index.html similarity index 92% rename from sample/TypeShim.Sample.Client/@typeshim/app/index.html rename to sample/@client/app/index.html index 78f05e10..7bb81257 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/app/index.html +++ b/sample/@client/app/index.html @@ -4,7 +4,7 @@ - @typeshim/app Demo + @client/app Demo diff --git a/sample/TypeShim.Sample.Client/@typeshim/app/package.json b/sample/@client/app/package.json similarity index 71% rename from sample/TypeShim.Sample.Client/@typeshim/app/package.json rename to sample/@client/app/package.json index 9c409c9c..869f8be8 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/app/package.json +++ b/sample/@client/app/package.json @@ -1,5 +1,5 @@ { - "name": "@typeshim/app", + "name": "@client/app", "version": "1.0.0", "description": "", "main": "index.js", @@ -11,8 +11,5 @@ }, "keywords": [], "author": "", - "license": "ISC", - "dependencies": { - "@typeshim/people-ui": "*" - } + "license": "ISC" } diff --git a/sample/TypeShim.Sample.Client/@typeshim/app/src/App.tsx b/sample/@client/app/src/App.tsx similarity index 89% rename from sample/TypeShim.Sample.Client/@typeshim/app/src/App.tsx rename to sample/@client/app/src/App.tsx index 83537014..bc625c5a 100644 --- a/sample/TypeShim.Sample.Client/@typeshim/app/src/App.tsx +++ b/sample/@client/app/src/App.tsx @@ -1,8 +1,8 @@ import { useState } from 'react'; import Home from './pages/Home'; import People from './pages/People'; -import { TypeShimProvider } from '@typeshim/wasm-exports'; -import { AppProvider } from '@typeshim/people-ui'; +import { TypeShimProvider } from '@client/wasm-exports'; +import { AppProvider } from './people/AppProvider'; type Page = 'home' | 'people'; @@ -28,7 +28,7 @@ function Content() { display: 'flex', gap: '1rem' }}> - @typeshim/app + @client/app