@woodsportal/hubspot-kit 1.0.34 → 1.0.36
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 +14 -0
- package/dist/cli.js +170 -181
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
- package/scripts/node-loader-interop.mjs +20 -0
- package/scripts/run-dev.mjs +12 -75
- package/scripts/vite/consumer-react-aliases.js +31 -0
- package/scripts/vite/consumer-react-aliases.test.mjs +32 -0
- package/scripts/vite/create-dev-server-config.mjs +114 -0
- package/scripts/vite/ensure-dev-kit-shims.js +39 -14
- package/scripts/vite/ensure-dev-kit-shims.test.mjs +47 -0
- package/scripts/vite/react-dev-plugin-options.js +1 -1
- package/scripts/vite/resolve-from-project-root.js +14 -4
- package/vite/vite.config.dev.mjs +2 -81
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@woodsportal/hubspot-kit",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.36",
|
|
4
4
|
"description": "WoodsCLI — HubSpot CMS dev kit by WoodsPortal. wp CLI, Vite presets, module-config overlay, and theme/module build pipelines.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"build": "tsup",
|
|
52
52
|
"dev": "tsup --watch",
|
|
53
53
|
"typecheck": "tsc --noEmit",
|
|
54
|
-
"test": "node --import tsx --test 'src/lib/**/*.test.ts' 'src/schema/**/*.test.ts' 'src/vite/**/*.test.ts' 'scripts/portal-build-id.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",
|
|
54
|
+
"test": "node --import tsx --test 'src/lib/**/*.test.ts' 'src/schema/**/*.test.ts' 'src/vite/**/*.test.ts' 'scripts/portal-build-id.test.mjs' 'scripts/vite/ensure-dev-kit-shims.test.mjs' 'scripts/vite/consumer-react-aliases.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",
|
|
55
55
|
"test:examples": "node examples/smoke/run-matrix.mjs --tier static",
|
|
56
56
|
"lint": "eslint src",
|
|
57
57
|
"verify": "npm run typecheck && npm run test && npm run test:examples && npm run build",
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Current Active LTS — update when Node release schedule changes. */
|
|
2
|
+
export const NODE_LTS_RECOMMENDED = '24'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @returns {string | null}
|
|
6
|
+
* @see https://github.com/nodejs/node/issues/59366
|
|
7
|
+
*/
|
|
8
|
+
export function nodeLoaderInteropWarning() {
|
|
9
|
+
const [major, minor] = process.versions.node.split('.').map(Number)
|
|
10
|
+
|
|
11
|
+
if (major === 22 && minor >= 18) {
|
|
12
|
+
return `Node 22.18+ can fail loading Vite config (getStatus). Upgrade to Node ${NODE_LTS_RECOMMENDED} LTS or the latest Node 22 patch.`
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (major === 23 && minor < 4) {
|
|
16
|
+
return `Node 23.0–23.3 can fail loading Vite config (getStatus). Upgrade to Node ${NODE_LTS_RECOMMENDED} LTS.`
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return null
|
|
20
|
+
}
|
package/scripts/run-dev.mjs
CHANGED
|
@@ -1,92 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Local dev server —
|
|
4
|
-
*
|
|
3
|
+
* Local dev server — programmatic Vite (configFile: false) avoids fragile
|
|
4
|
+
* vite.config.* loading on some Node versions and keeps one config source.
|
|
5
5
|
*/
|
|
6
|
-
import { createRequire } from 'node:module'
|
|
7
|
-
import { dirname, resolve } from 'node:path'
|
|
8
|
-
import { pathToFileURL } from 'node:url'
|
|
9
|
-
|
|
10
6
|
import { findProjectRoot, getKitRoot } from './project-root.mjs'
|
|
7
|
+
import { importConsumerDep } from './resolve-consumer-dep.mjs'
|
|
8
|
+
import { createDevServerViteConfig } from './vite/create-dev-server-config.mjs'
|
|
11
9
|
|
|
12
10
|
const projectRoot = findProjectRoot()
|
|
13
11
|
const kitRoot = getKitRoot()
|
|
14
|
-
const require = createRequire(pathToFileURL(resolve(projectRoot, 'package.json')))
|
|
15
|
-
|
|
16
12
|
const port = Number(process.env.WP_HS_DEV_PORT ?? process.argv[2] ?? 3000)
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
const viteReact = require('@vitejs/plugin-react')
|
|
20
|
-
const { TanStackRouterVite } = require('@tanstack/router-plugin/vite')
|
|
21
|
-
const tailwindcss = require('@tailwindcss/vite')
|
|
22
|
-
|
|
23
|
-
const tailwindPrefixPlugin = (
|
|
24
|
-
await import(pathToFileURL(resolve(kitRoot, 'scripts/tailwind/prefix-plugin.js')).href)
|
|
25
|
-
).default
|
|
26
|
-
const TailwindContentPlugin = (
|
|
27
|
-
await import(pathToFileURL(resolve(kitRoot, 'scripts/tailwind/tailwind-content-plugin.js')).href)
|
|
28
|
-
).default
|
|
29
|
-
const sdkLogBridge = (
|
|
30
|
-
await import(pathToFileURL(resolve(kitRoot, 'scripts/vite/sdk-log-bridge.js')).href)
|
|
31
|
-
).default
|
|
32
|
-
const moduleConfigStore = (
|
|
33
|
-
await import(pathToFileURL(resolve(kitRoot, 'scripts/vite/module-config-store.js')).href)
|
|
34
|
-
).default
|
|
35
|
-
const resolveFromProjectRoot = (
|
|
36
|
-
await import(pathToFileURL(resolve(kitRoot, 'scripts/vite/resolve-from-project-root.js')).href)
|
|
37
|
-
).default
|
|
38
|
-
const { createDevReactPluginOptions } = await import(
|
|
39
|
-
pathToFileURL(resolve(kitRoot, 'scripts/vite/react-dev-plugin-options.js')).href
|
|
40
|
-
)
|
|
41
|
-
const { ensureDevKitShims } = await import(
|
|
42
|
-
pathToFileURL(resolve(kitRoot, 'scripts/vite/ensure-dev-kit-shims.js')).href
|
|
43
|
-
)
|
|
44
|
-
const isPrefix = (await import(pathToFileURL(resolve(kitRoot, 'scripts/tailwind/prefix.env.js')).href))
|
|
45
|
-
.default
|
|
14
|
+
process.env.WP_HS_PROJECT_ROOT = projectRoot
|
|
46
15
|
|
|
47
|
-
const
|
|
16
|
+
const userConfig = await createDevServerViteConfig({ projectRoot, kitRoot, port })
|
|
17
|
+
const resolved =
|
|
18
|
+
typeof userConfig === 'function'
|
|
19
|
+
? await userConfig({ mode: 'dev', command: 'serve' })
|
|
20
|
+
: await userConfig
|
|
48
21
|
|
|
22
|
+
const { createServer } = await importConsumerDep('vite')
|
|
49
23
|
const server = await createServer({
|
|
50
|
-
|
|
24
|
+
...resolved,
|
|
51
25
|
configFile: false,
|
|
52
26
|
mode: 'dev',
|
|
53
|
-
plugins: [
|
|
54
|
-
resolveFromProjectRoot(projectRoot, kitRoot),
|
|
55
|
-
sdkLogBridge(),
|
|
56
|
-
moduleConfigStore(projectRoot),
|
|
57
|
-
TanStackRouterVite({ autoCodeSplitting: false }),
|
|
58
|
-
viteReact.default?.(createDevReactPluginOptions()) ?? viteReact(createDevReactPluginOptions()),
|
|
59
|
-
tailwindcss.default?.() ?? tailwindcss(),
|
|
60
|
-
...(isPrefix('dev') ? [tailwindPrefixPlugin(), TailwindContentPlugin()] : []),
|
|
61
|
-
],
|
|
62
|
-
resolve: {
|
|
63
|
-
preserveSymlinks: true,
|
|
64
|
-
alias: {
|
|
65
|
-
'@/dev/module-config': moduleConfigRoot,
|
|
66
|
-
'@woodsportal/hubspot-kit/dev/bootstrap': bootstrapShim,
|
|
67
|
-
'@': resolve(projectRoot, './src'),
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
optimizeDeps: {
|
|
71
|
-
include: [
|
|
72
|
-
'react/compiler-runtime',
|
|
73
|
-
'react/jsx-dev-runtime',
|
|
74
|
-
'react/jsx-runtime',
|
|
75
|
-
'react-dom/client',
|
|
76
|
-
],
|
|
77
|
-
exclude: ['woodsportal-client-sdk', 'woodsportal-client-sdk/auth', 'woodsportal-client-sdk/crm'],
|
|
78
|
-
},
|
|
79
|
-
define: {
|
|
80
|
-
'process.env.NODE_ENV': JSON.stringify('development'),
|
|
81
|
-
'process.env': {},
|
|
82
|
-
process: JSON.stringify({ env: {} }),
|
|
83
|
-
},
|
|
84
|
-
server: {
|
|
85
|
-
port,
|
|
86
|
-
fs: {
|
|
87
|
-
allow: [projectRoot, kitRoot],
|
|
88
|
-
},
|
|
89
|
-
},
|
|
90
27
|
})
|
|
91
28
|
|
|
92
29
|
await server.listen()
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'
|
|
2
|
+
import { resolve } from 'node:path'
|
|
3
|
+
import { pathToFileURL } from 'node:url'
|
|
4
|
+
|
|
5
|
+
/** Subpath runtimes only — do not alias top-level `react` / `react-dom` (breaks `react/jsx-runtime`). */
|
|
6
|
+
const REACT_RUNTIME_SPECS = [
|
|
7
|
+
'react/jsx-runtime',
|
|
8
|
+
'react/jsx-dev-runtime',
|
|
9
|
+
'react-dom/client',
|
|
10
|
+
'react/compiler-runtime',
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Pin React runtimes to the consumer's node_modules so kit UI under `.wphs/` or
|
|
15
|
+
* `node_modules/@woodsportal/hubspot-kit` never loads a mismatched CJS copy in the browser.
|
|
16
|
+
*/
|
|
17
|
+
export function consumerReactAliases(projectRoot) {
|
|
18
|
+
const require = createRequire(pathToFileURL(resolve(projectRoot, 'package.json')))
|
|
19
|
+
/** @type {Record<string, string>} */
|
|
20
|
+
const alias = {}
|
|
21
|
+
|
|
22
|
+
for (const spec of REACT_RUNTIME_SPECS) {
|
|
23
|
+
try {
|
|
24
|
+
alias[spec] = require.resolve(spec)
|
|
25
|
+
} catch {
|
|
26
|
+
// consumer may omit optional subpaths until install completes
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return alias
|
|
31
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import assert from 'node:assert/strict'
|
|
2
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
|
|
3
|
+
import { tmpdir } from 'node:os'
|
|
4
|
+
import { join, resolve } from 'node:path'
|
|
5
|
+
import { describe, it } from 'node:test'
|
|
6
|
+
|
|
7
|
+
import { consumerReactAliases } from './consumer-react-aliases.js'
|
|
8
|
+
|
|
9
|
+
describe('consumerReactAliases', () => {
|
|
10
|
+
it('resolves react jsx runtimes from the consumer project root', () => {
|
|
11
|
+
const root = mkdtempSync(join(tmpdir(), 'wp-react-alias-'))
|
|
12
|
+
try {
|
|
13
|
+
mkdirSync(join(root, 'node_modules', 'react'), { recursive: true })
|
|
14
|
+
writeFileSync(
|
|
15
|
+
join(root, 'node_modules', 'react', 'package.json'),
|
|
16
|
+
JSON.stringify({
|
|
17
|
+
name: 'react',
|
|
18
|
+
exports: {
|
|
19
|
+
'./jsx-dev-runtime': './jsx-dev-runtime.js',
|
|
20
|
+
},
|
|
21
|
+
}),
|
|
22
|
+
)
|
|
23
|
+
writeFileSync(join(root, 'node_modules', 'react', 'jsx-dev-runtime.js'), 'export {}')
|
|
24
|
+
writeFileSync(join(root, 'package.json'), JSON.stringify({ name: 'fixture', type: 'module' }))
|
|
25
|
+
|
|
26
|
+
const alias = consumerReactAliases(root)
|
|
27
|
+
assert.match(alias['react/jsx-dev-runtime'], /node_modules[/\\]react[/\\]jsx-dev-runtime\.js$/)
|
|
28
|
+
} finally {
|
|
29
|
+
rmSync(root, { recursive: true, force: true })
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
})
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Vite dev-server config for `vite.config.dev.mjs` and `scripts/run-dev.mjs`.
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync } from 'node:fs'
|
|
5
|
+
import { resolve } from 'node:path'
|
|
6
|
+
|
|
7
|
+
import { importConsumerDep } from '../resolve-consumer-dep.mjs'
|
|
8
|
+
import { findProjectRoot, getKitRoot } from '../project-root.mjs'
|
|
9
|
+
import { readWoodsportalConfig } from '../read-woodsportal-config.mjs'
|
|
10
|
+
import { consumerReactAliases } from './consumer-react-aliases.js'
|
|
11
|
+
|
|
12
|
+
export async function createDevServerViteConfig(options = {}) {
|
|
13
|
+
const port = options.port ?? Number(process.env.WP_HS_DEV_PORT ?? 3000)
|
|
14
|
+
const projectRoot = options.projectRoot ?? findProjectRoot()
|
|
15
|
+
const kitRoot = options.kitRoot ?? getKitRoot()
|
|
16
|
+
|
|
17
|
+
const [
|
|
18
|
+
{ ensureDevKitShims },
|
|
19
|
+
{ default: bootstrapShimResolver },
|
|
20
|
+
{ default: resolveFromProjectRoot },
|
|
21
|
+
{ default: sdkLogBridge },
|
|
22
|
+
{ default: moduleConfigStore },
|
|
23
|
+
{ createDevReactPluginOptions },
|
|
24
|
+
{ default: isPrefix },
|
|
25
|
+
] = await Promise.all([
|
|
26
|
+
import('./ensure-dev-kit-shims.js'),
|
|
27
|
+
import('./bootstrap-shim-resolver.js'),
|
|
28
|
+
import('./resolve-from-project-root.js'),
|
|
29
|
+
import('./sdk-log-bridge.js'),
|
|
30
|
+
import('./module-config-store.js'),
|
|
31
|
+
import('./react-dev-plugin-options.js'),
|
|
32
|
+
import('../tailwind/prefix.env.js'),
|
|
33
|
+
])
|
|
34
|
+
|
|
35
|
+
const { moduleConfigRoot, bootstrapShim, bootstrapGreenfieldShim } = ensureDevKitShims(
|
|
36
|
+
projectRoot,
|
|
37
|
+
kitRoot,
|
|
38
|
+
)
|
|
39
|
+
const { config } = readWoodsportalConfig(projectRoot)
|
|
40
|
+
const routesDir = resolve(projectRoot, 'src/routes')
|
|
41
|
+
const hasTanStackRoutes = existsSync(routesDir)
|
|
42
|
+
|
|
43
|
+
const { defineConfig } = await importConsumerDep('vite')
|
|
44
|
+
const [{ default: viteReact }, { TanStackRouterVite }, { default: tailwindcss }] = await Promise.all([
|
|
45
|
+
importConsumerDep('@vitejs/plugin-react'),
|
|
46
|
+
importConsumerDep('@tanstack/router-plugin/vite'),
|
|
47
|
+
importConsumerDep('@tailwindcss/vite'),
|
|
48
|
+
])
|
|
49
|
+
|
|
50
|
+
return defineConfig(async ({ mode, command }) => {
|
|
51
|
+
const prefixPlugins = isPrefix(mode)
|
|
52
|
+
? [
|
|
53
|
+
(await import('../tailwind/prefix-plugin.js')).default(),
|
|
54
|
+
(await import('../tailwind/tailwind-content-plugin.js')).default(),
|
|
55
|
+
]
|
|
56
|
+
: []
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
root: projectRoot,
|
|
60
|
+
plugins: [
|
|
61
|
+
bootstrapShimResolver({ bootstrapShim, bootstrapGreenfieldShim, kitRoot }),
|
|
62
|
+
resolveFromProjectRoot(projectRoot, kitRoot),
|
|
63
|
+
...(command === 'serve' && mode === 'dev'
|
|
64
|
+
? [sdkLogBridge(), moduleConfigStore(projectRoot)]
|
|
65
|
+
: []),
|
|
66
|
+
...(hasTanStackRoutes ? [TanStackRouterVite({ autoCodeSplitting: false })] : []),
|
|
67
|
+
viteReact(createDevReactPluginOptions()),
|
|
68
|
+
tailwindcss(),
|
|
69
|
+
...prefixPlugins,
|
|
70
|
+
],
|
|
71
|
+
resolve: {
|
|
72
|
+
dedupe: ['react', 'react-dom'],
|
|
73
|
+
alias: {
|
|
74
|
+
...consumerReactAliases(projectRoot),
|
|
75
|
+
'@/dev/module-config': moduleConfigRoot,
|
|
76
|
+
'@wphs/bootstrap': bootstrapShim,
|
|
77
|
+
'@wphs/bootstrap-greenfield': bootstrapGreenfieldShim,
|
|
78
|
+
'@woodsportal/hubspot-kit/dev/bootstrap': bootstrapShim,
|
|
79
|
+
'@woodsportal/hubspot-kit/dev/bootstrap-greenfield': bootstrapGreenfieldShim,
|
|
80
|
+
'@wphs/adapter': resolve(projectRoot, config?.dev?.adapter ?? './wphs.adapter.ts'),
|
|
81
|
+
'@': resolve(projectRoot, './src'),
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
optimizeDeps: {
|
|
85
|
+
include: [
|
|
86
|
+
'react',
|
|
87
|
+
'react-dom',
|
|
88
|
+
'react/jsx-dev-runtime',
|
|
89
|
+
'react/jsx-runtime',
|
|
90
|
+
'react-dom/client',
|
|
91
|
+
],
|
|
92
|
+
exclude: [
|
|
93
|
+
'woodsportal-client-sdk',
|
|
94
|
+
'woodsportal-client-sdk/auth',
|
|
95
|
+
'woodsportal-client-sdk/crm',
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
define: {
|
|
99
|
+
'import.meta.env.VITE_WPHS_MODULE_NAME': JSON.stringify(
|
|
100
|
+
config?.module?.name ?? config?.theme?.name ?? 'module',
|
|
101
|
+
),
|
|
102
|
+
'process.env.NODE_ENV': JSON.stringify(mode === 'dev' ? 'development' : 'production'),
|
|
103
|
+
'process.env': {},
|
|
104
|
+
process: JSON.stringify({ env: {} }),
|
|
105
|
+
},
|
|
106
|
+
server: {
|
|
107
|
+
port,
|
|
108
|
+
fs: {
|
|
109
|
+
allow: [projectRoot, kitRoot],
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
}
|
|
@@ -1,23 +1,48 @@
|
|
|
1
|
-
import { existsSync, lstatSync, mkdirSync, rmSync, symlinkSync } from 'node:fs'
|
|
2
|
-
import { resolve } from 'node:path'
|
|
1
|
+
import { cpSync, existsSync, lstatSync, mkdirSync, rmSync, symlinkSync } from 'node:fs'
|
|
2
|
+
import { dirname, resolve } from 'node:path'
|
|
3
|
+
import { platform } from 'node:os'
|
|
3
4
|
|
|
4
5
|
import { moduleConfigPaths } from '../module-config-dir.mjs'
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
const isWin = platform() === 'win32'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Link or copy kit dev sources into `.wphs/` so Vite serves them in-project.
|
|
11
|
+
* Windows: directory junctions (no admin) and file copy fallback — symlinks often fail with EPERM.
|
|
12
|
+
*/
|
|
13
|
+
export function ensureKitShim(shimPath, target, { directory }) {
|
|
14
|
+
const targetAbs = resolve(target)
|
|
15
|
+
const shimAbs = resolve(shimPath)
|
|
16
|
+
|
|
7
17
|
try {
|
|
8
|
-
if (existsSync(
|
|
9
|
-
const stat = lstatSync(
|
|
18
|
+
if (existsSync(shimAbs)) {
|
|
19
|
+
const stat = lstatSync(shimAbs)
|
|
10
20
|
if (stat.isSymbolicLink()) {
|
|
11
|
-
return
|
|
21
|
+
return shimAbs
|
|
12
22
|
}
|
|
13
|
-
rmSync(
|
|
23
|
+
rmSync(shimAbs, { recursive: directory, force: true })
|
|
14
24
|
}
|
|
15
25
|
|
|
16
|
-
mkdirSync(
|
|
17
|
-
|
|
18
|
-
|
|
26
|
+
mkdirSync(dirname(shimAbs), { recursive: true })
|
|
27
|
+
|
|
28
|
+
if (isWin && directory) {
|
|
29
|
+
symlinkSync(targetAbs, shimAbs, 'junction')
|
|
30
|
+
return shimAbs
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
symlinkSync(targetAbs, shimAbs, directory ? 'dir' : 'file')
|
|
34
|
+
return shimAbs
|
|
19
35
|
} catch {
|
|
20
|
-
|
|
36
|
+
try {
|
|
37
|
+
if (existsSync(shimAbs)) {
|
|
38
|
+
rmSync(shimAbs, { recursive: directory, force: true })
|
|
39
|
+
}
|
|
40
|
+
mkdirSync(dirname(shimAbs), { recursive: true })
|
|
41
|
+
cpSync(targetAbs, shimAbs, { recursive: directory, force: true })
|
|
42
|
+
return shimAbs
|
|
43
|
+
} catch {
|
|
44
|
+
return targetAbs
|
|
45
|
+
}
|
|
21
46
|
}
|
|
22
47
|
}
|
|
23
48
|
|
|
@@ -28,19 +53,19 @@ function ensureSymlink(shimPath, target, { directory }) {
|
|
|
28
53
|
export function ensureDevKitShims(projectRoot, kitRoot) {
|
|
29
54
|
const { devDir } = moduleConfigPaths(projectRoot)
|
|
30
55
|
|
|
31
|
-
const moduleConfigRoot =
|
|
56
|
+
const moduleConfigRoot = ensureKitShim(
|
|
32
57
|
resolve(devDir, '.kit-module-config'),
|
|
33
58
|
resolve(kitRoot, 'src/dev-module-config'),
|
|
34
59
|
{ directory: true },
|
|
35
60
|
)
|
|
36
61
|
|
|
37
|
-
const bootstrapShim =
|
|
62
|
+
const bootstrapShim = ensureKitShim(
|
|
38
63
|
resolve(devDir, '.kit-bootstrap.tsx'),
|
|
39
64
|
resolve(kitRoot, 'src/dev/bootstrap.tsx'),
|
|
40
65
|
{ directory: false },
|
|
41
66
|
)
|
|
42
67
|
|
|
43
|
-
const bootstrapGreenfieldShim =
|
|
68
|
+
const bootstrapGreenfieldShim = ensureKitShim(
|
|
44
69
|
resolve(devDir, '.kit-bootstrap-greenfield.tsx'),
|
|
45
70
|
resolve(kitRoot, 'src/dev/bootstrap-greenfield.tsx'),
|
|
46
71
|
{ directory: false },
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import assert from 'node:assert/strict'
|
|
2
|
+
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
3
|
+
import { tmpdir } from 'node:os'
|
|
4
|
+
import { join, resolve } from 'node:path'
|
|
5
|
+
import { describe, it } from 'node:test'
|
|
6
|
+
|
|
7
|
+
import { ensureKitShim } from './ensure-dev-kit-shims.js'
|
|
8
|
+
|
|
9
|
+
describe('ensureKitShim', () => {
|
|
10
|
+
it('creates a file shim inside the consumer workspace', () => {
|
|
11
|
+
const root = mkdtempSync(join(tmpdir(), 'wp-kit-shim-file-'))
|
|
12
|
+
try {
|
|
13
|
+
const targetDir = join(root, 'kit', 'src', 'dev')
|
|
14
|
+
mkdirSync(targetDir, { recursive: true })
|
|
15
|
+
const target = join(targetDir, 'bootstrap.tsx')
|
|
16
|
+
writeFileSync(target, 'export {}')
|
|
17
|
+
|
|
18
|
+
const shim = join(root, 'project', '.wphs', '.kit-bootstrap.tsx')
|
|
19
|
+
const result = ensureKitShim(shim, target, { directory: false })
|
|
20
|
+
|
|
21
|
+
assert.equal(result, resolve(shim))
|
|
22
|
+
assert.equal(readFileSync(shim, 'utf8'), 'export {}')
|
|
23
|
+
} finally {
|
|
24
|
+
rmSync(root, { recursive: true, force: true })
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('creates a directory shim inside the consumer workspace', () => {
|
|
29
|
+
const root = mkdtempSync(join(tmpdir(), 'wp-kit-shim-dir-'))
|
|
30
|
+
try {
|
|
31
|
+
const targetDir = join(root, 'kit', 'src', 'dev-module-config', 'ui')
|
|
32
|
+
mkdirSync(targetDir, { recursive: true })
|
|
33
|
+
const targetFile = join(targetDir, 'HsFieldLabel.tsx')
|
|
34
|
+
writeFileSync(targetFile, 'export {}')
|
|
35
|
+
|
|
36
|
+
const shim = join(root, 'project', '.wphs', '.kit-module-config')
|
|
37
|
+
const result = ensureKitShim(shim, join(root, 'kit', 'src', 'dev-module-config'), {
|
|
38
|
+
directory: true,
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
assert.equal(result, resolve(shim))
|
|
42
|
+
assert.equal(readFileSync(join(shim, 'ui', 'HsFieldLabel.tsx'), 'utf8'), 'export {}')
|
|
43
|
+
} finally {
|
|
44
|
+
rmSync(root, { recursive: true, force: true })
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
})
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* but still use the React plugin's Babel JSX pipeline — do not use plugin `exclude`.
|
|
5
5
|
*/
|
|
6
6
|
const DEV_KIT_UI_RE =
|
|
7
|
-
/[/\\]dev-module-config[/\\]|[/\\]\.kit-bootstrap(?:-greenfield)?\.tsx$|[/\\]dev[/\\]bootstrap(?:-greenfield)?\.tsx$/
|
|
7
|
+
/[/\\](?:dev-module-config|\.kit-module-config)[/\\]|[/\\]\.kit-bootstrap(?:-greenfield)?\.tsx$|[/\\]dev[/\\]bootstrap(?:-greenfield)?\.tsx$/
|
|
8
8
|
|
|
9
9
|
export function createDevReactPluginOptions() {
|
|
10
10
|
return {
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'
|
|
2
|
-
import { resolve } from 'node:path'
|
|
2
|
+
import { resolve, sep } from 'node:path'
|
|
3
3
|
import { pathToFileURL } from 'node:url'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* When Vite transforms
|
|
7
|
-
* resolve from the consumer project's node_modules
|
|
6
|
+
* When Vite transforms kit dev UI (`.wphs/`, package src, or dev-module-config),
|
|
7
|
+
* bare imports must resolve from the consumer project's node_modules.
|
|
8
8
|
*/
|
|
9
9
|
export default function resolveFromProjectRoot(projectRoot, kitRoot) {
|
|
10
10
|
const require = createRequire(pathToFileURL(resolve(projectRoot, 'package.json')))
|
|
11
11
|
const kitRootNorm = resolve(kitRoot)
|
|
12
|
+
const wphsNorm = resolve(projectRoot, '.wphs')
|
|
13
|
+
|
|
14
|
+
function isKitUiImporter(importer) {
|
|
15
|
+
const norm = resolve(importer)
|
|
16
|
+
if (norm.startsWith(kitRootNorm)) return true
|
|
17
|
+
if (norm.includes(`${sep}.wphs${sep}`) || norm.includes(`${sep}.wphs`)) return true
|
|
18
|
+
if (norm.includes(`${sep}dev-module-config${sep}`)) return true
|
|
19
|
+
if (norm.includes(`${sep}.kit-module-config${sep}`)) return true
|
|
20
|
+
return false
|
|
21
|
+
}
|
|
12
22
|
|
|
13
23
|
return {
|
|
14
24
|
name: 'wp-resolve-from-project-root',
|
|
@@ -18,7 +28,7 @@ export default function resolveFromProjectRoot(projectRoot, kitRoot) {
|
|
|
18
28
|
if (source.startsWith('.') || source.startsWith('/') || source.startsWith('\0')) {
|
|
19
29
|
return null
|
|
20
30
|
}
|
|
21
|
-
if (!
|
|
31
|
+
if (!isKitUiImporter(importer)) {
|
|
22
32
|
return null
|
|
23
33
|
}
|
|
24
34
|
try {
|
package/vite/vite.config.dev.mjs
CHANGED
|
@@ -1,82 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { resolve } from 'node:path'
|
|
1
|
+
import { createDevServerViteConfig } from '../scripts/vite/create-dev-server-config.mjs'
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
import tailwindPrefixPlugin from '../scripts/tailwind/prefix-plugin.js'
|
|
6
|
-
import TailwindContentPlugin from '../scripts/tailwind/tailwind-content-plugin.js'
|
|
7
|
-
import sdkLogBridge from '../scripts/vite/sdk-log-bridge.js'
|
|
8
|
-
import moduleConfigStore from '../scripts/vite/module-config-store.js'
|
|
9
|
-
import resolveFromProjectRoot from '../scripts/vite/resolve-from-project-root.js'
|
|
10
|
-
import bootstrapShimResolver from '../scripts/vite/bootstrap-shim-resolver.js'
|
|
11
|
-
import { createDevReactPluginOptions } from '../scripts/vite/react-dev-plugin-options.js'
|
|
12
|
-
import { ensureDevKitShims } from '../scripts/vite/ensure-dev-kit-shims.js'
|
|
13
|
-
import isPrefix from '../scripts/tailwind/prefix.env.js'
|
|
14
|
-
import { findProjectRoot, getKitRoot } from '../scripts/project-root.mjs'
|
|
15
|
-
import { readWoodsportalConfig } from '../scripts/read-woodsportal-config.mjs'
|
|
16
|
-
|
|
17
|
-
const kitRoot = getKitRoot()
|
|
18
|
-
const projectRoot = findProjectRoot()
|
|
19
|
-
const { moduleConfigRoot, bootstrapShim, bootstrapGreenfieldShim } = ensureDevKitShims(projectRoot, kitRoot)
|
|
20
|
-
const { config } = readWoodsportalConfig(projectRoot)
|
|
21
|
-
const routesDir = resolve(projectRoot, 'src/routes')
|
|
22
|
-
const hasTanStackRoutes = existsSync(routesDir)
|
|
23
|
-
|
|
24
|
-
export default loadDevViteConfig()
|
|
25
|
-
|
|
26
|
-
async function loadDevViteConfig() {
|
|
27
|
-
// Load vite before plugins: parallel import of vite + @vitejs/plugin-react breaks on Node 20+ (CJS/ESM interop).
|
|
28
|
-
const { defineConfig } = await importConsumerDep('vite')
|
|
29
|
-
const [{ default: viteReact }, { TanStackRouterVite }, { default: tailwindcss }] = await Promise.all([
|
|
30
|
-
importConsumerDep('@vitejs/plugin-react'),
|
|
31
|
-
importConsumerDep('@tanstack/router-plugin/vite'),
|
|
32
|
-
importConsumerDep('@tailwindcss/vite'),
|
|
33
|
-
])
|
|
34
|
-
|
|
35
|
-
return defineConfig(({ mode, command }) => ({
|
|
36
|
-
root: projectRoot,
|
|
37
|
-
plugins: [
|
|
38
|
-
bootstrapShimResolver({ bootstrapShim, bootstrapGreenfieldShim, kitRoot }),
|
|
39
|
-
resolveFromProjectRoot(projectRoot, kitRoot),
|
|
40
|
-
...(command === 'serve' && mode === 'dev'
|
|
41
|
-
? [sdkLogBridge(), moduleConfigStore(projectRoot)]
|
|
42
|
-
: []),
|
|
43
|
-
...(hasTanStackRoutes ? [TanStackRouterVite({ autoCodeSplitting: false })] : []),
|
|
44
|
-
viteReact(createDevReactPluginOptions()),
|
|
45
|
-
tailwindcss(),
|
|
46
|
-
...(isPrefix(mode) ? [tailwindPrefixPlugin(), TailwindContentPlugin()] : []),
|
|
47
|
-
],
|
|
48
|
-
resolve: {
|
|
49
|
-
preserveSymlinks: true,
|
|
50
|
-
alias: {
|
|
51
|
-
'@/dev/module-config': moduleConfigRoot,
|
|
52
|
-
'@wphs/bootstrap': bootstrapShim,
|
|
53
|
-
'@wphs/bootstrap-greenfield': bootstrapGreenfieldShim,
|
|
54
|
-
'@woodsportal/hubspot-kit/dev/bootstrap': bootstrapShim,
|
|
55
|
-
'@woodsportal/hubspot-kit/dev/bootstrap-greenfield': bootstrapGreenfieldShim,
|
|
56
|
-
'@wphs/adapter': resolve(projectRoot, config?.dev?.adapter ?? './wphs.adapter.ts'),
|
|
57
|
-
'@': resolve(projectRoot, './src'),
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
optimizeDeps: {
|
|
61
|
-
exclude: [
|
|
62
|
-
'woodsportal-client-sdk',
|
|
63
|
-
'woodsportal-client-sdk/auth',
|
|
64
|
-
'woodsportal-client-sdk/crm',
|
|
65
|
-
],
|
|
66
|
-
},
|
|
67
|
-
define: {
|
|
68
|
-
'import.meta.env.VITE_WPHS_MODULE_NAME': JSON.stringify(
|
|
69
|
-
config?.module?.name ?? config?.theme?.name ?? 'module',
|
|
70
|
-
),
|
|
71
|
-
'process.env.NODE_ENV': JSON.stringify(mode === 'dev' ? 'development' : 'production'),
|
|
72
|
-
'process.env': {},
|
|
73
|
-
process: JSON.stringify({ env: {} }),
|
|
74
|
-
},
|
|
75
|
-
server: {
|
|
76
|
-
port: 3000,
|
|
77
|
-
fs: {
|
|
78
|
-
allow: [projectRoot, kitRoot],
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
}))
|
|
82
|
-
}
|
|
3
|
+
export default createDevServerViteConfig()
|