@woodsportal/hubspot-kit 5.0.3-beta.2 → 5.0.3-beta.3
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@woodsportal/hubspot-kit",
|
|
3
|
-
"version": "5.0.3-beta.
|
|
3
|
+
"version": "5.0.3-beta.3",
|
|
4
4
|
"packageManager": "pnpm@10.12.1",
|
|
5
5
|
"description": "WoodsCLI — HubSpot CMS dev kit by WoodsPortal. wp CLI, Vite presets, module-config overlay, and theme/module build pipelines.",
|
|
6
6
|
"type": "module",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"build": "tsup",
|
|
53
53
|
"dev": "tsup --watch",
|
|
54
54
|
"typecheck": "tsc --noEmit",
|
|
55
|
-
"test": "node --import tsx --test 'src/lib/**/*.test.ts' 'src/cli/**/*.test.ts' 'src/schema/**/*.test.ts' 'src/vite/**/*.test.ts' 'scripts/portal-build-id.test.mjs' 'scripts/resolve-consumer-dep.test.mjs' 'scripts/wp-cli-smoke.test.mjs' 'scripts/vite/ensure-dev-kit-shims.test.mjs' 'scripts/vite/consumer-react-aliases.test.mjs' 'scripts/vite/resolve-from-project-root.test.mjs' 'scripts/tailwind/prefix-plugin.test.mjs' && vitest run src/dev-module-config/__tests__/normalize-repeater-items.test.ts src/dev-module-config/__tests__/module-config-transform.test.ts src/dev-module-config/__tests__/flatten-visible-fields.test.ts src/dev-module-config/__tests__/drill-down-panels.test.ts",
|
|
55
|
+
"test": "node --import tsx --test 'src/lib/**/*.test.ts' 'src/cli/**/*.test.ts' 'src/schema/**/*.test.ts' 'src/vite/**/*.test.ts' 'scripts/portal-build-id.test.mjs' 'scripts/cdn-release-artifacts.test.mjs' 'scripts/hubspot-module-postbuild.test.mjs' 'scripts/resolve-consumer-dep.test.mjs' 'scripts/wp-cli-smoke.test.mjs' 'scripts/vite/ensure-dev-kit-shims.test.mjs' 'scripts/vite/consumer-react-aliases.test.mjs' 'scripts/vite/resolve-from-project-root.test.mjs' 'scripts/tailwind/prefix-plugin.test.mjs' && vitest run src/dev-module-config/__tests__/normalize-repeater-items.test.ts src/dev-module-config/__tests__/module-config-transform.test.ts src/dev-module-config/__tests__/flatten-visible-fields.test.ts src/dev-module-config/__tests__/drill-down-panels.test.ts",
|
|
56
56
|
"test:examples": "node examples/smoke/run-matrix.mjs --tier static",
|
|
57
57
|
"test:dist-pack": "node --test scripts/dist-cli-pack-smoke.test.mjs",
|
|
58
58
|
"lint": "eslint src",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Write dist/cdn/manifest.json after vendor + app builds.
|
|
4
4
|
*/
|
|
5
|
-
import { readdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
5
|
+
import { readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
6
6
|
import { resolve } from 'node:path'
|
|
7
7
|
import { gzipSync } from 'node:zlib'
|
|
8
8
|
|
|
@@ -52,8 +52,11 @@ const allJsRelPaths = readdirSync(cdnDir, { recursive: true })
|
|
|
52
52
|
const staleJs = allJsRelPaths.filter((file) => !cdnArtifactMatchesBuildId(buildId, file))
|
|
53
53
|
if (staleJs.length > 0) {
|
|
54
54
|
console.warn(
|
|
55
|
-
`[cdn-manifest]
|
|
55
|
+
`[cdn-manifest] removing ${staleJs.length} stale .js artifact(s) for buildId ${buildId}: ${staleJs.join(', ')}`,
|
|
56
56
|
)
|
|
57
|
+
for (const file of staleJs) {
|
|
58
|
+
rmSync(resolve(cdnDir, file), { force: true })
|
|
59
|
+
}
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
const jsFiles = allJsRelPaths
|
|
@@ -72,8 +75,11 @@ const allCssFiles = readdirSync(cdnDir).filter((f) => f.endsWith('.css'))
|
|
|
72
75
|
const staleCss = allCssFiles.filter((file) => !cdnArtifactMatchesBuildId(buildId, file))
|
|
73
76
|
if (staleCss.length > 0) {
|
|
74
77
|
console.warn(
|
|
75
|
-
`[cdn-manifest]
|
|
78
|
+
`[cdn-manifest] removing ${staleCss.length} stale .css artifact(s) for buildId ${buildId}: ${staleCss.join(', ')}`,
|
|
76
79
|
)
|
|
80
|
+
for (const file of staleCss) {
|
|
81
|
+
rmSync(resolve(cdnDir, file), { force: true })
|
|
82
|
+
}
|
|
77
83
|
}
|
|
78
84
|
|
|
79
85
|
const cssFiles = allCssFiles
|
|
@@ -55,14 +55,70 @@ export function assertValidJavaScriptSyntax(jsPath) {
|
|
|
55
55
|
execSync(`node --check ${JSON.stringify(jsPath)}`, { stdio: 'pipe' })
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* CodeBuild sets MODULE_BUILD_ID; never let a leftover manifest.buildId win.
|
|
60
|
+
* @param {{ buildId?: string }} manifest
|
|
61
|
+
* @param {NodeJS.ProcessEnv} [env]
|
|
62
|
+
*/
|
|
63
|
+
export function resolveInjectBuildId(manifest, env = process.env) {
|
|
64
|
+
const envId = env.MODULE_BUILD_ID?.trim() || env.PORTAL_BUILD_ID?.trim()
|
|
65
|
+
const manifestId = manifest.buildId?.trim()
|
|
66
|
+
const buildId = envId || manifestId
|
|
67
|
+
if (!buildId) {
|
|
68
|
+
throw new Error('module.html inject needs manifest.buildId or MODULE_BUILD_ID')
|
|
69
|
+
}
|
|
70
|
+
return buildId
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Pin HubL/JS CDN fields even when a stale worker already baked an older build id.
|
|
75
|
+
* @param {string} html
|
|
76
|
+
* @param {{ baseUrl: string, buildId: string, vendorFile: string, appFile: string, appCssFile: string }} pins
|
|
77
|
+
*/
|
|
78
|
+
export function pinModuleHtmlCdnUrls(html, pins) {
|
|
79
|
+
const { baseUrl, buildId, vendorFile, appFile, appCssFile } = pins
|
|
80
|
+
let out = html
|
|
81
|
+
.replaceAll('__PORTAL_CDN_BASE__', baseUrl)
|
|
82
|
+
.replaceAll('__PORTAL_BUILD_ID__', buildId)
|
|
83
|
+
.replaceAll('__PORTAL_VENDOR_FILE__', vendorFile)
|
|
84
|
+
.replaceAll('__PORTAL_APP_FILE__', appFile)
|
|
85
|
+
.replaceAll('__PORTAL_APP_CSS_FILE__', appCssFile)
|
|
86
|
+
|
|
87
|
+
out = out.replace(/assetBaseUrl:\s*"[^"]*"/g, `assetBaseUrl: "${baseUrl}"`)
|
|
88
|
+
out = out.replace(/buildId:\s*"[^"]*"/g, `buildId: "${buildId}"`)
|
|
89
|
+
out = out.replace(
|
|
90
|
+
/\{% set portal_cdn_base = "[^"]*" %\}/g,
|
|
91
|
+
`{% set portal_cdn_base = "${baseUrl}" %}`,
|
|
92
|
+
)
|
|
93
|
+
out = out.replace(
|
|
94
|
+
/\{% set portal_vendor_script = "[^"]*" %\}/g,
|
|
95
|
+
`{% set portal_vendor_script = "${vendorFile}" %}`,
|
|
96
|
+
)
|
|
97
|
+
out = out.replace(
|
|
98
|
+
/\{% set portal_app_script = "[^"]*" %\}/g,
|
|
99
|
+
`{% set portal_app_script = "${appFile}" %}`,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
if (!out.includes(buildId) || !out.includes(vendorFile) || !out.includes(appFile)) {
|
|
103
|
+
throw new Error(
|
|
104
|
+
`module.html inject failed: expected ${vendorFile} and ${appFile} for buildId ${buildId}`,
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
if (out.includes('__PORTAL_')) {
|
|
108
|
+
throw new Error('module.html still has CDN placeholders after inject')
|
|
109
|
+
}
|
|
110
|
+
return out
|
|
111
|
+
}
|
|
112
|
+
|
|
58
113
|
/**
|
|
59
114
|
* Replace CDN placeholders in module.html from dist/cdn/manifest.json.
|
|
60
115
|
* @param {string} html
|
|
61
116
|
* @param {string} manifestPath
|
|
117
|
+
* @param {NodeJS.ProcessEnv} [env]
|
|
62
118
|
*/
|
|
63
|
-
export function injectCdnManifestIntoModuleHtml(html, manifestPath) {
|
|
119
|
+
export function injectCdnManifestIntoModuleHtml(html, manifestPath, env = process.env) {
|
|
64
120
|
if (!existsSync(manifestPath)) {
|
|
65
|
-
if (html.includes('__PORTAL_CDN_BASE__')) {
|
|
121
|
+
if (html.includes('__PORTAL_CDN_BASE__') || /vendor\.\d/.test(html) || html.includes('portal_vendor_script')) {
|
|
66
122
|
throw new Error(
|
|
67
123
|
`Missing ${manifestPath} — run yarn build:cdn:dev or yarn build:cdn:prod before hubspot post-build`,
|
|
68
124
|
)
|
|
@@ -71,14 +127,16 @@ export function injectCdnManifestIntoModuleHtml(html, manifestPath) {
|
|
|
71
127
|
}
|
|
72
128
|
|
|
73
129
|
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'))
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
130
|
+
const buildId = resolveInjectBuildId(manifest, env)
|
|
131
|
+
const { vendorFile, appFile, appCssFile } = resolveCdnPrimaryScripts({ ...manifest, buildId })
|
|
132
|
+
|
|
133
|
+
return pinModuleHtmlCdnUrls(html, {
|
|
134
|
+
baseUrl: manifest.baseUrl,
|
|
135
|
+
buildId,
|
|
136
|
+
vendorFile,
|
|
137
|
+
appFile,
|
|
138
|
+
appCssFile,
|
|
139
|
+
})
|
|
82
140
|
}
|
|
83
141
|
|
|
84
142
|
/**
|
|
@@ -91,7 +149,8 @@ export function mergeCdnAppStylesIntoModuleCss(moduleDir, manifestPath) {
|
|
|
91
149
|
}
|
|
92
150
|
|
|
93
151
|
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'))
|
|
94
|
-
const
|
|
152
|
+
const buildId = resolveInjectBuildId(manifest)
|
|
153
|
+
const { appCssFile } = resolveCdnPrimaryScripts({ ...manifest, buildId })
|
|
95
154
|
|
|
96
155
|
const cdnCssPath = resolve(moduleDir, '../cdn', appCssFile)
|
|
97
156
|
if (!existsSync(cdnCssPath)) {
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import assert from 'node:assert/strict'
|
|
2
|
+
import { mkdtempSync, writeFileSync } from 'node:fs'
|
|
3
|
+
import { tmpdir } from 'node:os'
|
|
4
|
+
import { join } from 'node:path'
|
|
5
|
+
import { describe, it } from 'node:test'
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
injectCdnManifestIntoModuleHtml,
|
|
9
|
+
pinModuleHtmlCdnUrls,
|
|
10
|
+
resolveInjectBuildId,
|
|
11
|
+
} from './hubspot-module-postbuild.mjs'
|
|
12
|
+
|
|
13
|
+
const placeholders = ` assetBaseUrl: "__PORTAL_CDN_BASE__",
|
|
14
|
+
buildId: "__PORTAL_BUILD_ID__",
|
|
15
|
+
{% set portal_cdn_base = "__PORTAL_CDN_BASE__" %}
|
|
16
|
+
{% set portal_vendor_script = "__PORTAL_VENDOR_FILE__" %}
|
|
17
|
+
{% set portal_app_script = "__PORTAL_APP_FILE__" %}
|
|
18
|
+
`
|
|
19
|
+
|
|
20
|
+
const baked800 = ` assetBaseUrl: "https://cdn.example/cdn",
|
|
21
|
+
buildId: "5.0.2-beta.800",
|
|
22
|
+
{% set portal_cdn_base = "https://cdn.example/cdn" %}
|
|
23
|
+
{% set portal_vendor_script = "vendor.5.0.2-beta.800.js" %}
|
|
24
|
+
{% set portal_app_script = "app.5.0.2-beta.800.js" %}
|
|
25
|
+
`
|
|
26
|
+
|
|
27
|
+
describe('resolveInjectBuildId', () => {
|
|
28
|
+
it('prefers MODULE_BUILD_ID over a stale manifest.buildId', () => {
|
|
29
|
+
assert.equal(
|
|
30
|
+
resolveInjectBuildId({ buildId: '5.0.2-beta.800' }, { MODULE_BUILD_ID: '5.0.2-beta.804' }),
|
|
31
|
+
'5.0.2-beta.804',
|
|
32
|
+
)
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
describe('pinModuleHtmlCdnUrls', () => {
|
|
37
|
+
it('rewrites leftover baked 800 pins to the current build id', () => {
|
|
38
|
+
const out = pinModuleHtmlCdnUrls(baked800, {
|
|
39
|
+
baseUrl: 'https://cdn.example/cdn',
|
|
40
|
+
buildId: '5.0.2-beta.804',
|
|
41
|
+
vendorFile: 'vendor.5.0.2-beta.804.js',
|
|
42
|
+
appFile: 'app.5.0.2-beta.804.js',
|
|
43
|
+
appCssFile: 'app.5.0.2-beta.804.css',
|
|
44
|
+
})
|
|
45
|
+
assert.match(out, /buildId: "5\.0\.2-beta\.804"/)
|
|
46
|
+
assert.match(out, /vendor\.5\.0\.2-beta\.804\.js/)
|
|
47
|
+
assert.match(out, /app\.5\.0\.2-beta\.804\.js/)
|
|
48
|
+
assert.doesNotMatch(out, /5\.0\.2-beta\.800/)
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
describe('injectCdnManifestIntoModuleHtml', () => {
|
|
53
|
+
it('pins vendor/app from MODULE_BUILD_ID even when the manifest still lists 800 first', () => {
|
|
54
|
+
const dir = mkdtempSync(join(tmpdir(), 'wp-mod-html-'))
|
|
55
|
+
const manifestPath = join(dir, 'manifest.json')
|
|
56
|
+
writeFileSync(
|
|
57
|
+
manifestPath,
|
|
58
|
+
JSON.stringify({
|
|
59
|
+
baseUrl: 'https://cdn.example/cdn',
|
|
60
|
+
buildId: '5.0.2-beta.800',
|
|
61
|
+
scripts: [
|
|
62
|
+
{ name: 'vendor', file: 'vendor.5.0.2-beta.800.js' },
|
|
63
|
+
{ name: 'vendor', file: 'vendor.5.0.2-beta.804.js' },
|
|
64
|
+
{ name: 'app', file: 'app.5.0.2-beta.800.js' },
|
|
65
|
+
{ name: 'app', file: 'app.5.0.2-beta.804.js' },
|
|
66
|
+
],
|
|
67
|
+
styles: [
|
|
68
|
+
{ name: 'app', file: 'app.5.0.2-beta.800.css' },
|
|
69
|
+
{ name: 'app', file: 'app.5.0.2-beta.804.css' },
|
|
70
|
+
],
|
|
71
|
+
}),
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
const fromPlaceholders = injectCdnManifestIntoModuleHtml(placeholders, manifestPath, {
|
|
75
|
+
MODULE_BUILD_ID: '5.0.2-beta.804',
|
|
76
|
+
})
|
|
77
|
+
assert.match(fromPlaceholders, /vendor\.5\.0\.2-beta\.804\.js/)
|
|
78
|
+
assert.doesNotMatch(fromPlaceholders, /5\.0\.2-beta\.800/)
|
|
79
|
+
|
|
80
|
+
const fromBaked = injectCdnManifestIntoModuleHtml(baked800, manifestPath, {
|
|
81
|
+
MODULE_BUILD_ID: '5.0.2-beta.804',
|
|
82
|
+
})
|
|
83
|
+
assert.match(fromBaked, /vendor\.5\.0\.2-beta\.804\.js/)
|
|
84
|
+
assert.doesNotMatch(fromBaked, /5\.0\.2-beta\.800/)
|
|
85
|
+
})
|
|
86
|
+
})
|