@reactionary/source 0.0.30 → 0.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/CLAUDE.md +11 -0
  2. package/core/package.json +1 -1
  3. package/core/src/cache/cache-evaluation.interface.ts +19 -0
  4. package/core/src/cache/cache.interface.ts +38 -0
  5. package/core/src/cache/noop-cache.ts +42 -0
  6. package/core/src/cache/redis-cache.ts +55 -22
  7. package/core/src/client/client-builder.ts +63 -0
  8. package/core/src/client/client.ts +27 -3
  9. package/core/src/decorators/trpc.decorators.ts +144 -0
  10. package/core/src/index.ts +6 -1
  11. package/core/src/providers/analytics.provider.ts +3 -6
  12. package/core/src/providers/base.provider.ts +13 -63
  13. package/core/src/providers/cart.provider.ts +10 -6
  14. package/core/src/providers/identity.provider.ts +8 -5
  15. package/core/src/providers/inventory.provider.ts +5 -6
  16. package/core/src/providers/price.provider.ts +6 -6
  17. package/core/src/providers/product.provider.ts +6 -6
  18. package/core/src/providers/search.provider.ts +6 -6
  19. package/core/src/schemas/mutations/base.mutation.ts +0 -1
  20. package/core/src/schemas/mutations/cart.mutation.ts +0 -6
  21. package/core/src/schemas/mutations/identity.mutation.ts +0 -5
  22. package/core/src/schemas/mutations/product.mutation.ts +0 -1
  23. package/core/src/schemas/queries/base.query.ts +0 -1
  24. package/core/src/schemas/queries/cart.query.ts +1 -3
  25. package/core/src/schemas/queries/identity.query.ts +1 -3
  26. package/core/src/schemas/queries/inventory.query.ts +0 -1
  27. package/core/src/schemas/queries/price.query.ts +0 -3
  28. package/core/src/schemas/queries/product.query.ts +2 -7
  29. package/core/src/schemas/queries/search.query.ts +0 -3
  30. package/examples/node/package.json +1 -5
  31. package/examples/node/src/basic/basic-node-provider-model-extension.spec.ts +97 -0
  32. package/examples/node/src/basic/basic-node-provider-query-extension.spec.ts +84 -0
  33. package/examples/node/src/basic/basic-node-setup.spec.ts +40 -0
  34. package/otel/src/index.ts +3 -0
  35. package/otel/src/trace-decorator.ts +246 -0
  36. package/package.json +2 -1
  37. package/providers/algolia/src/core/initialize.ts +11 -9
  38. package/providers/algolia/src/providers/product.provider.ts +44 -11
  39. package/providers/algolia/src/providers/search.provider.ts +47 -66
  40. package/providers/commercetools/src/core/client.ts +0 -1
  41. package/providers/commercetools/src/core/initialize.ts +28 -24
  42. package/providers/commercetools/src/providers/cart.provider.ts +58 -89
  43. package/providers/commercetools/src/providers/identity.provider.ts +34 -50
  44. package/providers/commercetools/src/providers/inventory.provider.ts +16 -38
  45. package/providers/commercetools/src/providers/price.provider.ts +30 -35
  46. package/providers/commercetools/src/providers/product.provider.ts +48 -38
  47. package/providers/commercetools/src/providers/search.provider.ts +32 -47
  48. package/providers/commercetools/src/schema/capabilities.schema.ts +1 -1
  49. package/providers/fake/package.json +1 -0
  50. package/providers/fake/src/core/initialize.ts +17 -14
  51. package/providers/fake/src/index.ts +4 -0
  52. package/providers/fake/src/providers/analytics.provider.ts +19 -0
  53. package/providers/fake/src/providers/cart.provider.ts +107 -0
  54. package/providers/fake/src/providers/identity.provider.ts +78 -67
  55. package/providers/fake/src/providers/inventory.provider.ts +54 -0
  56. package/providers/fake/src/providers/price.provider.ts +60 -0
  57. package/providers/fake/src/providers/product.provider.ts +53 -49
  58. package/providers/fake/src/providers/search.provider.ts +15 -33
  59. package/providers/posthog/src/core/initialize.ts +6 -4
  60. package/trpc/__mocks__/superjson.js +25 -0
  61. package/trpc/jest.config.ts +14 -0
  62. package/trpc/package.json +2 -1
  63. package/trpc/src/client.ts +176 -0
  64. package/trpc/src/index.ts +35 -62
  65. package/trpc/src/integration.spec.ts +216 -0
  66. package/trpc/src/server.ts +123 -0
  67. package/trpc/src/transparent-client.spec.ts +160 -0
  68. package/trpc/src/types.ts +142 -0
  69. package/trpc/tsconfig.json +3 -0
  70. package/trpc/tsconfig.lib.json +2 -1
  71. package/trpc/tsconfig.spec.json +15 -0
  72. package/tsconfig.base.json +0 -2
  73. package/core/src/cache/caching-strategy.ts +0 -25
  74. package/examples/angular/e2e/example.spec.ts +0 -9
  75. package/examples/angular/eslint.config.mjs +0 -41
  76. package/examples/angular/playwright.config.ts +0 -38
  77. package/examples/angular/project.json +0 -86
  78. package/examples/angular/public/favicon.ico +0 -0
  79. package/examples/angular/src/app/app.component.html +0 -6
  80. package/examples/angular/src/app/app.component.scss +0 -22
  81. package/examples/angular/src/app/app.component.ts +0 -14
  82. package/examples/angular/src/app/app.config.ts +0 -16
  83. package/examples/angular/src/app/app.routes.ts +0 -25
  84. package/examples/angular/src/app/cart/cart.component.html +0 -4
  85. package/examples/angular/src/app/cart/cart.component.scss +0 -14
  86. package/examples/angular/src/app/cart/cart.component.ts +0 -73
  87. package/examples/angular/src/app/identity/identity.component.html +0 -6
  88. package/examples/angular/src/app/identity/identity.component.scss +0 -18
  89. package/examples/angular/src/app/identity/identity.component.ts +0 -49
  90. package/examples/angular/src/app/product/product.component.html +0 -14
  91. package/examples/angular/src/app/product/product.component.scss +0 -11
  92. package/examples/angular/src/app/product/product.component.ts +0 -42
  93. package/examples/angular/src/app/search/search.component.html +0 -35
  94. package/examples/angular/src/app/search/search.component.scss +0 -129
  95. package/examples/angular/src/app/search/search.component.ts +0 -50
  96. package/examples/angular/src/app/services/product.service.ts +0 -35
  97. package/examples/angular/src/app/services/search.service.ts +0 -48
  98. package/examples/angular/src/app/services/trpc.client.ts +0 -27
  99. package/examples/angular/src/index.html +0 -13
  100. package/examples/angular/src/main.ts +0 -7
  101. package/examples/angular/src/styles.scss +0 -17
  102. package/examples/angular/src/test-setup.ts +0 -6
  103. package/examples/angular/tsconfig.app.json +0 -10
  104. package/examples/angular/tsconfig.editor.json +0 -6
  105. package/examples/angular/tsconfig.json +0 -32
  106. package/examples/node/src/initialize-algolia.spec.ts +0 -29
  107. package/examples/node/src/initialize-commercetools.spec.ts +0 -31
  108. package/examples/node/src/initialize-extended-providers.spec.ts +0 -38
  109. package/examples/node/src/initialize-mixed-providers.spec.ts +0 -36
  110. package/examples/node/src/providers/custom-algolia-product.provider.ts +0 -18
  111. package/examples/node/src/schemas/custom-product.schema.ts +0 -8
  112. package/examples/trpc-node/.env.example +0 -52
  113. package/examples/trpc-node/eslint.config.mjs +0 -3
  114. package/examples/trpc-node/project.json +0 -61
  115. package/examples/trpc-node/src/assets/.gitkeep +0 -0
  116. package/examples/trpc-node/src/main.ts +0 -59
  117. package/examples/trpc-node/src/router-instance.ts +0 -52
  118. package/examples/trpc-node/tsconfig.app.json +0 -9
  119. package/examples/trpc-node/tsconfig.json +0 -13
@@ -1,73 +1,77 @@
1
1
  import {
2
- BaseMutation,
3
2
  Product,
4
- ProductMutation,
5
3
  ProductProvider,
6
- ProductQuery,
4
+ ProductQueryById,
5
+ ProductQueryBySlug,
7
6
  Session,
7
+ Cache as ReactinaryCache,
8
8
  } from '@reactionary/core';
9
9
  import z from 'zod';
10
10
  import { FakeConfiguration } from '../schema/configuration.schema';
11
11
  import { base, en, Faker } from '@faker-js/faker';
12
+ import { traced } from '@reactionary/otel';
12
13
 
13
14
  export class FakeProductProvider<
14
- T extends Product = Product,
15
- Q extends ProductQuery = ProductQuery,
16
- M extends ProductMutation = ProductMutation
17
- > extends ProductProvider<T, Q, M> {
15
+ T extends Product = Product
16
+ > extends ProductProvider<T> {
18
17
  protected config: FakeConfiguration;
19
18
 
20
- constructor(config: FakeConfiguration, schema: z.ZodType<T>, querySchema: z.ZodType<Q, Q>, mutationSchema: z.ZodType<M, M>) {
21
- super(schema, querySchema, mutationSchema);
19
+ constructor(config: FakeConfiguration, schema: z.ZodType<T>, cache: ReactinaryCache) {
20
+ super(schema, cache);
22
21
 
23
22
  this.config = config;
24
23
  }
25
24
 
26
- protected override async fetch(queries: Q[], session: Session): Promise<T[]> {
27
- const results = new Array<T>();
25
+ @traced()
26
+ public override async getById(
27
+ payload: ProductQueryById,
28
+ _session: Session
29
+ ): Promise<T> {
30
+ return this.parseSingle(payload);
31
+ }
28
32
 
29
- for (const query of queries) {
30
- const generator = new Faker({
31
- seed: 42,
32
- locale: [en, base],
33
- });
33
+ public override async getBySlug(
34
+ payload: ProductQueryBySlug,
35
+ _session: Session
36
+ ): Promise<T> {
37
+ return this.parseSingle(payload);
38
+ }
34
39
 
35
- const key = (query.id as string) || generator.commerce.isbn();
36
- const slug = (query.slug as string) || generator.lorem.slug();
40
+ protected override parseSingle(body: ProductQueryById | ProductQueryBySlug): T {
41
+ const generator = new Faker({
42
+ seed: 42,
43
+ locale: [en, base],
44
+ });
37
45
 
38
- const product: Product = {
39
- identifier: {
40
- key: key,
41
- },
42
- name: generator.commerce.productName(),
43
- slug: slug,
44
- attributes: [],
45
- description: generator.commerce.productDescription(),
46
- image: generator.image.urlPicsumPhotos({
47
- width: 600,
48
- height: 600,
49
- }),
50
- images: [],
51
- meta: {
52
- cache: {
53
- hit: false,
54
- key: key,
55
- },
56
- placeholder: false
57
- },
58
- skus: [],
59
- };
46
+ const key = body.slug || body.id;
60
47
 
61
- results.push(product as T);
62
- }
48
+ // Create a model instance based on the schema
49
+ const model = this.newModel();
63
50
 
64
- return results;
65
- }
51
+ // Merge the generated data into the model
52
+ Object.assign(model, {
53
+ identifier: {
54
+ key: key,
55
+ },
56
+ name: generator.commerce.productName(),
57
+ slug: key,
58
+ attributes: [],
59
+ description: generator.commerce.productDescription(),
60
+ image: generator.image.urlPicsumPhotos({
61
+ width: 600,
62
+ height: 600,
63
+ }),
64
+ images: [],
65
+ meta: {
66
+ cache: {
67
+ hit: false,
68
+ key: key,
69
+ },
70
+ placeholder: false,
71
+ },
72
+ skus: [],
73
+ });
66
74
 
67
- protected override process(
68
- mutation: BaseMutation[],
69
- session: Session
70
- ): Promise<T> {
71
- throw new Error('Method not implemented.');
75
+ return this.assert(model);
72
76
  }
73
77
  }
@@ -1,12 +1,11 @@
1
1
  import {
2
- SearchIdentifier,
3
- SearchMutation,
4
2
  SearchProvider,
5
- SearchQuery,
3
+ SearchQueryByTerm,
6
4
  SearchResult,
7
5
  SearchResultFacet,
8
6
  SearchResultProduct,
9
7
  Session,
8
+ Cache as ReactinaryCache,
10
9
  } from '@reactionary/core';
11
10
  import z from 'zod';
12
11
  import { FakeConfiguration } from '../schema/configuration.schema';
@@ -14,41 +13,24 @@ import { Faker, en, base } from '@faker-js/faker';
14
13
  import { jitter } from '../utilities/jitter';
15
14
 
16
15
  export class FakeSearchProvider<
17
- T extends SearchResult = SearchResult,
18
- Q extends SearchQuery = SearchQuery,
19
- M extends SearchMutation = SearchMutation
20
- > extends SearchProvider<T, Q, M> {
16
+ T extends SearchResult = SearchResult
17
+ > extends SearchProvider<T> {
21
18
  protected config: FakeConfiguration;
22
19
 
23
- constructor(config: FakeConfiguration, schema: z.ZodType<T>, querySchema: z.ZodType<Q, Q>, mutationSchema: z.ZodType<M, M>) {
24
- super(schema, querySchema, mutationSchema);
20
+ constructor(config: FakeConfiguration, schema: z.ZodType<T>, cache: ReactinaryCache) {
21
+ super(schema, cache);
25
22
 
26
23
  this.config = config;
27
24
  }
28
25
 
29
- protected override async fetch(queries: Q[], session: Session): Promise<T[]> {
30
- const results = [];
31
-
32
- for (const query of queries) {
33
- const result = await this.get(query.search);
34
-
35
- results.push(result);
36
- }
37
-
38
- return results;
39
- }
40
-
41
- protected override process(mutations: M[], session: Session): Promise<T> {
42
- throw new Error('Method not implemented.');
43
- }
44
-
45
- public async get(identifier: SearchIdentifier): Promise<T> {
26
+ public override async queryByTerm(
27
+ payload: SearchQueryByTerm,
28
+ _session: Session
29
+ ): Promise<SearchResult> {
46
30
  await jitter(this.config.jitter.mean, this.config.jitter.deviation);
47
31
 
48
- return this.parse({}, identifier);
49
- }
32
+ const query = payload.search;
50
33
 
51
- public parse(data: unknown, query: SearchIdentifier): T {
52
34
  const querySpecificity =
53
35
  20 - query.term.length - query.page - query.facets.length;
54
36
  const totalProducts = 10 * querySpecificity;
@@ -77,7 +59,7 @@ export class FakeSearchProvider<
77
59
  height: 300,
78
60
  width: 300,
79
61
  grayscale: true,
80
- blur: 8
62
+ blur: 8,
81
63
  }),
82
64
  name: productGenerator.commerce.productName(),
83
65
  slug: productGenerator.lorem.slug(),
@@ -131,10 +113,10 @@ export class FakeSearchProvider<
131
113
  meta: {
132
114
  cache: {
133
115
  hit: false,
134
- key: ''
116
+ key: '',
135
117
  },
136
- placeholder: false
137
- }
118
+ placeholder: false,
119
+ },
138
120
  } satisfies SearchResult;
139
121
 
140
122
  return this.schema.parse(result);
@@ -1,9 +1,11 @@
1
- import { Client } from "@reactionary/core";
1
+ import { Client, Cache } from "@reactionary/core";
2
2
  import { PosthogConfiguration } from "../schema/configuration.schema";
3
3
  import { PosthogCapabilities } from "../schema/capabilities.schema";
4
4
 
5
- export function withPosthogCapabilities(configuration: PosthogConfiguration, capabilities: PosthogCapabilities) {
6
- const client: Partial<Client> = {};
5
+ export function withPosthogCapabilities(_configuration: PosthogConfiguration, _capabilities: PosthogCapabilities) {
6
+ return (_cache: Cache) => {
7
+ const client: Partial<Client> = {};
7
8
 
8
- return client;
9
+ return client;
10
+ };
9
11
  }
@@ -0,0 +1,25 @@
1
+ // Mock superjson for Jest testing
2
+ module.exports = {
3
+ default: {
4
+ stringify: JSON.stringify,
5
+ parse: JSON.parse,
6
+ serialize: (obj) => ({ json: obj, meta: undefined }),
7
+ deserialize: (data) => data.json,
8
+ output: {
9
+ serialize: (obj) => ({ json: obj, meta: undefined })
10
+ },
11
+ input: {
12
+ deserialize: (data) => data.json
13
+ }
14
+ },
15
+ stringify: JSON.stringify,
16
+ parse: JSON.parse,
17
+ serialize: (obj) => ({ json: obj, meta: undefined }),
18
+ deserialize: (data) => data.json,
19
+ output: {
20
+ serialize: (obj) => ({ json: obj, meta: undefined })
21
+ },
22
+ input: {
23
+ deserialize: (data) => data.json
24
+ }
25
+ };
@@ -0,0 +1,14 @@
1
+ export default {
2
+ displayName: 'trpc',
3
+ preset: '../jest.preset.js',
4
+ testEnvironment: 'node',
5
+ testTimeout: 15000,
6
+ transform: {
7
+ '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
8
+ },
9
+ moduleFileExtensions: ['ts', 'js', 'html'],
10
+ moduleNameMapper: {
11
+ '^superjson$': '<rootDir>/__mocks__/superjson.js',
12
+ },
13
+ coverageDirectory: '../coverage/trpc',
14
+ };
package/trpc/package.json CHANGED
@@ -9,6 +9,7 @@
9
9
  "@reactionary/core": "0.0.1",
10
10
  "@reactionary/otel": "0.0.1",
11
11
  "superjson": "^2.2.2",
12
- "zod": "4.0.0-beta.20250430T185432"
12
+ "zod": "4.0.0-beta.20250430T185432",
13
+ "@trpc/client": "^11.1.2"
13
14
  }
14
15
  }
@@ -0,0 +1,176 @@
1
+ import { Client, Session, isTRPCQuery, isTRPCMutation, isTRPCMethod } from '@reactionary/core';
2
+ import type { TransparentClient } from './types';
3
+ import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
4
+ import type { TRPCClientError } from '@trpc/client';
5
+
6
+ /**
7
+ * Configuration options for TRPC client creation
8
+ */
9
+ export interface TRPCClientOptions {
10
+ /** Default session to use if not provided in method calls */
11
+ defaultSession?: Session;
12
+ /** Whether to automatically provide session from defaultSession */
13
+ autoSession?: boolean;
14
+ }
15
+
16
+ /**
17
+ * Create a type-safe client proxy that uses the original client's type interface
18
+ * while routing all calls through TRPC
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * import { createTRPCProxyClient } from '@trpc/client';
23
+ * import { createTRPCClient } from '@reactionary/trpc/client';
24
+ *
25
+ * const trpc = createTRPCProxyClient<AppRouter>({
26
+ * url: 'http://localhost:3000',
27
+ * });
28
+ *
29
+ * // Pass the original client type as the generic parameter
30
+ * const client = createTRPCClient<typeof serverClient>(trpc, {
31
+ * defaultSession: mySession,
32
+ * autoSession: true
33
+ * });
34
+ *
35
+ * // Fully typed using the original client interface!
36
+ * const product = await client.product.getById({ id: '123' }, session);
37
+ * ```
38
+ */
39
+ export function createTRPCClient<TOriginalClient extends Partial<Client>>(
40
+ trpcClient: any,
41
+ options: TRPCClientOptions = {}
42
+ ): TransparentClient<TOriginalClient> {
43
+ const { defaultSession, autoSession = false } = options;
44
+
45
+ return new Proxy({} as TransparentClient<TOriginalClient>, {
46
+ get(target, providerName: string | symbol) {
47
+ if (typeof providerName !== 'string') {
48
+ return undefined;
49
+ }
50
+
51
+ // Return a typed proxy for the provider that intercepts method calls
52
+ return new Proxy({}, {
53
+ get(providerTarget, methodName: string | symbol) {
54
+ if (typeof methodName !== 'string') {
55
+ return undefined;
56
+ }
57
+
58
+ // Only expose methods that are marked with TRPC decorators
59
+ // This eliminates the need to filter TRPC-specific properties
60
+ return async (payload: any, sessionArg?: Session) => {
61
+ // Determine session to use
62
+ let session = sessionArg;
63
+ if (!session && autoSession && defaultSession) {
64
+ session = defaultSession;
65
+ }
66
+
67
+ // Prepare input for TRPC call
68
+ const input = {
69
+ payload,
70
+ session
71
+ };
72
+
73
+ // Access TRPC provider and method lazily
74
+ const trpcProvider = trpcClient[providerName];
75
+ const trpcMethod = trpcProvider[methodName];
76
+
77
+ // Use decorator metadata to determine if this is a query or mutation
78
+ // Note: We can't directly check the original provider here since we only have
79
+ // the TRPC client, so we'll fall back to the router's procedure type detection
80
+ if (trpcMethod?.query) {
81
+ return await trpcMethod.query(input);
82
+ } else if (trpcMethod?.mutate) {
83
+ return await trpcMethod.mutate(input);
84
+ } else {
85
+ throw new Error(`Method ${String(providerName)}.${String(methodName)} not found on TRPC client`);
86
+ }
87
+ };
88
+ }
89
+ });
90
+ }
91
+ });
92
+ }
93
+
94
+ /**
95
+ * Session provider interface for dependency injection
96
+ */
97
+ export interface SessionProvider {
98
+ getSession(): Promise<Session> | Session;
99
+ }
100
+
101
+ /**
102
+ * Create a TRPC client with session provider for automatic session management
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * const sessionProvider: SessionProvider = {
107
+ * getSession: () => getCurrentUserSession()
108
+ * };
109
+ *
110
+ * const client = createTRPCClientWithSessionProvider(trpc, sessionProvider);
111
+ *
112
+ * // Session is automatically provided, fully typed
113
+ * const product = await client.product.getById({ id: '123' });
114
+ * ```
115
+ */
116
+ export function createTRPCClientWithSessionProvider<TOriginalClient extends Partial<Client>>(
117
+ trpcClient: any,
118
+ sessionProvider: SessionProvider
119
+ ): TransparentClient<TOriginalClient> {
120
+ return new Proxy({} as TransparentClient<TOriginalClient>, {
121
+ get(target, providerName: string | symbol) {
122
+ if (typeof providerName !== 'string') {
123
+ return undefined;
124
+ }
125
+
126
+ return new Proxy({}, {
127
+ get(providerTarget, methodName: string | symbol) {
128
+ if (typeof methodName !== 'string') {
129
+ return undefined;
130
+ }
131
+
132
+ return async (payload: any, sessionArg?: Session) => {
133
+ // If no session provided, get from provider
134
+ let session = sessionArg;
135
+ if (!session) {
136
+ session = await sessionProvider.getSession();
137
+ }
138
+
139
+ const input = {
140
+ payload,
141
+ session
142
+ };
143
+
144
+ // Access TRPC provider and method lazily
145
+ const trpcProvider = trpcClient[providerName];
146
+ const trpcMethod = trpcProvider[methodName];
147
+
148
+ // Use TRPC client's procedure type detection
149
+ if (trpcMethod?.query) {
150
+ return await trpcMethod.query(input);
151
+ } else if (trpcMethod?.mutate) {
152
+ return await trpcMethod.mutate(input);
153
+ } else {
154
+ throw new Error(`Method ${String(providerName)}.${String(methodName)} not found on TRPC client`);
155
+ }
156
+ };
157
+ }
158
+ });
159
+ }
160
+ });
161
+ }
162
+
163
+ /**
164
+ * Type alias for creating typed TRPC clients
165
+ * Use the original client type, not the router type
166
+ *
167
+ * @example
168
+ * ```typescript
169
+ * type MyClient = typeof serverClient;
170
+ *
171
+ * function useClient(): MyClient {
172
+ * return createTRPCClient<MyClient>(trpcProxyClient);
173
+ * }
174
+ * ```
175
+ */
176
+ export type TRPCClientFromRouter<TOriginalClient> = TOriginalClient;
package/trpc/src/index.ts CHANGED
@@ -1,70 +1,43 @@
1
+ // Re-export server utilities
2
+ export {
3
+ createTRPCServerRouter,
4
+ createTRPCContext,
5
+ router,
6
+ mergeRouters,
7
+ type TRPCRouterFromClient
8
+ } from './server';
9
+
10
+ // Re-export client utilities
11
+ export {
12
+ createTRPCClient,
13
+ createTRPCClientWithSessionProvider,
14
+ type TRPCClientOptions,
15
+ type SessionProvider,
16
+ type TRPCClientFromRouter
17
+ } from './client';
18
+
19
+ // Re-export type utilities
20
+ export {
21
+ type ClientMethodMap,
22
+ type MethodInfo,
23
+ type TRPCMethodInput,
24
+ type TransparentClient,
25
+ introspectClient,
26
+ isQueryMethod,
27
+ isMutationMethod
28
+ } from './types';
29
+
30
+ // Legacy exports for backward compatibility
1
31
  import { initTRPC } from '@trpc/server';
2
- import {
3
- Client,
4
- Session,
5
- } from '@reactionary/core';
6
- import superjson from 'superjson';
7
- import { z } from 'zod';
8
- import { BaseProvider } from '@reactionary/core';
9
- import { TRPCQueryProcedure, TRPCMutationProcedure } from '@trpc/server';
32
+ import { Client, Session } from '@reactionary/core';
10
33
  import { createTRPCTracing } from '@reactionary/otel';
11
34
 
12
- const t = initTRPC.context<{ client: Client; session: Session }>().create({
13
- transformer: superjson,
14
- });
15
-
16
- export const router = t.router;
17
- export const mergeRouters = t.mergeRouters;
35
+ const t = initTRPC.context<{ client: Client; session: Session }>().create({});
18
36
 
19
37
  // Always apply tracing middleware - exporters controlled via OTEL env vars
20
38
  const basePublicProcedure = t.procedure;
21
39
  export const publicProcedure = basePublicProcedure.use(createTRPCTracing());
22
40
 
23
- export function createTRPCRouter<T extends Client = Client>(client: T) {
24
- type BaseProviderKeys<T> = {
25
- [K in keyof T]: T[K] extends BaseProvider ? K : never;
26
- }[keyof T];
27
-
28
- type ReactionaryRouter = {
29
- [Property in BaseProviderKeys<Client>]: TRPCQueryProcedure<{
30
- input: Array<z.infer<T[Property]['querySchema']>>;
31
- output: Array<z.infer<Awaited<T[Property]['schema']>>>;
32
- meta: any;
33
- }>;
34
- } & {
35
- [Property in BaseProviderKeys<Client> as `${Property}Mutation`]: TRPCMutationProcedure<{
36
- input: Array<z.infer<T[Property]['mutationSchema']>>;
37
- output: z.infer<Awaited<T[Property]['schema']>>;
38
- meta: any;
39
- }>;
40
- };
41
-
42
- const routes: Record<string, any> = {};
43
- // Always enable tracing - exporters are controlled via env vars
44
- const procedure = basePublicProcedure.use(createTRPCTracing());
45
-
46
- for (const key in client) {
47
- const provider = client[key];
48
-
49
- if (provider instanceof BaseProvider) {
50
- const queryKey = key as keyof ReactionaryRouter;
51
- const mutationKey = key + 'Mutation' as keyof ReactionaryRouter;
52
-
53
- routes[queryKey] = procedure
54
- .input(provider.querySchema.array())
55
- .output(provider.schema.array())
56
- .query(async (opts) => {
57
- return provider.query(opts.input, opts.ctx.session);
58
- });
59
-
60
- routes[mutationKey] = procedure
61
- .input(provider.mutationSchema.array())
62
- .output(provider.schema)
63
- .mutation(async (opts) => {
64
- return provider.mutate(opts.input, opts.ctx.session);
65
- });
66
- }
67
- }
68
-
69
- return router<ReactionaryRouter>(routes as ReactionaryRouter);
70
- }
41
+ // Legacy function - deprecated, use createTRPCServerRouter instead
42
+ import { createTRPCServerRouter } from './server';
43
+ export const createTRPCRouter = createTRPCServerRouter;