@hanzogui/vite-plugin 8.3.1 → 8.3.2

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 (43) hide show
  1. package/dist/cjs/extensions.js +16 -0
  2. package/dist/cjs/extensions.js.map +1 -0
  3. package/dist/cjs/here.js +6 -0
  4. package/dist/cjs/here.js.map +1 -0
  5. package/dist/cjs/index.js +5 -0
  6. package/dist/cjs/index.js.map +1 -0
  7. package/dist/cjs/loadGui.js +84 -0
  8. package/dist/cjs/loadGui.js.map +1 -0
  9. package/dist/cjs/package.json +1 -0
  10. package/dist/cjs/plugin.js +523 -0
  11. package/dist/cjs/plugin.js.map +1 -0
  12. package/dist/esm/extensions.js +13 -0
  13. package/dist/esm/extensions.js.map +1 -0
  14. package/dist/esm/here.js +3 -0
  15. package/dist/esm/here.js.map +1 -0
  16. package/dist/esm/index.js +2 -2
  17. package/dist/esm/index.js.map +1 -1
  18. package/dist/esm/loadGui.js +76 -0
  19. package/dist/esm/loadGui.js.map +1 -0
  20. package/dist/esm/plugin.js +518 -0
  21. package/dist/esm/plugin.js.map +1 -0
  22. package/package.json +25 -19
  23. package/src/here.cjs.ts +3 -0
  24. package/src/here.ts +2 -0
  25. package/src/index.ts +1 -1
  26. package/src/plugin.ts +7 -9
  27. package/types/here.d.ts +2 -0
  28. package/types/here.d.ts.map +1 -0
  29. package/types/index.d.ts +1 -1
  30. package/types/index.d.ts.map +1 -1
  31. package/types/plugin.d.ts.map +1 -1
  32. package/dist/cjs/extensions.cjs +0 -28
  33. package/dist/cjs/index.cjs +0 -20
  34. package/dist/cjs/loadGui.cjs +0 -101
  35. package/dist/cjs/plugin.cjs +0 -473
  36. package/dist/esm/extensions.mjs +0 -3
  37. package/dist/esm/extensions.mjs.map +0 -1
  38. package/dist/esm/index.mjs +0 -2
  39. package/dist/esm/index.mjs.map +0 -1
  40. package/dist/esm/loadGui.mjs +0 -61
  41. package/dist/esm/loadGui.mjs.map +0 -1
  42. package/dist/esm/plugin.mjs +0 -435
  43. package/dist/esm/plugin.mjs.map +0 -1
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extensions = void 0;
4
+ exports.extensions = [
5
+ '.ios.js',
6
+ '.native.js',
7
+ '.native.ts',
8
+ '.native.tsx',
9
+ '.js',
10
+ '.jsx',
11
+ '.json',
12
+ '.ts',
13
+ '.tsx',
14
+ '.mjs',
15
+ ];
16
+ //# sourceMappingURL=extensions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extensions.js","sourceRoot":"","sources":["../../src/extensions.ts"],"names":[],"mappings":";;;AAAa,QAAA,UAAU,GAAG;IACxB,SAAS;IACT,YAAY;IACZ,YAAY;IACZ,aAAa;IACb,KAAK;IACL,MAAM;IACN,OAAO;IACP,KAAK;IACL,MAAM;IACN,MAAM;CACP,CAAA"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.url = void 0;
4
+ const node_url_1 = require("node:url");
5
+ exports.url = (0, node_url_1.pathToFileURL)(__filename).href;
6
+ //# sourceMappingURL=here.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"here.cjs.js","sourceRoot":"","sources":["../../src/here.cjs.ts"],"names":[],"mappings":";;;AAAA,uCAAwC;AAE3B,QAAA,GAAG,GAAG,IAAA,wBAAa,EAAC,UAAU,CAAC,CAAC,IAAI,CAAA"}
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./plugin.js"), exports);
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,sDAA2B"}
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getGuiOptions = getGuiOptions;
4
+ exports.getLoadPromise = getLoadPromise;
5
+ exports.loadGuiBuildConfig = loadGuiBuildConfig;
6
+ exports.ensureFullConfigLoaded = ensureFullConfigLoaded;
7
+ exports.cleanup = cleanup;
8
+ const tslib_1 = require("tslib");
9
+ const StaticWorker = tslib_1.__importStar(require("@hanzogui/static-worker"));
10
+ // use globalThis to share state across vite environments (SSR, client, etc.)
11
+ const LOAD_STATE_KEY = '__hanzogui_load_state__';
12
+ function getLoadState() {
13
+ if (!globalThis[LOAD_STATE_KEY]) {
14
+ ;
15
+ globalThis[LOAD_STATE_KEY] = {
16
+ loadPromise: null,
17
+ loadedOptions: null,
18
+ fullConfigLoaded: false,
19
+ fullConfigLoadPromise: null,
20
+ };
21
+ }
22
+ return globalThis[LOAD_STATE_KEY];
23
+ }
24
+ function getGuiOptions() {
25
+ return getLoadState().loadedOptions;
26
+ }
27
+ function getLoadPromise() {
28
+ return getLoadState().loadPromise;
29
+ }
30
+ /**
31
+ * Load just the hanzogui.build.ts config (lightweight)
32
+ * This doesn't bundle the full hanzogui config - call ensureFullConfigLoaded() for that
33
+ */
34
+ async function loadGuiBuildConfig(optionsIn) {
35
+ const state = getLoadState();
36
+ if (state.loadedOptions)
37
+ return state.loadedOptions;
38
+ if (state.loadPromise)
39
+ return state.loadPromise;
40
+ state.loadPromise = (async () => {
41
+ const options = await StaticWorker.loadGuiBuildConfig({
42
+ ...optionsIn,
43
+ platform: 'web',
44
+ });
45
+ state.loadedOptions = options;
46
+ return options;
47
+ })();
48
+ return state.loadPromise;
49
+ }
50
+ /**
51
+ * Ensure the full hanzogui config is loaded (heavy - bundles config + components)
52
+ * Call this lazily when transform/extraction is actually needed
53
+ */
54
+ async function ensureFullConfigLoaded() {
55
+ const state = getLoadState();
56
+ if (state.fullConfigLoaded)
57
+ return;
58
+ if (state.fullConfigLoadPromise)
59
+ return state.fullConfigLoadPromise;
60
+ // set promise immediately to prevent race conditions
61
+ // (don't await loadGuiBuildConfig before setting this)
62
+ state.fullConfigLoadPromise = (async () => {
63
+ const options = await loadGuiBuildConfig();
64
+ // load full hanzogui config in worker (asynchronous)
65
+ if (!options.disableWatchGuiConfig && !options.disable) {
66
+ await StaticWorker.loadGui({
67
+ components: ['@hanzo/gui'],
68
+ platform: 'web',
69
+ ...options,
70
+ });
71
+ }
72
+ state.fullConfigLoaded = true;
73
+ })();
74
+ return state.fullConfigLoadPromise;
75
+ }
76
+ async function cleanup() {
77
+ await StaticWorker.destroyPool();
78
+ const state = getLoadState();
79
+ state.loadPromise = null;
80
+ state.loadedOptions = null;
81
+ state.fullConfigLoaded = false;
82
+ state.fullConfigLoadPromise = null;
83
+ }
84
+ //# sourceMappingURL=loadGui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadGui.js","sourceRoot":"","sources":["../../src/loadGui.ts"],"names":[],"mappings":";;;;;;;;AAAA,MAAY,YAAY,4DAA+B;AAGvD,6EAA6E;AAC7E,MAAM,cAAc,GAAG,yBAAyB,CAAA;AAShD,SAAS,YAAY;IACnB,IAAI,CAAE,UAAkB,CAAC,cAAc,CAAC,EAAE,CAAC;QACzC,CAAC;QAAC,UAAkB,CAAC,cAAc,CAAC,GAAG;YACrC,WAAW,EAAE,IAAI;YACjB,aAAa,EAAE,IAAI;YACnB,gBAAgB,EAAE,KAAK;YACvB,qBAAqB,EAAE,IAAI;SAC5B,CAAA;IACH,CAAC;IACD,OAAQ,UAAkB,CAAC,cAAc,CAAC,CAAA;AAC5C,CAAC;AAED;IACE,OAAO,YAAY,EAAE,CAAC,aAAa,CAAA;AACrC,CAAC;AAED;IACE,OAAO,YAAY,EAAE,CAAC,WAAW,CAAA;AACnC,CAAC;AAED;;;GAGG;AACI,KAAK,6BACV,SAA+B;IAE/B,MAAM,KAAK,GAAG,YAAY,EAAE,CAAA;IAC5B,IAAI,KAAK,CAAC,aAAa;QAAE,OAAO,KAAK,CAAC,aAAa,CAAA;IACnD,IAAI,KAAK,CAAC,WAAW;QAAE,OAAO,KAAK,CAAC,WAAW,CAAA;IAE/C,KAAK,CAAC,WAAW,GAAG,CAAC,KAAK,IAAI,EAAE;QAC9B,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,kBAAkB,CAAC;YACpD,GAAG,SAAS;YACZ,QAAQ,EAAE,KAAK;SAChB,CAAC,CAAA;QAEF,KAAK,CAAC,aAAa,GAAG,OAAO,CAAA;QAC7B,OAAO,OAAO,CAAA;IAChB,CAAC,CAAC,EAAE,CAAA;IAEJ,OAAO,KAAK,CAAC,WAAW,CAAA;AAC1B,CAAC;AAED;;;GAGG;AACI,KAAK;IACV,MAAM,KAAK,GAAG,YAAY,EAAE,CAAA;IAE5B,IAAI,KAAK,CAAC,gBAAgB;QAAE,OAAM;IAClC,IAAI,KAAK,CAAC,qBAAqB;QAAE,OAAO,KAAK,CAAC,qBAAqB,CAAA;IAEnE,qDAAqD;IACrD,uDAAuD;IACvD,KAAK,CAAC,qBAAqB,GAAG,CAAC,KAAK,IAAI,EAAE;QACxC,MAAM,OAAO,GAAG,MAAM,kBAAkB,EAAE,CAAA;QAE1C,qDAAqD;QACrD,IAAI,CAAC,OAAO,CAAC,qBAAqB,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACvD,MAAM,YAAY,CAAC,OAAO,CAAC;gBACzB,UAAU,EAAE,CAAC,YAAY,CAAC;gBAC1B,QAAQ,EAAE,KAAK;gBACf,GAAG,OAAO;aACX,CAAC,CAAA;QACJ,CAAC;QACD,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAA;IAC/B,CAAC,CAAC,EAAE,CAAA;IAEJ,OAAO,KAAK,CAAC,qBAAqB,CAAA;AACpC,CAAC;AAEM,KAAK;IACV,MAAM,YAAY,CAAC,WAAW,EAAE,CAAA;IAChC,MAAM,KAAK,GAAG,YAAY,EAAE,CAAA;IAC5B,KAAK,CAAC,WAAW,GAAG,IAAI,CAAA;IACxB,KAAK,CAAC,aAAa,GAAG,IAAI,CAAA;IAC1B,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAA;IAC9B,KAAK,CAAC,qBAAqB,GAAG,IAAI,CAAA;AACpC,CAAC"}
@@ -0,0 +1 @@
1
+ { "type": "commonjs" }
@@ -0,0 +1,523 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hanzoguiAliases = hanzoguiAliases;
4
+ exports.hanzoguiPlugin = hanzoguiPlugin;
5
+ const tslib_1 = require("tslib");
6
+ const Static = tslib_1.__importStar(require("@hanzogui/static-worker"));
7
+ const static_worker_1 = require("@hanzogui/static-worker");
8
+ const node_crypto_1 = require("node:crypto");
9
+ const node_module_1 = require("node:module");
10
+ const here_ts_1 = require("./here.js");
11
+ const node_path_1 = tslib_1.__importDefault(require("node:path"));
12
+ const loadGui_ts_1 = require("./loadGui.js");
13
+ // Plugin dependencies resolve from the plugin's own location, not the user's project.
14
+ const _pluginRequire = (0, node_module_1.createRequire)(here_ts_1.url);
15
+ const resolve = (name) => _pluginRequire.resolve(name);
16
+ const normalizePath = (value) => value.replace(/\\/g, '/');
17
+ /** what an installed package can hold extractable source in */
18
+ const PACKAGE_EXTENSIONS = /\.(mjs|js|jsx|tsx)$/;
19
+ const CACHE_KEY = '__hanzogui_vite_cache__';
20
+ const CACHE_SIZE_KEY = '__hanzogui_vite_cache_size__';
21
+ const PENDING_KEY = '__hanzogui_vite_pending__';
22
+ function getSharedCache() {
23
+ if (!globalThis[CACHE_KEY]) {
24
+ ;
25
+ globalThis[CACHE_KEY] = {};
26
+ }
27
+ return globalThis[CACHE_KEY];
28
+ }
29
+ function getSharedCacheSize() {
30
+ return globalThis[CACHE_SIZE_KEY] || 0;
31
+ }
32
+ function setSharedCacheSize(size) {
33
+ ;
34
+ globalThis[CACHE_SIZE_KEY] = size;
35
+ }
36
+ function clearSharedCache() {
37
+ ;
38
+ globalThis[CACHE_KEY] = {};
39
+ globalThis[CACHE_SIZE_KEY] = 0;
40
+ }
41
+ // resolves package ids against the user's project root (not the plugin's
42
+ // install location). returns true if the id is resolvable, false if the
43
+ // dep isn't installed, safe to call for optional deps.
44
+ function isInstalled(projectRoot, id) {
45
+ try {
46
+ const req = (0, node_module_1.createRequire)(node_path_1.default.join(projectRoot, 'package.json'));
47
+ req.resolve(id);
48
+ return true;
49
+ }
50
+ catch {
51
+ return false;
52
+ }
53
+ }
54
+ function addIfInstalled(userConf, projectRoot, ids) {
55
+ var _a;
56
+ const root = projectRoot || process.cwd();
57
+ userConf.optimizeDeps || (userConf.optimizeDeps = {});
58
+ (_a = userConf.optimizeDeps).include || (_a.include = []);
59
+ for (const id of ids) {
60
+ if (!userConf.optimizeDeps.include.includes(id) && isInstalled(root, id)) {
61
+ userConf.optimizeDeps.include.push(id);
62
+ }
63
+ }
64
+ }
65
+ // pending extractions map - dedupes concurrent requests for same file
66
+ function getPendingExtractions() {
67
+ if (!globalThis[PENDING_KEY]) {
68
+ ;
69
+ globalThis[PENDING_KEY] = new Map();
70
+ }
71
+ return globalThis[PENDING_KEY];
72
+ }
73
+ /**
74
+ * returns vite-compatible aliases for hanzogui
75
+ * use this when you need control over alias ordering in your config
76
+ */
77
+ function hanzoguiAliases(options = {}) {
78
+ const aliases = [];
79
+ if (options.svg) {
80
+ aliases.push({
81
+ find: 'react-native-svg',
82
+ replacement: resolve('@hanzogui/react-native-svg'),
83
+ });
84
+ }
85
+ if (options.rnwLite) {
86
+ // base package path for subpath imports (package directory, not entry file)
87
+ const rnwlBase = node_path_1.default.dirname(resolve('@hanzogui/react-native-web-lite/package.json'));
88
+ // vite aliases need the esm entry; require.resolve points at cjs.
89
+ const rnwl = normalizePath(node_path_1.default.join(rnwlBase, options.rnwLite === 'without-animated'
90
+ ? 'dist/esm/without-animated.js'
91
+ : 'dist/esm/index.js'));
92
+ aliases.push({
93
+ // map deep RNW paths like dist/exports/StyleSheet/preprocess to rnw-lite's flat structure
94
+ // extracts the final path segment (e.g. "preprocess" or "createReactDOMStyle")
95
+ find: /^react-native(?:-web)?\/dist\/(?:exports|modules)\/.*\/([^/]+)$/,
96
+ replacement: `${normalizePath(rnwlBase)}/dist/esm/$1.js`,
97
+ }, {
98
+ find: /^react-native$/,
99
+ replacement: rnwl,
100
+ }, {
101
+ find: /^react-native\/(Libraries\/Utilities\/codegenNativeComponent|Libraries\/Utilities\/codegenNativeCommand)$/,
102
+ replacement: `${rnwlBase}/$1`,
103
+ }, {
104
+ find: 'react-native/package.json',
105
+ replacement: resolve('@hanzogui/react-native-web-lite/package.json'),
106
+ }, {
107
+ find: /^react-native-web$/,
108
+ replacement: rnwl,
109
+ });
110
+ }
111
+ return aliases;
112
+ }
113
+ function hanzoguiPlugin({ disableResolveConfig, ...hanzoguiOptionsIn } = {}) {
114
+ // extraction ON by default, set disableExtraction: true to opt out
115
+ let shouldExtract = !hanzoguiOptionsIn.disableExtraction;
116
+ let watcher;
117
+ // temporary vxrn native env bridge
118
+ const enableNativeEnv = !!globalThis.__vxrnEnableNativeEnv;
119
+ const extensions = [
120
+ `.web.mjs`,
121
+ `.web.js`,
122
+ `.web.jsx`,
123
+ `.web.ts`,
124
+ `.web.tsx`,
125
+ '.mjs',
126
+ '.js',
127
+ '.mts',
128
+ '.ts',
129
+ '.jsx',
130
+ '.tsx',
131
+ '.json',
132
+ ];
133
+ // start loading immediately but don't block
134
+ (0, loadGui_ts_1.loadGuiBuildConfig)(hanzoguiOptionsIn);
135
+ // helper to await load when needed
136
+ const ensureLoaded = async () => {
137
+ const promise = (0, loadGui_ts_1.getLoadPromise)();
138
+ if (promise)
139
+ await promise;
140
+ const options = (0, loadGui_ts_1.getGuiOptions)();
141
+ // update shouldExtract from loaded config (hanzogui.build.ts)
142
+ if (options) {
143
+ shouldExtract = !options.disableExtraction;
144
+ }
145
+ return options;
146
+ };
147
+ // extract plugin state
148
+ const getHash = (input) => (0, node_crypto_1.createHash)('sha1').update(input).digest('base64');
149
+ // use shared cache across environments
150
+ const memoryCache = getSharedCache();
151
+ const cssMap = new Map();
152
+ let config;
153
+ let server;
154
+ const virtualExt = `.hanzogui.css`;
155
+ const getAbsoluteVirtualFileId = (filePath) => {
156
+ if (filePath.startsWith(config.root)) {
157
+ return filePath;
158
+ }
159
+ return normalizePath(node_path_1.default.join(config.root, filePath));
160
+ };
161
+ function isNotClient(environment) {
162
+ return environment?.name && environment.name !== 'client';
163
+ }
164
+ function isNative(environment) {
165
+ return (environment?.name && (environment.name === 'ios' || environment.name === 'android'));
166
+ }
167
+ function invalidateModule(absoluteId) {
168
+ if (!server)
169
+ return;
170
+ const { moduleGraph } = server;
171
+ const modules = moduleGraph.getModulesByFile(absoluteId);
172
+ if (modules) {
173
+ for (const module of modules) {
174
+ moduleGraph.invalidateModule(module);
175
+ module.lastHMRTimestamp = module.lastInvalidationTimestamp || Date.now();
176
+ }
177
+ }
178
+ }
179
+ const basePlugin = {
180
+ name: 'hanzogui',
181
+ enforce: 'pre',
182
+ configureServer(_server) {
183
+ server = _server;
184
+ },
185
+ async buildEnd() {
186
+ await watcher?.then((res) => {
187
+ res?.dispose();
188
+ });
189
+ },
190
+ async config(_, env) {
191
+ const options = await ensureLoaded();
192
+ if (!options) {
193
+ throw new Error(`No hanzogui options loaded`);
194
+ }
195
+ // start watching config if enabled
196
+ if (!options.disableWatchGuiConfig) {
197
+ watcher = Static.watchGuiConfig({
198
+ components: ['@hanzo/gui'],
199
+ config: './src/hanzogui.config.ts',
200
+ ...options,
201
+ }).catch((err) => {
202
+ console.error(` [Gui] Error watching config: ${err}`);
203
+ });
204
+ }
205
+ return {
206
+ envPrefix: ['GUI_'],
207
+ // A dependency that RENDERS is bundled, not externalised.
208
+ //
209
+ // An externalised package resolves react itself, and under SSR that is a
210
+ // second module instance of the one react in the tree — its dispatcher is
211
+ // null while the app renders, so the package's first hook throws and the
212
+ // whole page fails, not just the subtree. GuiProvider mounts a telemetry
213
+ // client for every app, so these two arrive in apps that never named them.
214
+ //
215
+ // It belongs here rather than in each app's config because every gui app
216
+ // already mounts this plugin, and a list repeated per app is a list the
217
+ // next app forgets.
218
+ ssr: { noExternal: ['@hanzo/event', '@hanzo/observe'] },
219
+ environments: {
220
+ client: {
221
+ define: {
222
+ 'process.env.GUI_IS_CLIENT': JSON.stringify(true),
223
+ 'process.env.GUI_ENVIRONMENT': '"client"',
224
+ },
225
+ },
226
+ },
227
+ define: {
228
+ // reanimated support
229
+ _frameTimestamp: undefined,
230
+ _WORKLET: false,
231
+ __DEV__: `${env.mode === 'development'}`,
232
+ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || env.mode),
233
+ 'process.env.ENABLE_RSC': JSON.stringify(process.env.ENABLE_RSC || ''),
234
+ 'process.env.ENABLE_STEPS': JSON.stringify(process.env.ENABLE_STEPS || ''),
235
+ 'process.env.IS_STATIC': JSON.stringify(false),
236
+ ...(env.mode === 'production' && {
237
+ 'process.env.GUI_OPTIMIZE_THEMES': JSON.stringify(true),
238
+ }),
239
+ },
240
+ resolve: disableResolveConfig || enableNativeEnv
241
+ ? {}
242
+ : {
243
+ extensions,
244
+ alias: {
245
+ ...(options.platform !== 'native' && {
246
+ 'react-native/Libraries/Renderer/shims/ReactFabric': resolve('@hanzogui/proxy-worm'),
247
+ 'react-native/Libraries/Utilities/codegenNativeComponent': resolve('@hanzogui/proxy-worm'),
248
+ 'react-native-svg': resolve('@hanzogui/react-native-svg'),
249
+ ...(!options?.useReactNativeWebLite && {
250
+ 'react-native': resolve('react-native-web'),
251
+ }),
252
+ }),
253
+ },
254
+ },
255
+ };
256
+ },
257
+ };
258
+ const rnwLitePlugin = {
259
+ name: 'hanzogui-rnw-lite',
260
+ config() {
261
+ if (enableNativeEnv) {
262
+ return {};
263
+ }
264
+ const options = (0, loadGui_ts_1.getGuiOptions)();
265
+ if (!options?.useReactNativeWebLite) {
266
+ return {};
267
+ }
268
+ // react-native-web-lite imports memoize-one internally. the esbuild dep
269
+ // scanner doesn't follow it through the react-native -> rnw-lite alias, so
270
+ // vite discovers it only at request time, re-optimizes mid-load, and full
271
+ // reloads. on slow runners (CI) the in-flight optimized-dep request 504s
272
+ // ("Outdated Optimize Dep") and surfaces as a console error. pre-include
273
+ // it so the first optimize pass is complete and no reload is triggered.
274
+ const include = [];
275
+ if (isInstalled(process.cwd(), 'memoize-one')) {
276
+ include.push('memoize-one');
277
+ }
278
+ return {
279
+ resolve: {
280
+ alias: hanzoguiAliases({ rnwLite: options.useReactNativeWebLite }),
281
+ },
282
+ optimizeDeps: {
283
+ // upstream react-native-web must not be pre-bundled when aliased to lite
284
+ exclude: ['react-native-web'],
285
+ include,
286
+ },
287
+ };
288
+ },
289
+ };
290
+ // extract plugin for optimize mode
291
+ // always included, but checks shouldExtract dynamically after config loads
292
+ const extractPlugin = {
293
+ name: 'hanzogui-extract',
294
+ enforce: 'pre',
295
+ async config(userConf) {
296
+ var _a, _b;
297
+ // wait for config to load to know if we should extract
298
+ const options = await ensureLoaded();
299
+ userConf.optimizeDeps || (userConf.optimizeDeps = {});
300
+ (_a = userConf.optimizeDeps).include || (_a.include = []);
301
+ // inline-style-prefixer is CJS with __esModule and breaks without pre-bundling
302
+ // (reference error: exports is not defined). always include it.
303
+ userConf.optimizeDeps.include.push('inline-style-prefixer');
304
+ // pre-bundle hanzogui packages that use internal hooks (useThemeName, etc.)
305
+ // from sub-entries, vite's dep crawler can otherwise split them into a
306
+ // separate chunk with its own hanzogui copy, producing two ThemeStateContext
307
+ // instances and "Missing theme" errors at runtime.
308
+ //
309
+ // @hanzogui/sheet/controller is the lightweight controller subpath imported
310
+ // by popover/dialog/select; the app imports @hanzogui/sheet (full). if these
311
+ // land in separate optimized chunks they each get their own copy of
312
+ // SheetControllerContext, so the SheetController provider (from /controller)
313
+ // and the Sheet consumer (from the full entry) never match and adapted
314
+ // sheets silently never open. include both so they share one context chunk.
315
+ addIfInstalled(userConf, userConf.root, [
316
+ '@hanzogui/toast',
317
+ '@hanzogui/toast/v2',
318
+ '@hanzogui/sheet',
319
+ '@hanzogui/sheet/controller',
320
+ ]);
321
+ // dedupe hanzogui packages so nested resolutions collapse to a single
322
+ // instance. pairs with the include above: include pre-bundles, dedupe
323
+ // prevents duplicate bundling when sub-deps re-resolve them.
324
+ userConf.resolve || (userConf.resolve = {});
325
+ (_b = userConf.resolve).dedupe || (_b.dedupe = []);
326
+ for (const id of [
327
+ 'hanzogui',
328
+ '@hanzogui/core',
329
+ '@hanzogui/web',
330
+ '@hanzogui/toast',
331
+ '@hanzogui/sheet',
332
+ ]) {
333
+ if (!userConf.resolve.dedupe.includes(id) &&
334
+ isInstalled(userConf.root || process.cwd(), id)) {
335
+ userConf.resolve.dedupe.push(id);
336
+ }
337
+ }
338
+ if (!shouldExtract)
339
+ return;
340
+ userConf.optimizeDeps.include.push('@hanzogui/core/inject-styles');
341
+ },
342
+ async configResolved(resolvedConfig) {
343
+ config = resolvedConfig;
344
+ },
345
+ async resolveId(source) {
346
+ if (!shouldExtract)
347
+ return;
348
+ if (isNative(this.environment)) {
349
+ return;
350
+ }
351
+ if (isNotClient(this.environment)) {
352
+ return;
353
+ }
354
+ const [validId, query] = source.split('?');
355
+ if (!validId.endsWith(virtualExt)) {
356
+ return;
357
+ }
358
+ const absoluteId = source.startsWith(config.root)
359
+ ? source
360
+ : getAbsoluteVirtualFileId(validId);
361
+ if (cssMap.has(absoluteId)) {
362
+ return absoluteId + (query ? `?${query}` : '');
363
+ }
364
+ },
365
+ async load(id) {
366
+ if (!shouldExtract)
367
+ return;
368
+ const options = (0, loadGui_ts_1.getGuiOptions)();
369
+ if (options?.disable) {
370
+ return;
371
+ }
372
+ if (isNative(this.environment)) {
373
+ return;
374
+ }
375
+ if (isNotClient(this.environment)) {
376
+ return;
377
+ }
378
+ const [validId] = id.split('?');
379
+ return cssMap.get(validId);
380
+ },
381
+ transform: {
382
+ order: 'pre',
383
+ async handler(code, id) {
384
+ // ensure hanzogui is loaded before transform
385
+ const options = await ensureLoaded();
386
+ // ensure full config (heavy bundling) is loaded before extraction
387
+ await (0, loadGui_ts_1.ensureFullConfigLoaded)();
388
+ // fully disabled = no extraction AND no debug attrs
389
+ if (options?.disable) {
390
+ return;
391
+ }
392
+ if (isNative(this.environment)) {
393
+ return;
394
+ }
395
+ const [validId] = id.split('?');
396
+ // app source is .tsx; an allowlisted package is whatever it publishes,
397
+ // which for our design system is the jsx-preserving .mjs/.js build
398
+ const pkg = (0, static_worker_1.installedPackageOf)(validId);
399
+ if (pkg
400
+ ? !(0, static_worker_1.isExtractable)(validId, options?.extractPackages) ||
401
+ !PACKAGE_EXTENSIONS.test(validId)
402
+ : !validId.endsWith('.tsx')) {
403
+ return;
404
+ }
405
+ const { shouldDisable, shouldPrintDebug } = await (0, static_worker_1.getPragmaOptions)({
406
+ source: code,
407
+ path: validId,
408
+ });
409
+ if (shouldPrintDebug) {
410
+ console.trace(`Current file: ${id} in environment: ${this.environment?.name}, shouldDisable: ${shouldDisable}`);
411
+ console.info(`\n\nOriginal source:\n${code}\n\n`);
412
+ }
413
+ if (shouldDisable) {
414
+ return;
415
+ }
416
+ const isSSR = isNotClient(this.environment);
417
+ // cache key without environment - share compiled JS between SSR/client
418
+ const cacheKey = getHash(`${code}${id}`);
419
+ const pending = getPendingExtractions();
420
+ // helper to format result based on environment
421
+ const formatResult = (entry) => {
422
+ const finalCode = !isSSR && entry.cssImport ? `${entry.js}\n${entry.cssImport}` : entry.js;
423
+ return { code: finalCode, map: entry.map };
424
+ };
425
+ // check cache first
426
+ const cached = memoryCache[cacheKey];
427
+ if (cached) {
428
+ if (process.env.DEBUG_GUI_CACHE) {
429
+ console.info(`[hanzogui-cache] HIT ${this.environment?.name || 'unknown'} ${id.split('/').pop()} key=${cacheKey.slice(0, 8)}`);
430
+ }
431
+ return formatResult(cached);
432
+ }
433
+ // check if another request is already extracting this file
434
+ const pendingExtraction = pending.get(cacheKey);
435
+ if (pendingExtraction) {
436
+ if (process.env.DEBUG_GUI_CACHE) {
437
+ console.info(`[hanzogui-cache] WAIT ${this.environment?.name || 'unknown'} ${id.split('/').pop()} key=${cacheKey.slice(0, 8)}`);
438
+ }
439
+ const result = await pendingExtraction;
440
+ if (result) {
441
+ return formatResult(result);
442
+ }
443
+ return;
444
+ }
445
+ if (process.env.DEBUG_GUI_CACHE) {
446
+ console.info(`[hanzogui-cache] EXTRACT ${this.environment?.name || 'unknown'} ${id.split('/').pop()} key=${cacheKey.slice(0, 8)}`);
447
+ }
448
+ // create extraction promise and store it for deduplication
449
+ const extractionPromise = (async () => {
450
+ let extracted;
451
+ try {
452
+ extracted = await Static.extractToClassNames({
453
+ source: code,
454
+ sourcePath: validId,
455
+ options: options,
456
+ shouldPrintDebug,
457
+ });
458
+ }
459
+ catch (err) {
460
+ if (process.env.DEBUG_GUI_CACHE) {
461
+ console.info(`[hanzogui-cache] ERROR extracting ${id.split('/').pop()}:`, err);
462
+ }
463
+ console.error(err instanceof Error ? err.message : String(err));
464
+ return null;
465
+ }
466
+ if (!extracted) {
467
+ if (process.env.DEBUG_GUI_CACHE) {
468
+ console.info(`[hanzogui-cache] no extraction result for ${id.split('/').pop()}`);
469
+ }
470
+ return null;
471
+ }
472
+ const rootRelativeId = `${validId}${virtualExt}`;
473
+ const absoluteId = getAbsoluteVirtualFileId(rootRelativeId);
474
+ let cssImport = null;
475
+ // store CSS and prepare import (but don't include in cached JS)
476
+ if (extracted.styles) {
477
+ this.addWatchFile(rootRelativeId);
478
+ if (server && cssMap.has(absoluteId)) {
479
+ invalidateModule(rootRelativeId);
480
+ }
481
+ cssImport = `import "${rootRelativeId}";`;
482
+ cssMap.set(absoluteId, extracted.styles);
483
+ }
484
+ // cache the JS separately from CSS import
485
+ const jsCode = extracted.js.toString();
486
+ const cacheEntry = {
487
+ js: jsCode,
488
+ map: extracted.map,
489
+ cssImport,
490
+ };
491
+ // track cache size and clear if too large (64MB)
492
+ const newSize = getSharedCacheSize() + jsCode.length;
493
+ if (newSize > 67108864) {
494
+ clearSharedCache();
495
+ }
496
+ else {
497
+ setSharedCacheSize(newSize);
498
+ }
499
+ memoryCache[cacheKey] = cacheEntry;
500
+ if (process.env.DEBUG_GUI_CACHE) {
501
+ console.info(`[hanzogui-cache] WRITE key=${cacheKey.slice(0, 8)} cacheSize=${Object.keys(memoryCache).length}`);
502
+ }
503
+ return cacheEntry;
504
+ })();
505
+ // store pending promise for deduplication
506
+ pending.set(cacheKey, extractionPromise);
507
+ try {
508
+ const result = await extractionPromise;
509
+ if (result) {
510
+ return formatResult(result);
511
+ }
512
+ return;
513
+ }
514
+ finally {
515
+ // clean up pending map
516
+ pending.delete(cacheKey);
517
+ }
518
+ },
519
+ },
520
+ };
521
+ return [basePlugin, rnwLitePlugin, extractPlugin];
522
+ }
523
+ //# sourceMappingURL=plugin.js.map