@vendure-platform/create 1.0.0-major.202610111621.147.1 → 1.0.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/CHANGELOG.md +45 -0
- package/dist/add-to-existing.d.ts +2 -2
- package/dist/add-to-existing.js +1 -1
- package/dist/assets/storefront/package.json +1 -1
- package/dist/assets/storefront/src/app/[locale]/(catalog)/product/[slug]/page.tsx +1 -1
- package/dist/assets/storefront/src/components/commerce/business-unit-switcher.tsx +1 -1
- package/dist/assets/storefront/src/components/commerce/configurator-form.tsx +3 -3
- package/dist/assets/storefront/src/components/commerce/product-image-carousel.tsx +17 -4
- package/dist/assets/storefront/src/components/layout/navbar/navbar-user.tsx +1 -1
- package/dist/assets/storefront/src/lib/vendure/queries.ts +1 -0
- package/dist/assets/templates/README.md.hbs +34 -4
- package/dist/console-onboarding.d.ts +5 -0
- package/dist/console-onboarding.js +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,48 @@
|
|
|
1
|
+
## 1.0.0 (2026-10-12)
|
|
2
|
+
|
|
3
|
+
### ⚠️ Breaking Changes
|
|
4
|
+
|
|
5
|
+
- print the Console plan link and stop starting trials from the terminal ([#622](https://github.com/vendurehq/vendure-platform/pull/622))
|
|
6
|
+
|
|
7
|
+
`@vendure-platform/console-auth` no longer exports
|
|
8
|
+
`startProjectEvaluation`, `evaluationDenial`, `StartedEvaluation`,
|
|
9
|
+
`EVALUATION_OFFER_CODES` and `EvaluationOfferCode`. `ProjectEvaluationState`
|
|
10
|
+
has no `offerCodes`, and `ConsoleOnboardingInteraction` has no
|
|
11
|
+
`chooseEvaluation`.
|
|
12
|
+
|
|
13
|
+
### 🚀 Features
|
|
14
|
+
|
|
15
|
+
- ship a Dockerfile and .dockerignore that keep secrets out of the image ([#754](https://github.com/vendurehq/vendure-platform/pull/754))
|
|
16
|
+
- make the demo data a choice and a development dependency ([#623](https://github.com/vendurehq/vendure-platform/pull/623))
|
|
17
|
+
- scaffold server and worker entrypoints ([#567](https://github.com/vendurehq/vendure-platform/pull/567))
|
|
18
|
+
- scaffold from a named Console Project and give the harness its Console modes ([#529](https://github.com/vendurehq/vendure-platform/pull/529))
|
|
19
|
+
- register the scheduler in scaffolded projects ([#512](https://github.com/vendurehq/vendure-platform/pull/512))
|
|
20
|
+
- interactive Console login instead of a hand-set token ([#511](https://github.com/vendurehq/vendure-platform/pull/511))
|
|
21
|
+
- load project editions from Console ([#508](https://github.com/vendurehq/vendure-platform/pull/508))
|
|
22
|
+
- generate edition facades and install one per project ([#498](https://github.com/vendurehq/vendure-platform/pull/498))
|
|
23
|
+
|
|
24
|
+
### 🩹 Fixes
|
|
25
|
+
|
|
26
|
+
- require stable Core 3.8.0 and drop the remaining 3.8.0 prerelease floors ([#765](https://github.com/vendurehq/vendure-platform/pull/765))
|
|
27
|
+
- follow-ups for add next steps, first migration and first reindex ([#762](https://github.com/vendurehq/vendure-platform/pull/762))
|
|
28
|
+
- name the roles that can issue registry access, fix the failed-link follow-up ([#753](https://github.com/vendurehq/vendure-platform/pull/753))
|
|
29
|
+
- refuse unsupported projects in add and register the CLI plugin ([#752](https://github.com/vendurehq/vendure-platform/pull/752))
|
|
30
|
+
- record the Console Project next to the registry token in .npmrc ([#748](https://github.com/vendurehq/vendure-platform/pull/748))
|
|
31
|
+
- give new projects one copy of the MCP SDK ([#737](https://github.com/vendurehq/vendure-platform/pull/737))
|
|
32
|
+
- exempt Vendure packages from the pnpm release age ([#731](https://github.com/vendurehq/vendure-platform/pull/731))
|
|
33
|
+
- scope a first CLI login to a Customer Account ([#708](https://github.com/vendurehq/vendure-platform/pull/708))
|
|
34
|
+
- stop the spinner in the scaffolder before linking ([85f9f9ab](https://github.com/vendurehq/vendure-platform/commit/85f9f9ab478b21be81b8ed472a5326943b811f47))
|
|
35
|
+
- report linking state accurately ([180e10d9](https://github.com/vendurehq/vendure-platform/commit/180e10d94b9bd94a4e31f945dedbe0ef7e2de544))
|
|
36
|
+
- stop the spinner while linking to Console ([4c29f5fa](https://github.com/vendurehq/vendure-platform/commit/4c29f5fa2eeb11ec10ec59d826979c4c1605c092))
|
|
37
|
+
- support scoped npm and pnpm installs ([#690](https://github.com/vendurehq/vendure-platform/pull/690))
|
|
38
|
+
- report missing env files and deduplicate sharp ([#631](https://github.com/vendurehq/vendure-platform/pull/631))
|
|
39
|
+
- name the session account when --console-project is not in it ([#617](https://github.com/vendurehq/vendure-platform/pull/617))
|
|
40
|
+
- preserve existing-project capability composition ([#517](https://github.com/vendurehq/vendure-platform/pull/517))
|
|
41
|
+
|
|
42
|
+
## 0.6.1 (2026-10-08)
|
|
43
|
+
|
|
44
|
+
Version bump only — no functional changes in @vendure-platform/create.
|
|
45
|
+
|
|
1
46
|
## 0.6.0 (2026-10-06)
|
|
2
47
|
|
|
3
48
|
Version bump only — no functional changes in @vendure-platform/create.
|
|
@@ -78,8 +78,8 @@ interface DetectedProject {
|
|
|
78
78
|
*/
|
|
79
79
|
export declare function detectExistingProject(projectDir: string): Promise<DetectedProject>;
|
|
80
80
|
/**
|
|
81
|
-
* Throw when the project cannot run Vendure Platform: Core older than 3.8
|
|
82
|
-
* (a 3.8 prerelease
|
|
81
|
+
* Throw when the project cannot run Vendure Platform: Core older than 3.8.0
|
|
82
|
+
* (a 3.8.0 prerelease is older) or a database other than PostgreSQL. Call
|
|
83
83
|
* it before anything links the project, issues a token or writes a file.
|
|
84
84
|
* Returns warnings for facts it cannot read.
|
|
85
85
|
*/
|
package/dist/add-to-existing.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=this&&this.__createBinding||(Object.create?function(e,n,t,r){void 0===r&&(r=t);var o=Object.getOwnPropertyDescriptor(n,t);o&&!("get"in o?!n.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return n[t]}}),Object.defineProperty(e,r,o)}:function(e,n,t,r){void 0===r&&(r=t),e[r]=n[t]}),n=this&&this.__setModuleDefault||(Object.create?function(e,n){Object.defineProperty(e,"default",{enumerable:!0,value:n})}:function(e,n){e.default=n}),t=this&&this.__importStar||function(){var t=function(e){return t=Object.getOwnPropertyNames||function(e){var n=[];for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[n.length]=t);return n},t(e)};return function(r){if(r&&r.__esModule)return r;var o={};if(null!=r)for(var i=t(r),s=0;s<i.length;s++)"default"!==i[s]&&e(o,r,i[s]);return n(o,r),o}}();Object.defineProperty(exports,"__esModule",{value:!0}),exports.detectExistingProject=v,exports.assertSupportedProject=k,exports.applyAddToExisting=P,exports.runAddToExistingCli=E,exports.addToExisting=A,exports.formatChecklist=N;const r=t(require("@clack/prompts")),o=require("@vendure-platform/console-auth"),i=require("@vendure-platform/plugin-meta"),s=t(require("fs-extra")),a=require("node:os"),d=t(require("path")),l=require("./console-onboarding"),u=require("./plugin-registry"),c=require("./template-renderer"),p="vendure-platform-installation-guide.md",f="@vendure-platform/cli",h={major:3,minor:8},g=["postgres","mysql","mariadb","better-sqlite3","sqljs","sqlite","mssql","oracle","cockroachdb"];async function v(e){var n,t;const r=d.join(e,"package.json");if(!await s.pathExists(r))throw new Error(`No package.json found at ${r}. Run this from your Vendure project root.`);const o=await s.readJson(r),i={...null!==(n=o.dependencies)&&void 0!==n?n:{},...null!==(t=o.devDependencies)&&void 0!==t?t:{}},a="@vendure/core"in i,l=[d.join(e,"src","vendure-config.ts"),d.join(e,"server","src","vendure-config.ts"),d.join(e,"src","vendure-config.js")];let u=null;for(const e of l)if(await s.pathExists(e)){u=e;break}const c=y(u?await s.readFile(u,"utf8"):""),p=await m(e,i["@vendure/core"]);return{projectDir:e,packageJsonPath:r,vendureConfigPath:u,hasVendureCore:a,coreVersion:p.version,coreVersionIsRangeFloor:p.isRangeFloor,databaseType:w(c),hasDefaultSearchPlugin:c.includes("DefaultSearchPlugin.init"),envPath:d.join(e,".env"),npmrcPath:d.join(e,".npmrc"),gitignorePath:d.join(e,".gitignore")}}async function m(e,n){var t,r;const o=d.join(e,"node_modules","@vendure","core","package.json");if(await s.pathExists(o)){const e=(await s.readJson(o)).version;if("string"==typeof e)return{version:e,isRangeFloor:!1}}return"string"!=typeof n?{version:null,isRangeFloor:!1}:{version:null!==(r=null===(t=n.match(/\d+\.\d+\.\d+(?:-[\w.-]+)?/))||void 0===t?void 0:t[0])&&void 0!==r?r:null,isRangeFloor:!/^[~=v]?\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(n.trim())}}function y(e){return e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/(^|[^:'"`])\/\/.*$/gm,"$1")}function w(e){var n,t;const r=e.match(/dbConnectionOptions\s*:\s*\{/);if(!r||void 0===r.index)return null;let o=0,i=e.length;for(let n=r.index+r[0].length-1;n<e.length;n++)if("{"===e[n])o++;else if("}"===e[n]&&0===--o){i=n;break}const s=new RegExp(`\\btype:\\s*['"\`](${g.join("|")})['"\`]`);return null!==(t=null===(n=e.slice(r.index,i).match(s))||void 0===n?void 0:n[1])&&void 0!==t?t:null}function k(e){var n;const t=[],[r,o]=(null!==(n=e.coreVersion)&&void 0!==n?n:"").split(/[.-]/).map(Number);if(null===e.coreVersion||Number.isNaN(r)||Number.isNaN(o))t.push(`Could not read the @vendure/core version. Vendure Platform needs ${h.major}.${h.minor} or later.`);else if(r<h.major||r===h.major&&o<h.minor){if(e.coreVersionIsRangeFloor)return t.push(`package.json allows @vendure/core ${e.coreVersion} or later, and Vendure Platform needs ${h.major}.${h.minor} or later. Install dependencies and run this command again to check the installed version.`),t.concat(j(e));throw new Error(`This project uses @vendure/core ${e.coreVersion}. Vendure Platform needs ${h.major}.${h.minor} or later, so the install would fail. Nothing was changed. Upgrade @vendure/core to ${h.major}.${h.minor} or later, then run this command again.`)}return t.concat(j(e))}function j(e){if(null===e.databaseType)return["Could not read dbConnectionOptions.type from vendure-config.ts. Vendure Platform needs PostgreSQL."];if("postgres"!==e.databaseType)throw new Error(`This project uses the "${e.databaseType}" database. Vendure Platform needs PostgreSQL, because its entities use column types other databases do not support. Nothing was changed. Move the project to PostgreSQL, then run this command again.`);return[]}async function P(e,n){const{profile:t,dryRun:r,licenseToken:h,consoleOnboarding:g}=n,v=(0,u.resolveProfilePluginKeys)(t).map(e=>(0,u.getPlugin)(e)),m=(0,c.resolvePluginVersionSpec)(),y=[],w=await(0,l.finishConsoleOnboarding)(r?void 0:g,n.projectDir,n.registryToken);w.registryLogin&&y.push(`Log in to the registry: ${w.registryLogin}`);const{token:k,projectId:j}=(0,l.resolveRegistryToken)(n.registryToken,w);w.registryAccessDenied&&!k?y.push("Ask a member with the Credential manager, Project admin or Admin role for a Registry Access Token, then run this command again with --registry-token."):k||w.registryLogin||y.push("Run `vendure console link` to link this project and get a Registry Access Token.");const P=v.map(e=>e.packageName),{added:C,cliPluginRegistered:R}=await b(e.packageJsonPath,m,t,P,r);if(C.length>0){const e=1===C.length?C[0]:`${C.length} packages (${C[0]}, \u2026)`;y.push(`Added ${e} at ${m} to package.json \u2014 run \`npm install\` (or your package manager equivalent).`)}R&&y.push(`Registered ${f} under vendure.cli.plugins in package.json.`),y.push(...await $(e.packageJsonPath,(0,c.resolveMcpSdkVersion)(),r));const{context:E,hbs:A}=(0,c.buildTemplateContext)("","",!1,{profile:t,licenseToken:h,existingProject:!0}),N=(0,c.renderTemplate)((0,c.getTemplatePath)("env.hbs"),E,A),V=await S(e.envPath,N,r);if(V>0&&y.push(`Appended ${V} env var(s) to .env \u2014 fill in real values before booting.`),h&&await D(e.envPath,h,r)&&y.push("Filled in the empty VENDURE_PLATFORM_LICENSE_TOKEN value in .env."),r)y.push("Update .npmrc (registry scope, auth token, pnpm hoist line).");else{const n=!g||Boolean(k)||Boolean(w.registryLogin)||await(0,o.hasRegistryAuthToken)(e.projectDir,w.registryUrl)||await(0,o.hasRegistryAuthToken)((0,a.homedir)(),w.registryUrl);"written"===(await(0,o.ensureRegistryNpmrc)(e.projectDir,{registryUrl:w.registryUrl,scope:w.scope,token:k,projectId:j,routeScope:n})).kind&&y.push("Updated .npmrc."),n||y.push(`Left the ${w.scope} registry line out of .npmrc, because it fails every install without a token. Add it with a Registry Access Token: https://docs.platform.vendure.io/getting-started/registry-access`)}await x(e.gitignorePath,".npmrc",r)&&y.push("Added .npmrc to .gitignore so any future registry token never gets committed.");const O=T(v,t),_=d.join(e.projectDir,p);r||await s.writeFile(_,O),y.push(`Wrote ${d.relative(e.projectDir,_)} \u2014 follow it to wire up your vendure-config.ts.`);const I=d.join(e.vendureConfigPath?d.dirname(e.vendureConfigPath):d.join(e.projectDir,"src"),"platform-edition.ts"),F=await s.pathExists(I);r||F||(await s.ensureDir(d.dirname(I)),await s.writeFile(I,(0,i.renderEditionConfig)(t)));const q=d.relative(e.projectDir,I);return y.push(F?`Kept existing ${q}. Confirm that it exports the ${t} edition.`:`Wrote ${q} for the ${t} edition.`),y.push("Swap `import { bootstrap } from '@vendure/core'` for `'./platform-edition'` in your server entry file (and `bootstrapWorker` if you have a worker). See the installation guide's \"Bootstrap import\" section."),e.hasDefaultSearchPlugin&&y.push('Remove `DefaultSearchPlugin` from vendure-config.ts. Advanced Search replaces it, and the server fails to start with both. See the installation guide\'s "Remove DefaultSearchPlugin" section.'),y.push("Generate and run a migration for the new platform entities."),y.push("Rebuild the dashboard if you serve a pre-built artefact."),y.push("Grant new permissions to existing admin roles via Settings \u2192 Roles."),y}async function b(e,n,t,r,o){var a,d,l,u,c,p;const h=await s.readJson(e);null!==(a=h.dependencies)&&void 0!==a||(h.dependencies={});const g=[(0,i.facadePackageName)(t),...r].filter((e,n,t)=>t.indexOf(e)===n),v=[];for(const e of g)h.dependencies[e]||(h.dependencies[e]=n,v.push(e));null!==(d=h.devDependencies)&&void 0!==d||(h.devDependencies={}),h.dependencies[f]||h.devDependencies[f]||(h.devDependencies[f]=n,v.push(f));const m=null!==(c=null===(u=null===(l=h.vendure)||void 0===l?void 0:l.cli)||void 0===u?void 0:u.plugins)&&void 0!==c?c:[],y=!m.includes(f);return y&&(h.vendure={...h.vendure,cli:{...null===(p=h.vendure)||void 0===p?void 0:p.cli,plugins:[...m,f]}}),(v.length>0||y)&&!o&&await s.writeJson(e,h,{spaces:2}),{added:v,cliPluginRegistered:y}}async function $(e,n,t){var r,o;const i=await s.readJson(e),a=[];let d=!1;const l=null===(r=i.overrides)||void 0===r?void 0:r["@vendure/mcp-sdk"];if(void 0===l?(i.overrides={...i.overrides,"@vendure/mcp-sdk":n},d=!0,a.push(`Added an "overrides" entry for @vendure/mcp-sdk ${n} to package.json, so every package uses one copy of the MCP SDK. With pnpm, put the same entry under "overrides" in pnpm-workspace.yaml instead.`)):"string"!=typeof l||l.startsWith("$")?a.push(`package.json already overrides @vendure/mcp-sdk. Check that it resolves to ${n}, the version the Vendure Platform packages need.`):l!==n&&a.push(`package.json overrides @vendure/mcp-sdk to ${l}, but the Vendure Platform packages need ${n}. Set it to ${n}, or the MCP server lists none of their tools.`),i.overrides["@vendure/mcp-sdk"]===n)for(const e of["dependencies","devDependencies"]){const t=null===(o=i[e])||void 0===o?void 0:o["@vendure/mcp-sdk"];void 0!==t&&t!==n&&(i[e]["@vendure/mcp-sdk"]=n,d=!0,a.push(`Changed @vendure/mcp-sdk in package.json ${e} from ${t} to ${n}, the version of the override. npm refuses an override that differs from a direct dependency.`))}return d&&!t&&await s.writeJson(e,i,{spaces:2}),a}async function D(e,n,t){if(!await s.pathExists(e))return!1;const r=(await s.readFile(e,"utf8")).split("\n");let o=!1;const i="VENDURE_PLATFORM_LICENSE_TOKEN";for(let e=0;e<r.length;e++){const t=r[e].trim();if(!t.startsWith("#")&&t===`${i}=`){r[e]=`${i}=${n}`,o=!0;break}}return o&&!t&&await s.writeFile(e,r.join("\n")),o}async function S(e,n,t){const r=await s.pathExists(e)?await s.readFile(e,"utf8"):"",o=new Set(r.split("\n").map(R).filter(Boolean)),i=[];let a=0;for(const e of n.split(/\n{2,}/)){const n=C(e.split("\n"),o),t=n.filter(e=>R(e)).length;0!==t&&(a+=t,i.push(n.join("\n")))}if(0===a||t)return a;if(""===r.trim())await s.writeFile(e,n);else{const n=r.endsWith("\n")?"":"\n",t=`\n# Added by @vendure-platform/create add\n${i.join("\n\n")}\n`;await s.writeFile(e,r+n+t)}return a}function C(e,n){const t=[];for(const r of e)if(n.has(R(r)))for(;t.length>1&&t[t.length-1].trim().startsWith("#");)t.pop();else t.push(r);return t}function R(e){var n,t;const r=e.trim();return r.startsWith("#")?"":null!==(t=null===(n=r.split("=")[0])||void 0===n?void 0:n.trim())&&void 0!==t?t:""}async function x(e,n,t){let r="";await s.pathExists(e)&&(r=await s.readFile(e,"utf8"));const o=r.split("\n").map(e=>e.trim());if(o.includes(n)||o.includes(`/${n}`))return!1;const i=""===r||r.endsWith("\n")?"":"\n";return t||await s.writeFile(e,r+i+n+"\n"),!0}function T(e,n){const t=(0,i.facadePackageName)(n),r=["import { VendurePlatform } from './platform-edition';"],{context:o,hbs:s}=(0,c.buildTemplateContext)("","",!1,{profile:n});for(const n of e)n.platformImports&&r.push(...n.platformImports);return`# Vendure Platform installation guide\n\nPaste these changes into your existing project. Step 1 is the most important \u2014\nwithout it, every Vendure Platform plugin refuses to start with\n\`LICENSE_GUARD_NONCE_MISMATCH\`.\n\n## 1. Bootstrap import (server entry point)\n\nIn your server entry file (typically \`src/index.ts\` or wherever you call\n\`bootstrap()\`), swap the bootstrap import from \`@vendure/core\` to\n\`./platform-edition\`:\n\n\`\`\`ts\n// before\nimport { bootstrap } from '@vendure/core';\n\n// after\nimport { bootstrap } from './platform-edition';\n\`\`\`\n\nIf you also run a separate worker process, swap \`bootstrapWorker\` too:\n\n\`\`\`ts\nimport { bootstrapWorker } from './platform-edition';\n\`\`\`\n\nThe \`./platform-edition\` bootstrap re-exports the \`${t}\`\ndrop-in wrapper around \`@vendure/core\`'s \`bootstrap\`. It primes the runtime license guard before\nNest builds the DI container. Without this swap, plugins like \`OrgAccountsPlugin\`\nfail at startup with \`LICENSE_GUARD_NONCE_MISMATCH\`.\n\n## 2. Imports in vendure-config.ts\n\nAdd to the top of the file (after your existing imports):\n\n\`\`\`ts\n${r.join("\n")}\n\`\`\`\n\n## 3. Plugins array\n\nSpread \`VendurePlatform.init({...})\` into the \`plugins\` array \u2014 typically\nbetween \`DefaultJobQueuePlugin\` and \`DashboardPlugin\`:\n\n\`\`\`ts\n...VendurePlatform.init({\n${s.compile("{{platformPluginOptions}}")(o)}\n}),\n\`\`\`\n\n## 4. Remove DefaultSearchPlugin\n\nAdvanced Search replaces Vendure's default search. If your config has it, delete \`DefaultSearchPlugin.init({...})\`\nfrom the \`plugins\` array and its import from \`@vendure/core\`. Projects from \`@vendure/create\`\nhave it. With both plugins the server stops at startup with\n\`Field "SearchResult.inStock" can only be defined once\`.\n\n## 5. Order process\n\nIf \`approvalWorkflows\` is selected, VendurePlatform will append\n\`approvalOrderProcess\` to your order process chain and override\n\`arrangingPaymentRequiresContents\` and \`checkAllItemsBeforeCancel\`. If you\nhave custom order process handlers they are preserved; the flags above are\nnot.\n\nSee https://docs.vendure.io/current/platform/getting-started/introduction for the full reference.\n`}async function E(e){var n,t,o,i;const s=process.cwd(),a=await v(s);a.hasVendureCore||r.log.warn("No @vendure/core dependency found in package.json. Continuing anyway \u2014 make sure this is the right directory."),a.vendureConfigPath?r.log.info(`Detected vendure-config.ts at ${d.relative(s,a.vendureConfigPath)}`):r.log.warn("No vendure-config.ts found under src/ or server/src/. The installation guide will still be written to the project root.");for(const e of k(a))r.log.warn(e);a.hasDefaultSearchPlugin&&r.log.warn("vendure-config.ts uses DefaultSearchPlugin. Remove it when you apply the installation guide: Advanced Search replaces it, and the server fails to start with both."),(void 0===e.profile||void 0===e.registryToken)&&r.intro("Add Vendure Platform to existing project");const c=null===(n=e.profile)||void 0===n?void 0:n.trim();let p;if(void 0!==c){if(!(0,u.isCapabilityProfileName)(c))throw new Error(`Unknown edition "${c}". Use starter, growth, scale, or enterprise.`);p=c}const f=void 0!==p||void 0!==e.registryToken||e.dryRun?void 0:await(0,l.startConsoleOnboarding)({projectDir:s,interactive:(0,l.isInteractive)()}),h=null!=p?p:null==f?void 0:f.edition;if(!h){if(void 0!==e.registryToken||e.dryRun)throw new Error("--profile is required when Console onboarding is skipped.");throw new Error("Could not determine the project edition. Link a Console Project with an edition or pass --profile.")}return{projectDir:s,profile:h,dryRun:null!==(t=e.dryRun)&&void 0!==t&&t,registryToken:(null===(o=e.registryToken)||void 0===o?void 0:o.trim())||void 0,licenseToken:(null===(i=e.licenseToken)||void 0===i?void 0:i.trim())||void 0,consoleOnboarding:f}}async function A(e){const n=await v(e.projectDir),t=u.ALWAYS_ACTIVE_KEYS.map(e=>(0,u.getPlugin)(e).displayName);t.length>0&&r.log.info(`Always-on core plugins: ${t.join(", ")}`);const o=N(await P(n,e));r.note(o,e.dryRun?"Dry run \u2014 would do:":"Next steps"),r.outro(e.dryRun?"Dry run complete \u2014 no files written.":"Done.")}function N(e){const n=Math.max(40,Math.min(process.stdout.columns||80,100)-6);return e.map((e,t)=>{const r=`${t+1}. `,o=" ".repeat(r.length);return V(e,n-r.length).map((e,n)=>(0===n?r:o)+e).join("\n")}).join("\n")}function V(e,n){const t=[];let r="";for(const o of e.split(/\s+/))""===r?r=o:r.length+1+o.length<=n?r+=" "+o:(t.push(r),r=o);return""!==r&&t.push(r),t.length>0?t:[""]}
|
|
1
|
+
"use strict";var e=this&&this.__createBinding||(Object.create?function(e,n,t,r){void 0===r&&(r=t);var o=Object.getOwnPropertyDescriptor(n,t);o&&!("get"in o?!n.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return n[t]}}),Object.defineProperty(e,r,o)}:function(e,n,t,r){void 0===r&&(r=t),e[r]=n[t]}),n=this&&this.__setModuleDefault||(Object.create?function(e,n){Object.defineProperty(e,"default",{enumerable:!0,value:n})}:function(e,n){e.default=n}),t=this&&this.__importStar||function(){var t=function(e){return t=Object.getOwnPropertyNames||function(e){var n=[];for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(n[n.length]=t);return n},t(e)};return function(r){if(r&&r.__esModule)return r;var o={};if(null!=r)for(var i=t(r),s=0;s<i.length;s++)"default"!==i[s]&&e(o,r,i[s]);return n(o,r),o}}();Object.defineProperty(exports,"__esModule",{value:!0}),exports.detectExistingProject=m,exports.assertSupportedProject=k,exports.applyAddToExisting=x,exports.runAddToExistingCli=V,exports.addToExisting=I,exports.formatChecklist=N;const r=t(require("@clack/prompts")),o=require("@vendure-platform/console-auth"),i=require("@vendure-platform/plugin-meta"),s=t(require("fs-extra")),a=require("node:os"),d=t(require("path")),l=require("./console-onboarding"),u=require("./plugin-registry"),c=require("./template-renderer"),p="vendure-platform-installation-guide.md",h="@vendure-platform/cli",f="3.8.0",g='After the first boot, reindex search once, or storefront search returns nothing. See "Rebuild the search index" in the installation guide.',v=["postgres","mysql","mariadb","better-sqlite3","sqljs","sqlite","mssql","oracle","cockroachdb"];async function m(e){var n,t;const r=d.join(e,"package.json");if(!await s.pathExists(r))throw new Error(`No package.json found at ${r}. Run this from your Vendure project root.`);const o=await s.readJson(r),i={...null!==(n=o.dependencies)&&void 0!==n?n:{},...null!==(t=o.devDependencies)&&void 0!==t?t:{}},a="@vendure/core"in i,l=[d.join(e,"src","vendure-config.ts"),d.join(e,"server","src","vendure-config.ts"),d.join(e,"src","vendure-config.js")];let u=null;for(const e of l)if(await s.pathExists(e)){u=e;break}const c=w(u?await s.readFile(u,"utf8"):""),p=await y(e,i["@vendure/core"]);return{projectDir:e,packageJsonPath:r,vendureConfigPath:u,hasVendureCore:a,coreVersion:p.version,coreVersionIsRangeFloor:p.isRangeFloor,databaseType:b(c),hasDefaultSearchPlugin:c.includes("DefaultSearchPlugin.init"),envPath:d.join(e,".env"),npmrcPath:d.join(e,".npmrc"),gitignorePath:d.join(e,".gitignore")}}async function y(e,n){var t,r;const o=d.join(e,"node_modules","@vendure","core","package.json");if(await s.pathExists(o)){const e=(await s.readJson(o)).version;if("string"==typeof e)return{version:e,isRangeFloor:!1}}if("string"!=typeof n)return{version:null,isRangeFloor:!1};const i=null!==(r=null===(t=n.match(/\d+\.\d+\.\d+(?:-[\w.-]+)?/))||void 0===t?void 0:t[0])&&void 0!==r?r:null,a=n.trim();return{version:i,isRangeFloor:!(/^[=v]?\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(a)||/^~\d+\.\d+\.\d+$/.test(a))}}function w(e){return e.replace(/\/\*[\s\S]*?\*\//g,"").replace(/(^|[^:'"`])\/\/.*$/gm,"$1")}function b(e){var n,t;const r=e.match(/dbConnectionOptions\s*:\s*\{/);if(!r||void 0===r.index)return null;let o=0,i=e.length;for(let n=r.index+r[0].length-1;n<e.length;n++)if("{"===e[n])o++;else if("}"===e[n]&&0===--o){i=n;break}const s=new RegExp(`\\btype:\\s*['"\`](${v.join("|")})['"\`]`);return null!==(t=null===(n=e.slice(r.index,i).match(s))||void 0===n?void 0:n[1])&&void 0!==t?t:null}function k(e){const n=[],t=null===e.coreVersion?null:P(e.coreVersion);if(null===t)n.push(`Could not read the @vendure/core version. Vendure Platform needs ${f} or later.`);else if(t){if(e.coreVersionIsRangeFloor)return n.push(`package.json allows @vendure/core ${e.coreVersion} or later, and Vendure Platform needs ${f} or later. Install dependencies and run this command again to check the installed version.`),n.concat(j(e));throw new Error(`This project uses @vendure/core ${e.coreVersion}. Vendure Platform needs ${f} or later, so the install would fail. Nothing was changed. Upgrade @vendure/core to ${f} or later, then run this command again.`)}return n.concat(j(e))}function P(e){const n=/^(\d+)\.(\d+)\.(\d+)(-)?/.exec(e);if(!n)return null;const t=f.split(".").map(Number);for(let e=0;e<3;e++){const r=Number(n[e+1]);if(r!==t[e])return r<t[e]}return void 0!==n[4]}function j(e){if(null===e.databaseType)return["Could not read dbConnectionOptions.type from vendure-config.ts. Vendure Platform needs PostgreSQL."];if("postgres"!==e.databaseType)throw new Error(`This project uses the "${e.databaseType}" database. Vendure Platform needs PostgreSQL, because its entities use column types other databases do not support. Nothing was changed. Move the project to PostgreSQL, then run this command again.`);return[]}async function x(e,n){const{profile:t,dryRun:r,licenseToken:f,consoleOnboarding:v}=n,m=(0,u.resolveProfilePluginKeys)(t).map(e=>(0,u.getPlugin)(e)),y=(0,c.resolvePluginVersionSpec)(),w=[],b=await(0,l.finishConsoleOnboarding)(r?void 0:v,n.projectDir,n.registryToken);b.registryLogin&&w.push(`Log in to the registry: ${b.registryLogin}`);const{token:k,projectId:P}=(0,l.resolveRegistryToken)(n.registryToken,b);b.registryAccessDenied&&!k?w.push("Ask a member with the Credential manager, Project admin or Admin role for a Registry Access Token, then run this command again with --registry-token."):k||b.registryLogin||w.push((0,l.registryTokenStep)(n.projectDir));const j=m.map(e=>e.packageName),{added:x,cliPluginRegistered:R}=await S(e.packageJsonPath,y,t,j,r);if(x.length>0){const e=1===x.length?x[0]:`${x.length} packages (${x[0]}, \u2026)`;w.push(`Added ${e} at ${y} to package.json \u2014 run \`npm install\` (or your package manager equivalent).`)}R&&w.push(`Registered ${h} under vendure.cli.plugins in package.json.`),w.push(...await $(e.packageJsonPath,(0,c.resolveMcpSdkVersion)(),r));const{context:T,hbs:V}=(0,c.buildTemplateContext)("","",!1,{profile:t,licenseToken:f,existingProject:!0}),I=(0,c.renderTemplate)((0,c.getTemplatePath)("env.hbs"),T,V),N=await C(e.envPath,I,r);if(N>0&&w.push(`Appended ${N} env var(s) to .env \u2014 fill in real values before booting.`),f&&await D(e.envPath,f,r)&&w.push("Filled in the empty VENDURE_PLATFORM_LICENSE_TOKEN value in .env."),r)w.push("Update .npmrc (registry scope, auth token, pnpm hoist line).");else{const n=!v||Boolean(k)||Boolean(b.registryLogin)||await(0,o.hasRegistryAuthToken)(e.projectDir,b.registryUrl)||await(0,o.hasRegistryAuthToken)((0,a.homedir)(),b.registryUrl);"written"===(await(0,o.ensureRegistryNpmrc)(e.projectDir,{registryUrl:b.registryUrl,scope:b.scope,token:k,projectId:P,routeScope:n})).kind&&w.push("Updated .npmrc."),n||w.push(`Left the ${b.scope} registry line out of .npmrc, because it fails every install without a token. Add it with a Registry Access Token: https://docs.platform.vendure.io/getting-started/registry-access`)}await A(e.gitignorePath,".npmrc",r)&&w.push("Added .npmrc to .gitignore so any future registry token never gets committed.");const O=E(m,t),_=d.join(e.projectDir,p);r||await s.writeFile(_,O),w.push(`Wrote ${d.relative(e.projectDir,_)} \u2014 follow it to wire up your vendure-config.ts.`);const q=d.join(e.vendureConfigPath?d.dirname(e.vendureConfigPath):d.join(e.projectDir,"src"),"platform-edition.ts"),F=await s.pathExists(q);r||F||(await s.ensureDir(d.dirname(q)),await s.writeFile(q,(0,i.renderEditionConfig)(t)));const W=d.relative(e.projectDir,q);return w.push(F?`Kept existing ${W}. Confirm that it exports the ${t} edition.`:`Wrote ${W} for the ${t} edition.`),w.push("Swap `import { bootstrap } from '@vendure/core'` for `'./platform-edition'` in your server entry file (and `bootstrapWorker` if you have a worker). See the installation guide's \"Bootstrap import\" section."),e.hasDefaultSearchPlugin&&w.push('Remove `DefaultSearchPlugin` from vendure-config.ts. Advanced Search replaces it, and the server fails to start with both. See the installation guide\'s "Remove DefaultSearchPlugin" section.'),w.push("Generate and run a migration for the new platform entities."),w.push("Rebuild the dashboard if you serve a pre-built artefact."),w.push("Grant new permissions to existing admin roles via Settings \u2192 Roles."),w.push(g),w}async function S(e,n,t,r,o){var a,d,l,u,c,p;const f=await s.readJson(e);null!==(a=f.dependencies)&&void 0!==a||(f.dependencies={});const g=[(0,i.facadePackageName)(t),...r].filter((e,n,t)=>t.indexOf(e)===n),v=[];for(const e of g)f.dependencies[e]||(f.dependencies[e]=n,v.push(e));null!==(d=f.devDependencies)&&void 0!==d||(f.devDependencies={}),f.dependencies[h]||f.devDependencies[h]||(f.devDependencies[h]=n,v.push(h));const m=null!==(c=null===(u=null===(l=f.vendure)||void 0===l?void 0:l.cli)||void 0===u?void 0:u.plugins)&&void 0!==c?c:[],y=!m.includes(h);return y&&(f.vendure={...f.vendure,cli:{...null===(p=f.vendure)||void 0===p?void 0:p.cli,plugins:[...m,h]}}),(v.length>0||y)&&!o&&await s.writeJson(e,f,{spaces:2}),{added:v,cliPluginRegistered:y}}async function $(e,n,t){var r,o;const i=await s.readJson(e),a=[];let d=!1;const l=null===(r=i.overrides)||void 0===r?void 0:r["@vendure/mcp-sdk"];if(void 0===l?(i.overrides={...i.overrides,"@vendure/mcp-sdk":n},d=!0,a.push(`Added an "overrides" entry for @vendure/mcp-sdk ${n} to package.json, so every package uses one copy of the MCP SDK. With pnpm, put the same entry under "overrides" in pnpm-workspace.yaml instead.`)):"string"!=typeof l||l.startsWith("$")?a.push(`package.json already overrides @vendure/mcp-sdk. Check that it resolves to ${n}, the version the Vendure Platform packages need.`):l!==n&&a.push(`package.json overrides @vendure/mcp-sdk to ${l}, but the Vendure Platform packages need ${n}. Set it to ${n}, or the MCP server lists none of their tools.`),i.overrides["@vendure/mcp-sdk"]===n)for(const e of["dependencies","devDependencies"]){const t=null===(o=i[e])||void 0===o?void 0:o["@vendure/mcp-sdk"];void 0!==t&&t!==n&&(i[e]["@vendure/mcp-sdk"]=n,d=!0,a.push(`Changed @vendure/mcp-sdk in package.json ${e} from ${t} to ${n}, the version of the override. npm refuses an override that differs from a direct dependency.`))}return d&&!t&&await s.writeJson(e,i,{spaces:2}),a}async function D(e,n,t){if(!await s.pathExists(e))return!1;const r=(await s.readFile(e,"utf8")).split("\n");let o=!1;const i="VENDURE_PLATFORM_LICENSE_TOKEN";for(let e=0;e<r.length;e++){const t=r[e].trim();if(!t.startsWith("#")&&t===`${i}=`){r[e]=`${i}=${n}`,o=!0;break}}return o&&!t&&await s.writeFile(e,r.join("\n")),o}async function C(e,n,t){const r=await s.pathExists(e)?await s.readFile(e,"utf8"):"",o=new Set(r.split("\n").map(T).filter(Boolean)),i=[];let a=0;for(const e of n.split(/\n{2,}/)){const n=R(e.split("\n"),o),t=n.filter(e=>T(e)).length;0!==t&&(a+=t,i.push(n.join("\n")))}if(0===a||t)return a;if(""===r.trim())await s.writeFile(e,n);else{const n=r.endsWith("\n")?"":"\n",t=`\n# Added by @vendure-platform/create add\n${i.join("\n\n")}\n`;await s.writeFile(e,r+n+t)}return a}function R(e,n){const t=[];for(const r of e)if(n.has(T(r)))for(;t.length>1&&t[t.length-1].trim().startsWith("#");)t.pop();else t.push(r);return t}function T(e){var n,t;const r=e.trim();return r.startsWith("#")?"":null!==(t=null===(n=r.split("=")[0])||void 0===n?void 0:n.trim())&&void 0!==t?t:""}async function A(e,n,t){let r="";await s.pathExists(e)&&(r=await s.readFile(e,"utf8"));const o=r.split("\n").map(e=>e.trim());if(o.includes(n)||o.includes(`/${n}`))return!1;const i=""===r||r.endsWith("\n")?"":"\n";return t||await s.writeFile(e,r+i+n+"\n"),!0}function E(e,n){const t=(0,i.facadePackageName)(n),r=["import { VendurePlatform } from './platform-edition';"],{context:o,hbs:s}=(0,c.buildTemplateContext)("","",!1,{profile:n});for(const n of e)n.platformImports&&r.push(...n.platformImports);return`# Vendure Platform installation guide\n\nPaste these changes into your existing project. Step 1 is the most important \u2014\nwithout it, every Vendure Platform plugin refuses to start with\n\`LICENSE_GUARD_NONCE_MISMATCH\`.\n\n## 1. Bootstrap import (server entry point)\n\nIn your server entry file (typically \`src/index.ts\` or wherever you call\n\`bootstrap()\`), swap the bootstrap import from \`@vendure/core\` to\n\`./platform-edition\`:\n\n\`\`\`ts\n// before\nimport { bootstrap } from '@vendure/core';\n\n// after\nimport { bootstrap } from './platform-edition';\n\`\`\`\n\nIf you also run a separate worker process, swap \`bootstrapWorker\` too:\n\n\`\`\`ts\nimport { bootstrapWorker } from './platform-edition';\n\`\`\`\n\nThe \`./platform-edition\` bootstrap re-exports the \`${t}\`\ndrop-in wrapper around \`@vendure/core\`'s \`bootstrap\`. It primes the runtime license guard before\nNest builds the DI container. Without this swap, plugins like \`OrgAccountsPlugin\`\nfail at startup with \`LICENSE_GUARD_NONCE_MISMATCH\`.\n\n## 2. Imports in vendure-config.ts\n\nAdd to the top of the file (after your existing imports):\n\n\`\`\`ts\n${r.join("\n")}\n\`\`\`\n\n## 3. Plugins array\n\nSpread \`VendurePlatform.init({...})\` into the \`plugins\` array \u2014 typically\nbetween \`DefaultJobQueuePlugin\` and \`DashboardPlugin\`:\n\n\`\`\`ts\n...VendurePlatform.init({\n${s.compile("{{platformPluginOptions}}")(o)}\n}),\n\`\`\`\n\n## 4. Remove DefaultSearchPlugin\n\nAdvanced Search replaces Vendure's default search. If your config has it, delete \`DefaultSearchPlugin.init({...})\`\nfrom the \`plugins\` array and its import from \`@vendure/core\`. Projects from \`@vendure/create\`\nhave it. With both plugins the server stops at startup with\n\`Field "SearchResult.inStock" can only be defined once\`.\n\n## 5. Order process\n\nIf \`approvalWorkflows\` is selected, VendurePlatform will append\n\`approvalOrderProcess\` to your order process chain and override\n\`arrangingPaymentRequiresContents\` and \`checkAllItemsBeforeCancel\`. If you\nhave custom order process handlers they are preserved; the flags above are\nnot.\n\n## 6. Rebuild the search index\n\nAdvanced Search starts with an empty index and nothing fills it from your existing catalog. Until you rebuild it,\n\`search\` on the Shop API returns \`totalItems: 0\` even though \`products\` lists every product. Do this once per\nenvironment, after the server and a worker are running.\n\nUse a role with the \`UpdateCatalog\` permission. \`Superadmin\` has it. In the Dashboard, open **Search** and use the\n**Reindex** button, or call the Admin API:\n\n\`\`\`graphql\nmutation {\n reindex {\n id\n }\n}\n\`\`\`\n\nThe work runs on the worker, so a project with no running worker never finishes it. Watch the job under\n**System** \u2192 **Job queue**. The time grows with the number of product variants. A sample catalog of a few dozen\nproducts is quick, and a large catalog takes noticeably longer. When the\njob is completed, \`search(input: {}) { totalItems }\` returns your variants. New and changed products reach the\nindex by themselves from then on.\n\nSee https://docs.vendure.io/current/platform/getting-started/introduction for the full reference.\n`}async function V(e){var n,t,o,i;const s=process.cwd(),a=await m(s);a.hasVendureCore||r.log.warn("No @vendure/core dependency found in package.json. Continuing anyway \u2014 make sure this is the right directory."),a.vendureConfigPath?r.log.info(`Detected vendure-config.ts at ${d.relative(s,a.vendureConfigPath)}`):r.log.warn("No vendure-config.ts found under src/ or server/src/. The installation guide will still be written to the project root.");for(const e of k(a))r.log.warn(e);a.hasDefaultSearchPlugin&&r.log.warn("vendure-config.ts uses DefaultSearchPlugin. Remove it when you apply the installation guide: Advanced Search replaces it, and the server fails to start with both."),(void 0===e.profile||void 0===e.registryToken)&&r.intro("Add Vendure Platform to existing project");const c=null===(n=e.profile)||void 0===n?void 0:n.trim();let p;if(void 0!==c){if(!(0,u.isCapabilityProfileName)(c))throw new Error(`Unknown edition "${c}". Use starter, growth, scale, or enterprise.`);p=c}const h=void 0!==p||void 0!==e.registryToken||e.dryRun?void 0:await(0,l.startConsoleOnboarding)({projectDir:s,interactive:(0,l.isInteractive)()}),f=null!=p?p:null==h?void 0:h.edition;if(!f){if(void 0!==e.registryToken||e.dryRun)throw new Error("--profile is required when Console onboarding is skipped.");throw new Error("Could not determine the project edition. Link a Console Project with an edition or pass --profile.")}return{projectDir:s,profile:f,dryRun:null!==(t=e.dryRun)&&void 0!==t&&t,registryToken:(null===(o=e.registryToken)||void 0===o?void 0:o.trim())||void 0,licenseToken:(null===(i=e.licenseToken)||void 0===i?void 0:i.trim())||void 0,consoleOnboarding:h}}async function I(e){const n=await m(e.projectDir),t=u.ALWAYS_ACTIVE_KEYS.map(e=>(0,u.getPlugin)(e).displayName);t.length>0&&r.log.info(`Always-on core plugins: ${t.join(", ")}`);const o=N(await x(n,e));r.note(o,e.dryRun?"Dry run \u2014 would do:":"Next steps"),r.outro(e.dryRun?"Dry run complete \u2014 no files written.":"Done.")}function N(e){const n=Math.max(40,Math.min(process.stdout.columns||80,100)-6);return e.map((e,t)=>{const r=`${t+1}. `,o=" ".repeat(r.length);return O(e,n-r.length).map((e,n)=>(0===n?r:o)+e).join("\n")}).join("\n")}function O(e,n){const t=[];let r="";for(const o of e.split(/\s+/))""===r?r=o:r.length+1+o.length<=n?r+=" "+o:(t.push(r),r=o);return""!==r&&t.push(r),t.length>0?t:[""]}
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@radix-ui/react-toggle": "^1.1.10",
|
|
38
38
|
"@radix-ui/react-toggle-group": "^1.1.11",
|
|
39
39
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
40
|
-
"@vendure-platform/storefront-client": "^1.0.0
|
|
40
|
+
"@vendure-platform/storefront-client": "^1.0.0",
|
|
41
41
|
"class-variance-authority": "^0.7.1",
|
|
42
42
|
"clsx": "^2.1.1",
|
|
43
43
|
"cmdk": "^1.1.1",
|
|
@@ -292,7 +292,7 @@ async function ProductDetailContent({
|
|
|
292
292
|
evaluateAction={evaluateConfiguration}
|
|
293
293
|
addToOrderAction={addConfigurationToOrder}
|
|
294
294
|
>
|
|
295
|
-
<CarouselComponent images={product.assets} />
|
|
295
|
+
<CarouselComponent images={product.assets} fit="contain" />
|
|
296
296
|
{productDescription}
|
|
297
297
|
</ConfiguratorForm>
|
|
298
298
|
{primaryCollection && (
|
|
@@ -19,7 +19,7 @@ export function BusinessUnitSwitcher({ businessUnits, activeBusinessUnitId }: Bu
|
|
|
19
19
|
const [isPending, startTransition] = useTransition();
|
|
20
20
|
const activeBu = businessUnits.find((bu) => bu.id === activeBusinessUnitId);
|
|
21
21
|
|
|
22
|
-
if (businessUnits.length
|
|
22
|
+
if (businessUnits.length === 0) {
|
|
23
23
|
return null;
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -137,7 +137,7 @@ export function ConfiguratorForm({
|
|
|
137
137
|
|
|
138
138
|
const lines = evaluation?.lines ?? [];
|
|
139
139
|
const systemErrors = evaluation?.errors ?? [];
|
|
140
|
-
const totalPrice = lines.reduce((sum, line) => sum + line.productVariant.
|
|
140
|
+
const totalPrice = lines.reduce((sum, line) => sum + line.productVariant.price * line.quantity, 0);
|
|
141
141
|
|
|
142
142
|
// Collect all field-level error/warning messages for the top banner
|
|
143
143
|
const fieldIssues: { fieldName: string; message: string; type: string }[] = [];
|
|
@@ -299,7 +299,7 @@ export function ConfiguratorForm({
|
|
|
299
299
|
</span>
|
|
300
300
|
<span className="text-sm font-mono tabular-nums">
|
|
301
301
|
<Price
|
|
302
|
-
value={line.productVariant.
|
|
302
|
+
value={line.productVariant.price * line.quantity}
|
|
303
303
|
currencyCode={currencyCode}
|
|
304
304
|
/>
|
|
305
305
|
</span>
|
|
@@ -376,7 +376,7 @@ function BomSidebar({
|
|
|
376
376
|
</div>
|
|
377
377
|
<p className="text-sm font-mono tabular-nums text-right mt-0.5">
|
|
378
378
|
<Price
|
|
379
|
-
value={line.productVariant.
|
|
379
|
+
value={line.productVariant.price * line.quantity}
|
|
380
380
|
currencyCode={currencyCode}
|
|
381
381
|
/>
|
|
382
382
|
</p>
|
|
@@ -7,13 +7,26 @@ import { useTranslations } from 'next-intl';
|
|
|
7
7
|
import Image from 'next/image';
|
|
8
8
|
import { useState } from 'react';
|
|
9
9
|
|
|
10
|
+
const FIT_CLASSES = {
|
|
11
|
+
cover: { image: 'object-cover', frame: 'bg-muted' },
|
|
12
|
+
contain: { image: 'object-contain', frame: 'bg-card' },
|
|
13
|
+
} as const;
|
|
14
|
+
|
|
10
15
|
export interface ProductImageCarouselProps {
|
|
11
16
|
images: ProductDetail['assets'];
|
|
12
17
|
selectedIndex?: number;
|
|
13
18
|
onIndexChange?: (index: number) => void;
|
|
19
|
+
/** `contain` shows the whole image on the card background, for tall or wide product shots. Default `cover`. */
|
|
20
|
+
fit?: 'cover' | 'contain';
|
|
14
21
|
}
|
|
15
22
|
|
|
16
|
-
export function ProductImageCarousel({
|
|
23
|
+
export function ProductImageCarousel({
|
|
24
|
+
images,
|
|
25
|
+
selectedIndex,
|
|
26
|
+
onIndexChange,
|
|
27
|
+
fit = 'cover',
|
|
28
|
+
}: ProductImageCarouselProps) {
|
|
29
|
+
const fitClasses = FIT_CLASSES[fit];
|
|
17
30
|
const t = useTranslations('Product');
|
|
18
31
|
const [internalIndex, setInternalIndex] = useState(0);
|
|
19
32
|
const [loadedSources, setLoadedSources] = useState<Set<number>>(new Set());
|
|
@@ -46,13 +59,13 @@ export function ProductImageCarousel({ images, selectedIndex, onIndexChange }: P
|
|
|
46
59
|
return (
|
|
47
60
|
<div className="space-y-4">
|
|
48
61
|
{/* Main Image */}
|
|
49
|
-
<div className=
|
|
62
|
+
<div className={`relative aspect-[4/3] rounded-lg overflow-hidden group ${fitClasses.frame}`}>
|
|
50
63
|
{/* Preview image — always rendered, acts as placeholder */}
|
|
51
64
|
<Image
|
|
52
65
|
src={currentImage.preview}
|
|
53
66
|
alt={t('productImageAlt', { index: currentIndex + 1 })}
|
|
54
67
|
fill
|
|
55
|
-
className=
|
|
68
|
+
className={fitClasses.image}
|
|
56
69
|
sizes="(max-width: 1024px) 100vw, 50vw"
|
|
57
70
|
priority={currentIndex === 0}
|
|
58
71
|
/>
|
|
@@ -61,7 +74,7 @@ export function ProductImageCarousel({ images, selectedIndex, onIndexChange }: P
|
|
|
61
74
|
src={currentImage.source}
|
|
62
75
|
alt={t('productImageAlt', { index: currentIndex + 1 })}
|
|
63
76
|
fill
|
|
64
|
-
className={
|
|
77
|
+
className={`${fitClasses.image} transition-opacity duration-300 ${
|
|
65
78
|
sourceLoaded ? 'opacity-100' : 'opacity-0'
|
|
66
79
|
}`}
|
|
67
80
|
sizes="(max-width: 1024px) 100vw, 50vw"
|
|
@@ -116,7 +116,7 @@ export async function NavbarUser() {
|
|
|
116
116
|
<DropdownMenuSeparator />
|
|
117
117
|
</>
|
|
118
118
|
)}
|
|
119
|
-
{companyAccount && businessUnits.length >
|
|
119
|
+
{companyAccount && businessUnits.length > 0 && (
|
|
120
120
|
<>
|
|
121
121
|
<DropdownMenuLabel className="text-xs text-muted-foreground">
|
|
122
122
|
{t('businessUnit')}
|
|
@@ -59,7 +59,7 @@ for older scaffolds and verification steps.
|
|
|
59
59
|
| `npm run dev` | Start the server, worker, and dashboard through `vendure dev` |
|
|
60
60
|
| `npm run build:dashboard` | Build the admin dashboard for production |
|
|
61
61
|
| `npm run populate` | Seed a linked development database |
|
|
62
|
-
| `npm run migration:generate -- <name>` | Diff the entities against the database and write a migration |
|
|
62
|
+
| `npm run migration:generate -- <name>` | Diff the entities against the database and write a migration. Add `--from-empty` for the first one |
|
|
63
63
|
| `npm run migration:run` | Apply pending migrations in a linked development environment |
|
|
64
64
|
| `npm run migration:run:prod` | Apply compiled migrations with the explicit production credential |
|
|
65
65
|
| `npm run start:server` | Start the compiled server with Node.js |
|
|
@@ -83,7 +83,35 @@ logic as `vendure dev`.
|
|
|
83
83
|
|
|
84
84
|
Get the production Environment Credential from the Installations page in Vendure
|
|
85
85
|
Console. Set it as `VENDURE_PLATFORM_LICENSE_TOKEN` in the deployment secret
|
|
86
|
-
store.
|
|
86
|
+
store.
|
|
87
|
+
|
|
88
|
+
### First migration
|
|
89
|
+
|
|
90
|
+
This project ships no migration. Development creates the schema with
|
|
91
|
+
`synchronize`, and production does not. On an empty database, `migration:run:prod`
|
|
92
|
+
exits with success and creates only the migrations table. The server then stops
|
|
93
|
+
with `Timed out when awaiting the DB schema to be ready!`. Generate the first
|
|
94
|
+
migration once, before the first build and before the first image build.
|
|
95
|
+
`--from-empty` writes the full schema. A plain `migration:generate` writes
|
|
96
|
+
nothing, because your development database already has the tables. Start
|
|
97
|
+
PostgreSQL with `docker compose up -d`, then run this from `server/`:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
{{#if usesBun}}
|
|
101
|
+
bun run migration:generate -- initial --from-empty
|
|
102
|
+
{{else if usesPnpm}}
|
|
103
|
+
pnpm run migration:generate -- initial --from-empty
|
|
104
|
+
{{else}}
|
|
105
|
+
npm run migration:generate -- initial --from-empty
|
|
106
|
+
{{/if}}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Review the SQL in `server/src/migrations/` and commit the file. The build and
|
|
110
|
+
the image include it. Later entity changes, such as a new plugin or a new custom
|
|
111
|
+
field, need a plain `migration:generate -- <name>` without `--from-empty`.
|
|
112
|
+
|
|
113
|
+
Build before you remove development dependencies. Run these commands from
|
|
114
|
+
`server/`:
|
|
87
115
|
|
|
88
116
|
```bash
|
|
89
117
|
npm run build
|
|
@@ -129,8 +157,10 @@ lockfile.
|
|
|
129
157
|
|
|
130
158
|
The image holds no credential. Set `VENDURE_PLATFORM_LICENSE_TOKEN` to the
|
|
131
159
|
production Environment Credential, and the `DB_*` variables, when you start the
|
|
132
|
-
container.
|
|
133
|
-
the
|
|
160
|
+
container. Generate the [first migration](#first-migration) before you build the
|
|
161
|
+
image, or the migrate step creates no schema on a new database. Run the
|
|
162
|
+
migrations as a separate step from the same image, and run the worker as a
|
|
163
|
+
second container:
|
|
134
164
|
|
|
135
165
|
```bash
|
|
136
166
|
docker run --rm --env-file production.env {{projectName}} node dist/migrate.js run
|
|
@@ -99,3 +99,8 @@ export declare function isInteractive(): boolean;
|
|
|
99
99
|
export declare function finishConsoleOnboarding(onboarding: ConsoleOnboarding | undefined, linkRoot: string,
|
|
100
100
|
/** A token the person passed with `--registry-token`. It makes the denial moot. */
|
|
101
101
|
suppliedRegistryToken?: string): Promise<ConsoleOnboardingResult>;
|
|
102
|
+
/**
|
|
103
|
+
* The next step for a project that has no Registry Access Token. It follows
|
|
104
|
+
* the same installed-CLI check as the warning after a failed link.
|
|
105
|
+
*/
|
|
106
|
+
export declare function registryTokenStep(linkRoot: string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=this&&this.__createBinding||(Object.create?function(e,n,o,t){void 0===t&&(t=o);var r=Object.getOwnPropertyDescriptor(n,o);r&&!("get"in r?!n.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return n[o]}}),Object.defineProperty(e,t,r)}:function(e,n,o,t){void 0===t&&(t=o),e[t]=n[o]}),n=this&&this.__setModuleDefault||(Object.create?function(e,n){Object.defineProperty(e,"default",{enumerable:!0,value:n})}:function(e,n){e.default=n}),o=this&&this.__importStar||function(){var o=function(e){return o=Object.getOwnPropertyNames||function(e){var n=[];for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&(n[n.length]=o);return n},o(e)};return function(t){if(t&&t.__esModule)return t;var r={};if(null!=t)for(var i=o(t),s=0;s<i.length;s++)"default"!==i[s]&&e(r,t,i[s]);return n(r,t),r}}();Object.defineProperty(exports,"__esModule",{value:!0}),exports.resolveRegistryToken=u,exports.startConsoleOnboarding=d,exports.isInteractive=g,exports.finishConsoleOnboarding=f;const t=o(require("@clack/prompts")),r=require("@vendure-platform/console-auth"),i=require("node:fs"),s=require("node:path"),c=require("./plugin-registry"),a=require("./registry");class ProjectHasNoPlan extends Error{constructor(){super(...arguments),this.name="ProjectHasNoPlan"}}const l="Continuing without a Vendure Console Project.";function u(e,n){return e?{token:e,projectId:void 0}:{token:n.registryToken,projectId:n.registryProjectId}}async function d(e){const n=Boolean(e.projectId)&&!e.interactive;let o;try{o=(0,r.resolveConsoleOrigins)(process.env)}catch(e){if(n)throw e;return void t.log.warn(`${
|
|
1
|
+
"use strict";var e=this&&this.__createBinding||(Object.create?function(e,n,o,t){void 0===t&&(t=o);var r=Object.getOwnPropertyDescriptor(n,o);r&&!("get"in r?!n.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return n[o]}}),Object.defineProperty(e,t,r)}:function(e,n,o,t){void 0===t&&(t=o),e[t]=n[o]}),n=this&&this.__setModuleDefault||(Object.create?function(e,n){Object.defineProperty(e,"default",{enumerable:!0,value:n})}:function(e,n){e.default=n}),o=this&&this.__importStar||function(){var o=function(e){return o=Object.getOwnPropertyNames||function(e){var n=[];for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&(n[n.length]=o);return n},o(e)};return function(t){if(t&&t.__esModule)return t;var r={};if(null!=t)for(var i=o(t),s=0;s<i.length;s++)"default"!==i[s]&&e(r,t,i[s]);return n(r,t),r}}();Object.defineProperty(exports,"__esModule",{value:!0}),exports.resolveRegistryToken=u,exports.startConsoleOnboarding=d,exports.isInteractive=g,exports.finishConsoleOnboarding=f,exports.registryTokenStep=j;const t=o(require("@clack/prompts")),r=require("@vendure-platform/console-auth"),i=require("node:fs"),s=require("node:path"),c=require("./plugin-registry"),a=require("./registry");class ProjectHasNoPlan extends Error{constructor(){super(...arguments),this.name="ProjectHasNoPlan"}}const l="Continuing without a Vendure Console Project.";function u(e,n){return e?{token:e,projectId:void 0}:{token:n.registryToken,projectId:n.registryProjectId}}async function d(e){const n=Boolean(e.projectId)&&!e.interactive;let o;try{o=(0,r.resolveConsoleOrigins)(process.env)}catch(e){if(n)throw e;return void t.log.warn(`${O(e)} Continuing without Vendure Console.`)}const i=await k(o,e.interactive,n);if(!i)return;let s=i;const a=new r.ConsoleApi({apiOrigin:o.apiOrigin,getAccessToken:()=>s,refreshAccessToken:async()=>{s=await(0,r.refreshStoredConsoleToken)({...o,failedAccessToken:s})}});let u;for(;!u;)try{u=await(0,r.selectConsoleProject)({api:a,interaction:P(e.projectId),origins:o,projectRoot:e.projectDir})}catch(i){if(i instanceof r.ConsoleOnboardingCancelled)throw i;if(i instanceof r.ConsoleApiError&&"auth.organization_missing"===i.code)throw new r.ConsoleCustomerAccountRequired(`Your Vendure Console login is not scoped to a Customer Account. Run "${(0,r.consoleLoginCommand)(o.apiOrigin)} --organization <Account identifier>", then run this command again.`);if(!(i instanceof ProjectNotInSessionAccount)){if(n)throw i;return void t.log.warn(`${O(i)} ${l}`)}const c=await $(a,i);if(!e.interactive)throw new Error(c);t.log.warn(c);const u=await t.confirm({message:"Sign in with another Vendure Console account?",initialValue:!0});if(t.isCancel(u))throw new r.ConsoleOnboardingCancelled;if(!u)return void t.log.warn(l);const d=await b(o,e.interactive);if(!d)return;s=d}const{project:d,edition:g}=u,f=(0,r.projectSubscriptionUrl)(o.appOrigin,d.id);if(!g)throw t.note(`Choose a plan: ${f}\nThen retry this command and select ${d.name}.`,"Next steps"),new ProjectHasNoPlan(`The Console Project ${d.name} is kept. No files or Registry Access Token were created.`);return{project:{id:d.id,name:d.name},edition:g&&(0,c.isCapabilityProfileName)(g)?g:void 0,subscriptionUrl:f,finish:async n=>({...await v(a,d,n,o,e.projectDir),subscriptionUrl:f})}}function g(){return Boolean(process.stdin.isTTY&&process.stdout.isTTY)}async function f(e,n,o){if(!e)return(0,a.offlineRegistry)();try{const r=await e.finish(n);return r.registryAccessDenied&&!o&&t.log.warn(`Your Console role cannot issue Registry Access Tokens for ${e.project.name}, so this project cannot install Platform packages yet. Ask a member with the Credential manager, Project admin or Admin role to issue one in Vendure Console. Send them the Project name "${e.project.name}", then pass the token you get with --registry-token.`),r}catch(o){return t.log.warn(`Could not finish linking to Vendure Console. ${O(o)} ${y(n)}`),{...(0,a.offlineRegistry)(),subscriptionUrl:e.subscriptionUrl}}}const p=[3,8],h="https://docs.platform.vendure.io/getting-started/registry-access";function w(e){for(let n=e;;n=(0,s.dirname)(n)){try{const e=JSON.parse((0,i.readFileSync)((0,s.join)(n,"node_modules","@vendure","cli","package.json"),"utf8"));if("string"==typeof e.version)return e.version}catch{}if((0,s.dirname)(n)===n)return}}function C(e){const n=w(e);if(void 0===n)return;const[o,t]=n.split(".").map(e=>Number.parseInt(e,10)),[r,i]=p;return o>r||o===r&&t>=i?void 0:n}function m(e,n){const[o,t]=p;return`@vendure/cli ${n} has no "console link" command. Update it to ${o}.${t} or later and run "npx vendure console link" in ${e}, or create a Registry Access Token for the Project in Vendure Console and add it to ${(0,s.join)(e,".npmrc")} by hand. Steps: ${h}`}function y(e){const n=C(e);return void 0===n?`Run "npx vendure console link" in ${e} to finish.`:m(e,n)}function j(e){const n=C(e);return void 0===n?"Run `vendure console link` to link this project and get a Registry Access Token.":m(e,n)}async function v(e,n,o,i,s){await(0,r.writeProjectLink)({api:e,interaction:P(),projectRoot:o,projectId:n.id,origins:i}),t.log.success(`Linked ${o} to ${n.name}.`);const c=await(0,r.acquireRegistryAccess)({api:e,projectId:n.id,projectRoot:s,interaction:{confirmRotate:async e=>{const n=await t.confirm({message:`Replace the Registry Access Token "${e}"? Whatever installs with the current one stops working.`,initialValue:!1});if(t.isCancel(n))throw new r.ConsoleOnboardingCancelled;return n},report:e=>t.log.info(e),warn:e=>t.log.warn(e)},defaultRegistryUrl:(0,r.registryUrlFor)(i.apiOrigin),defaultScope:a.REGISTRY_SCOPE});if("permission-denied"===c.reason)return{registryUrl:c.registryUrl,scope:c.scope,registryAccessDenied:!0};if("npm-login"===c.fallback){const e=`npm login --auth-type=web --registry=${(0,a.registryLoginUrl)(c.registryUrl)}`,n="rotation-declined"===c.reason?"You kept the existing Registry Access Token. Its secret was not written to this directory.":"The named Registry Access Token is inactive. Replace it in Vendure Console.";return t.log.warn(`${n} Log in to the registry before installing:\n ${e}`),{registryUrl:c.registryUrl,scope:c.scope,registryLogin:e}}return{registryUrl:c.registryUrl,scope:c.scope,registryToken:c.token,registryProjectId:n.id}}async function k(e,n,o){let i;try{i=await(0,r.resolveStoredConsoleToken)(e)}catch(e){if(o)throw e;return void t.log.warn(`${O(e)} Continuing without Vendure Console.`)}if(i)return(0,r.scopeStoredConsoleSession)({...e,accessToken:i,...n?{chooseCustomerAccount:A}:{}});if(!n)return;const s=await t.confirm({message:"Sign in to Vendure Console to set this project up?",initialValue:!0});if(t.isCancel(s))throw new r.ConsoleOnboardingCancelled;return s?b(e,n):void 0}async function b(e,n){const o=t.spinner();o.start("Waiting for you to finish signing in to Vendure Console");let i=!0;const s=e=>{i&&o.stop(e),i=!1};try{const o=await(0,r.loginAndStoreConsoleToken)({...e,onDeviceAuthorization:e=>t.log.info(`Open ${e.verificationUriComplete} and enter code ${e.userCode} to sign in.`),...n?{chooseCustomerAccount:e=>(s("Signed in to Vendure Console."),A(e))}:{}});return s("Signed in to Vendure Console."),o}catch(e){if(e instanceof r.ConsoleCustomerAccountRequired||e instanceof r.ConsoleOnboardingCancelled)throw s("Signed in to Vendure Console."),e;return s("Could not sign in to Vendure Console."),void t.log.warn(`${O(e)} Continuing without it.`)}}const A=async e=>{const n=await t.select({message:"Which Vendure Console Customer Account is this project for?",options:e.map(e=>({label:e.name,value:e.customerAccountId,hint:`Account identifier ${e.customerAccountId}`}))});if(t.isCancel(n))throw new r.ConsoleOnboardingCancelled;const o=e.find(e=>e.customerAccountId===n);if(!o)throw new r.ConsoleOnboardingCancelled;return o};function P(e){return{chooseProject:async n=>{if(e){const o=n.find(n=>n.id===e);if(!o)throw new ProjectNotInSessionAccount(e);return o}const o=await t.select({message:"Which Vendure Console Project is this?",options:[...n.map(e=>({label:e.name,value:e.id,hint:e.edition?`${e.edition} edition`:"no edition yet"})),{label:"Create a new Project",value:""}]});if(t.isCancel(o))throw new r.ConsoleOnboardingCancelled;return n.find(e=>e.id===o)},newProjectName:async()=>{if(e)throw new ProjectNotInSessionAccount(e);const n=await t.text({message:"Name for the new Vendure Console Project:",validate:e=>e.trim()?void 0:"A name is required"});if(t.isCancel(n))throw new r.ConsoleOnboardingCancelled;return n},report:e=>t.log.info(e),warn:e=>t.log.warn(e)}}class ProjectNotInSessionAccount extends Error{constructor(e){super(),this.projectId=e}}async function $(e,n){const o=await(0,r.readViewerAccount)(e).catch(()=>{}),t=`--console-project ${n.projectId}`;return o?`${t} is not a Project of the account "${o.name}" that this session uses.`:`${t} is not one of your Vendure Console Projects.`}function O(e){return e instanceof Error?e.message:String(e)}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vendure-platform/create",
|
|
3
|
-
"version": "1.0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "CLI tool to scaffold a Vendure demo project with Vendure Platform plugins",
|
|
5
5
|
"vendurePlugin": {
|
|
6
6
|
"slug": "create",
|
|
@@ -49,9 +49,9 @@
|
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@clack/prompts": "^0.10.0",
|
|
52
|
-
"@vendure/cli": "3.8.0
|
|
53
|
-
"@vendure-platform/console-auth": "1.0.0
|
|
54
|
-
"@vendure-platform/plugin-meta": "1.0.0
|
|
52
|
+
"@vendure/cli": "3.8.0",
|
|
53
|
+
"@vendure-platform/console-auth": "1.0.0",
|
|
54
|
+
"@vendure-platform/plugin-meta": "1.0.0",
|
|
55
55
|
"commander": "^13.1.0",
|
|
56
56
|
"fs-extra": "^11.3.0",
|
|
57
57
|
"handlebars": "^4.7.8",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@types/fs-extra": "^11.0.4",
|
|
62
|
-
"@vendure/mcp-sdk": "3.8.0
|
|
62
|
+
"@vendure/mcp-sdk": "3.8.0",
|
|
63
63
|
"concurrently": "^9.1.2",
|
|
64
64
|
"vitest": "^3.2.4"
|
|
65
65
|
}
|