@vendure/dashboard 3.7.0-minor-202607010310 → 3.7.0
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/dist/bundle/chunks/{2SSKDMRQ-mFHSQL2r.js → 2SSKDMRQ-Ddh65BrY.js} +2 -2
- package/dist/bundle/chunks/{AP7HFJJL-C8jBgxkH.js → AP7HFJJL-Db7gWBRq.js} +1 -1
- package/dist/bundle/chunks/{WDYDFRGG-CV5uCOo9.js → WDYDFRGG-D-AGRv_K.js} +2 -2
- package/dist/bundle/chunks/{main-BrEvUQtC.js → main-DsM_74hl.js} +18 -18
- package/dist/bundle/main.js +1 -1
- package/package.json +3 -3
- package/src/app/derive-base-url.spec.ts +53 -0
- package/src/app/derive-base-url.ts +41 -0
- package/src/app/main.tsx +6 -26
- package/dist/vite/.vendure-dashboard-temp/compiler/4381-13d969e9-469a-43f5-bf2c-2e91858ef25e/dev-config.js +0 -251
- package/dist/vite/.vendure-dashboard-temp/compiler/4381-13d969e9-469a-43f5-bf2c-2e91858ef25e/package.json +0 -4
- package/dist/vite/.vendure-dashboard-temp/compiler/4381-13d969e9-469a-43f5-bf2c-2e91858ef25e/test-plugins/nav-modifier-plugin/nav-modifier-plugin.js +0 -23
- package/dist/vite/.vendure-dashboard-temp/compiler/4381-13d969e9-469a-43f5-bf2c-2e91858ef25e/test-plugins/reviews/api/api-extensions.js +0 -99
- package/dist/vite/.vendure-dashboard-temp/compiler/4381-13d969e9-469a-43f5-bf2c-2e91858ef25e/test-plugins/reviews/api/product-entity.resolver.js +0 -73
- package/dist/vite/.vendure-dashboard-temp/compiler/4381-13d969e9-469a-43f5-bf2c-2e91858ef25e/test-plugins/reviews/api/product-review-admin.resolver.js +0 -146
- package/dist/vite/.vendure-dashboard-temp/compiler/4381-13d969e9-469a-43f5-bf2c-2e91858ef25e/test-plugins/reviews/api/product-review-entity.resolver.js +0 -79
- package/dist/vite/.vendure-dashboard-temp/compiler/4381-13d969e9-469a-43f5-bf2c-2e91858ef25e/test-plugins/reviews/api/product-review-shop.resolver.js +0 -79
- package/dist/vite/.vendure-dashboard-temp/compiler/4381-13d969e9-469a-43f5-bf2c-2e91858ef25e/test-plugins/reviews/entities/product-review-translation.entity.js +0 -47
- package/dist/vite/.vendure-dashboard-temp/compiler/4381-13d969e9-469a-43f5-bf2c-2e91858ef25e/test-plugins/reviews/entities/product-review.entity.js +0 -90
- package/dist/vite/.vendure-dashboard-temp/compiler/4381-13d969e9-469a-43f5-bf2c-2e91858ef25e/test-plugins/reviews/generated-admin-types.js +0 -1021
- package/dist/vite/.vendure-dashboard-temp/compiler/4381-13d969e9-469a-43f5-bf2c-2e91858ef25e/test-plugins/reviews/generated-shop-types.js +0 -974
- package/dist/vite/.vendure-dashboard-temp/compiler/4381-13d969e9-469a-43f5-bf2c-2e91858ef25e/test-plugins/reviews/reviews-plugin.js +0 -46
- package/dist/vite/.vendure-dashboard-temp/compiler/4381-13d969e9-469a-43f5-bf2c-2e91858ef25e/test-plugins/reviews/types.js +0 -2
- package/dist/vite/.vendure-dashboard-temp/gql-tada/4381-13d969e9-469a-43f5-bf2c-2e91858ef25e/schema.graphql +0 -6844
- package/dist/vite/.vendure-dashboard-temp/gql-tada/4381-13d969e9-469a-43f5-bf2c-2e91858ef25e/tsconfig.json +0 -10
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3449-17220ddc-97f6-49c6-99d8-e74b8e94d5f2 → 3390-1f9204be-301a-46ef-909f-bcf03820d62c}/dev-config.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3449-17220ddc-97f6-49c6-99d8-e74b8e94d5f2 → 3390-1f9204be-301a-46ef-909f-bcf03820d62c}/package.json +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3449-17220ddc-97f6-49c6-99d8-e74b8e94d5f2 → 3390-1f9204be-301a-46ef-909f-bcf03820d62c}/test-plugins/nav-modifier-plugin/nav-modifier-plugin.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3449-17220ddc-97f6-49c6-99d8-e74b8e94d5f2 → 3390-1f9204be-301a-46ef-909f-bcf03820d62c}/test-plugins/reviews/api/api-extensions.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3449-17220ddc-97f6-49c6-99d8-e74b8e94d5f2 → 3390-1f9204be-301a-46ef-909f-bcf03820d62c}/test-plugins/reviews/api/product-entity.resolver.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3449-17220ddc-97f6-49c6-99d8-e74b8e94d5f2 → 3390-1f9204be-301a-46ef-909f-bcf03820d62c}/test-plugins/reviews/api/product-review-admin.resolver.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3449-17220ddc-97f6-49c6-99d8-e74b8e94d5f2 → 3390-1f9204be-301a-46ef-909f-bcf03820d62c}/test-plugins/reviews/api/product-review-entity.resolver.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3449-17220ddc-97f6-49c6-99d8-e74b8e94d5f2 → 3390-1f9204be-301a-46ef-909f-bcf03820d62c}/test-plugins/reviews/api/product-review-shop.resolver.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3449-17220ddc-97f6-49c6-99d8-e74b8e94d5f2 → 3390-1f9204be-301a-46ef-909f-bcf03820d62c}/test-plugins/reviews/entities/product-review-translation.entity.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3449-17220ddc-97f6-49c6-99d8-e74b8e94d5f2 → 3390-1f9204be-301a-46ef-909f-bcf03820d62c}/test-plugins/reviews/entities/product-review.entity.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3449-17220ddc-97f6-49c6-99d8-e74b8e94d5f2 → 3390-1f9204be-301a-46ef-909f-bcf03820d62c}/test-plugins/reviews/generated-admin-types.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3449-17220ddc-97f6-49c6-99d8-e74b8e94d5f2 → 3390-1f9204be-301a-46ef-909f-bcf03820d62c}/test-plugins/reviews/generated-shop-types.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3449-17220ddc-97f6-49c6-99d8-e74b8e94d5f2 → 3390-1f9204be-301a-46ef-909f-bcf03820d62c}/test-plugins/reviews/reviews-plugin.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/compiler/{3449-17220ddc-97f6-49c6-99d8-e74b8e94d5f2 → 3390-1f9204be-301a-46ef-909f-bcf03820d62c}/test-plugins/reviews/types.js +0 -0
- /package/dist/vite/.vendure-dashboard-temp/gql-tada/{3449-17220ddc-97f6-49c6-99d8-e74b8e94d5f2 → 3390-1f9204be-301a-46ef-909f-bcf03820d62c}/schema.graphql +0 -0
- /package/dist/vite/.vendure-dashboard-temp/gql-tada/{3449-17220ddc-97f6-49c6-99d8-e74b8e94d5f2 → 3390-1f9204be-301a-46ef-909f-bcf03820d62c}/tsconfig.json +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as createLocalStorage, T as THEME_PREFERENCE, P as PiPProvider, a as ThemeContext, b as ParentPanel, C as ContentView, Q as QueryDevtoolsContext } from "./AP7HFJJL-
|
|
2
|
-
import { g as getPreferredColorScheme, c as createMemo, a as createComponent } from "./main-
|
|
1
|
+
import { c as createLocalStorage, T as THEME_PREFERENCE, P as PiPProvider, a as ThemeContext, b as ParentPanel, C as ContentView, Q as QueryDevtoolsContext } from "./AP7HFJJL-Db7gWBRq.js";
|
|
2
|
+
import { g as getPreferredColorScheme, c as createMemo, a as createComponent } from "./main-DsM_74hl.js";
|
|
3
3
|
var DevtoolsPanelComponent = (props) => {
|
|
4
4
|
const [localStore, setLocalStore] = createLocalStorage({
|
|
5
5
|
prefix: "TanstackQueryDevtools"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as createContext, d as createSignal, o as onMount, e as createEffect, c as createMemo, a as createComponent, P as Portal, m as memo, S as Show, t as template, i as insert, f as createRenderEffect, h as className, j as clearDelegatedEvents, k as delegateEvents, u as useContext, l as onCleanup, s as sortFns, n as mutationSortFns, p as on, q as setAttribute, r as getSidedProp, v as use, w as convertRemToPixels, x as createUniqueId, y as batch, z as getQueryStatusLabel, A as getMutationStatusColor, B as getQueryStatusColor, C as getQueryStatusColorByLabel, D as displayValue, F as For, E as untrack, $ as $TRACK, G as useTransition, H as spread, I as mergeProps, J as createRoot, K as serialize, L as Index, M as updateNestedDataByPath, N as addEventListener, O as stringify, Q as Match, R as Switch, T as deleteNestedDataByPath, U as splitProps, V as Dynamic, W as createComputed } from "./main-
|
|
1
|
+
import { b as createContext, d as createSignal, o as onMount, e as createEffect, c as createMemo, a as createComponent, P as Portal, m as memo, S as Show, t as template, i as insert, f as createRenderEffect, h as className, j as clearDelegatedEvents, k as delegateEvents, u as useContext, l as onCleanup, s as sortFns, n as mutationSortFns, p as on, q as setAttribute, r as getSidedProp, v as use, w as convertRemToPixels, x as createUniqueId, y as batch, z as getQueryStatusLabel, A as getMutationStatusColor, B as getQueryStatusColor, C as getQueryStatusColorByLabel, D as displayValue, F as For, E as untrack, $ as $TRACK, G as useTransition, H as spread, I as mergeProps, J as createRoot, K as serialize, L as Index, M as updateNestedDataByPath, N as addEventListener, O as stringify, Q as Match, R as Switch, T as deleteNestedDataByPath, U as splitProps, V as Dynamic, W as createComputed } from "./main-DsM_74hl.js";
|
|
2
2
|
var isNonNullable = (i2) => i2 != null;
|
|
3
3
|
var filterNonNullable = (arr) => arr.filter(isNonNullable);
|
|
4
4
|
function chain(callbacks) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as createLocalStorage, T as THEME_PREFERENCE, P as PiPProvider, a as ThemeContext, D as Devtools, Q as QueryDevtoolsContext } from "./AP7HFJJL-
|
|
2
|
-
import { g as getPreferredColorScheme, c as createMemo, a as createComponent } from "./main-
|
|
1
|
+
import { c as createLocalStorage, T as THEME_PREFERENCE, P as PiPProvider, a as ThemeContext, D as Devtools, Q as QueryDevtoolsContext } from "./AP7HFJJL-Db7gWBRq.js";
|
|
2
|
+
import { g as getPreferredColorScheme, c as createMemo, a as createComponent } from "./main-DsM_74hl.js";
|
|
3
3
|
var DevtoolsComponent = (props) => {
|
|
4
4
|
const [localStore, setLocalStore] = createLocalStorage({
|
|
5
5
|
prefix: "TanstackQueryDevtools"
|
|
@@ -3812,7 +3812,7 @@ var TanstackQueryDevtools = class {
|
|
|
3812
3812
|
if (this.#Component) {
|
|
3813
3813
|
Devtools = this.#Component;
|
|
3814
3814
|
} else {
|
|
3815
|
-
Devtools = lazy(() => import("./WDYDFRGG-
|
|
3815
|
+
Devtools = lazy(() => import("./WDYDFRGG-D-AGRv_K.js"));
|
|
3816
3816
|
this.#Component = Devtools;
|
|
3817
3817
|
}
|
|
3818
3818
|
setupStyleSheet(this.#styleNonce, this.#shadowDOMTarget);
|
|
@@ -3950,7 +3950,7 @@ var TanstackQueryDevtoolsPanel = class {
|
|
|
3950
3950
|
if (this.#Component) {
|
|
3951
3951
|
Devtools = this.#Component;
|
|
3952
3952
|
} else {
|
|
3953
|
-
Devtools = lazy(() => import("./2SSKDMRQ-
|
|
3953
|
+
Devtools = lazy(() => import("./2SSKDMRQ-Ddh65BrY.js"));
|
|
3954
3954
|
this.#Component = Devtools;
|
|
3955
3955
|
}
|
|
3956
3956
|
setupStyleSheet(this.#styleNonce, this.#shadowDOMTarget);
|
|
@@ -4152,6 +4152,21 @@ function AppProviders({
|
|
|
4152
4152
|
function setDocumentDirection(direction) {
|
|
4153
4153
|
document.documentElement.setAttribute("dir", direction);
|
|
4154
4154
|
}
|
|
4155
|
+
function deriveBaseUrl(moduleUrl, fallbackBase) {
|
|
4156
|
+
let derived;
|
|
4157
|
+
try {
|
|
4158
|
+
if (moduleUrl) {
|
|
4159
|
+
const entryRe = /^(.*)\/(?:src\/app|dist\/bundle)\//;
|
|
4160
|
+
const m = entryRe.exec(new URL(moduleUrl).pathname);
|
|
4161
|
+
if (m) derived = m[1] || "/";
|
|
4162
|
+
}
|
|
4163
|
+
} catch {
|
|
4164
|
+
}
|
|
4165
|
+
const baseUrl = derived ?? fallbackBase;
|
|
4166
|
+
if (!baseUrl || baseUrl === "/") return void 0;
|
|
4167
|
+
const normalized = baseUrl.startsWith("/") ? baseUrl : "/" + baseUrl;
|
|
4168
|
+
return normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
|
|
4169
|
+
}
|
|
4155
4170
|
const DEFAULT_TITLE = "Vendure";
|
|
4156
4171
|
function usePageTitle() {
|
|
4157
4172
|
const matches = useMatches();
|
|
@@ -26654,22 +26669,7 @@ const rootRouteChildren = {
|
|
|
26654
26669
|
LoginRoute
|
|
26655
26670
|
};
|
|
26656
26671
|
const routeTree = Route$W._addFileChildren(rootRouteChildren)._addFileTypes();
|
|
26657
|
-
const processedBaseUrl = (
|
|
26658
|
-
let derived;
|
|
26659
|
-
try {
|
|
26660
|
-
const moduleUrl = typeof import.meta?.url === "string" ? import.meta.url : "";
|
|
26661
|
-
if (moduleUrl) {
|
|
26662
|
-
const entryRe = /^(.*?)\/(?:src\/app\/main|dist\/bundle\/main)\.[a-z]+/;
|
|
26663
|
-
const m = entryRe.exec(new URL(moduleUrl).pathname);
|
|
26664
|
-
if (m) derived = m[1] || "/";
|
|
26665
|
-
}
|
|
26666
|
-
} catch {
|
|
26667
|
-
}
|
|
26668
|
-
const baseUrl = derived ?? "/";
|
|
26669
|
-
if (!baseUrl || baseUrl === "/") return void 0;
|
|
26670
|
-
const normalized = baseUrl.startsWith("/") ? baseUrl : "/" + baseUrl;
|
|
26671
|
-
return normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
|
|
26672
|
-
})();
|
|
26672
|
+
const processedBaseUrl = deriveBaseUrl(typeof import.meta?.url === "string" ? import.meta.url : "", "/");
|
|
26673
26673
|
const routerOptions = {
|
|
26674
26674
|
defaultPreload: "intent",
|
|
26675
26675
|
scrollRestoration: true,
|
package/dist/bundle/main.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vendure/dashboard",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "3.7.0
|
|
4
|
+
"version": "3.7.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -138,8 +138,8 @@
|
|
|
138
138
|
"@storybook/addon-vitest": "^10.3.1",
|
|
139
139
|
"@storybook/react-vite": "^10.3.1",
|
|
140
140
|
"@types/node": "^22.19.0",
|
|
141
|
-
"@vendure/common": "
|
|
142
|
-
"@vendure/core": "
|
|
141
|
+
"@vendure/common": "3.7.0",
|
|
142
|
+
"@vendure/core": "3.7.0",
|
|
143
143
|
"@vitest/browser": "^3.2.4",
|
|
144
144
|
"@vitest/coverage-v8": "^3.2.4",
|
|
145
145
|
"eslint": "^9.39.0",
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { deriveBaseUrl } from './derive-base-url.js';
|
|
4
|
+
|
|
5
|
+
describe('deriveBaseUrl', () => {
|
|
6
|
+
const origin = 'http://localhost:5174';
|
|
7
|
+
|
|
8
|
+
it('derives the base from the bundle entry file', () => {
|
|
9
|
+
expect(deriveBaseUrl(`${origin}/admin/dashboard/dist/bundle/main.js`, '/')).toBe('/admin/dashboard');
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
// #4719 — in bundle mode the derivation code is split into a hashed chunk,
|
|
13
|
+
// so the module URL points at dist/bundle/chunks/main-<hash>.js, not main.js.
|
|
14
|
+
it('derives the base from a code-split bundle chunk', () => {
|
|
15
|
+
expect(deriveBaseUrl(`${origin}/admin/dashboard/dist/bundle/chunks/main-abc123.js`, '/')).toBe(
|
|
16
|
+
'/admin/dashboard',
|
|
17
|
+
);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('derives the base from the source entry (dev / source-shipping mode)', () => {
|
|
21
|
+
expect(deriveBaseUrl(`${origin}/admin/dashboard/src/app/main.tsx`, '/')).toBe('/admin/dashboard');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('returns undefined when mounted at the root (bundle)', () => {
|
|
25
|
+
expect(deriveBaseUrl(`${origin}/dist/bundle/main.js`, '/')).toBeUndefined();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('returns undefined when mounted at the root (source)', () => {
|
|
29
|
+
expect(deriveBaseUrl(`${origin}/src/app/main.tsx`, '/')).toBeUndefined();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Greedy match must anchor on the LAST marker occurrence, so a deployment
|
|
33
|
+
// base that itself contains a marker segment is not truncated.
|
|
34
|
+
it('does not truncate when the deployment base contains a marker segment', () => {
|
|
35
|
+
expect(deriveBaseUrl(`${origin}/vendor/src/app/my-admin/dist/bundle/chunks/main-abc.js`, '/')).toBe(
|
|
36
|
+
'/vendor/src/app/my-admin',
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('strips a trailing slash from the fallback base', () => {
|
|
41
|
+
expect(deriveBaseUrl('', '/admin/dashboard/')).toBe('/admin/dashboard');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('falls back to the provided base when the module URL yields no marker', () => {
|
|
45
|
+
expect(deriveBaseUrl(`${origin}/something/else/entry.js`, '/admin/dashboard')).toBe(
|
|
46
|
+
'/admin/dashboard',
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('returns undefined for an invalid module URL with no usable fallback', () => {
|
|
51
|
+
expect(deriveBaseUrl('not a url', '/')).toBeUndefined();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description
|
|
3
|
+
* Derives the router `basepath` from the running module's own URL.
|
|
4
|
+
*
|
|
5
|
+
* Works in BOTH source-shipping mode (`<base>/src/app/main.tsx`) and the
|
|
6
|
+
* experimental bundle mode (`<base>/dist/bundle/...`). Using the module URL is
|
|
7
|
+
* stable regardless of which sub-route the page was first loaded on — reading
|
|
8
|
+
* `document.baseURI` instead breaks deep-link navigation because it reflects
|
|
9
|
+
* the current page URL, not the dashboard root (see issue #4719).
|
|
10
|
+
*
|
|
11
|
+
* The regex anchors on the marker directory (`src/app` / `dist/bundle`) rather
|
|
12
|
+
* than the entry filename: in bundle mode Vite code-splits this logic into a
|
|
13
|
+
* hashed chunk served from `dist/bundle/chunks/main-<hash>.js`, so `moduleUrl`
|
|
14
|
+
* points at the chunk, not `dist/bundle/main.js`. The match is greedy so it
|
|
15
|
+
* anchors on the LAST occurrence of the marker — which is always the
|
|
16
|
+
* dashboard's own entry, since the entry file is the final path segment. This
|
|
17
|
+
* means an intermediate `/src/app/` or `/dist/bundle/` in the deployment base
|
|
18
|
+
* cannot truncate the result.
|
|
19
|
+
*
|
|
20
|
+
* @param moduleUrl - typically `import.meta.url` of the calling module.
|
|
21
|
+
* @param fallbackBase - used when the module URL yields no base, typically
|
|
22
|
+
* `import.meta.env.BASE_URL`.
|
|
23
|
+
* @returns the normalized base (leading slash, no trailing slash), or
|
|
24
|
+
* `undefined` when the dashboard is mounted at the root.
|
|
25
|
+
*/
|
|
26
|
+
export function deriveBaseUrl(moduleUrl: string, fallbackBase: string | undefined): string | undefined {
|
|
27
|
+
let derived: string | undefined;
|
|
28
|
+
try {
|
|
29
|
+
if (moduleUrl) {
|
|
30
|
+
const entryRe = /^(.*)\/(?:src\/app|dist\/bundle)\//;
|
|
31
|
+
const m = entryRe.exec(new URL(moduleUrl).pathname);
|
|
32
|
+
if (m) derived = m[1] || '/';
|
|
33
|
+
}
|
|
34
|
+
} catch {
|
|
35
|
+
// Ignore — fall back to `fallbackBase` below.
|
|
36
|
+
}
|
|
37
|
+
const baseUrl = derived ?? fallbackBase;
|
|
38
|
+
if (!baseUrl || baseUrl === '/') return undefined;
|
|
39
|
+
const normalized = baseUrl.startsWith('/') ? baseUrl : '/' + baseUrl;
|
|
40
|
+
return normalized.endsWith('/') ? normalized.slice(0, -1) : normalized;
|
|
41
|
+
}
|
package/src/app/main.tsx
CHANGED
|
@@ -16,41 +16,21 @@ import React, { useEffect } from 'react';
|
|
|
16
16
|
import { createPortal } from 'react-dom';
|
|
17
17
|
import { createRoot } from 'react-dom/client';
|
|
18
18
|
|
|
19
|
+
import { DirectionProvider } from '@/vdb/components/ui/direction.js';
|
|
19
20
|
import { useDisplayLocale } from '@/vdb/hooks/use-display-locale.js';
|
|
20
21
|
import { useUiLanguageLoader } from '@/vdb/hooks/use-ui-language-loader.js';
|
|
21
22
|
import { useUserSettings } from '@/vdb/hooks/use-user-settings.js';
|
|
22
|
-
import { DirectionProvider } from '@/vdb/components/ui/direction.js';
|
|
23
23
|
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
|
24
24
|
import { AppProviders, queryClient } from './app-providers.js';
|
|
25
25
|
import { setDocumentDirection } from './common/set-document-direction.js';
|
|
26
|
+
import { deriveBaseUrl } from './derive-base-url.js';
|
|
26
27
|
import { routeTree } from './routeTree.gen.js';
|
|
27
28
|
import './styles.css';
|
|
28
29
|
|
|
29
|
-
const processedBaseUrl = (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
// issue #4719). Using `import.meta.url` is stable regardless of what
|
|
34
|
-
// sub-route the page was first loaded on, which is important: previous
|
|
35
|
-
// attempts to read `document.baseURI` broke deep-link navigation because
|
|
36
|
-
// it reflects the CURRENT page URL, not the dashboard root.
|
|
37
|
-
let derived: string | undefined;
|
|
38
|
-
try {
|
|
39
|
-
const moduleUrl = typeof import.meta?.url === 'string' ? import.meta.url : '';
|
|
40
|
-
if (moduleUrl) {
|
|
41
|
-
const entryRe = /^(.*?)\/(?:src\/app\/main|dist\/bundle\/main)\.[a-z]+/;
|
|
42
|
-
const m = entryRe.exec(new URL(moduleUrl).pathname);
|
|
43
|
-
if (m) derived = m[1] || '/';
|
|
44
|
-
}
|
|
45
|
-
} catch {
|
|
46
|
-
// Ignore — fall back to import.meta.env.BASE_URL below.
|
|
47
|
-
}
|
|
48
|
-
const baseUrl = derived ?? import.meta.env.BASE_URL;
|
|
49
|
-
if (!baseUrl || baseUrl === '/') return undefined;
|
|
50
|
-
// Ensure leading slash, remove trailing slash
|
|
51
|
-
const normalized = baseUrl.startsWith('/') ? baseUrl : '/' + baseUrl;
|
|
52
|
-
return normalized.endsWith('/') ? normalized.slice(0, -1) : normalized;
|
|
53
|
-
})();
|
|
30
|
+
const processedBaseUrl = deriveBaseUrl(
|
|
31
|
+
typeof import.meta?.url === 'string' ? import.meta.url : '',
|
|
32
|
+
import.meta.env.BASE_URL,
|
|
33
|
+
);
|
|
54
34
|
|
|
55
35
|
const routerOptions: RouterOptions<AnyRoute, any> = {
|
|
56
36
|
defaultPreload: 'intent' as const,
|
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
-
};
|
|
8
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
-
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
|
-
var _a, _b;
|
|
15
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.devConfig = void 0;
|
|
17
|
-
const admin_ui_plugin_1 = require("@vendure/admin-ui-plugin");
|
|
18
|
-
const asset_server_plugin_1 = require("@vendure/asset-server-plugin");
|
|
19
|
-
const shared_constants_1 = require("@vendure/common/lib/shared-constants");
|
|
20
|
-
const core_1 = require("@vendure/core");
|
|
21
|
-
const plugin_1 = require("@vendure/dashboard/plugin");
|
|
22
|
-
const email_plugin_1 = require("@vendure/email-plugin");
|
|
23
|
-
const graphiql_plugin_1 = require("@vendure/graphiql-plugin");
|
|
24
|
-
const telemetry_plugin_1 = require("@vendure/telemetry-plugin");
|
|
25
|
-
require("dotenv/config");
|
|
26
|
-
const path_1 = __importDefault(require("path"));
|
|
27
|
-
const nav_modifier_plugin_1 = require("./test-plugins/nav-modifier-plugin/nav-modifier-plugin");
|
|
28
|
-
// import { FieldTestPlugin } from './test-plugins/field-test/field-test-plugin';
|
|
29
|
-
const reviews_plugin_1 = require("./test-plugins/reviews/reviews-plugin");
|
|
30
|
-
const IS_INSTRUMENTED = process.env.IS_INSTRUMENTED === 'true';
|
|
31
|
-
const dashboardAppDir = path_1.default.basename(__dirname) === 'dist'
|
|
32
|
-
? path_1.default.join(__dirname, './dashboard')
|
|
33
|
-
: path_1.default.join(__dirname, './dist/dashboard');
|
|
34
|
-
let ReadonlySettingsTestPlugin = class ReadonlySettingsTestPlugin {
|
|
35
|
-
constructor(settingsStoreService, requestContextService) {
|
|
36
|
-
this.settingsStoreService = settingsStoreService;
|
|
37
|
-
this.requestContextService = requestContextService;
|
|
38
|
-
}
|
|
39
|
-
async onApplicationBootstrap() {
|
|
40
|
-
const ctx = await this.requestContextService.create({ apiType: 'admin' });
|
|
41
|
-
await this.settingsStoreService.set(ctx, 'ReadonlyTest.buildVersion', 'v3.5.2');
|
|
42
|
-
await this.settingsStoreService.set(ctx, 'ReadonlyTest.buildMeta', {
|
|
43
|
-
buildDate: '2026-03-06',
|
|
44
|
-
commit: 'd0384f3ed',
|
|
45
|
-
features: ['settings-store-ui', 'option-groups'],
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
ReadonlySettingsTestPlugin = __decorate([
|
|
50
|
-
(0, core_1.VendurePlugin)({
|
|
51
|
-
imports: [core_1.PluginCommonModule],
|
|
52
|
-
configuration: config => {
|
|
53
|
-
config.settingsStoreFields = {
|
|
54
|
-
...config.settingsStoreFields,
|
|
55
|
-
ReadonlyTest: [
|
|
56
|
-
{ name: 'buildVersion', readonly: true },
|
|
57
|
-
{ name: 'buildMeta', readonly: true },
|
|
58
|
-
],
|
|
59
|
-
};
|
|
60
|
-
return config;
|
|
61
|
-
},
|
|
62
|
-
}),
|
|
63
|
-
__metadata("design:paramtypes", [typeof (_a = typeof core_1.SettingsStoreService !== "undefined" && core_1.SettingsStoreService) === "function" ? _a : Object, typeof (_b = typeof core_1.RequestContextService !== "undefined" && core_1.RequestContextService) === "function" ? _b : Object])
|
|
64
|
-
], ReadonlySettingsTestPlugin);
|
|
65
|
-
/**
|
|
66
|
-
* Config settings used during development
|
|
67
|
-
*/
|
|
68
|
-
exports.devConfig = {
|
|
69
|
-
apiOptions: {
|
|
70
|
-
port: Number(process.env.API_PORT) || shared_constants_1.API_PORT,
|
|
71
|
-
adminApiPath: shared_constants_1.ADMIN_API_PATH,
|
|
72
|
-
adminApiPlayground: {
|
|
73
|
-
settings: {
|
|
74
|
-
'request.credentials': 'include',
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
adminApiDebug: true,
|
|
78
|
-
shopApiPath: shared_constants_1.SHOP_API_PATH,
|
|
79
|
-
shopApiPlayground: {
|
|
80
|
-
settings: {
|
|
81
|
-
'request.credentials': 'include',
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
shopApiDebug: true,
|
|
85
|
-
},
|
|
86
|
-
authOptions: {
|
|
87
|
-
disableAuth: false,
|
|
88
|
-
tokenMethod: ['bearer', 'cookie', 'api-key'],
|
|
89
|
-
requireVerification: true,
|
|
90
|
-
customPermissions: [],
|
|
91
|
-
cookieOptions: {
|
|
92
|
-
secret: 'abc',
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
dbConnectionOptions: {
|
|
96
|
-
synchronize: false,
|
|
97
|
-
logging: false,
|
|
98
|
-
migrations: [path_1.default.join(__dirname, 'migrations/*.ts')],
|
|
99
|
-
...getDbConfig(),
|
|
100
|
-
},
|
|
101
|
-
paymentOptions: {
|
|
102
|
-
paymentMethodHandlers: [core_1.dummyPaymentHandler],
|
|
103
|
-
},
|
|
104
|
-
settingsStoreFields: {
|
|
105
|
-
MyPlugin: [
|
|
106
|
-
{
|
|
107
|
-
name: 'globalVal',
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
name: 'userVal',
|
|
111
|
-
scope: core_1.SettingsStoreScopes.user,
|
|
112
|
-
},
|
|
113
|
-
],
|
|
114
|
-
},
|
|
115
|
-
customFields: {},
|
|
116
|
-
logger: new core_1.DefaultLogger({ level: core_1.LogLevel.Verbose }),
|
|
117
|
-
importExportOptions: {
|
|
118
|
-
importAssetsDir: path_1.default.join(__dirname, 'import-assets'),
|
|
119
|
-
},
|
|
120
|
-
plugins: [
|
|
121
|
-
// MultivendorPlugin.init({
|
|
122
|
-
// platformFeePercent: 10,
|
|
123
|
-
// platformFeeSKU: 'FEE',
|
|
124
|
-
// }),
|
|
125
|
-
ReadonlySettingsTestPlugin,
|
|
126
|
-
reviews_plugin_1.ReviewsPlugin,
|
|
127
|
-
// FieldTestPlugin,
|
|
128
|
-
nav_modifier_plugin_1.NavModifierPlugin,
|
|
129
|
-
graphiql_plugin_1.GraphiqlPlugin.init(),
|
|
130
|
-
asset_server_plugin_1.AssetServerPlugin.init({
|
|
131
|
-
route: 'assets',
|
|
132
|
-
assetUploadDir: path_1.default.join(__dirname, 'assets'),
|
|
133
|
-
}),
|
|
134
|
-
core_1.DefaultSearchPlugin.init({ bufferUpdates: false, indexStockStatus: false }),
|
|
135
|
-
// Enable if you need to debug the job queue
|
|
136
|
-
// BullMQJobQueuePlugin.init({}),
|
|
137
|
-
core_1.DefaultJobQueuePlugin.init({}),
|
|
138
|
-
// JobQueueTestPlugin.init({ queueCount: 10 }),
|
|
139
|
-
core_1.DefaultSchedulerPlugin.init({}),
|
|
140
|
-
email_plugin_1.EmailPlugin.init({
|
|
141
|
-
devMode: true,
|
|
142
|
-
route: 'mailbox',
|
|
143
|
-
handlers: email_plugin_1.defaultEmailHandlers,
|
|
144
|
-
templateLoader: new email_plugin_1.FileBasedTemplateLoader(path_1.default.join(__dirname, '../email-plugin/templates')),
|
|
145
|
-
outputPath: path_1.default.join(__dirname, 'test-emails'),
|
|
146
|
-
globalTemplateVars: {
|
|
147
|
-
verifyEmailAddressUrl: 'http://localhost:4201/verify',
|
|
148
|
-
passwordResetUrl: 'http://localhost:4201/reset-password',
|
|
149
|
-
changeEmailAddressUrl: 'http://localhost:4201/change-email-address',
|
|
150
|
-
},
|
|
151
|
-
}),
|
|
152
|
-
...(IS_INSTRUMENTED ? [telemetry_plugin_1.TelemetryPlugin.init({})] : []),
|
|
153
|
-
// AdminUiPlugin.init({
|
|
154
|
-
// route: 'admin',
|
|
155
|
-
// port: 5001,
|
|
156
|
-
// adminUiConfig: {},
|
|
157
|
-
// // Un-comment to compile a custom admin ui
|
|
158
|
-
// // app: compileUiExtensions({
|
|
159
|
-
// // outputPath: path.join(__dirname, './custom-admin-ui'),
|
|
160
|
-
// // extensions: [
|
|
161
|
-
// // {
|
|
162
|
-
// // id: 'ui-extensions-library',
|
|
163
|
-
// // extensionPath: path.join(__dirname, 'example-plugins/ui-extensions-library/ui'),
|
|
164
|
-
// // routes: [{ route: 'ui-library', filePath: 'routes.ts' }],
|
|
165
|
-
// // providers: ['providers.ts'],
|
|
166
|
-
// // },
|
|
167
|
-
// // {
|
|
168
|
-
// // globalStyles: path.join(
|
|
169
|
-
// // __dirname,
|
|
170
|
-
// // 'test-plugins/with-ui-extension/ui/custom-theme.scss',
|
|
171
|
-
// // ),
|
|
172
|
-
// // },
|
|
173
|
-
// // ],
|
|
174
|
-
// // devMode: true,
|
|
175
|
-
// // }),
|
|
176
|
-
// }),
|
|
177
|
-
admin_ui_plugin_1.AdminUiPlugin.init({
|
|
178
|
-
route: 'admin',
|
|
179
|
-
port: 5001,
|
|
180
|
-
adminUiConfig: {},
|
|
181
|
-
// Un-comment to compile a custom admin ui
|
|
182
|
-
// app: compileUiExtensions({
|
|
183
|
-
// outputPath: path.join(__dirname, './custom-admin-ui'),
|
|
184
|
-
// extensions: [
|
|
185
|
-
// {
|
|
186
|
-
// id: 'ui-extensions-library',
|
|
187
|
-
// extensionPath: path.join(__dirname, 'example-plugins/ui-extensions-library/ui'),
|
|
188
|
-
// routes: [{ route: 'ui-library', filePath: 'routes.ts' }],
|
|
189
|
-
// providers: ['providers.ts'],
|
|
190
|
-
// },
|
|
191
|
-
// {
|
|
192
|
-
// globalStyles: path.join(
|
|
193
|
-
// __dirname,
|
|
194
|
-
// 'test-plugins/with-ui-extension/ui/custom-theme.scss',
|
|
195
|
-
// ),
|
|
196
|
-
// },
|
|
197
|
-
// ],
|
|
198
|
-
// devMode: true,
|
|
199
|
-
// }),
|
|
200
|
-
}),
|
|
201
|
-
plugin_1.DashboardPlugin.init({
|
|
202
|
-
route: 'dashboard',
|
|
203
|
-
appDir: dashboardAppDir,
|
|
204
|
-
}),
|
|
205
|
-
],
|
|
206
|
-
};
|
|
207
|
-
function getDbConfig() {
|
|
208
|
-
const dbType = process.env.DB || 'mysql';
|
|
209
|
-
switch (dbType) {
|
|
210
|
-
case 'postgres':
|
|
211
|
-
console.log('Using postgres connection');
|
|
212
|
-
return {
|
|
213
|
-
synchronize: true,
|
|
214
|
-
type: 'postgres',
|
|
215
|
-
host: process.env.DB_HOST || 'localhost',
|
|
216
|
-
port: Number(process.env.DB_PORT) || 5432,
|
|
217
|
-
username: process.env.DB_USERNAME || 'vendure',
|
|
218
|
-
password: process.env.DB_PASSWORD || 'password',
|
|
219
|
-
database: process.env.DB_NAME || 'vendure-dev',
|
|
220
|
-
schema: process.env.DB_SCHEMA || 'public',
|
|
221
|
-
};
|
|
222
|
-
case 'sqlite':
|
|
223
|
-
console.log('Using sqlite connection');
|
|
224
|
-
return {
|
|
225
|
-
synchronize: true,
|
|
226
|
-
type: 'better-sqlite3',
|
|
227
|
-
database: path_1.default.join(__dirname, 'vendure.sqlite'),
|
|
228
|
-
};
|
|
229
|
-
case 'sqljs':
|
|
230
|
-
console.log('Using sql.js connection');
|
|
231
|
-
return {
|
|
232
|
-
type: 'sqljs',
|
|
233
|
-
autoSave: true,
|
|
234
|
-
database: new Uint8Array([]),
|
|
235
|
-
location: path_1.default.join(__dirname, 'vendure.sqlite'),
|
|
236
|
-
};
|
|
237
|
-
case 'mysql':
|
|
238
|
-
case 'mariadb':
|
|
239
|
-
default:
|
|
240
|
-
console.log('Using mysql connection');
|
|
241
|
-
return {
|
|
242
|
-
synchronize: true,
|
|
243
|
-
type: 'mariadb',
|
|
244
|
-
host: '127.0.0.1',
|
|
245
|
-
port: 3306,
|
|
246
|
-
username: 'vendure',
|
|
247
|
-
password: 'password',
|
|
248
|
-
database: 'vendure-dev',
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
-
};
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.NavModifierPlugin = void 0;
|
|
10
|
-
const core_1 = require("@vendure/core");
|
|
11
|
-
/**
|
|
12
|
-
* A minimal test plugin that demonstrates the function form of `navSections`
|
|
13
|
-
* in `defineDashboardExtension`. It moves the "Administrators" and "Roles"
|
|
14
|
-
* items out of the "Settings" section into a new "Access & Identity" section.
|
|
15
|
-
*/
|
|
16
|
-
let NavModifierPlugin = class NavModifierPlugin {
|
|
17
|
-
};
|
|
18
|
-
exports.NavModifierPlugin = NavModifierPlugin;
|
|
19
|
-
exports.NavModifierPlugin = NavModifierPlugin = __decorate([
|
|
20
|
-
(0, core_1.VendurePlugin)({
|
|
21
|
-
dashboard: './dashboard/index.tsx',
|
|
22
|
-
})
|
|
23
|
-
], NavModifierPlugin);
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.shopApiExtensions = exports.adminApiExtensions = exports.commonApiExtensions = void 0;
|
|
4
|
-
const graphql_tag_1 = require("graphql-tag");
|
|
5
|
-
exports.commonApiExtensions = (0, graphql_tag_1.gql) `
|
|
6
|
-
type ProductReviewTranslation {
|
|
7
|
-
id: ID!
|
|
8
|
-
languageCode: LanguageCode!
|
|
9
|
-
text: String!
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
type ProductReview implements Node {
|
|
13
|
-
id: ID!
|
|
14
|
-
createdAt: DateTime!
|
|
15
|
-
updatedAt: DateTime!
|
|
16
|
-
product: Product!
|
|
17
|
-
productVariant: ProductVariant
|
|
18
|
-
summary: String!
|
|
19
|
-
body: String
|
|
20
|
-
rating: Float!
|
|
21
|
-
authorName: String!
|
|
22
|
-
authorLocation: String
|
|
23
|
-
upvotes: Int!
|
|
24
|
-
downvotes: Int!
|
|
25
|
-
state: String!
|
|
26
|
-
response: String
|
|
27
|
-
responseCreatedAt: DateTime
|
|
28
|
-
translations: [ProductReviewTranslation!]!
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
type ProductReviewList implements PaginatedList {
|
|
32
|
-
items: [ProductReview!]!
|
|
33
|
-
totalItems: Int!
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
type ProductReviewHistogramItem {
|
|
37
|
-
bin: Int!
|
|
38
|
-
frequency: Int!
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
extend type Product {
|
|
42
|
-
reviews(options: ProductReviewListOptions): ProductReviewList!
|
|
43
|
-
reviewsHistogram: [ProductReviewHistogramItem!]!
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
# Auto-generated at runtime
|
|
47
|
-
input ProductReviewListOptions
|
|
48
|
-
`;
|
|
49
|
-
exports.adminApiExtensions = (0, graphql_tag_1.gql) `
|
|
50
|
-
${exports.commonApiExtensions}
|
|
51
|
-
|
|
52
|
-
input ProductReviewTranslationInput {
|
|
53
|
-
languageCode: LanguageCode!
|
|
54
|
-
text: String!
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
input UpdateProductReviewInput {
|
|
58
|
-
id: ID!
|
|
59
|
-
summary: String
|
|
60
|
-
body: String
|
|
61
|
-
response: String
|
|
62
|
-
state: String
|
|
63
|
-
translations: [ProductReviewTranslationInput!]!
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
extend type ProductReview {
|
|
67
|
-
author: Customer
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
extend type Query {
|
|
71
|
-
productReviews(options: ProductReviewListOptions): ProductReviewList!
|
|
72
|
-
productReview(id: ID!): ProductReview
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
extend type Mutation {
|
|
76
|
-
updateProductReview(input: UpdateProductReviewInput!): ProductReview!
|
|
77
|
-
approveProductReview(id: ID!): ProductReview
|
|
78
|
-
rejectProductReview(id: ID!): ProductReview
|
|
79
|
-
}
|
|
80
|
-
`;
|
|
81
|
-
exports.shopApiExtensions = (0, graphql_tag_1.gql) `
|
|
82
|
-
${exports.commonApiExtensions}
|
|
83
|
-
|
|
84
|
-
input SubmitProductReviewInput {
|
|
85
|
-
productId: ID!
|
|
86
|
-
variantId: ID
|
|
87
|
-
customerId: ID
|
|
88
|
-
summary: String!
|
|
89
|
-
body: String!
|
|
90
|
-
rating: Float!
|
|
91
|
-
authorName: String!
|
|
92
|
-
authorLocation: String
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
extend type Mutation {
|
|
96
|
-
submitProductReview(input: SubmitProductReviewInput!): ProductReview!
|
|
97
|
-
voteOnReview(id: ID!, vote: Boolean!): ProductReview!
|
|
98
|
-
}
|
|
99
|
-
`;
|