@reactionary/source 0.0.48 → 0.0.52

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 (175) hide show
  1. package/core/package.json +4 -3
  2. package/core/src/cache/cache.interface.ts +1 -1
  3. package/core/src/cache/memory-cache.ts +2 -2
  4. package/core/src/cache/noop-cache.ts +1 -1
  5. package/core/src/cache/redis-cache.ts +1 -1
  6. package/core/src/client/client-builder.ts +4 -4
  7. package/core/src/client/client.ts +12 -12
  8. package/core/src/decorators/reactionary.decorator.ts +22 -2
  9. package/core/src/index.ts +14 -14
  10. package/core/src/initialization.ts +1 -1
  11. package/core/src/providers/analytics.provider.ts +2 -2
  12. package/core/src/providers/base.provider.ts +5 -5
  13. package/core/src/providers/cart.provider.ts +6 -6
  14. package/core/src/providers/category.provider.ts +4 -9
  15. package/core/src/providers/checkout.provider.ts +156 -0
  16. package/core/src/providers/identity.provider.ts +5 -5
  17. package/core/src/providers/index.ts +13 -12
  18. package/core/src/providers/inventory.provider.ts +4 -4
  19. package/core/src/providers/order.provider.ts +31 -0
  20. package/core/src/providers/price.provider.ts +5 -5
  21. package/core/src/providers/product.provider.ts +5 -5
  22. package/core/src/providers/profile.provider.ts +5 -5
  23. package/core/src/providers/search.provider.ts +4 -4
  24. package/core/src/providers/store.provider.ts +4 -4
  25. package/core/src/schemas/capabilities.schema.ts +2 -1
  26. package/core/src/schemas/models/analytics.model.ts +1 -1
  27. package/core/src/schemas/models/cart.model.ts +3 -28
  28. package/core/src/schemas/models/category.model.ts +2 -2
  29. package/core/src/schemas/models/checkout.model.ts +66 -0
  30. package/core/src/schemas/models/cost.model.ts +21 -0
  31. package/core/src/schemas/models/identifiers.model.ts +23 -2
  32. package/core/src/schemas/models/identity.model.ts +8 -5
  33. package/core/src/schemas/models/index.ts +19 -15
  34. package/core/src/schemas/models/inventory.model.ts +2 -2
  35. package/core/src/schemas/models/order.model.ts +46 -0
  36. package/core/src/schemas/models/payment.model.ts +5 -12
  37. package/core/src/schemas/models/price.model.ts +3 -3
  38. package/core/src/schemas/models/product.model.ts +6 -3
  39. package/core/src/schemas/models/profile.model.ts +2 -2
  40. package/core/src/schemas/models/search.model.ts +2 -3
  41. package/core/src/schemas/models/shipping-method.model.ts +34 -3
  42. package/core/src/schemas/models/store.model.ts +2 -2
  43. package/core/src/schemas/mutations/analytics.mutation.ts +2 -2
  44. package/core/src/schemas/mutations/cart.mutation.ts +5 -5
  45. package/core/src/schemas/mutations/checkout.mutation.ts +50 -0
  46. package/core/src/schemas/mutations/identity.mutation.ts +1 -1
  47. package/core/src/schemas/mutations/index.ts +10 -10
  48. package/core/src/schemas/mutations/profile.mutation.ts +1 -1
  49. package/core/src/schemas/queries/cart.query.ts +2 -2
  50. package/core/src/schemas/queries/category.query.ts +3 -3
  51. package/core/src/schemas/queries/checkout.query.ts +22 -0
  52. package/core/src/schemas/queries/identity.query.ts +1 -1
  53. package/core/src/schemas/queries/index.ts +13 -12
  54. package/core/src/schemas/queries/inventory.query.ts +2 -2
  55. package/core/src/schemas/queries/order.query.ts +9 -0
  56. package/core/src/schemas/queries/price.query.ts +2 -2
  57. package/core/src/schemas/queries/product.query.ts +9 -2
  58. package/core/src/schemas/queries/profile.query.ts +1 -1
  59. package/core/src/schemas/queries/search.query.ts +2 -2
  60. package/core/src/schemas/queries/store.query.ts +1 -1
  61. package/core/src/schemas/session.schema.ts +3 -3
  62. package/core/tsconfig.json +3 -2
  63. package/examples/next/next.config.js +17 -6
  64. package/examples/next/src/app/page.tsx +1 -2
  65. package/examples/node/package.json +2 -1
  66. package/examples/node/src/basic/basic-node-setup.spec.ts +1 -1
  67. package/examples/node/tsconfig.json +2 -1
  68. package/examples/node/tsconfig.spec.json +3 -2
  69. package/package.json +3 -1
  70. package/providers/algolia/package.json +2 -1
  71. package/providers/algolia/src/core/initialize.ts +5 -5
  72. package/providers/algolia/src/index.ts +5 -5
  73. package/providers/algolia/src/providers/product.provider.ts +8 -2
  74. package/providers/algolia/src/providers/search.provider.ts +1 -1
  75. package/providers/algolia/src/test/search.provider.spec.ts +1 -1
  76. package/providers/algolia/tsconfig.json +2 -1
  77. package/providers/algolia/tsconfig.spec.json +3 -2
  78. package/providers/commercetools/{jest.config.ts → jest.config.cjs} +1 -1
  79. package/providers/commercetools/package.json +3 -2
  80. package/providers/commercetools/src/core/client.ts +63 -32
  81. package/providers/commercetools/src/core/initialize.ts +20 -16
  82. package/providers/commercetools/src/index.ts +10 -10
  83. package/providers/commercetools/src/providers/cart.provider.ts +14 -19
  84. package/providers/commercetools/src/providers/category.provider.ts +3 -12
  85. package/providers/commercetools/src/providers/checkout.provider.ts +644 -0
  86. package/providers/commercetools/src/providers/identity.provider.ts +8 -8
  87. package/providers/commercetools/src/providers/index.ts +12 -9
  88. package/providers/commercetools/src/providers/inventory.provider.ts +2 -4
  89. package/providers/commercetools/src/providers/order.provider.ts +163 -0
  90. package/providers/commercetools/src/providers/price.provider.ts +3 -3
  91. package/providers/commercetools/src/providers/product.provider.ts +24 -6
  92. package/providers/commercetools/src/providers/profile.provider.ts +2 -2
  93. package/providers/commercetools/src/providers/search.provider.ts +3 -5
  94. package/providers/commercetools/src/providers/store.provider.ts +3 -3
  95. package/providers/commercetools/src/schema/capabilities.schema.ts +2 -1
  96. package/providers/commercetools/src/schema/commercetools.schema.ts +7 -5
  97. package/providers/commercetools/src/schema/configuration.schema.ts +2 -0
  98. package/providers/commercetools/src/test/cart.provider.spec.ts +24 -4
  99. package/providers/commercetools/src/test/category.provider.spec.ts +3 -3
  100. package/providers/commercetools/src/test/checkout.provider.spec.ts +312 -0
  101. package/providers/commercetools/src/test/identity.provider.spec.ts +3 -3
  102. package/providers/commercetools/src/test/inventory.provider.spec.ts +2 -2
  103. package/providers/commercetools/src/test/price.provider.spec.ts +4 -4
  104. package/providers/commercetools/src/test/product.provider.spec.ts +22 -5
  105. package/providers/commercetools/src/test/profile.provider.spec.ts +3 -3
  106. package/providers/commercetools/src/test/search.provider.spec.ts +2 -2
  107. package/providers/commercetools/src/test/store.provider.spec.ts +2 -2
  108. package/providers/commercetools/src/test/test-utils.ts +14 -0
  109. package/providers/commercetools/tsconfig.json +2 -1
  110. package/providers/commercetools/tsconfig.spec.json +4 -3
  111. package/providers/fake/{jest.config.ts → jest.config.cjs} +1 -1
  112. package/providers/fake/package.json +2 -2
  113. package/providers/fake/src/core/initialize.ts +6 -6
  114. package/providers/fake/src/index.ts +4 -4
  115. package/providers/fake/src/providers/analytics.provider.ts +1 -1
  116. package/providers/fake/src/providers/cart.provider.ts +2 -2
  117. package/providers/fake/src/providers/category.provider.ts +7 -3
  118. package/providers/fake/src/providers/identity.provider.ts +1 -1
  119. package/providers/fake/src/providers/index.ts +9 -9
  120. package/providers/fake/src/providers/inventory.provider.ts +1 -1
  121. package/providers/fake/src/providers/price.provider.ts +1 -1
  122. package/providers/fake/src/providers/product.provider.ts +10 -4
  123. package/providers/fake/src/providers/search.provider.ts +2 -5
  124. package/providers/fake/src/providers/store.provider.ts +2 -3
  125. package/providers/fake/src/test/cart.provider.spec.ts +3 -3
  126. package/providers/fake/src/test/category.provider.spec.ts +2 -2
  127. package/providers/fake/src/test/price.provider.spec.ts +2 -2
  128. package/providers/fake/src/test/product.provider.spec.ts +8 -8
  129. package/providers/fake/src/test/test-utils.ts +1 -1
  130. package/providers/fake/tsconfig.json +2 -1
  131. package/providers/fake/tsconfig.spec.json +1 -3
  132. package/providers/posthog/package.json +4 -4
  133. package/providers/posthog/project.json +2 -2
  134. package/providers/posthog/src/core/initialize.ts +2 -2
  135. package/providers/posthog/src/index.ts +3 -3
  136. package/providers/posthog/tsconfig.json +2 -1
  137. package/tsconfig.base.json +3 -4
  138. package/.claude/settings.local.json +0 -28
  139. package/core/src/providers/cart-payment.provider.ts +0 -57
  140. package/core/src/schemas/mutations/cart-payment.mutation.ts +0 -21
  141. package/core/src/schemas/queries/cart-payment.query.ts +0 -12
  142. package/otel/README.md +0 -227
  143. package/otel/eslint.config.mjs +0 -23
  144. package/otel/package.json +0 -11
  145. package/otel/pnpm-lock.yaml +0 -805
  146. package/otel/project.json +0 -33
  147. package/otel/src/index.ts +0 -22
  148. package/otel/src/metrics.ts +0 -76
  149. package/otel/src/provider-instrumentation.ts +0 -108
  150. package/otel/src/test/otel.spec.ts +0 -8
  151. package/otel/src/trace-decorator.ts +0 -226
  152. package/otel/src/tracer.ts +0 -83
  153. package/otel/src/trpc-middleware.ts +0 -128
  154. package/otel/tsconfig.json +0 -23
  155. package/otel/tsconfig.lib.json +0 -23
  156. package/otel/tsconfig.spec.json +0 -28
  157. package/otel/vite.config.ts +0 -24
  158. package/providers/commercetools/src/providers/cart-payment.provider.ts +0 -193
  159. package/providers/commercetools/src/test/cart-payment.provider.spec.ts +0 -145
  160. package/trpc/README.md +0 -7
  161. package/trpc/__mocks__/superjson.js +0 -25
  162. package/trpc/eslint.config.mjs +0 -19
  163. package/trpc/jest.config.ts +0 -14
  164. package/trpc/package.json +0 -14
  165. package/trpc/project.json +0 -31
  166. package/trpc/src/client.ts +0 -175
  167. package/trpc/src/index.ts +0 -44
  168. package/trpc/src/integration.spec.ts +0 -223
  169. package/trpc/src/server.ts +0 -125
  170. package/trpc/src/test-utils.ts +0 -31
  171. package/trpc/src/transparent-client.spec.ts +0 -162
  172. package/trpc/src/types.ts +0 -144
  173. package/trpc/tsconfig.json +0 -16
  174. package/trpc/tsconfig.lib.json +0 -10
  175. package/trpc/tsconfig.spec.json +0 -15
@@ -1,175 +0,0 @@
1
- import type { Client, RequestContext} from '@reactionary/core';
2
- import { Session } from '@reactionary/core';
3
- import type { TransparentClient } from './types';
4
-
5
- /**
6
- * Configuration options for TRPC client creation
7
- */
8
- export interface TRPCClientOptions {
9
- /** Default session to use if not provided in method calls */
10
- defaultRequestContext?: RequestContext
11
- /** Whether to automatically provide request context from defaultRequestContext\ */
12
- autoRequestContext?: boolean;
13
- }
14
-
15
- /**
16
- * Create a type-safe client proxy that uses the original client's type interface
17
- * while routing all calls through TRPC
18
- *
19
- * @example
20
- * ```typescript
21
- * import { createTRPCProxyClient } from '@trpc/client';
22
- * import { createTRPCClient } from '@reactionary/trpc/client';
23
- *
24
- * const trpc = createTRPCProxyClient<AppRouter>({
25
- * url: 'http://localhost:3000',
26
- * });
27
- *
28
- * // Pass the original client type as the generic parameter
29
- * const client = createTRPCClient<typeof serverClient>(trpc, {
30
- * defaultSession: mySession,
31
- * autoSession: true
32
- * });
33
- *
34
- * // Fully typed using the original client interface!
35
- * const product = await client.product.getById({ id: '123' }, reqCtx);
36
- * ```
37
- */
38
- export function createTRPCClient<TOriginalClient extends Partial<Client>>(
39
- trpcClient: any,
40
- options: TRPCClientOptions = {}
41
- ): TransparentClient<TOriginalClient> {
42
- const { defaultRequestContext, autoRequestContext = false } = options;
43
-
44
- return new Proxy({} as TransparentClient<TOriginalClient>, {
45
- get(target, providerName: string | symbol) {
46
- if (typeof providerName !== 'string') {
47
- return undefined;
48
- }
49
-
50
- // Return a typed proxy for the provider that intercepts method calls
51
- return new Proxy({}, {
52
- get(providerTarget, methodName: string | symbol) {
53
- if (typeof methodName !== 'string') {
54
- return undefined;
55
- }
56
-
57
- // Only expose methods that are marked with TRPC decorators
58
- // This eliminates the need to filter TRPC-specific properties
59
- return async (payload: any, reqCtxArg?: RequestContext) => {
60
- // Determine request context to use
61
- let reqCtx = reqCtxArg;
62
- if (!reqCtx && autoRequestContext && defaultRequestContext) {
63
- reqCtx = defaultRequestContext;
64
- }
65
-
66
- // Prepare input for TRPC call
67
- const input = {
68
- payload,
69
- reqCtx
70
- };
71
-
72
- // Access TRPC provider and method lazily
73
- const trpcProvider = trpcClient[providerName];
74
- const trpcMethod = trpcProvider[methodName];
75
-
76
- // Use decorator metadata to determine if this is a query or mutation
77
- // Note: We can't directly check the original provider here since we only have
78
- // the TRPC client, so we'll fall back to the router's procedure type detection
79
- if (trpcMethod?.query) {
80
- return await trpcMethod.query(input);
81
- } else if (trpcMethod?.mutate) {
82
- return await trpcMethod.mutate(input);
83
- } else {
84
- throw new Error(`Method ${String(providerName)}.${String(methodName)} not found on TRPC client`);
85
- }
86
- };
87
- }
88
- });
89
- }
90
- });
91
- }
92
-
93
- /**
94
- * Session provider interface for dependency injection
95
- */
96
- export interface SessionProvider {
97
- getRequestContext(): Promise<RequestContext> | RequestContext;
98
- }
99
-
100
- /**
101
- * Create a TRPC client with session provider for automatic session management
102
- *
103
- * @example
104
- * ```typescript
105
- * const sessionProvider: SessionProvider = {
106
- * getSession: () => getCurrentUserSession()
107
- * };
108
- *
109
- * const client = createTRPCClientWithSessionProvider(trpc, reqCtxProvider);
110
- *
111
- * // Session is automatically provided, fully typed
112
- * const product = await client.product.getById({ id: '123' });
113
- * ```
114
- */
115
- export function createTRPCClientWithSessionProvider<TOriginalClient extends Partial<Client>>(
116
- trpcClient: any,
117
- sessionProvider: SessionProvider
118
- ): TransparentClient<TOriginalClient> {
119
- return new Proxy({} as TransparentClient<TOriginalClient>, {
120
- get(target, providerName: string | symbol) {
121
- if (typeof providerName !== 'string') {
122
- return undefined;
123
- }
124
-
125
- return new Proxy({}, {
126
- get(providerTarget, methodName: string | symbol) {
127
- if (typeof methodName !== 'string') {
128
- return undefined;
129
- }
130
-
131
- return async (payload: any, reqCtxArg?: RequestContext) => {
132
- // If no session provided, get from provider
133
- let reqCtx = reqCtxArg;
134
- if (!reqCtx) {
135
- reqCtx = await sessionProvider.getRequestContext();
136
- }
137
-
138
- const input = {
139
- payload,
140
- reqCtx
141
- };
142
-
143
- // Access TRPC provider and method lazily
144
- const trpcProvider = trpcClient[providerName];
145
- const trpcMethod = trpcProvider[methodName];
146
-
147
- // Use TRPC client's procedure type detection
148
- if (trpcMethod?.query) {
149
- return await trpcMethod.query(input);
150
- } else if (trpcMethod?.mutate) {
151
- return await trpcMethod.mutate(input);
152
- } else {
153
- throw new Error(`Method ${String(providerName)}.${String(methodName)} not found on TRPC client`);
154
- }
155
- };
156
- }
157
- });
158
- }
159
- });
160
- }
161
-
162
- /**
163
- * Type alias for creating typed TRPC clients
164
- * Use the original client type, not the router type
165
- *
166
- * @example
167
- * ```typescript
168
- * type MyClient = typeof serverClient;
169
- *
170
- * function useClient(): MyClient {
171
- * return createTRPCClient<MyClient>(trpcProxyClient);
172
- * }
173
- * ```
174
- */
175
- export type TRPCClientFromRouter<TOriginalClient> = TOriginalClient;
package/trpc/src/index.ts DELETED
@@ -1,44 +0,0 @@
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
31
- import { initTRPC } from '@trpc/server';
32
- import type { Client, RequestContext} from '@reactionary/core';
33
- import { Session } from '@reactionary/core';
34
- import { createTRPCTracing } from '@reactionary/otel';
35
-
36
- const t = initTRPC.context<{ client: Client; reqCtx: RequestContext }>().create({});
37
-
38
- // Always apply tracing middleware - exporters controlled via OTEL env vars
39
- const basePublicProcedure = t.procedure;
40
- export const publicProcedure = basePublicProcedure.use(createTRPCTracing());
41
-
42
- // Legacy function - deprecated, use createTRPCServerRouter instead
43
- import { createTRPCServerRouter } from './server';
44
- export const createTRPCRouter = createTRPCServerRouter;
@@ -1,223 +0,0 @@
1
- import { ClientBuilder, NoOpCache } from '@reactionary/core';
2
- import { withFakeCapabilities } from '@reactionary/provider-fake';
3
- import { createTRPCServerRouter, createTRPCContext } from './server';
4
- import { createTRPCClient } from './client';
5
- import type { TransparentClient } from './types';
6
- import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
7
- import { createHTTPHandler } from '@trpc/server/adapters/standalone';
8
- import * as http from 'http';
9
- import { createInitialRequestContext } from '@reactionary/core';
10
-
11
- /**
12
- * Integration test that actually starts an HTTP server and makes real network calls
13
- * This is the real test that verifies the TRPC transparent transport works end-to-end
14
- */
15
-
16
- // Polyfill fetch for Node.js
17
- global.fetch = global.fetch || require('node-fetch');
18
-
19
- // Create the server-side client
20
- const serverClient = new ClientBuilder()
21
- .withCapability(
22
- withFakeCapabilities(
23
- {
24
- jitter: {
25
- mean: 0,
26
- deviation: 0,
27
- },
28
- seeds: {
29
- category: 1,
30
- product: 1,
31
- search: 1
32
- }
33
- },
34
- { search: true, product: true, identity: false }
35
- )
36
- )
37
- .withCache(new NoOpCache())
38
- .build();
39
-
40
- // Create TRPC router from the client (do this at module level for type inference)
41
- const router = createTRPCServerRouter(serverClient);
42
- type AppRouter = typeof router;
43
-
44
- xdescribe('TRPC Integration Test - Real HTTP Server', () => {
45
- let server: http.Server;
46
- let serverPort: number;
47
- let trpcProxyClient: ReturnType<typeof createTRPCProxyClient<AppRouter>>;
48
- let transparentClient: TransparentClient<typeof serverClient>;
49
-
50
- beforeAll(async () => {
51
-
52
- // Create TRPC HTTP handler
53
- const handler = createHTTPHandler({
54
- router,
55
- createContext: createTRPCContext,
56
- });
57
-
58
- // Start HTTP server with TRPC handler
59
- server = http.createServer(handler);
60
-
61
- // Find available port
62
- serverPort = 3001;
63
- await new Promise<void>((resolve, reject) => {
64
- const tryPort = (port: number) => {
65
- server.listen(port, (err?: Error) => {
66
- if (err) {
67
- if (port < 3010) {
68
- tryPort(port + 1);
69
- } else {
70
- reject(err);
71
- }
72
- } else {
73
- serverPort = port;
74
- resolve();
75
- }
76
- });
77
- };
78
- tryPort(serverPort);
79
- });
80
-
81
- // Create real TRPC proxy client (no transformer for testing)
82
- trpcProxyClient = createTRPCProxyClient<AppRouter>({
83
- links: [
84
- httpBatchLink({
85
- url: `http://localhost:${serverPort}`,
86
- }),
87
- ],
88
- });
89
-
90
- // Create transparent client using the real implementation - now properly typed!
91
- transparentClient = createTRPCClient<typeof serverClient>(trpcProxyClient);
92
- });
93
-
94
- afterAll(async () => {
95
- if (server) {
96
- await new Promise<void>((resolve) => {
97
- server.close(() => resolve());
98
- });
99
- }
100
- });
101
-
102
- const reqCtx = createInitialRequestContext();
103
-
104
- describe('Product Provider via HTTP', () => {
105
- it('should fetch product by slug through real HTTP calls', async () => {
106
- const slug = 'integration-test-product';
107
-
108
- // Get result from transparent client (through HTTP/TRPC)
109
- const trpcResult = await transparentClient.product.getBySlug(
110
- { slug },
111
- reqCtx
112
- );
113
-
114
- // Get result from server client (direct call)
115
- const directResult = await serverClient.product.getBySlug(
116
- { slug },
117
- reqCtx
118
- );
119
-
120
- // Results should have the same structure
121
- expect(trpcResult).toBeDefined();
122
- expect(trpcResult.slug).toBe(slug);
123
- expect(trpcResult.name).toBeDefined();
124
- expect(trpcResult.description).toBeDefined();
125
- expect(trpcResult.image).toBeDefined();
126
-
127
- // Both should have the same slug (faker uses seed for consistency)
128
- expect(trpcResult.slug).toBe(directResult.slug);
129
- });
130
-
131
- it('should fetch product by id through real HTTP calls', async () => {
132
- const productId = 'integration-test-id';
133
-
134
- const trpcResult = await transparentClient.product.getById(
135
- { id: productId },
136
- reqCtx
137
- );
138
-
139
- const directResult = await serverClient.product.getById(
140
- { id: productId },
141
- reqCtx
142
- );
143
-
144
- expect(trpcResult).toBeDefined();
145
- expect(trpcResult.identifier.key).toBe(productId);
146
- expect(trpcResult.name).toBeDefined();
147
- expect(trpcResult.description).toBeDefined();
148
-
149
- // Should match direct call
150
- expect(trpcResult.identifier?.key).toBe(directResult.identifier?.key);
151
- });
152
- });
153
-
154
- describe('Search Provider via HTTP', () => {
155
- it('should perform search through real HTTP calls', async () => {
156
- const searchTerm = 'integration test search';
157
-
158
- const trpcResult = await transparentClient.search.queryByTerm(
159
- {
160
- search: {
161
- term: searchTerm,
162
- page: 0,
163
- pageSize: 10,
164
- facets: []
165
- }
166
- },
167
- reqCtx
168
- );
169
-
170
- const directResult = await serverClient.search.queryByTerm(
171
- {
172
- search: {
173
- term: searchTerm,
174
- page: 0,
175
- pageSize: 10,
176
- facets: []
177
- }
178
- },
179
- reqCtx
180
- );
181
-
182
- expect(trpcResult).toBeDefined();
183
- expect(trpcResult.products).toBeDefined();
184
- expect(Array.isArray(trpcResult.products)).toBe(true);
185
- expect(trpcResult.facets).toBeDefined();
186
-
187
- // Should match direct call structure
188
- expect(trpcResult.products.length).toBe(directResult.products.length);
189
- });
190
- });
191
-
192
- describe('Network Error Handling', () => {
193
- it('should handle HTTP errors gracefully', async () => {
194
- // This should work normally first
195
- const result = await transparentClient.product.getById(
196
- { id: 'test-error-handling' },
197
- reqCtx
198
- );
199
- expect(result).toBeDefined();
200
- });
201
- });
202
-
203
- describe('API Equivalence', () => {
204
- it('should produce identical results for TRPC vs direct calls', async () => {
205
- const testId = 'equivalence-test';
206
-
207
- // Make same call through both paths
208
- const [trpcResult, directResult] = await Promise.all([
209
- transparentClient.product.getById(
210
- { id: testId },
211
- reqCtx
212
- ),
213
- serverClient.product.getById({ id: testId }, reqCtx)
214
- ]);
215
-
216
- // Results should be structurally equivalent
217
- expect(trpcResult.identifier.key).toBe(directResult.identifier.key);
218
- expect(trpcResult.name).toBe(directResult.name);
219
- expect(trpcResult.slug).toBe(directResult.slug);
220
- expect(trpcResult.description).toBe(directResult.description);
221
- });
222
- });
223
- });
@@ -1,125 +0,0 @@
1
- import { initTRPC } from '@trpc/server';
2
- import type { Client, RequestContext, Session } from '@reactionary/core';
3
- import superjson from 'superjson';
4
- import { z } from 'zod';
5
- import { createTRPCTracing } from '@reactionary/otel';
6
- import type {
7
- MethodInfo
8
- } from './types';
9
- import {
10
- introspectClient
11
- } from './types';
12
-
13
- // Initialize TRPC with context containing session (no transformer for testing)
14
- const t = initTRPC.context<{ reqCtx?: RequestContext }>().create();
15
-
16
- export const router = t.router;
17
- export const mergeRouters = t.mergeRouters;
18
-
19
- // Apply tracing middleware
20
- const baseProcedure = t.procedure.use(createTRPCTracing());
21
-
22
- /**
23
- * Create a TRPC router from a built client instance
24
- * This function introspects the client and automatically creates TRPC procedures
25
- * for all provider methods while maintaining type safety
26
- *
27
- * @example
28
- * ```typescript
29
- * const client = buildClient([
30
- * withFakeCapabilities(config, { product: true, search: true })
31
- * ]);
32
- *
33
- * const router = createTRPCServerRouter(client);
34
- * ```
35
- */
36
- export function createTRPCServerRouter<T extends Partial<Client>>(client: T) {
37
- const methods = introspectClient(client);
38
-
39
- // Group methods by provider
40
- const providerMethods = methods.reduce((acc, method) => {
41
- if (!acc[method.providerName]) {
42
- acc[method.providerName] = [];
43
- }
44
- acc[method.providerName].push(method);
45
- return acc;
46
- }, {} as Record<string, MethodInfo[]>);
47
-
48
- // Build router structure
49
- const routes: Record<string, any> = {};
50
-
51
- for (const [providerName, providerMethodsList] of Object.entries(providerMethods)) {
52
- const providerRoutes: Record<string, any> = {};
53
-
54
- for (const methodInfo of providerMethodsList) {
55
- const procedure = createProcedureForMethod(methodInfo);
56
- providerRoutes[methodInfo.name] = procedure;
57
- }
58
-
59
- routes[providerName] = t.router(providerRoutes);
60
- }
61
-
62
- return t.router(routes);
63
- }
64
-
65
- /**
66
- * Create a TRPC procedure for a specific provider method
67
- */
68
- function createProcedureForMethod(methodInfo: MethodInfo) {
69
- // Create input schema - we use a flexible schema since we want to preserve
70
- // the original method signatures without requiring schema definitions
71
- const inputSchema = z.object({
72
- payload: z.any(), // The actual payload from the provider method
73
- reqCtx: z.any().optional(), // Session is optional in input since it might come from context
74
- });
75
-
76
- const procedureWithInput = baseProcedure.input(inputSchema);
77
-
78
- if (methodInfo.isQuery) {
79
- return procedureWithInput.query(async ({ input, ctx }) => {
80
- const reqCtx = input.reqCtx || ctx.reqCtx;
81
-
82
- // Call the original provider method
83
- if (reqCtx) {
84
- return await methodInfo.method(input.payload, reqCtx);
85
- } else {
86
- // Some methods might not require session
87
- return await methodInfo.method(input.payload);
88
- }
89
- });
90
- } else if (methodInfo.isMutation) {
91
- return procedureWithInput.mutation(async ({ input, ctx }) => {
92
- const reqCtx = input.reqCtx || ctx.reqCtx;
93
-
94
- // Call the original provider method
95
- if (reqCtx) {
96
- return await methodInfo.method(input.payload, reqCtx);
97
- } else {
98
- // Some methods might not require session
99
- return await methodInfo.method(input.payload);
100
- }
101
- });
102
- } else {
103
- throw new Error(`Method ${methodInfo.name} is neither query nor mutation`);
104
- }
105
- }
106
-
107
- /**
108
- * Type helper to extract the router type from a client
109
- * This enables full type safety on the client side
110
- */
111
- export type TRPCRouterFromClient<T extends Partial<Client>> = ReturnType<typeof createTRPCServerRouter<T>>;
112
-
113
- /**
114
- * Context creator for TRPC server
115
- * Override this to provide session from your authentication system
116
- */
117
- export function createTRPCContext(_opts: { req?: any; res?: any }) {
118
- // Default implementation - you should override this based on your auth system
119
- return {
120
- session: undefined as Session | undefined,
121
- };
122
- }
123
-
124
- // Create publicProcedure here to avoid circular imports
125
- export const publicProcedure = baseProcedure;
@@ -1,31 +0,0 @@
1
- import type { Session } from '@reactionary/core';
2
-
3
- export function createAnonymousTestSession(): Session {
4
- return {
5
- id: 'test-session-id',
6
- identity: {
7
- type: 'Anonymous',
8
- meta: {
9
- cache: { hit: false, key: '' },
10
- placeholder: false,
11
- },
12
- id: { userId: 'anonymous' },
13
- token: undefined,
14
- issued: new Date(),
15
- expiry: new Date(new Date().getTime() + 3600 * 1000),
16
- logonId: "",
17
- createdAt: "",
18
- updatedAt: "",
19
- keyring: [],
20
- currentService: undefined
21
- },
22
- languageContext: {
23
- locale: 'en-US',
24
- currencyCode: 'USD',
25
- countryCode: 'US',
26
- },
27
- storeIdentifier: {
28
- key: 'the-good-store',
29
- },
30
- };
31
- }