@woodsportal/hubspot-kit 1.0.35 → 1.0.37

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": "1.0.35",
3
+ "version": "1.0.37",
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' 'scripts/vite/ensure-dev-kit-shims.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/resolve-consumer-dep.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",
@@ -1,25 +1,90 @@
1
1
  /**
2
2
  * Resolve and import packages from the consumer project (woodscli.json root).
3
- * Kit scripts live under @woodsportal/hubspot-kit; Vite/React plugins are consumer deps.
3
+ * Pure filesystem resolution — avoids createRequire (Node 24+ getStatus) and
4
+ * import.meta.resolve from kit context (wrong node_modules).
4
5
  */
5
- import { createRequire } from 'node:module'
6
- import { resolve } from 'node:path'
6
+ import { existsSync, readFileSync } from 'node:fs'
7
+ import { resolve, sep } from 'node:path'
7
8
  import { pathToFileURL } from 'node:url'
9
+
8
10
  import { findProjectRoot } from './project-root.mjs'
9
11
 
10
12
  /**
11
- * @param {string} specifier - package name or subpath export
13
+ * @param {string} specifier
14
+ * @param {string} projectRoot
15
+ */
16
+ function readPkgJson(projectRoot, pkgName) {
17
+ const pkgJsonPath = resolve(projectRoot, 'node_modules', ...pkgName.split('/'), 'package.json')
18
+ if (!existsSync(pkgJsonPath)) {
19
+ throw new Error(`Cannot find package '${pkgName}' under ${projectRoot}`)
20
+ }
21
+ return { pkgJsonPath, pkg: JSON.parse(readFileSync(pkgJsonPath, 'utf8')) }
22
+ }
23
+
24
+ /**
25
+ * @param {string} pkgRoot
26
+ * @param {string} target
27
+ */
28
+ function resolveTargetFile(pkgRoot, target) {
29
+ const rel = target.replace(/^\.\//, '')
30
+ const abs = resolve(pkgRoot, rel)
31
+ if (existsSync(abs)) return abs
32
+ if (existsSync(`${abs}.js`)) return `${abs}.js`
33
+ if (existsSync(`${abs}.mjs`)) return `${abs}.mjs`
34
+ if (existsSync(resolve(abs, 'index.js'))) return resolve(abs, 'index.js')
35
+ return abs
36
+ }
37
+
38
+ /**
39
+ * @param {unknown} exportEntry
40
+ * @returns {string | null}
12
41
  */
13
- export function resolveConsumerDep(specifier) {
14
- const root = findProjectRoot()
15
- const require = createRequire(resolve(root, 'package.json'))
16
- return require.resolve(specifier)
42
+ function pickExportTarget(exportEntry) {
43
+ if (typeof exportEntry === 'string') return exportEntry
44
+ if (!exportEntry || typeof exportEntry !== 'object') return null
45
+
46
+ const record = /** @type {Record<string, unknown>} */ (exportEntry)
47
+ for (const key of ['import', 'default', 'node', 'require', 'module-sync']) {
48
+ const val = record[key]
49
+ if (typeof val === 'string') return val
50
+ const nested = pickExportTarget(val)
51
+ if (nested) return nested
52
+ }
53
+ return null
54
+ }
55
+
56
+ /**
57
+ * @param {string} specifier e.g. vite, @vitejs/plugin-react, react/jsx-dev-runtime
58
+ * @param {string} projectRoot
59
+ */
60
+ export function resolveConsumerDep(specifier, projectRoot = findProjectRoot()) {
61
+ const segments = specifier.split('/')
62
+ const pkgName = segments[0].startsWith('@')
63
+ ? `${segments[0]}/${segments[1]}`
64
+ : segments[0]
65
+ const subpath = segments[0].startsWith('@') ? segments.slice(2).join('/') : segments.slice(1).join('/')
66
+ const pkgRoot = resolve(projectRoot, 'node_modules', ...pkgName.split('/'))
67
+ const { pkg } = readPkgJson(projectRoot, pkgName)
68
+
69
+ if (!subpath) {
70
+ const rootExport = pickExportTarget(pkg.exports?.['.']) ?? pkg.module ?? pkg.main ?? 'index.js'
71
+ return resolveTargetFile(pkgRoot, rootExport)
72
+ }
73
+
74
+ const exportKey = `./${subpath}`
75
+ const exportTarget = pickExportTarget(pkg.exports?.[exportKey])
76
+ if (exportTarget) {
77
+ return resolveTargetFile(pkgRoot, exportTarget)
78
+ }
79
+
80
+ return resolveTargetFile(pkgRoot, subpath)
17
81
  }
18
82
 
19
83
  /**
20
84
  * @param {string} specifier
85
+ * @param {string} [projectRoot]
21
86
  */
22
- export async function importConsumerDep(specifier) {
23
- const resolved = resolveConsumerDep(specifier)
24
- return import(pathToFileURL(resolved).href)
87
+ export async function importConsumerDep(specifier, projectRoot = findProjectRoot()) {
88
+ const abs = resolveConsumerDep(specifier, projectRoot)
89
+ return import(pathToFileURL(abs).href)
25
90
  }
@@ -0,0 +1,22 @@
1
+ import assert from 'node:assert/strict'
2
+ import { describe, it } from 'node:test'
3
+
4
+ import { importConsumerDep, resolveConsumerDep } from './resolve-consumer-dep.mjs'
5
+ import { consumerDepFixtureRoot } from './test-fixtures/consumer-dep-fixture-root.mjs'
6
+
7
+ describe('resolveConsumerDep', () => {
8
+ it('resolves vite from consumer node_modules via filesystem resolver', () => {
9
+ const vitePath = resolveConsumerDep('vite', consumerDepFixtureRoot)
10
+ assert.match(vitePath, /node_modules[/\\]vite[/\\]/)
11
+ })
12
+
13
+ it('imports vite without createRequire', async () => {
14
+ const vite = await importConsumerDep('vite', consumerDepFixtureRoot)
15
+ assert.equal(typeof vite.createServer, 'function')
16
+ })
17
+
18
+ it('resolves nested package exports (TanStack router vite subpath)', () => {
19
+ const path = resolveConsumerDep('@tanstack/router-plugin/vite', consumerDepFixtureRoot)
20
+ assert.match(path, /node_modules[/\\]@tanstack[/\\]router-plugin[/\\]/)
21
+ })
22
+ })
@@ -1,107 +1,29 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Local dev server — loads Vite and plugins from the consumer project's node_modules
4
- * (configFile: false) so the kit does not need its own vite install.
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 { existsSync } from 'node:fs'
7
- import { resolve } from 'node:path'
8
-
9
- import { importConsumerDep } from './resolve-consumer-dep.mjs'
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
12
  const port = Number(process.env.WP_HS_DEV_PORT ?? process.argv[2] ?? 3000)
15
13
 
16
- const [
17
- { ensureDevKitShims },
18
- { default: resolveFromProjectRoot },
19
- { default: sdkLogBridge },
20
- { default: moduleConfigStore },
21
- { createDevReactPluginOptions },
22
- { default: isPrefix },
23
- { default: bootstrapShimResolver },
24
- { readWoodsportalConfig },
25
- { createServer },
26
- viteReactMod,
27
- tanstackMod,
28
- tailwindcssMod,
29
- ] = await Promise.all([
30
- import('./vite/ensure-dev-kit-shims.js'),
31
- import('./vite/resolve-from-project-root.js'),
32
- import('./vite/sdk-log-bridge.js'),
33
- import('./vite/module-config-store.js'),
34
- import('./vite/react-dev-plugin-options.js'),
35
- import('./tailwind/prefix.env.js'),
36
- import('./vite/bootstrap-shim-resolver.js'),
37
- import('./read-woodsportal-config.mjs'),
38
- importConsumerDep('vite'),
39
- importConsumerDep('@vitejs/plugin-react'),
40
- importConsumerDep('@tanstack/router-plugin/vite'),
41
- importConsumerDep('@tailwindcss/vite'),
42
- ])
43
-
44
- const viteReact = viteReactMod.default ?? viteReactMod
45
- const { TanStackRouterVite } = tanstackMod
46
- const tailwindcss = tailwindcssMod.default ?? tailwindcssMod
47
-
48
- const { moduleConfigRoot, bootstrapShim, bootstrapGreenfieldShim } = ensureDevKitShims(
49
- projectRoot,
50
- kitRoot,
51
- )
52
- const { config } = readWoodsportalConfig(projectRoot)
53
- const routesDir = resolve(projectRoot, 'src/routes')
54
- const hasTanStackRoutes = existsSync(routesDir)
14
+ process.env.WP_HS_PROJECT_ROOT = projectRoot
55
15
 
56
- const prefixPlugins = isPrefix('dev')
57
- ? [
58
- (await import('./tailwind/prefix-plugin.js')).default(),
59
- (await import('./tailwind/tailwind-content-plugin.js')).default(),
60
- ]
61
- : []
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
62
21
 
22
+ const { createServer } = await importConsumerDep('vite')
63
23
  const server = await createServer({
64
- root: projectRoot,
24
+ ...resolved,
65
25
  configFile: false,
66
26
  mode: 'dev',
67
- plugins: [
68
- bootstrapShimResolver({ bootstrapShim, bootstrapGreenfieldShim, kitRoot }),
69
- resolveFromProjectRoot(projectRoot, kitRoot),
70
- sdkLogBridge(),
71
- moduleConfigStore(projectRoot),
72
- ...(hasTanStackRoutes ? [TanStackRouterVite({ autoCodeSplitting: false })] : []),
73
- viteReact(createDevReactPluginOptions()),
74
- tailwindcss(),
75
- ...prefixPlugins,
76
- ],
77
- resolve: {
78
- preserveSymlinks: true,
79
- dedupe: ['react', 'react-dom'],
80
- alias: {
81
- '@/dev/module-config': moduleConfigRoot,
82
- '@wphs/bootstrap': bootstrapShim,
83
- '@wphs/bootstrap-greenfield': bootstrapGreenfieldShim,
84
- '@woodsportal/hubspot-kit/dev/bootstrap': bootstrapShim,
85
- '@woodsportal/hubspot-kit/dev/bootstrap-greenfield': bootstrapGreenfieldShim,
86
- '@wphs/adapter': resolve(projectRoot, config?.dev?.adapter ?? './wphs.adapter.ts'),
87
- '@': resolve(projectRoot, './src'),
88
- },
89
- },
90
- optimizeDeps: {
91
- include: ['react', 'react-dom', 'react/jsx-dev-runtime', 'react/jsx-runtime'],
92
- exclude: ['woodsportal-client-sdk', 'woodsportal-client-sdk/auth', 'woodsportal-client-sdk/crm'],
93
- },
94
- define: {
95
- 'process.env.NODE_ENV': JSON.stringify('development'),
96
- 'process.env': {},
97
- process: JSON.stringify({ env: {} }),
98
- },
99
- server: {
100
- port,
101
- fs: {
102
- allow: [projectRoot, kitRoot],
103
- },
104
- },
105
27
  })
106
28
 
107
29
  await server.listen()
@@ -0,0 +1,3 @@
1
+ export function TanStackRouterVite() {
2
+ return { name: 'tanstack-router-vite-fixture' }
3
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "@tanstack/router-plugin",
3
+ "type": "module",
4
+ "exports": {
5
+ "./vite": {
6
+ "import": {
7
+ "types": "./dist/esm/vite.d.ts",
8
+ "default": "./dist/esm/vite.js"
9
+ },
10
+ "require": {
11
+ "types": "./dist/cjs/vite.d.cts",
12
+ "default": "./dist/cjs/vite.cjs"
13
+ }
14
+ }
15
+ }
16
+ }
@@ -0,0 +1 @@
1
+ export function jsxDEV() {}
@@ -0,0 +1 @@
1
+ export function jsx() {}
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "react",
3
+ "type": "module",
4
+ "exports": {
5
+ "./jsx-dev-runtime": "./jsx-dev-runtime.js",
6
+ "./jsx-runtime": "./jsx-runtime.js"
7
+ }
8
+ }
@@ -0,0 +1 @@
1
+ export function createServer() {}
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "vite",
3
+ "type": "module",
4
+ "exports": {
5
+ ".": {
6
+ "import": "./dist/node/index.js",
7
+ "require": "./index.cjs"
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,8 @@
1
+ import { dirname, resolve } from 'node:path'
2
+ import { fileURLToPath } from 'node:url'
3
+
4
+ /** Portable fake consumer root — no sibling monorepo checkout required. */
5
+ export const consumerDepFixtureRoot = resolve(
6
+ dirname(fileURLToPath(import.meta.url)),
7
+ 'consumer-dep',
8
+ )
@@ -0,0 +1,28 @@
1
+ import { resolveConsumerDep } from '../resolve-consumer-dep.mjs'
2
+
3
+ /** Subpath runtimes only — do not alias top-level `react` / `react-dom` (breaks `react/jsx-runtime`). */
4
+ const REACT_RUNTIME_SPECS = [
5
+ 'react/jsx-runtime',
6
+ 'react/jsx-dev-runtime',
7
+ 'react-dom/client',
8
+ 'react/compiler-runtime',
9
+ ]
10
+
11
+ /**
12
+ * Pin React runtimes to the consumer's node_modules so kit UI under `.wphs/` or
13
+ * `node_modules/@woodsportal/hubspot-kit` never loads a mismatched CJS copy in the browser.
14
+ */
15
+ export function consumerReactAliases(projectRoot) {
16
+ /** @type {Record<string, string>} */
17
+ const alias = {}
18
+
19
+ for (const spec of REACT_RUNTIME_SPECS) {
20
+ try {
21
+ alias[spec] = resolveConsumerDep(spec, projectRoot)
22
+ } catch {
23
+ // consumer may omit optional subpaths until install completes
24
+ }
25
+ }
26
+
27
+ return alias
28
+ }
@@ -0,0 +1,12 @@
1
+ import assert from 'node:assert/strict'
2
+ import { describe, it } from 'node:test'
3
+
4
+ import { consumerDepFixtureRoot } from '../test-fixtures/consumer-dep-fixture-root.mjs'
5
+ import { consumerReactAliases } from './consumer-react-aliases.js'
6
+
7
+ describe('consumerReactAliases', () => {
8
+ it('resolves react jsx runtimes from the consumer project root', () => {
9
+ const alias = consumerReactAliases(consumerDepFixtureRoot)
10
+ assert.match(alias['react/jsx-dev-runtime'], /node_modules[/\\]react[/\\]jsx-dev-runtime/)
11
+ })
12
+ })
@@ -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,15 +1,23 @@
1
- import { createRequire } from 'node:module'
2
- import { resolve } from 'node:path'
3
- import { pathToFileURL } from 'node:url'
1
+ import { resolve, sep } from 'node:path'
2
+
3
+ import { resolveConsumerDep } from '../resolve-consumer-dep.mjs'
4
4
 
5
5
  /**
6
- * When Vite transforms files under @woodsportal/hubspot-kit, bare imports must
7
- * resolve from the consumer project's node_modules (not the kit package root).
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
- const require = createRequire(pathToFileURL(resolve(projectRoot, 'package.json')))
11
10
  const kitRootNorm = resolve(kitRoot)
12
11
 
12
+ function isKitUiImporter(importer) {
13
+ const norm = resolve(importer)
14
+ if (norm.startsWith(kitRootNorm)) return true
15
+ if (norm.includes(`${sep}.wphs${sep}`) || norm.includes(`${sep}.wphs`)) return true
16
+ if (norm.includes(`${sep}dev-module-config${sep}`)) return true
17
+ if (norm.includes(`${sep}.kit-module-config${sep}`)) return true
18
+ return false
19
+ }
20
+
13
21
  return {
14
22
  name: 'wp-resolve-from-project-root',
15
23
  enforce: 'pre',
@@ -18,11 +26,11 @@ export default function resolveFromProjectRoot(projectRoot, kitRoot) {
18
26
  if (source.startsWith('.') || source.startsWith('/') || source.startsWith('\0')) {
19
27
  return null
20
28
  }
21
- if (!resolve(importer).startsWith(kitRootNorm)) {
29
+ if (!isKitUiImporter(importer)) {
22
30
  return null
23
31
  }
24
32
  try {
25
- return require.resolve(source)
33
+ return resolveConsumerDep(source, projectRoot)
26
34
  } catch {
27
35
  return null
28
36
  }
@@ -1,107 +1,3 @@
1
- import { importConsumerDep } from '../scripts/resolve-consumer-dep.mjs'
1
+ import { createDevServerViteConfig } from '../scripts/vite/create-dev-server-config.mjs'
2
2
 
3
- export default loadDevViteConfig()
4
-
5
- async function loadDevViteConfig() {
6
- const [
7
- { findProjectRoot, getKitRoot },
8
- { readWoodsportalConfig },
9
- { ensureDevKitShims },
10
- { default: bootstrapShimResolver },
11
- { default: resolveFromProjectRoot },
12
- { default: sdkLogBridge },
13
- { default: moduleConfigStore },
14
- { createDevReactPluginOptions },
15
- { default: isPrefix },
16
- ] = await Promise.all([
17
- import('../scripts/project-root.mjs'),
18
- import('../scripts/read-woodsportal-config.mjs'),
19
- import('../scripts/vite/ensure-dev-kit-shims.js'),
20
- import('../scripts/vite/bootstrap-shim-resolver.js'),
21
- import('../scripts/vite/resolve-from-project-root.js'),
22
- import('../scripts/vite/sdk-log-bridge.js'),
23
- import('../scripts/vite/module-config-store.js'),
24
- import('../scripts/vite/react-dev-plugin-options.js'),
25
- import('../scripts/tailwind/prefix.env.js'),
26
- ])
27
-
28
- const { existsSync } = await import('node:fs')
29
- const { resolve } = await import('node:path')
30
-
31
- const kitRoot = getKitRoot()
32
- const projectRoot = findProjectRoot()
33
- const { moduleConfigRoot, bootstrapShim, bootstrapGreenfieldShim } = ensureDevKitShims(
34
- projectRoot,
35
- kitRoot,
36
- )
37
- const { config } = readWoodsportalConfig(projectRoot)
38
- const routesDir = resolve(projectRoot, 'src/routes')
39
- const hasTanStackRoutes = existsSync(routesDir)
40
-
41
- // Load vite before plugins: parallel import of vite + @vitejs/plugin-react breaks on Node 20+ (CJS/ESM interop).
42
- const { defineConfig } = await importConsumerDep('vite')
43
- const [{ default: viteReact }, { TanStackRouterVite }, { default: tailwindcss }] = await Promise.all([
44
- importConsumerDep('@vitejs/plugin-react'),
45
- importConsumerDep('@tanstack/router-plugin/vite'),
46
- importConsumerDep('@tailwindcss/vite'),
47
- ])
48
-
49
- return defineConfig(async ({ mode, command }) => {
50
- const prefixPlugins = isPrefix(mode)
51
- ? [
52
- (await import('../scripts/tailwind/prefix-plugin.js')).default(),
53
- (await import('../scripts/tailwind/tailwind-content-plugin.js')).default(),
54
- ]
55
- : []
56
-
57
- return {
58
- root: projectRoot,
59
- plugins: [
60
- bootstrapShimResolver({ bootstrapShim, bootstrapGreenfieldShim, kitRoot }),
61
- resolveFromProjectRoot(projectRoot, kitRoot),
62
- ...(command === 'serve' && mode === 'dev'
63
- ? [sdkLogBridge(), moduleConfigStore(projectRoot)]
64
- : []),
65
- ...(hasTanStackRoutes ? [TanStackRouterVite({ autoCodeSplitting: false })] : []),
66
- viteReact(createDevReactPluginOptions()),
67
- tailwindcss(),
68
- ...prefixPlugins,
69
- ],
70
- resolve: {
71
- preserveSymlinks: true,
72
- dedupe: ['react', 'react-dom'],
73
- alias: {
74
- '@/dev/module-config': moduleConfigRoot,
75
- '@wphs/bootstrap': bootstrapShim,
76
- '@wphs/bootstrap-greenfield': bootstrapGreenfieldShim,
77
- '@woodsportal/hubspot-kit/dev/bootstrap': bootstrapShim,
78
- '@woodsportal/hubspot-kit/dev/bootstrap-greenfield': bootstrapGreenfieldShim,
79
- '@wphs/adapter': resolve(projectRoot, config?.dev?.adapter ?? './wphs.adapter.ts'),
80
- '@': resolve(projectRoot, './src'),
81
- },
82
- },
83
- optimizeDeps: {
84
- include: ['react', 'react-dom', 'react/jsx-dev-runtime', 'react/jsx-runtime'],
85
- exclude: [
86
- 'woodsportal-client-sdk',
87
- 'woodsportal-client-sdk/auth',
88
- 'woodsportal-client-sdk/crm',
89
- ],
90
- },
91
- define: {
92
- 'import.meta.env.VITE_WPHS_MODULE_NAME': JSON.stringify(
93
- config?.module?.name ?? config?.theme?.name ?? 'module',
94
- ),
95
- 'process.env.NODE_ENV': JSON.stringify(mode === 'dev' ? 'development' : 'production'),
96
- 'process.env': {},
97
- process: JSON.stringify({ env: {} }),
98
- },
99
- server: {
100
- port: 3000,
101
- fs: {
102
- allow: [projectRoot, kitRoot],
103
- },
104
- },
105
- }
106
- })
107
- }
3
+ export default createDevServerViteConfig()