@reactionary/source 0.0.27

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 (197) hide show
  1. package/.editorconfig +13 -0
  2. package/.github/workflows/pull-request.yml +37 -0
  3. package/.github/workflows/release.yml +49 -0
  4. package/.nvmrc +1 -0
  5. package/.prettierignore +6 -0
  6. package/.prettierrc +3 -0
  7. package/.verdaccio/config.yml +28 -0
  8. package/.vscode/extensions.json +9 -0
  9. package/README.md +39 -0
  10. package/core/README.md +11 -0
  11. package/core/eslint.config.mjs +23 -0
  12. package/core/package.json +8 -0
  13. package/core/project.json +33 -0
  14. package/core/src/cache/caching-strategy.ts +25 -0
  15. package/core/src/cache/redis-cache.ts +41 -0
  16. package/core/src/client/client.ts +39 -0
  17. package/core/src/index.ts +42 -0
  18. package/core/src/providers/analytics.provider.ts +10 -0
  19. package/core/src/providers/base.provider.ts +75 -0
  20. package/core/src/providers/cart.provider.ts +10 -0
  21. package/core/src/providers/identity.provider.ts +10 -0
  22. package/core/src/providers/inventory.provider.ts +11 -0
  23. package/core/src/providers/price.provider.ts +10 -0
  24. package/core/src/providers/product.provider.ts +11 -0
  25. package/core/src/providers/search.provider.ts +12 -0
  26. package/core/src/schemas/capabilities.schema.ts +13 -0
  27. package/core/src/schemas/models/analytics.model.ts +7 -0
  28. package/core/src/schemas/models/base.model.ts +19 -0
  29. package/core/src/schemas/models/cart.model.ts +17 -0
  30. package/core/src/schemas/models/currency.model.ts +187 -0
  31. package/core/src/schemas/models/identifiers.model.ts +45 -0
  32. package/core/src/schemas/models/identity.model.ts +15 -0
  33. package/core/src/schemas/models/inventory.model.ts +8 -0
  34. package/core/src/schemas/models/price.model.ts +17 -0
  35. package/core/src/schemas/models/product.model.ts +28 -0
  36. package/core/src/schemas/models/search.model.ts +35 -0
  37. package/core/src/schemas/mutations/analytics.mutation.ts +22 -0
  38. package/core/src/schemas/mutations/base.mutation.ts +7 -0
  39. package/core/src/schemas/mutations/cart.mutation.ts +30 -0
  40. package/core/src/schemas/mutations/identity.mutation.ts +18 -0
  41. package/core/src/schemas/mutations/inventory.mutation.ts +5 -0
  42. package/core/src/schemas/mutations/price.mutation.ts +5 -0
  43. package/core/src/schemas/mutations/product.mutation.ts +6 -0
  44. package/core/src/schemas/mutations/search.mutation.ts +5 -0
  45. package/core/src/schemas/queries/analytics.query.ts +5 -0
  46. package/core/src/schemas/queries/base.query.ts +7 -0
  47. package/core/src/schemas/queries/cart.query.ts +12 -0
  48. package/core/src/schemas/queries/identity.query.ts +10 -0
  49. package/core/src/schemas/queries/inventory.query.ts +9 -0
  50. package/core/src/schemas/queries/price.query.ts +12 -0
  51. package/core/src/schemas/queries/product.query.ts +18 -0
  52. package/core/src/schemas/queries/search.query.ts +12 -0
  53. package/core/src/schemas/session.schema.ts +9 -0
  54. package/core/tsconfig.json +23 -0
  55. package/core/tsconfig.lib.json +23 -0
  56. package/core/tsconfig.spec.json +28 -0
  57. package/eslint.config.mjs +46 -0
  58. package/examples/angular/e2e/example.spec.ts +9 -0
  59. package/examples/angular/eslint.config.mjs +41 -0
  60. package/examples/angular/playwright.config.ts +38 -0
  61. package/examples/angular/project.json +86 -0
  62. package/examples/angular/public/favicon.ico +0 -0
  63. package/examples/angular/src/app/app.component.html +6 -0
  64. package/examples/angular/src/app/app.component.scss +22 -0
  65. package/examples/angular/src/app/app.component.ts +14 -0
  66. package/examples/angular/src/app/app.config.ts +16 -0
  67. package/examples/angular/src/app/app.routes.ts +25 -0
  68. package/examples/angular/src/app/cart/cart.component.html +4 -0
  69. package/examples/angular/src/app/cart/cart.component.scss +14 -0
  70. package/examples/angular/src/app/cart/cart.component.ts +73 -0
  71. package/examples/angular/src/app/identity/identity.component.html +6 -0
  72. package/examples/angular/src/app/identity/identity.component.scss +18 -0
  73. package/examples/angular/src/app/identity/identity.component.ts +49 -0
  74. package/examples/angular/src/app/product/product.component.html +14 -0
  75. package/examples/angular/src/app/product/product.component.scss +11 -0
  76. package/examples/angular/src/app/product/product.component.ts +42 -0
  77. package/examples/angular/src/app/search/search.component.html +35 -0
  78. package/examples/angular/src/app/search/search.component.scss +129 -0
  79. package/examples/angular/src/app/search/search.component.ts +50 -0
  80. package/examples/angular/src/app/services/product.service.ts +35 -0
  81. package/examples/angular/src/app/services/search.service.ts +48 -0
  82. package/examples/angular/src/app/services/trpc.client.ts +27 -0
  83. package/examples/angular/src/index.html +13 -0
  84. package/examples/angular/src/main.ts +7 -0
  85. package/examples/angular/src/styles.scss +17 -0
  86. package/examples/angular/src/test-setup.ts +6 -0
  87. package/examples/angular/tsconfig.app.json +10 -0
  88. package/examples/angular/tsconfig.editor.json +6 -0
  89. package/examples/angular/tsconfig.json +32 -0
  90. package/examples/node/README.md +11 -0
  91. package/examples/node/eslint.config.mjs +22 -0
  92. package/examples/node/jest.config.ts +10 -0
  93. package/examples/node/package.json +10 -0
  94. package/examples/node/project.json +20 -0
  95. package/examples/node/src/index.ts +2 -0
  96. package/examples/node/src/initialize-algolia.spec.ts +29 -0
  97. package/examples/node/src/initialize-commercetools.spec.ts +31 -0
  98. package/examples/node/src/initialize-extended-providers.spec.ts +38 -0
  99. package/examples/node/src/initialize-mixed-providers.spec.ts +36 -0
  100. package/examples/node/src/providers/custom-algolia-product.provider.ts +18 -0
  101. package/examples/node/src/schemas/custom-product.schema.ts +8 -0
  102. package/examples/node/tsconfig.json +23 -0
  103. package/examples/node/tsconfig.lib.json +10 -0
  104. package/examples/node/tsconfig.spec.json +15 -0
  105. package/examples/trpc-node/eslint.config.mjs +3 -0
  106. package/examples/trpc-node/project.json +61 -0
  107. package/examples/trpc-node/src/assets/.gitkeep +0 -0
  108. package/examples/trpc-node/src/main.ts +55 -0
  109. package/examples/trpc-node/src/router-instance.ts +52 -0
  110. package/examples/trpc-node/tsconfig.app.json +9 -0
  111. package/examples/trpc-node/tsconfig.json +13 -0
  112. package/examples/vue/eslint.config.mjs +24 -0
  113. package/examples/vue/index.html +13 -0
  114. package/examples/vue/project.json +8 -0
  115. package/examples/vue/src/app/App.vue +275 -0
  116. package/examples/vue/src/main.ts +6 -0
  117. package/examples/vue/src/styles.scss +9 -0
  118. package/examples/vue/src/vue-shims.d.ts +5 -0
  119. package/examples/vue/tsconfig.app.json +14 -0
  120. package/examples/vue/tsconfig.json +20 -0
  121. package/examples/vue/vite.config.ts +31 -0
  122. package/jest.config.ts +6 -0
  123. package/jest.preset.js +3 -0
  124. package/migrations.json +11 -0
  125. package/nx.json +130 -0
  126. package/package.json +118 -0
  127. package/project.json +14 -0
  128. package/providers/algolia/README.md +11 -0
  129. package/providers/algolia/eslint.config.mjs +22 -0
  130. package/providers/algolia/jest.config.ts +10 -0
  131. package/providers/algolia/package.json +9 -0
  132. package/providers/algolia/project.json +33 -0
  133. package/providers/algolia/src/core/initialize.ts +20 -0
  134. package/providers/algolia/src/index.ts +7 -0
  135. package/providers/algolia/src/providers/product.provider.ts +25 -0
  136. package/providers/algolia/src/providers/search.provider.ts +125 -0
  137. package/providers/algolia/src/schema/capabilities.schema.ts +10 -0
  138. package/providers/algolia/src/schema/configuration.schema.ts +9 -0
  139. package/providers/algolia/src/schema/search.schema.ts +14 -0
  140. package/providers/algolia/src/test/product.provider.spec.ts +18 -0
  141. package/providers/algolia/src/test/search.provider.spec.ts +82 -0
  142. package/providers/algolia/tsconfig.json +23 -0
  143. package/providers/algolia/tsconfig.lib.json +10 -0
  144. package/providers/algolia/tsconfig.spec.json +15 -0
  145. package/providers/commercetools/README.md +11 -0
  146. package/providers/commercetools/eslint.config.mjs +22 -0
  147. package/providers/commercetools/jest.config.ts +10 -0
  148. package/providers/commercetools/package.json +10 -0
  149. package/providers/commercetools/project.json +33 -0
  150. package/providers/commercetools/src/core/client.ts +152 -0
  151. package/providers/commercetools/src/core/initialize.ts +40 -0
  152. package/providers/commercetools/src/index.ts +12 -0
  153. package/providers/commercetools/src/providers/cart.provider.ts +223 -0
  154. package/providers/commercetools/src/providers/identity.provider.ts +130 -0
  155. package/providers/commercetools/src/providers/inventory.provider.ts +82 -0
  156. package/providers/commercetools/src/providers/price.provider.ts +66 -0
  157. package/providers/commercetools/src/providers/product.provider.ts +90 -0
  158. package/providers/commercetools/src/providers/search.provider.ts +86 -0
  159. package/providers/commercetools/src/schema/capabilities.schema.ts +13 -0
  160. package/providers/commercetools/src/schema/configuration.schema.ts +11 -0
  161. package/providers/commercetools/src/test/product.provider.spec.ts +20 -0
  162. package/providers/commercetools/src/test/search.provider.spec.ts +18 -0
  163. package/providers/commercetools/tsconfig.json +23 -0
  164. package/providers/commercetools/tsconfig.lib.json +10 -0
  165. package/providers/commercetools/tsconfig.spec.json +15 -0
  166. package/providers/fake/README.md +7 -0
  167. package/providers/fake/eslint.config.mjs +22 -0
  168. package/providers/fake/package.json +9 -0
  169. package/providers/fake/project.json +33 -0
  170. package/providers/fake/src/core/initialize.ts +24 -0
  171. package/providers/fake/src/index.ts +8 -0
  172. package/providers/fake/src/providers/identity.provider.ts +91 -0
  173. package/providers/fake/src/providers/product.provider.ts +73 -0
  174. package/providers/fake/src/providers/search.provider.ts +142 -0
  175. package/providers/fake/src/schema/capabilities.schema.ts +10 -0
  176. package/providers/fake/src/schema/configuration.schema.ts +15 -0
  177. package/providers/fake/src/utilities/jitter.ts +14 -0
  178. package/providers/fake/tsconfig.json +20 -0
  179. package/providers/fake/tsconfig.lib.json +9 -0
  180. package/providers/posthog/README.md +7 -0
  181. package/providers/posthog/eslint.config.mjs +22 -0
  182. package/providers/posthog/package.json +11 -0
  183. package/providers/posthog/project.json +33 -0
  184. package/providers/posthog/src/core/initialize.ts +9 -0
  185. package/providers/posthog/src/index.ts +4 -0
  186. package/providers/posthog/src/schema/capabilities.schema.ts +8 -0
  187. package/providers/posthog/src/schema/configuration.schema.ts +8 -0
  188. package/providers/posthog/tsconfig.json +20 -0
  189. package/providers/posthog/tsconfig.lib.json +9 -0
  190. package/trpc/README.md +7 -0
  191. package/trpc/eslint.config.mjs +19 -0
  192. package/trpc/package.json +13 -0
  193. package/trpc/project.json +31 -0
  194. package/trpc/src/index.ts +64 -0
  195. package/trpc/tsconfig.json +13 -0
  196. package/trpc/tsconfig.lib.json +9 -0
  197. package/tsconfig.base.json +30 -0
@@ -0,0 +1,46 @@
1
+ import nx from '@nx/eslint-plugin';
2
+
3
+ export default [
4
+ ...nx.configs['flat/base'],
5
+ ...nx.configs['flat/typescript'],
6
+ ...nx.configs['flat/javascript'],
7
+ {
8
+ ignores: [
9
+ '**/dist',
10
+ '**/vite.config.*.timestamp*',
11
+ '**/vitest.config.*.timestamp*',
12
+ ],
13
+ },
14
+ {
15
+ files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.vue'],
16
+ rules: {
17
+ '@nx/enforce-module-boundaries': [
18
+ 'error',
19
+ {
20
+ enforceBuildableLibDependency: true,
21
+ allow: ['^.*/eslint(\\.base)?\\.config\\.[cm]?js$'],
22
+ depConstraints: [
23
+ {
24
+ sourceTag: '*',
25
+ onlyDependOnLibsWithTags: ['*'],
26
+ },
27
+ ],
28
+ },
29
+ ],
30
+ },
31
+ },
32
+ {
33
+ files: [
34
+ '**/*.ts',
35
+ '**/*.tsx',
36
+ '**/*.cts',
37
+ '**/*.mts',
38
+ '**/*.js',
39
+ '**/*.jsx',
40
+ '**/*.cjs',
41
+ '**/*.mjs',
42
+ ],
43
+ // Override or add rules here
44
+ rules: {},
45
+ },
46
+ ];
@@ -0,0 +1,9 @@
1
+ import { test, expect } from '@playwright/test';
2
+
3
+ test('displays search results', async ({ page }) => {
4
+ await page.goto('/');
5
+
6
+ await page.waitForSelector('article', { state: 'visible' });
7
+
8
+ expect(await page.locator('article').count()).toBe(20);
9
+ });
@@ -0,0 +1,41 @@
1
+ import playwright from 'eslint-plugin-playwright';
2
+ import nx from '@nx/eslint-plugin';
3
+ import baseConfig from '../../eslint.config.mjs';
4
+
5
+ export default [
6
+ playwright.configs['flat/recommended'],
7
+ ...baseConfig,
8
+ ...nx.configs['flat/angular'],
9
+ ...nx.configs['flat/angular-template'],
10
+ {
11
+ files: ['**/*.ts'],
12
+ rules: {
13
+ '@angular-eslint/directive-selector': [
14
+ 'error',
15
+ {
16
+ type: 'attribute',
17
+ prefix: 'app',
18
+ style: 'camelCase',
19
+ },
20
+ ],
21
+ '@angular-eslint/component-selector': [
22
+ 'error',
23
+ {
24
+ type: 'element',
25
+ prefix: 'app',
26
+ style: 'kebab-case',
27
+ },
28
+ ],
29
+ },
30
+ },
31
+ {
32
+ files: ['**/*.html'],
33
+ // Override or add rules here
34
+ rules: {},
35
+ },
36
+ {
37
+ files: ['**/*.ts', '**/*.js'],
38
+ // Override or add rules here
39
+ rules: {},
40
+ },
41
+ ];
@@ -0,0 +1,38 @@
1
+ import { defineConfig, devices } from '@playwright/test';
2
+ import { nxE2EPreset } from '@nx/playwright/preset';
3
+ import { workspaceRoot } from '@nx/devkit';
4
+
5
+ // For CI, you may want to set BASE_URL to the deployed application.
6
+ const baseURL = process.env['BASE_URL'] || 'http://localhost:4200';
7
+
8
+ /**
9
+ * Read environment variables from file.
10
+ * https://github.com/motdotla/dotenv
11
+ */
12
+ // require('dotenv').config();
13
+
14
+ /**
15
+ * See https://playwright.dev/docs/test-configuration.
16
+ */
17
+ export default defineConfig({
18
+ ...nxE2EPreset(__filename, { testDir: './e2e' }),
19
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
20
+ use: {
21
+ baseURL,
22
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
23
+ trace: 'on-first-retry',
24
+ },
25
+ /* Run your local dev server before starting the tests */
26
+ webServer: {
27
+ command: 'npx nx serve examples-angular',
28
+ url: 'http://localhost:4200',
29
+ reuseExistingServer: !process.env.CI,
30
+ cwd: workspaceRoot,
31
+ },
32
+ projects: [
33
+ {
34
+ name: 'chromium',
35
+ use: { ...devices['Desktop Chrome'] },
36
+ },
37
+ ],
38
+ });
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "examples-angular",
3
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
4
+ "projectType": "application",
5
+ "prefix": "app",
6
+ "sourceRoot": "examples/angular/src",
7
+ "tags": [],
8
+ "targets": {
9
+ "build": {
10
+ "executor": "@angular-devkit/build-angular:application",
11
+ "outputs": ["{options.outputPath}"],
12
+ "options": {
13
+ "outputPath": "dist/examples/angular",
14
+ "index": "examples/angular/src/index.html",
15
+ "browser": "examples/angular/src/main.ts",
16
+ "polyfills": [],
17
+ "tsConfig": "examples/angular/tsconfig.app.json",
18
+ "inlineStyleLanguage": "scss",
19
+ "assets": [
20
+ {
21
+ "glob": "**/*",
22
+ "input": "examples/angular/public"
23
+ }
24
+ ],
25
+ "styles": ["examples/angular/src/styles.scss"],
26
+ "scripts": []
27
+ },
28
+ "configurations": {
29
+ "production": {
30
+ "budgets": [
31
+ {
32
+ "type": "initial",
33
+ "maximumWarning": "500kb",
34
+ "maximumError": "1mb"
35
+ },
36
+ {
37
+ "type": "anyComponentStyle",
38
+ "maximumWarning": "4kb",
39
+ "maximumError": "8kb"
40
+ }
41
+ ],
42
+ "outputHashing": "all"
43
+ },
44
+ "development": {
45
+ "optimization": false,
46
+ "extractLicenses": false,
47
+ "sourceMap": true
48
+ }
49
+ },
50
+ "defaultConfiguration": "production"
51
+ },
52
+ "serve": {
53
+ "executor": "@angular-devkit/build-angular:dev-server",
54
+ "configurations": {
55
+ "production": {
56
+ "buildTarget": "examples-angular:build:production"
57
+ },
58
+ "development": {
59
+ "buildTarget": "examples-angular:build:development"
60
+ }
61
+ },
62
+ "defaultConfiguration": "development",
63
+ "continuous": true,
64
+ "dependsOn": [
65
+ { "projects": ["trpc-node"], "target": "serve" }
66
+ ]
67
+ },
68
+ "extract-i18n": {
69
+ "executor": "@angular-devkit/build-angular:extract-i18n",
70
+ "options": {
71
+ "buildTarget": "examples-angular:build"
72
+ }
73
+ },
74
+ "lint": {
75
+ "executor": "@nx/eslint:lint"
76
+ },
77
+ "serve-static": {
78
+ "executor": "@nx/web:file-server",
79
+ "options": {
80
+ "buildTarget": "examples-angular:build",
81
+ "staticFilePath": "dist/examples/angular/browser",
82
+ "spa": true
83
+ }
84
+ }
85
+ }
86
+ }
@@ -0,0 +1,6 @@
1
+ <header>
2
+ <input (keydown)="this.service.term.set(inputTerm.value)" #inputTerm/>
3
+ </header>
4
+ <main>
5
+ <router-outlet></router-outlet>
6
+ </main>
@@ -0,0 +1,22 @@
1
+ :host {
2
+ display: block;
3
+ }
4
+
5
+ header {
6
+ padding: 0.5rem;
7
+
8
+ input {
9
+ padding-inline: 1rem;
10
+ color: rgb(205, 214, 244);
11
+ background: rgb(88, 91, 112);
12
+ width: 100%;
13
+ height: 3rem;
14
+ border-radius: 0.5rem;
15
+ }
16
+ }
17
+
18
+ main {
19
+ display: block;
20
+ width: 100%;
21
+ padding-inline: 0.5rem;
22
+ }
@@ -0,0 +1,14 @@
1
+ import { Component, inject } from '@angular/core';
2
+ import { RouterModule } from '@angular/router';
3
+ import { SearchService } from './services/search.service';
4
+ import { TRPC } from './services/trpc.client';
5
+
6
+ @Component({
7
+ imports: [RouterModule],
8
+ selector: 'app-root',
9
+ templateUrl: './app.component.html',
10
+ styleUrl: './app.component.scss',
11
+ })
12
+ export class AppComponent {
13
+ protected service = inject(SearchService);
14
+ }
@@ -0,0 +1,16 @@
1
+ import { ApplicationConfig, provideExperimentalZonelessChangeDetection } from '@angular/core';
2
+ import { NoPreloading, provideRouter, withPreloading, withRouterConfig } from '@angular/router';
3
+ import { appRoutes } from './app.routes';
4
+
5
+ export const appConfig: ApplicationConfig = {
6
+ providers: [
7
+ provideExperimentalZonelessChangeDetection(),
8
+ provideRouter(
9
+ appRoutes,
10
+ withPreloading(NoPreloading),
11
+ withRouterConfig({
12
+ onSameUrlNavigation: 'ignore'
13
+ })
14
+ )
15
+ ],
16
+ };
@@ -0,0 +1,25 @@
1
+ import { Route } from '@angular/router';
2
+
3
+ export const appRoutes: Route[] = [
4
+ {
5
+ path: 'search',
6
+ loadComponent: () => import('./search/search.component').then(x => x.SearchComponent)
7
+ },
8
+ {
9
+ path: 'product/:slug',
10
+ loadComponent: () => import('./product/product.component').then(x => x.ProductComponent)
11
+ },
12
+ {
13
+ path: 'identity',
14
+ loadComponent: () => import('./identity/identity.component').then(x => x.IdentityComponent)
15
+ },
16
+ {
17
+ path: 'cart',
18
+ loadComponent: () => import('./cart/cart.component').then(x => x.CartComponent)
19
+ },
20
+ {
21
+ path: '**',
22
+ pathMatch: 'prefix',
23
+ redirectTo: 'search'
24
+ }
25
+ ];
@@ -0,0 +1,4 @@
1
+ <pre>{{ cart() | json }}</pre>
2
+ <button (click)="add()">Add</button>
3
+ <button (click)="adjust()">Adjust</button>
4
+ <button (click)="remove()">Remove</button>
@@ -0,0 +1,14 @@
1
+ :host {
2
+ display: grid;
3
+ grid-template-columns: 600px;
4
+ justify-content: center;
5
+ gap: 0.5rem;
6
+ }
7
+
8
+ pre {
9
+ color: white;
10
+ }
11
+
12
+ input, button {
13
+ height: 3rem;
14
+ }
@@ -0,0 +1,73 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ Component,
4
+ inject,
5
+ signal,
6
+ ViewEncapsulation,
7
+ } from '@angular/core';
8
+ import { CommonModule } from '@angular/common';
9
+ import { TRPC } from '../services/trpc.client';
10
+ import { Cart } from '@reactionary/core';
11
+
12
+ @Component({
13
+ selector: 'app-cart',
14
+ imports: [CommonModule],
15
+ templateUrl: './cart.component.html',
16
+ styleUrl: './cart.component.scss',
17
+ encapsulation: ViewEncapsulation.ShadowDom,
18
+ changeDetection: ChangeDetectionStrategy.OnPush,
19
+ })
20
+ export class CartComponent {
21
+ protected trpc = inject(TRPC);
22
+ protected cart = signal<Cart | undefined>(undefined);
23
+
24
+ protected async add() {
25
+ const c = await this.trpc.client.cartMutation.mutate([
26
+ {
27
+ mutation: 'add',
28
+ cart: {
29
+ key: this.cart()?.identifier.key || '',
30
+ },
31
+ product: {
32
+ key: 'ad153f54-6ae9-4800-8e5e-b40a07eb87b4',
33
+ },
34
+ quantity: 2,
35
+ },
36
+ ]);
37
+
38
+ this.cart.set(c);
39
+ }
40
+
41
+ protected async adjust() {
42
+ const existing = this.cart();
43
+
44
+ if (existing) {
45
+ const c = await this.trpc.client.cartMutation.mutate([
46
+ {
47
+ mutation: 'adjustQuantity',
48
+ cart: existing.identifier,
49
+ item: existing.items[0].identifier,
50
+ quantity: existing.items[0].quantity + 1,
51
+ },
52
+ ]);
53
+
54
+ this.cart.set(c);
55
+ }
56
+ }
57
+
58
+ protected async remove() {
59
+ const existing = this.cart();
60
+
61
+ if (existing) {
62
+ const c = await this.trpc.client.cartMutation.mutate([
63
+ {
64
+ mutation: 'remove',
65
+ cart: existing.identifier,
66
+ item: existing.items[0].identifier,
67
+ },
68
+ ]);
69
+
70
+ this.cart.set(c);
71
+ }
72
+ }
73
+ }
@@ -0,0 +1,6 @@
1
+ <pre>{{ identity() | json }}</pre>
2
+ <input #username />
3
+ <input #password />
4
+ <button (click)="login(username.value, password.value)">Log in</button>
5
+ <button (click)="logout()">Logout</button>
6
+ <button (click)="refresh()">Refresh</button>
@@ -0,0 +1,18 @@
1
+ :host {
2
+ display: grid;
3
+ grid-template-columns: 600px;
4
+ justify-content: center;
5
+ gap: 0.5rem;
6
+ }
7
+
8
+ pre {
9
+ color: white;
10
+ }
11
+
12
+ input, button {
13
+ height: 3rem;
14
+ }
15
+
16
+ h2 {
17
+ color: white;
18
+ }
@@ -0,0 +1,49 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ Component,
4
+ inject,
5
+ signal,
6
+ ViewEncapsulation,
7
+ } from '@angular/core';
8
+ import { CommonModule } from '@angular/common';
9
+ import { TRPC } from '../services/trpc.client';
10
+ import { Identity } from '@reactionary/core';
11
+
12
+ @Component({
13
+ selector: 'app-identity',
14
+ imports: [CommonModule],
15
+ templateUrl: './identity.component.html',
16
+ styleUrl: './identity.component.scss',
17
+ encapsulation: ViewEncapsulation.ShadowDom,
18
+ changeDetection: ChangeDetectionStrategy.OnPush,
19
+ })
20
+ export class IdentityComponent {
21
+ protected trpc = inject(TRPC);
22
+ protected identity = signal<Identity | undefined>(undefined);
23
+
24
+ protected async login(username: string, password: string) {
25
+ const res = await this.trpc.client.identityMutation.mutate([
26
+ {
27
+ mutation: 'login',
28
+ username,
29
+ password
30
+ }
31
+ ]);
32
+
33
+ this.identity.set(res);
34
+ }
35
+
36
+ protected async logout() {
37
+ const res = await this.trpc.client.identityMutation.mutate([{
38
+ mutation: 'logout'
39
+ }])
40
+
41
+ this.identity.set(res);
42
+ }
43
+
44
+ protected async refresh() {
45
+ const res = await this.trpc.client.identity.query([{ query: 'self' }])
46
+
47
+ this.identity.set(res[0]);
48
+ }
49
+ }
@@ -0,0 +1,14 @@
1
+ @if (service.productResource.value(); as product) {
2
+ <section>
3
+ <img [src]="product.image" [alt]="product.name" />
4
+ </section>
5
+ <section>
6
+ <h2>{{ product.name }}</h2>
7
+ <h3>{{ product.description }}</h3>
8
+ <ol>
9
+ @for (attribute of product.attributes; track $index) {
10
+ ${{ attribute | json }}
11
+ }
12
+ </ol>
13
+ </section>
14
+ }
@@ -0,0 +1,11 @@
1
+ :host {
2
+ display: grid;
3
+ grid-template-columns: 1fr 1fr;
4
+ gap: 1rem;
5
+ color: rgb(205, 214, 244);
6
+ }
7
+
8
+ img {
9
+ width: 100%;
10
+ border-radius: 0.5rem;
11
+ }
@@ -0,0 +1,42 @@
1
+ import { Component, effect, inject } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { ProductService } from '../services/product.service';
4
+ import { TRPC } from '../services/trpc.client';
5
+
6
+ @Component({
7
+ selector: 'app-product',
8
+ imports: [CommonModule],
9
+ templateUrl: './product.component.html',
10
+ styleUrl: './product.component.scss',
11
+ })
12
+ export class ProductComponent {
13
+ protected service = inject(ProductService);
14
+ protected trpc = inject(TRPC);
15
+
16
+ constructor() {
17
+ effect(async () => {
18
+ const product = this.service.productResource.value();
19
+
20
+ console.log('product: ', product);
21
+
22
+ if (product && product.skus.length > 0) {
23
+ const inventory = await this.trpc.client.inventory.query([{
24
+ query: 'sku',
25
+ sku: product.skus[0].identifier.key,
26
+ }]);
27
+ console.log('inventory: ', inventory);
28
+
29
+ const prices = await this.trpc.client.price.query([
30
+ { sku: product.skus[0].identifier, query: 'sku' },
31
+ ]);
32
+ console.log('price: ', prices);
33
+
34
+ const pricesWithUnknownSku = await this.trpc.client.price.query([
35
+ { sku: product.skus[0].identifier, query: 'sku' },
36
+ { sku: { key: '123456' }, query: 'sku' },
37
+ ]);
38
+ console.log('pricesWithUnknownSku: ', pricesWithUnknownSku);
39
+ }
40
+ });
41
+ }
42
+ }
@@ -0,0 +1,35 @@
1
+ <aside>
2
+ @for (facet of service.search()?.facets; track $index) {
3
+ <details [open]="true">
4
+ <summary>{{ facet.name }}</summary>
5
+
6
+ <div class="content">
7
+ @for (value of facet.values; track $index) {
8
+ <label>
9
+ <span>{{ value.name }}</span>
10
+ <span>{{ value.count }}</span>
11
+ <input type="checkbox" (click)="toggleFacet(value.identifier)" [checked]="value.active"/>
12
+ </label>
13
+ }
14
+ </div>
15
+ </details>
16
+ }
17
+ </aside>
18
+ <section>
19
+ @for (product of service.search()?.products; track $index) {
20
+ <a [routerLink]="['/', 'product', product.slug]">
21
+ <article>
22
+ <img [src]="product.image.replace('w_200', 'w_200,h_200,')" [alt]="product.name" />
23
+ <h3>{{ product.name }}</h3>
24
+ </article>
25
+ </a>
26
+ }
27
+ </section>
28
+ <footer>
29
+ <button (click)="previousPage()" [disabled]="hasPrevious()">
30
+ &lt;
31
+ </button>
32
+ <button (click)="nextPage()" [disabled]="hasNext()">
33
+ &gt;
34
+ </button>
35
+ </footer>