@woodsportal/hubspot-kit 1.0.5 → 1.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +242 -33
  3. package/dist/{chunk-JDGIAYHX.js → chunk-GTTIJVAR.js} +43 -3
  4. package/dist/chunk-GTTIJVAR.js.map +1 -0
  5. package/dist/cli.js +1378 -339
  6. package/dist/cli.js.map +1 -1
  7. package/dist/exec-U2OJATR3.js +12 -0
  8. package/dist/index.d.ts +20 -0
  9. package/dist/index.js +8 -1
  10. package/dist/index.js.map +1 -1
  11. package/examples/greenfield/module-hybrid-cdn/README.md +40 -3
  12. package/examples/greenfield/module-hybrid-cdn/public/fields.json +44 -1
  13. package/examples/greenfield/module-hybrid-cdn/src/app.tsx +8 -0
  14. package/examples/greenfield/module-hybrid-cdn/src/assets/css/main.dev.css +6 -1
  15. package/examples/greenfield/module-hybrid-cdn/src/cdn/app-entry.ts +32 -0
  16. package/examples/greenfield/module-hybrid-cdn/src/cdn/vendor-entry.ts +28 -0
  17. package/examples/greenfield/module-hybrid-cdn/src/components/layout/section-card.tsx +20 -0
  18. package/examples/greenfield/module-hybrid-cdn/src/components/layout/starter-nav.tsx +28 -0
  19. package/examples/greenfield/module-hybrid-cdn/src/components/layout/starter-shell.tsx +18 -0
  20. package/examples/greenfield/module-hybrid-cdn/src/config/router.ts +4 -0
  21. package/examples/greenfield/module-hybrid-cdn/src/config/routes.ts +5 -0
  22. package/examples/greenfield/module-hybrid-cdn/src/defaultData.ts +2 -7
  23. package/examples/greenfield/module-hybrid-cdn/src/features/starter/components/starter-guide-page.tsx +93 -0
  24. package/examples/greenfield/module-hybrid-cdn/src/features/starter/components/starter-home-page.tsx +21 -0
  25. package/examples/greenfield/module-hybrid-cdn/src/features/starter/components/starter-home.tsx +52 -0
  26. package/examples/greenfield/module-hybrid-cdn/src/features/starter/components/starter-single-page.tsx +17 -0
  27. package/examples/greenfield/module-hybrid-cdn/src/features/starter/content/woodscli-guide-content.ts +86 -0
  28. package/examples/greenfield/module-hybrid-cdn/src/features/starter/hooks/use-starter-preview.ts +47 -0
  29. package/examples/greenfield/module-hybrid-cdn/src/features/starter/index.ts +6 -0
  30. package/examples/greenfield/module-hybrid-cdn/src/hubspot/bootstrap.ts +10 -0
  31. package/examples/greenfield/module-hybrid-cdn/src/hubspot/default-data.ts +7 -0
  32. package/examples/greenfield/module-hybrid-cdn/src/integrations/tanstack-router/router.tsx +25 -0
  33. package/examples/greenfield/module-hybrid-cdn/src/main.tsx +4 -3
  34. package/examples/greenfield/module-hybrid-cdn/src/portal/mount-dev-preview.tsx +8 -0
  35. package/examples/greenfield/module-hybrid-cdn/src/portal/mount-portal.tsx +12 -0
  36. package/examples/greenfield/module-hybrid-cdn/src/routeTree.gen.ts +77 -0
  37. package/examples/greenfield/module-hybrid-cdn/src/routes/__root.tsx +15 -0
  38. package/examples/greenfield/module-hybrid-cdn/src/routes/guide.tsx +7 -0
  39. package/examples/greenfield/module-hybrid-cdn/src/routes/index.tsx +7 -0
  40. package/examples/greenfield/module-hybrid-cdn/tsconfig.json +20 -0
  41. package/examples/greenfield/module-monolith/public/fields.json +44 -1
  42. package/examples/greenfield/module-monolith/src/app.tsx +8 -0
  43. package/examples/greenfield/module-monolith/src/assets/css/main.dev.css +8 -0
  44. package/examples/greenfield/module-monolith/src/components/layout/section-card.tsx +20 -0
  45. package/examples/greenfield/module-monolith/src/components/layout/starter-nav.tsx +28 -0
  46. package/examples/greenfield/module-monolith/src/components/layout/starter-shell.tsx +18 -0
  47. package/examples/greenfield/module-monolith/src/config/router.ts +4 -0
  48. package/examples/greenfield/module-monolith/src/config/routes.ts +5 -0
  49. package/examples/greenfield/module-monolith/src/defaultData.ts +2 -7
  50. package/examples/greenfield/module-monolith/src/features/starter/components/starter-guide-page.tsx +93 -0
  51. package/examples/greenfield/module-monolith/src/features/starter/components/starter-home-page.tsx +21 -0
  52. package/examples/greenfield/module-monolith/src/features/starter/components/starter-home.tsx +52 -0
  53. package/examples/greenfield/module-monolith/src/features/starter/components/starter-single-page.tsx +17 -0
  54. package/examples/greenfield/module-monolith/src/features/starter/content/woodscli-guide-content.ts +86 -0
  55. package/examples/greenfield/module-monolith/src/features/starter/hooks/use-starter-preview.ts +47 -0
  56. package/examples/greenfield/module-monolith/src/features/starter/index.ts +6 -0
  57. package/examples/greenfield/module-monolith/src/hubspot/default-data.ts +7 -0
  58. package/examples/greenfield/module-monolith/src/hubspot/types.ts +17 -0
  59. package/examples/greenfield/module-monolith/src/integrations/tanstack-router/router.tsx +25 -0
  60. package/examples/greenfield/module-monolith/src/main.tsx +5 -0
  61. package/examples/greenfield/module-monolith/src/portal/mount-dev-preview.tsx +8 -0
  62. package/examples/greenfield/module-monolith/src/portal/mount-portal.tsx +12 -0
  63. package/examples/greenfield/module-monolith/src/routeTree.gen.ts +77 -0
  64. package/examples/greenfield/module-monolith/src/routes/__root.tsx +15 -0
  65. package/examples/greenfield/module-monolith/src/routes/guide.tsx +7 -0
  66. package/examples/greenfield/module-monolith/src/routes/index.tsx +7 -0
  67. package/examples/greenfield/module-monolith/tsconfig.json +20 -0
  68. package/package.json +1 -1
  69. package/scripts/check-hubspot-bundle-size.mjs +5 -2
  70. package/scripts/ensure-wphs-workspace.mjs +2 -1
  71. package/scripts/hubspot-module-postbuild.mjs +1 -1
  72. package/scripts/read-woodsportal-config.mjs +4 -1
  73. package/scripts/run-hubspot-module-postbuild.mjs +9 -4
  74. package/scripts/vite/bootstrap-shim-resolver.js +47 -0
  75. package/scripts/vite/ensure-dev-kit-shims.js +7 -1
  76. package/scripts/vite/react-dev-plugin-options.js +2 -1
  77. package/scripts/watch-hubspot.mjs +107 -17
  78. package/scripts/wphs-paths.mjs +1 -0
  79. package/scripts/write-audit-artifacts.mjs +2 -1
  80. package/src/dev/bootstrap-greenfield.tsx +17 -9
  81. package/src/dev-module-config/dev-module-display-name.ts +5 -0
  82. package/src/dev-module-config/ui/ModuleConfigPersistenceStatus.tsx +5 -5
  83. package/src/dev-module-config/ui/ModuleConfigShell.tsx +2 -1
  84. package/src/dev-module-config/ui/module-config-theme.css +6 -0
  85. package/src/dev-module-config/ui/navigation/ModuleConfigNavContext.tsx +11 -5
  86. package/templates/module-hybrid-cdn/README.md +53 -3
  87. package/templates/module-hybrid-cdn/package.json +6 -2
  88. package/templates/module-hybrid-cdn/public/fields.json +44 -1
  89. package/templates/module-hybrid-cdn/src/app.tsx +8 -0
  90. package/templates/module-hybrid-cdn/src/assets/css/main.dev.css +6 -1
  91. package/templates/module-hybrid-cdn/src/cdn/app-entry.ts +32 -0
  92. package/templates/module-hybrid-cdn/src/cdn/vendor-entry.ts +28 -0
  93. package/templates/module-hybrid-cdn/src/components/layout/section-card.tsx +20 -0
  94. package/templates/module-hybrid-cdn/src/components/layout/starter-nav.tsx +28 -0
  95. package/templates/module-hybrid-cdn/src/components/layout/starter-shell.tsx +18 -0
  96. package/templates/module-hybrid-cdn/src/config/router.ts +4 -0
  97. package/templates/module-hybrid-cdn/src/config/routes.ts +5 -0
  98. package/templates/module-hybrid-cdn/src/defaultData.ts +2 -7
  99. package/templates/module-hybrid-cdn/src/features/starter/components/starter-guide-page.tsx +93 -0
  100. package/templates/module-hybrid-cdn/src/features/starter/components/starter-home-page.tsx +21 -0
  101. package/templates/module-hybrid-cdn/src/features/starter/components/starter-home.tsx +52 -0
  102. package/templates/module-hybrid-cdn/src/features/starter/components/starter-single-page.tsx +17 -0
  103. package/templates/module-hybrid-cdn/src/features/starter/content/woodscli-guide-content.ts +86 -0
  104. package/templates/module-hybrid-cdn/src/features/starter/hooks/starter-preview-values.ts +42 -0
  105. package/templates/module-hybrid-cdn/src/features/starter/hooks/use-starter-preview.dev.ts +17 -0
  106. package/templates/module-hybrid-cdn/src/features/starter/hooks/use-starter-preview.ts +30 -0
  107. package/templates/module-hybrid-cdn/src/features/starter/index.ts +6 -0
  108. package/templates/module-hybrid-cdn/src/hubspot/bootstrap.ts +10 -0
  109. package/templates/module-hybrid-cdn/src/hubspot/default-data.ts +7 -0
  110. package/templates/module-hybrid-cdn/src/hubspot/module-entry.tsx +9 -0
  111. package/templates/module-hybrid-cdn/src/integrations/tanstack-router/router.tsx +25 -0
  112. package/templates/module-hybrid-cdn/src/main.tsx +4 -3
  113. package/templates/module-hybrid-cdn/src/portal/mount-dev-preview.tsx +8 -0
  114. package/templates/module-hybrid-cdn/src/portal/mount-portal.tsx +12 -0
  115. package/templates/module-hybrid-cdn/src/routeTree.gen.ts +77 -0
  116. package/templates/module-hybrid-cdn/src/routes/__root.tsx +15 -0
  117. package/templates/module-hybrid-cdn/src/routes/guide.tsx +7 -0
  118. package/templates/module-hybrid-cdn/src/routes/index.tsx +7 -0
  119. package/templates/module-hybrid-cdn/tsconfig.json +20 -0
  120. package/templates/module-hybrid-cdn/vite.config.monolith.mjs +8 -0
  121. package/templates/module-monolith/README.md +59 -0
  122. package/templates/module-monolith/index.html +1 -1
  123. package/templates/module-monolith/package.json +10 -3
  124. package/templates/module-monolith/public/fields.json +44 -1
  125. package/templates/module-monolith/public/module.html +1 -0
  126. package/templates/module-monolith/src/app.tsx +8 -0
  127. package/templates/module-monolith/src/assets/css/main.dev.css +6 -1
  128. package/templates/module-monolith/src/components/layout/section-card.tsx +20 -0
  129. package/templates/module-monolith/src/components/layout/starter-nav.tsx +28 -0
  130. package/templates/module-monolith/src/components/layout/starter-shell.tsx +18 -0
  131. package/templates/module-monolith/src/config/router.ts +4 -0
  132. package/templates/module-monolith/src/config/routes.ts +5 -0
  133. package/templates/module-monolith/src/defaultData.ts +2 -7
  134. package/templates/module-monolith/src/features/starter/components/starter-guide-page.tsx +93 -0
  135. package/templates/module-monolith/src/features/starter/components/starter-home-page.tsx +21 -0
  136. package/templates/module-monolith/src/features/starter/components/starter-home.tsx +52 -0
  137. package/templates/module-monolith/src/features/starter/components/starter-single-page.tsx +17 -0
  138. package/templates/module-monolith/src/features/starter/content/woodscli-guide-content.ts +86 -0
  139. package/templates/module-monolith/src/features/starter/hooks/starter-preview-values.ts +42 -0
  140. package/templates/module-monolith/src/features/starter/hooks/use-starter-preview.dev.ts +17 -0
  141. package/templates/module-monolith/src/features/starter/hooks/use-starter-preview.ts +30 -0
  142. package/templates/module-monolith/src/features/starter/index.ts +6 -0
  143. package/templates/module-monolith/src/hubspot/default-data.ts +7 -0
  144. package/templates/module-monolith/src/hubspot/module-entry.tsx +9 -0
  145. package/templates/module-monolith/src/integrations/tanstack-router/router.tsx +25 -0
  146. package/templates/module-monolith/src/main.tsx +4 -3
  147. package/templates/module-monolith/src/portal/mount-dev-preview.tsx +8 -0
  148. package/templates/module-monolith/src/portal/mount-portal.tsx +12 -0
  149. package/templates/module-monolith/src/routeTree.gen.ts +77 -0
  150. package/templates/module-monolith/src/routes/__root.tsx +15 -0
  151. package/templates/module-monolith/src/routes/guide.tsx +7 -0
  152. package/templates/module-monolith/src/routes/index.tsx +7 -0
  153. package/templates/module-monolith/tsconfig.json +20 -0
  154. package/templates/module-monolith/vite.config.monolith.mjs +8 -0
  155. package/templates/module-monolith/woodscli.json +1 -0
  156. package/templates/shared/.env.dev.example +5 -0
  157. package/templates/shared/.env.prod.example +5 -0
  158. package/templates/shared/.env.stg.example +3 -0
  159. package/templates/shared/portal.cdn.json.example +8 -0
  160. package/templates/theme-starter/package.json +5 -2
  161. package/vite/vite.config.dev.mjs +9 -1
  162. package/vite/vite.config.monolith.mjs +22 -17
  163. package/dist/chunk-JDGIAYHX.js.map +0 -1
  164. package/dist/exec-K5C6LZP4.js +0 -10
  165. /package/dist/{exec-K5C6LZP4.js.map → exec-U2OJATR3.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.27 — 2026-06-07
4
+
5
+ ### Docs
6
+ - Expanded README: full command reference, workflows, project layout, documentation index
7
+ - Aligned `GETTING-STARTED.md` and `HUBSPOT-CLI-SETUP.md` (`defaultPortal` = portal name)
8
+
9
+ ## 1.0.26 — 2026-06-07
10
+
11
+ ### CLI
12
+ - `wp portal list` / `wp portal use` — switch `defaultPortal` via `hs accounts use`
13
+ - `wp setup` — copy missing hubspot config, env files, and vite shims
14
+ - Progress loaders on build/deploy/publish/upload/setup/doctor; `wp watch` stays TTY-friendly
15
+ - `wp watch --rebuild` and monolith deploy CDN skip fixes
16
+ - Default `--tier dev` for build/deploy/publish/upload/watch
17
+
3
18
  ## 1.0.2 — 2026-06-07
4
19
 
5
20
  ### WoodsCLI product positioning
package/README.md CHANGED
@@ -1,62 +1,271 @@
1
1
  # WoodsCLI
2
2
 
3
- > HubSpot CMS dev kit by WoodsPortal — modules and themes.
4
- > `npm i @woodsportal/hubspot-kit` · `wp dev`
3
+ **HubSpot CMS dev kit by WoodsPortal**local preview, module field editing, Vite build pipelines, and HubSpot upload/watch for **custom modules** and **themes**.
5
4
 
6
- WoodsCLI (`wp`) is the development CLI for **HubSpot CMS custom modules** (React/JS + `fields.json`) and **themes** (templates, CSS, theme fields). It wraps `@hubspot/cli` for upload/watch and adds local preview, Content/Styles field editing (**Ctrl+Shift+Z**), and hybrid CDN or monolith build pipelines.
5
+ ```bash
6
+ npm i -D @woodsportal/hubspot-kit@^1.0.27
7
+ npx wp --version
8
+ ```
9
+
10
+ The `wp` CLI wraps [`@hubspot/cli`](https://developers.hubspot.com/docs/cms/developer-reference/local-development-cli) for CMS operations and adds WoodsPortal-specific tooling: hybrid CDN or monolith module builds, the **module-config overlay** (**Ctrl+Shift+Z** / **Cmd+Shift+Z**), and a `.wphs/` local workspace.
11
+
12
+ ---
13
+
14
+ ## What you get
15
+
16
+ | Capability | Command / artifact |
17
+ |------------|-------------------|
18
+ | Scaffold module or theme | `wp init` |
19
+ | Local SPA + field editor | `wp dev` (`wp local`) |
20
+ | HubSpot file sync | `wp watch`, `wp upload` |
21
+ | Full ship pipeline | `wp deploy` (build → CDN publish → upload) |
22
+ | Project health check | `wp doctor` |
23
+ | Portal switching | `wp portal use` |
24
+ | CI / regression gates | `wp examples smoke`, `wp regression smoke`, `wp audit *` |
25
+
26
+ **Reference implementation:** [woodsportal-client-frontend](https://github.com/Digital-Woods/digitalwoods.io-woodsportal-client-frontend) — advanced hybrid CDN module with a full app adapter.
27
+
28
+ ---
29
+
30
+ ## Prerequisites
31
+
32
+ | Requirement | Notes |
33
+ |-------------|--------|
34
+ | **Node.js 20+** | Enforced by `wp doctor` |
35
+ | **HubSpot CLI** | `npm i -g @hubspot/cli` — required for upload/watch/deploy |
36
+ | **HubSpot CMS portal** | Design Manager access; PAT or OAuth via `wp auth` |
37
+ | **Project config** | `woodscli.json` at repo root (created by `wp init` or `wp adopt`) |
7
38
 
8
- ## Two tracks
39
+ Local preview (`wp dev`) runs **without** HubSpot credentials. Upload, watch, and deploy need a valid project `hubspot.config.yml`.
9
40
 
10
- | Track | `projectType` | Quick start |
11
- |-------|---------------|-------------|
12
- | **Module (hybrid CDN)** | `module-hybrid-cdn` | `wp init -t module-hybrid-cdn` → `wp dev` → `wp deploy` |
13
- | **Module (monolith)** | `module-monolith` | `wp init -t module-monolith` → `wp dev` → `wp build --hubspot-only` |
14
- | **Theme** | `theme-starter` | `wp init -t theme-starter` → `wp dev` → `wp upload` |
41
+ ---
15
42
 
16
- WoodsPortal client-frontend is the **reference advanced module** (hybrid CDN + full app adapter).
43
+ ## Install
17
44
 
18
- ## Quick start
45
+ **New project** (scaffold includes the kit):
19
46
 
20
47
  ```bash
21
- npx wp init -t module-hybrid-cdn
22
- cd my-project && npm install
48
+ npx wp init -t module-hybrid-cdn -n my-portal-module
49
+ cd my-portal-module && npm install
50
+ ```
51
+
52
+ **Existing consumer** (add dev dependency):
53
+
54
+ ```bash
55
+ npm i -D @woodsportal/hubspot-kit@^1.0.27
56
+ # or: yarn add -D @woodsportal/hubspot-kit@^1.0.26
57
+ ```
58
+
59
+ Use scripts that call `wp` directly, or rely on `node_modules/.bin/wp` after install.
60
+
61
+ ---
62
+
63
+ ## Project types
64
+
65
+ | Track | `projectType` | Build output | Typical ship flow |
66
+ |-------|---------------|--------------|-------------------|
67
+ | **Module (hybrid CDN)** | `module-hybrid-cdn` | `dist/cdn/*` + `module.outDir` | `wp deploy` |
68
+ | **Module (monolith)** | `module-monolith` | Single bundle in `module.outDir` | `wp build` → `wp upload` |
69
+ | **Theme** | `theme-starter` | Theme folder under `theme.srcDir` | `wp upload` |
70
+
71
+ Init templates live under `templates/` in this package. Hybrid CDN splits vendor/app chunks for jsDelivr; monolith sets `cdn.mode: none` and skips CDN publish on deploy.
72
+
73
+ ---
74
+
75
+ ## Quick start (greenfield)
76
+
77
+ ```bash
78
+ npx wp init -t module-hybrid-cdn -n my-portal-module
79
+ cd my-portal-module && npm install
80
+
81
+ wp setup # hubspot.config.yml, .env.*, CDN files, vite shims (never overwrites)
82
+ wp doctor # Node, config, .wphs/, HubSpot CLI
83
+ wp auth # HubSpot login — updates hubspot.config.yml
84
+ wp portal use # interactive default portal (or: wp portal use <name>)
85
+
86
+ wp dev # http://localhost:3000 — alias: wp local
87
+ ```
88
+
89
+ **Module overlay:** open the dev server, press **Ctrl+Shift+Z** (Windows/Linux) or **Cmd+Shift+Z** (macOS) to edit Content/Styles fields against `fields.json`.
90
+
91
+ ---
92
+
93
+ ## Existing repository
94
+
95
+ ```bash
96
+ wp adopt # detect module/theme layout, add woodscli.json + .wphs/
97
+ wp setup
98
+ wp migrate --yes # if you still have legacy .dev/ or woodsportal.hs.json
23
99
  wp doctor
24
- wp dev # alias: wp local
25
100
  ```
26
101
 
27
- Existing repo:
102
+ Legacy filename `woodsportal.hs.json` is **not** read — migrate to `woodscli.json` with `wp migrate --yes`.
103
+
104
+ ---
105
+
106
+ ## Day-to-day workflows
107
+
108
+ ### Local development
109
+
110
+ ```bash
111
+ wp dev # Vite HMR + module-config overlay
112
+ wp dev -p 3001 # custom port
113
+ ```
114
+
115
+ ### Watch HubSpot folder (CMS sync)
116
+
117
+ ```bash
118
+ wp watch # hs cms watch on module.outDir (builds if output missing)
119
+ wp watch --rebuild # rebuild on src/ + public/ changes, then watch
120
+ ```
121
+
122
+ `wp watch` does not use progress spinners so **Ctrl+C** and HubSpot TTY output stay reliable.
123
+
124
+ ### Build and ship
28
125
 
29
126
  ```bash
30
- wp adopt
31
- wp migrate --yes # if migrating from .dev/
127
+ wp build # default --tier dev
128
+ wp build --cdn-only # hybrid CDN chunks only
129
+ wp build --hubspot-only # module bundle only (monolith-friendly)
130
+
131
+ wp publish --tier dev # push CDN mirror (hybrid only)
132
+ wp upload --tier dev # hs cms upload
133
+ wp deploy --tier dev # build + publish + upload (skips CDN when cdn.mode: none)
32
134
  ```
33
135
 
34
- ## Commands
136
+ Tiers: `dev` | `stg` | `prod`. Production upload requires confirmation (`--yes` or `WP_HS_CONFIRM_PROD=1`). See [docs/BUILD-MODES.md](./docs/BUILD-MODES.md).
137
+
138
+ ---
139
+
140
+ ## HubSpot authentication
141
+
142
+ 1. `wp setup` copies `hubspot.config.yml.example` → `hubspot.config.yml` (gitignored).
143
+ 2. `wp auth` runs `hs auth` (browser / PAT flow).
144
+ 3. `wp portal list` shows configured portals; `wp portal use <name>` sets `defaultPortal`.
145
+
146
+ Run auth and portal commands from the **project root** so HubSpot CLI reads `./hubspot.config.yml`.
147
+
148
+ Full guide: [docs/HUBSPOT-CLI-SETUP.md](./docs/HUBSPOT-CLI-SETUP.md)
149
+
150
+ ---
151
+
152
+ ## Command reference
153
+
154
+ Global flags (all commands): `--project <path>`, `--ci`, `--json`, `--verbose`, `--quiet`, `--dry-run`, `-y/--yes`.
155
+
156
+ ### Project lifecycle
35
157
 
36
158
  | Command | Description |
37
159
  |---------|-------------|
38
- | `wp dev` | Local Vite server + CMS dev tool |
39
- | `wp build` | CDN + module (or theme no-op) |
40
- | `wp deploy` | Build, publish CDN, upload module |
41
- | `wp adopt` | Detect module/theme and add config + `.wphs/` |
42
- | `wp migrate` | `.dev/` `.wphs/` |
43
- | `wp examples smoke` | Run examples matrix (CI) |
44
- | `wp audit secrets` | Scan for hardcoded credentials |
160
+ | `wp init [-t template] [-n name] [--router hash\|browser\|none]` | Scaffold `module-hybrid-cdn`, `module-monolith`, or `theme-starter` |
161
+ | `wp adopt` | Add WoodsCLI config to an existing module/theme repo |
162
+ | `wp migrate` | Move legacy `.dev/` / `woodsportal.hs.json` → `.wphs/` + `woodscli.json` |
163
+ | `wp setup [--tier dev\|stg\|prod]` | Copy missing config, env, CDN, and vite shim files |
164
+ | `wp doctor` | Prerequisite checks (interactive progress on TTY) |
165
+ | `wp config validate` | Validate `woodscli.json` (zod) |
45
166
 
46
- See [docs/CLI-REFERENCE.md](./docs/CLI-REFERENCE.md), [docs/MODULES.md](./docs/MODULES.md), [docs/THEMES.md](./docs/THEMES.md), [docs/EXAMPLES.md](./docs/EXAMPLES.md).
167
+ ### HubSpot account
47
168
 
48
- ## Config
169
+ | Command | Description |
170
+ |---------|-------------|
171
+ | `wp auth` | `hs auth` — add or refresh portal credentials |
172
+ | `wp portal list` / `wp portal ls` | List `portals[]` and current `defaultPortal` |
173
+ | `wp portal use [name]` | `hs accounts use` — name or portalId; interactive if name omitted |
49
174
 
50
- **Config:** `woodscli.json` at project root. Legacy `woodsportal.hs.json` → run `wp migrate --yes`.
175
+ ### Develop and sync
51
176
 
52
- Local workspace: **`.wphs/`** only. Consumer hook: **`wphs.adapter.ts`**.
177
+ | Command | Description |
178
+ |---------|-------------|
179
+ | `wp dev` / `wp local` | Local Vite dev server + module-config UI |
180
+ | `wp watch [--rebuild] [--tier dev\|stg\|prod]` | `hs cms watch` on built module/theme output |
181
+ | `wp fields sync [--direction pull\|push]` | Sync `fields.json` with local cache |
53
182
 
54
- HubSpot upload/watch: **`hubspot.config.yml`** — [setup guide](./docs/HUBSPOT-CLI-SETUP.md).
183
+ ### Build and deploy
55
184
 
56
- ## Prerequisites
185
+ | Command | Description |
186
+ |---------|-------------|
187
+ | `wp build [--tier] [--cdn-only] [--hubspot-only] [--cdn-esm]` | CDN + module (or theme no-op) |
188
+ | `wp publish [--tier] [--dry-run]` | Verify CDN endpoint and push jsDelivr mirror |
189
+ | `wp upload [--tier]` | `hs cms upload` using paths from `woodscli.json` |
190
+ | `wp deploy [--tier] [--skip-publish]` | Full pipeline: build → publish → upload |
191
+
192
+ ### Quality and CI
193
+
194
+ | Command | Description |
195
+ |---------|-------------|
196
+ | `wp regression smoke [--skip-doctor]` | Config validate + consumer boundary checks |
197
+ | `wp examples list` | List scenarios from `examples/manifest.json` |
198
+ | `wp examples smoke [--scenario id] [--tier static\|live]` | Examples matrix (used in kit CI) |
199
+ | `wp audit ship-bundle` | Fail if dev-only strings appear in `dist/` |
200
+ | `wp audit parity [--baseline dir]` | Compare `dist/` to baseline snapshot |
201
+ | `wp audit baseline [--baseline dir]` | Capture parity baseline under `.wphs/` |
202
+ | `wp audit secrets` | Scan for hardcoded PATs / credentials |
203
+
204
+ Detailed flags and exit codes: [docs/CLI-REFERENCE.md](./docs/CLI-REFERENCE.md)
205
+
206
+ ---
207
+
208
+ ## Project layout
209
+
210
+ ```
211
+ my-project/
212
+ ├── woodscli.json # WoodsCLI project config (required)
213
+ ├── hubspot.config.yml # HubSpot CLI portals (gitignored; from wp setup)
214
+ ├── wphs.adapter.ts # Consumer adapter hook (modules)
215
+ ├── vite.config.dev.mjs # Re-exports kit dev preset
216
+ ├── vite.config.hubspot.mjs # or vite.config.monolith.mjs
217
+ ├── .wphs/ # Local workspace (module-config, cache, audit)
218
+ ├── src/ # App source
219
+ ├── public/ # fields.json, module.html (modules)
220
+ └── dist/ # Build output (cdn + module.outDir)
221
+ ```
222
+
223
+ | File / dir | Purpose |
224
+ |------------|---------|
225
+ | `woodscli.json` | `projectType`, module/theme paths, CDN mode, env tiers |
226
+ | `.wphs/` | Module-config overlay state, fixtures, audit baseline |
227
+ | `wphs.adapter.ts` | Bridge to your app (routing, API, HubSpot context) |
228
+ | `hubspot.config.yml` | Portal names, PATs, `defaultPortal` |
229
+
230
+ Config field reference: [docs/CONFIG-REFERENCE.md](./docs/CONFIG-REFERENCE.md)
231
+
232
+ ---
233
+
234
+ ## Documentation
235
+
236
+ | Doc | Topic |
237
+ |-----|--------|
238
+ | [GETTING-STARTED.md](./docs/GETTING-STARTED.md) | First-run walkthrough |
239
+ | [CLI-REFERENCE.md](./docs/CLI-REFERENCE.md) | All commands, flags, exit codes |
240
+ | [HUBSPOT-CLI-SETUP.md](./docs/HUBSPOT-CLI-SETUP.md) | PAT, auth, portals |
241
+ | [MODULES.md](./docs/MODULES.md) | Module build paths and overlay |
242
+ | [THEMES.md](./docs/THEMES.md) | Theme starter workflow |
243
+ | [BUILD-MODES.md](./docs/BUILD-MODES.md) | CDN vs monolith, tiers, prod guards |
244
+ | [ADAPTER.md](./docs/ADAPTER.md) | `wphs.adapter.ts` contract |
245
+ | [EXAMPLES.md](./docs/EXAMPLES.md) | Examples smoke matrix |
246
+ | [TROUBLESHOOTING.md](./docs/TROUBLESHOOTING.md) | Common failures |
247
+ | [RUNBOOK.md](./docs/RUNBOOK.md) | Ops and release notes |
248
+ | [CONTRIBUTING.md](./CONTRIBUTING.md) | PR and verify workflow |
249
+
250
+ ---
251
+
252
+ ## Develop the kit
253
+
254
+ ```bash
255
+ git clone https://github.com/Digital-Woods/digitalwoods.io-woodsportal-hubspot-kit.git
256
+ cd digitalwoods.io-woodsportal-hubspot-kit
257
+ npm ci
258
+ npm run verify # typecheck + test + examples smoke + build
259
+ ```
260
+
261
+ Link locally in a consumer:
262
+
263
+ ```bash
264
+ npm i -D @woodsportal/hubspot-kit@file:../digitalwoods.io-woodsportal-hubspot-kit
265
+ ```
57
266
 
58
- Node 20+, `@hubspot/cli`, HubSpot account with CMS.
267
+ ---
59
268
 
60
269
  ## License
61
270
 
62
- MIT — Digital Woods
271
+ MIT — [Digital Woods](https://github.com/Digital-Woods)
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/lib/exec.ts
4
- import { spawnSync } from "child_process";
4
+ import { spawn, spawnSync } from "child_process";
5
5
 
6
6
  // src/lib/errors.ts
7
7
  var ExitCode = {
@@ -76,12 +76,52 @@ ${detail}`, {
76
76
  function runNodeScript(scriptPath, args, options) {
77
77
  runCommand(process.execPath, [scriptPath, ...args], options);
78
78
  }
79
+ function runNodeScriptLongRunning(scriptPath, args, options) {
80
+ const { cwd, env = process.env, logger, dryRun = false } = options;
81
+ if (dryRun) {
82
+ logger?.info(`[dry-run] node ${scriptPath} ${args.join(" ")}`, { cwd });
83
+ return Promise.resolve(0);
84
+ }
85
+ return new Promise((resolve, reject) => {
86
+ const child = spawn(process.execPath, [scriptPath, ...args], {
87
+ cwd,
88
+ env,
89
+ stdio: "inherit"
90
+ });
91
+ const forwardSignal = (signal) => {
92
+ if (!child.killed) {
93
+ child.kill(signal);
94
+ }
95
+ };
96
+ process.on("SIGINT", forwardSignal);
97
+ process.on("SIGTERM", forwardSignal);
98
+ child.on("error", (error) => {
99
+ process.off("SIGINT", forwardSignal);
100
+ process.off("SIGTERM", forwardSignal);
101
+ reject(error);
102
+ });
103
+ child.on("exit", (code, signal) => {
104
+ process.off("SIGINT", forwardSignal);
105
+ process.off("SIGTERM", forwardSignal);
106
+ if (signal === "SIGINT") {
107
+ resolve(130);
108
+ return;
109
+ }
110
+ if (signal === "SIGTERM") {
111
+ resolve(143);
112
+ return;
113
+ }
114
+ resolve(code ?? 1);
115
+ });
116
+ });
117
+ }
79
118
 
80
119
  export {
81
120
  ExitCode,
82
121
  WpHsError,
83
122
  isWpHsError,
84
123
  runCommand,
85
- runNodeScript
124
+ runNodeScript,
125
+ runNodeScriptLongRunning
86
126
  };
87
- //# sourceMappingURL=chunk-JDGIAYHX.js.map
127
+ //# sourceMappingURL=chunk-GTTIJVAR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/exec.ts","../src/lib/errors.ts"],"sourcesContent":["import { spawn, spawnSync, type SpawnSyncOptions } from 'node:child_process'\n\nimport { WpHsError, ExitCode } from './errors.js'\nimport type { Logger } from './logger.js'\n\nconst SECRET_PATTERN = /(token|secret|password|pat|key)=/i\n\nfunction maskEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {\n const masked: NodeJS.ProcessEnv = { ...env }\n for (const key of Object.keys(masked)) {\n if (/token|secret|password|pat|auth/i.test(key) && masked[key]) {\n masked[key] = '[redacted]'\n }\n }\n return masked\n}\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}\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] } = options\n\n if (dryRun) {\n logger?.info(`[dry-run] ${command} ${args.join(' ')}`, { cwd })\n return { status: 0, stdout: '', stderr: '' }\n }\n\n logger?.debug(`exec: ${command} ${args.join(' ')}`, {\n cwd,\n env: logger ? maskEnv(env) : undefined,\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 if (!okCodes.includes(status)) {\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 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\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(`[dry-run] node ${scriptPath} ${args.join(' ')}`, { cwd })\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","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":[]}