diff --git a/.env.example b/.env.example index c52e5d9cd2..0bfb16700d 100644 --- a/.env.example +++ b/.env.example @@ -5,11 +5,16 @@ # Copy this file to .env and fill in the values. # # Note: the `.env` file is ignored by git. -# Contact Filiph Siitam Sandström if you need help. # ==================================================================================== +# DEVOPS. ============================================================================ +ADMIN_DOMAIN= +LANDING_DOMAIN= + # Database. ========================================================================== MONGODB_URI= +MONGODB_DATA_API_URI= +MONGODB_DATA_API_TOKEN= # Authentication. ==================================================================== AUTH_SECRET= diff --git a/.eslintignore b/.eslintignore index 68cf6f7a8f..ad0f8f0913 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,6 +3,7 @@ node_modules/ build/ coverage/ dist/ +**/dist/ .next/ .now/ storybook-static/ @@ -20,7 +21,8 @@ vitest.setup.ts next.config.* -tailwind.config.cjs -tailwind.config.js -postcss.config.cjs -postcss.config.js +tailwind.config.* +postcss.config.* +vite.config.* +vitest.config.* +vitest.setup.* diff --git a/.github/common/bootstrap/action.yml b/.github/common/bootstrap/action.yml index d6cff2a198..f4bf35b1de 100644 --- a/.github/common/bootstrap/action.yml +++ b/.github/common/bootstrap/action.yml @@ -1,17 +1,19 @@ -name: '📦 Bootstrap' -description: 'Install and configure dependencies' +name: "📦 Bootstrap" +description: "Install and configure dependencies" runs: - using: 'composite' + using: "composite" steps: + - name: 🏎️ Setup pnpm + uses: pnpm/action-setup@v4 + - name: 🏎️ Setup Node uses: actions/setup-node@v4 with: - registry-url: 'https://registry.npmjs.org/' - node-version-file: '.nvmrc' + registry-url: "https://registry.npmjs.org/" + node-version-file: ".nvmrc" + cache: "pnpm" - - name: 🏎️ Setup pnpm - uses: pnpm/action-setup@v3 - with: - version: 9 - run_install: true + - name: 📦 Install dependencies + shell: bash + run: pnpm install --frozen-lockfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad8b2c29a9..ec0527f4b1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,9 +21,6 @@ env: SHOPIFY_API_KEY: ${{ secrets.SHOPIFY_API_KEY }} SHOPIFY_API_SECRET_KEY: ${{ secrets.SHOPIFY_API_SECRET_KEY }} AUTH_SECRET: 'development-secret' - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_ORG: ${{ vars.SENTRY_ORG }} - SENTRY_PROJECT: ${{ vars.SENTRY_PROJECT }} MONGODB_DATA_API_TOKEN: ${{ secrets.MONGODB_DATA_API_TOKEN }} MONGODB_DATA_API_URI: ${{ secrets.MONGODB_DATA_API_URI }} EDGE_CONFIG: ${{ secrets.EDGE_CONFIG }} @@ -64,11 +61,11 @@ jobs: - name: 🦺 Report Coverage to GitHub if: ${{ !cancelled() }} - uses: davelosert/vitest-coverage-report-action@v2.7.0 + uses: davelosert/vitest-coverage-report-action@v2.8.1 - name: 🦺 Codecov Coverage Reports if: ${{ !cancelled() }} - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml.disabled similarity index 94% rename from .github/workflows/deploy.yml rename to .github/workflows/deploy.yml.disabled index feec4bfa90..b15573ff8b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml.disabled @@ -17,9 +17,6 @@ env: SHOPIFY_API_KEY: ${{ secrets.SHOPIFY_API_KEY }} SHOPIFY_API_SECRET_KEY: ${{ secrets.SHOPIFY_API_SECRET_KEY }} AUTH_SECRET: 'development-secret' - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_ORG: ${{ vars.SENTRY_ORG }} - SENTRY_PROJECT: ${{ vars.SENTRY_PROJECT }} MONGODB_DATA_API_TOKEN: ${{ secrets.MONGODB_DATA_API_TOKEN }} MONGODB_DATA_API_URI: ${{ secrets.MONGODB_DATA_API_URI }} diff --git a/.vscode/settings.json b/.vscode/settings.json index 72753d78be..054c6ea51b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -41,7 +41,6 @@ "**/.DS_Store": true, "**/.git": true, "**/.hg": true, - "**/.next": true, "**/.svn": true, "**/*.tsbuildinfo": true, "**/CVS": true, @@ -102,6 +101,7 @@ "nums", "overscroll", "pagetype", + "pkce", "predev", "Preloadable", "prismic", @@ -174,7 +174,6 @@ "editor.defaultFormatter": "esbenp.prettier-vscode" }, "prettier.prettierPath": "./node_modules/prettier", - "tailwindCSS.classAttributes": ["class", "className", ".*ClassName", ".*Styles"], "tailwindCSS.lint.invalidVariant": "warning", "tailwindCSS.colorDecorators": true, diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..f9e505f8bd --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +BSD 2-Clause License + +Copyright (c) 2022-2025, Filiph Sandström + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index 88bcf251a3..3203f7859e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ -# Nordcom Commerce +# Headless Commerce -[![Unit & Integration Testing](https://github.com/NordcomInc/sweetsideofsweden-frontend/actions/workflows/ci.yml/badge.svg)](https://github.com/NordcomInc/sweetsideofsweden-frontend/actions/workflows/ci.yml) -[![codecov](https://codecov.io/gh/NordcomInc/sweetsideofsweden-frontend/graph/badge.svg?token=L6I8T166LD)](https://codecov.io/gh/NordcomInc/sweetsideofsweden-frontend) -[![wakatime](https://wakatime.com/badge/github/NordcomInc/sweetsideofsweden-frontend.svg)](https://wakatime.com/badge/github/NordcomInc/sweetsideofsweden-frontend) +[![Unit & Integration Testing](https://github.com/filiphsps/commerce/actions/workflows/ci.yml/badge.svg)](https://github.com/filiphsps/commerce/actions/workflows/ci.yml) +[![codecov](https://codecov.io/gh/filiphsps/commerce/graph/badge.svg?token=IOzAGHRDnf)](https://codecov.io/gh/filiphsps/commerce) -Multi-tenenant headless e-commerce solution as a service. +Multi-tenant headless e-commerce solution as a service. Currently supports Shopify. ## Quick-Start @@ -18,15 +17,3 @@ Multi-tenenant headless e-commerce solution as a service. - In-depth testing support. - Built with `TypeScript`. - Always targeting `node` **LTS**. - -### Maintainers - -- 2019-2024: Filiph Siitam Sandström - [@filiphsps](https://github.com/filiphsps). -- 2023-2024: Nordcom Group Inc. - [@NordcomInc](https://github.com/NordcomInc). -- 2024: Nordcom AB - [@NordcomInc](https://github.com/NordcomInc). - -### Legal - -- © 2019-2024 Filiph Siitam Sandström. -- © 2023 Nordcom Group Inc. -- © 2024 Nordcom AB. diff --git a/apps/admin/next-env.d.ts b/apps/admin/next-env.d.ts index 40c3d68096..1b3be0840f 100644 --- a/apps/admin/next-env.d.ts +++ b/apps/admin/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/apps/admin/next.config.js b/apps/admin/next.config.js index 74c71a7b70..cbc47fdc3c 100644 --- a/apps/admin/next.config.js +++ b/apps/admin/next.config.js @@ -34,11 +34,11 @@ const config = { trailingSlash: true, transpilePackages: [], assetPrefix: getBaseUrl(), + turbopack: { root: path.resolve('../..') }, experimental: { - after: true, appNavFailHandling: true, caseSensitiveRoutes: true, - cssChunking: 'loose', + cssChunking: true, esmExternals: true, middlewarePrefetch: 'flexible', optimizeCss: true, @@ -53,10 +53,8 @@ const config = { serverSourceMaps: true, staleTimes: { dynamic: 0, static: 180 }, taint: true, - turbo: { root: path.resolve('../..') }, - typedEnv: true, - typedRoutes: true, - useEarlyImport: true, + typedEnv: false, + typedRoutes: false, useWasmBinary: false, webpackBuildWorker: true }, @@ -126,16 +124,6 @@ const config = { topLevelAwait: true }; - config.plugins.push( - new webpack.DefinePlugin({ - __SENTRY_DEBUG__: false, - __SENTRY_TRACING__: false, - __RRWEB_EXCLUDE_IFRAME__: true, - __RRWEB_EXCLUDE_SHADOW_DOM__: true, - __SENTRY_EXCLUDE_REPLAY_WORKER__: true - }) - ); - if (isServer) { config.devtool = 'source-map'; } diff --git a/apps/admin/package.json b/apps/admin/package.json index 9fd838936e..0bfd91c1d7 100644 --- a/apps/admin/package.json +++ b/apps/admin/package.json @@ -27,7 +27,7 @@ "contributors": [ { "name": "Filiph Siitam Sandström", - "email": "filiph@nordcom.io", + "email": "filfat@hotmail.se", "url": "https://github.com/filiphsps/" } ], @@ -44,73 +44,74 @@ }, "homepage": "https://shops.nordcom.io/", "dependencies": { - "@apollo/client": "3.11.8", - "@apollo/experimental-nextjs-app-support": "0.11.5", - "@auth/core": "0.37.3", + "@apollo/client": "3.13.8", + "@apollo/experimental-nextjs-app-support": "0.12.1", + "@auth/core": "0.38.0", "@next/third-parties": "15.0.2-canary.10", "@nordcom/commerce-db": "workspace:*", "@nordcom/commerce-errors": "workspace:*", "@nordcom/commerce-marketing-common": "workspace:*", - "@nordcom/nordstar": "0.0.71", - "@opentelemetry/api-logs": "0.54.2", - "@opentelemetry/instrumentation": "0.54.2", - "@opentelemetry/sdk-logs": "0.54.2", - "@radix-ui/react-avatar": "1.1.1", - "@radix-ui/react-scroll-area": "1.2.0", - "@radix-ui/react-separator": "1.1.0", - "@radix-ui/react-slot": "1.1.0", - "@shopify/hydrogen-react": "2024.7.6", - "@shopify/shopify-api": "11.6.0", - "@vercel/analytics": "1.3.2", - "@vercel/otel": "1.10.0", - "@vercel/speed-insights": "1.1.0", - "@vercel/toolbar": "0.1.22", - "class-variance-authority": "0.7.0", + "@nordcom/nordstar": "0.0.73-unstable-20250703081501", + "@opentelemetry/api-logs": "0.200.0", + "@opentelemetry/instrumentation": "0.200.0", + "@opentelemetry/sdk-logs": "0.200.0", + "@radix-ui/react-avatar": "1.1.4", + "@radix-ui/react-scroll-area": "1.2.4", + "@radix-ui/react-separator": "1.1.3", + "@radix-ui/react-slot": "1.2.0", + "@shopify/hydrogen-react": "2025.1.3", + "@shopify/shopify-api": "11.12.0", + "@vercel/analytics": "1.5.0", + "@vercel/otel": "1.11.0", + "@vercel/speed-insights": "1.2.0", + "@vercel/toolbar": "0.1.36", + "class-variance-authority": "0.7.1", "clsx": "2.1.1", "geist": "1.3.1", - "lucide-react": "0.456.0", - "mongoose": "8.8.0", + "lucide-react": "0.500.0", + "mongoose": "8.13.2", "next-auth": "5.0.0-beta.25", - "next-seo": "6.6.0", + "next-seo": "6.8.0", "next-sitemap": "4.2.3", - "next": "15.0.2-canary.10", - "nextjs-toploader": "3.7.15", + "next": "15.4.0-canary.110", + "nextjs-toploader": "3.8.16", "nprogress": "0.2.0", - "react-dom": "0.0.0-experimental-28668d39-20241023", - "react": "0.0.0-experimental-28668d39-20241023", - "sharp": "0.33.5", - "sonner": "1.7.0", - "tailwind-merge": "2.5.4", + "react-dom": "19.1.0", + "react": "19.1.0", + "sharp": "0.34.2", + "sonner": "2.0.5", + "tailwind-merge": "3.3.1", "tailwindcss-animate": "1.0.7", "use-context-selector": "2.0.0" }, "devDependencies": { - "@happy-dom/global-registrator": "15.8.0", + "@happy-dom/global-registrator": "17.4.0", "@nordcom/prettier": "0.1.1", - "@tailwindcss/forms": "0.5.9", - "@tailwindcss/typography": "0.5.15", + "@tailwindcss/forms": "0.5.10", + "@tailwindcss/postcss": "4.1.4", + "@tailwindcss/typography": "0.5.16", "@testing-library/jest-dom": "6.6.3", - "@testing-library/react": "16.0.1", - "@types/node": "22.8.6", + "@testing-library/react": "16.3.0", + "@types/node": "24.0.10", "@types/nprogress": "0.2.3", - "@types/react-dom": "18.3.0", - "@types/react": "18.3.8", - "autoprefixer": "10.4.20", + "@types/react-dom": "19.1.6", + "@types/react": "19.1.8", + "autoprefixer": "10.4.21", "babel-plugin-react-compiler": "19.0.0-beta-8a03594-20241020", - "concurrently": "9.1.0", + "concurrently": "9.1.2", "critters": "0.0.25", - "dotenv": "16.4.5", - "eslint-config-next": "15.0.2-canary.10", + "dotenv": "17.0.1", + "eslint-config-next": "15.3.4", "eslint": "8.57.1", - "graphql": "16.9.0", - "happy-dom": "15.10.2", + "graphql": "16.10.0", + "happy-dom": "17.4.0", "postcss-import": "16.1.0", - "postcss": "8.4.47", - "prettier": "3.3.3", + "postcss": "8.5.6", + "prettier": "3.5.3", "rimraf": "6.0.1", "server-only": "0.0.1", - "tailwindcss": "3.4.14", - "typescript": "5.6.3", - "vitest": "1.6.0" + "tailwindcss": "4.1.4", + "typescript": "5.8.3", + "vitest": "3.2.4" } } diff --git a/apps/admin/postcss.config.js b/apps/admin/postcss.config.js index 41cd24e855..de948d68b9 100644 --- a/apps/admin/postcss.config.js +++ b/apps/admin/postcss.config.js @@ -1,7 +1,7 @@ export default { plugins: { 'postcss-import': {}, - 'tailwindcss': {}, + '@tailwindcss/postcss': {}, 'autoprefixer': {} } }; diff --git a/apps/admin/src/app/(auth)/auth/layout.tsx b/apps/admin/src/app/(auth)/auth/layout.tsx index ff2c4c611d..e6776a094c 100644 --- a/apps/admin/src/app/(auth)/auth/layout.tsx +++ b/apps/admin/src/app/(auth)/auth/layout.tsx @@ -9,5 +9,5 @@ export const metadata: Metadata = { }; export default async function AuthLayout({ children }: { children: ReactNode }) { - return
{children}
; + return
{children as any}
; } diff --git a/apps/admin/src/app/(auth)/auth/login/page.tsx b/apps/admin/src/app/(auth)/auth/login/page.tsx index f90a87626a..22456d98e1 100644 --- a/apps/admin/src/app/(auth)/auth/login/page.tsx +++ b/apps/admin/src/app/(auth)/auth/login/page.tsx @@ -11,7 +11,7 @@ export const metadata: Metadata = { title: 'Login' }; -export default async function IndexAdminPage({}: { params: IndexAdminPageParams }) { +export default async function IndexAdminPage({}: { params: any }) { const session = await auth(); if (session?.user) { redirect('/'); diff --git a/apps/admin/src/app/(auth)/layout.tsx b/apps/admin/src/app/(auth)/layout.tsx index 27a81a6a94..bb1c0bb54a 100644 --- a/apps/admin/src/app/(auth)/layout.tsx +++ b/apps/admin/src/app/(auth)/layout.tsx @@ -3,5 +3,5 @@ import { View } from '@nordcom/nordstar'; import type { ReactNode } from 'react'; export default async function AuthLayout({ children }: { children: ReactNode }) { - return {children}; + return {children as any}; } diff --git a/apps/admin/src/app/(dashboard)/[domain]/layout.tsx b/apps/admin/src/app/(dashboard)/[domain]/layout.tsx index c732c78199..adbd361848 100644 --- a/apps/admin/src/app/(dashboard)/[domain]/layout.tsx +++ b/apps/admin/src/app/(dashboard)/[domain]/layout.tsx @@ -78,7 +78,7 @@ export default async function ShopLayout({ children, params }: ShopLayoutProps) return (
- +
@@ -140,7 +140,7 @@ export default async function ShopLayout({ children, params }: ShopLayoutProps)
- {children} + {children as any}
diff --git a/apps/admin/src/app/(dashboard)/[domain]/reviews/layout.tsx b/apps/admin/src/app/(dashboard)/[domain]/reviews/layout.tsx index 059b3faa53..96b14638ba 100644 --- a/apps/admin/src/app/(dashboard)/[domain]/reviews/layout.tsx +++ b/apps/admin/src/app/(dashboard)/[domain]/reviews/layout.tsx @@ -10,7 +10,7 @@ export default async function ReviewsLayout({ return ( <>
{modal}
- {children} + {children as any} ); } diff --git a/apps/admin/src/app/(dashboard)/layout.tsx b/apps/admin/src/app/(dashboard)/layout.tsx index 2b49a2e1f6..8d5c88be59 100644 --- a/apps/admin/src/app/(dashboard)/layout.tsx +++ b/apps/admin/src/app/(dashboard)/layout.tsx @@ -6,5 +6,5 @@ import type { ReactNode } from 'react'; export default async function DashboardLayout({ children }: { children: ReactNode }) { const session = await auth(); - return {children}; + return {children as any}; } diff --git a/apps/admin/src/app/(setup)/layout.tsx b/apps/admin/src/app/(setup)/layout.tsx index 397f34383d..bbb654d4a1 100644 --- a/apps/admin/src/app/(setup)/layout.tsx +++ b/apps/admin/src/app/(setup)/layout.tsx @@ -6,5 +6,5 @@ import type { ReactNode } from 'react'; export default async function SetupLayout({ children }: { children: ReactNode }) { const session = await auth(); - return {children}; + return {children as any}; } diff --git a/apps/admin/src/app/globals.css b/apps/admin/src/app/globals.css index df532f925c..73b4712b35 100644 --- a/apps/admin/src/app/globals.css +++ b/apps/admin/src/app/globals.css @@ -37,13 +37,7 @@ } @layer base { - * { - @apply border-border; - } - html { - @apply font-sans; - @apply bg-background text-foreground; font-feature-settings: 'rlig' 1, 'calt' 1; diff --git a/apps/admin/src/app/integrations/shopify/api/shopify.ts b/apps/admin/src/app/integrations/shopify/api/shopify.ts index daf40debec..3970b6bc23 100644 --- a/apps/admin/src/app/integrations/shopify/api/shopify.ts +++ b/apps/admin/src/app/integrations/shopify/api/shopify.ts @@ -5,8 +5,8 @@ import { ApiVersion, shopifyApi } from '@shopify/shopify-api'; export const shopifyAdminApi = shopifyApi({ userAgentPrefix: 'nordcom', - apiKey: process.env.SHOPIFY_API_KEY as string, - apiSecretKey: process.env.SHOPIFY_API_SECRET_KEY as string, + apiKey: (process.env.SHOPIFY_API_KEY as string) || '', + apiSecretKey: (process.env.SHOPIFY_API_SECRET_KEY as string) || '', scopes: [ 'read_products', 'read_orders', @@ -16,7 +16,14 @@ export const shopifyAdminApi = shopifyApi({ 'read_own_subscription_contracts', 'write_own_subscription_contracts' ], - hostName: process.env.NODE_ENV === 'development' ? 'localhost:3000' : 'admin.shops.nordcom.io', + hostName: + process.env.NODE_ENV === 'development' + ? 'localhost:3000' + : (process.env.ADMIN_DOMAIN as string) || 'admin.shops.nordcom.io', isEmbeddedApp: true, - apiVersion: ApiVersion.October23 + apiVersion: ApiVersion.October24, + future: { + customerAddressDefaultFix: true, + lineItemBilling: true + } }); diff --git a/apps/admin/src/app/layout.tsx b/apps/admin/src/app/layout.tsx index 953f3c0ac0..8fecee567b 100644 --- a/apps/admin/src/app/layout.tsx +++ b/apps/admin/src/app/layout.tsx @@ -20,7 +20,7 @@ export const viewport: Viewport = { }; export const metadata: Metadata = { - metadataBase: new URL(`https://admin.shops.nordcom.io/`), + metadataBase: new URL(`https://${(process.env.ADMIN_DOMAIN as string) || 'admin.shops.nordcom.io'}/`), title: { default: 'admin', template: `%s · Nordcom Commerce` @@ -50,7 +50,7 @@ export default async function RootLayout({ children }: { children: ReactNode }) - {children} + {children as any} ); diff --git a/apps/admin/src/app/manifest.ts b/apps/admin/src/app/manifest.ts index e7e2e30c9a..9f7c87eb0c 100644 --- a/apps/admin/src/app/manifest.ts +++ b/apps/admin/src/app/manifest.ts @@ -6,7 +6,7 @@ export default function manifest(): MetadataRoute.Manifest { short_name: 'nordcom', description: 'Nordcom Commerce', display_override: ['standalone', 'fullscreen'], - scope: 'https://admin.shops.nordcom.io/', + scope: `https://${(process.env.ADMIN_DOMAIN as string) || 'admin.shops.nordcom.io'}/`, start_url: '/', display: 'standalone', background_color: '#000000', diff --git a/apps/admin/src/app/page.tsx b/apps/admin/src/app/page.tsx index 2d98dc64fd..aa8317e8a6 100644 --- a/apps/admin/src/app/page.tsx +++ b/apps/admin/src/app/page.tsx @@ -41,12 +41,12 @@ export default async function Overview() { return (
-
+
Nordcom AB's Logo{shopsActions}
-