@scandipwa/magento-scripts 2.4.10-alpha.0 → 2.4.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/lib/commands/cli.js +25 -9
  2. package/lib/commands/execute.js +18 -4
  3. package/lib/config/docker.js +17 -12
  4. package/lib/config/magento/required-php-extensions/magento-2.4.js +1 -0
  5. package/lib/config/php-config.js +2 -1
  6. package/lib/config/services/composer/versions/composer-1.js +1 -1
  7. package/lib/config/services/composer/versions/composer-2.9.js +8 -0
  8. package/lib/config/services/composer/versions/index.js +2 -1
  9. package/lib/config/services/elasticsearch/versions/elasticsearch-6.8.js +4 -4
  10. package/lib/config/services/elasticsearch/versions/elasticsearch-7.6.js +2 -1
  11. package/lib/config/services/mariadb/versions/index.js +2 -1
  12. package/lib/config/services/mariadb/versions/mariadb-11.8.js +11 -0
  13. package/lib/config/services/nginx/versions/nginx-1.18.js +2 -1
  14. package/lib/config/services/nginx/versions/nginx-1.22.js +2 -1
  15. package/lib/config/services/nginx/versions/nginx-1.24.js +2 -1
  16. package/lib/config/services/nginx/versions/nginx-1.26.js +2 -1
  17. package/lib/config/services/nginx/versions/nginx-1.28.js +3 -2
  18. package/lib/config/services/php/versions/php-8.1.js +1 -1
  19. package/lib/config/services/php/versions/php-8.2.js +1 -1
  20. package/lib/config/services/php/versions/php-8.3.js +1 -1
  21. package/lib/config/services/php/versions/php-8.4.js +1 -1
  22. package/lib/config/services/php/versions/php-8.5.js +32 -0
  23. package/lib/config/services/redis/index.js +3 -1
  24. package/lib/config/services/redis/valkey-9.0.js +8 -0
  25. package/lib/config/services/varnish/index.js +2 -1
  26. package/lib/config/services/varnish/varnish-8-0.js +15 -0
  27. package/lib/config/templates/magentorc.template +1 -0
  28. package/lib/config/templates/nginx.template.conf +1 -1
  29. package/lib/config/versions/magento-2.4.4-p16.js +1 -1
  30. package/lib/config/versions/magento-2.4.4-p17.js +41 -0
  31. package/lib/config/versions/magento-2.4.4-p18.js +43 -0
  32. package/lib/config/versions/magento-2.4.5-p16.js +41 -0
  33. package/lib/config/versions/magento-2.4.5-p17.js +43 -0
  34. package/lib/config/versions/magento-2.4.6-p14.js +41 -0
  35. package/lib/config/versions/magento-2.4.6-p15.js +43 -0
  36. package/lib/config/versions/magento-2.4.7-p1.js +2 -2
  37. package/lib/config/versions/magento-2.4.7-p10.js +42 -0
  38. package/lib/config/versions/magento-2.4.7-p2.js +2 -2
  39. package/lib/config/versions/magento-2.4.7-p3.js +2 -2
  40. package/lib/config/versions/magento-2.4.7-p4.js +2 -2
  41. package/lib/config/versions/magento-2.4.7-p5.js +2 -2
  42. package/lib/config/versions/magento-2.4.7-p6.js +2 -2
  43. package/lib/config/versions/magento-2.4.7-p7.js +2 -2
  44. package/lib/config/versions/magento-2.4.7-p8.js +2 -2
  45. package/lib/config/versions/magento-2.4.7-p9.js +41 -0
  46. package/lib/config/versions/magento-2.4.7.js +2 -2
  47. package/lib/config/versions/magento-2.4.8-p1.js +2 -2
  48. package/lib/config/versions/magento-2.4.8-p2.js +2 -2
  49. package/lib/config/versions/magento-2.4.8-p3.js +2 -3
  50. package/lib/config/versions/magento-2.4.8-p4.js +42 -0
  51. package/lib/config/versions/magento-2.4.8-p5.js +42 -0
  52. package/lib/config/versions/magento-2.4.8.js +2 -2
  53. package/lib/config/versions/magento-2.4.9-beta1.js +41 -0
  54. package/lib/config/versions/magento-2.4.9.js +44 -0
  55. package/lib/tasks/docker/containers/container-api.d.ts +4 -4
  56. package/lib/tasks/docker/containers/container-api.js +2 -2
  57. package/lib/tasks/docker/containers/tasks.js +31 -18
  58. package/lib/tasks/docker/image/image-api.d.ts +12 -0
  59. package/lib/tasks/docker/image/image-api.js +22 -1
  60. package/lib/tasks/docker/project-image-builder.js +25 -13
  61. package/lib/tasks/execute.js +51 -7
  62. package/lib/tasks/magento/setup-magento/clear-logs.js +31 -0
  63. package/lib/tasks/magento/setup-magento/disable-2fa.js +13 -0
  64. package/lib/tasks/magento/setup-magento/index.js +29 -1
  65. package/lib/tasks/magento/setup-magento/set-base-url.js +42 -15
  66. package/lib/tasks/magento/setup-magento/urn-highlighter.js +84 -2
  67. package/lib/tasks/requirements/searchengine-version.js +25 -30
  68. package/lib/tasks/start.js +9 -5
  69. package/lib/util/config-file-validator.js +15 -7
  70. package/lib/util/execute-in-container.js +88 -6
  71. package/lib/util/instance-metadata.js +15 -9
  72. package/lib/util/open-browser.js +7 -0
  73. package/lib/util/wait-for-logs.js +5 -2
  74. package/package.json +2 -2
  75. package/typings/context.d.ts +4 -2
  76. package/typings/index.d.ts +22 -0
  77. package/lib/config/services/elasticsearch/base-repo.js +0 -3
@@ -70,10 +70,10 @@ export interface ContainerExecOptions {
70
70
  interactive?: boolean
71
71
  }
72
72
 
73
- export function exec<T>(
73
+ export function exec<T extends boolean = false>(
74
74
  options: ContainerExecOptions,
75
75
  execOptions?: ExecAsyncSpawnOptions<T>
76
- ): Promise<string>
76
+ ): Promise<T extends true ? { code: number; result: string } : string>
77
77
 
78
78
  export function execCommand(options: ContainerExecOptions): string[]
79
79
 
@@ -168,10 +168,10 @@ export interface ContainerRunOptions {
168
168
  platform?: string
169
169
  }
170
170
 
171
- export function run<T>(
171
+ export function run<T extends boolean = false>(
172
172
  containerOptions: ContainerRunOptions,
173
173
  execOptions?: ExecAsyncSpawnOptions<T>
174
- ): Promise<string>
174
+ ): Promise<T extends true ? { code: number; result: string } : string>
175
175
 
176
176
  export function runCommand(options: ContainerRunOptions): string[]
177
177
 
@@ -16,9 +16,9 @@ const transformEnvValue = (value) => {
16
16
 
17
17
  for (const [key, val] of Object.entries(value)) {
18
18
  if (typeof val === 'string' && val) {
19
- envArguments.push(`--env ${key}='${val.replaceAll("'", "\\'")}'`)
19
+ envArguments.push(`--env=${key}='${val.replaceAll("'", "\\'")}'`)
20
20
  } else if (String(val)) {
21
- envArguments.push(`--env ${key}=${val}`)
21
+ envArguments.push(`--env=${key}=${val}`)
22
22
  }
23
23
  }
24
24
 
@@ -16,23 +16,28 @@ const stopAndRemoveContainers = async (containers) => {
16
16
  }
17
17
 
18
18
  /**
19
- * @param {string} image
20
- */
21
- const pull = async (image) => execAsyncSpawn(`docker pull ${image}`)
22
-
23
- /**
24
- * @param {string[]} acc
25
- * @param {{ remoteImages?: string[], image: string }} val
19
+ * @param {{ image: string, platform?: string }[]} acc
20
+ * @param {{ remoteImages?: string[], image: string, platform?: string }} val
26
21
  */
27
22
  const remoteImageReducer = (acc, val) => {
28
23
  if (
29
24
  Array.isArray(val.remoteImages) &&
30
25
  val.remoteImages.every((image) => typeof image === 'string')
31
26
  ) {
32
- return acc.concat(val.remoteImages)
27
+ return acc.concat(
28
+ val.remoteImages.map((image) => ({
29
+ image,
30
+ platform: val.platform
31
+ }))
32
+ )
33
33
  }
34
34
 
35
- return acc.concat([val.image])
35
+ return acc.concat([
36
+ {
37
+ image: val.image,
38
+ platform: val.platform
39
+ }
40
+ ])
36
41
  }
37
42
 
38
43
  /**
@@ -59,10 +64,10 @@ const pullImages = () => ({
59
64
  containers
60
65
  .filter(filterNonPullableImages)
61
66
  .reduce(remoteImageReducer, [])
62
- .map((image) => {
67
+ .map(({ image, platform }) => {
63
68
  const [repo, tag = 'latest'] = image.split(':')
64
69
 
65
- return { repo, tag }
70
+ return { repo, tag, platform }
66
71
  })
67
72
  .reduce(
68
73
  (acc, val) =>
@@ -76,11 +81,15 @@ const pullImages = () => ({
76
81
  ),
77
82
  []
78
83
  )
79
- .map(({ repo, tag }) => ({
84
+ .map(({ repo, tag, platform }) => ({
80
85
  title: `Pulling ${logger.style.file(
81
86
  `${repo}:${tag}`
82
87
  )} image`,
83
- task: () => pull(`${repo}:${tag}`)
88
+ task: () =>
89
+ imageApi.pull({
90
+ image: `${repo}:${tag}`,
91
+ platform
92
+ })
84
93
  })),
85
94
  {
86
95
  concurrent: true,
@@ -92,7 +101,7 @@ const pullImages = () => ({
92
101
  const imagesFilter = containers
93
102
  .filter(filterNonPullableImages)
94
103
  .reduce(remoteImageReducer, [])
95
- .map((image) => `reference='${image}'`)
104
+ .map(({ image }) => `reference='${image}'`)
96
105
 
97
106
  const existingImages = await imageApi.ls({
98
107
  formatToJSON: true,
@@ -102,10 +111,10 @@ const pullImages = () => ({
102
111
  const missingContainerImages = containers
103
112
  .filter(filterNonPullableImages)
104
113
  .reduce(remoteImageReducer, [])
105
- .map((image) => {
114
+ .map(({ image, platform }) => {
106
115
  const [repo, tag = 'latest'] = image.split(':')
107
116
 
108
- return { repo, tag }
117
+ return { repo, tag, platform }
109
118
  })
110
119
  .filter(
111
120
  ({ repo, tag }) =>
@@ -132,9 +141,13 @@ const pullImages = () => ({
132
141
  }
133
142
 
134
143
  return task.newListr(
135
- missingContainerImages.map(({ repo, tag }) => ({
144
+ missingContainerImages.map(({ repo, tag, platform }) => ({
136
145
  title: `Pulling ${logger.style.file(`${repo}:${tag}`)} image`,
137
- task: () => pull(`${repo}:${tag}`)
146
+ task: () =>
147
+ imageApi.pull({
148
+ image: `${repo}:${tag}`,
149
+ platform
150
+ })
138
151
  })),
139
152
  {
140
153
  concurrent: true,
@@ -75,3 +75,15 @@ export function inspect(
75
75
  options?: ImagesInspectOptions<true>,
76
76
  execOptions?: ExecAsyncSpawnOptions<false>
77
77
  ): Promise<ImagesInspectResult>
78
+
79
+ export interface ImagesPullOptions {
80
+ image: string
81
+ allTags?: boolean
82
+ platform?: string
83
+ quiet?: boolean
84
+ }
85
+
86
+ export function pull(
87
+ options?: ImagesPullOptions,
88
+ execOptions?: ExecAsyncSpawnOptions<false>
89
+ ): Promise<string>
@@ -78,7 +78,28 @@ const inspect = async (options, execOptions = {}) => {
78
78
  return execAsyncSpawn(`docker image inspect ${args}`, execOptions)
79
79
  }
80
80
 
81
+ /**
82
+ * @param {import('./image-api').ImagesPullOptions} options
83
+ * @param {import('../../../util/exec-async-command').ExecAsyncSpawnOptions} execOptions
84
+ */
85
+ const pull = async (options, execOptions = {}) => {
86
+ const { image, allTags, platform, quiet } = options
87
+
88
+ const allTagsArg = typeof allTags === 'boolean' ? '--all-tags' : ''
89
+ const platformArg =
90
+ typeof platform === 'string' ? `--platform=${platform}` : ''
91
+
92
+ const quietArg = typeof quiet === 'boolean' ? '--quiet' : ''
93
+
94
+ const args = [allTagsArg, platformArg, quietArg, image]
95
+ .filter(Boolean)
96
+ .join(' ')
97
+
98
+ return execAsyncSpawn(`docker image pull ${args}`, execOptions)
99
+ }
100
+
81
101
  module.exports = {
82
102
  ls,
83
- inspect
103
+ inspect,
104
+ pull
84
105
  }
@@ -223,11 +223,13 @@ const buildDockerFileInstructions = async (
223
223
  const { agentVersion, licenseKey } = newRelic
224
224
 
225
225
  // eslint-disable-next-line max-len
226
+ // Use linux-musl archive for Alpine-based images.
227
+ const newRelicArchive = `newrelic-php5-${agentVersion}-linux-musl`
226
228
  dockerFileInstructions.run('apk add --no-cache gcompat')
227
- .run(`curl -L https://download.newrelic.com/php_agent/archive/${agentVersion}/newrelic-php5-${agentVersion}-linux.tar.gz | tar -C /tmp -zx \
229
+ .run(`curl -L https://download.newrelic.com/php_agent/archive/${agentVersion}/${newRelicArchive}.tar.gz | tar -C /tmp -zx \
228
230
  && export NR_INSTALL_USE_CP_NOT_LN=1 \
229
231
  && export NR_INSTALL_SILENT=1 \
230
- && /tmp/newrelic-php5-${agentVersion}-linux/newrelic-install install \
232
+ && /tmp/${newRelicArchive}/newrelic-install install \
231
233
  && rm -rf /tmp/newrelic-php5-* /tmp/nrinstall*`)
232
234
  .run(`sed -i -e "s/REPLACE_WITH_REAL_KEY/${licenseKey}/" \
233
235
  -e "s/newrelic.appname[[:space:]]=[[:space:]].*/newrelic.appname=\\"${
@@ -302,17 +304,25 @@ const buildDebugDockerFileInstructions = async (ctx, { image, tag }) => {
302
304
  * @returns {import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
303
305
  */
304
306
  const buildProjectImage = () => ({
305
- title: rosettaTranslatedContainers.includes('php')
306
- ? 'Building Project Images (for x86)'
307
- : 'Building Project Images',
307
+ title: 'Building Project Images',
308
308
  task: async (ctx, task) => {
309
309
  const containers = ctx.config.docker.getContainers(ctx.ports)
310
+ const isUsingLinuxAmd64Platform =
311
+ rosettaTranslatedContainers.includes('php') ||
312
+ containers.php.platform === 'linux/amd64'
313
+
314
+ if (isUsingLinuxAmd64Platform) {
315
+ task.title = 'Building Project Images (for x86)'
316
+ } else if (
317
+ containers.php.platform &&
318
+ containers.php.platform !== 'linux/amd64'
319
+ ) {
320
+ task.title = `Building Project Images (for ${containers.php.platform})`
321
+ }
310
322
 
311
323
  return task.newListr([
312
324
  {
313
- title: rosettaTranslatedContainers.includes('php')
314
- ? 'Building PHP image (for x86)'
315
- : 'Building PHP image',
325
+ title: 'Building PHP image',
316
326
  task: async () => {
317
327
  const [image, tag = 'latest'] =
318
328
  ctx.config.overridenConfiguration.configuration.php.baseImage.split(
@@ -328,8 +338,10 @@ const buildProjectImage = () => ({
328
338
  try {
329
339
  await execAsyncSpawn(
330
340
  `docker build -t ${containers.php.image}${
331
- rosettaTranslatedContainers.includes('php')
341
+ isUsingLinuxAmd64Platform
332
342
  ? ' --platform linux/amd64'
343
+ : containers.php.platform
344
+ ? ` --platform ${containers.php.platform}`
333
345
  : ''
334
346
  } -<<EOF
335
347
  ${dockerFileInstructions}
@@ -350,9 +362,7 @@ EOF`,
350
362
  }
351
363
  },
352
364
  {
353
- title: rosettaTranslatedContainers.includes('php')
354
- ? 'Building PHP with XDebug image (for x86)'
355
- : 'Building PHP with XDebug image',
365
+ title: 'Building PHP with XDebug image',
356
366
  task: async () => {
357
367
  const [phpImage, phpTag] = containers.php.image.split(':')
358
368
  const debugImageInstructions =
@@ -364,8 +374,10 @@ EOF`,
364
374
  try {
365
375
  await execAsyncSpawn(
366
376
  `docker build -t ${containers.phpWithXdebug.image}${
367
- rosettaTranslatedContainers.includes('php')
377
+ isUsingLinuxAmd64Platform
368
378
  ? ' --platform linux/amd64'
379
+ : containers.php.platform
380
+ ? ` --platform ${containers.php.platform}`
369
381
  : ''
370
382
  } -<<EOF
371
383
  ${debugImageInstructions}
@@ -8,7 +8,9 @@ const { getCachedPorts } = require('../config/get-port-config')
8
8
  const checkPHPVersion = require('./requirements/php-version')
9
9
  const {
10
10
  executeInContainer,
11
- runInContainer
11
+ executeInContainerNonInteractive,
12
+ runInContainer,
13
+ runInContainerNonInteractive
12
14
  } = require('../util/execute-in-container')
13
15
  const { containerApi } = require('./docker/containers')
14
16
  const dockerNetwork = require('./docker/network')
@@ -17,10 +19,11 @@ const { prepareFileSystem } = require('./file-system')
17
19
 
18
20
  /**
19
21
  *
20
- * @param {{ containerName: string, commands: string[] }} argv
22
+ * @param {{ containerName: string, commands: string[], nonInteractive?: boolean }} argv
21
23
  * @returns
22
24
  */
23
25
  const executeTask = async (argv) => {
26
+ const { nonInteractive = false } = argv
24
27
  const tasks = new Listr(
25
28
  [
26
29
  checkRequirements(),
@@ -35,8 +38,12 @@ const executeTask = async (argv) => {
35
38
  {
36
39
  concurrent: false,
37
40
  exitOnError: true,
38
- ctx: { throwMagentoVersionMissing: true },
39
- renderer: process.stdout.isTTY ? 'default' : 'silent',
41
+ ctx: /** @type {any} */ ({ throwMagentoVersionMissing: true }),
42
+ renderer: nonInteractive
43
+ ? 'silent'
44
+ : process.stdout.isTTY
45
+ ? 'default'
46
+ : 'silent',
40
47
  rendererOptions: { collapse: false, clearOutput: true }
41
48
  }
42
49
  )
@@ -45,10 +52,12 @@ const executeTask = async (argv) => {
45
52
  try {
46
53
  ctx = await tasks.run()
47
54
  } catch (e) {
48
- logger.error(e.message || e)
55
+ logger.error(e instanceof Error ? e.message : String(e))
49
56
  process.exit(1)
50
57
  }
51
- const containers = ctx.config.docker.getContainers(ctx.ports)
58
+ const containers = /** @type {Record<string, any>} */ (
59
+ ctx.config.docker.getContainers(ctx.ports)
60
+ )
52
61
  const services = Object.keys(containers)
53
62
 
54
63
  if (
@@ -71,6 +80,11 @@ const executeTask = async (argv) => {
71
80
  ? containerResult[1]
72
81
  : containerResult
73
82
 
83
+ if (nonInteractive && argv.commands.length === 0) {
84
+ logger.error('Non-interactive mode requires a command to execute')
85
+ process.exit(1)
86
+ }
87
+
74
88
  if (argv.commands.length === 0) {
75
89
  // if we have default connect command then use it
76
90
  if (container.connectCommand) {
@@ -88,6 +102,20 @@ const executeTask = async (argv) => {
88
102
  })
89
103
 
90
104
  if (containerList.length > 0) {
105
+ if (nonInteractive) {
106
+ const result = await executeInContainerNonInteractive({
107
+ containerName: container.name,
108
+ commands: argv.commands,
109
+ user: container.user,
110
+ env: container.execCommandEnv
111
+ })
112
+
113
+ if (result.result) {
114
+ process.stdout.write(`${result.result}\n`)
115
+ }
116
+ process.exit(result.code)
117
+ }
118
+
91
119
  if (process.stdout.isTTY) {
92
120
  logger.logN(
93
121
  `Executing container ${logger.style.misc(
@@ -101,13 +129,29 @@ const executeTask = async (argv) => {
101
129
  const result = executeInContainer({
102
130
  containerName: container.name,
103
131
  commands: argv.commands,
104
- user: container.user
132
+ user: container.user,
133
+ env: container.execCommandEnv
105
134
  })
106
135
 
107
136
  return result
108
137
  }
109
138
 
110
139
  if (container.name.includes('php')) {
140
+ if (nonInteractive) {
141
+ const result = await runInContainerNonInteractive(
142
+ {
143
+ ...container,
144
+ name: `${container.name}_exec-${Date.now()}`
145
+ },
146
+ argv.commands
147
+ )
148
+
149
+ if (result.result) {
150
+ process.stdout.write(`${result.result}\n`)
151
+ }
152
+ process.exit(result.code)
153
+ }
154
+
111
155
  if (process.stdout.isTTY) {
112
156
  logger.logN(
113
157
  `Starting container ${logger.style.misc(
@@ -0,0 +1,31 @@
1
+ const fs = require('fs')
2
+ const path = require('path')
3
+ const pathExists = require('../../../util/path-exists')
4
+
5
+ /**
6
+ * @returns {import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
7
+ */
8
+ const clearLogs = () => ({
9
+ title: 'Clearing Magento logs',
10
+ task: async (ctx, task) => {
11
+ let deletedLogsCount = 0
12
+ await Promise.all(
13
+ [
14
+ './var/log/system.log',
15
+ './var/log/debug.log',
16
+ './var/log/xdebug.log'
17
+ ].map(async (logPath) => {
18
+ if (await pathExists(path.join(process.cwd(), logPath))) {
19
+ await fs.promises.rm(path.join(process.cwd(), logPath))
20
+ deletedLogsCount++
21
+ }
22
+ })
23
+ )
24
+
25
+ if (deletedLogsCount === 0) {
26
+ task.skip()
27
+ }
28
+ }
29
+ })
30
+
31
+ module.exports = clearLogs
@@ -1,6 +1,7 @@
1
1
  const configPhpToJson = require('../../../util/config-php-json')
2
2
  const getJsonfileData = require('../../../util/get-jsonfile-data')
3
3
  const path = require('path')
4
+ const semver = require('semver')
4
5
  const composerTask = require('../../../util/composer-task')
5
6
  const magentoTask = require('../../../util/magento-task')
6
7
 
@@ -9,6 +10,18 @@ const magentoTask = require('../../../util/magento-task')
9
10
  */
10
11
  module.exports = () => ({
11
12
  title: 'Disabling 2FA module',
13
+ // this module is only for magento 2.4 or newer
14
+ skip: (ctx) => {
15
+ const { magentoVersion } = ctx
16
+
17
+ const pureMagentoVersion = magentoVersion.match(
18
+ /^([0-9]+\.[0-9]+\.[0-9]+)/
19
+ )[1]
20
+
21
+ const isMagento24 = semver.satisfies(pureMagentoVersion, '>=2.4.0')
22
+
23
+ return !isMagento24
24
+ },
12
25
  task: async (ctx, task) => {
13
26
  // Check if MarkShust module is already installed via composer.lock
14
27
  const composerLockPath = path.join(
@@ -26,7 +26,21 @@ const setupMagento = (options = {}) => ({
26
26
  if (options.onlyInstallMagento) {
27
27
  return task.newListr([
28
28
  flushRedisConfig(),
29
- migrateDatabase({ onlyInstallMagento: true })
29
+ migrateDatabase({ onlyInstallMagento: true }),
30
+ {
31
+ title: 'Disabling Magento caches',
32
+ task: (ctx, task) => {
33
+ const { varnish } =
34
+ ctx.config.overridenConfiguration.configuration
35
+ return task.newListr(
36
+ magentoTask(
37
+ `cache:disable block_html layout${
38
+ !varnish.enabled ? ' full_page' : ''
39
+ }`
40
+ )
41
+ )
42
+ }
43
+ }
30
44
  ])
31
45
  }
32
46
 
@@ -35,6 +49,20 @@ const setupMagento = (options = {}) => ({
35
49
  setupMagentoFilePermissions(),
36
50
  updateEnvPHP(),
37
51
  migrateDatabase(),
52
+ {
53
+ title: 'Disabling Magento caches',
54
+ task: (ctx, task) => {
55
+ const { varnish } =
56
+ ctx.config.overridenConfiguration.configuration
57
+ return task.newListr(
58
+ magentoTask(
59
+ `cache:disable block_html layout${
60
+ !varnish.enabled ? ' full_page' : ''
61
+ }`
62
+ )
63
+ )
64
+ }
65
+ },
38
66
  flushRedisConfig(),
39
67
  {
40
68
  title: 'Configuring Magento settings',
@@ -5,9 +5,10 @@ const KnownError = require('../../../errors/known-error')
5
5
  * @param {number} scopeId
6
6
  * @param {string} code
7
7
  * @param {string} host
8
+ * @param {'websites' | 'stores'} scopeType
8
9
  * @returns {import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
9
10
  */
10
- const setBaseUrlForScope = (scopeId, code, host) => ({
11
+ const setBaseUrlForScope = (scopeId, code, host, scopeType) => ({
11
12
  title: `store code ${code} at ${host}`,
12
13
  task: async (ctx, task) => {
13
14
  const {
@@ -31,7 +32,7 @@ const setBaseUrlForScope = (scopeId, code, host) => ({
31
32
  const secureLocation = `${host}/` // SSL will work only on port 443, so you cannot run multiple projects with SSL at the same time.
32
33
  const httpUrl = `http://${location}`
33
34
  const httpsUrl = `https://${secureLocation}`
34
- const scope = scopeId === 0 ? 'default' : 'websites'
35
+ const scope = scopeId === 0 ? 'default' : scopeType
35
36
  const table = 'core_config_data'
36
37
  const values = [
37
38
  {
@@ -83,11 +84,13 @@ const setBaseUrl = () => ({
83
84
  task: async (ctx, task) => {
84
85
  const {
85
86
  config: {
86
- overridenConfiguration: { ssl, storeDomains }
87
+ overridenConfiguration: { ssl, storeDomains, configuration }
87
88
  },
88
89
  databaseConnection
89
90
  } = ctx
90
91
 
92
+ const runType = configuration?.nginx?.runType || 'website'
93
+
91
94
  const enableSecureFrontend = ssl.enabled ? '1' : '0'
92
95
 
93
96
  await updateTableValues(
@@ -110,27 +113,33 @@ const setBaseUrl = () => ({
110
113
  { databaseConnection, task }
111
114
  )
112
115
 
113
- /** @type {{ website_id: number, code: string }[][]}} */
114
- const [storeWebsites] = await databaseConnection.query(
115
- `select * from store_website;`
116
+ const scopeType = runType === 'store' ? 'stores' : 'websites'
117
+ const tableName = runType === 'store' ? 'store' : 'store_website'
118
+ const idField = runType === 'store' ? 'store_id' : 'website_id'
119
+
120
+ const [entities] = await databaseConnection.query(
121
+ `select * from ${tableName};`
116
122
  )
117
123
 
118
- if (!storeWebsites || storeWebsites.length === 0) {
124
+ if (!entities || entities.length === 0) {
119
125
  throw new KnownError(
120
- `No store websites found in database, store_website table is empty or does not exist`
126
+ `No ${
127
+ runType === 'store' ? 'stores' : 'store websites'
128
+ } found in database, ${tableName} table is empty or does not exist`
121
129
  )
122
130
  }
123
131
 
124
132
  const storeDomainsWithMapping = Object.entries(storeDomains).reduce(
125
133
  (acc, [key, val]) => {
126
- const storeWebsite = storeWebsites.find(
127
- ({ code }) => code === key
134
+ const entity = entities.find(
135
+ /** @param {{ code: string }} entity */
136
+ (entity) => entity.code === key
128
137
  )
129
- if (storeWebsite) {
138
+ if (entity) {
130
139
  return {
131
140
  ...acc,
132
- [storeWebsite.code]: {
133
- websiteId: storeWebsite.website_id,
141
+ [entity.code]: {
142
+ scopeId: entity[idField],
134
143
  domain: val
135
144
  }
136
145
  }
@@ -141,10 +150,28 @@ const setBaseUrl = () => ({
141
150
  {}
142
151
  )
143
152
 
153
+ // Check for missing store codes when runType is 'store'
154
+ if (runType === 'store') {
155
+ const missingCodes = Object.keys(storeDomains).filter(
156
+ (code) =>
157
+ !entities.some(
158
+ /** @param {{ code: string }} entity */
159
+ (entity) => entity.code === code
160
+ )
161
+ )
162
+ if (missingCodes.length > 0) {
163
+ throw new KnownError(
164
+ `Store codes not found in database: ${missingCodes.join(
165
+ ', '
166
+ )}. Please check your storeDomains configuration in cma.js matches the store codes in the store table.`
167
+ )
168
+ }
169
+ }
170
+
144
171
  return task.newListr(
145
172
  Object.entries(storeDomainsWithMapping).map(
146
- ([storeCode, { websiteId, domain }]) =>
147
- setBaseUrlForScope(websiteId, storeCode, domain)
173
+ ([storeCode, { scopeId, domain }]) =>
174
+ setBaseUrlForScope(scopeId, storeCode, domain, scopeType)
148
175
  ),
149
176
  {
150
177
  concurrent: true,