@reactionary/source 0.0.38 → 0.0.40
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.
- package/core/package.json +2 -3
- package/core/src/index.ts +0 -2
- package/core/src/schemas/capabilities.schema.ts +1 -1
- package/core/src/schemas/models/base.model.ts +5 -5
- package/core/src/schemas/models/cart.model.ts +1 -1
- package/core/src/schemas/models/identifiers.model.ts +12 -12
- package/core/src/schemas/models/price.model.ts +1 -1
- package/core/src/schemas/models/product.model.ts +2 -2
- package/core/src/schemas/models/search.model.ts +3 -3
- package/core/src/schemas/mutations/base.mutation.ts +1 -1
- package/core/src/schemas/mutations/inventory.mutation.ts +0 -4
- package/core/src/schemas/mutations/price.mutation.ts +0 -4
- package/core/src/schemas/mutations/product.mutation.ts +0 -4
- package/core/src/schemas/mutations/search.mutation.ts +0 -4
- package/core/src/schemas/queries/analytics.query.ts +0 -4
- package/core/src/schemas/queries/base.query.ts +1 -1
- package/core/src/schemas/queries/cart.query.ts +0 -1
- package/core/src/schemas/queries/inventory.query.ts +0 -4
- package/examples/next/.swcrc +30 -0
- package/examples/next/eslint.config.mjs +21 -0
- package/examples/next/index.d.ts +6 -0
- package/examples/next/next-env.d.ts +5 -0
- package/examples/next/next.config.js +20 -0
- package/examples/next/project.json +9 -0
- package/examples/next/public/.gitkeep +0 -0
- package/examples/next/public/favicon.ico +0 -0
- package/examples/next/src/app/global.css +0 -0
- package/examples/next/src/app/layout.tsx +18 -0
- package/examples/next/src/app/page.module.scss +2 -0
- package/examples/next/src/app/page.tsx +51 -0
- package/examples/next/src/instrumentation.ts +9 -0
- package/examples/next/tsconfig.json +44 -0
- package/examples/node/src/basic/basic-node-provider-model-extension.spec.ts +0 -1
- package/examples/node/src/basic/basic-node-setup.spec.ts +0 -1
- package/otel/README.md +152 -172
- package/otel/package.json +0 -1
- package/otel/src/index.ts +16 -6
- package/otel/src/metrics.ts +3 -3
- package/otel/src/trace-decorator.ts +76 -97
- package/otel/src/tracer.ts +3 -3
- package/package.json +2 -2
- package/providers/algolia/package.json +1 -1
- package/providers/algolia/src/schema/configuration.schema.ts +1 -1
- package/providers/algolia/src/test/search.provider.spec.ts +2 -2
- package/providers/commercetools/package.json +1 -1
- package/providers/commercetools/src/schema/configuration.schema.ts +1 -1
- package/providers/fake/package.json +1 -1
- package/providers/fake/src/providers/cart.provider.ts +1 -1
- package/providers/fake/src/providers/search.provider.ts +11 -2
- package/providers/fake/src/schema/configuration.schema.ts +3 -3
- package/providers/fake/src/test/category.provider.spec.ts +1 -3
- package/providers/posthog/package.json +1 -1
- package/providers/posthog/src/schema/configuration.schema.ts +1 -1
- package/trpc/package.json +1 -2
- package/trpc/src/client.ts +1 -3
- package/tsconfig.base.json +2 -0
- package/core/src/decorators/trpc.decorators.ts +0 -144
- package/otel/src/sdk.ts +0 -57
package/otel/src/tracer.ts
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
SpanOptions,
|
|
9
9
|
Attributes,
|
|
10
10
|
} from '@opentelemetry/api';
|
|
11
|
-
import { isOtelInitialized } from './sdk';
|
|
12
11
|
|
|
13
12
|
const TRACER_NAME = '@reactionary/otel';
|
|
14
13
|
const TRACER_VERSION = '0.0.1';
|
|
@@ -17,8 +16,9 @@ let globalTracer: Tracer | null = null;
|
|
|
17
16
|
|
|
18
17
|
export function getTracer(): Tracer {
|
|
19
18
|
if (!globalTracer) {
|
|
20
|
-
//
|
|
21
|
-
|
|
19
|
+
// Simply get the tracer from the API
|
|
20
|
+
// If the SDK is not initialized by the host application,
|
|
21
|
+
// this will return a ProxyTracer that produces NonRecordingSpans
|
|
22
22
|
globalTracer = trace.getTracer(TRACER_NAME, TRACER_VERSION);
|
|
23
23
|
}
|
|
24
24
|
return globalTracer;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reactionary/source",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.40",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"private": false,
|
|
6
6
|
"dependencies": {
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"search-insights": "^2.17.3",
|
|
47
47
|
"superjson": "^2.2.2",
|
|
48
48
|
"vue": "^3.5.13",
|
|
49
|
-
"zod": "4.
|
|
49
|
+
"zod": "4.1.9",
|
|
50
50
|
"zone.js": "~0.15.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SearchResultSchema } from '@reactionary/core';
|
|
1
|
+
import { NoOpCache, SearchResultSchema } from '@reactionary/core';
|
|
2
2
|
import { AlgoliaSearchProvider } from '../providers/search.provider';
|
|
3
3
|
|
|
4
4
|
describe('Algolia Search Provider', () => {
|
|
@@ -6,7 +6,7 @@ describe('Algolia Search Provider', () => {
|
|
|
6
6
|
apiKey: process.env['ALGOLIA_API_KEY'] || '',
|
|
7
7
|
appId: process.env['ALGOLIA_APP_ID'] || '',
|
|
8
8
|
indexName: process.env['ALGOLIA_INDEX'] || '',
|
|
9
|
-
}, SearchResultSchema);
|
|
9
|
+
}, SearchResultSchema, new NoOpCache());
|
|
10
10
|
|
|
11
11
|
it('should be able to get a result by term', async () => {
|
|
12
12
|
const result = await provider.get({
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from '@reactionary/core';
|
|
11
11
|
import z from 'zod';
|
|
12
12
|
import { FakeConfiguration } from '../schema/configuration.schema';
|
|
13
|
-
import { Faker, en, base } from '@faker-js/faker
|
|
13
|
+
import { Faker, en, base } from '@faker-js/faker';
|
|
14
14
|
|
|
15
15
|
export class FakeCartProvider<
|
|
16
16
|
T extends Cart = Cart
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SearchProvider,
|
|
3
|
-
SearchQueryByTerm,
|
|
4
3
|
SearchResult,
|
|
5
4
|
SearchResultFacet,
|
|
6
5
|
SearchResultProduct,
|
|
7
|
-
Session,
|
|
8
6
|
Cache as ReactionaryCache,
|
|
9
7
|
} from '@reactionary/core';
|
|
8
|
+
import type { SearchQueryByTerm, Session } from '@reactionary/core';
|
|
10
9
|
import z from 'zod';
|
|
11
10
|
import { FakeConfiguration } from '../schema/configuration.schema';
|
|
12
11
|
import { Faker, en, base } from '@faker-js/faker';
|
|
13
12
|
import { jitter } from '../utilities/jitter';
|
|
13
|
+
import { traced } from '@reactionary/otel';
|
|
14
14
|
|
|
15
15
|
export class FakeSearchProvider<
|
|
16
16
|
T extends SearchResult = SearchResult
|
|
@@ -23,6 +23,7 @@ export class FakeSearchProvider<
|
|
|
23
23
|
this.config = config;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
@traced()
|
|
26
27
|
public override async queryByTerm(
|
|
27
28
|
payload: SearchQueryByTerm,
|
|
28
29
|
_session: Session
|
|
@@ -119,6 +120,14 @@ export class FakeSearchProvider<
|
|
|
119
120
|
},
|
|
120
121
|
} satisfies SearchResult;
|
|
121
122
|
|
|
123
|
+
const foo = this.childFunction();
|
|
124
|
+
|
|
122
125
|
return this.schema.parse(result);
|
|
123
126
|
}
|
|
127
|
+
|
|
128
|
+
@traced()
|
|
129
|
+
protected childFunction() {
|
|
130
|
+
const foo = 42;
|
|
131
|
+
return foo;
|
|
132
|
+
}
|
|
124
133
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
|
-
export const FakeConfigurationSchema = z.
|
|
3
|
+
export const FakeConfigurationSchema = z.looseObject({
|
|
4
4
|
jitter: z
|
|
5
|
-
.
|
|
5
|
+
.looseObject({
|
|
6
6
|
mean: z.number().min(0).max(10000),
|
|
7
7
|
deviation: z.number().min(0).max(5000),
|
|
8
8
|
})
|
|
@@ -10,7 +10,7 @@ export const FakeConfigurationSchema = z.looseInterface({
|
|
|
10
10
|
mean: 0,
|
|
11
11
|
deviation: 0,
|
|
12
12
|
}),
|
|
13
|
-
seeds: z.
|
|
13
|
+
seeds: z.looseObject({
|
|
14
14
|
product: z.number().min(0).max(10000).default(1),
|
|
15
15
|
search: z.number().min(0).max(10000).default(1),
|
|
16
16
|
category: z.number().min(0).max(10000).default(1),
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import 'dotenv/config'
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
import { CategorySchema, NoOpCache,
|
|
5
|
-
|
|
6
|
-
import { getTracer, shutdownOtel } from '@reactionary/otel';
|
|
4
|
+
import { CategorySchema, NoOpCache, Session } from '@reactionary/core';
|
|
7
5
|
import { FakeCategoryProvider } from '../providers';
|
|
8
6
|
import { createAnonymousTestSession, getFakerTestConfiguration } from './test-utils';
|
|
9
7
|
describe('Faker Category Provider', () => {
|
package/trpc/package.json
CHANGED
package/trpc/src/client.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { Client, Session
|
|
1
|
+
import { Client, Session } from '@reactionary/core';
|
|
2
2
|
import type { TransparentClient } from './types';
|
|
3
|
-
import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
|
|
4
|
-
import type { TRPCClientError } from '@trpc/client';
|
|
5
3
|
|
|
6
4
|
/**
|
|
7
5
|
* Configuration options for TRPC client creation
|
package/tsconfig.base.json
CHANGED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import 'reflect-metadata';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Metadata keys for TRPC method decorators
|
|
5
|
-
*/
|
|
6
|
-
export const TRPC_QUERY_METADATA_KEY = Symbol('trpc:query');
|
|
7
|
-
export const TRPC_MUTATION_METADATA_KEY = Symbol('trpc:mutation');
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Options for TRPC method decorators
|
|
13
|
-
*/
|
|
14
|
-
export interface TRPCMethodOptions {
|
|
15
|
-
/** Custom name for the TRPC procedure (defaults to method name) */
|
|
16
|
-
name?: string;
|
|
17
|
-
/** Description for documentation purposes */
|
|
18
|
-
description?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Decorator to mark a provider method as a TRPC query procedure
|
|
23
|
-
* Query procedures are read-only operations (GET-like)
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* ```typescript
|
|
27
|
-
* class ProductProvider extends BaseProvider {
|
|
28
|
-
* @trpcQuery()
|
|
29
|
-
* async getById(payload: ProductQueryById, session: Session): Promise<Product> {
|
|
30
|
-
* // implementation
|
|
31
|
-
* }
|
|
32
|
-
*
|
|
33
|
-
* @trpcQuery({ name: 'findBySlug', description: 'Find product by URL slug' })
|
|
34
|
-
* async getBySlug(payload: ProductQueryBySlug, session: Session): Promise<Product> {
|
|
35
|
-
* // implementation
|
|
36
|
-
* }
|
|
37
|
-
* }
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
40
|
-
export function trpcQuery(options: TRPCMethodOptions = {}): MethodDecorator {
|
|
41
|
-
return function (target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) {
|
|
42
|
-
// Store metadata about this method being a TRPC query
|
|
43
|
-
const metadata = {
|
|
44
|
-
methodName: String(propertyKey),
|
|
45
|
-
isQuery: true,
|
|
46
|
-
isMutation: false,
|
|
47
|
-
options
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
// Store on the prototype so it's inherited
|
|
51
|
-
Reflect.defineMetadata(TRPC_QUERY_METADATA_KEY, metadata, target, propertyKey);
|
|
52
|
-
|
|
53
|
-
// Also store a list of all TRPC methods on the class
|
|
54
|
-
const existingMethods = Reflect.getMetadata(TRPC_QUERY_METADATA_KEY, target.constructor) || [];
|
|
55
|
-
existingMethods.push({ propertyKey, metadata });
|
|
56
|
-
Reflect.defineMetadata(TRPC_QUERY_METADATA_KEY, existingMethods, target.constructor);
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Decorator to mark a provider method as a TRPC mutation procedure
|
|
62
|
-
* Mutation procedures are write operations that modify state (POST/PUT/DELETE-like)
|
|
63
|
-
*
|
|
64
|
-
* @example
|
|
65
|
-
* ```typescript
|
|
66
|
-
* class CartProvider extends BaseProvider {
|
|
67
|
-
* @trpcMutation()
|
|
68
|
-
* async add(payload: CartAddMutation, session: Session): Promise<Cart> {
|
|
69
|
-
* // implementation
|
|
70
|
-
* }
|
|
71
|
-
*
|
|
72
|
-
* @trpcMutation({ name: 'removeItem' })
|
|
73
|
-
* async remove(payload: CartRemoveMutation, session: Session): Promise<Cart> {
|
|
74
|
-
* // implementation
|
|
75
|
-
* }
|
|
76
|
-
* }
|
|
77
|
-
* ```
|
|
78
|
-
*/
|
|
79
|
-
export function trpcMutation(options: TRPCMethodOptions = {}): MethodDecorator {
|
|
80
|
-
return function (target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) {
|
|
81
|
-
// Store metadata about this method being a TRPC mutation
|
|
82
|
-
const metadata = {
|
|
83
|
-
methodName: String(propertyKey),
|
|
84
|
-
isQuery: false,
|
|
85
|
-
isMutation: true,
|
|
86
|
-
options
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
// Store on the prototype so it's inherited
|
|
90
|
-
Reflect.defineMetadata(TRPC_MUTATION_METADATA_KEY, metadata, target, propertyKey);
|
|
91
|
-
|
|
92
|
-
// Also store a list of all TRPC methods on the class
|
|
93
|
-
const existingMethods = Reflect.getMetadata(TRPC_MUTATION_METADATA_KEY, target.constructor) || [];
|
|
94
|
-
existingMethods.push({ propertyKey, metadata });
|
|
95
|
-
Reflect.defineMetadata(TRPC_MUTATION_METADATA_KEY, existingMethods, target.constructor);
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Get all TRPC query methods from a class or instance
|
|
101
|
-
*/
|
|
102
|
-
export function getTRPCQueryMethods(target: any): Array<{ propertyKey: string | symbol; metadata: any }> {
|
|
103
|
-
const constructor = typeof target === 'function' ? target : target.constructor;
|
|
104
|
-
return Reflect.getMetadata(TRPC_QUERY_METADATA_KEY, constructor) || [];
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Get all TRPC mutation methods from a class or instance
|
|
109
|
-
*/
|
|
110
|
-
export function getTRPCMutationMethods(target: any): Array<{ propertyKey: string | symbol; metadata: any }> {
|
|
111
|
-
const constructor = typeof target === 'function' ? target : target.constructor;
|
|
112
|
-
return Reflect.getMetadata(TRPC_MUTATION_METADATA_KEY, constructor) || [];
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Get all TRPC methods (both queries and mutations) from a class or instance
|
|
117
|
-
*/
|
|
118
|
-
export function getAllTRPCMethods(target: any): Array<{ propertyKey: string | symbol; metadata: any }> {
|
|
119
|
-
return [
|
|
120
|
-
...getTRPCQueryMethods(target),
|
|
121
|
-
...getTRPCMutationMethods(target)
|
|
122
|
-
];
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Check if a method is marked as a TRPC query
|
|
127
|
-
*/
|
|
128
|
-
export function isTRPCQuery(target: any, methodName: string | symbol): boolean {
|
|
129
|
-
return !!Reflect.getMetadata(TRPC_QUERY_METADATA_KEY, target, methodName);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Check if a method is marked as a TRPC mutation
|
|
134
|
-
*/
|
|
135
|
-
export function isTRPCMutation(target: any, methodName: string | symbol): boolean {
|
|
136
|
-
return !!Reflect.getMetadata(TRPC_MUTATION_METADATA_KEY, target, methodName);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Check if a method is marked for TRPC exposure (query or mutation)
|
|
141
|
-
*/
|
|
142
|
-
export function isTRPCMethod(target: any, methodName: string | symbol): boolean {
|
|
143
|
-
return isTRPCQuery(target, methodName) || isTRPCMutation(target, methodName);
|
|
144
|
-
}
|
package/otel/src/sdk.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { NodeSDK } from '@opentelemetry/sdk-node';
|
|
2
|
-
|
|
3
|
-
let sdk: NodeSDK | null = null;
|
|
4
|
-
let isInitialized = false;
|
|
5
|
-
let initializationPromise: Promise<void> | null = null;
|
|
6
|
-
|
|
7
|
-
// Detect if we're running in a browser environment
|
|
8
|
-
function isBrowser(): boolean {
|
|
9
|
-
return typeof window !== 'undefined' && typeof process === 'undefined';
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// Auto-initialize OTEL on first use with standard env vars
|
|
13
|
-
function ensureInitialized(): void {
|
|
14
|
-
if (isInitialized || initializationPromise) {
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Skip initialization in browser environments
|
|
19
|
-
if (isBrowser()) {
|
|
20
|
-
isInitialized = true;
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Prevent multiple initialization attempts
|
|
25
|
-
initializationPromise = Promise.resolve().then(() => {
|
|
26
|
-
// Let NodeSDK handle everything automatically via env vars
|
|
27
|
-
// The SDK will automatically pick up OTEL_* environment variables
|
|
28
|
-
sdk = new NodeSDK();
|
|
29
|
-
|
|
30
|
-
sdk.start();
|
|
31
|
-
isInitialized = true;
|
|
32
|
-
|
|
33
|
-
process.on('SIGTERM', async () => {
|
|
34
|
-
try {
|
|
35
|
-
await shutdownOtel();
|
|
36
|
-
if (process.env['OTEL_LOG_LEVEL'] === 'debug') {
|
|
37
|
-
console.log('OpenTelemetry terminated successfully');
|
|
38
|
-
}
|
|
39
|
-
} catch (error) {
|
|
40
|
-
console.error('Error terminating OpenTelemetry', error);
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export async function shutdownOtel(): Promise<void> {
|
|
47
|
-
if (sdk) {
|
|
48
|
-
await sdk.shutdown();
|
|
49
|
-
sdk = null;
|
|
50
|
-
isInitialized = false;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function isOtelInitialized(): boolean {
|
|
55
|
-
ensureInitialized();
|
|
56
|
-
return isInitialized;
|
|
57
|
-
}
|