@42wp/dev-env 1.0.4 → 1.0.6
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/README.md +21 -0
- package/package.json +1 -1
- package/src/commands/start.js +30 -3
- package/src/lib/deps.js +69 -0
- package/src/locales/en.js +7 -0
- package/src/locales/pt.js +7 -0
package/README.md
CHANGED
|
@@ -76,6 +76,27 @@ pass `--force`.
|
|
|
76
76
|
| `wpvip` | clone + mount the VIP mu-plugins |
|
|
77
77
|
| `initial_content` | `true` (200 posts) or a number |
|
|
78
78
|
|
|
79
|
+
### Project dependencies
|
|
80
|
+
|
|
81
|
+
Before installing WordPress, `42wp start` installs the project's dependencies in
|
|
82
|
+
your repo so WordPress and its mu-plugins load cleanly:
|
|
83
|
+
|
|
84
|
+
- `composer install` — when `composer.json` is present
|
|
85
|
+
- `<pm> install` — when `package.json` is present, where `<pm>` is inferred from the
|
|
86
|
+
lockfile: `pnpm-lock.yaml` → **pnpm**, `yarn.lock` → **yarn**, `package-lock.json`
|
|
87
|
+
→ **npm** (defaults to npm)
|
|
88
|
+
|
|
89
|
+
These run **on your machine**, in the mounted repo, before the containers start.
|
|
90
|
+
**Composer is required**: if a project has a `composer.json` and its PHP
|
|
91
|
+
dependencies can't be installed (composer missing, or the install fails), `start`
|
|
92
|
+
stops — a project with unmet PHP deps would break during the WordPress install
|
|
93
|
+
anyway. The JS install is best-effort (a missing tool or failure just warns). Skip
|
|
94
|
+
the whole step with `--skip-deps`:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
42wp start my-site --skip-deps
|
|
98
|
+
```
|
|
99
|
+
|
|
79
100
|
### WordPress version
|
|
80
101
|
|
|
81
102
|
By default projects are built on **`wordpress:php8.4-apache`** (newest WordPress,
|
package/package.json
CHANGED
package/src/commands/start.js
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
} from '../lib/naming.js';
|
|
16
16
|
import { projectDir } from '../lib/paths.js';
|
|
17
17
|
import { readProjectConfig } from '../lib/projectConfig.js';
|
|
18
|
+
import { installProjectDeps } from '../lib/deps.js';
|
|
18
19
|
import {
|
|
19
20
|
missingWpDirs,
|
|
20
21
|
pathExists,
|
|
@@ -213,16 +214,42 @@ export async function start(rawName, opts = {}) {
|
|
|
213
214
|
await fs.writeFile(path.join(envDir, 'dev-helper.php'), await readTemplate('dev-helper.php'), 'utf8');
|
|
214
215
|
}
|
|
215
216
|
|
|
217
|
+
// 4d. Install the project's dependencies (composer / JS) on the host BEFORE the
|
|
218
|
+
// containers start, so WordPress and its mu-plugins load cleanly during
|
|
219
|
+
// install. Composer is required — if its deps can't be installed the project
|
|
220
|
+
// would likely break during `wp core install`, so stop now. --skip-deps skips.
|
|
221
|
+
if (!opts['skip-deps']) {
|
|
222
|
+
try {
|
|
223
|
+
await installProjectDeps(repoDir);
|
|
224
|
+
} catch (err) {
|
|
225
|
+
error(err.message);
|
|
226
|
+
process.exitCode = 1;
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
216
231
|
// 5. Build & start project containers.
|
|
217
232
|
step(t('start.upping'));
|
|
218
233
|
await compose(['up', '-d', '--build'], { cwd: envDir });
|
|
219
234
|
|
|
220
|
-
// 6. Wait for
|
|
235
|
+
// 6. Wait for the WordPress core to be fully copied into the container before
|
|
236
|
+
// installing. The wordpress image's entrypoint extracts core alphabetically,
|
|
237
|
+
// so wp-includes/version.php lands BEFORE wp-settings.php — polling `wp core
|
|
238
|
+
// version` alone can proceed mid-copy on slow disks (e.g. a VM), and then
|
|
239
|
+
// `wp core install` fatals on a missing wp-settings.php. Waiting for
|
|
240
|
+
// wp-settings.php (which `install` requires, and which comes after all of
|
|
241
|
+
// wp-includes/) closes that window.
|
|
221
242
|
step(t('start.waitingWp'));
|
|
222
243
|
await pollUntil(
|
|
223
244
|
async () => {
|
|
224
|
-
const
|
|
225
|
-
|
|
245
|
+
const settings = await dockerExecCapture(container, [
|
|
246
|
+
'test',
|
|
247
|
+
'-f',
|
|
248
|
+
'/var/www/html/wp-settings.php',
|
|
249
|
+
]);
|
|
250
|
+
if (settings.code !== 0) return false;
|
|
251
|
+
const version = await dockerExecCapture(container, ['wp', 'core', 'version', '--allow-root']);
|
|
252
|
+
return version.code === 0;
|
|
226
253
|
},
|
|
227
254
|
{ label: 'WordPress', timeout: 90000 },
|
|
228
255
|
);
|
package/src/lib/deps.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Installs a project's dependencies on the HOST (in the mounted repo) before the
|
|
2
|
+
// WordPress install, so WordPress and its mu-plugins load cleanly. Best-effort: a
|
|
3
|
+
// missing tool or a failed install warns and continues — it never aborts `start`.
|
|
4
|
+
//
|
|
5
|
+
// - PHP: `composer install` when composer.json is present. REQUIRED — a project
|
|
6
|
+
// whose PHP deps can't be installed would likely break during the WordPress
|
|
7
|
+
// install, so a missing composer or a failed install throws (aborts `start`).
|
|
8
|
+
// - JS: `<pm> install` when package.json is present, where <pm> is inferred from
|
|
9
|
+
// the lockfile (pnpm-lock.yaml -> pnpm, yarn.lock -> yarn, package-lock.json
|
|
10
|
+
// / npm-shrinkwrap.json -> npm), defaulting to npm. Best-effort (build
|
|
11
|
+
// assets don't block WordPress from booting), so it only warns on failure.
|
|
12
|
+
|
|
13
|
+
import fs from 'node:fs';
|
|
14
|
+
import path from 'node:path';
|
|
15
|
+
|
|
16
|
+
import { run, capture } from './docker.js';
|
|
17
|
+
import { step } from './log.js';
|
|
18
|
+
import { t } from './i18n.js';
|
|
19
|
+
|
|
20
|
+
// Infer the JS package manager from the repo's lockfile; default to npm.
|
|
21
|
+
export function detectPackageManager(dir) {
|
|
22
|
+
if (fs.existsSync(path.join(dir, 'pnpm-lock.yaml'))) return 'pnpm';
|
|
23
|
+
if (fs.existsSync(path.join(dir, 'yarn.lock'))) return 'yarn';
|
|
24
|
+
if (fs.existsSync(path.join(dir, 'package-lock.json'))) return 'npm';
|
|
25
|
+
if (fs.existsSync(path.join(dir, 'npm-shrinkwrap.json'))) return 'npm';
|
|
26
|
+
return 'npm';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const has = (dir, name) => fs.existsSync(path.join(dir, name));
|
|
30
|
+
|
|
31
|
+
// Is a host command available? (spawns `<cmd> --version`).
|
|
32
|
+
async function toolAvailable(cmd) {
|
|
33
|
+
try {
|
|
34
|
+
const { code } = await capture(cmd, ['--version']);
|
|
35
|
+
return code === 0;
|
|
36
|
+
} catch {
|
|
37
|
+
return false; // ENOENT — not installed
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Run one dependency install (tool + args) in repoDir. When `required`, a missing
|
|
42
|
+
// tool or a failed install throws (so the caller can abort); otherwise it warns.
|
|
43
|
+
async function installWith(tool, args, repoDir, { required = false } = {}) {
|
|
44
|
+
if (!(await toolAvailable(tool))) {
|
|
45
|
+
if (required) throw new Error(t('deps.missingRequired', { tool }));
|
|
46
|
+
step(t('deps.missingTool', { tool }));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
step(t('deps.installing', { tool }));
|
|
50
|
+
try {
|
|
51
|
+
await run(tool, args, { cwd: repoDir });
|
|
52
|
+
} catch {
|
|
53
|
+
if (required) throw new Error(t('deps.failedRequired', { tool }));
|
|
54
|
+
step(t('deps.failed', { tool }));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Install the project's PHP and JS dependencies on the host, in repoDir. Throws if
|
|
59
|
+
// composer is required but unavailable/failing (caller aborts `start`).
|
|
60
|
+
export async function installProjectDeps(repoDir) {
|
|
61
|
+
// Composer is required — a missing vendor/ autoload can fatal WordPress on load.
|
|
62
|
+
if (has(repoDir, 'composer.json')) {
|
|
63
|
+
await installWith('composer', ['install', '--no-interaction'], repoDir, { required: true });
|
|
64
|
+
}
|
|
65
|
+
// JS deps are best-effort (build assets, not needed for WordPress to boot).
|
|
66
|
+
if (has(repoDir, 'package.json')) {
|
|
67
|
+
await installWith(detectPackageManager(repoDir), ['install'], repoDir);
|
|
68
|
+
}
|
|
69
|
+
}
|
package/src/locales/en.js
CHANGED
|
@@ -31,6 +31,13 @@ export default {
|
|
|
31
31
|
'start.upping': 'Starting project containers...',
|
|
32
32
|
'start.waitingWp': 'Waiting for the WordPress container to respond...',
|
|
33
33
|
'start.installing': 'Running silent WordPress install...',
|
|
34
|
+
'deps.installing': 'Installing project dependencies (${tool})...',
|
|
35
|
+
'deps.failed': 'Could not install ${tool} dependencies (continuing anyway).',
|
|
36
|
+
'deps.missingTool': '${tool} not found on your machine — skipping. Install it and re-run to set up dependencies.',
|
|
37
|
+
'deps.missingRequired':
|
|
38
|
+
"${tool} is required to install this project's dependencies but was not found. Install ${tool} and re-run, or pass --skip-deps to skip.",
|
|
39
|
+
'deps.failedRequired':
|
|
40
|
+
'Failed to install ${tool} dependencies. Fix the error above and re-run, or pass --skip-deps to skip.',
|
|
34
41
|
'start.installingLang': 'Installing WordPress language pack (${locale})...',
|
|
35
42
|
'start.langFailed': 'Could not install the ${locale} language pack (continuing in English).',
|
|
36
43
|
'start.activatingTheme': 'Activating theme (${theme})...',
|
package/src/locales/pt.js
CHANGED
|
@@ -31,6 +31,13 @@ export default {
|
|
|
31
31
|
'start.upping': 'Subindo containers do projeto...',
|
|
32
32
|
'start.waitingWp': 'Aguardando o container WP responder...',
|
|
33
33
|
'start.installing': 'Executando instalação silenciosa do WordPress...',
|
|
34
|
+
'deps.installing': 'Instalando as dependências do projeto (${tool})...',
|
|
35
|
+
'deps.failed': 'Não foi possível instalar as dependências de ${tool} (continuando mesmo assim).',
|
|
36
|
+
'deps.missingTool': '${tool} não encontrado na sua máquina — pulando. Instale-o e rode novamente para configurar as dependências.',
|
|
37
|
+
'deps.missingRequired':
|
|
38
|
+
'${tool} é necessário para instalar as dependências deste projeto, mas não foi encontrado. Instale o ${tool} e rode novamente, ou use --skip-deps para pular.',
|
|
39
|
+
'deps.failedRequired':
|
|
40
|
+
'Falha ao instalar as dependências de ${tool}. Corrija o erro acima e rode novamente, ou use --skip-deps para pular.',
|
|
34
41
|
'start.installingLang': 'Instalando o pacote de idioma do WordPress (${locale})...',
|
|
35
42
|
'start.langFailed': 'Não foi possível instalar o pacote de idioma ${locale} (continuando em inglês).',
|
|
36
43
|
'start.activatingTheme': 'Ativando o tema (${theme})...',
|