@reactionary/source 0.3.0 → 0.3.1
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/src/client/client-builder.ts +3 -7
- package/core/src/client/client.ts +2 -3
- package/core/src/decorators/reactionary.decorator.ts +2 -2
- package/core/src/initialization.ts +8 -3
- package/core/src/providers/analytics.provider.ts +75 -0
- package/core/src/providers/cart.provider.ts +3 -0
- package/core/src/providers/category.provider.ts +1 -0
- package/core/src/schemas/errors/invalid-input.error.ts +1 -1
- package/core/src/schemas/errors/invalid-output.error.ts +1 -1
- package/core/src/schemas/models/identifiers.model.ts +3 -0
- package/core/src/schemas/models/order.model.ts +2 -2
- package/core/src/schemas/mutations/analytics/index.ts +23 -0
- package/core/src/schemas/mutations/analytics/product-add-to-cart.mutation.ts +25 -0
- package/core/src/schemas/mutations/analytics/product-details-view.mutation.ts +14 -0
- package/core/src/schemas/mutations/analytics/product-summary-click.mutation.ts +26 -0
- package/core/src/schemas/mutations/analytics/product-summary-view.mutation.ts +25 -0
- package/core/src/schemas/mutations/analytics/purchase.mutation.ts +14 -0
- package/core/src/schemas/mutations/index.ts +1 -1
- package/core/src/schemas/queries/order-search.query.ts +3 -0
- package/core/src/schemas/session.schema.ts +20 -9
- package/core/src/test/client-builder.spec.ts +60 -0
- package/core/src/zod-utils.ts +3 -1
- package/documentation/{1-purpose.md → docs/1-purpose.md} +4 -0
- package/documentation/docs/8-tracking.md +9 -0
- package/documentation/docs/providers/analytics.provider.md +297 -0
- package/documentation/docs/providers/base.provider.md +118 -0
- package/documentation/docs/providers/cart.provider.md +305 -0
- package/documentation/docs/providers/category.provider.md +244 -0
- package/documentation/docs/providers/checkout.provider.md +315 -0
- package/documentation/docs/providers/identity.provider.md +194 -0
- package/documentation/docs/providers/inventory.provider.md +162 -0
- package/documentation/docs/providers/order-search.provider.md +155 -0
- package/documentation/docs/providers/order.provider.md +160 -0
- package/documentation/docs/providers/price.provider.md +197 -0
- package/documentation/docs/providers/product-search.provider.md +265 -0
- package/documentation/docs/providers/product.provider.md +204 -0
- package/documentation/docs/providers/profile.provider.md +283 -0
- package/documentation/docs/providers/store.provider.md +146 -0
- package/documentation/docs/schemas/schemas.md +1862 -0
- package/documentation/docusaurus.config.js +33 -0
- package/documentation/scripts/generate.ts +52 -0
- package/documentation/sidebars.js +8 -0
- package/documentation/src/css/custom.css +3 -0
- package/documentation/src/pages/index.js +12 -0
- package/eslint.config.mjs +1 -1
- package/examples/node/package.json +6 -6
- package/examples/node/src/basic/basic-node-provider-model-extension.spec.ts +0 -2
- package/package.json +19 -5
- package/providers/algolia/project.json +1 -1
- package/providers/algolia/src/core/initialize.ts +5 -0
- package/providers/algolia/src/providers/analytics.provider.ts +112 -0
- package/providers/algolia/src/providers/index.ts +1 -0
- package/providers/commercetools/project.json +1 -1
- package/providers/commercetools/src/providers/profile.provider.ts +1 -4
- package/providers/fake/project.json +1 -1
- package/providers/fake/src/providers/analytics.provider.ts +5 -0
- package/providers/fake/src/providers/checkout.provider.ts +5 -2
- package/providers/fake/src/providers/product.provider.ts +18 -8
- package/providers/fake/src/test/cart.provider.spec.ts +0 -2
- package/providers/fake/src/test/category.provider.spec.ts +3 -3
- package/providers/fake/src/test/checkout.provider.spec.ts +3 -7
- package/providers/google-analytics/README.md +11 -0
- package/providers/google-analytics/eslint.config.mjs +25 -0
- package/providers/google-analytics/package.json +18 -0
- package/providers/google-analytics/project.json +33 -0
- package/providers/google-analytics/src/core/initialize.ts +16 -0
- package/providers/google-analytics/src/index.ts +4 -0
- package/providers/google-analytics/src/providers/analytics.provider.ts +162 -0
- package/providers/google-analytics/src/schema/capabilities.schema.ts +10 -0
- package/providers/google-analytics/src/schema/configuration.schema.ts +9 -0
- package/providers/google-analytics/src/test/analytics.provider.spec.ts +93 -0
- package/providers/google-analytics/tsconfig.json +24 -0
- package/providers/google-analytics/tsconfig.lib.json +23 -0
- package/providers/google-analytics/tsconfig.spec.json +28 -0
- package/providers/google-analytics/vite.config.ts +26 -0
- package/providers/google-analytics/vitest.config.mts +21 -0
- package/providers/medusa/package.json +3 -10
- package/providers/medusa/project.json +1 -1
- package/providers/medusa/src/providers/profile.provider.ts +5 -15
- package/providers/medusa/src/test/test-utils.ts +0 -1
- package/providers/medusa/tsconfig.json +3 -0
- package/providers/medusa/tsconfig.lib.json +16 -1
- package/providers/meilisearch/project.json +1 -1
- package/providers/posthog/project.json +1 -1
- package/tsconfig.base.json +4 -1
- package/.claude/settings.local.json +0 -28
- package/core/src/schemas/mutations/analytics.mutation.ts +0 -23
- package/providers/algolia/src/test/test-utils.ts +0 -31
- /package/documentation/{2-getting-started.md → docs/2-getting-started.md} +0 -0
- /package/documentation/{3-querying-and-changing-data.md → docs/3-querying-and-changing-data.md} +0 -0
- /package/documentation/{4-product-data.md → docs/4-product-data.md} +0 -0
- /package/documentation/{5-cart-and-checkout.md → docs/5-cart-and-checkout.md} +0 -0
- /package/documentation/{6-product-search.md → docs/6-product-search.md} +0 -0
- /package/documentation/{7-marketing.md → docs/7-marketing.md} +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
title: 'My Project',
|
|
5
|
+
tagline: 'Documentation',
|
|
6
|
+
url: 'https://your-site.com',
|
|
7
|
+
baseUrl: '/',
|
|
8
|
+
onBrokenLinks: 'throw',
|
|
9
|
+
staticDirectories: [path.resolve(__dirname, 'static')],
|
|
10
|
+
i18n: {
|
|
11
|
+
defaultLocale: 'en',
|
|
12
|
+
locales: ['en'],
|
|
13
|
+
},
|
|
14
|
+
markdown: {
|
|
15
|
+
format: 'md',
|
|
16
|
+
},
|
|
17
|
+
presets: [
|
|
18
|
+
[
|
|
19
|
+
'classic',
|
|
20
|
+
{
|
|
21
|
+
docs: {
|
|
22
|
+
path: path.resolve(__dirname, 'docs'),
|
|
23
|
+
routeBasePath: '/',
|
|
24
|
+
sidebarPath: path.resolve(__dirname, 'sidebars.js'),
|
|
25
|
+
},
|
|
26
|
+
blog: false,
|
|
27
|
+
theme: {
|
|
28
|
+
customCss: path.resolve(__dirname, 'src/css/custom.css'),
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
],
|
|
33
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { zod2md } from 'zod2md';
|
|
2
|
+
import { writeFileSync } from 'fs';
|
|
3
|
+
import * as td from 'typedoc';
|
|
4
|
+
import type { TypeDocOptions } from 'typedoc';
|
|
5
|
+
import type { PluginOptions as MarkdownPluginOptions } from 'typedoc-plugin-markdown';
|
|
6
|
+
import fs from 'fs/promises';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
|
|
9
|
+
type TypedocWithMarkdownOptions = TypeDocOptions & MarkdownPluginOptions;
|
|
10
|
+
|
|
11
|
+
const projects = [
|
|
12
|
+
{
|
|
13
|
+
entry: 'core/src/schemas/index.ts',
|
|
14
|
+
title: 'Schemas',
|
|
15
|
+
output: 'documentation/docs/schemas/schemas.md',
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
async function main() {
|
|
20
|
+
for (const project of projects) {
|
|
21
|
+
const markdown = await zod2md({
|
|
22
|
+
entry: project.entry,
|
|
23
|
+
title: `${project.title} Schemas`,
|
|
24
|
+
tsconfig: './core/tsconfig.lib.json',
|
|
25
|
+
});
|
|
26
|
+
writeFileSync(project.output, markdown);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const typedocConfig = {
|
|
30
|
+
entryPoints: ['core/src/providers/*.provider.ts'],
|
|
31
|
+
tsconfig: 'core/tsconfig.lib.json',
|
|
32
|
+
plugin: ['typedoc-plugin-markdown'],
|
|
33
|
+
out: 'documentation/docs/providers',
|
|
34
|
+
outputFileStrategy: 'modules',
|
|
35
|
+
categorizeByGroup: true,
|
|
36
|
+
readme: 'none',
|
|
37
|
+
membersWithOwnFile: [],
|
|
38
|
+
modulesFileName: undefined,
|
|
39
|
+
} satisfies TypedocWithMarkdownOptions;
|
|
40
|
+
const app = await td.Application.bootstrapWithPlugins(typedocConfig);
|
|
41
|
+
|
|
42
|
+
const project = await app.convert();
|
|
43
|
+
if (project) {
|
|
44
|
+
await app.generateOutputs(project);
|
|
45
|
+
|
|
46
|
+
await fs.rm(path.join('documentation/docs/providers', 'README.md'), {
|
|
47
|
+
force: true,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
main();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import Layout from '@theme/Layout';
|
|
2
|
+
|
|
3
|
+
export default function Home() {
|
|
4
|
+
return (
|
|
5
|
+
<Layout title="Home">
|
|
6
|
+
<main style={{ padding: '2rem' }}>
|
|
7
|
+
<h1>Welcome to My Docs</h1>
|
|
8
|
+
<p>Get started by reading the <a href="/docs/intro">introduction</a>.</p>
|
|
9
|
+
</main>
|
|
10
|
+
</Layout>
|
|
11
|
+
);
|
|
12
|
+
}
|
package/eslint.config.mjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reactionary/examples-node",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"types": "src/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@reactionary/core": "0.3.
|
|
8
|
-
"@reactionary/provider-commercetools": "0.3.
|
|
9
|
-
"@reactionary/provider-algolia": "0.3.
|
|
10
|
-
"@reactionary/provider-medusa": "0.3.
|
|
11
|
-
"@reactionary/provider-meilisearch": "0.3.
|
|
7
|
+
"@reactionary/core": "0.3.1",
|
|
8
|
+
"@reactionary/provider-commercetools": "0.3.1",
|
|
9
|
+
"@reactionary/provider-algolia": "0.3.1",
|
|
10
|
+
"@reactionary/provider-medusa": "0.3.1",
|
|
11
|
+
"@reactionary/provider-meilisearch": "0.3.1"
|
|
12
12
|
},
|
|
13
13
|
"type": "module"
|
|
14
14
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reactionary/source",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"private": false,
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@commercetools/platform-sdk": "^8.16.0",
|
|
8
8
|
"@commercetools/ts-client": "^4.2.1",
|
|
9
|
+
"@commercetools/ts-sdk-apm": "^4.0.0",
|
|
10
|
+
"@docusaurus/core": "^3.9.2",
|
|
11
|
+
"@docusaurus/preset-classic": "^3.9.2",
|
|
9
12
|
"@faker-js/faker": "^9.8.0",
|
|
10
13
|
"@medusajs/js-sdk": "^2.13.0",
|
|
11
14
|
"@opentelemetry/api": "^1.9.0",
|
|
@@ -19,7 +22,6 @@
|
|
|
19
22
|
"meilisearch": "^0.55.0",
|
|
20
23
|
"node-object-hash": "^3.1.1",
|
|
21
24
|
"posthog-node": "^5.24.0",
|
|
22
|
-
"search-insights": "^2.17.3",
|
|
23
25
|
"zod": "4.1.9"
|
|
24
26
|
},
|
|
25
27
|
"devDependencies": {
|
|
@@ -44,15 +46,23 @@
|
|
|
44
46
|
"@types/debug": "^4.1.12",
|
|
45
47
|
"@types/node": "^24.0.0",
|
|
46
48
|
"@typescript-eslint/utils": "^8.33.1",
|
|
49
|
+
"@vitest/coverage-v8": "^4.0.0",
|
|
50
|
+
"docusaurus-plugin-typedoc": "^1.4.2",
|
|
51
|
+
"esbuild": "^0.19.2",
|
|
52
|
+
"jsonc-eslint-parser": "^2.1.0",
|
|
47
53
|
"nx": "22.4.5",
|
|
48
|
-
"prettier": "
|
|
54
|
+
"prettier": "~3.6.2",
|
|
49
55
|
"ts-node": "10.9.1",
|
|
50
56
|
"tslib": "^2.3.0",
|
|
57
|
+
"typedoc": "^0.28.16",
|
|
58
|
+
"typedoc-plugin-markdown": "^4.9.0",
|
|
51
59
|
"typescript": "5.9.3",
|
|
52
60
|
"typescript-eslint": "^8.33.1",
|
|
61
|
+
"verdaccio": "^6.0.5",
|
|
53
62
|
"vite": "7.1.9",
|
|
54
63
|
"vite-tsconfig-paths": "^5.1.4",
|
|
55
|
-
"vitest": "^4.0.9"
|
|
64
|
+
"vitest": "^4.0.9",
|
|
65
|
+
"zod2md": "^0.2.5"
|
|
56
66
|
},
|
|
57
67
|
"nx": {
|
|
58
68
|
"includedScripts": []
|
|
@@ -62,5 +72,9 @@
|
|
|
62
72
|
"provenance": false
|
|
63
73
|
},
|
|
64
74
|
"packageManager": "pnpm@8.15.9+sha512.499434c9d8fdd1a2794ebf4552b3b25c0a633abcee5bb15e7b5de90f32f47b513aca98cd5cfd001c31f0db454bc3804edccd578501e4ca293a6816166bbd9f81",
|
|
65
|
-
"scripts": {
|
|
75
|
+
"scripts": {
|
|
76
|
+
"docs:start": "docusaurus start --config documentation/docusaurus.config.js",
|
|
77
|
+
"docs:build": "docusaurus build --config documentation/docusaurus.config.js",
|
|
78
|
+
"docs:generate": "node ./documentation/scripts/generate.ts"
|
|
79
|
+
}
|
|
66
80
|
}
|
|
@@ -2,6 +2,7 @@ import type { Cache, ClientFromCapabilities, RequestContext } from "@reactionary
|
|
|
2
2
|
import { AlgoliaSearchProvider } from "../providers/product-search.provider.js";
|
|
3
3
|
import type { AlgoliaCapabilities } from "../schema/capabilities.schema.js";
|
|
4
4
|
import type { AlgoliaConfiguration } from "../schema/configuration.schema.js";
|
|
5
|
+
import { AlgoliaAnalyticsProvider } from "../providers/analytics.provider.js";
|
|
5
6
|
|
|
6
7
|
export function withAlgoliaCapabilities<T extends AlgoliaCapabilities>(configuration: AlgoliaConfiguration, capabilities: T) {
|
|
7
8
|
return (cache: Cache, context: RequestContext): ClientFromCapabilities<T> => {
|
|
@@ -11,6 +12,10 @@ export function withAlgoliaCapabilities<T extends AlgoliaCapabilities>(configura
|
|
|
11
12
|
client.productSearch = new AlgoliaSearchProvider(configuration, cache, context);
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
if (capabilities.analytics) {
|
|
16
|
+
client.analytics = new AlgoliaAnalyticsProvider(cache, context, configuration);
|
|
17
|
+
}
|
|
18
|
+
|
|
14
19
|
return client;
|
|
15
20
|
};
|
|
16
21
|
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AnalyticsProvider,
|
|
3
|
+
type AnalyticsMutationProductAddToCartEvent,
|
|
4
|
+
type AnalyticsMutationProductSummaryClickEvent,
|
|
5
|
+
type AnalyticsMutationProductSummaryViewEvent,
|
|
6
|
+
type AnalyticsMutationPurchaseEvent,
|
|
7
|
+
type Cache,
|
|
8
|
+
type RequestContext,
|
|
9
|
+
} from '@reactionary/core';
|
|
10
|
+
import {
|
|
11
|
+
insightsClient,
|
|
12
|
+
type InsightsClient,
|
|
13
|
+
type ViewedObjectIDs,
|
|
14
|
+
type ClickedObjectIDsAfterSearch,
|
|
15
|
+
type AddedToCartObjectIDsAfterSearch,
|
|
16
|
+
type PurchasedObjectIDs,
|
|
17
|
+
} from 'algoliasearch';
|
|
18
|
+
import type { AlgoliaConfiguration } from '../schema/configuration.schema.js';
|
|
19
|
+
import type { AlgoliaProductSearchIdentifier } from '../schema/search.schema.js';
|
|
20
|
+
|
|
21
|
+
export class AlgoliaAnalyticsProvider extends AnalyticsProvider {
|
|
22
|
+
protected client: InsightsClient;
|
|
23
|
+
protected config: AlgoliaConfiguration;
|
|
24
|
+
|
|
25
|
+
constructor(
|
|
26
|
+
cache: Cache,
|
|
27
|
+
requestContext: RequestContext,
|
|
28
|
+
config: AlgoliaConfiguration
|
|
29
|
+
) {
|
|
30
|
+
super(cache, requestContext);
|
|
31
|
+
|
|
32
|
+
this.config = config;
|
|
33
|
+
this.client = insightsClient(this.config.appId, this.config.apiKey);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
protected override async processProductAddToCart(
|
|
37
|
+
event: AnalyticsMutationProductAddToCartEvent
|
|
38
|
+
) {
|
|
39
|
+
if (event.source && event.source.type === 'search') {
|
|
40
|
+
const algoliaEvent = {
|
|
41
|
+
eventName: 'addToCart',
|
|
42
|
+
eventType: 'conversion',
|
|
43
|
+
eventSubtype: 'addToCart',
|
|
44
|
+
index: this.config.indexName,
|
|
45
|
+
objectIDs: [event.product.key],
|
|
46
|
+
userToken: this.context.session.identityContext.personalizationKey,
|
|
47
|
+
queryID: (event.source.identifier as AlgoliaProductSearchIdentifier)
|
|
48
|
+
.key,
|
|
49
|
+
} satisfies AddedToCartObjectIDsAfterSearch;
|
|
50
|
+
|
|
51
|
+
this.client.pushEvents({
|
|
52
|
+
events: [algoliaEvent],
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
protected override async processProductSummaryClick(
|
|
58
|
+
event: AnalyticsMutationProductSummaryClickEvent
|
|
59
|
+
) {
|
|
60
|
+
if (event.source && event.source.type === 'search') {
|
|
61
|
+
const algoliaEvent = {
|
|
62
|
+
eventName: 'click',
|
|
63
|
+
eventType: 'click',
|
|
64
|
+
index: this.config.indexName,
|
|
65
|
+
objectIDs: [event.product.key],
|
|
66
|
+
userToken: this.context.session.identityContext.personalizationKey,
|
|
67
|
+
positions: [event.position],
|
|
68
|
+
queryID: (event.source.identifier as AlgoliaProductSearchIdentifier)
|
|
69
|
+
.key,
|
|
70
|
+
} satisfies ClickedObjectIDsAfterSearch;
|
|
71
|
+
|
|
72
|
+
this.client.pushEvents({
|
|
73
|
+
events: [algoliaEvent],
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
protected override async processProductSummaryView(
|
|
79
|
+
event: AnalyticsMutationProductSummaryViewEvent
|
|
80
|
+
) {
|
|
81
|
+
if (event.source && event.source.type === 'search') {
|
|
82
|
+
const algoliaEvent = {
|
|
83
|
+
eventName: 'view',
|
|
84
|
+
eventType: 'view',
|
|
85
|
+
index: this.config.indexName,
|
|
86
|
+
objectIDs: event.products.map((x) => x.key),
|
|
87
|
+
userToken: this.context.session.identityContext.personalizationKey,
|
|
88
|
+
} satisfies ViewedObjectIDs;
|
|
89
|
+
|
|
90
|
+
this.client.pushEvents({
|
|
91
|
+
events: [algoliaEvent],
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
protected override async processPurchase(
|
|
97
|
+
event: AnalyticsMutationPurchaseEvent
|
|
98
|
+
): Promise<void> {
|
|
99
|
+
const algoliaEvent = {
|
|
100
|
+
eventName: 'purchase',
|
|
101
|
+
eventType: 'conversion',
|
|
102
|
+
eventSubtype: 'purchase',
|
|
103
|
+
index: this.config.indexName,
|
|
104
|
+
objectIDs: event.order.items.map((x) => x.identifier.key),
|
|
105
|
+
userToken: this.context.session.identityContext.personalizationKey,
|
|
106
|
+
} satisfies PurchasedObjectIDs;
|
|
107
|
+
|
|
108
|
+
this.client.pushEvents({
|
|
109
|
+
events: [algoliaEvent],
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -237,10 +237,7 @@ export class CommercetoolsProfileProvider extends ProfileProvider {
|
|
|
237
237
|
if (addressToMakeDefault.id === customer.defaultBillingAddressId) {
|
|
238
238
|
return error<InvalidInputError>({
|
|
239
239
|
type: 'InvalidInput',
|
|
240
|
-
error:
|
|
241
|
-
field: 'addressIdentifier',
|
|
242
|
-
message: 'Cannot set shipping address as default billing address',
|
|
243
|
-
}
|
|
240
|
+
error: 'Cannot set shipping address as default billing address'
|
|
244
241
|
});
|
|
245
242
|
}
|
|
246
243
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
AnalyticsMutation,
|
|
2
3
|
Cache,
|
|
3
4
|
RequestContext} from '@reactionary/core';
|
|
4
5
|
import {
|
|
@@ -15,4 +16,8 @@ export class FakeAnalyticsProvider extends AnalyticsProvider {
|
|
|
15
16
|
|
|
16
17
|
this.config = config;
|
|
17
18
|
}
|
|
19
|
+
|
|
20
|
+
public override async track(event: AnalyticsMutation): Promise<void> {
|
|
21
|
+
// No-op
|
|
22
|
+
}
|
|
18
23
|
}
|
|
@@ -29,9 +29,12 @@ import {
|
|
|
29
29
|
CheckoutMutationFinalizeCheckoutSchema,
|
|
30
30
|
success,
|
|
31
31
|
type CheckoutIdentifier,
|
|
32
|
+
PaymentMethodSchema,
|
|
33
|
+
ShippingMethodSchema,
|
|
32
34
|
} from '@reactionary/core';
|
|
33
35
|
import type { FakeConfiguration } from '../schema/configuration.schema.js';
|
|
34
36
|
import { base, en, Faker } from '@faker-js/faker';
|
|
37
|
+
import z from 'zod';
|
|
35
38
|
|
|
36
39
|
export class FakeCheckoutProvider extends CheckoutProvider {
|
|
37
40
|
protected config: FakeConfiguration;
|
|
@@ -90,7 +93,7 @@ export class FakeCheckoutProvider extends CheckoutProvider {
|
|
|
90
93
|
|
|
91
94
|
@Reactionary({
|
|
92
95
|
inputSchema: CheckoutQueryForAvailableShippingMethodsSchema,
|
|
93
|
-
outputSchema:
|
|
96
|
+
outputSchema: z.array(ShippingMethodSchema),
|
|
94
97
|
})
|
|
95
98
|
public override async getAvailableShippingMethods(
|
|
96
99
|
payload: CheckoutQueryForAvailableShippingMethods
|
|
@@ -116,7 +119,7 @@ export class FakeCheckoutProvider extends CheckoutProvider {
|
|
|
116
119
|
|
|
117
120
|
@Reactionary({
|
|
118
121
|
inputSchema: CheckoutQueryForAvailablePaymentMethodsSchema,
|
|
119
|
-
outputSchema:
|
|
122
|
+
outputSchema: z.array(PaymentMethodSchema),
|
|
120
123
|
})
|
|
121
124
|
public override async getAvailablePaymentMethods(
|
|
122
125
|
payload: CheckoutQueryForAvailablePaymentMethods
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
type Result,
|
|
15
15
|
error,
|
|
16
16
|
success,
|
|
17
|
-
type NotFoundError
|
|
17
|
+
type NotFoundError,
|
|
18
18
|
} from '@reactionary/core';
|
|
19
19
|
import type z from 'zod';
|
|
20
20
|
import type { FakeConfiguration } from '../schema/configuration.schema.js';
|
|
@@ -23,7 +23,11 @@ import { base, en, Faker } from '@faker-js/faker';
|
|
|
23
23
|
export class FakeProductProvider extends ProductProvider {
|
|
24
24
|
protected config: FakeConfiguration;
|
|
25
25
|
|
|
26
|
-
constructor(
|
|
26
|
+
constructor(
|
|
27
|
+
config: FakeConfiguration,
|
|
28
|
+
cache: ReactinaryCache,
|
|
29
|
+
context: RequestContext
|
|
30
|
+
) {
|
|
27
31
|
super(cache, context);
|
|
28
32
|
|
|
29
33
|
this.config = config;
|
|
@@ -31,7 +35,11 @@ export class FakeProductProvider extends ProductProvider {
|
|
|
31
35
|
|
|
32
36
|
@Reactionary({
|
|
33
37
|
inputSchema: ProductQueryByIdSchema,
|
|
34
|
-
outputSchema: ProductSchema
|
|
38
|
+
outputSchema: ProductSchema,
|
|
39
|
+
cache: true,
|
|
40
|
+
cacheTimeToLiveInSeconds: 300,
|
|
41
|
+
currencyDependentCaching: false,
|
|
42
|
+
localeDependentCaching: true,
|
|
35
43
|
})
|
|
36
44
|
public override async getById(
|
|
37
45
|
payload: ProductQueryById
|
|
@@ -41,7 +49,7 @@ export class FakeProductProvider extends ProductProvider {
|
|
|
41
49
|
|
|
42
50
|
@Reactionary({
|
|
43
51
|
inputSchema: ProductQueryBySlugSchema,
|
|
44
|
-
outputSchema: ProductSchema
|
|
52
|
+
outputSchema: ProductSchema,
|
|
45
53
|
})
|
|
46
54
|
public override async getBySlug(
|
|
47
55
|
payload: ProductQueryBySlug
|
|
@@ -53,7 +61,9 @@ export class FakeProductProvider extends ProductProvider {
|
|
|
53
61
|
inputSchema: ProductQueryBySKUSchema,
|
|
54
62
|
outputSchema: ProductSchema,
|
|
55
63
|
})
|
|
56
|
-
public override async getBySKU(
|
|
64
|
+
public override async getBySKU(
|
|
65
|
+
payload: ProductQueryBySKU
|
|
66
|
+
): Promise<Result<Product>> {
|
|
57
67
|
return success(this.parseSingle(payload.variant.sku));
|
|
58
68
|
}
|
|
59
69
|
|
|
@@ -79,12 +89,12 @@ export class FakeProductProvider extends ProductProvider {
|
|
|
79
89
|
ean: '',
|
|
80
90
|
gtin: '',
|
|
81
91
|
identifier: {
|
|
82
|
-
sku: ''
|
|
92
|
+
sku: '',
|
|
83
93
|
},
|
|
84
94
|
images: [],
|
|
85
95
|
name: '',
|
|
86
96
|
options: [],
|
|
87
|
-
upc: ''
|
|
97
|
+
upc: '',
|
|
88
98
|
},
|
|
89
99
|
description: generator.commerce.productDescription(),
|
|
90
100
|
manufacturer: '',
|
|
@@ -93,7 +103,7 @@ export class FakeProductProvider extends ProductProvider {
|
|
|
93
103
|
published: true,
|
|
94
104
|
sharedAttributes: [],
|
|
95
105
|
variants: [],
|
|
96
|
-
} satisfies Product
|
|
106
|
+
} satisfies Product;
|
|
97
107
|
|
|
98
108
|
return result;
|
|
99
109
|
}
|
|
@@ -72,8 +72,6 @@ describe('Fake Cart Provider', () => {
|
|
|
72
72
|
expect(updatedCart.value.items.length).toBe(1);
|
|
73
73
|
expect(updatedCart.value.items[0].variant.sku).toBe(testData.skuWithoutTiers);
|
|
74
74
|
expect(updatedCart.value.items[0].quantity).toBe(3);
|
|
75
|
-
expect(updatedCart.value.items[0].price.totalPrice.value).toBe(cart.value.items[0].price.totalPrice.value * 3);
|
|
76
|
-
expect(updatedCart.value.items[0].price.unitPrice.value).toBe(cart.value.items[0].price.unitPrice.value);
|
|
77
75
|
});
|
|
78
76
|
|
|
79
77
|
it('should be able to remove an item from a cart', async () => {
|
|
@@ -158,16 +158,16 @@ describe('Faker Category Provider', () => {
|
|
|
158
158
|
expect(result.value.text).not.toBe('');
|
|
159
159
|
});
|
|
160
160
|
|
|
161
|
-
it('returns a
|
|
161
|
+
it('returns a not found error for categories that do not exist', async () => {
|
|
162
162
|
const result = await provider.getById({
|
|
163
163
|
id: { key: 'non-existent-category' },
|
|
164
164
|
});
|
|
165
165
|
|
|
166
|
-
if (
|
|
166
|
+
if (result.success) {
|
|
167
167
|
assert.fail();
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
expect(result.
|
|
170
|
+
expect(result.error.type).toBe('NotFound');
|
|
171
171
|
});
|
|
172
172
|
|
|
173
173
|
describe('caching', () => {
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import 'dotenv/config';
|
|
2
2
|
import type { RequestContext } from '@reactionary/core';
|
|
3
3
|
import {
|
|
4
|
-
CartSchema,
|
|
5
|
-
IdentitySchema,
|
|
6
4
|
NoOpCache,
|
|
7
5
|
createInitialRequestContext,
|
|
8
6
|
} from '@reactionary/core';
|
|
9
7
|
import { getFakerTestConfiguration } from './test-utils.js';
|
|
10
|
-
import {
|
|
11
|
-
import { FakeIdentityProvider } from '../providers/index.js';
|
|
12
|
-
import { describe, expect, it, beforeAll, beforeEach, assert } from 'vitest';
|
|
8
|
+
import { describe, expect, it, beforeEach, assert } from 'vitest';
|
|
13
9
|
import { FakeCheckoutProvider } from '../providers/checkout.provider.js';
|
|
14
10
|
|
|
15
11
|
describe('Fake Checkout Provider', () => {
|
|
@@ -200,7 +196,7 @@ describe('Fake Checkout Provider', () => {
|
|
|
200
196
|
});
|
|
201
197
|
|
|
202
198
|
if (!result.success) {
|
|
203
|
-
assert.fail();
|
|
199
|
+
assert.fail(JSON.stringify(result.error));
|
|
204
200
|
}
|
|
205
201
|
|
|
206
202
|
expect(result.value.length).toBeGreaterThan(0);
|
|
@@ -214,7 +210,7 @@ describe('Fake Checkout Provider', () => {
|
|
|
214
210
|
});
|
|
215
211
|
|
|
216
212
|
if (!result.success) {
|
|
217
|
-
assert.fail();
|
|
213
|
+
assert.fail(JSON.stringify(result.error));
|
|
218
214
|
}
|
|
219
215
|
|
|
220
216
|
expect(result.value.length).toBeGreaterThan(0);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# google-analytics
|
|
2
|
+
|
|
3
|
+
This library was generated with [Nx](https://nx.dev).
|
|
4
|
+
|
|
5
|
+
## Building
|
|
6
|
+
|
|
7
|
+
Run `nx build google-analytics` to build the library.
|
|
8
|
+
|
|
9
|
+
## Running unit tests
|
|
10
|
+
|
|
11
|
+
Run `nx test google-analytics` to execute the unit tests via [Vitest](https://vitest.dev/).
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import baseConfig from '../../eslint.config.mjs';
|
|
2
|
+
|
|
3
|
+
export default [
|
|
4
|
+
...baseConfig,
|
|
5
|
+
{
|
|
6
|
+
files: ['**/*.json'],
|
|
7
|
+
rules: {
|
|
8
|
+
'@nx/dependency-checks': [
|
|
9
|
+
'error',
|
|
10
|
+
{
|
|
11
|
+
ignoredFiles: [
|
|
12
|
+
'{projectRoot}/eslint.config.{js,cjs,mjs,ts,cts,mts}',
|
|
13
|
+
'{projectRoot}/esbuild.config.{js,ts,mjs,mts}',
|
|
14
|
+
'{projectRoot}/vite.config.{js,ts,mjs,mts}',
|
|
15
|
+
'{projectRoot}/**/*.spec.ts',
|
|
16
|
+
],
|
|
17
|
+
ignoredDependencies: ['vitest', '@nx/vite'],
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
languageOptions: {
|
|
22
|
+
parser: await import('jsonc-eslint-parser'),
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@reactionary/google-analytics",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"types": "src/index.d.ts",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"@reactionary/core": "0.0.1",
|
|
8
|
+
"zod": "4.1.9"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"vitest": "*",
|
|
12
|
+
"@vitest/ui": "*",
|
|
13
|
+
"@vitest/coverage-v8": "*",
|
|
14
|
+
"vite-tsconfig-paths": "*"
|
|
15
|
+
},
|
|
16
|
+
"type": "module",
|
|
17
|
+
"sideEffects": false
|
|
18
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "google-analytics",
|
|
3
|
+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
+
"sourceRoot": "providers/google-analytics/src",
|
|
5
|
+
"projectType": "library",
|
|
6
|
+
"release": {
|
|
7
|
+
"version": {
|
|
8
|
+
"manifestRootsToUpdate": ["dist/{projectRoot}"],
|
|
9
|
+
"currentVersionResolver": "git-tag",
|
|
10
|
+
"fallbackCurrentVersionResolver": "disk"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"tags": [],
|
|
14
|
+
"targets": {
|
|
15
|
+
"build": {
|
|
16
|
+
"executor": "@nx/esbuild:esbuild",
|
|
17
|
+
"outputs": ["{options.outputPath}"],
|
|
18
|
+
"options": {
|
|
19
|
+
"outputPath": "dist/providers/google-analytics",
|
|
20
|
+
"main": "providers/google-analytics/src/index.ts",
|
|
21
|
+
"tsConfig": "providers/google-analytics/tsconfig.lib.json",
|
|
22
|
+
"assets": ["providers/google-analytics/*.md"],
|
|
23
|
+
"format": ["esm"],
|
|
24
|
+
"bundle": false
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"nx-release-publish": {
|
|
28
|
+
"options": {
|
|
29
|
+
"packageRoot": "dist/{projectRoot}"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|