@vendure/create 3.5.2-master-202512180239 → 3.5.2
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/assets/.env.hbs +1 -1
- package/assets/monorepo/root-gitignore.template +5 -0
- package/assets/monorepo/root-package.json.hbs +22 -0
- package/assets/monorepo/root-readme.hbs +69 -0
- package/assets/monorepo/storefront-env.hbs +5 -0
- package/assets/tsconfig.dashboard.hbs +21 -0
- package/assets/tsconfig.template.json +1 -0
- package/assets/{vite.config.template.mts → vite.config.hbs} +1 -1
- package/lib/constants.d.ts +13 -1
- package/lib/constants.js +39 -2
- package/lib/constants.js.map +1 -1
- package/lib/create-vendure-app.d.ts +2 -1
- package/lib/create-vendure-app.js +298 -122
- package/lib/create-vendure-app.js.map +1 -1
- package/lib/gather-user-responses.d.ts +3 -3
- package/lib/gather-user-responses.js +39 -8
- package/lib/gather-user-responses.js.map +1 -1
- package/lib/helpers.d.ts +11 -0
- package/lib/helpers.js +74 -4
- package/lib/helpers.js.map +1 -1
- package/lib/types.d.ts +3 -0
- package/package.json +4 -3
- package/assets/tsconfig.dashboard.template.json +0 -21
|
@@ -38,8 +38,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.createVendureApp = createVendureApp;
|
|
40
40
|
const prompts_1 = require("@clack/prompts");
|
|
41
|
+
const shared_constants_1 = require("@vendure/common/lib/shared-constants");
|
|
41
42
|
const commander_1 = require("commander");
|
|
43
|
+
const crypto_1 = require("crypto");
|
|
42
44
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
45
|
+
const handlebars_1 = __importDefault(require("handlebars"));
|
|
43
46
|
const node_child_process_1 = require("node:child_process");
|
|
44
47
|
const promises_1 = require("node:timers/promises");
|
|
45
48
|
const open_1 = __importDefault(require("open"));
|
|
@@ -69,16 +72,18 @@ commander_1.program
|
|
|
69
72
|
.option('--verbose', 'Alias for --log-level verbose', false)
|
|
70
73
|
.option('--use-npm', 'Uses npm rather than as the default package manager. DEPRECATED: Npm is now the default')
|
|
71
74
|
.option('--ci', 'Runs without prompts for use in CI scenarios', false)
|
|
75
|
+
.option('--with-storefront', 'Include Next.js storefront (only used with --ci)', false)
|
|
72
76
|
.parse(process.argv);
|
|
73
77
|
const options = commander_1.program.opts();
|
|
74
|
-
void createVendureApp(projectName, options.useNpm, options.verbose ? 'verbose' : options.logLevel || 'info', options.ci).catch(err => {
|
|
78
|
+
void createVendureApp(projectName, options.useNpm, options.verbose ? 'verbose' : options.logLevel || 'info', options.ci, options.withStorefront).catch(err => {
|
|
75
79
|
(0, logger_1.log)(err);
|
|
76
80
|
process.exit(1);
|
|
77
81
|
});
|
|
78
|
-
async function createVendureApp(name,
|
|
79
|
-
|
|
82
|
+
async function createVendureApp(name, _useNpm, // Deprecated: npm is now the default package manager
|
|
83
|
+
logLevel, isCi = false, withStorefront = false) {
|
|
84
|
+
var _a, _b, _c;
|
|
80
85
|
(0, logger_1.setLogLevel)(logLevel);
|
|
81
|
-
if (!runPreChecks(name
|
|
86
|
+
if (!runPreChecks(name)) {
|
|
82
87
|
return;
|
|
83
88
|
}
|
|
84
89
|
(0, prompts_1.intro)(`Let's create a ${picocolors_1.default.blue(picocolors_1.default.bold('Vendure App'))} ✨ ${picocolors_1.default.dim(`v${packageJson.version}`)}`);
|
|
@@ -98,20 +103,18 @@ async function createVendureApp(name, useNpm, logLevel, isCi = false) {
|
|
|
98
103
|
}));
|
|
99
104
|
(0, helpers_1.checkCancel)(mode);
|
|
100
105
|
const portSpinner = (0, prompts_1.spinner)();
|
|
101
|
-
let port
|
|
102
|
-
|
|
106
|
+
let port;
|
|
107
|
+
let storefrontPort = constants_1.STOREFRONT_PORT;
|
|
103
108
|
portSpinner.start(`Establishing port...`);
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
portSpinner.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
109
|
+
try {
|
|
110
|
+
port = await (0, helpers_1.findAvailablePort)(constants_1.SERVER_PORT, constants_1.PORT_SCAN_RANGE);
|
|
111
|
+
portSpinner.stop(`Using port ${port}`);
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
portSpinner.stop(picocolors_1.default.red('Could not find an available port'));
|
|
115
|
+
(0, prompts_1.outro)(e.message);
|
|
116
|
+
process.exit(1);
|
|
113
117
|
}
|
|
114
|
-
portSpinner.stop(`Using port ${port}`);
|
|
115
118
|
process.env.PORT = port.toString();
|
|
116
119
|
const root = path_1.default.resolve(name);
|
|
117
120
|
const appName = path_1.default.basename(root);
|
|
@@ -120,83 +123,179 @@ async function createVendureApp(name, useNpm, logLevel, isCi = false) {
|
|
|
120
123
|
if (scaffoldExists) {
|
|
121
124
|
(0, logger_1.log)(picocolors_1.default.yellow('It appears that a new Vendure project scaffold already exists. Re-using the existing files...'), { newline: 'after' });
|
|
122
125
|
}
|
|
123
|
-
const { dbType, configSource, envSource, envDtsSource, indexSource, indexWorkerSource, readmeSource, dockerfileSource, dockerComposeSource, populateProducts, } = mode === 'ci'
|
|
124
|
-
? await (0, gather_user_responses_1.getCiConfiguration)(root, packageManager)
|
|
126
|
+
const { dbType, configSource, envSource, envDtsSource, indexSource, indexWorkerSource, readmeSource, dockerfileSource, dockerComposeSource, tsconfigDashboardSource, viteConfigSource, populateProducts, includeStorefront, } = mode === 'ci'
|
|
127
|
+
? await (0, gather_user_responses_1.getCiConfiguration)(root, packageManager, port, withStorefront)
|
|
125
128
|
: mode === 'manual'
|
|
126
|
-
? await (0, gather_user_responses_1.getManualConfiguration)(root, packageManager)
|
|
127
|
-
: await (0, gather_user_responses_1.getQuickStartConfiguration)(root, packageManager);
|
|
129
|
+
? await (0, gather_user_responses_1.getManualConfiguration)(root, packageManager, port)
|
|
130
|
+
: await (0, gather_user_responses_1.getQuickStartConfiguration)(root, packageManager, port);
|
|
131
|
+
// Determine the server root directory (either root or apps/server for monorepo)
|
|
132
|
+
const serverRoot = includeStorefront ? path_1.default.join(root, 'apps', 'server') : root;
|
|
133
|
+
const storefrontRoot = path_1.default.join(root, 'apps', 'storefront');
|
|
134
|
+
// Find an available storefront port if including storefront
|
|
135
|
+
if (includeStorefront) {
|
|
136
|
+
const storefrontPortSpinner = (0, prompts_1.spinner)();
|
|
137
|
+
storefrontPortSpinner.start(`Establishing storefront port...`);
|
|
138
|
+
try {
|
|
139
|
+
// Start scanning from the higher of STOREFRONT_PORT or serverPort + 1
|
|
140
|
+
// to avoid conflicts with the server port
|
|
141
|
+
const storefrontStartPort = Math.max(constants_1.STOREFRONT_PORT, port + 1);
|
|
142
|
+
storefrontPort = await (0, helpers_1.findAvailablePort)(storefrontStartPort, constants_1.PORT_SCAN_RANGE);
|
|
143
|
+
storefrontPortSpinner.stop(`Using storefront port ${storefrontPort}`);
|
|
144
|
+
}
|
|
145
|
+
catch (e) {
|
|
146
|
+
storefrontPortSpinner.stop(picocolors_1.default.red('Could not find an available storefront port'));
|
|
147
|
+
(0, prompts_1.outro)(e.message);
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
128
151
|
process.chdir(root);
|
|
129
152
|
if (packageManager !== 'npm' && !(0, helpers_1.checkThatNpmCanReadCwd)()) {
|
|
130
153
|
process.exit(1);
|
|
131
154
|
}
|
|
132
|
-
const packageJsonContents = {
|
|
133
|
-
name: appName,
|
|
134
|
-
version: '0.1.0',
|
|
135
|
-
private: true,
|
|
136
|
-
scripts: {
|
|
137
|
-
'dev:server': 'ts-node ./src/index.ts',
|
|
138
|
-
'dev:worker': 'ts-node ./src/index-worker.ts',
|
|
139
|
-
dev: 'concurrently npm:dev:*',
|
|
140
|
-
build: 'tsc',
|
|
141
|
-
'start:server': 'node ./dist/index.js',
|
|
142
|
-
'start:worker': 'node ./dist/index-worker.js',
|
|
143
|
-
start: 'concurrently npm:start:*',
|
|
144
|
-
},
|
|
145
|
-
};
|
|
146
155
|
const setupSpinner = (0, prompts_1.spinner)();
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
await (
|
|
156
|
+
const projectType = includeStorefront ? 'monorepo' : 'project';
|
|
157
|
+
setupSpinner.start(`Setting up your new Vendure ${projectType} in ${picocolors_1.default.green(root)}\nThis may take a few minutes...`);
|
|
158
|
+
const assetPath = (fileName) => path_1.default.join(__dirname, '../assets', fileName);
|
|
159
|
+
const templatePath = (fileName) => path_1.default.join(__dirname, '../assets/monorepo', fileName);
|
|
160
|
+
if (includeStorefront) {
|
|
161
|
+
// Create monorepo structure
|
|
162
|
+
await fs_extra_1.default.ensureDir(path_1.default.join(root, 'apps'));
|
|
163
|
+
await fs_extra_1.default.ensureDir(serverRoot);
|
|
164
|
+
await fs_extra_1.default.ensureDir(path_1.default.join(serverRoot, 'src'));
|
|
165
|
+
// Generate root package.json from template
|
|
166
|
+
const rootPackageTemplate = await fs_extra_1.default.readFile(templatePath('root-package.json.hbs'), 'utf-8');
|
|
167
|
+
const rootPackageContent = handlebars_1.default.compile(rootPackageTemplate)({ name: appName });
|
|
168
|
+
fs_extra_1.default.writeFileSync(path_1.default.join(root, 'package.json'), rootPackageContent + os_1.default.EOL);
|
|
169
|
+
// Generate root README from template
|
|
170
|
+
const rootReadmeTemplate = await fs_extra_1.default.readFile(templatePath('root-readme.hbs'), 'utf-8');
|
|
171
|
+
const rootReadmeContent = handlebars_1.default.compile(rootReadmeTemplate)({
|
|
172
|
+
name: appName,
|
|
173
|
+
serverPort: port,
|
|
174
|
+
storefrontPort,
|
|
175
|
+
superadminIdentifier: shared_constants_1.SUPER_ADMIN_USER_IDENTIFIER,
|
|
176
|
+
superadminPassword: shared_constants_1.SUPER_ADMIN_USER_PASSWORD,
|
|
177
|
+
});
|
|
178
|
+
fs_extra_1.default.writeFileSync(path_1.default.join(root, 'README.md'), rootReadmeContent);
|
|
179
|
+
// Copy root .gitignore
|
|
180
|
+
await fs_extra_1.default.copyFile(templatePath('root-gitignore.template'), path_1.default.join(root, '.gitignore'));
|
|
181
|
+
// Create server package.json
|
|
182
|
+
const serverPackageJsonContents = {
|
|
183
|
+
name: 'server',
|
|
184
|
+
version: constants_1.DEFAULT_PROJECT_VERSION,
|
|
185
|
+
private: true,
|
|
186
|
+
scripts: getServerPackageScripts(),
|
|
187
|
+
};
|
|
188
|
+
fs_extra_1.default.writeFileSync(path_1.default.join(serverRoot, 'package.json'), JSON.stringify(serverPackageJsonContents, null, 2) + os_1.default.EOL);
|
|
156
189
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
190
|
+
else {
|
|
191
|
+
// Single project structure (original behavior)
|
|
192
|
+
const packageJsonContents = {
|
|
193
|
+
name: appName,
|
|
194
|
+
version: constants_1.DEFAULT_PROJECT_VERSION,
|
|
195
|
+
private: true,
|
|
196
|
+
scripts: getServerPackageScripts(),
|
|
197
|
+
};
|
|
198
|
+
fs_extra_1.default.writeFileSync(path_1.default.join(root, 'package.json'), JSON.stringify(packageJsonContents, null, 2) + os_1.default.EOL);
|
|
199
|
+
fs_extra_1.default.ensureDirSync(path_1.default.join(root, 'src'));
|
|
160
200
|
}
|
|
161
|
-
|
|
162
|
-
if
|
|
163
|
-
|
|
164
|
-
|
|
201
|
+
setupSpinner.stop(`Created ${picocolors_1.default.green('package.json')}`);
|
|
202
|
+
// Download storefront if needed
|
|
203
|
+
if (includeStorefront) {
|
|
204
|
+
const storefrontSpinner = (0, prompts_1.spinner)();
|
|
205
|
+
storefrontSpinner.start(`Downloading Next.js storefront...`);
|
|
165
206
|
try {
|
|
166
|
-
await (0, helpers_1.
|
|
207
|
+
await (0, helpers_1.downloadAndExtractStorefront)(storefrontRoot);
|
|
208
|
+
// Update storefront package.json name and dev script port
|
|
209
|
+
const storefrontPackageJsonPath = path_1.default.join(storefrontRoot, 'package.json');
|
|
210
|
+
const storefrontPackageJson = await fs_extra_1.default.readJson(storefrontPackageJsonPath);
|
|
211
|
+
storefrontPackageJson.name = 'storefront';
|
|
212
|
+
if ((_a = storefrontPackageJson.scripts) === null || _a === void 0 ? void 0 : _a.dev) {
|
|
213
|
+
storefrontPackageJson.scripts.dev = `next dev --port ${storefrontPort}`;
|
|
214
|
+
}
|
|
215
|
+
await fs_extra_1.default.writeJson(storefrontPackageJsonPath, storefrontPackageJson, { spaces: 2 });
|
|
216
|
+
// Generate storefront .env.local from template
|
|
217
|
+
const storefrontEnvTemplate = await fs_extra_1.default.readFile(templatePath('storefront-env.hbs'), 'utf-8');
|
|
218
|
+
const storefrontEnvContent = handlebars_1.default.compile(storefrontEnvTemplate)({
|
|
219
|
+
serverPort: port,
|
|
220
|
+
storefrontPort,
|
|
221
|
+
name: appName,
|
|
222
|
+
revalidationSecret: (0, crypto_1.randomBytes)(32).toString('base64'),
|
|
223
|
+
});
|
|
224
|
+
fs_extra_1.default.writeFileSync(path_1.default.join(storefrontRoot, '.env.local'), storefrontEnvContent);
|
|
225
|
+
storefrontSpinner.stop(`Downloaded Next.js storefront`);
|
|
167
226
|
}
|
|
168
227
|
catch (e) {
|
|
169
|
-
|
|
228
|
+
storefrontSpinner.stop(picocolors_1.default.red(`Failed to download storefront`));
|
|
229
|
+
(0, logger_1.log)(e.message, { level: 'verbose' });
|
|
230
|
+
(0, prompts_1.outro)(picocolors_1.default.red(`Failed to download storefront: ${e.message}`));
|
|
170
231
|
process.exit(1);
|
|
171
232
|
}
|
|
172
|
-
|
|
233
|
+
}
|
|
234
|
+
// Install dependencies
|
|
235
|
+
const { dependencies, devDependencies } = (0, helpers_1.getDependencies)(dbType, `@${packageJson.version}`);
|
|
236
|
+
// Install server dependencies
|
|
237
|
+
await installDependenciesWithSpinner({
|
|
238
|
+
dependencies,
|
|
239
|
+
logLevel,
|
|
240
|
+
cwd: serverRoot,
|
|
241
|
+
spinnerMessage: `Installing ${dependencies[0]} + ${dependencies.length - 1} more dependencies`,
|
|
242
|
+
successMessage: `Successfully installed ${dependencies.length} dependencies`,
|
|
243
|
+
failureMessage: 'Failed to install dependencies. Please try again.',
|
|
244
|
+
});
|
|
245
|
+
if (devDependencies.length) {
|
|
246
|
+
await installDependenciesWithSpinner({
|
|
247
|
+
dependencies: devDependencies,
|
|
248
|
+
isDevDependencies: true,
|
|
249
|
+
logLevel,
|
|
250
|
+
cwd: serverRoot,
|
|
251
|
+
spinnerMessage: `Installing ${devDependencies[0]} + ${devDependencies.length - 1} more dev dependencies`,
|
|
252
|
+
successMessage: `Successfully installed ${devDependencies.length} dev dependencies`,
|
|
253
|
+
failureMessage: 'Failed to install dev dependencies. Please try again.',
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
if (includeStorefront) {
|
|
257
|
+
// Install storefront dependencies
|
|
258
|
+
const storefrontInstalled = await installDependenciesWithSpinner({
|
|
259
|
+
dependencies: [],
|
|
260
|
+
logLevel,
|
|
261
|
+
cwd: storefrontRoot,
|
|
262
|
+
spinnerMessage: 'Installing storefront dependencies...',
|
|
263
|
+
successMessage: 'Installed storefront dependencies',
|
|
264
|
+
failureMessage: 'Failed to install storefront dependencies',
|
|
265
|
+
warnOnFailure: true,
|
|
266
|
+
});
|
|
267
|
+
if (!storefrontInstalled) {
|
|
268
|
+
(0, logger_1.log)('You may need to run npm install in the storefront directory manually.', { level: 'info' });
|
|
269
|
+
}
|
|
173
270
|
}
|
|
174
271
|
const scaffoldSpinner = (0, prompts_1.spinner)();
|
|
175
272
|
scaffoldSpinner.start(`Generating app scaffold`);
|
|
176
273
|
// We add this pause so that the above output is displayed before the
|
|
177
274
|
// potentially lengthy file operations begin, which can prevent that
|
|
178
275
|
// from displaying and thus make the user think that the process has hung.
|
|
179
|
-
await (0, promises_1.setTimeout)(
|
|
180
|
-
|
|
181
|
-
|
|
276
|
+
await (0, promises_1.setTimeout)(constants_1.SCAFFOLD_DELAY_MS);
|
|
277
|
+
const srcPathScript = (fileName) => path_1.default.join(serverRoot, 'src', `${fileName}.ts`);
|
|
278
|
+
if (!includeStorefront) {
|
|
279
|
+
fs_extra_1.default.ensureDirSync(path_1.default.join(serverRoot, 'src'));
|
|
280
|
+
}
|
|
182
281
|
const configFile = srcPathScript('vendure-config');
|
|
183
282
|
try {
|
|
184
283
|
await fs_extra_1.default
|
|
185
284
|
.writeFile(configFile, configSource)
|
|
186
|
-
.then(() => fs_extra_1.default.writeFile(path_1.default.join(
|
|
285
|
+
.then(() => fs_extra_1.default.writeFile(path_1.default.join(serverRoot, '.env'), envSource))
|
|
187
286
|
.then(() => fs_extra_1.default.writeFile(srcPathScript('environment.d'), envDtsSource))
|
|
188
287
|
.then(() => fs_extra_1.default.writeFile(srcPathScript('index'), indexSource))
|
|
189
288
|
.then(() => fs_extra_1.default.writeFile(srcPathScript('index-worker'), indexWorkerSource))
|
|
190
|
-
.then(() => fs_extra_1.default.writeFile(path_1.default.join(
|
|
191
|
-
.then(() => fs_extra_1.default.writeFile(path_1.default.join(
|
|
192
|
-
.then(() => fs_extra_1.default.writeFile(path_1.default.join(
|
|
193
|
-
.then(() => fs_extra_1.default.ensureDir(path_1.default.join(
|
|
194
|
-
.then(() => fs_extra_1.default.copyFile(assetPath('gitignore.template'), path_1.default.join(
|
|
195
|
-
.then(() => fs_extra_1.default.copyFile(assetPath('tsconfig.template.json'), path_1.default.join(
|
|
196
|
-
.then(() => fs_extra_1.default.
|
|
197
|
-
.then(() => fs_extra_1.default.
|
|
198
|
-
.then(() => createDirectoryStructure(
|
|
199
|
-
.then(() => copyEmailTemplates(
|
|
289
|
+
.then(() => fs_extra_1.default.writeFile(path_1.default.join(serverRoot, 'README.md'), readmeSource))
|
|
290
|
+
.then(() => fs_extra_1.default.writeFile(path_1.default.join(serverRoot, 'Dockerfile'), dockerfileSource))
|
|
291
|
+
.then(() => fs_extra_1.default.writeFile(path_1.default.join(serverRoot, 'docker-compose.yml'), dockerComposeSource))
|
|
292
|
+
.then(() => fs_extra_1.default.ensureDir(path_1.default.join(serverRoot, 'src/plugins')))
|
|
293
|
+
.then(() => fs_extra_1.default.copyFile(assetPath('gitignore.template'), path_1.default.join(serverRoot, '.gitignore')))
|
|
294
|
+
.then(() => fs_extra_1.default.copyFile(assetPath('tsconfig.template.json'), path_1.default.join(serverRoot, 'tsconfig.json')))
|
|
295
|
+
.then(() => fs_extra_1.default.writeFile(path_1.default.join(serverRoot, 'tsconfig.dashboard.json'), tsconfigDashboardSource))
|
|
296
|
+
.then(() => fs_extra_1.default.writeFile(path_1.default.join(serverRoot, 'vite.config.mts'), viteConfigSource))
|
|
297
|
+
.then(() => createDirectoryStructure(serverRoot))
|
|
298
|
+
.then(() => copyEmailTemplates(serverRoot));
|
|
200
299
|
}
|
|
201
300
|
catch (e) {
|
|
202
301
|
(0, prompts_1.outro)(picocolors_1.default.red(`Failed to create app scaffold: ${e.message}`));
|
|
@@ -205,7 +304,7 @@ async function createVendureApp(name, useNpm, logLevel, isCi = false) {
|
|
|
205
304
|
scaffoldSpinner.stop(`Generated app scaffold`);
|
|
206
305
|
if (mode === 'quick' && dbType === 'postgres') {
|
|
207
306
|
(0, helpers_1.cleanUpDockerResources)(name);
|
|
208
|
-
await (0, helpers_1.startPostgresDatabase)(
|
|
307
|
+
await (0, helpers_1.startPostgresDatabase)(serverRoot);
|
|
209
308
|
}
|
|
210
309
|
const populateSpinner = (0, prompts_1.spinner)();
|
|
211
310
|
populateSpinner.start(`Initializing your new Vendure server`);
|
|
@@ -216,31 +315,10 @@ async function createVendureApp(name, useNpm, logLevel, isCi = false) {
|
|
|
216
315
|
populateProducts
|
|
217
316
|
? 'We are populating sample data so that you can start testing right away'
|
|
218
317
|
: 'We are setting up your Vendure server',
|
|
219
|
-
|
|
220
|
-
`✨ We'd love it if you drop us a star on GitHub: https://github.com/vendure-ecommerce/vendure`,
|
|
221
|
-
`📖 Check out the Vendure documentation at https://docs.vendure.io`,
|
|
222
|
-
`💬 Join our Discord community to chat with other Vendure developers: https://vendure.io/community`,
|
|
223
|
-
'💡 In the mean time, here are some tips to get you started',
|
|
224
|
-
`Vendure provides dedicated GraphQL APIs for both the Admin and Shop`,
|
|
225
|
-
`Almost every aspect of Vendure is customizable via plugins`,
|
|
226
|
-
`You can run 'vendure add' from the command line to add new plugins & features`,
|
|
227
|
-
`Use the EventBus in your plugins to react to events in the system`,
|
|
228
|
-
`Vendure supports multiple languages & currencies out of the box`,
|
|
229
|
-
`☕ Did we mention this can take a while?`,
|
|
230
|
-
`Our custom fields feature allows you to add any kind of data to your entities`,
|
|
231
|
-
`Vendure is built with TypeScript, so you get full type safety`,
|
|
232
|
-
`Combined with GraphQL's static schema, your type safety is end-to-end`,
|
|
233
|
-
`☕ Almost there now... thanks for your patience!`,
|
|
234
|
-
`Collections allow you to group products together`,
|
|
235
|
-
`Our AssetServerPlugin allows you to dynamically resize & optimize images`,
|
|
236
|
-
`Order flows are fully customizable to suit your business requirements`,
|
|
237
|
-
`Role-based permissions allow you to control access to every part of the system`,
|
|
238
|
-
`Customers can be grouped for targeted promotions & custom pricing`,
|
|
239
|
-
`You can find integrations in the Vendure Hub: https://vendure.io/hub`,
|
|
318
|
+
...constants_1.TIPS_WHILE_WAITING,
|
|
240
319
|
];
|
|
241
320
|
let tipIndex = 0;
|
|
242
321
|
let timer;
|
|
243
|
-
const tipInterval = 10000;
|
|
244
322
|
function displayTip() {
|
|
245
323
|
populateSpinner.message(tips[tipIndex]);
|
|
246
324
|
tipIndex++;
|
|
@@ -248,16 +326,28 @@ async function createVendureApp(name, useNpm, logLevel, isCi = false) {
|
|
|
248
326
|
// skip the intro tips if looping
|
|
249
327
|
tipIndex = 3;
|
|
250
328
|
}
|
|
251
|
-
timer = setTimeout(displayTip,
|
|
329
|
+
timer = setTimeout(displayTip, constants_1.TIP_INTERVAL_MS);
|
|
252
330
|
}
|
|
253
|
-
timer = setTimeout(displayTip,
|
|
331
|
+
timer = setTimeout(displayTip, constants_1.TIP_INTERVAL_MS);
|
|
332
|
+
// Change to serverRoot so that ts-node can correctly resolve modules.
|
|
333
|
+
// In monorepo mode, dependencies are hoisted to the root node_modules,
|
|
334
|
+
// but ts-node needs to be anchored in the server directory for proper
|
|
335
|
+
// module resolution and to find the tsconfig.json.
|
|
336
|
+
process.chdir(serverRoot);
|
|
254
337
|
// register ts-node so that the config file can be loaded
|
|
338
|
+
// We use transpileOnly to skip type checking during bootstrap, as the
|
|
339
|
+
// complex module resolution with npm workspaces and ESM packages can
|
|
340
|
+
// cause false TypeScript errors. Type checking happens when users run
|
|
341
|
+
// their own build/dev commands.
|
|
255
342
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
256
|
-
require((0, helpers_1.resolvePackageRootDir)('ts-node',
|
|
343
|
+
require((0, helpers_1.resolvePackageRootDir)('ts-node', serverRoot)).register({
|
|
344
|
+
project: path_1.default.join(serverRoot, 'tsconfig.json'),
|
|
345
|
+
transpileOnly: true,
|
|
346
|
+
});
|
|
257
347
|
let superAdminCredentials;
|
|
258
348
|
try {
|
|
259
|
-
const { populate } = await Promise.resolve(`${path_1.default.join((0, helpers_1.resolvePackageRootDir)('@vendure/core',
|
|
260
|
-
const { bootstrap, DefaultLogger, LogLevel, JobQueueService } = await Promise.resolve(`${path_1.default.join((0, helpers_1.resolvePackageRootDir)('@vendure/core',
|
|
349
|
+
const { populate } = await Promise.resolve(`${path_1.default.join((0, helpers_1.resolvePackageRootDir)('@vendure/core', serverRoot), 'cli', 'populate')}`).then(s => __importStar(require(s)));
|
|
350
|
+
const { bootstrap, DefaultLogger, LogLevel, JobQueueService } = await Promise.resolve(`${path_1.default.join((0, helpers_1.resolvePackageRootDir)('@vendure/core', serverRoot), 'dist', 'index')}`).then(s => __importStar(require(s)));
|
|
261
351
|
const { config } = await Promise.resolve(`${configFile}`).then(s => __importStar(require(s)));
|
|
262
352
|
const assetsDir = path_1.default.join(__dirname, '../assets');
|
|
263
353
|
superAdminCredentials = config.authOptions.superadminCredentials;
|
|
@@ -269,7 +359,7 @@ async function createVendureApp(name, useNpm, logLevel, isCi = false) {
|
|
|
269
359
|
: LogLevel.Info;
|
|
270
360
|
const bootstrapFn = async () => {
|
|
271
361
|
var _a;
|
|
272
|
-
await (0, helpers_1.checkDbConnection)(config.dbConnectionOptions,
|
|
362
|
+
await (0, helpers_1.checkDbConnection)(config.dbConnectionOptions, serverRoot);
|
|
273
363
|
const _app = await bootstrap(Object.assign(Object.assign({}, config), { apiOptions: Object.assign(Object.assign({}, ((_a = config.apiOptions) !== null && _a !== void 0 ? _a : {})), { port }), dbConnectionOptions: Object.assign(Object.assign({}, config.dbConnectionOptions), { synchronize: true }), logger: new DefaultLogger({ level: vendureLogLevel }), importExportOptions: {
|
|
274
364
|
importAssetsDir: path_1.default.join(assetsDir, 'images'),
|
|
275
365
|
} }));
|
|
@@ -281,11 +371,11 @@ async function createVendureApp(name, useNpm, logLevel, isCi = false) {
|
|
|
281
371
|
if (isCi) {
|
|
282
372
|
(0, logger_1.log)('[CI] Pausing before close...');
|
|
283
373
|
}
|
|
284
|
-
await (0, promises_1.setTimeout)(isCi ?
|
|
374
|
+
await (0, promises_1.setTimeout)(isCi ? constants_1.CI_PAUSE_BEFORE_CLOSE_MS : constants_1.NORMAL_PAUSE_BEFORE_CLOSE_MS);
|
|
285
375
|
await app.close();
|
|
286
376
|
if (isCi) {
|
|
287
377
|
(0, logger_1.log)('[CI] Pausing after close...');
|
|
288
|
-
await (0, promises_1.setTimeout)(
|
|
378
|
+
await (0, promises_1.setTimeout)(constants_1.CI_PAUSE_AFTER_CLOSE_MS);
|
|
289
379
|
}
|
|
290
380
|
populateSpinner.stop(`Server successfully initialized${populateProducts ? ' and populated' : ''}`);
|
|
291
381
|
clearTimeout(timer);
|
|
@@ -306,8 +396,8 @@ async function createVendureApp(name, useNpm, logLevel, isCi = false) {
|
|
|
306
396
|
const dashboardUrl = `http://localhost:${port}/dashboard`;
|
|
307
397
|
const quickStartInstructions = [
|
|
308
398
|
'Use the following credentials to log in to the Dashboard:',
|
|
309
|
-
`Username: ${picocolors_1.default.green((
|
|
310
|
-
`Password: ${picocolors_1.default.green((
|
|
399
|
+
`Username: ${picocolors_1.default.green((_b = config.authOptions.superadminCredentials) === null || _b === void 0 ? void 0 : _b.identifier)}`,
|
|
400
|
+
`Password: ${picocolors_1.default.green((_c = config.authOptions.superadminCredentials) === null || _c === void 0 ? void 0 : _c.password)}`,
|
|
311
401
|
`Open your browser and navigate to: ${picocolors_1.default.green(dashboardUrl)}`,
|
|
312
402
|
'',
|
|
313
403
|
];
|
|
@@ -325,13 +415,20 @@ async function createVendureApp(name, useNpm, logLevel, isCi = false) {
|
|
|
325
415
|
}
|
|
326
416
|
// process.stdin.resume();
|
|
327
417
|
process.on('SIGINT', function () {
|
|
328
|
-
displayOutro(
|
|
418
|
+
displayOutro({
|
|
419
|
+
root,
|
|
420
|
+
name,
|
|
421
|
+
superAdminCredentials,
|
|
422
|
+
includeStorefront,
|
|
423
|
+
serverPort: port,
|
|
424
|
+
storefrontPort,
|
|
425
|
+
});
|
|
329
426
|
quickStartProcess === null || quickStartProcess === void 0 ? void 0 : quickStartProcess.kill('SIGINT');
|
|
330
427
|
process.exit(0);
|
|
331
428
|
});
|
|
332
429
|
// Give enough time for the server to get up and running
|
|
333
430
|
// before opening the window.
|
|
334
|
-
await (0, promises_1.setTimeout)(
|
|
431
|
+
await (0, promises_1.setTimeout)(constants_1.AUTO_RUN_DELAY_MS);
|
|
335
432
|
try {
|
|
336
433
|
await (0, open_1.default)(dashboardUrl, {
|
|
337
434
|
newInstance: true,
|
|
@@ -350,7 +447,14 @@ async function createVendureApp(name, useNpm, logLevel, isCi = false) {
|
|
|
350
447
|
}
|
|
351
448
|
else {
|
|
352
449
|
clearTimeout(timer);
|
|
353
|
-
displayOutro(
|
|
450
|
+
displayOutro({
|
|
451
|
+
root,
|
|
452
|
+
name,
|
|
453
|
+
superAdminCredentials,
|
|
454
|
+
includeStorefront,
|
|
455
|
+
serverPort: port,
|
|
456
|
+
storefrontPort,
|
|
457
|
+
});
|
|
354
458
|
process.exit(0);
|
|
355
459
|
}
|
|
356
460
|
}
|
|
@@ -360,34 +464,106 @@ async function createVendureApp(name, useNpm, logLevel, isCi = false) {
|
|
|
360
464
|
process.exit(1);
|
|
361
465
|
}
|
|
362
466
|
}
|
|
363
|
-
|
|
467
|
+
/**
|
|
468
|
+
* Returns the standard npm scripts for the server package.json.
|
|
469
|
+
*/
|
|
470
|
+
function getServerPackageScripts() {
|
|
471
|
+
return {
|
|
472
|
+
'dev:server': 'ts-node ./src/index.ts',
|
|
473
|
+
'dev:worker': 'ts-node ./src/index-worker.ts',
|
|
474
|
+
'dev:dashboard': 'vite --clearScreen false',
|
|
475
|
+
dev: 'concurrently --kill-others npm:dev:*',
|
|
476
|
+
build: 'tsc',
|
|
477
|
+
'build:dashboard': 'vite build',
|
|
478
|
+
'start:server': 'node ./dist/index.js',
|
|
479
|
+
'start:worker': 'node ./dist/index-worker.js',
|
|
480
|
+
start: 'concurrently npm:start:*',
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Installs dependencies with a spinner, handling success/failure messaging.
|
|
485
|
+
* Returns true if installation succeeded, false otherwise.
|
|
486
|
+
*/
|
|
487
|
+
async function installDependenciesWithSpinner(installOptions) {
|
|
488
|
+
const { dependencies, isDevDependencies = false, logLevel, cwd, spinnerMessage, successMessage, failureMessage, warnOnFailure = false, } = installOptions;
|
|
489
|
+
const installSpinner = (0, prompts_1.spinner)();
|
|
490
|
+
installSpinner.start(spinnerMessage);
|
|
491
|
+
try {
|
|
492
|
+
await (0, helpers_1.installPackages)({ dependencies, isDevDependencies, logLevel, cwd });
|
|
493
|
+
installSpinner.stop(successMessage);
|
|
494
|
+
return true;
|
|
495
|
+
}
|
|
496
|
+
catch (e) {
|
|
497
|
+
if (warnOnFailure) {
|
|
498
|
+
installSpinner.stop(picocolors_1.default.yellow(`Warning: ${failureMessage}`));
|
|
499
|
+
return false;
|
|
500
|
+
}
|
|
501
|
+
else {
|
|
502
|
+
(0, prompts_1.outro)(picocolors_1.default.red(failureMessage));
|
|
503
|
+
process.exit(1);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
508
|
+
function displayOutro(outroOptions) {
|
|
364
509
|
var _a, _b;
|
|
510
|
+
const { root, name, superAdminCredentials, includeStorefront, serverPort = constants_1.SERVER_PORT, storefrontPort = constants_1.STOREFRONT_PORT, } = outroOptions;
|
|
365
511
|
const startCommand = 'npm run dev';
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
`Next, run:`,
|
|
371
|
-
picocolors_1.default.gray('$ ') + picocolors_1.default.blue(picocolors_1.default.bold(`cd ${name}`)),
|
|
372
|
-
picocolors_1.default.gray('$ ') + picocolors_1.default.blue(picocolors_1.default.bold(`${startCommand}`)),
|
|
373
|
-
`\n`,
|
|
374
|
-
`This will start the server in development mode.`,
|
|
375
|
-
`\n`,
|
|
376
|
-
`To run the Dashboard, in a new terminal navigate to your project directory and run:`,
|
|
377
|
-
picocolors_1.default.gray('$ ') + picocolors_1.default.blue(picocolors_1.default.bold(`npx vite`)),
|
|
378
|
-
`\n`,
|
|
379
|
-
`To access the Dashboard, open your browser and navigate to:`,
|
|
380
|
-
picocolors_1.default.green(`http://localhost:3000/dashboard`),
|
|
512
|
+
const identifier = (_a = superAdminCredentials === null || superAdminCredentials === void 0 ? void 0 : superAdminCredentials.identifier) !== null && _a !== void 0 ? _a : shared_constants_1.SUPER_ADMIN_USER_IDENTIFIER;
|
|
513
|
+
const password = (_b = superAdminCredentials === null || superAdminCredentials === void 0 ? void 0 : superAdminCredentials.password) !== null && _b !== void 0 ? _b : shared_constants_1.SUPER_ADMIN_USER_PASSWORD;
|
|
514
|
+
// Common footer for both modes
|
|
515
|
+
const commonFooter = [
|
|
381
516
|
`\n`,
|
|
382
517
|
`Use the following credentials to log in:`,
|
|
383
|
-
`Username: ${picocolors_1.default.green(
|
|
384
|
-
`Password: ${picocolors_1.default.green(
|
|
518
|
+
`Username: ${picocolors_1.default.green(identifier)}`,
|
|
519
|
+
`Password: ${picocolors_1.default.green(password)}`,
|
|
385
520
|
'\n',
|
|
386
521
|
'➡️ Docs: https://docs.vendure.io',
|
|
387
522
|
'➡️ Discord community: https://vendure.io/community',
|
|
388
523
|
'➡️ Star us on GitHub:',
|
|
389
524
|
' https://github.com/vendure-ecommerce/vendure',
|
|
390
525
|
];
|
|
526
|
+
let nextSteps;
|
|
527
|
+
if (includeStorefront) {
|
|
528
|
+
nextSteps = [
|
|
529
|
+
`Your new Vendure project was created!`,
|
|
530
|
+
picocolors_1.default.gray(root),
|
|
531
|
+
`\n`,
|
|
532
|
+
`This is a monorepo with the following apps:`,
|
|
533
|
+
` ${picocolors_1.default.cyan('apps/server')} - Vendure backend`,
|
|
534
|
+
` ${picocolors_1.default.cyan('apps/storefront')} - Next.js frontend`,
|
|
535
|
+
`\n`,
|
|
536
|
+
`Next, run:`,
|
|
537
|
+
picocolors_1.default.gray('$ ') + picocolors_1.default.blue(picocolors_1.default.bold(`cd ${name}`)),
|
|
538
|
+
picocolors_1.default.gray('$ ') + picocolors_1.default.blue(picocolors_1.default.bold(`${startCommand}`)),
|
|
539
|
+
`\n`,
|
|
540
|
+
`This will start both the server and storefront.`,
|
|
541
|
+
`\n`,
|
|
542
|
+
`Access points:`,
|
|
543
|
+
` Dashboard: ${picocolors_1.default.green(`http://localhost:${serverPort}/dashboard`)}`,
|
|
544
|
+
` Storefront: ${picocolors_1.default.green(`http://localhost:${storefrontPort}`)}`,
|
|
545
|
+
...commonFooter,
|
|
546
|
+
];
|
|
547
|
+
}
|
|
548
|
+
else {
|
|
549
|
+
nextSteps = [
|
|
550
|
+
`Your new Vendure server was created!`,
|
|
551
|
+
picocolors_1.default.gray(root),
|
|
552
|
+
`\n`,
|
|
553
|
+
`Next, run:`,
|
|
554
|
+
picocolors_1.default.gray('$ ') + picocolors_1.default.blue(picocolors_1.default.bold(`cd ${name}`)),
|
|
555
|
+
picocolors_1.default.gray('$ ') + picocolors_1.default.blue(picocolors_1.default.bold(`${startCommand}`)),
|
|
556
|
+
`\n`,
|
|
557
|
+
`This will start the server in development mode.`,
|
|
558
|
+
`\n`,
|
|
559
|
+
`To run the Dashboard, in a new terminal navigate to your project directory and run:`,
|
|
560
|
+
picocolors_1.default.gray('$ ') + picocolors_1.default.blue(picocolors_1.default.bold(`npx vite`)),
|
|
561
|
+
`\n`,
|
|
562
|
+
`To access the Dashboard, open your browser and navigate to:`,
|
|
563
|
+
picocolors_1.default.green(`http://localhost:${serverPort}/dashboard`),
|
|
564
|
+
...commonFooter,
|
|
565
|
+
];
|
|
566
|
+
}
|
|
391
567
|
(0, prompts_1.note)(nextSteps.join('\n'), picocolors_1.default.green('Setup complete!'));
|
|
392
568
|
(0, prompts_1.outro)(`Happy hacking!`);
|
|
393
569
|
}
|
|
@@ -395,7 +571,7 @@ function displayOutro(root, name, superAdminCredentials) {
|
|
|
395
571
|
* Run some initial checks to ensure that it is okay to proceed with creating
|
|
396
572
|
* a new Vendure project in the given location.
|
|
397
573
|
*/
|
|
398
|
-
function runPreChecks(name
|
|
574
|
+
function runPreChecks(name) {
|
|
399
575
|
if (typeof name === 'undefined') {
|
|
400
576
|
(0, logger_1.log)(picocolors_1.default.red(`Please specify the project directory:`));
|
|
401
577
|
(0, logger_1.log)(` ${picocolors_1.default.cyan(commander_1.program.name())} ${picocolors_1.default.green('<project-directory>')}`, { newline: 'after' });
|