@woodsportal/hubspot-kit 1.0.30 → 1.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/dist/chunk-4GOJPOW3.js +258 -0
- package/dist/chunk-4GOJPOW3.js.map +1 -0
- package/dist/cli.js +1303 -505
- package/dist/cli.js.map +1 -1
- package/dist/{exec-U2OJATR3.js → exec-VY6BGWF3.js} +6 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/examples/fixtures/adopted-module-hybrid/woodscli.json +1 -1
- package/examples/fixtures/adopted-module-monolith/woodscli.json +1 -1
- package/examples/greenfield/module-hybrid-cdn/public/fields.json +28 -17
- package/examples/greenfield/module-hybrid-cdn/public/meta.json +9 -0
- package/examples/greenfield/module-hybrid-cdn/public/module.html +21 -0
- package/examples/greenfield/module-hybrid-cdn/src/assets/css/main.prod.css +6 -0
- package/examples/greenfield/module-hybrid-cdn/src/cdn/app-entry.ts +10 -0
- package/examples/greenfield/module-hybrid-cdn/src/hubspot/bootstrap.ts +6 -0
- package/examples/greenfield/module-hybrid-cdn/src/portal/api-endpoint.ts +11 -0
- package/examples/greenfield/module-hybrid-cdn/src/portal/ensure-portal-cdn-stylesheet.ts +58 -0
- package/examples/greenfield/module-hybrid-cdn/vite.config.cdn-app.mjs +1 -0
- package/examples/greenfield/module-hybrid-cdn/vite.config.cdn-esm.mjs +1 -0
- package/examples/greenfield/module-hybrid-cdn/vite.config.cdn-vendor.mjs +1 -0
- package/examples/greenfield/module-hybrid-cdn/woodscli.json +1 -1
- package/examples/greenfield/module-monolith/woodscli.json +1 -1
- package/package.json +2 -2
- package/scripts/build-cdn.mjs +17 -8
- package/scripts/bump-module-build-id.mjs +28 -0
- package/scripts/hubspot-module-postbuild.mjs +45 -7
- package/scripts/load-portal-cdn-config.mjs +21 -3
- package/scripts/portal-build-id.mjs +346 -0
- package/scripts/portal-build-id.test.mjs +132 -0
- package/scripts/portal-subprocess-stdio.mjs +38 -0
- package/scripts/publish-cdn-github.mjs +80 -17
- package/scripts/resolve-cdn-base-url.mjs +2 -1
- package/scripts/resolve-module-build-id-meta.mjs +7 -0
- package/scripts/resolve-portal-build-id.mjs +16 -56
- package/scripts/resolve-vite-config.mjs +26 -0
- package/scripts/run-hubspot-module-postbuild.mjs +4 -1
- package/scripts/run-vite-build.mjs +13 -5
- package/scripts/tailwind/prefix-plugin.js +46 -8
- package/scripts/tailwind/tailwind-content-plugin.js +0 -1
- package/scripts/vite/portal-build-shared.js +3 -1
- package/src/dev-module-config/__tests__/flatten-visible-fields.test.ts +107 -0
- package/src/dev-module-config/runtime/module-config-bridge.ts +10 -2
- package/src/dev-module-config/schema/types.ts +10 -0
- package/src/dev-module-config/schema/visibility.ts +42 -4
- package/src/dev-module-config/ui/ModuleConfigShell.tsx +10 -9
- package/src/dev-module-config/ui/hubspot/HsOccurrenceGroupEditor.tsx +3 -3
- package/templates/module-hybrid-cdn/public/fields.json +52 -36
- package/templates/module-hybrid-cdn/public/meta.json +9 -0
- package/templates/module-hybrid-cdn/public/module.html +36 -0
- package/templates/module-hybrid-cdn/src/assets/css/main.dev.css +8 -0
- package/templates/module-hybrid-cdn/src/assets/css/main.prod.css +12 -0
- package/templates/module-hybrid-cdn/src/assets/css/tailwind.css.config.css +7 -0
- package/templates/module-hybrid-cdn/src/cdn/app-entry.ts +18 -2
- package/templates/module-hybrid-cdn/src/features/starter/components/starter-home.tsx +9 -11
- package/templates/module-hybrid-cdn/src/features/starter/hooks/starter-preview-values.ts +23 -5
- package/templates/module-hybrid-cdn/src/features/starter/hooks/use-starter-preview.dev.ts +1 -0
- package/templates/module-hybrid-cdn/src/hubspot/bootstrap.ts +6 -0
- package/templates/module-hybrid-cdn/src/portal/api-endpoint.ts +11 -0
- package/templates/module-hybrid-cdn/src/portal/ensure-portal-cdn-stylesheet.ts +115 -0
- package/templates/module-hybrid-cdn/src/portal/mount-portal.tsx +35 -5
- package/templates/module-hybrid-cdn/vite.config.cdn-app.mjs +1 -0
- package/templates/module-hybrid-cdn/vite.config.cdn-esm.mjs +1 -0
- package/templates/module-hybrid-cdn/vite.config.cdn-vendor.mjs +1 -0
- package/templates/module-hybrid-cdn/woodscli.json +1 -1
- package/templates/module-monolith/public/fields.json +23 -16
- package/templates/module-monolith/public/meta.json +9 -0
- package/templates/module-monolith/src/features/starter/components/starter-home.tsx +9 -11
- package/templates/module-monolith/src/features/starter/hooks/starter-preview-values.ts +23 -5
- package/templates/module-monolith/src/features/starter/hooks/use-starter-preview.dev.ts +1 -0
- package/templates/module-monolith/woodscli.json +1 -1
- package/vite/vite.config.dev.mjs +16 -10
- package/vite/vite.config.hubspot.mjs +8 -2
- package/dist/chunk-GTTIJVAR.js +0 -127
- package/dist/chunk-GTTIJVAR.js.map +0 -1
- /package/dist/{exec-U2OJATR3.js.map → exec-VY6BGWF3.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,57 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
### Module build id (collaborative CDN deploys)
|
|
6
|
+
- **Rename** `.portal-build-id` → `.module-build-id` (channel baseline); `wp migrate --yes` upgrades legacy projects
|
|
7
|
+
- **Auto-bump** on `wp deploy` and `wp build --cdn-only` — `{baseline}.{devSlug}.{seq}` in gitignored `.wphs/state/module-build-id.json`
|
|
8
|
+
- **`--no-bump`** — rebuild/publish without advancing seq; `PORTAL_BUILD_ID` / `MODULE_BUILD_ID` / `GITHUB_REF_NAME` still override
|
|
9
|
+
- **`wp setup`** — prompts for CDN dev slug (`.wphs/config/developer.json`); optional `portal.cdn.local.json` mirror override
|
|
10
|
+
- **`wp publish`** — aborts on remote tag collision (use `--force-tag` only to intentionally overwrite)
|
|
11
|
+
|
|
12
|
+
### Hybrid CDN (module-config overlay)
|
|
13
|
+
- **Content tab** — stop flattening CONTENT-tab groups at shell level; keep `home`, `menu_options`, custom editors, and collapsibles
|
|
14
|
+
- **Styles tab** — expand tab-aligned `style` / `styles` wrapper once with `pathPrefix` for nested style field paths
|
|
15
|
+
- **Starter scaffold** — wrap Content fields in a `content` group; `readContentField` supports grouped + flat module values
|
|
16
|
+
- **`mount-portal.tsx`** — mode-aware `loadCss()` + `MountPortalOptions` (`skipRuntimeCss`, `skipAppRender`)
|
|
17
|
+
- **`cdn/app-entry.ts`** — `mountPortal({ skipRuntimeCss: true })`; editor-only CDN stylesheet fallback via `ensurePortalCdnStylesheetIfNeeded()`
|
|
18
|
+
- **`module.html`** — `{% scope_css %}` reset + `:root` `--starter-accent` for HubSpot pages
|
|
19
|
+
- **CSS entries** — shared `tailwind.css.config.css`; documented never-merge rules on `main.dev.css` / `main.prod.css`
|
|
20
|
+
- **`wp doctor`** — CSS pipeline checks (prefix, `.temp` @source, `skipRuntimeCss`, `module.css` dw utilities, CDN `require_css` warning)
|
|
21
|
+
|
|
22
|
+
## 1.0.33 — 2026-06-08
|
|
23
|
+
|
|
24
|
+
### Dev server
|
|
25
|
+
- **`wp dev`** — resolve Vite and `@vitejs/plugin-react` from the consumer project (not the kit’s `node_modules`); avoid top-level `await` and parallel `vite` + `plugin-react` import (Node CJS/ESM interop)
|
|
26
|
+
- **Module config overlay** — expand STYLE-tab field groups (e.g. `styles.accent_color`) in the panel; starter preview reads nested style values after `fields.json` STYLE group change
|
|
27
|
+
- **Dev persistence** — sync `module` field values into `__WPHS_DATA__` on load/apply so starter preview survives page reload (`.wphs/config/module-config.local.json`)
|
|
28
|
+
|
|
29
|
+
### Hybrid CDN (CMS styles)
|
|
30
|
+
- **Prefix build** — disable React Compiler on stg/prod (`dw:`) builds so memoized `className` strings stay prefixed
|
|
31
|
+
- **Prefix plugin** — nested `className` ternaries and `return` string literals; starter hero uses JSX `className` branches (not runtime helper strings)
|
|
32
|
+
|
|
33
|
+
## 1.0.32 — 2026-06-08
|
|
34
|
+
|
|
35
|
+
### Hybrid CDN (HubSpot editor + deploy)
|
|
36
|
+
- **jsDelivr** — CDN base URLs use `@main` (versioned filenames); git tags remain for releases
|
|
37
|
+
- **`module.css`** — copy `app.*.css` into uploaded `module.css` (CMS editor does not load external CDN CSS)
|
|
38
|
+
- **`main.prod.css`** — `prefix(dw)` + `.temp` sources (matches client-frontend); fixes JS/CSS class mismatch on HubSpot pages
|
|
39
|
+
- **STYLE fields** — `fields.json` style group on STYLE tab; `meta.json` in hybrid/monolith templates
|
|
40
|
+
- **Bootstrap** — hubspot `bootstrap.ts` imports `main.prod.css`; CDN `app-entry` CSS fallback helper
|
|
41
|
+
- **`wp doctor`** — CDN mirror public + jsDelivr reachability; hybrid `module.html` no longer requires `require_css`
|
|
42
|
+
|
|
43
|
+
## 1.0.31 — 2026-06-08
|
|
44
|
+
|
|
45
|
+
### CLI
|
|
46
|
+
- **Deploy/build spinners** — immediate @clack spinner on intro; async subprocess spawn keeps animation during Vite/git
|
|
47
|
+
- **`--verbose`** — step log mode (no spinners), compact `[debug]` exec lines, streamed child output; secrets redacted in logs
|
|
48
|
+
- **Upload errors** — surface underlying `hs` failure message instead of generic wrapper
|
|
49
|
+
|
|
50
|
+
### Hybrid CDN
|
|
51
|
+
- Fix `vite.config.cdn-vendor.mjs` resolution, hubspot `outDir` from `woodscli.json`, API URL in CDN bundle (`api-endpoint.ts`)
|
|
52
|
+
- **`fields.json`** — use `text` + `display: textarea` (not invalid `textarea` type); hybrid `module.html` uses CDN placeholders only
|
|
53
|
+
- `wp doctor` validates `fields.json` and hybrid `module.html` CDN field references
|
|
54
|
+
|
|
3
55
|
## 1.0.30 — 2026-06-08
|
|
4
56
|
|
|
5
57
|
### CLI
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/lib/exec.ts
|
|
4
|
+
import { spawn, spawnSync } from "child_process";
|
|
5
|
+
|
|
6
|
+
// src/lib/exec-debug.ts
|
|
7
|
+
import { basename, relative } from "path";
|
|
8
|
+
var SECRET_ENV_KEY = /(_KEY|_TOKEN|_SECRET|_PASSWORD|_PAT|AUTH|CREDENTIAL|GITHUB|NPM_|ERASER|LINEAR|AWS_|SSH_)/i;
|
|
9
|
+
var RELEVANT_ENV_PREFIX = /^WP_HS_|^WP_/;
|
|
10
|
+
function isSecretEnvKey(key) {
|
|
11
|
+
return SECRET_ENV_KEY.test(key);
|
|
12
|
+
}
|
|
13
|
+
function formatRelevantEnv(env) {
|
|
14
|
+
const pairs = Object.entries(env).filter(([key, value]) => value !== void 0 && RELEVANT_ENV_PREFIX.test(key)).sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => {
|
|
15
|
+
const shown = isSecretEnvKey(key) ? "[redacted]" : value;
|
|
16
|
+
return `${key}=${shown}`;
|
|
17
|
+
});
|
|
18
|
+
return pairs.length > 0 ? pairs.join(" ") : void 0;
|
|
19
|
+
}
|
|
20
|
+
function shortenScriptPath(scriptPath) {
|
|
21
|
+
const marker = "/scripts/";
|
|
22
|
+
const idx = scriptPath.lastIndexOf(marker);
|
|
23
|
+
if (idx >= 0) {
|
|
24
|
+
return `scripts/${scriptPath.slice(idx + marker.length)}`;
|
|
25
|
+
}
|
|
26
|
+
return basename(scriptPath);
|
|
27
|
+
}
|
|
28
|
+
function formatExecCommand(command, args) {
|
|
29
|
+
if (command === process.execPath && args.length > 0) {
|
|
30
|
+
const rest = args.slice(1).join(" ");
|
|
31
|
+
return `node ${shortenScriptPath(args[0])}${rest ? ` ${rest}` : ""}`;
|
|
32
|
+
}
|
|
33
|
+
return [command, ...args].join(" ");
|
|
34
|
+
}
|
|
35
|
+
function formatExecCwd(cwd, projectRoot) {
|
|
36
|
+
if (projectRoot) {
|
|
37
|
+
try {
|
|
38
|
+
const rel = relative(projectRoot, cwd);
|
|
39
|
+
if (!rel.startsWith("..")) {
|
|
40
|
+
return rel === "" ? "." : rel;
|
|
41
|
+
}
|
|
42
|
+
} catch {
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const parts = cwd.split("/");
|
|
46
|
+
if (parts.length > 3) {
|
|
47
|
+
return `\u2026/${parts.slice(-2).join("/")}`;
|
|
48
|
+
}
|
|
49
|
+
return cwd;
|
|
50
|
+
}
|
|
51
|
+
function formatExecDebugLine(command, args, cwd, env, projectRoot) {
|
|
52
|
+
const cmd = formatExecCommand(command, args);
|
|
53
|
+
const cwdLabel = formatExecCwd(cwd, projectRoot);
|
|
54
|
+
const envLabel = formatRelevantEnv(env);
|
|
55
|
+
const parts = [cmd, `cwd=${cwdLabel}`];
|
|
56
|
+
if (envLabel) {
|
|
57
|
+
parts.push(envLabel);
|
|
58
|
+
}
|
|
59
|
+
return parts.join(" ");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// src/lib/errors.ts
|
|
63
|
+
var ExitCode = {
|
|
64
|
+
SUCCESS: 0,
|
|
65
|
+
USER_ERROR: 1,
|
|
66
|
+
PREREQUISITE: 2,
|
|
67
|
+
BUILD_FAILED: 3,
|
|
68
|
+
PUBLISH_FAILED: 4,
|
|
69
|
+
AUDIT_FAILED: 5,
|
|
70
|
+
INTERNAL: 10
|
|
71
|
+
};
|
|
72
|
+
var WpHsError = class extends Error {
|
|
73
|
+
exitCode;
|
|
74
|
+
remediation;
|
|
75
|
+
constructor(message, options = {}) {
|
|
76
|
+
super(message, { cause: options.cause });
|
|
77
|
+
this.name = "WpHsError";
|
|
78
|
+
this.exitCode = options.exitCode ?? ExitCode.USER_ERROR;
|
|
79
|
+
this.remediation = options.remediation;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
function isWpHsError(error) {
|
|
83
|
+
return error instanceof WpHsError;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/lib/exec.ts
|
|
87
|
+
var SECRET_PATTERN = /(token|secret|password|pat|key)=/i;
|
|
88
|
+
function logExec(logger, command, args, options) {
|
|
89
|
+
if (!logger) return;
|
|
90
|
+
const env = options.env ?? process.env;
|
|
91
|
+
logger.debug(
|
|
92
|
+
formatExecDebugLine(command, args, options.cwd, env, options.projectRoot)
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
function runCommand(command, args, options) {
|
|
96
|
+
const { cwd, env = process.env, logger, dryRun = false, okCodes = [0], streamOutput = false } = options;
|
|
97
|
+
if (dryRun) {
|
|
98
|
+
logger?.info(`[dry-run] ${formatExecDebugLine(command, args, cwd, env, options.projectRoot)}`);
|
|
99
|
+
return { status: 0, stdout: "", stderr: "" };
|
|
100
|
+
}
|
|
101
|
+
logExec(logger, command, args, options);
|
|
102
|
+
if (streamOutput) {
|
|
103
|
+
const result2 = spawnSync(command, args, {
|
|
104
|
+
cwd,
|
|
105
|
+
env,
|
|
106
|
+
encoding: "utf8",
|
|
107
|
+
stdio: "inherit"
|
|
108
|
+
});
|
|
109
|
+
const status2 = result2.status ?? 1;
|
|
110
|
+
throwOnBadExit(command, args, status2, "", "", okCodes);
|
|
111
|
+
return { status: status2, stdout: "", stderr: "" };
|
|
112
|
+
}
|
|
113
|
+
const spawnOpts = {
|
|
114
|
+
cwd,
|
|
115
|
+
env,
|
|
116
|
+
encoding: "utf8",
|
|
117
|
+
stdio: ["inherit", "pipe", "pipe"]
|
|
118
|
+
};
|
|
119
|
+
const result = spawnSync(command, args, spawnOpts);
|
|
120
|
+
const status = result.status ?? 1;
|
|
121
|
+
const stdout = typeof result.stdout === "string" ? result.stdout : "";
|
|
122
|
+
const stderr = typeof result.stderr === "string" ? result.stderr : "";
|
|
123
|
+
throwOnBadExit(command, args, status, stdout, stderr, okCodes);
|
|
124
|
+
return { status, stdout, stderr };
|
|
125
|
+
}
|
|
126
|
+
function runNodeScript(scriptPath, args, options) {
|
|
127
|
+
runCommand(process.execPath, [scriptPath, ...args], options);
|
|
128
|
+
}
|
|
129
|
+
function throwOnBadExit(command, args, status, stdout, stderr, okCodes) {
|
|
130
|
+
if (okCodes.includes(status)) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const detail = stderr.trim() || stdout.trim() || `exit ${status}`;
|
|
134
|
+
if (SECRET_PATTERN.test(detail)) {
|
|
135
|
+
throw new WpHsError(`Command failed: ${command}`, {
|
|
136
|
+
exitCode: ExitCode.USER_ERROR,
|
|
137
|
+
remediation: "Re-run with --verbose for details (secrets are never logged)."
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
throw new WpHsError(`Command failed: ${command} ${args.join(" ")}
|
|
141
|
+
${detail}`, {
|
|
142
|
+
exitCode: ExitCode.USER_ERROR
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function runCommandAsync(command, args, options) {
|
|
146
|
+
const { cwd, env = process.env, logger, dryRun = false, okCodes = [0], streamOutput = false } = options;
|
|
147
|
+
if (dryRun) {
|
|
148
|
+
logger?.info(`[dry-run] ${formatExecDebugLine(command, args, cwd, env, options.projectRoot)}`);
|
|
149
|
+
return Promise.resolve({ status: 0, stdout: "", stderr: "" });
|
|
150
|
+
}
|
|
151
|
+
logExec(logger, command, args, options);
|
|
152
|
+
if (streamOutput) {
|
|
153
|
+
return new Promise((resolve, reject) => {
|
|
154
|
+
const child = spawn(command, args, {
|
|
155
|
+
cwd,
|
|
156
|
+
env,
|
|
157
|
+
stdio: "inherit"
|
|
158
|
+
});
|
|
159
|
+
child.on("error", (error) => {
|
|
160
|
+
reject(error);
|
|
161
|
+
});
|
|
162
|
+
child.on("close", (code) => {
|
|
163
|
+
const status = code ?? 1;
|
|
164
|
+
try {
|
|
165
|
+
throwOnBadExit(command, args, status, "", "", okCodes);
|
|
166
|
+
resolve({ status, stdout: "", stderr: "" });
|
|
167
|
+
} catch (error) {
|
|
168
|
+
reject(error);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
return new Promise((resolve, reject) => {
|
|
174
|
+
const child = spawn(command, args, {
|
|
175
|
+
cwd,
|
|
176
|
+
env,
|
|
177
|
+
stdio: ["inherit", "pipe", "pipe"]
|
|
178
|
+
});
|
|
179
|
+
let stdout = "";
|
|
180
|
+
let stderr = "";
|
|
181
|
+
child.stdout?.setEncoding("utf8");
|
|
182
|
+
child.stderr?.setEncoding("utf8");
|
|
183
|
+
child.stdout?.on("data", (chunk) => {
|
|
184
|
+
stdout += chunk;
|
|
185
|
+
});
|
|
186
|
+
child.stderr?.on("data", (chunk) => {
|
|
187
|
+
stderr += chunk;
|
|
188
|
+
});
|
|
189
|
+
child.on("error", (error) => {
|
|
190
|
+
reject(error);
|
|
191
|
+
});
|
|
192
|
+
child.on("close", (code) => {
|
|
193
|
+
const status = code ?? 1;
|
|
194
|
+
try {
|
|
195
|
+
throwOnBadExit(command, args, status, stdout, stderr, okCodes);
|
|
196
|
+
resolve({ status, stdout, stderr });
|
|
197
|
+
} catch (error) {
|
|
198
|
+
reject(error);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
function runNodeScriptAsync(scriptPath, args, options) {
|
|
204
|
+
return runCommandAsync(process.execPath, [scriptPath, ...args], options).then(() => void 0);
|
|
205
|
+
}
|
|
206
|
+
function runNodeScriptLongRunning(scriptPath, args, options) {
|
|
207
|
+
const { cwd, env = process.env, logger, dryRun = false } = options;
|
|
208
|
+
if (dryRun) {
|
|
209
|
+
logger?.info(
|
|
210
|
+
`[dry-run] ${formatExecDebugLine(process.execPath, [scriptPath, ...args], cwd, env, options.projectRoot)}`
|
|
211
|
+
);
|
|
212
|
+
return Promise.resolve(0);
|
|
213
|
+
}
|
|
214
|
+
return new Promise((resolve, reject) => {
|
|
215
|
+
const child = spawn(process.execPath, [scriptPath, ...args], {
|
|
216
|
+
cwd,
|
|
217
|
+
env,
|
|
218
|
+
stdio: "inherit"
|
|
219
|
+
});
|
|
220
|
+
const forwardSignal = (signal) => {
|
|
221
|
+
if (!child.killed) {
|
|
222
|
+
child.kill(signal);
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
process.on("SIGINT", forwardSignal);
|
|
226
|
+
process.on("SIGTERM", forwardSignal);
|
|
227
|
+
child.on("error", (error) => {
|
|
228
|
+
process.off("SIGINT", forwardSignal);
|
|
229
|
+
process.off("SIGTERM", forwardSignal);
|
|
230
|
+
reject(error);
|
|
231
|
+
});
|
|
232
|
+
child.on("exit", (code, signal) => {
|
|
233
|
+
process.off("SIGINT", forwardSignal);
|
|
234
|
+
process.off("SIGTERM", forwardSignal);
|
|
235
|
+
if (signal === "SIGINT") {
|
|
236
|
+
resolve(130);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
if (signal === "SIGTERM") {
|
|
240
|
+
resolve(143);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
resolve(code ?? 1);
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export {
|
|
249
|
+
ExitCode,
|
|
250
|
+
WpHsError,
|
|
251
|
+
isWpHsError,
|
|
252
|
+
runCommand,
|
|
253
|
+
runNodeScript,
|
|
254
|
+
runCommandAsync,
|
|
255
|
+
runNodeScriptAsync,
|
|
256
|
+
runNodeScriptLongRunning
|
|
257
|
+
};
|
|
258
|
+
//# sourceMappingURL=chunk-4GOJPOW3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/exec.ts","../src/lib/exec-debug.ts","../src/lib/errors.ts"],"sourcesContent":["import { spawn, spawnSync, type SpawnSyncOptions } from 'node:child_process'\n\nimport { formatExecDebugLine } from './exec-debug.js'\nimport { WpHsError, ExitCode } from './errors.js'\nimport type { Logger } from './logger.js'\n\nconst SECRET_PATTERN = /(token|secret|password|pat|key)=/i\n\nexport type RunOptions = {\n cwd: string\n env?: NodeJS.ProcessEnv\n logger?: Logger\n dryRun?: boolean\n timeoutMs?: number\n /** Expected exit code on success (default 0) */\n okCodes?: number[]\n /** Stream child stdout/stderr to the terminal (verbose mode). */\n streamOutput?: boolean\n /** Shorten cwd paths in debug logs. */\n projectRoot?: string\n}\n\nfunction logExec(logger: Logger | undefined, command: string, args: string[], options: RunOptions): void {\n if (!logger) return\n const env = options.env ?? process.env\n logger.debug(\n formatExecDebugLine(command, args, options.cwd, env, options.projectRoot),\n )\n}\n\nexport function runCommand(\n command: string,\n args: string[],\n options: RunOptions,\n): { status: number; stdout: string; stderr: string } {\n const { cwd, env = process.env, logger, dryRun = false, okCodes = [0], streamOutput = false } =\n options\n\n if (dryRun) {\n logger?.info(`[dry-run] ${formatExecDebugLine(command, args, cwd, env, options.projectRoot)}`)\n return { status: 0, stdout: '', stderr: '' }\n }\n\n logExec(logger, command, args, options)\n\n if (streamOutput) {\n const result = spawnSync(command, args, {\n cwd,\n env,\n encoding: 'utf8',\n stdio: 'inherit',\n })\n const status = result.status ?? 1\n throwOnBadExit(command, args, status, '', '', okCodes)\n return { status, stdout: '', stderr: '' }\n }\n\n const spawnOpts: SpawnSyncOptions = {\n cwd,\n env,\n encoding: 'utf8',\n stdio: ['inherit', 'pipe', 'pipe'],\n }\n\n const result = spawnSync(command, args, spawnOpts)\n const status = result.status ?? 1\n const stdout = typeof result.stdout === 'string' ? result.stdout : ''\n const stderr = typeof result.stderr === 'string' ? result.stderr : ''\n\n throwOnBadExit(command, args, status, stdout, stderr, okCodes)\n\n return { status, stdout, stderr }\n}\n\nexport function runNodeScript(\n scriptPath: string,\n args: string[],\n options: RunOptions,\n): void {\n runCommand(process.execPath, [scriptPath, ...args], options)\n}\n\nfunction throwOnBadExit(\n command: string,\n args: string[],\n status: number,\n stdout: string,\n stderr: string,\n okCodes: number[],\n): void {\n if (okCodes.includes(status)) {\n return\n }\n const detail = stderr.trim() || stdout.trim() || `exit ${status}`\n if (SECRET_PATTERN.test(detail)) {\n throw new WpHsError(`Command failed: ${command}`, {\n exitCode: ExitCode.USER_ERROR,\n remediation: 'Re-run with --verbose for details (secrets are never logged).',\n })\n }\n throw new WpHsError(`Command failed: ${command} ${args.join(' ')}\\n${detail}`, {\n exitCode: ExitCode.USER_ERROR,\n })\n}\n\n/**\n * Non-blocking spawn — keeps the Node event loop alive so @clack spinners animate.\n */\nexport function runCommandAsync(\n command: string,\n args: string[],\n options: RunOptions,\n): Promise<{ status: number; stdout: string; stderr: string }> {\n const { cwd, env = process.env, logger, dryRun = false, okCodes = [0], streamOutput = false } =\n options\n\n if (dryRun) {\n logger?.info(`[dry-run] ${formatExecDebugLine(command, args, cwd, env, options.projectRoot)}`)\n return Promise.resolve({ status: 0, stdout: '', stderr: '' })\n }\n\n logExec(logger, command, args, options)\n\n if (streamOutput) {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n cwd,\n env,\n stdio: 'inherit',\n })\n\n child.on('error', (error) => {\n reject(error)\n })\n\n child.on('close', (code) => {\n const status = code ?? 1\n try {\n throwOnBadExit(command, args, status, '', '', okCodes)\n resolve({ status, stdout: '', stderr: '' })\n } catch (error) {\n reject(error)\n }\n })\n })\n }\n\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n cwd,\n env,\n stdio: ['inherit', 'pipe', 'pipe'],\n })\n\n let stdout = ''\n let stderr = ''\n\n child.stdout?.setEncoding('utf8')\n child.stderr?.setEncoding('utf8')\n child.stdout?.on('data', (chunk: string) => {\n stdout += chunk\n })\n child.stderr?.on('data', (chunk: string) => {\n stderr += chunk\n })\n\n child.on('error', (error) => {\n reject(error)\n })\n\n child.on('close', (code) => {\n const status = code ?? 1\n try {\n throwOnBadExit(command, args, status, stdout, stderr, okCodes)\n resolve({ status, stdout, stderr })\n } catch (error) {\n reject(error)\n }\n })\n })\n}\n\nexport function runNodeScriptAsync(\n scriptPath: string,\n args: string[],\n options: RunOptions,\n): Promise<void> {\n return runCommandAsync(process.execPath, [scriptPath, ...args], options).then(() => undefined)\n}\n\n/**\n * Spawn a Node script with inherited stdio and forward SIGINT/SIGTERM (wp watch, long-running tools).\n * Unlike spawnSync, the parent event loop stays alive so Ctrl+C works while the child runs.\n */\nexport function runNodeScriptLongRunning(\n scriptPath: string,\n args: string[],\n options: RunOptions,\n): Promise<number> {\n const { cwd, env = process.env, logger, dryRun = false } = options\n\n if (dryRun) {\n logger?.info(\n `[dry-run] ${formatExecDebugLine(process.execPath, [scriptPath, ...args], cwd, env, options.projectRoot)}`,\n )\n return Promise.resolve(0)\n }\n\n return new Promise((resolve, reject) => {\n const child = spawn(process.execPath, [scriptPath, ...args], {\n cwd,\n env,\n stdio: 'inherit',\n })\n\n const forwardSignal = (signal: NodeJS.Signals) => {\n if (!child.killed) {\n child.kill(signal)\n }\n }\n\n process.on('SIGINT', forwardSignal)\n process.on('SIGTERM', forwardSignal)\n\n child.on('error', (error) => {\n process.off('SIGINT', forwardSignal)\n process.off('SIGTERM', forwardSignal)\n reject(error)\n })\n\n child.on('exit', (code, signal) => {\n process.off('SIGINT', forwardSignal)\n process.off('SIGTERM', forwardSignal)\n\n if (signal === 'SIGINT') {\n resolve(130)\n return\n }\n if (signal === 'SIGTERM') {\n resolve(143)\n return\n }\n\n resolve(code ?? 1)\n })\n })\n}\n","import { basename, relative } from 'node:path'\n\nconst SECRET_ENV_KEY =\n /(_KEY|_TOKEN|_SECRET|_PASSWORD|_PAT|AUTH|CREDENTIAL|GITHUB|NPM_|ERASER|LINEAR|AWS_|SSH_)/i\n\nconst RELEVANT_ENV_PREFIX = /^WP_HS_|^WP_/\n\nexport function isSecretEnvKey(key: string): boolean {\n return SECRET_ENV_KEY.test(key)\n}\n\nexport function maskEnvForLog(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const masked: NodeJS.ProcessEnv = {}\n for (const [key, value] of Object.entries(env)) {\n if (value === undefined) continue\n masked[key] = isSecretEnvKey(key) ? '[redacted]' : value\n }\n return masked\n}\n\nexport function formatRelevantEnv(env: NodeJS.ProcessEnv): string | undefined {\n const pairs = Object.entries(env)\n .filter(([key, value]) => value !== undefined && RELEVANT_ENV_PREFIX.test(key))\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, value]) => {\n const shown = isSecretEnvKey(key) ? '[redacted]' : value\n return `${key}=${shown}`\n })\n\n return pairs.length > 0 ? pairs.join(' ') : undefined\n}\n\nfunction shortenScriptPath(scriptPath: string): string {\n const marker = '/scripts/'\n const idx = scriptPath.lastIndexOf(marker)\n if (idx >= 0) {\n return `scripts/${scriptPath.slice(idx + marker.length)}`\n }\n return basename(scriptPath)\n}\n\nexport function formatExecCommand(command: string, args: string[]): string {\n if (command === process.execPath && args.length > 0) {\n const rest = args.slice(1).join(' ')\n return `node ${shortenScriptPath(args[0])}${rest ? ` ${rest}` : ''}`\n }\n return [command, ...args].join(' ')\n}\n\nexport function formatExecCwd(cwd: string, projectRoot?: string): string {\n if (projectRoot) {\n try {\n const rel = relative(projectRoot, cwd)\n if (!rel.startsWith('..')) {\n return rel === '' ? '.' : rel\n }\n } catch {\n // fall through\n }\n }\n const parts = cwd.split('/')\n if (parts.length > 3) {\n return `…/${parts.slice(-2).join('/')}`\n }\n return cwd\n}\n\n/** One-line verbose exec label for developers (no full env dump). */\nexport function formatExecDebugLine(\n command: string,\n args: string[],\n cwd: string,\n env: NodeJS.ProcessEnv,\n projectRoot?: string,\n): string {\n const cmd = formatExecCommand(command, args)\n const cwdLabel = formatExecCwd(cwd, projectRoot)\n const envLabel = formatRelevantEnv(env)\n const parts = [cmd, `cwd=${cwdLabel}`]\n if (envLabel) {\n parts.push(envLabel)\n }\n return parts.join(' ')\n}\n","export const ExitCode = {\n SUCCESS: 0,\n USER_ERROR: 1,\n PREREQUISITE: 2,\n BUILD_FAILED: 3,\n PUBLISH_FAILED: 4,\n AUDIT_FAILED: 5,\n INTERNAL: 10,\n} as const\n\nexport type ExitCodeValue = (typeof ExitCode)[keyof typeof ExitCode]\n\nexport class WpHsError extends Error {\n readonly exitCode: ExitCodeValue\n readonly remediation?: string\n\n constructor(\n message: string,\n options: { exitCode?: ExitCodeValue; remediation?: string; cause?: unknown } = {},\n ) {\n super(message, { cause: options.cause })\n this.name = 'WpHsError'\n this.exitCode = options.exitCode ?? ExitCode.USER_ERROR\n this.remediation = options.remediation\n }\n}\n\nexport function isWpHsError(error: unknown): error is WpHsError {\n return error instanceof WpHsError\n}\n"],"mappings":"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","names":["result","status"]}
|