@reactionary/provider-fake 0.3.12 → 0.3.13
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/initialize.js +4 -0
- package/package.json +2 -2
- package/providers/index.js +1 -0
- package/providers/product-reviews.provider.js +149 -0
- package/schema/capabilities.schema.js +2 -1
- package/src/providers/index.d.ts +1 -0
- package/src/providers/product-reviews.provider.d.ts +12 -0
- package/src/schema/capabilities.schema.d.ts +1 -0
- package/src/utilities/seed.d.ts +1 -0
- package/utilities/seed.js +11 -0
package/core/initialize.js
CHANGED
|
@@ -12,6 +12,7 @@ import { FakeCheckoutProvider } from "../providers/checkout.provider.js";
|
|
|
12
12
|
import { FakeOrderSearchProvider } from "../providers/order-search.provider.js";
|
|
13
13
|
import { FakeOrderProvider } from "../providers/order.provider.js";
|
|
14
14
|
import { FakeProfileProvider } from "../providers/profile.provider.js";
|
|
15
|
+
import { FakeProductReviewsProvider } from "../providers/product-reviews.provider.js";
|
|
15
16
|
function withFakeCapabilities(configuration, capabilities) {
|
|
16
17
|
return (cache, context) => {
|
|
17
18
|
const client = {};
|
|
@@ -63,6 +64,9 @@ function withFakeCapabilities(configuration, capabilities) {
|
|
|
63
64
|
if (capabilities.profile) {
|
|
64
65
|
client.profile = new FakeProfileProvider(configuration, cache, context);
|
|
65
66
|
}
|
|
67
|
+
if (capabilities.productReviews) {
|
|
68
|
+
client.productReviews = new FakeProductReviewsProvider(configuration, cache, context);
|
|
69
|
+
}
|
|
66
70
|
return client;
|
|
67
71
|
};
|
|
68
72
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reactionary/provider-fake",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.13",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"types": "src/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@reactionary/core": "0.3.
|
|
7
|
+
"@reactionary/core": "0.3.13",
|
|
8
8
|
"zod": "4.1.9",
|
|
9
9
|
"@faker-js/faker": "^9.8.0"
|
|
10
10
|
},
|
package/providers/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export * from "./order-search.provider.js";
|
|
|
8
8
|
export * from "./order.provider.js";
|
|
9
9
|
export * from "./price.provider.js";
|
|
10
10
|
export * from "./product.provider.js";
|
|
11
|
+
export * from "./product-reviews.provider.js";
|
|
11
12
|
export * from "./product-search.provider.js";
|
|
12
13
|
export * from "./profile.provider.js";
|
|
13
14
|
export * from "./store.provider.js";
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result)
|
|
9
|
+
__defProp(target, key, result);
|
|
10
|
+
return result;
|
|
11
|
+
};
|
|
12
|
+
import {
|
|
13
|
+
ProductReviewsProvider,
|
|
14
|
+
Reactionary,
|
|
15
|
+
success,
|
|
16
|
+
error,
|
|
17
|
+
ProductReviewSchema,
|
|
18
|
+
ProductRatingSummarySchema,
|
|
19
|
+
ProductReviewPaginatedResultSchema
|
|
20
|
+
} from "@reactionary/core";
|
|
21
|
+
import { base, en, Faker } from "@faker-js/faker";
|
|
22
|
+
import { calcSeed } from "../utilities/seed.js";
|
|
23
|
+
class FakeProductReviewsProvider extends ProductReviewsProvider {
|
|
24
|
+
constructor(config, cache, context) {
|
|
25
|
+
super(cache, context);
|
|
26
|
+
this.config = config;
|
|
27
|
+
this.faker = new Faker({ locale: [en] });
|
|
28
|
+
}
|
|
29
|
+
createReviewsForProduct(productIdentifier) {
|
|
30
|
+
const seed = calcSeed(productIdentifier.key);
|
|
31
|
+
this.faker.seed(seed);
|
|
32
|
+
const hasAnyReviews = this.faker.datatype.boolean({ probability: 0.5 });
|
|
33
|
+
if (!hasAnyReviews) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
if (productIdentifier.key === "unknown-product-id") {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
const reviews = [];
|
|
40
|
+
const totalReviews = this.faker.number.int({ min: 1, max: 20 });
|
|
41
|
+
for (let i = 0; i < totalReviews; i++) {
|
|
42
|
+
const review = {
|
|
43
|
+
identifier: {
|
|
44
|
+
key: `fake-review-${productIdentifier.key}-${i}`
|
|
45
|
+
},
|
|
46
|
+
product: productIdentifier,
|
|
47
|
+
authorName: this.faker.person.fullName(),
|
|
48
|
+
authorId: this.faker.string.uuid(),
|
|
49
|
+
rating: this.faker.number.int({ min: 1, max: 5 }),
|
|
50
|
+
title: this.faker.lorem.sentence(),
|
|
51
|
+
content: this.faker.lorem.paragraphs({ min: 1, max: 5 }),
|
|
52
|
+
createdAt: this.faker.date.past({ years: 1 }).toISOString(),
|
|
53
|
+
updatedAt: this.faker.datatype.boolean() ? this.faker.date.recent({ days: 30 }).toISOString() : void 0,
|
|
54
|
+
verified: this.faker.datatype.boolean(),
|
|
55
|
+
reply: this.faker.datatype.boolean({ probability: 0.3 }) ? this.faker.lorem.sentences(2) : void 0,
|
|
56
|
+
repliedAt: this.faker.datatype.boolean({ probability: 0.3 }) ? this.faker.date.recent({ days: 7 }).toISOString() : void 0
|
|
57
|
+
};
|
|
58
|
+
reviews.push(review);
|
|
59
|
+
}
|
|
60
|
+
return reviews.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
61
|
+
}
|
|
62
|
+
async getRatingSummary(query) {
|
|
63
|
+
const reviews = this.createReviewsForProduct(query.product);
|
|
64
|
+
if (reviews.length === 0) {
|
|
65
|
+
const emptySummary = this.createEmptyProductRatingSummary({ product: query.product });
|
|
66
|
+
return success(emptySummary);
|
|
67
|
+
}
|
|
68
|
+
const totalRatings = reviews.length;
|
|
69
|
+
const averageRating = reviews.reduce((sum, review) => sum + review.rating, 0) / (totalRatings || 1);
|
|
70
|
+
const ratingDistribution = {
|
|
71
|
+
"1": reviews.filter((x) => x.rating === 1).length,
|
|
72
|
+
"2": reviews.filter((x) => x.rating === 2).length,
|
|
73
|
+
"3": reviews.filter((x) => x.rating === 3).length,
|
|
74
|
+
"4": reviews.filter((x) => x.rating === 4).length,
|
|
75
|
+
"5": reviews.filter((x) => x.rating === 5).length
|
|
76
|
+
};
|
|
77
|
+
const summary = {
|
|
78
|
+
identifier: {
|
|
79
|
+
product: query.product
|
|
80
|
+
},
|
|
81
|
+
averageRating,
|
|
82
|
+
totalRatings,
|
|
83
|
+
ratingDistribution
|
|
84
|
+
};
|
|
85
|
+
return success(summary);
|
|
86
|
+
}
|
|
87
|
+
async findReviews(query) {
|
|
88
|
+
const pageSize = query.paginationOptions?.pageSize ?? 20;
|
|
89
|
+
const pageNumber = query.paginationOptions?.pageNumber ?? 1;
|
|
90
|
+
const reviews = this.createReviewsForProduct(query.product);
|
|
91
|
+
const returnedReviews = reviews.slice((pageNumber - 1) * pageSize, pageNumber * pageSize);
|
|
92
|
+
const paginatedResult = {
|
|
93
|
+
items: returnedReviews,
|
|
94
|
+
totalCount: reviews.length,
|
|
95
|
+
pageSize,
|
|
96
|
+
pageNumber,
|
|
97
|
+
totalPages: Math.ceil(reviews.length / Math.max(pageSize, 1))
|
|
98
|
+
};
|
|
99
|
+
return success(paginatedResult);
|
|
100
|
+
}
|
|
101
|
+
async submitReview(mutation) {
|
|
102
|
+
if (this.context.session.identityContext.identity.type !== "Registered") {
|
|
103
|
+
return error({ type: "InvalidInput", error: "Only registered users can submit reviews." });
|
|
104
|
+
}
|
|
105
|
+
const review = {
|
|
106
|
+
identifier: {
|
|
107
|
+
key: this.faker.string.uuid()
|
|
108
|
+
},
|
|
109
|
+
product: mutation.product,
|
|
110
|
+
authorName: mutation.authorName,
|
|
111
|
+
rating: mutation.rating,
|
|
112
|
+
title: mutation.title,
|
|
113
|
+
content: mutation.content,
|
|
114
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
115
|
+
verified: this.faker.datatype.boolean()
|
|
116
|
+
};
|
|
117
|
+
return success(review);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
__decorateClass([
|
|
121
|
+
Reactionary({
|
|
122
|
+
outputSchema: ProductRatingSummarySchema,
|
|
123
|
+
cache: true,
|
|
124
|
+
cacheTimeToLiveInSeconds: 300,
|
|
125
|
+
currencyDependentCaching: false,
|
|
126
|
+
localeDependentCaching: false
|
|
127
|
+
})
|
|
128
|
+
], FakeProductReviewsProvider.prototype, "getRatingSummary", 1);
|
|
129
|
+
__decorateClass([
|
|
130
|
+
Reactionary({
|
|
131
|
+
outputSchema: ProductReviewPaginatedResultSchema,
|
|
132
|
+
cache: true,
|
|
133
|
+
cacheTimeToLiveInSeconds: 60,
|
|
134
|
+
currencyDependentCaching: false,
|
|
135
|
+
localeDependentCaching: true
|
|
136
|
+
})
|
|
137
|
+
], FakeProductReviewsProvider.prototype, "findReviews", 1);
|
|
138
|
+
__decorateClass([
|
|
139
|
+
Reactionary({
|
|
140
|
+
outputSchema: ProductReviewSchema,
|
|
141
|
+
cache: false,
|
|
142
|
+
cacheTimeToLiveInSeconds: 0,
|
|
143
|
+
currencyDependentCaching: false,
|
|
144
|
+
localeDependentCaching: false
|
|
145
|
+
})
|
|
146
|
+
], FakeProductReviewsProvider.prototype, "submitReview", 1);
|
|
147
|
+
export {
|
|
148
|
+
FakeProductReviewsProvider
|
|
149
|
+
};
|
package/src/providers/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from './order-search.provider.js';
|
|
|
8
8
|
export * from './order.provider.js';
|
|
9
9
|
export * from './price.provider.js';
|
|
10
10
|
export * from './product.provider.js';
|
|
11
|
+
export * from './product-reviews.provider.js';
|
|
11
12
|
export * from './product-search.provider.js';
|
|
12
13
|
export * from './profile.provider.js';
|
|
13
14
|
export * from './store.provider.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ProductReviewsProvider } from '@reactionary/core';
|
|
2
|
+
import type { ProductReview, ProductRatingSummary, ProductReviewPaginatedResult, ProductReviewsListQuery, ProductReviewsGetRatingSummaryQuery, ProductReviewMutationSubmit, Result, RequestContext, Cache, ProductIdentifier } from '@reactionary/core';
|
|
3
|
+
import type { FakeConfiguration } from '../schema/configuration.schema.js';
|
|
4
|
+
export declare class FakeProductReviewsProvider extends ProductReviewsProvider {
|
|
5
|
+
protected config: FakeConfiguration;
|
|
6
|
+
private faker;
|
|
7
|
+
constructor(config: FakeConfiguration, cache: Cache, context: RequestContext);
|
|
8
|
+
protected createReviewsForProduct(productIdentifier: ProductIdentifier): ProductReview[];
|
|
9
|
+
getRatingSummary(query: ProductReviewsGetRatingSummaryQuery): Promise<Result<ProductRatingSummary>>;
|
|
10
|
+
findReviews(query: ProductReviewsListQuery): Promise<Result<ProductReviewPaginatedResult>>;
|
|
11
|
+
submitReview(mutation: ProductReviewMutationSubmit): Promise<Result<ProductReview>>;
|
|
12
|
+
}
|
|
@@ -11,6 +11,7 @@ export declare const FakeCapabilitiesSchema: z.ZodObject<{
|
|
|
11
11
|
profile: z.ZodOptional<z.ZodBoolean>;
|
|
12
12
|
store: z.ZodOptional<z.ZodBoolean>;
|
|
13
13
|
productSearch: z.ZodOptional<z.ZodBoolean>;
|
|
14
|
+
productReviews: z.ZodOptional<z.ZodBoolean>;
|
|
14
15
|
orderSearch: z.ZodOptional<z.ZodBoolean>;
|
|
15
16
|
}, z.core.$loose>;
|
|
16
17
|
export type FakeCapabilities = z.infer<typeof FakeCapabilitiesSchema>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function calcSeed(input: string): number;
|