kizlo 0.8.3 → 0.9.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/dist/cli/banner.js +1 -20
- package/dist/cli/commands/_setup.js +37 -21
- package/dist/cli/commands/_wiring.js +7 -12
- package/dist/cli/commands/create.js +24 -16
- package/dist/cli/commands/dev.js +51 -13
- package/dist/cli/commands/init.js +19 -13
- package/dist/cli/daemon/config.js +12 -2
- package/dist/cli/daemon/watch.js +4 -4
- package/dist/cli/index.js +0 -1
- package/dist/cli/presets/template.js +61 -37
- package/dist/cli/utils.js +2 -11
- package/dist/cli/wp/dev.js +4 -2
- package/dist/cli/wp/docker.d.ts +5 -1
- package/dist/cli/wp/docker.js +5 -1
- package/dist/package.js +1 -1
- package/dist/router.d.ts +9 -9
- package/dist/seo/schema.d.ts +5 -5
- package/dist/test.d.ts +2 -2
- package/dist/test.js +2 -2
- package/package.json +2 -1
- package/dist/cli/commands/watch.js +0 -35
package/dist/cli/banner.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
//#region src/cli/banner.ts
|
|
2
|
-
const KIZLO_CLI_WORD_MARK = [
|
|
3
|
-
"██╗ ██╗██╗███████╗██╗ ██████╗ ",
|
|
4
|
-
"██║ ██╔╝██║╚══███╔╝██║ ██╔═══██╗",
|
|
5
|
-
"█████╔╝ ██║ ███╔╝ ██║ ██║ ██║",
|
|
6
|
-
"██╔═██╗ ██║ ███╔╝ ██║ ██║ ██║",
|
|
7
|
-
"██║ ██╗██║███████╗███████╗╚██████╔╝",
|
|
8
|
-
"╚═╝ ╚═╝╚═╝╚══════╝╚══════╝ ╚═════╝ "
|
|
9
|
-
];
|
|
10
|
-
const KIZLO_TAGLINE = "Headless WordPress framework for TypeScript";
|
|
11
2
|
function colorSupported() {
|
|
12
3
|
return Boolean(process.stdout.isTTY) && process.env.NO_COLOR === void 0 && process.env.TERM !== "dumb";
|
|
13
4
|
}
|
|
@@ -22,16 +13,6 @@ function palette() {
|
|
|
22
13
|
reset: on ? "\x1B[0m" : ""
|
|
23
14
|
};
|
|
24
15
|
}
|
|
25
|
-
function printBanner(version) {
|
|
26
|
-
const color = colorSupported();
|
|
27
|
-
const cyan = color ? "\x1B[38;5;44m" : "";
|
|
28
|
-
const bold = color ? "\x1B[1m" : "";
|
|
29
|
-
const dim = color ? "\x1B[2m" : "";
|
|
30
|
-
const reset = color ? "\x1B[0m" : "";
|
|
31
|
-
const art = KIZLO_CLI_WORD_MARK.map((line) => `${cyan}${line}${reset}`).join("\n");
|
|
32
|
-
process.stdout.write(`\n${art}\n\n`);
|
|
33
|
-
process.stdout.write(`${dim}${KIZLO_TAGLINE}${reset} ${bold}v${version}${reset}\n\n`);
|
|
34
|
-
}
|
|
35
16
|
|
|
36
17
|
//#endregion
|
|
37
|
-
export { palette
|
|
18
|
+
export { palette };
|
|
@@ -11,6 +11,7 @@ import path from "node:path";
|
|
|
11
11
|
import fs from "node:fs";
|
|
12
12
|
import * as p from "@clack/prompts";
|
|
13
13
|
import { randomBytes } from "node:crypto";
|
|
14
|
+
import getPort, { portNumbers } from "get-port";
|
|
14
15
|
|
|
15
16
|
//#region src/cli/commands/_setup.ts
|
|
16
17
|
/** Production connection keys — what a real deploy needs, and what `.env.example` always lists. */
|
|
@@ -84,15 +85,34 @@ function withApiPath(baseUrl, apiPath) {
|
|
|
84
85
|
return baseUrl;
|
|
85
86
|
}
|
|
86
87
|
}
|
|
88
|
+
/** The conventional starting port a scaffolded app's dev server serves from. */
|
|
89
|
+
const DEFAULT_APP_PORT = 3e3;
|
|
90
|
+
/**
|
|
91
|
+
* Pick a free port for a freshly scaffolded app, preferring {@link DEFAULT_APP_PORT} and stepping
|
|
92
|
+
* upward when it's taken. `create` builds the app URL from this and writes it into `.env`, which is
|
|
93
|
+
* synced to WordPress as the event/webhook delivery target — so defaulting it to a port already in use
|
|
94
|
+
* would hand WordPress an unreachable URL, and it fails *silently* there (events just never arrive).
|
|
95
|
+
* `get-port` probes every loopback family (including the IPv6 `::1` a dev server often binds on macOS),
|
|
96
|
+
* so it never returns a port that's really in use. `init` doesn't use this — an existing project owns
|
|
97
|
+
* its own port, so it asks the user instead.
|
|
98
|
+
*/
|
|
99
|
+
function pickAppPort() {
|
|
100
|
+
return getPort({ port: portNumbers(DEFAULT_APP_PORT, DEFAULT_APP_PORT + 100) });
|
|
101
|
+
}
|
|
87
102
|
/**
|
|
88
103
|
* Collect the WordPress connection interactively: the backend/site URLs, the webhook signing
|
|
89
104
|
* secret, and either the local-dev folder or a remote site's credentials. The caller layers any
|
|
90
105
|
* framework-specific prompts (directory, import alias) on top of what this returns.
|
|
106
|
+
*
|
|
107
|
+
* When `baseUrl` is supplied the public-URL prompt is skipped and that value is used verbatim —
|
|
108
|
+
* `create` scaffolds a brand-new app that has no public URL yet, so it defaults to the local dev
|
|
109
|
+
* origin and lets the user fill in production later.
|
|
91
110
|
*/
|
|
92
|
-
async function collectConnectionInteractively(preset) {
|
|
111
|
+
async function collectConnectionInteractively(preset, opts = {}) {
|
|
93
112
|
let siteUrl;
|
|
94
113
|
let baseUrl;
|
|
95
|
-
if (
|
|
114
|
+
if (opts.baseUrl !== void 0) baseUrl = opts.baseUrl;
|
|
115
|
+
else if (preset.apiPath) baseUrl = orCancel(await p.text({
|
|
96
116
|
message: "Public app URL",
|
|
97
117
|
placeholder: "https://your-app.com",
|
|
98
118
|
validate: validate(urlString)
|
|
@@ -260,10 +280,9 @@ async function setupLocalWordPress(cwd, conn) {
|
|
|
260
280
|
conn.wpUrl = local.url;
|
|
261
281
|
conn.wpUsername = local.username;
|
|
262
282
|
conn.wpPassword = local.appPassword;
|
|
283
|
+
conn.adminPassword = local.adminPassword;
|
|
263
284
|
s.stop("Local WordPress ready");
|
|
264
285
|
if (local.secretSyncError) p.log.warn(`Could not sync KIZLO_DEV_SITE_SECRET to the local plugin (${local.secretSyncError})`);
|
|
265
|
-
p.log.success(`Local WordPress configured (${conn.devPath}) — .env points at ${conn.wpUrl}`);
|
|
266
|
-
if (local.adminPassword) p.log.warn(`wp-admin login: ${conn.wpUsername} / ${local.adminPassword} — save it, it's shown only once`);
|
|
267
286
|
} catch (error) {
|
|
268
287
|
s.stop("Local WordPress setup failed");
|
|
269
288
|
p.cancel(error instanceof Error ? error.message : String(error));
|
|
@@ -321,26 +340,23 @@ async function syncRemote(conn) {
|
|
|
321
340
|
});
|
|
322
341
|
if (!sync.ok) p.log.warn(`Could not sync the site settings to WordPress (${sync.error}) — make sure the kizlo plugin is active, then set them from the Kizlo settings.`);
|
|
323
342
|
}
|
|
324
|
-
/** The "Next steps" lines
|
|
325
|
-
function nextStepsLines(
|
|
343
|
+
/** The "Next steps" lines. `kizlo dev` is the single entry point for development. */
|
|
344
|
+
function nextStepsLines(conn, prefix = "") {
|
|
345
|
+
const login = conn.mode === "local" && conn.adminPassword ? [
|
|
346
|
+
``,
|
|
347
|
+
`Log in to wp-admin (${conn.wpUrl}/wp-admin):`,
|
|
348
|
+
` ${conn.wpUsername} / ${conn.adminPassword} — save it, it's shown only once`
|
|
349
|
+
] : [];
|
|
326
350
|
return [
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
``
|
|
331
|
-
] : [
|
|
332
|
-
`Watch your extensions and regenerate the contract during development:`,
|
|
333
|
-
` ${prefix}npx kizlo watch`,
|
|
334
|
-
``
|
|
335
|
-
],
|
|
336
|
-
`Generate the contract once for production builds:`,
|
|
337
|
-
` ${prefix}npx kizlo generate`
|
|
351
|
+
`Start developing:`,
|
|
352
|
+
` ${prefix}npx kizlo dev`,
|
|
353
|
+
...login
|
|
338
354
|
];
|
|
339
355
|
}
|
|
340
|
-
/** The shared "Next steps" note
|
|
341
|
-
function nextStepsNote(
|
|
342
|
-
p.note(nextStepsLines(
|
|
356
|
+
/** The shared "Next steps" note. */
|
|
357
|
+
function nextStepsNote(conn, prefix = "") {
|
|
358
|
+
p.note(nextStepsLines(conn, prefix).join("\n"), "Next steps");
|
|
343
359
|
}
|
|
344
360
|
|
|
345
361
|
//#endregion
|
|
346
|
-
export { collectConnectionFromEnv, collectConnectionInteractively, dirPath, nextStepsLines, nextStepsNote, orCancel, setupLocalWordPress, syncRemote, validate, withApiPath, writeEnv };
|
|
362
|
+
export { collectConnectionFromEnv, collectConnectionInteractively, dirPath, nextStepsLines, nextStepsNote, orCancel, pickAppPort, setupLocalWordPress, syncRemote, validate, withApiPath, writeEnv };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { resolveModuleImport, writeFileIfAbsent } from "../utils.js";
|
|
2
2
|
import { applyPatchToSource, patchChanged, renderPatchCode } from "../presets/patch.js";
|
|
3
|
-
import { findRootLayout,
|
|
3
|
+
import { findRootLayout, resolvePatch } from "../presets/template.js";
|
|
4
4
|
import { orCancel } from "./_setup.js";
|
|
5
5
|
import { CONTRACT_BARREL } from "../daemon/generate.js";
|
|
6
6
|
import path from "node:path";
|
|
@@ -19,7 +19,7 @@ export default defineConfig({
|
|
|
19
19
|
`;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
|
-
* Build the {@link ScaffoldContext} that adapts a template's
|
|
22
|
+
* Build the {@link ScaffoldContext} that adapts a template's conventions (paths and imports) to a real
|
|
23
23
|
* project. `dirRel` is the Kizlo home directory, `appDir` the App Router directory, and `alias` the
|
|
24
24
|
* import-alias prefix (empty for relative imports). The server-entry import is resolved per calling
|
|
25
25
|
* file so each scaffolded file references the server through the right specifier.
|
|
@@ -65,7 +65,7 @@ function reportScaffold(file, result, yes) {
|
|
|
65
65
|
if (result === "kept") p.log.info(`Kept existing ${file.label} (${file.relPath})${yes ? " — pass --force to overwrite" : ""}`);
|
|
66
66
|
else p.log.success(`${result === "overwritten" ? "Overwrote" : "Created"} ${file.label} (${file.relPath})`);
|
|
67
67
|
}
|
|
68
|
-
/** Seed the generated-contract directory so imports resolve before the first `kizlo
|
|
68
|
+
/** Seed the generated-contract directory so imports resolve before the first `kizlo dev`/`generate`. */
|
|
69
69
|
function writeGeneratedContract(cwd, serverDirRel) {
|
|
70
70
|
const generatedDirRel = path.join(serverDirRel, "generated");
|
|
71
71
|
writeFileIfAbsent(path.join(cwd, generatedDirRel, "contract.json"), "{}\n");
|
|
@@ -78,10 +78,10 @@ function writeGeneratedContract(cwd, serverDirRel) {
|
|
|
78
78
|
* rather than written to a guessed-at file. A confident apply is an idempotent upsert: it replaces
|
|
79
79
|
* our exports if present, adds them if not.
|
|
80
80
|
*/
|
|
81
|
-
function applyLayoutPatches(cwd,
|
|
81
|
+
function applyLayoutPatches(cwd, patches, conventions, scaffold) {
|
|
82
82
|
const manualSteps = [];
|
|
83
|
-
for (const entry of
|
|
84
|
-
const resolved = resolvePatch(entry,
|
|
83
|
+
for (const entry of patches) {
|
|
84
|
+
const resolved = resolvePatch(entry, conventions, scaffold);
|
|
85
85
|
const target = findRootLayout(cwd, scaffold.appDir, resolved.relPath);
|
|
86
86
|
if (!target) {
|
|
87
87
|
manualSteps.push(resolved);
|
|
@@ -101,12 +101,7 @@ function applyLayoutPatches(cwd, manifest, scaffold) {
|
|
|
101
101
|
const { text, changes } = applied;
|
|
102
102
|
if (patchChanged(changes)) {
|
|
103
103
|
fs.writeFileSync(target, text);
|
|
104
|
-
|
|
105
|
-
...changes.replacedExports.length ? [`replaced ${changes.replacedExports.join(", ")}`] : [],
|
|
106
|
-
...changes.addedExports.length ? [`added ${changes.addedExports.join(", ")}`] : [],
|
|
107
|
-
...changes.addedImports.length ? ["imports"] : []
|
|
108
|
-
];
|
|
109
|
-
p.log.success(`Wired Kizlo into your ${resolved.label} (${relTarget}) — ${parts.join(", ")}`);
|
|
104
|
+
p.log.success(`Wired Kizlo into your ${resolved.label} (${relTarget})`);
|
|
110
105
|
} else p.log.info(`Your ${resolved.label} is already wired (${relTarget})`);
|
|
111
106
|
}
|
|
112
107
|
for (const resolved of manualSteps) p.note(renderPatchCode(resolved), `Add these to your ${resolved.label} (the layout that renders <html>)`);
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { dockerAvailable } from "../wp/docker.js";
|
|
2
2
|
import { availablePackageManagers, detectInvokingPackageManager, ensureGitignored, frameworkCreateArgs, getVersion, installArgs, runCommandAsync, runCommandCaptured } from "../utils.js";
|
|
3
|
-
import { printBanner } from "../banner.js";
|
|
4
3
|
import { getPreset } from "../presets/index.js";
|
|
5
4
|
import { fetchTemplate } from "../presets/source.js";
|
|
6
|
-
import {
|
|
7
|
-
import { collectConnectionInteractively, nextStepsLines, orCancel, setupLocalWordPress, syncRemote, validate, withApiPath, writeEnv } from "./_setup.js";
|
|
5
|
+
import { adaptFile, changesFor, fileEntries, isExample, patchEntries, readManifest } from "../presets/template.js";
|
|
6
|
+
import { collectConnectionInteractively, nextStepsLines, orCancel, pickAppPort, setupLocalWordPress, syncRemote, validate, withApiPath, writeEnv } from "./_setup.js";
|
|
8
7
|
import { applyLayoutPatches, buildScaffoldContext, kizloConfigTemplate, reportScaffold, scaffoldFile, writeGeneratedContract } from "./_wiring.js";
|
|
9
8
|
import z from "zod/v4";
|
|
10
9
|
import path from "node:path";
|
|
@@ -58,14 +57,16 @@ function bootstrapArgs(manifest, pm, name) {
|
|
|
58
57
|
* Layer Kizlo's wiring onto a freshly bootstrapped app in `dir`, from an already-fetched template
|
|
59
58
|
* directory + manifest. The framework CLI has produced the base project (package.json, config,
|
|
60
59
|
* tsconfig, the root layout); this drives the manifest — the same engine `init` uses — to record the
|
|
61
|
-
* `kizlo` dependency, write `kizlo.config.ts`, scaffold the manifest's
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
60
|
+
* `kizlo` dependency, write `kizlo.config.ts`, scaffold the manifest's files (the `base` plumbing and
|
|
61
|
+
* the `create` layout/styles always, the `example`-flagged demo pages only when `includeExamples`),
|
|
62
|
+
* seed the generated contract, and ignore `.env`. On a fresh app Kizlo owns the layout, so `create`
|
|
63
|
+
* writes it whole (already SEO-wired) rather than patching — `applyLayoutPatches` runs over `create`'s
|
|
64
|
+
* patches, which are none today. The target directory layout comes straight from the manifest's
|
|
65
|
+
* conventions, which the bootstrap flags are chosen to match, so files land where they expect. Fresh
|
|
66
|
+
* files are written with `force`, silently replacing the framework defaults.
|
|
66
67
|
*/
|
|
67
68
|
async function applyManifestWiring(dir, templateDir, manifest, opts) {
|
|
68
|
-
const { kizloDir, appDir, alias } = manifest.
|
|
69
|
+
const { kizloDir, appDir, alias } = manifest.conventions;
|
|
69
70
|
const scaffold = buildScaffoldContext(dir, {
|
|
70
71
|
dirRel: kizloDir,
|
|
71
72
|
appDir,
|
|
@@ -73,18 +74,19 @@ async function applyManifestWiring(dir, templateDir, manifest, opts) {
|
|
|
73
74
|
clientUrl: void 0
|
|
74
75
|
});
|
|
75
76
|
recordKizloDependency(dir, manifest);
|
|
77
|
+
const changes = changesFor(manifest, "create").filter((change) => opts.includeExamples || !isExample(change));
|
|
76
78
|
const files = [{
|
|
77
79
|
label: "Kizlo config",
|
|
78
80
|
relPath: "kizlo.config.ts",
|
|
79
81
|
contents: kizloConfigTemplate(kizloDir, alias, opts.devPath)
|
|
80
|
-
}, ...
|
|
82
|
+
}, ...fileEntries(changes).map((entry) => adaptFile(templateDir, entry, manifest.conventions, scaffold))];
|
|
81
83
|
for (const file of files) reportScaffold(file, await scaffoldFile(dir, file, {
|
|
82
84
|
force: true,
|
|
83
85
|
yes: false
|
|
84
86
|
}), false);
|
|
85
87
|
writeGeneratedContract(dir, path.join(kizloDir, "server"));
|
|
86
88
|
ensureGitignored(dir, ".env");
|
|
87
|
-
applyLayoutPatches(dir, manifest, scaffold);
|
|
89
|
+
applyLayoutPatches(dir, patchEntries(changes), manifest.conventions, scaffold);
|
|
88
90
|
}
|
|
89
91
|
const create = defineCommand({
|
|
90
92
|
meta: {
|
|
@@ -105,8 +107,7 @@ const create = defineCommand({
|
|
|
105
107
|
},
|
|
106
108
|
async run({ args }) {
|
|
107
109
|
const cwd = process.cwd();
|
|
108
|
-
|
|
109
|
-
p.intro("kizlo create");
|
|
110
|
+
p.intro(`Let's create a new Kizlo application`);
|
|
110
111
|
const requested = args.template;
|
|
111
112
|
let template;
|
|
112
113
|
if (requested) {
|
|
@@ -155,7 +156,11 @@ const create = defineCommand({
|
|
|
155
156
|
})),
|
|
156
157
|
initialValue: defaultPm
|
|
157
158
|
}));
|
|
158
|
-
const
|
|
159
|
+
const includeExamples = orCancel(await p.confirm({
|
|
160
|
+
message: "Add example pages?",
|
|
161
|
+
initialValue: true
|
|
162
|
+
}));
|
|
163
|
+
const conn = await collectConnectionInteractively(preset, { baseUrl: `http://localhost:${await pickAppPort()}` });
|
|
159
164
|
if (preset.apiPath && conn.baseUrl) conn.baseUrl = withApiPath(conn.baseUrl, preset.apiPath);
|
|
160
165
|
if (conn.mode === "local" && !await dockerAvailable()) {
|
|
161
166
|
p.cancel("Docker isn't available — start Docker (or install it) and re-run, or choose “Use my own WordPress”.");
|
|
@@ -183,7 +188,10 @@ const create = defineCommand({
|
|
|
183
188
|
fail(`${preset.label} setup failed — see the output above and try again.`);
|
|
184
189
|
}
|
|
185
190
|
try {
|
|
186
|
-
await applyManifestWiring(dir, fetched.dir, manifest, {
|
|
191
|
+
await applyManifestWiring(dir, fetched.dir, manifest, {
|
|
192
|
+
devPath: conn.devPath,
|
|
193
|
+
includeExamples
|
|
194
|
+
});
|
|
187
195
|
} catch (error) {
|
|
188
196
|
fail(error instanceof Error ? error.message : String(error));
|
|
189
197
|
}
|
|
@@ -209,7 +217,7 @@ const create = defineCommand({
|
|
|
209
217
|
`cd ${name}`,
|
|
210
218
|
...depsInstalled ? [] : [`${pm} install`],
|
|
211
219
|
``,
|
|
212
|
-
...nextStepsLines(conn
|
|
220
|
+
...nextStepsLines(conn)
|
|
213
221
|
].join("\n"), "Next steps");
|
|
214
222
|
p.outro("Kizlo is ready 🎉");
|
|
215
223
|
}
|
package/dist/cli/commands/dev.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createStack } from "../wp/docker.js";
|
|
2
|
-
import { ensureGitignored, envGroups,
|
|
3
|
-
import {
|
|
4
|
-
import { resolveDevConfig } from "../daemon/config.js";
|
|
2
|
+
import { ensureGitignored, envGroups, groupDefault, mergeEnv, pickStackPort, withSpinner } from "../utils.js";
|
|
3
|
+
import { hasDevStack, resolveDevConfig } from "../daemon/config.js";
|
|
5
4
|
import { bootstrapDev } from "../wp/dev.js";
|
|
6
5
|
import { reapOrphans, registerSession, removeProjectContainers, spawnWatchdog, unregisterSession } from "../wp/session.js";
|
|
7
6
|
import { syncSiteSettings } from "../wp/settings.js";
|
|
8
7
|
import { devStack } from "../wp/stack.js";
|
|
8
|
+
import { palette } from "../banner.js";
|
|
9
9
|
import { startWatcher } from "../daemon/watch.js";
|
|
10
10
|
import { join } from "node:path";
|
|
11
11
|
import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
@@ -20,6 +20,18 @@ async function resolve$1(cwd) {
|
|
|
20
20
|
stack: createStack(devStack(cfg))
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* The stack lifecycle subcommands (`stop`/`down`/`reset`) only act on a local WordPress
|
|
25
|
+
* Docker stack. A bring-your-own-WordPress project (no `dev.path`) has no stack to manage,
|
|
26
|
+
* so — rather than fall through to `resolveDevConfig`'s hard "`dev.path` is required" error —
|
|
27
|
+
* print a plain note explaining there's nothing to do and exit cleanly. Returns true when a
|
|
28
|
+
* local stack is configured and the caller may proceed.
|
|
29
|
+
*/
|
|
30
|
+
async function requireDevStack(cwd) {
|
|
31
|
+
if (await hasDevStack(cwd)) return true;
|
|
32
|
+
note("No local WordPress stack is configured (`dev.path` is unset) — nothing to manage here.");
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
23
35
|
/** A dim, untagged one-liner (no consola timestamp) for the clean dev output. */
|
|
24
36
|
function note(text) {
|
|
25
37
|
const { dim, reset } = palette();
|
|
@@ -157,8 +169,8 @@ function armForegroundTeardown(cfg) {
|
|
|
157
169
|
}
|
|
158
170
|
}
|
|
159
171
|
/**
|
|
160
|
-
* Boot the stack and run in the foreground until exit — the
|
|
161
|
-
* `kizlo dev
|
|
172
|
+
* Boot the stack and run in the foreground until exit — the path behind bare
|
|
173
|
+
* `kizlo dev`. Arms teardown first (so a mid-startup cancel still
|
|
162
174
|
* stops partial containers), shows a timed spinner, prints the summary + stop hint, then
|
|
163
175
|
* parks. A referenced timer holds the event loop open — an unresolved promise alone would
|
|
164
176
|
* not, so without it Node would empty its loop and exit straight after printing.
|
|
@@ -213,15 +225,39 @@ async function startForeground(cfg) {
|
|
|
213
225
|
await new Promise(() => {});
|
|
214
226
|
}
|
|
215
227
|
/**
|
|
228
|
+
* Run the contract watcher in the foreground until exit — the path bare `kizlo dev` takes when no
|
|
229
|
+
* local dev stack is configured (a bring-your-own-WordPress project). Generates once, then watches
|
|
230
|
+
* the server files and regenerates on save. Returns immediately when another watcher already holds
|
|
231
|
+
* the lock; otherwise the persistent watcher keeps the process alive on its own.
|
|
232
|
+
*/
|
|
233
|
+
async function watchOnly(cwd) {
|
|
234
|
+
const stop = await startWatcher(cwd);
|
|
235
|
+
if (!stop) return;
|
|
236
|
+
process.on("exit", stop);
|
|
237
|
+
for (const signal of [
|
|
238
|
+
"SIGINT",
|
|
239
|
+
"SIGTERM",
|
|
240
|
+
"SIGHUP"
|
|
241
|
+
]) process.on(signal, () => {
|
|
242
|
+
stop();
|
|
243
|
+
process.exit(0);
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
216
247
|
* Start (or resume) the dev stack. Backs bare `kizlo dev`. Always runs in the foreground
|
|
217
248
|
* and stops the stack on exit, so it never outlives the session — the subcommands
|
|
218
|
-
* (`stop`/`down`/`reset`) manage everything else.
|
|
249
|
+
* (`stop`/`down`/`reset`) manage everything else. Without a local dev stack configured
|
|
250
|
+
* (`dev.path` unset), there's nothing to boot, so it runs the contract watcher alone.
|
|
219
251
|
*/
|
|
220
252
|
async function bringUp() {
|
|
221
|
-
|
|
253
|
+
const cwd = process.cwd();
|
|
254
|
+
if (!await hasDevStack(cwd)) {
|
|
255
|
+
await watchOnly(cwd);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
222
258
|
const reaped = await reapOrphans();
|
|
223
259
|
if (reaped.length) note(`Stopped ${reaped.length} orphaned dev stack${reaped.length === 1 ? "" : "s"}: ${reaped.join(", ")}`);
|
|
224
|
-
const cfg = await resolveDevConfig(
|
|
260
|
+
const cfg = await resolveDevConfig(cwd);
|
|
225
261
|
if (!cfg.wordpressPath.startsWith("..")) ensureGitignored(cfg.configDir, cfg.wordpressPath);
|
|
226
262
|
await startForeground(cfg);
|
|
227
263
|
}
|
|
@@ -232,6 +268,7 @@ const subCommands = {
|
|
|
232
268
|
description: "Stop the dev stack, keeping the database volume"
|
|
233
269
|
},
|
|
234
270
|
async run() {
|
|
271
|
+
if (!await requireDevStack(process.cwd())) return;
|
|
235
272
|
const { stack } = await resolve$1(process.cwd());
|
|
236
273
|
await withSpinner("Stopping WordPress dev stack", () => stack.composeStop(), "Stack stopped (volumes kept)");
|
|
237
274
|
}
|
|
@@ -242,6 +279,7 @@ const subCommands = {
|
|
|
242
279
|
description: "Stop and remove the dev stack containers (keeps the database and files)"
|
|
243
280
|
},
|
|
244
281
|
async run() {
|
|
282
|
+
if (!await requireDevStack(process.cwd())) return;
|
|
245
283
|
const { stack } = await resolve$1(process.cwd());
|
|
246
284
|
await withSpinner("Removing WordPress dev stack", () => stack.composeDown(), "Stack removed (database and files kept)");
|
|
247
285
|
}
|
|
@@ -249,24 +287,24 @@ const subCommands = {
|
|
|
249
287
|
reset: defineCommand({
|
|
250
288
|
meta: {
|
|
251
289
|
name: "reset",
|
|
252
|
-
description: "Wipe the database and the install folder
|
|
290
|
+
description: "Wipe the database and the install folder so the next `kizlo dev` rebuilds fresh"
|
|
253
291
|
},
|
|
254
292
|
async run() {
|
|
255
|
-
|
|
293
|
+
if (!await requireDevStack(process.cwd())) return;
|
|
256
294
|
const { cfg, stack } = await resolve$1(process.cwd());
|
|
257
|
-
await withSpinner("Wiping WordPress dev stack", () => stack.composeDown({ volumes: true }), "
|
|
295
|
+
await withSpinner("Wiping WordPress dev stack", () => stack.composeDown({ volumes: true }), "Local WordPress reset successfully");
|
|
258
296
|
rmSync(cfg.wordpressDir, {
|
|
259
297
|
recursive: true,
|
|
260
298
|
force: true
|
|
261
299
|
});
|
|
262
|
-
|
|
300
|
+
note("Run `kizlo dev` to rebuild a fresh stack.");
|
|
263
301
|
}
|
|
264
302
|
})
|
|
265
303
|
};
|
|
266
304
|
const dev = defineCommand({
|
|
267
305
|
meta: {
|
|
268
306
|
name: "dev",
|
|
269
|
-
description: "
|
|
307
|
+
description: "Run the dev stack and contract watcher (stop | down | reset)"
|
|
270
308
|
},
|
|
271
309
|
subCommands,
|
|
272
310
|
run: groupDefault(Object.keys(subCommands), bringUp)
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { dockerAvailable } from "../wp/docker.js";
|
|
2
|
-
import { addDependencyArgs, detectImportAlias, detectPackageManager, ensureGitignored, getVersion, loadEnvFiles,
|
|
3
|
-
import { printBanner } from "../banner.js";
|
|
2
|
+
import { addDependencyArgs, detectImportAlias, detectPackageManager, ensureGitignored, getVersion, loadEnvFiles, runCommandAsync } from "../utils.js";
|
|
4
3
|
import { PRESETS, detectPreset, getPreset } from "../presets/index.js";
|
|
5
4
|
import { fetchTemplate } from "../presets/source.js";
|
|
6
|
-
import {
|
|
5
|
+
import { adaptFile, changesFor, fileEntries, patchEntries, readManifest } from "../presets/template.js";
|
|
7
6
|
import { collectConnectionFromEnv, collectConnectionInteractively, dirPath, nextStepsNote, orCancel, setupLocalWordPress, syncRemote, validate, withApiPath, writeEnv } from "./_setup.js";
|
|
8
7
|
import { applyLayoutPatches, buildScaffoldContext, kizloConfigTemplate, reportScaffold, scaffoldFile, writeGeneratedContract } from "./_wiring.js";
|
|
9
8
|
import path from "node:path";
|
|
@@ -98,13 +97,13 @@ function isOlder(have, want) {
|
|
|
98
97
|
* When the project's kizlo is older, upgrade the project up to it and say so — a deliberate pin is
|
|
99
98
|
* never changed silently. Never downgrades.
|
|
100
99
|
*/
|
|
101
|
-
function alignKizloVersion(cwd, pm, pkg, manifest) {
|
|
100
|
+
async function alignKizloVersion(cwd, pm, pkg, manifest) {
|
|
102
101
|
const want = manifest.kizloVersion ?? `^${getVersion()}`;
|
|
103
102
|
const have = kizloDep(pkg);
|
|
104
103
|
if (!have || !isOlder(have, want)) return;
|
|
105
104
|
const s = p.spinner();
|
|
106
105
|
s.start(`Upgrading kizlo from ${have} to ${want}`);
|
|
107
|
-
const ok =
|
|
106
|
+
const ok = await runCommandAsync(addDependencyArgs(pm, `kizlo@${want}`), cwd, "ignore");
|
|
108
107
|
s.stop(ok ? `Upgraded kizlo to ${want}` : `Could not upgrade kizlo automatically — install kizlo@${want} yourself`);
|
|
109
108
|
}
|
|
110
109
|
const init = defineCommand({
|
|
@@ -139,10 +138,17 @@ const init = defineCommand({
|
|
|
139
138
|
const force = Boolean(args.force);
|
|
140
139
|
const cwd = process.cwd();
|
|
141
140
|
const pkgPath = path.join(cwd, "package.json");
|
|
142
|
-
|
|
143
|
-
p.intro("kizlo init");
|
|
141
|
+
p.intro(`Let's configure Kizlo in your existing application`);
|
|
144
142
|
if (!fs.existsSync(pkgPath)) {
|
|
145
|
-
p.
|
|
143
|
+
p.note([
|
|
144
|
+
"`kizlo init` adds Kizlo to an existing app, but this directory has no package.json.",
|
|
145
|
+
"",
|
|
146
|
+
"Start a new project (scaffolds an app with Kizlo already wired):",
|
|
147
|
+
" npx kizlo@latest create",
|
|
148
|
+
"",
|
|
149
|
+
"Already have an app? cd into it, then run `kizlo init` again."
|
|
150
|
+
].join("\n"), "Nothing to configure here");
|
|
151
|
+
p.cancel("No package.json found in this directory.");
|
|
146
152
|
process.exit(1);
|
|
147
153
|
}
|
|
148
154
|
const pkg = readPkg(pkgPath);
|
|
@@ -191,7 +197,7 @@ const init = defineCommand({
|
|
|
191
197
|
const spec = `kizlo@^${getVersion()}`;
|
|
192
198
|
const s = p.spinner();
|
|
193
199
|
s.start(`Installing kizlo with ${pm}`);
|
|
194
|
-
const ok =
|
|
200
|
+
const ok = await runCommandAsync(addDependencyArgs(pm, spec), cwd, "ignore");
|
|
195
201
|
s.stop(ok ? "Installed kizlo" : "Could not install kizlo automatically");
|
|
196
202
|
if (!ok) p.log.warn(`Install it yourself: ${addDependencyArgs(pm, spec).join(" ")}`);
|
|
197
203
|
}
|
|
@@ -221,8 +227,8 @@ const init = defineCommand({
|
|
|
221
227
|
const fetched = await fetchTemplate(preset.template);
|
|
222
228
|
try {
|
|
223
229
|
manifest = readManifest(fetched.dir);
|
|
224
|
-
alignKizloVersion(cwd, pm, pkg, manifest);
|
|
225
|
-
for (const entry of
|
|
230
|
+
await alignKizloVersion(cwd, pm, pkg, manifest);
|
|
231
|
+
for (const entry of fileEntries(changesFor(manifest, "init"))) files.push(adaptFile(fetched.dir, entry, manifest.conventions, scaffold));
|
|
226
232
|
} finally {
|
|
227
233
|
fetched.cleanup();
|
|
228
234
|
}
|
|
@@ -238,9 +244,9 @@ const init = defineCommand({
|
|
|
238
244
|
writeGeneratedContract(cwd, serverDirRel);
|
|
239
245
|
const gitignore = ensureGitignored(cwd, ".env");
|
|
240
246
|
for (const { file, result } of scaffolded) reportScaffold(file, result, yes);
|
|
241
|
-
if (manifest) applyLayoutPatches(cwd, manifest, scaffold);
|
|
247
|
+
if (manifest) applyLayoutPatches(cwd, patchEntries(changesFor(manifest, "init")), manifest.conventions, scaffold);
|
|
242
248
|
if (gitignore !== "present") p.log.success(`${gitignore === "created" ? "Created" : "Updated"} .gitignore (ignoring .env)`);
|
|
243
|
-
nextStepsNote(setup
|
|
249
|
+
nextStepsNote(setup);
|
|
244
250
|
p.outro("Kizlo is ready 🎉");
|
|
245
251
|
}
|
|
246
252
|
});
|
|
@@ -118,10 +118,20 @@ async function resolveTestConfig(cwd) {
|
|
|
118
118
|
};
|
|
119
119
|
}
|
|
120
120
|
/**
|
|
121
|
+
* Whether a local WordPress dev stack is configured (`dev.path` is set). When false, `kizlo dev`
|
|
122
|
+
* has no stack to boot and runs the contract watcher alone — the path a bring-your-own-WordPress
|
|
123
|
+
* project takes. Loads `kizlo.config.*` from the config dir; a missing config counts as no stack.
|
|
124
|
+
*/
|
|
125
|
+
async function hasDevStack(cwd) {
|
|
126
|
+
const fileConfig = await loadConfigFile(findConfigDir(cwd));
|
|
127
|
+
return Boolean(fileConfig?.dev?.path);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
121
130
|
* Resolve the `dev` block from `kizlo.config.*` into concrete values for the `dev`
|
|
122
131
|
* command, applying defaults (port 8080). `dev.path` is required — the whole
|
|
123
132
|
* WordPress install lives there, so we make the user choose a real folder rather
|
|
124
|
-
* than hide it under a default.
|
|
133
|
+
* than hide it under a default. Callers gate on {@link hasDevStack} first, since a
|
|
134
|
+
* project without a local stack runs the watcher alone rather than reaching here.
|
|
125
135
|
*/
|
|
126
136
|
async function resolveDevConfig(cwd) {
|
|
127
137
|
const configDir = findConfigDir(cwd);
|
|
@@ -150,4 +160,4 @@ async function resolveDevConfig(cwd) {
|
|
|
150
160
|
}
|
|
151
161
|
|
|
152
162
|
//#endregion
|
|
153
|
-
export { DEFAULT_DEV_DB_PORT, DEFAULT_DEV_PORT, resolveConfig, resolveDevConfig, resolveStackName, resolveTestConfig };
|
|
163
|
+
export { DEFAULT_DEV_DB_PORT, DEFAULT_DEV_PORT, hasDevStack, resolveConfig, resolveDevConfig, resolveStackName, resolveTestConfig };
|
package/dist/cli/daemon/watch.js
CHANGED
|
@@ -37,10 +37,10 @@ async function watch(cfg) {
|
|
|
37
37
|
/**
|
|
38
38
|
* Acquire the single-instance lock, generate the contract once, and start the file
|
|
39
39
|
* watcher. Returns a synchronous `stop()` that closes the watcher and releases the
|
|
40
|
-
* lock — or `undefined` when another watcher already holds the lock (a
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
40
|
+
* lock — or `undefined` when another watcher already holds the lock (a framework dev
|
|
41
|
+
* script, or a second `kizlo dev`), in which case the caller carries on without
|
|
42
|
+
* watching. Used by `kizlo dev`, both when it boots a local stack and when it runs
|
|
43
|
+
* the watcher alone, so a single terminal covers the whole dev loop.
|
|
44
44
|
*/
|
|
45
45
|
async function startWatcher(cwd, opts) {
|
|
46
46
|
const lock = lockPath(cwd);
|
package/dist/cli/index.js
CHANGED
|
@@ -12,7 +12,6 @@ runMain(defineCommand({
|
|
|
12
12
|
subCommands: {
|
|
13
13
|
create: () => import("./commands/create.js").then((m) => m.create),
|
|
14
14
|
init: () => import("./commands/init.js").then((m) => m.init),
|
|
15
|
-
watch: () => import("./commands/watch.js").then((m) => m.watch),
|
|
16
15
|
generate: () => import("./commands/generate.js").then((m) => m.generate),
|
|
17
16
|
dev: () => import("./commands/dev.js").then((m) => m.dev),
|
|
18
17
|
test: () => import("./commands/test.js").then((m) => m.test)
|
|
@@ -5,28 +5,39 @@ import fs from "node:fs";
|
|
|
5
5
|
|
|
6
6
|
//#region src/cli/presets/template.ts
|
|
7
7
|
/**
|
|
8
|
-
* The template's `template.json`. It is the single declaration of
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* strategy is unrepresentable:
|
|
8
|
+
* The template's `template.json`. It is the single declaration of what Kizlo lays onto a project and
|
|
9
|
+
* how — the same engine drives both `create` (onto a fresh app the framework CLI just bootstrapped)
|
|
10
|
+
* and `init` (onto the user's existing project). Changes are grouped into three sections so a command
|
|
11
|
+
* only ever applies what is safe for it:
|
|
13
12
|
*
|
|
14
|
-
* - `
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* - `
|
|
13
|
+
* - `base` — applied by both commands: the Kizlo plumbing (server entry, client, routes). Every
|
|
14
|
+
* change here must be safe on an existing project, so it is limited to files Kizlo owns, which
|
|
15
|
+
* never collide with the user's pages.
|
|
16
|
+
* - `create` — applied only by `create`, onto a freshly bootstrapped app it may freely overwrite:
|
|
17
|
+
* the root layout (written whole, already SEO-wired) and its styles as core wiring, plus the demo
|
|
18
|
+
* pages flagged `example`, which are written only when the user asks for example pages.
|
|
19
|
+
* - `init` — applied only by `init`, onto the user's existing project. The root-layout SEO wiring
|
|
20
|
+
* lands here as a `patch` so it merges into the layout the user already owns instead of replacing it.
|
|
21
|
+
*
|
|
22
|
+
* Each section is a list of changes, every one a member of a small closed set — deliberately no
|
|
23
|
+
* "patch an arbitrary source file" kind, so a dangerous strategy is unrepresentable:
|
|
24
|
+
*
|
|
25
|
+
* - `file` — a whole file Kizlo writes, adapted to the project's directories and written through the
|
|
26
|
+
* overwrite policy.
|
|
27
|
+
* - `patch` — a partial injection into a file the framework owns (the root layout's SEO exports):
|
|
28
|
+
* it adds or replaces individual modules (imports/exports) inside the file, never the whole file.
|
|
18
29
|
* Both commands try a confident apply, otherwise print the payload with placement instructions.
|
|
19
30
|
*/
|
|
20
|
-
const
|
|
31
|
+
const conventionsSchema = z.object({
|
|
21
32
|
kizloDir: z.string(),
|
|
22
33
|
appDir: z.string(),
|
|
23
34
|
alias: z.string()
|
|
24
35
|
});
|
|
25
|
-
const
|
|
26
|
-
kind: z.literal("
|
|
36
|
+
const fileSchema = z.object({
|
|
37
|
+
kind: z.literal("file"),
|
|
27
38
|
role: z.string(),
|
|
28
39
|
path: z.string(),
|
|
29
|
-
|
|
40
|
+
example: z.boolean().optional()
|
|
30
41
|
});
|
|
31
42
|
const patchSchema = z.object({
|
|
32
43
|
kind: z.literal("patch"),
|
|
@@ -46,12 +57,15 @@ const bootstrapSchema = z.object({
|
|
|
46
57
|
initializer: z.string(),
|
|
47
58
|
flags: z.array(z.string()).default([])
|
|
48
59
|
});
|
|
60
|
+
const changeSchema = z.discriminatedUnion("kind", [fileSchema, patchSchema]);
|
|
49
61
|
const manifestSchema = z.object({
|
|
50
62
|
framework: z.string(),
|
|
51
63
|
kizloVersion: z.string().optional(),
|
|
52
64
|
bootstrap: bootstrapSchema.optional(),
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
conventions: conventionsSchema,
|
|
66
|
+
base: z.array(changeSchema).default([]),
|
|
67
|
+
create: z.array(changeSchema).default([]),
|
|
68
|
+
init: z.array(changeSchema).default([])
|
|
55
69
|
});
|
|
56
70
|
/** Role → the human label init uses in prompts and logs. */
|
|
57
71
|
const ROLE_LABELS = {
|
|
@@ -62,6 +76,7 @@ const ROLE_LABELS = {
|
|
|
62
76
|
sitemap: "sitemap route",
|
|
63
77
|
"sitemap-redirect": "sitemap.xml redirect route",
|
|
64
78
|
manifest: "web manifest route",
|
|
79
|
+
"root-layout": "root layout",
|
|
65
80
|
"home-page": "home page",
|
|
66
81
|
"blog-post": "blog post page",
|
|
67
82
|
styles: "global styles"
|
|
@@ -73,55 +88,64 @@ function readManifest(templateDir) {
|
|
|
73
88
|
return manifestSchema.parse(JSON.parse(fs.readFileSync(manifestPath, "utf8")));
|
|
74
89
|
}
|
|
75
90
|
/**
|
|
76
|
-
* The
|
|
77
|
-
* `
|
|
78
|
-
*
|
|
91
|
+
* The changes a command applies: the shared `base` set plus the command's own section. `create` gets
|
|
92
|
+
* `base + create` (plumbing plus the demo pages); `init` gets `base + init` (plumbing plus any
|
|
93
|
+
* init-only surgical patches). `base` is applied first so a later section can override it.
|
|
79
94
|
*/
|
|
80
|
-
function
|
|
81
|
-
return manifest.
|
|
95
|
+
function changesFor(manifest, command) {
|
|
96
|
+
return [...manifest.base, ...manifest[command]];
|
|
97
|
+
}
|
|
98
|
+
/** The whole-file changes in a resolved change list. */
|
|
99
|
+
function fileEntries(changes) {
|
|
100
|
+
return changes.filter((change) => change.kind === "file");
|
|
101
|
+
}
|
|
102
|
+
/** The partial-injection changes in a resolved change list. */
|
|
103
|
+
function patchEntries(changes) {
|
|
104
|
+
return changes.filter((change) => change.kind === "patch");
|
|
82
105
|
}
|
|
83
|
-
|
|
84
|
-
|
|
106
|
+
/** Whether a change is opt-in demo content — written by `create` only when example pages are requested. */
|
|
107
|
+
function isExample(change) {
|
|
108
|
+
return change.kind === "file" && change.example === true;
|
|
85
109
|
}
|
|
86
110
|
/** The specifier the template's files use to reach the server entry, e.g. `@/lib/kizlo/server`. */
|
|
87
|
-
function serverImportSpecifier(
|
|
88
|
-
const withoutSrc =
|
|
89
|
-
return `${
|
|
111
|
+
function serverImportSpecifier(conventions) {
|
|
112
|
+
const withoutSrc = conventions.kizloDir.replace(/^src\//, "");
|
|
113
|
+
return `${conventions.alias.replace(/\/+$/, "")}/${withoutSrc}/server`;
|
|
90
114
|
}
|
|
91
115
|
/**
|
|
92
116
|
* Adapt a template path prefix (`src/app/...`, `src/lib/kizlo/...`) to the project's real directories.
|
|
93
|
-
* Only the leading
|
|
117
|
+
* Only the leading convention dir is swapped; the rest of the path is preserved verbatim.
|
|
94
118
|
*/
|
|
95
|
-
function adaptTemplatePath(relPath,
|
|
119
|
+
function adaptTemplatePath(relPath, conventions, ctx) {
|
|
96
120
|
const normalized = relPath.split(path.sep).join("/");
|
|
97
|
-
if (normalized ===
|
|
98
|
-
if (normalized ===
|
|
121
|
+
if (normalized === conventions.appDir || normalized.startsWith(`${conventions.appDir}/`)) return `${ctx.appDir}${normalized.slice(conventions.appDir.length)}`;
|
|
122
|
+
if (normalized === conventions.kizloDir || normalized.startsWith(`${conventions.kizloDir}/`)) return `${ctx.kizloDir}${normalized.slice(conventions.kizloDir.length)}`;
|
|
99
123
|
return normalized;
|
|
100
124
|
}
|
|
101
125
|
/**
|
|
102
|
-
* Turn
|
|
126
|
+
* Turn a `file` manifest entry into the {@link ScaffoldFile} init writes: read the template's real
|
|
103
127
|
* file, rewrite its path prefix to the project's directories, and swap the server-entry import
|
|
104
128
|
* specifier for the one resolved at the file's new location (tsconfig alias or relative). The swap is
|
|
105
129
|
* surgical — it replaces the exact specifier the template uses, not a loose directory substring — so
|
|
106
130
|
* an unrelated occurrence can't be corrupted. This is the job the old build-time extractor did; it
|
|
107
131
|
* moves to runtime and stays as precise.
|
|
108
132
|
*/
|
|
109
|
-
function
|
|
133
|
+
function adaptFile(templateDir, entry, conventions, ctx) {
|
|
110
134
|
const abs = path.join(templateDir, entry.path);
|
|
111
135
|
if (!fs.existsSync(abs)) throw new Error(`Template file "${entry.path}" is listed in the manifest but does not exist in the template.`);
|
|
112
136
|
const body = fs.readFileSync(abs, "utf8");
|
|
113
|
-
const relPath = adaptTemplatePath(entry.path,
|
|
137
|
+
const relPath = adaptTemplatePath(entry.path, conventions, ctx);
|
|
114
138
|
const fromDir = path.posix.dirname(relPath);
|
|
115
|
-
const contents = body.split(serverImportSpecifier(
|
|
139
|
+
const contents = body.split(serverImportSpecifier(conventions)).join(ctx.serverImport(fromDir));
|
|
116
140
|
return {
|
|
117
141
|
label: ROLE_LABELS[entry.role] ?? entry.role,
|
|
118
142
|
relPath,
|
|
119
143
|
contents
|
|
120
144
|
};
|
|
121
145
|
}
|
|
122
|
-
/**
|
|
123
|
-
function resolvePatch(entry,
|
|
124
|
-
const relPath = adaptTemplatePath(entry.path,
|
|
146
|
+
/** Adapt a patch's path prefix and server-import specifier to the project's real directories. */
|
|
147
|
+
function resolvePatch(entry, conventions, ctx) {
|
|
148
|
+
const relPath = adaptTemplatePath(entry.path, conventions, ctx);
|
|
125
149
|
const fromDir = path.posix.dirname(relPath);
|
|
126
150
|
const imports = entry.imports.map((imp) => ({
|
|
127
151
|
module: imp.module.replaceAll("{{serverImport}}", ctx.serverImport(fromDir)),
|
|
@@ -169,4 +193,4 @@ function rendersHtml(file) {
|
|
|
169
193
|
}
|
|
170
194
|
|
|
171
195
|
//#endregion
|
|
172
|
-
export {
|
|
196
|
+
export { adaptFile, changesFor, fileEntries, findRootLayout, isExample, patchEntries, readManifest, resolvePatch };
|
package/dist/cli/utils.js
CHANGED
|
@@ -87,7 +87,7 @@ function resolveModuleImport(cwd, targetRel, fromDirRel, alias) {
|
|
|
87
87
|
}
|
|
88
88
|
/**
|
|
89
89
|
* Loads the project's `.env` files into `process.env`. The single place env
|
|
90
|
-
* values come from — shared by `init --yes` and the `kizlo
|
|
90
|
+
* values come from — shared by `init --yes` and the `kizlo dev`/`generate`
|
|
91
91
|
* daemon so they always read the same source.
|
|
92
92
|
*/
|
|
93
93
|
function loadEnvFiles(cwd) {
|
|
@@ -180,15 +180,6 @@ function frameworkCreateArgs(pm, initializer, name, flags) {
|
|
|
180
180
|
];
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
|
-
function runCommand(args, cwd, stdio = "inherit") {
|
|
184
|
-
const [command, ...rest] = args;
|
|
185
|
-
if (!command) return false;
|
|
186
|
-
return spawnSync(command, rest, {
|
|
187
|
-
cwd,
|
|
188
|
-
stdio,
|
|
189
|
-
shell: process.platform === "win32"
|
|
190
|
-
}).status === 0;
|
|
191
|
-
}
|
|
192
183
|
/**
|
|
193
184
|
* Async sibling of {@link runCommand}: runs a command without blocking the event loop, so a clack
|
|
194
185
|
* spinner can keep animating while it works (a synchronous `spawnSync` would freeze it on the first
|
|
@@ -363,4 +354,4 @@ function groupDefault(subCommandNames, run) {
|
|
|
363
354
|
}
|
|
364
355
|
|
|
365
356
|
//#endregion
|
|
366
|
-
export { addDependencyArgs, availablePackageManagers, detectImportAlias, detectInvokingPackageManager, detectPackageManager, ensureGitignored, envGroups, envKeysPresent, frameworkCreateArgs, getVersion, groupDefault, installArgs, loadEnvFiles, mergeEnv, pickStackPort, resolveModuleImport,
|
|
357
|
+
export { addDependencyArgs, availablePackageManagers, detectImportAlias, detectInvokingPackageManager, detectPackageManager, ensureGitignored, envGroups, envKeysPresent, frameworkCreateArgs, getVersion, groupDefault, installArgs, loadEnvFiles, mergeEnv, pickStackPort, resolveModuleImport, runCommandAsync, runCommandCaptured, withSpinner, writeFileIfAbsent };
|
package/dist/cli/wp/dev.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WordPressService } from "../../wordpress/service.js";
|
|
2
2
|
import { DEFAULT_PLUGINS, TEST_ADMIN } from "./constants.js";
|
|
3
|
-
import { compose, composeUp, wpCli } from "./docker.js";
|
|
3
|
+
import { compose, composePull, composeUp, wpCli } from "./docker.js";
|
|
4
4
|
import { ensurePlugins } from "./utils.js";
|
|
5
5
|
import { createAdminAppPassword, seedUsers } from "./bootstrap.js";
|
|
6
6
|
import { prepareByo } from "./byo.js";
|
|
@@ -74,7 +74,9 @@ async function seedDevFixtures(cfg, url) {
|
|
|
74
74
|
*/
|
|
75
75
|
async function bootstrapDev(cfg) {
|
|
76
76
|
const url = devUrl(cfg.port);
|
|
77
|
-
const
|
|
77
|
+
const fresh = !existsSync(join(cfg.wordpressDir, "wp-includes", "version.php"));
|
|
78
|
+
const byo = fresh && cfg.byo ? await prepareByo(cfg.byo, cfg.wordpressDir, cfg.configDir) : void 0;
|
|
79
|
+
if (fresh && !byo) await composePull(["wordpress", "wp-cli"]).catch(() => void 0);
|
|
78
80
|
await composeUp();
|
|
79
81
|
const installed = (await compose([
|
|
80
82
|
"exec",
|
package/dist/cli/wp/docker.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ interface Stack {
|
|
|
22
22
|
/** Stack-bound docker helpers. */
|
|
23
23
|
interface DockerStack {
|
|
24
24
|
compose(args: string[], opts?: RunInput): Promise<RunResult>;
|
|
25
|
+
/** Pull the latest images for the named services (all when omitted) — refreshes a cached tag like `wordpress:latest`. */
|
|
26
|
+
composePull(services?: string[]): Promise<RunResult>;
|
|
25
27
|
composeUp(): Promise<void>;
|
|
26
28
|
composeStop(opts?: {
|
|
27
29
|
detached?: boolean;
|
|
@@ -48,6 +50,8 @@ declare function dockerAvailable(): Promise<boolean>;
|
|
|
48
50
|
declare function createStack(stack: Stack): DockerStack;
|
|
49
51
|
/** `docker compose <args>` against the active stack. */
|
|
50
52
|
declare const compose: DockerStack["compose"];
|
|
53
|
+
/** Pull the latest images for the active stack's named services (all when omitted). */
|
|
54
|
+
declare const composePull: (services?: string[]) => Promise<RunResult>;
|
|
51
55
|
/** Bring the active stack's services up detached and wait for health checks. */
|
|
52
56
|
declare const composeUp: () => Promise<void>;
|
|
53
57
|
/** Tear the active stack down, optionally removing volumes. */
|
|
@@ -61,4 +65,4 @@ declare const composeStop: (opts?: {
|
|
|
61
65
|
/** Run a wp-cli command against the active stack's warm `wp-cli` container. */
|
|
62
66
|
declare const wpCli: (args: string[]) => Promise<string>;
|
|
63
67
|
//#endregion
|
|
64
|
-
export { DockerStack, RunResult, Stack, compose, composeDown, composeStop, composeUp, createStack, dockerAvailable, wpCli };
|
|
68
|
+
export { DockerStack, RunResult, Stack, compose, composeDown, composePull, composeStop, composeUp, createStack, dockerAvailable, wpCli };
|
package/dist/cli/wp/docker.js
CHANGED
|
@@ -56,6 +56,7 @@ function bind(stack) {
|
|
|
56
56
|
WP_PORT: String(stack.port)
|
|
57
57
|
};
|
|
58
58
|
const compose$1 = (args, opts) => run("docker", [...base, ...args], env, opts);
|
|
59
|
+
const composePull$1 = (services = []) => compose$1(["pull", ...services]);
|
|
59
60
|
const composeUp$1 = async () => {
|
|
60
61
|
const res = await compose$1([
|
|
61
62
|
"up",
|
|
@@ -93,6 +94,7 @@ function bind(stack) {
|
|
|
93
94
|
};
|
|
94
95
|
return {
|
|
95
96
|
compose: compose$1,
|
|
97
|
+
composePull: composePull$1,
|
|
96
98
|
composeUp: composeUp$1,
|
|
97
99
|
composeStop: composeStop$1,
|
|
98
100
|
composeDown: composeDown$1,
|
|
@@ -117,6 +119,8 @@ function activeStack() {
|
|
|
117
119
|
}
|
|
118
120
|
/** `docker compose <args>` against the active stack. */
|
|
119
121
|
const compose = (args, opts) => activeStack().compose(args, opts);
|
|
122
|
+
/** Pull the latest images for the active stack's named services (all when omitted). */
|
|
123
|
+
const composePull = (services) => activeStack().composePull(services);
|
|
120
124
|
/** Bring the active stack's services up detached and wait for health checks. */
|
|
121
125
|
const composeUp = () => activeStack().composeUp();
|
|
122
126
|
/** Tear the active stack down, optionally removing volumes. */
|
|
@@ -127,4 +131,4 @@ const composeStop = (opts) => activeStack().composeStop(opts);
|
|
|
127
131
|
const wpCli = (args) => activeStack().wpCli(args);
|
|
128
132
|
|
|
129
133
|
//#endregion
|
|
130
|
-
export { compose, composeDown, composeStop, composeUp, createStack, dockerAvailable, wpCli };
|
|
134
|
+
export { compose, composeDown, composePull, composeStop, composeUp, createStack, dockerAvailable, wpCli };
|
package/dist/package.js
CHANGED
package/dist/router.d.ts
CHANGED
|
@@ -179,7 +179,7 @@ declare const ROUTER_MAP: {
|
|
|
179
179
|
include?: string | number | (string | number)[] | undefined;
|
|
180
180
|
offset?: string | number | undefined;
|
|
181
181
|
order?: "asc" | "desc" | undefined;
|
|
182
|
-
orderby?: "
|
|
182
|
+
orderby?: "id" | "date" | "slug" | "parent" | "title" | "author" | "include" | "modified" | "relevance" | "include_slugs" | undefined;
|
|
183
183
|
searchColumns?: ("post_title" | "post_content" | "post_excerpt")[] | undefined;
|
|
184
184
|
slug?: string | string[] | undefined;
|
|
185
185
|
taxRelation?: "AND" | "OR" | undefined;
|
|
@@ -507,7 +507,7 @@ declare const ROUTER_MAP: {
|
|
|
507
507
|
include?: string | number | (string | number)[] | undefined;
|
|
508
508
|
offset?: string | number | undefined;
|
|
509
509
|
order?: "asc" | "desc" | undefined;
|
|
510
|
-
orderby?: "
|
|
510
|
+
orderby?: "id" | "date" | "slug" | "parent" | "title" | "author" | "include" | "modified" | "relevance" | "include_slugs" | "menu_order" | undefined;
|
|
511
511
|
searchColumns?: ("post_title" | "post_content" | "post_excerpt")[] | undefined;
|
|
512
512
|
slug?: string | string[] | undefined;
|
|
513
513
|
parent?: string | number | (string | number)[] | undefined;
|
|
@@ -764,7 +764,7 @@ declare const ROUTER_MAP: {
|
|
|
764
764
|
exclude?: string | number | (string | number)[] | undefined;
|
|
765
765
|
include?: string | number | (string | number)[] | undefined;
|
|
766
766
|
order?: "asc" | "desc" | undefined;
|
|
767
|
-
orderBy?: "
|
|
767
|
+
orderBy?: "id" | "slug" | "name" | "description" | "include" | "include_slugs" | "term_group" | "count" | undefined;
|
|
768
768
|
hideEmpty?: string | boolean | undefined;
|
|
769
769
|
parent?: string | number | undefined;
|
|
770
770
|
post?: string | number | undefined;
|
|
@@ -976,7 +976,7 @@ declare const ROUTER_MAP: {
|
|
|
976
976
|
exclude?: string | number | (string | number)[] | undefined;
|
|
977
977
|
include?: string | number | (string | number)[] | undefined;
|
|
978
978
|
order?: "asc" | "desc" | undefined;
|
|
979
|
-
orderBy?: "
|
|
979
|
+
orderBy?: "id" | "slug" | "name" | "description" | "include" | "include_slugs" | "term_group" | "count" | undefined;
|
|
980
980
|
hideEmpty?: string | boolean | undefined;
|
|
981
981
|
post?: string | number | undefined;
|
|
982
982
|
slug?: string | string[] | undefined;
|
|
@@ -1135,7 +1135,7 @@ declare const ROUTER_MAP: {
|
|
|
1135
1135
|
sitemaps: {
|
|
1136
1136
|
list: Procedure<"internal", {}, {
|
|
1137
1137
|
key: string;
|
|
1138
|
-
type: "
|
|
1138
|
+
type: "author" | "post_type" | "taxonomy";
|
|
1139
1139
|
pages: number;
|
|
1140
1140
|
lastmod: string;
|
|
1141
1141
|
}[], DefinedErrorMapLike>;
|
|
@@ -1143,7 +1143,7 @@ declare const ROUTER_MAP: {
|
|
|
1143
1143
|
origin: string;
|
|
1144
1144
|
sitemaps: {
|
|
1145
1145
|
key: string;
|
|
1146
|
-
type: "
|
|
1146
|
+
type: "author" | "post_type" | "taxonomy";
|
|
1147
1147
|
pages: number;
|
|
1148
1148
|
lastmod: string;
|
|
1149
1149
|
}[];
|
|
@@ -1186,7 +1186,7 @@ declare const ROUTER_MAP: {
|
|
|
1186
1186
|
include?: string | number | (string | number)[] | undefined;
|
|
1187
1187
|
offset?: string | number | undefined;
|
|
1188
1188
|
order?: "asc" | "desc" | undefined;
|
|
1189
|
-
orderby?: "
|
|
1189
|
+
orderby?: "id" | "date" | "slug" | "parent" | "title" | "author" | "include" | "relevance" | "include_slugs" | "menu_order" | undefined;
|
|
1190
1190
|
searchColumns?: ("post_title" | "post_content" | "post_excerpt")[] | undefined;
|
|
1191
1191
|
slug?: string | string[] | undefined;
|
|
1192
1192
|
taxRelation?: "AND" | "OR" | undefined;
|
|
@@ -1265,7 +1265,7 @@ declare const ROUTER_MAP: {
|
|
|
1265
1265
|
include?: string | number | (string | number)[] | undefined;
|
|
1266
1266
|
offset?: string | number | undefined;
|
|
1267
1267
|
order?: "asc" | "desc" | undefined;
|
|
1268
|
-
orderby?: "
|
|
1268
|
+
orderby?: "id" | "date" | "slug" | "parent" | "title" | "author" | "include" | "relevance" | "include_slugs" | "menu_order" | undefined;
|
|
1269
1269
|
searchColumns?: ("post_title" | "post_content" | "post_excerpt")[] | undefined;
|
|
1270
1270
|
slug?: string | string[] | undefined;
|
|
1271
1271
|
taxRelation?: "AND" | "OR" | undefined;
|
|
@@ -1414,7 +1414,7 @@ declare const ROUTER_MAP: {
|
|
|
1414
1414
|
include?: string | number | (string | number)[] | undefined;
|
|
1415
1415
|
offset?: string | number | undefined;
|
|
1416
1416
|
order?: "asc" | "desc" | undefined;
|
|
1417
|
-
orderby?: "
|
|
1417
|
+
orderby?: "id" | "date" | "parent" | "post" | "include" | undefined;
|
|
1418
1418
|
parent?: string | number | (string | number)[] | undefined;
|
|
1419
1419
|
parentExclude?: string | number | (string | number)[] | undefined;
|
|
1420
1420
|
post?: string | number | (string | number)[] | undefined;
|
package/dist/seo/schema.d.ts
CHANGED
|
@@ -108,17 +108,17 @@ declare const Seo: z.ZodObject<{
|
|
|
108
108
|
type Seo = z.infer<typeof Seo>;
|
|
109
109
|
declare const CONTENT_TYPES: readonly ["post_type", "taxonomy", "author"];
|
|
110
110
|
declare const ContentType: z.ZodEnum<{
|
|
111
|
+
author: "author";
|
|
111
112
|
post_type: "post_type";
|
|
112
113
|
taxonomy: "taxonomy";
|
|
113
|
-
author: "author";
|
|
114
114
|
}>;
|
|
115
115
|
type ContentType = z.infer<typeof ContentType>;
|
|
116
116
|
declare const Sitemap: z.ZodObject<{
|
|
117
117
|
key: z.ZodString;
|
|
118
118
|
type: z.ZodEnum<{
|
|
119
|
+
author: "author";
|
|
119
120
|
post_type: "post_type";
|
|
120
121
|
taxonomy: "taxonomy";
|
|
121
|
-
author: "author";
|
|
122
122
|
}>;
|
|
123
123
|
pages: z.ZodNumber;
|
|
124
124
|
lastmod: z.ZodString;
|
|
@@ -127,9 +127,9 @@ type Sitemap = z.infer<typeof Sitemap>;
|
|
|
127
127
|
declare const SitemapList: z.ZodArray<z.ZodObject<{
|
|
128
128
|
key: z.ZodString;
|
|
129
129
|
type: z.ZodEnum<{
|
|
130
|
+
author: "author";
|
|
130
131
|
post_type: "post_type";
|
|
131
132
|
taxonomy: "taxonomy";
|
|
132
|
-
author: "author";
|
|
133
133
|
}>;
|
|
134
134
|
pages: z.ZodNumber;
|
|
135
135
|
lastmod: z.ZodString;
|
|
@@ -140,9 +140,9 @@ declare const SitemapIndex: z.ZodObject<{
|
|
|
140
140
|
sitemaps: z.ZodArray<z.ZodObject<{
|
|
141
141
|
key: z.ZodString;
|
|
142
142
|
type: z.ZodEnum<{
|
|
143
|
+
author: "author";
|
|
143
144
|
post_type: "post_type";
|
|
144
145
|
taxonomy: "taxonomy";
|
|
145
|
-
author: "author";
|
|
146
146
|
}>;
|
|
147
147
|
pages: z.ZodNumber;
|
|
148
148
|
lastmod: z.ZodString;
|
|
@@ -174,9 +174,9 @@ declare const SitemapUrlList: z.ZodArray<z.ZodObject<{
|
|
|
174
174
|
type SitemapUrlList = z.infer<typeof SitemapUrlList>;
|
|
175
175
|
declare const ListSitemapUrlInputBase: z.ZodObject<{
|
|
176
176
|
type: z.ZodEnum<{
|
|
177
|
+
author: "author";
|
|
177
178
|
post_type: "post_type";
|
|
178
179
|
taxonomy: "taxonomy";
|
|
179
|
-
author: "author";
|
|
180
180
|
}>;
|
|
181
181
|
page: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>, z.ZodCoercedNumber<string | number>>>;
|
|
182
182
|
}, z.core.$strip>;
|
package/dist/test.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DevPluginSource, Fixture, FixtureCleanupFn, FixtureSeedFn, JsonValue, LocalPlugin, PluginSource, SeedContext, TestAdminUser, TestCredentials, TestUser, defineFixture, isLocalPlugin } from "./cli/wp/types.js";
|
|
2
2
|
import { COMPOSE_FILE, CONFIG_FILES, CREDENTIALS_REL, DEFAULT_PLUGINS, DEFAULT_PORT, OPCACHE_INI, REMAP_ENTRYPOINT, SEED_MARKER_OPTION, SEED_VERSION, TEST_ADMIN, TEST_USER, githubRelease, kizloRelease } from "./cli/wp/constants.js";
|
|
3
|
-
import { DockerStack, RunResult, Stack, compose, composeDown, composeStop, composeUp, createStack, dockerAvailable, wpCli } from "./cli/wp/docker.js";
|
|
3
|
+
import { DockerStack, RunResult, Stack, compose, composeDown, composePull, composeStop, composeUp, createStack, dockerAvailable, wpCli } from "./cli/wp/docker.js";
|
|
4
4
|
import { activateLocalPlugin, credentialsPath, ensurePlugin, ensurePlugins, findConfigDir, getTestCredentials, isSeeded, recordedPort, resolvePluginSource } from "./cli/wp/utils.js";
|
|
5
5
|
import { TestAuthAdapterUser, toTestUser } from "./test/users.js";
|
|
6
6
|
import { testAuthAdapter } from "./test/auth.js";
|
|
@@ -10,4 +10,4 @@ import { KizloClientTestInstance, getKizloClientTestInstance } from "./test/clie
|
|
|
10
10
|
import { menuFixture } from "./menu/fixture.js";
|
|
11
11
|
import { postFixture } from "./post/fixture.js";
|
|
12
12
|
import { coreFixtures } from "./test/fixtures.js";
|
|
13
|
-
export { CAPTCHA_TEST_TOKEN_PASS, COMPOSE_FILE, CONFIG_FILES, CREDENTIALS_REL, DEFAULT_PLUGINS, DEFAULT_PORT, DevPluginSource, DockerStack, Fixture, FixtureCleanupFn, FixtureSeedFn, JsonValue, KizloClientTestInstance, KizloTestInstance, LocalPlugin, OPCACHE_INI, PluginSource, REMAP_ENTRYPOINT, RunResult, SEED_MARKER_OPTION, SEED_VERSION, SeedContext, Stack, TEST_ADMIN, TEST_USER, TestAdminUser, TestAuthAdapterUser, TestCredentials, TestUser, activateLocalPlugin, captchaMock, compose, composeDown, composeStop, composeUp, coreFixtures, createStack, credentialsPath, defineFixture, dockerAvailable, ensurePlugin, ensurePlugins, findConfigDir, getKizloClientTestInstance, getKizloTestInstance, getTestCredentials, githubRelease, isLocalPlugin, isSeeded, kizloRelease, menuFixture, postFixture, recordedPort, resolvePluginSource, testAuthAdapter, toTestUser, wpCli };
|
|
13
|
+
export { CAPTCHA_TEST_TOKEN_PASS, COMPOSE_FILE, CONFIG_FILES, CREDENTIALS_REL, DEFAULT_PLUGINS, DEFAULT_PORT, DevPluginSource, DockerStack, Fixture, FixtureCleanupFn, FixtureSeedFn, JsonValue, KizloClientTestInstance, KizloTestInstance, LocalPlugin, OPCACHE_INI, PluginSource, REMAP_ENTRYPOINT, RunResult, SEED_MARKER_OPTION, SEED_VERSION, SeedContext, Stack, TEST_ADMIN, TEST_USER, TestAdminUser, TestAuthAdapterUser, TestCredentials, TestUser, activateLocalPlugin, captchaMock, compose, composeDown, composePull, composeStop, composeUp, coreFixtures, createStack, credentialsPath, defineFixture, dockerAvailable, ensurePlugin, ensurePlugins, findConfigDir, getKizloClientTestInstance, getKizloTestInstance, getTestCredentials, githubRelease, isLocalPlugin, isSeeded, kizloRelease, menuFixture, postFixture, recordedPort, resolvePluginSource, testAuthAdapter, toTestUser, wpCli };
|
package/dist/test.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineFixture, isLocalPlugin } from "./cli/wp/types.js";
|
|
2
2
|
import { COMPOSE_FILE, CONFIG_FILES, CREDENTIALS_REL, DEFAULT_PLUGINS, DEFAULT_PORT, OPCACHE_INI, REMAP_ENTRYPOINT, SEED_MARKER_OPTION, SEED_VERSION, TEST_ADMIN, TEST_USER, githubRelease, kizloRelease } from "./cli/wp/constants.js";
|
|
3
|
-
import { compose, composeDown, composeStop, composeUp, createStack, dockerAvailable, wpCli } from "./cli/wp/docker.js";
|
|
3
|
+
import { compose, composeDown, composePull, composeStop, composeUp, createStack, dockerAvailable, wpCli } from "./cli/wp/docker.js";
|
|
4
4
|
import { activateLocalPlugin, credentialsPath, ensurePlugin, ensurePlugins, findConfigDir, getTestCredentials, isSeeded, recordedPort, resolvePluginSource } from "./cli/wp/utils.js";
|
|
5
5
|
import { testAuthAdapter } from "./test/auth.js";
|
|
6
6
|
import { CAPTCHA_TEST_TOKEN_PASS, captchaMock } from "./test/captcha.js";
|
|
@@ -11,4 +11,4 @@ import { coreFixtures } from "./test/fixtures.js";
|
|
|
11
11
|
import { toTestUser } from "./test/users.js";
|
|
12
12
|
import { getKizloTestInstance } from "./test/server.js";
|
|
13
13
|
|
|
14
|
-
export { CAPTCHA_TEST_TOKEN_PASS, COMPOSE_FILE, CONFIG_FILES, CREDENTIALS_REL, DEFAULT_PLUGINS, DEFAULT_PORT, OPCACHE_INI, REMAP_ENTRYPOINT, SEED_MARKER_OPTION, SEED_VERSION, TEST_ADMIN, TEST_USER, activateLocalPlugin, captchaMock, compose, composeDown, composeStop, composeUp, coreFixtures, createStack, credentialsPath, defineFixture, dockerAvailable, ensurePlugin, ensurePlugins, findConfigDir, getKizloClientTestInstance, getKizloTestInstance, getTestCredentials, githubRelease, isLocalPlugin, isSeeded, kizloRelease, menuFixture, postFixture, recordedPort, resolvePluginSource, testAuthAdapter, toTestUser, wpCli };
|
|
14
|
+
export { CAPTCHA_TEST_TOKEN_PASS, COMPOSE_FILE, CONFIG_FILES, CREDENTIALS_REL, DEFAULT_PLUGINS, DEFAULT_PORT, OPCACHE_INI, REMAP_ENTRYPOINT, SEED_MARKER_OPTION, SEED_VERSION, TEST_ADMIN, TEST_USER, activateLocalPlugin, captchaMock, compose, composeDown, composePull, composeStop, composeUp, coreFixtures, createStack, credentialsPath, defineFixture, dockerAvailable, ensurePlugin, ensurePlugins, findConfigDir, getKizloClientTestInstance, getKizloTestInstance, getTestCredentials, githubRelease, isLocalPlugin, isSeeded, kizloRelease, menuFixture, postFixture, recordedPort, resolvePluginSource, testAuthAdapter, toTestUser, wpCli };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kizlo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A headless WordPress framework for TypeScript.",
|
|
6
6
|
"keywords": [
|
|
@@ -86,6 +86,7 @@
|
|
|
86
86
|
"citty": "^0.1.6",
|
|
87
87
|
"consola": "^3.2.3",
|
|
88
88
|
"cookie": "^1.0.2",
|
|
89
|
+
"get-port": "^7.2.0",
|
|
89
90
|
"giget": "^3.0.0",
|
|
90
91
|
"jiti": "^2.7.0",
|
|
91
92
|
"magicast": "^0.5.3",
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { getVersion } from "../utils.js";
|
|
2
|
-
import { printBanner } from "../banner.js";
|
|
3
|
-
import { startWatcher } from "../daemon/watch.js";
|
|
4
|
-
import { defineCommand } from "citty";
|
|
5
|
-
|
|
6
|
-
//#region src/cli/commands/watch.ts
|
|
7
|
-
const args = { dir: {
|
|
8
|
-
type: "string",
|
|
9
|
-
description: "Override the Kizlo directory (defaults to kizlo.config.ts)"
|
|
10
|
-
} };
|
|
11
|
-
async function run({ args: args$1 }) {
|
|
12
|
-
printBanner(getVersion());
|
|
13
|
-
const stop = await startWatcher(process.cwd(), { dir: args$1.dir });
|
|
14
|
-
if (!stop) return;
|
|
15
|
-
process.on("exit", stop);
|
|
16
|
-
for (const signal of [
|
|
17
|
-
"SIGINT",
|
|
18
|
-
"SIGTERM",
|
|
19
|
-
"SIGHUP"
|
|
20
|
-
]) process.on(signal, () => {
|
|
21
|
-
stop();
|
|
22
|
-
process.exit(0);
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
const watch = defineCommand({
|
|
26
|
-
meta: {
|
|
27
|
-
name: "watch",
|
|
28
|
-
description: "Watch your extensions and regenerate the Kizlo contract"
|
|
29
|
-
},
|
|
30
|
-
args,
|
|
31
|
-
run
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
//#endregion
|
|
35
|
-
export { watch };
|