@tamagui/vite-plugin 2.7.7 → 3.0.0-beta.1097.1

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.
@@ -1,435 +1,1147 @@
1
- import * as Static from "@tamagui/static-worker";
2
- import { getPragmaOptions } from "@tamagui/static-worker";
1
+ import Static from "@tamagui/static";
3
2
  import { createHash } from "node:crypto";
4
- import { readdirSync } from "node:fs";
3
+ import { existsSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
4
+ import { gzipSync } from "node:zlib";
5
+ import { readFile } from "node:fs/promises";
5
6
  import { createRequire } from "node:module";
6
7
  import path from "node:path";
7
8
  import { fileURLToPath } from "node:url";
8
- import { loadTamaguiBuildConfig, getLoadPromise, getTamaguiOptions, ensureFullConfigLoaded } from "./loadTamagui.mjs";
9
- const _pluginRequire = createRequire(typeof __filename === "string" ? __filename : fileURLToPath(import.meta.url));
10
- const resolve = name => _pluginRequire.resolve(name);
11
- const normalizePath = value => value.replace(/\\/g, "/");
12
- const CACHE_KEY = "__tamagui_vite_cache__";
13
- const CACHE_SIZE_KEY = "__tamagui_vite_cache_size__";
14
- const PENDING_KEY = "__tamagui_vite_pending__";
15
- function getSharedCache() {
16
- if (!globalThis[CACHE_KEY]) {
17
- ;
18
- globalThis[CACHE_KEY] = {};
19
- }
20
- return globalThis[CACHE_KEY];
9
+ import { createFilter, createIdResolver, createRunnableDevEnvironment, defaultClientConditions, defaultClientMainFields, isRunnableDevEnvironment, resolveConfig } from "vite";
10
+ import { TAMAGUI_EVALUATION_ENVIRONMENT, createViteTamaguiLoader } from "./loadTamagui.mjs";
11
+ import { createCompilerStatsReport, formatCompilerStatsReport } from "./compilerStats.mjs";
12
+ import { ZERO_CSS_FILENAME, ZERO_ISLAND_DIRNAME, assertZeroGraph, buildIsland, createZeroRuntimeController, finalizeZeroCSS, zeroModuleKey } from "./zeroRuntime.mjs";
13
+
14
+ const environmentSpecificTransformPluginNames = /* @__PURE__ */ new Set(["one:compiler", "one:compiler-css-to-js"]);
15
+ const oneTsconfigPathsPluginName = "one:tsconfig-paths";
16
+ const bareTamaguiPackage = /^@tamagui\/[^/?#]+(?:[/?#]|$)/;
17
+ const inlineEvaluationTamaguiPackage = /^@tamagui\/(?:config|core|slider|web)(?:[/?#]|$)/;
18
+ const externalizablePackageExtensions = /* @__PURE__ */ new Set([
19
+ "",
20
+ ".js",
21
+ ".mjs",
22
+ ".cjs"
23
+ ]);
24
+ const TAMAGUI_COMPILER_CONDITION = "tamagui-compiler";
25
+ function packageDeclaresCompilerCondition(packageDir) {
26
+ const manifest = path.join(packageDir, "package.json");
27
+ if (!existsSync(manifest)) return false;
28
+ try {
29
+ const exports = JSON.parse(readFileSync(manifest, "utf8")).exports;
30
+ return JSON.stringify(exports ?? null).includes(`"${TAMAGUI_COMPILER_CONDITION}"`);
31
+ } catch {
32
+ return false;
33
+ }
34
+ }
35
+ function mergeEvaluationNoExternal(required, userNoExternal) {
36
+ if (userNoExternal === true) return true;
37
+ if (!userNoExternal) return required;
38
+ return [...required, ...Array.isArray(userNoExternal) ? userNoExternal : [userNoExternal]];
39
+ }
40
+ function createEvaluationResolveId(plugin, resolveBarePackage) {
41
+ const resolveId = plugin.resolveId;
42
+ if (plugin.name !== oneTsconfigPathsPluginName || !resolveId) return resolveId;
43
+ const handler = typeof resolveId === "object" ? resolveId.handler : resolveId;
44
+ const evaluationHandler = function(source, ...args) {
45
+ if (bareTamaguiPackage.test(source)) {
46
+ const importer = typeof args[0] === "string" ? args[0] : void 0;
47
+ return resolveBarePackage?.(this.environment, source, importer);
48
+ }
49
+ return Reflect.apply(handler, this, [source, ...args]);
50
+ };
51
+ return typeof resolveId === "object" ? {
52
+ ...resolveId,
53
+ handler: evaluationHandler
54
+ } : evaluationHandler;
55
+ }
56
+ function createEvaluationPluginFacade(plugin, resolveBarePackage) {
57
+ return {
58
+ name: plugin.name,
59
+ enforce: plugin.enforce,
60
+ resolveId: createEvaluationResolveId(plugin, resolveBarePackage),
61
+ load: plugin.load,
62
+ transform: environmentSpecificTransformPluginNames.has(plugin.name) ? void 0 : plugin.transform
63
+ };
64
+ }
65
+ const tamaguiEvaluationPluginNames = /* @__PURE__ */ new Set([
66
+ "tamagui",
67
+ "tamagui-extract",
68
+ "tamagui-rnw-lite"
69
+ ]);
70
+ function isEvaluationUserPlugin(plugin) {
71
+ return !!(plugin.resolveId || plugin.load || plugin.transform) && plugin.name !== "alias" && !plugin.name.startsWith("native:") && !plugin.name.startsWith("vite:") && !plugin.name.startsWith("builtin:vite-") && !tamaguiEvaluationPluginNames.has(plugin.name);
21
72
  }
22
- function getSharedCacheSize() {
23
- return globalThis[CACHE_SIZE_KEY] || 0;
73
+ function isEvaluationCorePlugin(plugin) {
74
+ return plugin.name === "alias" || plugin.name.startsWith("vite:") || plugin.name.startsWith("builtin:vite-");
24
75
  }
25
- function setSharedCacheSize(size) {
26
- ;
27
- globalThis[CACHE_SIZE_KEY] = size;
76
+ function isConfiguredEvaluationPackage(source, packages) {
77
+ const cleanSource = source.split(/[?#]/, 1)[0];
78
+ return [...packages].some((packageName) => cleanSource === packageName || cleanSource.startsWith(`${packageName}/`));
28
79
  }
29
- function clearSharedCache() {
30
- ;
31
- globalThis[CACHE_KEY] = {};
32
- globalThis[CACHE_SIZE_KEY] = 0;
80
+ function getEvaluationPackageName(source) {
81
+ if (!source) return;
82
+ const cleanSource = source.split(/[?#]/, 1)[0];
83
+ if (!cleanSource || cleanSource.startsWith(".") || cleanSource.startsWith("#") || cleanSource.startsWith("\0") || path.isAbsolute(cleanSource)) return;
84
+ if (cleanSource.startsWith("@")) {
85
+ const [scope, name2] = cleanSource.split("/");
86
+ return scope && name2 ? `${scope}/${name2}` : void 0;
87
+ }
88
+ const [name] = cleanSource.split("/");
89
+ return name && !path.extname(name) ? name : void 0;
90
+ }
91
+ function scanInstalledTamaguiPackages(root, configuredEvaluationPackages) {
92
+ const packageRequire = createRequire(path.join(root, "package.json"));
93
+ const externalizable = /* @__PURE__ */ new Set();
94
+ const compilerCondition = /* @__PURE__ */ new Set();
95
+ for (const modulePath of packageRequire.resolve.paths("@tamagui/core") || []) {
96
+ const scopePath = path.join(modulePath, "@tamagui");
97
+ if (!existsSync(scopePath)) continue;
98
+ for (const entry of readdirSync(scopePath, { withFileTypes: true })) {
99
+ if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
100
+ const packageName = `@tamagui/${entry.name}`;
101
+ if (inlineEvaluationTamaguiPackage.test(packageName) || configuredEvaluationPackages.has(packageName)) continue;
102
+ if (packageDeclaresCompilerCondition(path.join(scopePath, entry.name))) compilerCondition.add(packageName);
103
+ else externalizable.add(packageName);
104
+ }
105
+ }
106
+ return {
107
+ externalizable,
108
+ compilerCondition
109
+ };
110
+ }
111
+ function getEvaluationResolve(resolve2, root, disableTsconfigPaths, configuredEvaluationPackages) {
112
+ const noExternal = resolve2.noExternal;
113
+ const noExternalFilter = noExternal && noExternal !== true ? createFilter(void 0, noExternal, { resolve: false }) : void 0;
114
+ const isNoExternalPackage = noExternal === true ? () => true : noExternalFilter ? (packageName) => !noExternalFilter(packageName) : () => false;
115
+ return {
116
+ ...resolve2,
117
+ external: resolve2.external === true ? true : [.../* @__PURE__ */ new Set([...(resolve2.external || []).filter((packageName) => !isConfiguredEvaluationPackage(packageName, configuredEvaluationPackages)), ...[...scanInstalledTamaguiPackages(root, configuredEvaluationPackages).externalizable].filter((packageName) => !isNoExternalPackage(packageName))])],
118
+ ...disableTsconfigPaths && { tsconfigPaths: false }
119
+ };
120
+ }
121
+ function isConfiguredExternalPackage(source, external) {
122
+ if (external === true) return true;
123
+ const cleanSource = source.split(/[?#]/, 1)[0];
124
+ return external?.some((packageName) => cleanSource === packageName || cleanSource.startsWith(`${packageName}/`));
125
+ }
126
+ function createServeEvaluationConfig(config, configuredEvaluationPackages) {
127
+ const environment = config.environments[TAMAGUI_EVALUATION_ENVIRONMENT];
128
+ let packageResolver;
129
+ const resolveBarePackage = async (evaluationEnvironment, source, importer) => {
130
+ const resolved = await packageResolver?.(evaluationEnvironment, source, importer);
131
+ if (!resolved) return;
132
+ const cleanResolved = resolved.split(/[?#]/, 1)[0];
133
+ if (!inlineEvaluationTamaguiPackage.test(source) && !isConfiguredEvaluationPackage(source, configuredEvaluationPackages) && isConfiguredExternalPackage(source, evaluationEnvironment.config.resolve.external)) return {
134
+ id: source,
135
+ external: true
136
+ };
137
+ if (inlineEvaluationTamaguiPackage.test(source) || isConfiguredEvaluationPackage(source, configuredEvaluationPackages) || !normalizePath(cleanResolved).includes("/node_modules/") || !externalizablePackageExtensions.has(path.extname(cleanResolved))) return resolved;
138
+ return {
139
+ id: source,
140
+ external: true
141
+ };
142
+ };
143
+ const plugins = environment.plugins.flatMap((plugin) => {
144
+ if (isEvaluationCorePlugin(plugin)) return [plugin];
145
+ if (isEvaluationUserPlugin(plugin)) return [createEvaluationPluginFacade(plugin, resolveBarePackage)];
146
+ return [];
147
+ });
148
+ const resolve2 = getEvaluationResolve(environment.resolve, config.root, plugins.some((plugin) => plugin.name === oneTsconfigPathsPluginName), configuredEvaluationPackages);
149
+ const evaluationConfig = {
150
+ ...config,
151
+ environments: {
152
+ ...config.environments,
153
+ [TAMAGUI_EVALUATION_ENVIRONMENT]: {
154
+ ...environment,
155
+ plugins,
156
+ resolve: resolve2
157
+ }
158
+ }
159
+ };
160
+ packageResolver = createIdResolver(evaluationConfig);
161
+ return evaluationConfig;
162
+ }
163
+ async function createOwnedEvaluationConfig(config, configuredEvaluationPackages) {
164
+ const environment = config.environments[TAMAGUI_EVALUATION_ENVIRONMENT];
165
+ const plugins = environment.plugins.filter(isEvaluationUserPlugin).map((plugin) => createEvaluationPluginFacade(plugin));
166
+ const resolve2 = getEvaluationResolve(environment.resolve, config.root, plugins.some((plugin) => plugin.name === oneTsconfigPathsPluginName), configuredEvaluationPackages);
167
+ const { createEnvironment: _createEnvironment, ...dev } = environment.dev;
168
+ return resolveConfig({
169
+ configFile: false,
170
+ root: config.root,
171
+ mode: config.mode,
172
+ logLevel: config.logLevel,
173
+ plugins,
174
+ define: environment.define,
175
+ resolve: resolve2,
176
+ environments: { [TAMAGUI_EVALUATION_ENVIRONMENT]: {
177
+ consumer: environment.consumer,
178
+ keepProcessEnv: environment.keepProcessEnv,
179
+ define: environment.define,
180
+ resolve: resolve2,
181
+ optimizeDeps: environment.optimizeDeps,
182
+ dev: {
183
+ ...dev,
184
+ moduleRunnerTransform: true
185
+ }
186
+ } }
187
+ }, "serve", config.mode);
188
+ }
189
+ const _pluginRequire = createRequire(typeof __filename === "string" ? __filename : fileURLToPath(import.meta.url));
190
+ const resolve = (name) => _pluginRequire.resolve(name);
191
+ const normalizePath = (value) => value.replace(/\\/g, "/");
192
+ const PLUGIN_INSTANCE_KEY = "__tamagui_vite_plugin_instance__";
193
+ function reportCompilerStats(root, reports) {
194
+ const report = createCompilerStatsReport(root, reports);
195
+ console.info(formatCompilerStatsReport(report, process.env.TAMAGUI_COMPILER_STATS === "verbose"));
196
+ if (process.env.TAMAGUI_COMPILER_STATS_FILE) {
197
+ const outputPath = path.resolve(root, process.env.TAMAGUI_COMPILER_STATS_FILE);
198
+ writeFileSync(outputPath, `${JSON.stringify(report, null, 2)}
199
+ `);
200
+ console.info(`[tamagui] compiler stats JSON: ${path.relative(process.cwd(), outputPath)}`);
201
+ }
202
+ }
203
+ function getNextPluginInstanceId() {
204
+ const next = (globalThis[PLUGIN_INSTANCE_KEY] || 0) + 1;
205
+ globalThis[PLUGIN_INSTANCE_KEY] = next;
206
+ return next;
33
207
  }
34
208
  function isInstalled(projectRoot, id) {
35
- try {
36
- const req = createRequire(path.join(projectRoot, "package.json"));
37
- req.resolve(id);
38
- return true;
39
- } catch {
40
- return false;
41
- }
209
+ try {
210
+ createRequire(path.join(projectRoot, "package.json")).resolve(id);
211
+ return true;
212
+ } catch {
213
+ return false;
214
+ }
42
215
  }
43
216
  function addIfInstalled(userConf, projectRoot, ids) {
44
- const root = projectRoot || process.cwd();
45
- userConf.optimizeDeps ||= {};
46
- userConf.optimizeDeps.include ||= [];
47
- for (const id of ids) {
48
- if (!userConf.optimizeDeps.include.includes(id) && isInstalled(root, id)) {
49
- userConf.optimizeDeps.include.push(id);
50
- }
51
- }
217
+ const root = projectRoot || process.cwd();
218
+ userConf.optimizeDeps ||= {};
219
+ userConf.optimizeDeps.include ||= [];
220
+ for (const id of ids) if (!userConf.optimizeDeps.include.includes(id) && isInstalled(root, id)) userConf.optimizeDeps.include.push(id);
52
221
  }
53
- function getPendingExtractions() {
54
- if (!globalThis[PENDING_KEY]) {
55
- ;
56
- globalThis[PENDING_KEY] = /* @__PURE__ */new Map();
57
- }
58
- return globalThis[PENDING_KEY];
222
+ function svgWebEntry() {
223
+ return normalizePath(path.join(path.dirname(resolve("@tamagui/react-native-svg/package.json")), "dist/esm/index.mjs"));
59
224
  }
60
225
  function tamaguiAliases(options = {}) {
61
- const aliases = [];
62
- if (options.svg) {
63
- aliases.push({
64
- find: "react-native-svg",
65
- replacement: resolve("@tamagui/react-native-svg")
66
- });
67
- }
68
- if (options.rnwLite) {
69
- const rnwlBase = path.dirname(resolve("@tamagui/react-native-web-lite/package.json"));
70
- const rnwl = normalizePath(path.join(rnwlBase, options.rnwLite === "without-animated" ? "dist/esm/without-animated.mjs" : "dist/esm/index.mjs"));
71
- const rnwlFlatModules = readdirSync(path.join(rnwlBase, "dist/esm")).filter(file => file.endsWith(".mjs")).map(file => file.slice(0, -".mjs".length)).filter(name => /^[A-Za-z0-9_]+$/.test(name));
72
- aliases.push({
73
- // map deep RNW paths like dist/exports/StyleSheet/preprocess to rnw-lite's flat structure
74
- // extracts the final path segment (e.g. "preprocess" or "createReactDOMStyle")
75
- //
76
- // only match segments rnw-lite actually ships. it implements part of
77
- // react-native-web's export surface, not all of it, and there is no
78
- // flat StyleSheet.mjs. expo sdk 56 added
79
- // expo/src/launch/AppRegistry.web.tsx, which does
80
- // `require('react-native-web/dist/exports/StyleSheet')`; the unscoped
81
- // pattern rewrote that onto a file that does not exist and failed the
82
- // whole optimize. anything lite lacks now falls through to the real
83
- // package.
84
- find: new RegExp(`^react-native(?:-web)?\\/dist\\/(?:exports|modules)\\/(?:.*\\/)?(${rnwlFlatModules.join("|")})$`),
85
- replacement: `${normalizePath(rnwlBase)}/dist/esm/$1.mjs`
86
- }, {
87
- find: /^react-native$/,
88
- replacement: rnwl
89
- }, {
90
- find: /^react-native\/(Libraries\/Utilities\/codegenNativeComponent|Libraries\/Utilities\/codegenNativeCommand)$/,
91
- replacement: `${rnwlBase}/$1`
92
- }, {
93
- find: "react-native/package.json",
94
- replacement: resolve("@tamagui/react-native-web-lite/package.json")
95
- }, {
96
- find: /^react-native-web$/,
97
- replacement: rnwl
98
- });
99
- }
100
- return aliases;
226
+ const aliases = [];
227
+ if (options.svg) {
228
+ const svg = svgWebEntry();
229
+ aliases.push({
230
+ find: "react-native-svg",
231
+ replacement: svg
232
+ }, {
233
+ find: "@tamagui/react-native-svg",
234
+ replacement: svg
235
+ });
236
+ }
237
+ if (options.rnwLite) {
238
+ const rnwlBase = path.dirname(resolve("@tamagui/react-native-web-lite/package.json"));
239
+ const rnwl = normalizePath(path.join(rnwlBase, options.rnwLite === "without-animated" ? "dist/esm/without-animated.mjs" : "dist/esm/index.mjs"));
240
+ const rnwlFlatModules = readdirSync(path.join(rnwlBase, "dist/esm")).filter((file) => file.endsWith(".mjs")).map((file) => file.slice(0, -4)).filter((name) => /^[A-Za-z0-9_]+$/.test(name));
241
+ aliases.push({
242
+ find: new RegExp(`^react-native(?:-web)?\\/dist\\/(?:exports|modules)\\/(?:.*\\/)?(${rnwlFlatModules.join("|")})$`),
243
+ replacement: `${normalizePath(rnwlBase)}/dist/esm/$1.mjs`
244
+ }, {
245
+ find: /^react-native$/,
246
+ replacement: rnwl
247
+ }, {
248
+ find: /^react-native\/(Libraries\/Utilities\/codegenNativeComponent|Libraries\/Utilities\/codegenNativeCommand)$/,
249
+ replacement: `${rnwlBase}/$1`
250
+ }, {
251
+ find: "react-native/package.json",
252
+ replacement: resolve("@tamagui/react-native-web-lite/package.json")
253
+ }, {
254
+ find: /^react-native-web$/,
255
+ replacement: rnwl
256
+ });
257
+ }
258
+ return aliases;
101
259
  }
102
- function tamaguiPlugin({
103
- disableResolveConfig,
104
- ...tamaguiOptionsIn
105
- } = {}) {
106
- let shouldExtract = !tamaguiOptionsIn.disableExtraction;
107
- let watcher;
108
- const enableNativeEnv = !!globalThis.__vxrnEnableNativeEnv;
109
- const extensions = [`.web.mjs`, `.web.js`, `.web.jsx`, `.web.ts`, `.web.tsx`, ".mjs", ".js", ".mts", ".ts", ".jsx", ".tsx", ".json"];
110
- loadTamaguiBuildConfig(tamaguiOptionsIn);
111
- const ensureLoaded = async () => {
112
- const promise = getLoadPromise();
113
- if (promise) await promise;
114
- const options = getTamaguiOptions();
115
- if (options) {
116
- shouldExtract = !options.disableExtraction;
117
- }
118
- return options;
119
- };
120
- const getHash = input => createHash("sha1").update(input).digest("base64");
121
- const memoryCache = getSharedCache();
122
- const cssMap = /* @__PURE__ */new Map();
123
- let config;
124
- let server;
125
- const virtualExt = `.tamagui.css`;
126
- const getAbsoluteVirtualFileId = filePath => {
127
- if (filePath.startsWith(config.root)) {
128
- return filePath;
129
- }
130
- return normalizePath(path.join(config.root, filePath));
131
- };
132
- function isNotClient(environment) {
133
- return environment?.name && environment.name !== "client";
134
- }
135
- function isNative(environment) {
136
- return environment?.name && (environment.name === "ios" || environment.name === "android");
137
- }
138
- function invalidateModule(absoluteId) {
139
- if (!server) return;
140
- const {
141
- moduleGraph
142
- } = server;
143
- const modules = moduleGraph.getModulesByFile(absoluteId);
144
- if (modules) {
145
- for (const module of modules) {
146
- moduleGraph.invalidateModule(module);
147
- module.lastHMRTimestamp = module.lastInvalidationTimestamp || Date.now();
148
- }
149
- }
150
- }
151
- const basePlugin = {
152
- name: "tamagui",
153
- enforce: "pre",
154
- configureServer(_server) {
155
- server = _server;
156
- },
157
- async buildEnd() {
158
- await watcher?.then(res => {
159
- res?.dispose();
160
- });
161
- },
162
- async config(_, env) {
163
- const options = await ensureLoaded();
164
- if (!options) {
165
- throw new Error(`No tamagui options loaded`);
166
- }
167
- const useReactNativeWebLite = tamaguiOptionsIn.useReactNativeWebLite ?? options.useReactNativeWebLite;
168
- if (!options.disableWatchTamaguiConfig) {
169
- watcher = Static.watchTamaguiConfig({
170
- components: ["tamagui"],
171
- config: "./src/tamagui.config.ts",
172
- ...options
173
- }).catch(err => {
174
- console.error(` [Tamagui] Error watching config: ${err}`);
175
- });
176
- }
177
- return {
178
- envPrefix: ["TAMAGUI_"],
179
- environments: {
180
- client: {
181
- define: {
182
- "process.env.TAMAGUI_IS_CLIENT": JSON.stringify(true),
183
- "process.env.TAMAGUI_ENVIRONMENT": '"client"'
184
- }
185
- }
186
- },
187
- define: {
188
- // reanimated support
189
- _frameTimestamp: void 0,
190
- _WORKLET: false,
191
- __DEV__: `${env.mode === "development"}`,
192
- "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || env.mode),
193
- "process.env.ENABLE_RSC": JSON.stringify(process.env.ENABLE_RSC || ""),
194
- "process.env.ENABLE_STEPS": JSON.stringify(process.env.ENABLE_STEPS || ""),
195
- "process.env.IS_STATIC": JSON.stringify(false),
196
- ...(env.mode === "production" && {
197
- "process.env.TAMAGUI_OPTIMIZE_THEMES": JSON.stringify(true)
198
- })
199
- },
200
- resolve: disableResolveConfig || enableNativeEnv ? {} : {
201
- extensions,
202
- alias: {
203
- ...(options.platform !== "native" && {
204
- "react-native/Libraries/Renderer/shims/ReactFabric": resolve("@tamagui/proxy-worm"),
205
- "react-native/Libraries/Utilities/codegenNativeComponent": resolve("@tamagui/proxy-worm"),
206
- "react-native-svg": resolve("@tamagui/react-native-svg"),
207
- ...(!useReactNativeWebLite && {
208
- "react-native": resolve("react-native-web")
209
- })
210
- })
211
- }
212
- }
213
- };
214
- }
215
- };
216
- const rnwLitePlugin = {
217
- name: "tamagui-rnw-lite",
218
- // framework plugins may add their default react-native-web aliases from a
219
- // normal config hook. apply the explicit lite choice after those defaults.
220
- enforce: "post",
221
- config() {
222
- if (enableNativeEnv) {
223
- return {};
224
- }
225
- const options = getTamaguiOptions();
226
- const useReactNativeWebLite = tamaguiOptionsIn.useReactNativeWebLite ?? options?.useReactNativeWebLite;
227
- if (!useReactNativeWebLite) {
228
- return {};
229
- }
230
- const include = [];
231
- for (const dependency of ["memoize-one", "@react-native/normalize-color"]) {
232
- if (isInstalled(process.cwd(), dependency)) include.push(dependency);
233
- }
234
- return {
235
- resolve: {
236
- alias: tamaguiAliases({
237
- rnwLite: useReactNativeWebLite
238
- })
239
- },
240
- optimizeDeps: {
241
- // upstream react-native-web must not be pre-bundled when aliased to lite
242
- exclude: ["react-native-web"],
243
- include
244
- }
245
- };
246
- }
247
- };
248
- const extractPlugin = {
249
- name: "tamagui-extract",
250
- enforce: "pre",
251
- async config(userConf) {
252
- const options = await ensureLoaded();
253
- userConf.optimizeDeps ||= {};
254
- userConf.optimizeDeps.include ||= [];
255
- userConf.optimizeDeps.include.push("inline-style-prefixer");
256
- addIfInstalled(userConf, userConf.root, ["@tamagui/toast", "@tamagui/toast/v2", "@tamagui/sheet", "@tamagui/sheet/controller"]);
257
- userConf.resolve ||= {};
258
- userConf.resolve.dedupe ||= [];
259
- for (const id of ["tamagui", "@tamagui/core", "@tamagui/web", "@tamagui/toast", "@tamagui/sheet"]) {
260
- if (!userConf.resolve.dedupe.includes(id) && isInstalled(userConf.root || process.cwd(), id)) {
261
- userConf.resolve.dedupe.push(id);
262
- }
263
- }
264
- if (!shouldExtract) return;
265
- userConf.optimizeDeps.include.push("@tamagui/core/inject-styles");
266
- },
267
- async configResolved(resolvedConfig) {
268
- config = resolvedConfig;
269
- },
270
- async resolveId(source) {
271
- if (!shouldExtract) return;
272
- if (isNative(this.environment)) {
273
- return;
274
- }
275
- if (isNotClient(this.environment)) {
276
- return;
277
- }
278
- const [validId, query] = source.split("?");
279
- if (!validId.endsWith(virtualExt)) {
280
- return;
281
- }
282
- const absoluteId = source.startsWith(config.root) ? source : getAbsoluteVirtualFileId(validId);
283
- if (cssMap.has(absoluteId)) {
284
- return absoluteId + (query ? `?${query}` : "");
285
- }
286
- },
287
- async load(id) {
288
- if (!shouldExtract) return;
289
- const options = getTamaguiOptions();
290
- if (options?.disable) {
291
- return;
292
- }
293
- if (isNative(this.environment)) {
294
- return;
295
- }
296
- if (isNotClient(this.environment)) {
297
- return;
298
- }
299
- const [validId] = id.split("?");
300
- return cssMap.get(validId);
301
- },
302
- transform: {
303
- order: "pre",
304
- async handler(code, id) {
305
- const options = await ensureLoaded();
306
- await ensureFullConfigLoaded();
307
- if (options?.disable) {
308
- return;
309
- }
310
- if (isNative(this.environment)) {
311
- return;
312
- }
313
- const [validId] = id.split("?");
314
- if (!validId.endsWith(".tsx")) {
315
- return;
316
- }
317
- const {
318
- shouldDisable,
319
- shouldPrintDebug
320
- } = await getPragmaOptions({
321
- source: code,
322
- path: validId
323
- });
324
- if (shouldPrintDebug) {
325
- console.trace(`Current file: ${id} in environment: ${this.environment?.name}, shouldDisable: ${shouldDisable}`);
326
- console.info(`
327
-
328
- Original source:
329
- ${code}
330
-
260
+ function createTamaguiNativePlugin(tamaguiOptionsIn, nativeContext) {
261
+ let compilerFrontend = new Static.CompilerFrontend();
262
+ const projectDependencies = /* @__PURE__ */ new Set();
263
+ let root = nativeContext?.root || process.cwd();
264
+ let projectPromise = null;
265
+ let nativeOptions = null;
266
+ let rebuildProject = false;
267
+ let generation = 0;
268
+ const loadProject = async (resolveModule) => {
269
+ if (projectPromise) return projectPromise;
270
+ const shouldRebuild = rebuildProject;
271
+ rebuildProject = false;
272
+ const guarded = (async () => {
273
+ projectDependencies.clear();
274
+ const loadedOptions = await Static.loadTamaguiBuildConfigAsync({
275
+ ...tamaguiOptionsIn,
276
+ root,
277
+ platform: "native",
278
+ outputCSS: void 0
279
+ });
280
+ const options = {
281
+ ...loadedOptions,
282
+ root,
283
+ outputCSS: void 0
284
+ };
285
+ nativeOptions = options;
286
+ for (const dependency of Static.getTamaguiBuildConfigDependencies(loadedOptions)) projectDependencies.add(normalizePath(dependency));
287
+ if (options.disable || options.disableExtraction) return null;
288
+ const project = await Static.loadCompilerProject({
289
+ root,
290
+ target: "native",
291
+ options,
292
+ rebuild: shouldRebuild,
293
+ generation: `vite-native:${generation + 1}`,
294
+ missingProjectMessage: "Unable to load the Tamagui project for Vite native compilation",
295
+ async resolveComponents(moduleNames) {
296
+ return Promise.all(moduleNames.map(async (moduleName) => {
297
+ const id = await resolveModule(moduleName);
298
+ projectDependencies.add(normalizePath(id.split(/[?#]/, 1)[0]));
299
+ return {
300
+ moduleName,
301
+ id
302
+ };
303
+ }));
304
+ }
305
+ });
306
+ for (const dependency of project.projectInfo.dependencies ?? []) projectDependencies.add(normalizePath(dependency.split(/[?#]/, 1)[0]));
307
+ const configPath = options.config || "tamagui.config.ts";
308
+ projectDependencies.add(normalizePath(path.isAbsolute(configPath) ? configPath : path.resolve(root, configPath)));
309
+ const buildFile = options.buildFile || "tamagui.build.ts";
310
+ projectDependencies.add(normalizePath(path.isAbsolute(buildFile) ? buildFile : path.resolve(root, buildFile)));
311
+ if (options.themeBuilder?.input) projectDependencies.add(normalizePath(path.isAbsolute(options.themeBuilder.input) ? options.themeBuilder.input : path.resolve(root, options.themeBuilder.input)));
312
+ generation++;
313
+ return project;
314
+ })().catch((error) => {
315
+ if (projectPromise === guarded) projectPromise = null;
316
+ rebuildProject = true;
317
+ throw error;
318
+ });
319
+ projectPromise = guarded;
320
+ return projectPromise;
321
+ };
322
+ return {
323
+ name: "tamagui-native-compiler",
324
+ enforce: "post",
325
+ configResolved(config) {
326
+ root = config.root;
327
+ },
328
+ watchChange(id) {
329
+ if (projectDependencies.has(normalizePath(id.split(/[?#]/, 1)[0]))) {
330
+ rebuildProject = true;
331
+ projectPromise = null;
332
+ compilerFrontend = new Static.CompilerFrontend();
333
+ }
334
+ },
335
+ transform: {
336
+ order: "pre",
337
+ async handler(code, id) {
338
+ const environmentName = nativeContext?.platform || this.environment?.name;
339
+ if (environmentName !== "ios" && environmentName !== "android") return;
340
+ const [validId] = id.split("?");
341
+ if (!validId || !/\.[jt]sx$/.test(validId) || normalizePath(validId).split("/").includes("node_modules")) return;
342
+ const { shouldDisable } = await Static.getPragmaOptions({
343
+ source: code,
344
+ path: validId
345
+ });
346
+ if (shouldDisable) return;
347
+ const resolve2 = async (specifier, importer) => {
348
+ const resolution = await this.resolve(specifier, importer, { skipSelf: true });
349
+ return resolution ? {
350
+ id: resolution.id,
351
+ external: resolution.external === true
352
+ } : null;
353
+ };
354
+ const project = await loadProject(async (specifier) => {
355
+ const resolution = await resolve2(specifier, path.join(root, "__tamagui_native.tsx"));
356
+ if (!resolution) throw new Error(`Unable to resolve native compiler component ${specifier}`);
357
+ return resolution.id;
358
+ });
359
+ if (!project) return;
360
+ for (const dependency of projectDependencies) this.addWatchFile(dependency);
361
+ const result = await compilerFrontend.compile({
362
+ id: validId,
363
+ source: code,
364
+ root,
365
+ target: "native",
366
+ project,
367
+ resolve: resolve2,
368
+ evaluate: async ({ id: moduleId }) => nativeOptions ? Static.evaluateComponentModule(nativeOptions, moduleId) : null,
369
+ load: async (dependencyId) => {
370
+ const cleanDependencyId = dependencyId.split(/[?#]/, 1)[0];
371
+ if (!path.isAbsolute(cleanDependencyId)) return null;
372
+ try {
373
+ return await readFile(cleanDependencyId, "utf8");
374
+ } catch {
375
+ return null;
376
+ }
377
+ }
378
+ });
379
+ for (const dependency of result.plan.dependencies) if (path.isAbsolute(dependency)) this.addWatchFile(dependency);
380
+ if (result.plan.css) throw new Error(`Native Tamagui compilation produced unexpected CSS for ${validId}`);
381
+ return result.output.changed ? {
382
+ code: result.output.code,
383
+ map: result.output.map
384
+ } : void 0;
385
+ }
386
+ }
387
+ };
388
+ }
389
+ function tamaguiNativePlugin(tamaguiOptionsIn = {}) {
390
+ const plugin = createTamaguiNativePlugin(tamaguiOptionsIn);
391
+ const api = plugin.api && typeof plugin.api === "object" ? plugin.api : {};
392
+ return {
393
+ ...plugin,
394
+ api: {
395
+ ...api,
396
+ vxrnNative: (context) => createTamaguiNativePlugin(tamaguiOptionsIn, context)
397
+ }
398
+ };
399
+ }
400
+ function createTamaguiPlugins({ disableResolveConfig, wrapExtractedCSS = (css) => css, zeroIslandBuild, ...tamaguiOptionsIn } = {}) {
401
+ let shouldExtract = !tamaguiOptionsIn.disableExtraction;
402
+ const enableNativeEnv = !!globalThis.__vxrnEnableNativeEnv;
403
+ const tamaguiLoader = createViteTamaguiLoader(tamaguiOptionsIn);
404
+ const compilerFrontends = /* @__PURE__ */ new WeakMap();
405
+ const getCompilerFrontend = (environment) => {
406
+ let frontend = compilerFrontends.get(environment);
407
+ if (!frontend) {
408
+ frontend = new Static.CompilerFrontend();
409
+ compilerFrontends.set(environment, frontend);
410
+ }
411
+ return frontend;
412
+ };
413
+ const pluginInstanceId = getNextPluginInstanceId();
414
+ const configuredEvaluationPackages = /* @__PURE__ */ new Set();
415
+ let buildEnvironmentPromise = null;
416
+ let buildCleanupPromise = null;
417
+ const activeBuildEnvironments = /* @__PURE__ */ new Set();
418
+ const compilerReports = process.env.TAMAGUI_COMPILER_STATS || process.env.TAMAGUI_COMPILER_STATS_FILE ? /* @__PURE__ */ new Map() : null;
419
+ const releaseBuildEnvironment = async (environment) => {
420
+ if (!activeBuildEnvironments.delete(environment) || activeBuildEnvironments.size) return;
421
+ if (compilerReports?.size) reportCompilerStats(config?.root ?? process.cwd(), compilerReports);
422
+ const currentCleanup = Promise.resolve().then(async () => {
423
+ try {
424
+ await tamaguiLoader.cleanup();
425
+ } finally {
426
+ buildEnvironmentPromise = null;
427
+ }
428
+ });
429
+ buildCleanupPromise = currentCleanup;
430
+ try {
431
+ await currentCleanup;
432
+ } finally {
433
+ if (buildCleanupPromise === currentCleanup) buildCleanupPromise = null;
434
+ }
435
+ };
436
+ const extensions = [
437
+ `.web.mjs`,
438
+ `.web.js`,
439
+ `.web.jsx`,
440
+ `.web.ts`,
441
+ `.web.tsx`,
442
+ ".mjs",
443
+ ".js",
444
+ ".mts",
445
+ ".ts",
446
+ ".jsx",
447
+ ".tsx",
448
+ ".json"
449
+ ];
450
+ const getEvaluationEnvironmentOptions = (resolvedRoot, userNoExternal) => ({
451
+ consumer: "server",
452
+ keepProcessEnv: true,
453
+ define: {
454
+ "process.env.IS_STATIC": JSON.stringify("is_static"),
455
+ "process.env.TAMAGUI_IS_CLIENT": JSON.stringify(false),
456
+ "process.env.TAMAGUI_IS_SERVER": JSON.stringify(true),
457
+ "process.env.TAMAGUI_TARGET": JSON.stringify("web"),
458
+ "process.env.TAMAGUI_ENVIRONMENT": JSON.stringify(TAMAGUI_EVALUATION_ENVIRONMENT),
459
+ "process.env.TAMAGUI_RUNTIME": JSON.stringify("full"),
460
+ "process.env.TAMAGUI_DID_OUTPUT_CSS": JSON.stringify(""),
461
+ "process.env.VITE_ENVIRONMENT": JSON.stringify("ssr"),
462
+ "process.env.TAMAGUI_DISABLE_SLIDER_INTERVAL": JSON.stringify("1")
463
+ },
464
+ resolve: {
465
+ conditions: [TAMAGUI_COMPILER_CONDITION, ...defaultClientConditions],
466
+ mainFields: [...defaultClientMainFields],
467
+ noExternal: mergeEvaluationNoExternal([
468
+ inlineEvaluationTamaguiPackage,
469
+ ...configuredEvaluationPackages,
470
+ ...scanInstalledTamaguiPackages(resolvedRoot, configuredEvaluationPackages).compilerCondition
471
+ ], userNoExternal),
472
+ extensions
473
+ },
474
+ dev: {
475
+ createEnvironment(name, resolved) {
476
+ return createRunnableDevEnvironment(name, createServeEvaluationConfig(resolved, configuredEvaluationPackages));
477
+ },
478
+ moduleRunnerTransform: true
479
+ }
480
+ });
481
+ tamaguiLoader.loadTamaguiBuildConfig();
482
+ const ensureLoaded = async () => {
483
+ const promise = tamaguiLoader.getLoadPromise();
484
+ if (promise) await promise;
485
+ const options = tamaguiLoader.getTamaguiOptions();
486
+ if (options) shouldExtract = !options.disableExtraction;
487
+ return options;
488
+ };
489
+ const getHash = (input) => createHash("sha1").update(input).digest("base64");
490
+ const cssMap = /* @__PURE__ */ new Map();
491
+ const transformedModuleIds = /* @__PURE__ */ new Set();
492
+ const compilerHotUpdateSignatures = /* @__PURE__ */ new Map();
493
+ const compilerHotReloadSignatures = /* @__PURE__ */ new Map();
494
+ let config;
495
+ let server;
496
+ let zero = null;
497
+ let zeroReceipt = null;
498
+ let zeroBuildFailed = false;
499
+ let globalCSS = null;
500
+ let globalCSSExpected = null;
501
+ let zeroHtmlEntries = 0;
502
+ let zeroDevIslands = Promise.resolve();
503
+ const virtualExt = `.tamagui.css`;
504
+ const getAbsoluteVirtualFileId = (filePath) => {
505
+ if (filePath.startsWith(config.root)) return filePath;
506
+ return normalizePath(path.join(config.root, filePath));
507
+ };
508
+ const isAppJSXSource = (filePath) => {
509
+ if (!/\.[jt]sx$/.test(filePath)) return false;
510
+ const relative = path.relative(config.root, filePath);
511
+ return relative !== "" && relative !== ".." && !relative.startsWith(`..${path.sep}`) && !relative.split(path.sep).includes("node_modules");
512
+ };
513
+ const isFrameworkAnalysisRequest = (id) => id.includes("__react-router-build-client-route");
514
+ function isNotClient(environment) {
515
+ return environment?.name && environment.name !== "client";
516
+ }
517
+ const isDevEnvironment = (environment) => environment.mode === "dev";
518
+ function isNative(environment) {
519
+ return environment?.name && (environment.name === "ios" || environment.name === "android");
520
+ }
521
+ function invalidateCompilerModules() {
522
+ if (server) {
523
+ const ids = /* @__PURE__ */ new Set([...transformedModuleIds, ...cssMap.keys()]);
524
+ for (const environment of Object.values(server.environments)) {
525
+ if (environment.name === TAMAGUI_EVALUATION_ENVIRONMENT) continue;
526
+ for (const id of ids) {
527
+ const modules = environment.moduleGraph.getModulesByFile(id);
528
+ if (!modules) continue;
529
+ for (const module of modules) environment.moduleGraph.invalidateModule(module);
530
+ }
531
+ }
532
+ }
533
+ cssMap.clear();
534
+ }
535
+ return {
536
+ plugins: [
537
+ {
538
+ name: "tamagui",
539
+ enforce: "pre",
540
+ configureServer(_server) {
541
+ server = _server;
542
+ const evaluationEnvironment = server.environments[TAMAGUI_EVALUATION_ENVIRONMENT];
543
+ if (!isRunnableDevEnvironment(evaluationEnvironment)) throw new Error(`The ${TAMAGUI_EVALUATION_ENVIRONMENT} Vite environment must support ModuleRunner evaluation`);
544
+ tamaguiLoader.setEnvironment(evaluationEnvironment);
545
+ },
546
+ async buildEnd() {
547
+ await releaseBuildEnvironment(this.environment);
548
+ },
549
+ async config(userConfig, env) {
550
+ const options = await ensureLoaded();
551
+ if (!options) throw new Error(`No tamagui options loaded`);
552
+ const useReactNativeWebLite = tamaguiOptionsIn.useReactNativeWebLite ?? options.useReactNativeWebLite;
553
+ for (const source of [options.config, ...options.components || []]) {
554
+ const packageName = getEvaluationPackageName(source);
555
+ if (packageName) configuredEvaluationPackages.add(packageName);
556
+ }
557
+ const resolvedRoot = userConfig.root ? path.resolve(userConfig.root) : process.cwd();
558
+ zero = zeroIslandBuild ? null : await createZeroRuntimeController(options, resolvedRoot, userConfig.base || "/");
559
+ globalCSS = zeroIslandBuild || env.command !== "build" ? null : Static.resolveGlobalCSSOwnership(options, resolvedRoot);
560
+ return {
561
+ envPrefix: ["TAMAGUI_"],
562
+ environments: {
563
+ client: { define: {
564
+ "process.env.TAMAGUI_IS_CLIENT": JSON.stringify(true),
565
+ "process.env.TAMAGUI_ENVIRONMENT": "\"client\"",
566
+ ...zero?.isEnforcing && { "process.env.TAMAGUI_RUNTIME": JSON.stringify("zero") },
567
+ ...globalCSS && { "process.env.TAMAGUI_DID_OUTPUT_CSS": JSON.stringify("1") }
568
+ } },
569
+ ssr: { define: { ...globalCSS && { "process.env.TAMAGUI_DID_OUTPUT_CSS": JSON.stringify("1") } } },
570
+ [TAMAGUI_EVALUATION_ENVIRONMENT]: getEvaluationEnvironmentOptions(resolvedRoot, userConfig.environments?.[TAMAGUI_EVALUATION_ENVIRONMENT]?.resolve?.noExternal)
571
+ },
572
+ define: {
573
+ "process.env.TAMAGUI_RUNTIME": JSON.stringify("full"),
574
+ _frameTimestamp: void 0,
575
+ _WORKLET: false,
576
+ __DEV__: `${env.mode === "development"}`,
577
+ "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || env.mode),
578
+ "process.env.ENABLE_RSC": JSON.stringify(process.env.ENABLE_RSC || ""),
579
+ "process.env.ENABLE_STEPS": JSON.stringify(process.env.ENABLE_STEPS || ""),
580
+ "process.env.IS_STATIC": JSON.stringify(false),
581
+ ...env.mode === "production" && { "process.env.TAMAGUI_OPTIMIZE_THEMES": JSON.stringify(true) }
582
+ },
583
+ resolve: disableResolveConfig || enableNativeEnv ? {} : {
584
+ extensions,
585
+ alias: { ...options.platform !== "native" && {
586
+ "react-native/Libraries/Renderer/shims/ReactFabric": resolve("@tamagui/proxy-worm"),
587
+ "react-native/Libraries/Utilities/codegenNativeComponent": resolve("@tamagui/proxy-worm"),
588
+ "react-native-svg": svgWebEntry(),
589
+ "@tamagui/react-native-svg": svgWebEntry(),
590
+ ...!useReactNativeWebLite && { "react-native": resolve("react-native-web") }
591
+ } }
592
+ }
593
+ };
594
+ }
595
+ },
596
+ {
597
+ name: "tamagui-rnw-lite",
598
+ enforce: "post",
599
+ config() {
600
+ if (enableNativeEnv) return {};
601
+ const options = tamaguiLoader.getTamaguiOptions();
602
+ const useReactNativeWebLite = tamaguiOptionsIn.useReactNativeWebLite ?? options?.useReactNativeWebLite;
603
+ if (!useReactNativeWebLite) return {};
604
+ const include = [];
605
+ for (const dependency of ["memoize-one", "@react-native/normalize-color"]) if (isInstalled(process.cwd(), dependency)) include.push(dependency);
606
+ return {
607
+ resolve: { alias: tamaguiAliases({ rnwLite: useReactNativeWebLite }) },
608
+ ssr: { noExternal: [
609
+ /^@tamagui\//,
610
+ "tamagui",
611
+ "react-native",
612
+ "react-native-web"
613
+ ] },
614
+ optimizeDeps: {
615
+ exclude: ["react-native-web"],
616
+ include
617
+ }
618
+ };
619
+ }
620
+ },
621
+ {
622
+ name: "tamagui-extract",
623
+ enforce: "pre",
624
+ async config(userConf) {
625
+ await ensureLoaded();
626
+ userConf.optimizeDeps ||= {};
627
+ userConf.optimizeDeps.include ||= [];
628
+ userConf.optimizeDeps.include.push("inline-style-prefixer");
629
+ addIfInstalled(userConf, userConf.root, ["@react-native/normalize-color"]);
630
+ addIfInstalled(userConf, userConf.root, [
631
+ "@tamagui/core",
632
+ "@tamagui/core/theme-update",
633
+ "@tamagui/web",
634
+ "@tamagui/web/theme-update",
635
+ "@tamagui/animations-css",
636
+ "@tamagui/animations-css/extras",
637
+ "@tamagui/toast",
638
+ "@tamagui/sheet",
639
+ "@tamagui/sheet/controller"
640
+ ]);
641
+ userConf.resolve ||= {};
642
+ userConf.resolve.dedupe ||= [];
643
+ for (const id of [
644
+ "tamagui",
645
+ "@tamagui/core",
646
+ "@tamagui/core/theme-update",
647
+ "@tamagui/web",
648
+ "@tamagui/web/theme-update",
649
+ "@tamagui/animations-css",
650
+ "@tamagui/toast",
651
+ "@tamagui/sheet"
652
+ ]) if (!userConf.resolve.dedupe.includes(id) && isInstalled(userConf.root || process.cwd(), id)) userConf.resolve.dedupe.push(id);
653
+ if (!shouldExtract) return;
654
+ userConf.optimizeDeps.include.push("@tamagui/core/inject-styles");
655
+ },
656
+ async configResolved(resolvedConfig) {
657
+ config = resolvedConfig;
658
+ },
659
+ async buildStart() {
660
+ const buildConfig = this.environment.getTopLevelConfig();
661
+ if (buildConfig.command !== "build") return;
662
+ const pendingCleanup = buildCleanupPromise;
663
+ if (pendingCleanup) await pendingCleanup;
664
+ const buildEnvironment = this.environment;
665
+ activeBuildEnvironments.add(buildEnvironment);
666
+ try {
667
+ if (!tamaguiLoader.getEnvironment()) {
668
+ await tamaguiLoader.loadTamaguiBuildConfig();
669
+ buildEnvironmentPromise ||= (async () => {
670
+ const evaluationEnvironment = createRunnableDevEnvironment(TAMAGUI_EVALUATION_ENVIRONMENT, await createOwnedEvaluationConfig(buildConfig, configuredEvaluationPackages), { hot: false });
671
+ try {
672
+ await evaluationEnvironment.init();
673
+ } catch (error) {
674
+ await evaluationEnvironment.close().catch(() => void 0);
675
+ throw error;
676
+ }
677
+ tamaguiLoader.setEnvironment(evaluationEnvironment, { owned: true });
678
+ })();
679
+ await buildEnvironmentPromise;
680
+ }
681
+ } catch (error) {
682
+ await releaseBuildEnvironment(buildEnvironment);
683
+ throw error;
684
+ }
685
+ },
686
+ hotUpdate: {
687
+ order: "post",
688
+ async handler(options) {
689
+ if (!tamaguiLoader.isEvaluationDependency(options.file)) {
690
+ if (this.environment.name !== "client") return;
691
+ const compilerFrontend = getCompilerFrontend(this.environment);
692
+ const source = options.type === "delete" ? null : await options.read();
693
+ const affectedModules = /* @__PURE__ */ new Set();
694
+ const compilerHmrRoots = new Set(compilerFrontend.dependentsOf(options.file));
695
+ if (compilerHmrRoots.size || compilerFrontend.has(options.file)) compilerHmrRoots.add(options.file);
696
+ if (compilerFrontend.has(options.file) || compilerHmrRoots.size > 0) {
697
+ if (!(await ensureLoaded())?.disable) {
698
+ const invalidatedIds = options.type === "delete" ? (await compilerFrontend.remove(options.file)).invalidatedIds : await compilerFrontend.update({
699
+ id: options.file,
700
+ source,
701
+ root: config.root,
702
+ target: "web",
703
+ environment: this.environment.name,
704
+ project: {
705
+ ...await tamaguiLoader.getCompilerProject(),
706
+ generation: `${pluginInstanceId}:${tamaguiLoader.getGeneration()}`
707
+ },
708
+ resolve: async (specifier, importer) => {
709
+ const resolution = await this.environment.pluginContainer.resolveId(specifier, importer);
710
+ return resolution ? {
711
+ id: resolution.id,
712
+ external: resolution.external === true
713
+ } : null;
714
+ },
715
+ load: async (dependencyId) => {
716
+ const cleanDependencyId = dependencyId.split(/[?#]/, 1)[0];
717
+ if (!path.isAbsolute(cleanDependencyId)) return null;
718
+ try {
719
+ return await readFile(cleanDependencyId, "utf8");
720
+ } catch {
721
+ return null;
722
+ }
723
+ }
724
+ });
725
+ for (const invalidatedId of invalidatedIds) {
726
+ for (const module of this.environment.moduleGraph.getModulesByFile(invalidatedId) ?? []) {
727
+ this.environment.moduleGraph.invalidateModule(module);
728
+ if (compilerHmrRoots.has(invalidatedId) || module.isSelfAccepting) affectedModules.add(module);
729
+ }
730
+ const cssId = getAbsoluteVirtualFileId(`${invalidatedId}${virtualExt}`);
731
+ const cssModule = this.environment.moduleGraph.getModuleById(cssId);
732
+ if (cssModule) {
733
+ this.environment.moduleGraph.invalidateModule(cssModule);
734
+ affectedModules.add(cssModule);
735
+ }
736
+ }
737
+ }
738
+ }
739
+ return affectedModules.size ? [...affectedModules] : void 0;
740
+ }
741
+ const signature = await (async () => {
742
+ if (options.type === "delete") return getHash(`${options.type}:${options.file}`);
743
+ try {
744
+ return getHash(`${options.type}:${options.file}:${await options.read()}`);
745
+ } catch {
746
+ return getHash(`${options.type}:${options.file}:${options.timestamp}`);
747
+ }
748
+ })();
749
+ if (compilerHotUpdateSignatures.get(options.file) !== signature) {
750
+ compilerHotUpdateSignatures.set(options.file, signature);
751
+ tamaguiLoader.invalidate(options.file);
752
+ invalidateCompilerModules();
753
+ }
754
+ if (this.environment.name === "client" && compilerHotReloadSignatures.get(options.file) !== signature) {
755
+ compilerHotReloadSignatures.set(options.file, signature);
756
+ this.environment.hot.send({
757
+ type: "full-reload",
758
+ path: "*",
759
+ triggeredBy: options.file
760
+ });
761
+ }
762
+ return [];
763
+ }
764
+ },
765
+ async watchChange(id) {
766
+ if (config.command !== "build") return;
767
+ if (tamaguiLoader.isEvaluationDependency(id)) {
768
+ tamaguiLoader.invalidate(id);
769
+ invalidateCompilerModules();
770
+ }
771
+ },
772
+ async resolveId(source) {
773
+ if (isNative(this.environment)) return;
774
+ if (isNotClient(this.environment)) return;
775
+ if (!shouldExtract) return;
776
+ const [validId, query] = source.split("?");
777
+ if (!validId.endsWith(virtualExt)) return;
778
+ const absoluteId = validId.startsWith(config.root) ? validId : getAbsoluteVirtualFileId(validId);
779
+ if (cssMap.has(absoluteId)) return absoluteId + (query ? `?${query}` : "");
780
+ },
781
+ async load(id) {
782
+ if (tamaguiLoader.getTamaguiOptions()?.disable) return;
783
+ if (isNative(this.environment)) return;
784
+ if (isNotClient(this.environment)) return;
785
+ if (!shouldExtract) return;
786
+ const [validId] = id.split("?");
787
+ if (!validId.endsWith(virtualExt)) return;
788
+ if (isDevEnvironment(this.environment)) {
789
+ const importer = this.environment.moduleGraph.getModuleById(validId.slice(0, -virtualExt.length));
790
+ if (importer && importer.transformResult == null) await this.environment.transformRequest(importer.url);
791
+ }
792
+ return cssMap.get(validId);
793
+ }
794
+ },
795
+ {
796
+ name: "tamagui-compiler",
797
+ enforce: "post",
798
+ transform: {
799
+ order: "pre",
800
+ async handler(code, id) {
801
+ if (this.environment?.name === TAMAGUI_EVALUATION_ENVIRONMENT) return;
802
+ if (!tamaguiLoader.getEnvironment()) return;
803
+ if (isNative(this.environment)) return;
804
+ const [validId] = id.split("?");
805
+ if (isFrameworkAnalysisRequest(id) || !isAppJSXSource(validId) || !/\.[jt]sx$/.test(validId)) return;
806
+ if ((await ensureLoaded())?.disable || !shouldExtract) return;
807
+ const { shouldDisable } = await Static.getPragmaOptions({
808
+ source: code,
809
+ path: validId
810
+ });
811
+ if (shouldDisable) return;
812
+ const evaluationDependencies = await tamaguiLoader.ensureFullConfigLoaded();
813
+ for (const dependency of evaluationDependencies) this.addWatchFile(dependency);
814
+ const compilerProject = await tamaguiLoader.getCompilerProject();
815
+ const result = await getCompilerFrontend(this.environment).compile({
816
+ id: validId,
817
+ source: code,
818
+ root: config.root,
819
+ target: "web",
820
+ environment: this.environment.name,
821
+ project: {
822
+ ...compilerProject,
823
+ generation: `${pluginInstanceId}:${tamaguiLoader.getGeneration()}`,
824
+ zeroRuntime: zero !== null
825
+ },
826
+ resolve: async (specifier, importer) => {
827
+ const resolution = await this.resolve(specifier, importer, { skipSelf: true });
828
+ return resolution ? {
829
+ id: resolution.id,
830
+ external: resolution.external === true
831
+ } : null;
832
+ },
833
+ evaluate: ({ id: moduleId }) => tamaguiLoader.evaluateModule(moduleId),
834
+ load: async (dependencyId) => {
835
+ const cleanDependencyId = dependencyId.split(/[?#]/, 1)[0];
836
+ if (!path.isAbsolute(cleanDependencyId)) return null;
837
+ try {
838
+ return await readFile(cleanDependencyId, "utf8");
839
+ } catch {
840
+ return null;
841
+ }
842
+ }
843
+ });
844
+ transformedModuleIds.add(validId);
845
+ compilerReports?.set(validId, {
846
+ stats: result.plan.stats,
847
+ diagnostics: result.plan.diagnostics
848
+ });
849
+ for (const dependency of result.plan.dependencies) if (path.isAbsolute(dependency)) this.addWatchFile(dependency);
850
+ if (zeroIslandBuild) {
851
+ zeroIslandBuild.artifact.setIslandModuleCSS(zeroIslandBuild.islandId, validId, wrapExtractedCSS(result.plan.css));
852
+ return result.output.changed ? {
853
+ code: result.output.code,
854
+ map: result.output.map
855
+ } : void 0;
856
+ }
857
+ if (zero) {
858
+ const zeroResult = Static.transformZeroModule({
859
+ mode: zero.isEnforcing ? "enforce" : "report",
860
+ id: validId,
861
+ root: config.root,
862
+ source: code,
863
+ plan: result.plan,
864
+ config: await tamaguiLoader.getTamaguiConfig(),
865
+ isTamaguiSpecifier: Static.isTamaguiSpecifier,
866
+ resolveIslandLoader: (specifier) => {
867
+ const islandId = zero.loaderIds.get(zeroModuleKey(path.resolve(path.dirname(validId), specifier)));
868
+ return islandId ? { islandId } : null;
869
+ },
870
+ resolveIslandModule: (specifier) => zero.islandModuleIds.get(zeroModuleKey(path.resolve(path.dirname(validId), specifier))) ?? null
871
+ });
872
+ zero.transformed.add(validId);
873
+ if (zeroResult.erased.exports.length) zero.erasedExports.set(validId, zeroResult.erased.exports);
874
+ for (const violation of zeroResult.violations) {
875
+ const { line, column } = Static.offsetToLineColumn(code, violation.span.start);
876
+ zero.violations.push({
877
+ file: path.relative(config.root, validId),
878
+ line,
879
+ column,
880
+ rule: violation.rule,
881
+ code: violation.code,
882
+ component: violation.component,
883
+ message: violation.message
884
+ });
885
+ }
886
+ if (zero.isEnforcing) {
887
+ Static.mergeIslandBridges(zero.bridges, zeroResult.bridges);
888
+ const moduleCSS = [wrapExtractedCSS(result.plan.css), ...zeroResult.bridgeCSS.values()].filter(Boolean).join("\n");
889
+ if (config.command !== "build") {
890
+ let cssImport2 = "";
891
+ if (moduleCSS) {
892
+ const rootRelativeId = `${validId}${virtualExt}`;
893
+ cssMap.set(getAbsoluteVirtualFileId(rootRelativeId), moduleCSS);
894
+ this.addWatchFile(rootRelativeId);
895
+ cssImport2 = `
896
+ import "${rootRelativeId}";`;
897
+ }
898
+ return {
899
+ code: `${zeroResult.output.code}${cssImport2}`,
900
+ map: zeroResult.output.map
901
+ };
902
+ }
903
+ for (const [identifier, rules] of zeroResult.bridgeCSS) zero.artifact.setBridgeRules(identifier, rules);
904
+ zero.artifact.setZeroModuleCSS(validId, wrapExtractedCSS(result.plan.css));
905
+ return zeroResult.output.changed ? {
906
+ code: zeroResult.output.code,
907
+ map: zeroResult.output.map
908
+ } : void 0;
909
+ }
910
+ }
911
+ const isSSR = isNotClient(this.environment);
912
+ let cssImport = null;
913
+ if (result.plan.css) {
914
+ const rootRelativeId = `${validId}${virtualExt}`;
915
+ const absoluteId = getAbsoluteVirtualFileId(rootRelativeId);
916
+ cssMap.set(absoluteId, wrapExtractedCSS(result.plan.css));
917
+ this.addWatchFile(rootRelativeId);
918
+ if (!isSSR) cssImport = `import "${rootRelativeId}";`;
919
+ }
920
+ const finalCode = cssImport ? `${result.output.code}
921
+ ${cssImport}` : result.output.code;
922
+ return result.output.changed || cssImport ? {
923
+ code: finalCode,
924
+ map: result.output.map
925
+ } : void 0;
926
+ }
927
+ }
928
+ },
929
+ {
930
+ name: "tamagui-zero-runtime",
931
+ enforce: "post",
932
+ async buildStart() {
933
+ if (!zero || this.environment.name !== "client") return;
934
+ await tamaguiLoader.ensureFullConfigLoaded();
935
+ const tamaguiConfig = await tamaguiLoader.getTamaguiConfig();
936
+ if (!tamaguiConfig) throw new Error(`[tamagui zero-runtime] the Tamagui config did not evaluate, so no CSS artifact can be generated`);
937
+ zero.violations.length = 0;
938
+ zero.transformed.clear();
939
+ zero.erasedExports.clear();
940
+ if (!zero.isEnforcing) return;
941
+ Static.assertZeroConfigDrivers(tamaguiConfig);
942
+ zero.artifact.clearGraphs();
943
+ zero.bridges.clear();
944
+ zeroHtmlEntries = 0;
945
+ zero.artifact.setConfigCSS(tamaguiConfig.getCSS());
946
+ if (config.command !== "build") {
947
+ const islands = zero;
948
+ zeroDevIslands = Promise.all(islands.resolved.islands.map((island) => buildIsland({
949
+ island,
950
+ controller: islands,
951
+ root: config.root,
952
+ outDir: zeroDevIslandDir(islands),
953
+ mode: "development"
954
+ })));
955
+ await zeroDevIslands;
956
+ }
957
+ },
958
+ async configureServer(devServer) {
959
+ if (!zero?.isEnforcing) return;
960
+ const islandBase = `${zero.cssHref.replace(ZERO_CSS_FILENAME, "")}${ZERO_ISLAND_DIRNAME}/`;
961
+ devServer.middlewares.use(async (request, response, next) => {
962
+ const url = (request.url || "").split("?")[0];
963
+ if (url !== zero.cssHref && !url.startsWith(islandBase)) return next();
964
+ await zeroDevIslands;
965
+ if (url === zero.cssHref) {
966
+ response.setHeader("content-type", "text/css; charset=utf-8");
967
+ response.setHeader("cache-control", "no-cache");
968
+ response.end(zero.artifact.css());
969
+ return;
970
+ }
971
+ const islandId = url.slice(islandBase.length).replace(/\.js$/, "");
972
+ const file = path.join(zeroDevIslandDir(zero), ZERO_ISLAND_DIRNAME, `${islandId}.js`);
973
+ if (!existsSync(file)) return next();
974
+ response.setHeader("content-type", "text/javascript; charset=utf-8");
975
+ response.setHeader("cache-control", "no-cache");
976
+ response.end(readFileSync(file));
977
+ });
978
+ },
979
+ buildEnd(error) {
980
+ if (!zero || this.environment.name !== "client") return;
981
+ if (error) {
982
+ zeroBuildFailed = true;
983
+ return;
984
+ }
985
+ if (!zero.isEnforcing) return;
986
+ const importers = /* @__PURE__ */ new Map();
987
+ for (const moduleId of this.getModuleIds()) importers.set(moduleId, this.getModuleInfo(moduleId)?.importers ?? []);
988
+ const escape = Static.erasedExportEscape({
989
+ integration: "vite",
990
+ transformed: zero.transformed,
991
+ erasedExports: zero.erasedExports,
992
+ importersOf: importers
993
+ });
994
+ if (escape) {
995
+ zeroBuildFailed = true;
996
+ throw new Error(escape);
997
+ }
998
+ },
999
+ transformIndexHtml: {
1000
+ order: "post",
1001
+ handler(html) {
1002
+ if (!zero?.isEnforcing) return;
1003
+ zeroHtmlEntries++;
1004
+ return {
1005
+ html,
1006
+ tags: [{
1007
+ tag: "link",
1008
+ attrs: {
1009
+ rel: "stylesheet",
1010
+ href: zero.cssHref
1011
+ },
1012
+ injectTo: "head"
1013
+ }]
1014
+ };
1015
+ }
1016
+ },
1017
+ generateBundle(_outputOptions, bundle) {
1018
+ if (!zero?.isEnforcing || this.environment.name !== "client") return;
1019
+ const importers = /* @__PURE__ */ new Map();
1020
+ for (const moduleId of this.getModuleIds()) for (const imported of this.getModuleInfo(moduleId)?.importedIds ?? []) {
1021
+ const list = importers.get(imported);
1022
+ if (list) list.push(moduleId);
1023
+ else importers.set(imported, [moduleId]);
1024
+ }
1025
+ const entries = [];
1026
+ const modules = [];
1027
+ for (const chunk of Object.values(bundle)) {
1028
+ if (chunk.type !== "chunk") continue;
1029
+ for (const moduleId of Object.keys(chunk.modules)) {
1030
+ modules.push({
1031
+ id: moduleId,
1032
+ importers: importers.get(moduleId) ?? []
1033
+ });
1034
+ if (this.getModuleInfo(moduleId)?.isEntry) entries.push(moduleId);
1035
+ }
1036
+ }
1037
+ const checked = Static.checkZeroGraph({
1038
+ entries,
1039
+ modules,
1040
+ importerEdges: importers,
1041
+ root: zero.resolved.root
1042
+ });
1043
+ zeroReceipt = {
1044
+ integration: "vite",
1045
+ graph: "zero",
1046
+ entries: entries.sort(),
1047
+ moduleCount: modules.length,
1048
+ tamaguiModules: checked.tamaguiModules,
1049
+ forbidden: checked.forbidden,
1050
+ cssArtifact: null,
1051
+ identity: "",
1052
+ gzip: Object.fromEntries(Object.values(bundle).filter((chunk) => chunk.type === "chunk").map((chunk) => [chunk.fileName, gzipSync(Buffer.from(chunk.code), { level: 9 }).length]))
1053
+ };
1054
+ },
1055
+ async closeBundle() {
1056
+ if (!zero || this.environment.name !== "client") return;
1057
+ const outDir = path.resolve(config.root, this.environment.config.build.outDir);
1058
+ const receiptName = `vite-${path.basename(outDir)}`;
1059
+ Static.writeZeroViolationReport(zero.resolved.outDir, receiptName, {
1060
+ integration: "vite",
1061
+ mode: zero.isEnforcing ? "enforce" : "report",
1062
+ violations: zero.violations
1063
+ });
1064
+ if (!zero.isEnforcing || zeroBuildFailed) return;
1065
+ if (zero.violations.length) throw new Error(Static.formatZeroViolations(zero.violations));
1066
+ const islandOutputHashes = {};
1067
+ for (const island of zero.resolved.islands) {
1068
+ const built = await buildIsland({
1069
+ island,
1070
+ controller: zero,
1071
+ root: config.root,
1072
+ outDir,
1073
+ mode: config.mode
1074
+ });
1075
+ islandOutputHashes[island.id] = built.hash;
1076
+ }
1077
+ if (zeroHtmlEntries === 0) throw new Error(`[tamagui zero-runtime] the zero entry graph has no HTML entry, so the one generated CSS artifact ${zero.cssHref} is never loaded. Build a zero entry through its HTML document.`);
1078
+ const css = finalizeZeroCSS(zero, outDir);
1079
+ const bridgeManifest = Static.canonicalizeBridgeManifest(Object.fromEntries([...zero.bridges.entries()].sort(([left], [right]) => left < right ? -1 : 1)));
1080
+ const identityInputs = {
1081
+ runtimeLiteral: "zero",
1082
+ target: "web",
1083
+ configGeneration: `${pluginInstanceId}:${tamaguiLoader.getGeneration()}`,
1084
+ cssHash: css.hash,
1085
+ compilerVersion: Static.ZERO_COMPILER_VERSION,
1086
+ islandEntries: zero.resolved.islands.map((island) => island.module),
1087
+ bridgeManifestHash: Static.hashBridgeManifest(bridgeManifest),
1088
+ islandOutputHashes
1089
+ };
1090
+ const identity = Static.hashZeroIdentity(identityInputs);
1091
+ if (!zeroReceipt) throw new Error(`[tamagui zero-runtime] no module graph was recorded for the zero entry`);
1092
+ zeroReceipt.cssArtifact = {
1093
+ path: css.href,
1094
+ hash: css.hash
1095
+ };
1096
+ zeroReceipt.identity = identity;
1097
+ Static.writeZeroGraphReceipt(zero.resolved.outDir, receiptName, zeroReceipt);
1098
+ writeFileSync(path.join(zero.resolved.outDir, `${receiptName}.bridges.json`), `${JSON.stringify({
1099
+ identity,
1100
+ identityInputs,
1101
+ cssGzip: css.gzip,
1102
+ bridges: bridgeManifest
1103
+ }, null, 2)}
331
1104
  `);
332
- }
333
- if (shouldDisable) {
334
- return;
335
- }
336
- const isSSR = isNotClient(this.environment);
337
- const cacheKey = getHash(`${code}${id}`);
338
- const pending = getPendingExtractions();
339
- const formatResult = entry => {
340
- const finalCode = !isSSR && entry.cssImport ? `${entry.js}
341
- ${entry.cssImport}` : entry.js;
342
- return {
343
- code: finalCode,
344
- map: entry.map
345
- };
346
- };
347
- const cached = memoryCache[cacheKey];
348
- if (cached) {
349
- if (process.env.DEBUG_TAMAGUI_CACHE) {
350
- console.info(`[tamagui-cache] HIT ${this.environment?.name || "unknown"} ${id.split("/").pop()} key=${cacheKey.slice(0, 8)}`);
351
- }
352
- return formatResult(cached);
353
- }
354
- const pendingExtraction = pending.get(cacheKey);
355
- if (pendingExtraction) {
356
- if (process.env.DEBUG_TAMAGUI_CACHE) {
357
- console.info(`[tamagui-cache] WAIT ${this.environment?.name || "unknown"} ${id.split("/").pop()} key=${cacheKey.slice(0, 8)}`);
358
- }
359
- const result = await pendingExtraction;
360
- if (result) {
361
- return formatResult(result);
362
- }
363
- return;
364
- }
365
- if (process.env.DEBUG_TAMAGUI_CACHE) {
366
- console.info(`[tamagui-cache] EXTRACT ${this.environment?.name || "unknown"} ${id.split("/").pop()} key=${cacheKey.slice(0, 8)}`);
367
- }
368
- const extractionPromise = (async () => {
369
- let extracted;
370
- try {
371
- extracted = await Static.extractToClassNames({
372
- source: code,
373
- sourcePath: validId,
374
- options,
375
- shouldPrintDebug
376
- });
377
- } catch (err) {
378
- if (process.env.DEBUG_TAMAGUI_CACHE) {
379
- console.info(`[tamagui-cache] ERROR extracting ${id.split("/").pop()}:`, err);
380
- }
381
- console.error(err instanceof Error ? err.message : String(err));
382
- return null;
383
- }
384
- if (!extracted) {
385
- if (process.env.DEBUG_TAMAGUI_CACHE) {
386
- console.info(`[tamagui-cache] no extraction result for ${id.split("/").pop()}`);
387
- }
388
- return null;
389
- }
390
- const rootRelativeId = `${validId}${virtualExt}`;
391
- const absoluteId = getAbsoluteVirtualFileId(rootRelativeId);
392
- let cssImport = null;
393
- if (extracted.styles) {
394
- this.addWatchFile(rootRelativeId);
395
- if (server && cssMap.has(absoluteId)) {
396
- invalidateModule(rootRelativeId);
397
- }
398
- cssImport = `import "${rootRelativeId}";`;
399
- cssMap.set(absoluteId, extracted.styles);
400
- }
401
- const jsCode = extracted.js.toString();
402
- const cacheEntry = {
403
- js: jsCode,
404
- map: extracted.map,
405
- cssImport
406
- };
407
- const newSize = getSharedCacheSize() + jsCode.length;
408
- if (newSize > 67108864) {
409
- clearSharedCache();
410
- } else {
411
- setSharedCacheSize(newSize);
412
- }
413
- memoryCache[cacheKey] = cacheEntry;
414
- if (process.env.DEBUG_TAMAGUI_CACHE) {
415
- console.info(`[tamagui-cache] WRITE key=${cacheKey.slice(0, 8)} cacheSize=${Object.keys(memoryCache).length}`);
416
- }
417
- return cacheEntry;
418
- })();
419
- pending.set(cacheKey, extractionPromise);
420
- try {
421
- const result = await extractionPromise;
422
- if (result) {
423
- return formatResult(result);
424
- }
425
- return;
426
- } finally {
427
- pending.delete(cacheKey);
428
- }
429
- }
430
- }
431
- };
432
- return [basePlugin, rnwLitePlugin, extractPlugin];
1105
+ assertZeroGraph(zeroReceipt);
1106
+ }
1107
+ },
1108
+ {
1109
+ name: "tamagui-global-css",
1110
+ enforce: "post",
1111
+ apply: "build",
1112
+ async buildStart() {
1113
+ if (!globalCSS || this.environment.name !== "client") return;
1114
+ await tamaguiLoader.ensureFullConfigLoaded();
1115
+ const tamaguiConfig = await tamaguiLoader.getTamaguiConfig();
1116
+ if (!tamaguiConfig) throw new Error(`[tamagui] outputCSS is set but the Tamagui config did not evaluate, so no CSS artifact can be generated`);
1117
+ globalCSSExpected = tamaguiConfig.getCSS();
1118
+ },
1119
+ generateBundle() {
1120
+ if (!globalCSS || this.environment.name !== "client") return;
1121
+ const failure = Static.checkGlobalCSSArtifact({
1122
+ cssPath: globalCSS.cssPath,
1123
+ expectedCSS: globalCSSExpected ?? "",
1124
+ loadedModuleIds: this.getModuleIds(),
1125
+ importHint: `Import it once from your client entry: import ${JSON.stringify(relativeImportSpecifier(config.root, globalCSS.cssPath))}`
1126
+ });
1127
+ if (failure) throw new Error(failure.message);
1128
+ }
1129
+ },
1130
+ tamaguiNativePlugin(tamaguiOptionsIn)
1131
+ ],
1132
+ loader: tamaguiLoader
1133
+ };
1134
+ }
1135
+ function zeroDevIslandDir(zero) {
1136
+ return path.join(zero.resolved.outDir, "dev");
1137
+ }
1138
+ function relativeImportSpecifier(from, to) {
1139
+ const relative = normalizePath(path.relative(from, to));
1140
+ return relative.startsWith(".") ? relative : `./${relative}`;
433
1141
  }
434
- export { tamaguiAliases, tamaguiPlugin };
1142
+ function tamaguiPlugin(options = {}) {
1143
+ return createTamaguiPlugins(options).plugins;
1144
+ }
1145
+
1146
+ export { createTamaguiPlugins, tamaguiAliases, tamaguiNativePlugin, tamaguiPlugin };
435
1147
  //# sourceMappingURL=plugin.mjs.map