@flairjs/webpack-loader 0.0.1-beta.2 → 0.0.1-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -71,8 +71,33 @@ function tokensToCSSVars(tokens, prefix = []) {
71
71
  }
72
72
  return css$1;
73
73
  }
74
+ var Store = class {
75
+ fileNameToGeneratedCssNameMap = /* @__PURE__ */ new Map();
76
+ lastThemeUpdate = Date.now();
77
+ userTheme = /* @__PURE__ */ new Map();
78
+ getUserTheme() {
79
+ return this.userTheme.get(this.lastThemeUpdate) ?? null;
80
+ }
81
+ setUserTheme(theme) {
82
+ this.userTheme.set(this.lastThemeUpdate, theme);
83
+ }
84
+ getLastThemeUpdate() {
85
+ return this.lastThemeUpdate;
86
+ }
87
+ setLastThemeUpdate(timestamp) {
88
+ this.lastThemeUpdate = timestamp;
89
+ }
90
+ setFileNameToGeneratedCssNameMap(fileName, generatedCssName) {
91
+ this.fileNameToGeneratedCssNameMap.set(fileName, generatedCssName);
92
+ }
93
+ getGeneratedCssName(fileName) {
94
+ return this.fileNameToGeneratedCssNameMap.get(fileName);
95
+ }
96
+ };
97
+ const store = new Store();
74
98
  const __dirname$1 = (0, node_path.dirname)((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href));
75
99
  const getUserTheme = async () => {
100
+ if (store.getUserTheme()) return store.getUserTheme();
76
101
  try {
77
102
  let userThemeFilePath = path.default.resolve(process.cwd(), "flair.theme.ts");
78
103
  if (!(0, fs.existsSync)(userThemeFilePath)) userThemeFilePath = path.default.resolve(process.cwd(), "flair.theme.js");
@@ -88,10 +113,17 @@ const getUserTheme = async () => {
88
113
  });
89
114
  const cacheBuster = Date.now();
90
115
  const userTheme = await import(`${(0, url.pathToFileURL)(outFile).href}?update=${cacheBuster}`);
91
- if (userTheme.default) return {
92
- theme: userTheme.default,
93
- originalPath: userThemeFilePath
94
- };
116
+ if (userTheme.default) {
117
+ store.setUserTheme({
118
+ theme: userTheme.default,
119
+ originalPath: userThemeFilePath
120
+ });
121
+ return {
122
+ theme: userTheme.default,
123
+ originalPath: userThemeFilePath
124
+ };
125
+ }
126
+ store.setUserTheme(null);
95
127
  return null;
96
128
  } catch (error) {
97
129
  console.error("Error loading user theme:", error);
@@ -99,53 +131,60 @@ const getUserTheme = async () => {
99
131
  }
100
132
  };
101
133
  const require$1 = node_module.default.createRequire(require("url").pathToFileURL(__filename).href);
102
- /**
103
- * Initialize the shared plugin context
104
- */
105
- async function initializeSharedContext(options = {}) {
106
- const { buildThemeFile } = options;
107
- const fileNameToGeneratedCssNameMap = /* @__PURE__ */ new Map();
134
+ const getGeneratedCssDir = () => {
108
135
  const flairThemeFile = require$1.resolve("@flairjs/client/theme.css");
109
- const flairGeneratedCssDir = node_path.default.resolve(flairThemeFile, "../generated-css");
110
- if (!(0, node_fs.existsSync)(flairGeneratedCssDir)) await (0, node_fs_promises.mkdir)(flairGeneratedCssDir);
111
- else {
112
- await (0, node_fs_promises.rm)(flairGeneratedCssDir, {
113
- recursive: true,
114
- force: true
115
- });
116
- await (0, node_fs_promises.mkdir)(flairGeneratedCssDir);
136
+ return node_path.default.resolve(flairThemeFile, "../generated-css");
137
+ };
138
+ const setupGeneratedCssDir = async () => {
139
+ const flairGeneratedCssDir = getGeneratedCssDir();
140
+ try {
141
+ if (!(0, node_fs.existsSync)(flairGeneratedCssDir)) await (0, node_fs_promises.mkdir)(flairGeneratedCssDir);
142
+ else {
143
+ await (0, node_fs_promises.rm)(flairGeneratedCssDir, {
144
+ recursive: true,
145
+ force: true
146
+ });
147
+ await (0, node_fs_promises.mkdir)(flairGeneratedCssDir);
148
+ }
149
+ } catch (err) {
150
+ if (err?.code === "EEXIST") return flairGeneratedCssDir;
151
+ else if ((0, node_fs.existsSync)(flairGeneratedCssDir)) return flairGeneratedCssDir;
152
+ console.error(`[flairjs] Could not create generated CSS directory: ${flairGeneratedCssDir}`, err);
153
+ return null;
117
154
  }
155
+ return flairGeneratedCssDir;
156
+ };
157
+ const setupUserThemeFile = async ({ buildThemeFile }) => {
158
+ const flairThemeFile = require$1.resolve("@flairjs/client/theme.css");
118
159
  let userTheme = await getUserTheme();
119
160
  const buildThemeCSS = buildThemeFile ?? buildThemeTokens;
120
161
  if (userTheme) {
121
162
  const themeCSS = buildThemeCSS(userTheme.theme);
163
+ store.setLastThemeUpdate(Date.now());
122
164
  await (0, node_fs_promises.writeFile)(flairThemeFile, themeCSS, "utf-8");
123
165
  (0, node_fs.watch)(userTheme.originalPath, async () => {
124
166
  userTheme = await getUserTheme();
167
+ store.setLastThemeUpdate(Date.now());
125
168
  if (!userTheme) return;
126
169
  const themeCSS$1 = buildThemeCSS(userTheme.theme);
127
170
  await (0, node_fs_promises.writeFile)(flairThemeFile, themeCSS$1, "utf-8");
128
171
  });
129
172
  }
130
- const refreshCssFile = (filePath) => {
131
- if (fileNameToGeneratedCssNameMap.has(filePath)) {
132
- const previousGeneratedCssName = fileNameToGeneratedCssNameMap.get(filePath);
133
- setTimeout(() => {
134
- (0, node_fs_promises.rm)(node_path.default.join(flairGeneratedCssDir, previousGeneratedCssName));
135
- }, 2e3);
136
- }
137
- };
138
- return {
139
- flairThemeFile,
140
- flairGeneratedCssDir,
141
- userTheme,
142
- buildThemeCSS,
143
- refreshCssFile
144
- };
145
- }
173
+ return userTheme;
174
+ };
175
+ const removeOutdatedCssFiles = async (sourceFilePath, cssFilePath, { flairGeneratedCssDir }) => {
176
+ const previousGeneratedCssName = store.getGeneratedCssName(sourceFilePath);
177
+ if (previousGeneratedCssName && previousGeneratedCssName !== cssFilePath) setTimeout(() => {
178
+ (0, node_fs_promises.rm)(node_path.default.join(flairGeneratedCssDir, previousGeneratedCssName), { force: true });
179
+ }, 2e3);
180
+ else store.setFileNameToGeneratedCssNameMap(sourceFilePath, cssFilePath);
181
+ };
146
182
  function shouldProcessFile(id, include, exclude) {
147
- const isIncluded = (0, picomatch.default)(include || ["**/*.{js,ts,jsx,tsx}"]);
148
- const isExcluded = (0, picomatch.default)(exclude || ["node_modules/**"]);
183
+ const normalizePatterns = (patterns, defaults) => {
184
+ return (patterns ? Array.isArray(patterns) ? patterns : [patterns] : defaults).map((pattern) => pattern.replace(/\\/g, "/"));
185
+ };
186
+ const isIncluded = (0, picomatch.default)(normalizePatterns(include, ["**/*.{js,ts,jsx,tsx}"]));
187
+ const isExcluded = (0, picomatch.default)(normalizePatterns(exclude, ["node_modules/**"]));
149
188
  if (!isIncluded(id)) return false;
150
189
  if (isExcluded(id)) return false;
151
190
  return true;
@@ -191,27 +230,41 @@ const transformCode = (code, filePath, options) => {
191
230
 
192
231
  //#endregion
193
232
  //#region src/index.ts
233
+ let initialized = false;
194
234
  async function flairJsLoader(source, sourceMap) {
195
235
  const callback = this.async();
236
+ const options = this.getOptions() || {};
196
237
  if (!callback) {
197
238
  console.error("@flairjs/webpack-loader requires async support");
198
239
  return;
199
240
  }
200
- const options = this.getOptions() || {};
201
- const context = await initializeSharedContext(options);
241
+ let cssGeneratedDir = null;
242
+ let userTheme = null;
243
+ if (!initialized) {
244
+ cssGeneratedDir = await setupGeneratedCssDir();
245
+ userTheme = await setupUserThemeFile({ buildThemeFile: options.buildThemeFile });
246
+ initialized = true;
247
+ } else {
248
+ cssGeneratedDir = getGeneratedCssDir();
249
+ userTheme = await getUserTheme();
250
+ }
202
251
  const fileName = this.resourcePath;
203
252
  if (!shouldProcessFile(fileName, options?.include, options?.exclude)) return callback(null, source, sourceMap);
253
+ if (!cssGeneratedDir) {
254
+ console.error("[flairjs] Could not find generated CSS directory. Skipping processing.");
255
+ return callback(null, source, sourceMap);
256
+ }
204
257
  try {
205
258
  const result = transformCode(source, fileName, {
206
259
  appendTimestampToCssFile: true,
207
260
  classNameList: options?.classNameList,
208
261
  cssPreprocessor: options?.cssPreprocessor ? (css) => options.cssPreprocessor(css, fileName) : void 0,
209
- theme: context.userTheme?.theme,
210
- useTheme: !!context.userTheme,
211
- cssOutDir: context.flairGeneratedCssDir
262
+ theme: userTheme?.theme,
263
+ useTheme: !!userTheme,
264
+ cssOutDir: cssGeneratedDir
212
265
  });
213
266
  if (!result) return callback(null, source, sourceMap);
214
- if (result.generatedCssName) context.refreshCssFile(result.generatedCssName);
267
+ if (result.generatedCssName) removeOutdatedCssFiles(fileName, result.generatedCssName, { flairGeneratedCssDir: cssGeneratedDir });
215
268
  callback(null, result.code, result.sourcemap ? JSON.parse(result.sourcemap ?? "{}") : sourceMap);
216
269
  } catch (error) {
217
270
  console.error("[@flairjs/webpack-loader]", error);
package/dist/esm/index.js CHANGED
@@ -37,8 +37,33 @@ function tokensToCSSVars(tokens, prefix = []) {
37
37
  }
38
38
  return css$1;
39
39
  }
40
+ var Store = class {
41
+ fileNameToGeneratedCssNameMap = /* @__PURE__ */ new Map();
42
+ lastThemeUpdate = Date.now();
43
+ userTheme = /* @__PURE__ */ new Map();
44
+ getUserTheme() {
45
+ return this.userTheme.get(this.lastThemeUpdate) ?? null;
46
+ }
47
+ setUserTheme(theme) {
48
+ this.userTheme.set(this.lastThemeUpdate, theme);
49
+ }
50
+ getLastThemeUpdate() {
51
+ return this.lastThemeUpdate;
52
+ }
53
+ setLastThemeUpdate(timestamp) {
54
+ this.lastThemeUpdate = timestamp;
55
+ }
56
+ setFileNameToGeneratedCssNameMap(fileName, generatedCssName) {
57
+ this.fileNameToGeneratedCssNameMap.set(fileName, generatedCssName);
58
+ }
59
+ getGeneratedCssName(fileName) {
60
+ return this.fileNameToGeneratedCssNameMap.get(fileName);
61
+ }
62
+ };
63
+ const store = new Store();
40
64
  const __dirname = dirname(fileURLToPath(import.meta.url));
41
65
  const getUserTheme = async () => {
66
+ if (store.getUserTheme()) return store.getUserTheme();
42
67
  try {
43
68
  let userThemeFilePath = path$1.resolve(process.cwd(), "flair.theme.ts");
44
69
  if (!existsSync$1(userThemeFilePath)) userThemeFilePath = path$1.resolve(process.cwd(), "flair.theme.js");
@@ -54,10 +79,17 @@ const getUserTheme = async () => {
54
79
  });
55
80
  const cacheBuster = Date.now();
56
81
  const userTheme = await import(`${pathToFileURL(outFile).href}?update=${cacheBuster}`);
57
- if (userTheme.default) return {
58
- theme: userTheme.default,
59
- originalPath: userThemeFilePath
60
- };
82
+ if (userTheme.default) {
83
+ store.setUserTheme({
84
+ theme: userTheme.default,
85
+ originalPath: userThemeFilePath
86
+ });
87
+ return {
88
+ theme: userTheme.default,
89
+ originalPath: userThemeFilePath
90
+ };
91
+ }
92
+ store.setUserTheme(null);
61
93
  return null;
62
94
  } catch (error) {
63
95
  console.error("Error loading user theme:", error);
@@ -65,53 +97,60 @@ const getUserTheme = async () => {
65
97
  }
66
98
  };
67
99
  const require = module.createRequire(import.meta.url);
68
- /**
69
- * Initialize the shared plugin context
70
- */
71
- async function initializeSharedContext(options = {}) {
72
- const { buildThemeFile } = options;
73
- const fileNameToGeneratedCssNameMap = /* @__PURE__ */ new Map();
100
+ const getGeneratedCssDir = () => {
74
101
  const flairThemeFile = require.resolve("@flairjs/client/theme.css");
75
- const flairGeneratedCssDir = path.resolve(flairThemeFile, "../generated-css");
76
- if (!existsSync(flairGeneratedCssDir)) await mkdir(flairGeneratedCssDir);
77
- else {
78
- await rm(flairGeneratedCssDir, {
79
- recursive: true,
80
- force: true
81
- });
82
- await mkdir(flairGeneratedCssDir);
102
+ return path.resolve(flairThemeFile, "../generated-css");
103
+ };
104
+ const setupGeneratedCssDir = async () => {
105
+ const flairGeneratedCssDir = getGeneratedCssDir();
106
+ try {
107
+ if (!existsSync(flairGeneratedCssDir)) await mkdir(flairGeneratedCssDir);
108
+ else {
109
+ await rm(flairGeneratedCssDir, {
110
+ recursive: true,
111
+ force: true
112
+ });
113
+ await mkdir(flairGeneratedCssDir);
114
+ }
115
+ } catch (err) {
116
+ if (err?.code === "EEXIST") return flairGeneratedCssDir;
117
+ else if (existsSync(flairGeneratedCssDir)) return flairGeneratedCssDir;
118
+ console.error(`[flairjs] Could not create generated CSS directory: ${flairGeneratedCssDir}`, err);
119
+ return null;
83
120
  }
121
+ return flairGeneratedCssDir;
122
+ };
123
+ const setupUserThemeFile = async ({ buildThemeFile }) => {
124
+ const flairThemeFile = require.resolve("@flairjs/client/theme.css");
84
125
  let userTheme = await getUserTheme();
85
126
  const buildThemeCSS = buildThemeFile ?? buildThemeTokens;
86
127
  if (userTheme) {
87
128
  const themeCSS = buildThemeCSS(userTheme.theme);
129
+ store.setLastThemeUpdate(Date.now());
88
130
  await writeFile(flairThemeFile, themeCSS, "utf-8");
89
131
  watch(userTheme.originalPath, async () => {
90
132
  userTheme = await getUserTheme();
133
+ store.setLastThemeUpdate(Date.now());
91
134
  if (!userTheme) return;
92
135
  const themeCSS$1 = buildThemeCSS(userTheme.theme);
93
136
  await writeFile(flairThemeFile, themeCSS$1, "utf-8");
94
137
  });
95
138
  }
96
- const refreshCssFile = (filePath) => {
97
- if (fileNameToGeneratedCssNameMap.has(filePath)) {
98
- const previousGeneratedCssName = fileNameToGeneratedCssNameMap.get(filePath);
99
- setTimeout(() => {
100
- rm(path.join(flairGeneratedCssDir, previousGeneratedCssName));
101
- }, 2e3);
102
- }
103
- };
104
- return {
105
- flairThemeFile,
106
- flairGeneratedCssDir,
107
- userTheme,
108
- buildThemeCSS,
109
- refreshCssFile
110
- };
111
- }
139
+ return userTheme;
140
+ };
141
+ const removeOutdatedCssFiles = async (sourceFilePath, cssFilePath, { flairGeneratedCssDir }) => {
142
+ const previousGeneratedCssName = store.getGeneratedCssName(sourceFilePath);
143
+ if (previousGeneratedCssName && previousGeneratedCssName !== cssFilePath) setTimeout(() => {
144
+ rm(path.join(flairGeneratedCssDir, previousGeneratedCssName), { force: true });
145
+ }, 2e3);
146
+ else store.setFileNameToGeneratedCssNameMap(sourceFilePath, cssFilePath);
147
+ };
112
148
  function shouldProcessFile(id, include, exclude) {
113
- const isIncluded = picomatch(include || ["**/*.{js,ts,jsx,tsx}"]);
114
- const isExcluded = picomatch(exclude || ["node_modules/**"]);
149
+ const normalizePatterns = (patterns, defaults) => {
150
+ return (patterns ? Array.isArray(patterns) ? patterns : [patterns] : defaults).map((pattern) => pattern.replace(/\\/g, "/"));
151
+ };
152
+ const isIncluded = picomatch(normalizePatterns(include, ["**/*.{js,ts,jsx,tsx}"]));
153
+ const isExcluded = picomatch(normalizePatterns(exclude, ["node_modules/**"]));
115
154
  if (!isIncluded(id)) return false;
116
155
  if (isExcluded(id)) return false;
117
156
  return true;
@@ -157,27 +196,41 @@ const transformCode$1 = (code, filePath, options) => {
157
196
 
158
197
  //#endregion
159
198
  //#region src/index.ts
199
+ let initialized = false;
160
200
  async function flairJsLoader(source, sourceMap) {
161
201
  const callback = this.async();
202
+ const options = this.getOptions() || {};
162
203
  if (!callback) {
163
204
  console.error("@flairjs/webpack-loader requires async support");
164
205
  return;
165
206
  }
166
- const options = this.getOptions() || {};
167
- const context = await initializeSharedContext(options);
207
+ let cssGeneratedDir = null;
208
+ let userTheme = null;
209
+ if (!initialized) {
210
+ cssGeneratedDir = await setupGeneratedCssDir();
211
+ userTheme = await setupUserThemeFile({ buildThemeFile: options.buildThemeFile });
212
+ initialized = true;
213
+ } else {
214
+ cssGeneratedDir = getGeneratedCssDir();
215
+ userTheme = await getUserTheme();
216
+ }
168
217
  const fileName = this.resourcePath;
169
218
  if (!shouldProcessFile(fileName, options?.include, options?.exclude)) return callback(null, source, sourceMap);
219
+ if (!cssGeneratedDir) {
220
+ console.error("[flairjs] Could not find generated CSS directory. Skipping processing.");
221
+ return callback(null, source, sourceMap);
222
+ }
170
223
  try {
171
224
  const result = transformCode$1(source, fileName, {
172
225
  appendTimestampToCssFile: true,
173
226
  classNameList: options?.classNameList,
174
227
  cssPreprocessor: options?.cssPreprocessor ? (css) => options.cssPreprocessor(css, fileName) : void 0,
175
- theme: context.userTheme?.theme,
176
- useTheme: !!context.userTheme,
177
- cssOutDir: context.flairGeneratedCssDir
228
+ theme: userTheme?.theme,
229
+ useTheme: !!userTheme,
230
+ cssOutDir: cssGeneratedDir
178
231
  });
179
232
  if (!result) return callback(null, source, sourceMap);
180
- if (result.generatedCssName) context.refreshCssFile(result.generatedCssName);
233
+ if (result.generatedCssName) removeOutdatedCssFiles(fileName, result.generatedCssName, { flairGeneratedCssDir: cssGeneratedDir });
181
234
  callback(null, result.code, result.sourcemap ? JSON.parse(result.sourcemap ?? "{}") : sourceMap);
182
235
  } catch (error) {
183
236
  console.error("[@flairjs/webpack-loader]", error);
@@ -3982,8 +3982,33 @@ function tokensToCSSVars(tokens, prefix = []) {
3982
3982
  }
3983
3983
  return css$1;
3984
3984
  }
3985
+ var Store = class {
3986
+ fileNameToGeneratedCssNameMap = /* @__PURE__ */ new Map();
3987
+ lastThemeUpdate = Date.now();
3988
+ userTheme = /* @__PURE__ */ new Map();
3989
+ getUserTheme() {
3990
+ return this.userTheme.get(this.lastThemeUpdate) ?? null;
3991
+ }
3992
+ setUserTheme(theme) {
3993
+ this.userTheme.set(this.lastThemeUpdate, theme);
3994
+ }
3995
+ getLastThemeUpdate() {
3996
+ return this.lastThemeUpdate;
3997
+ }
3998
+ setLastThemeUpdate(timestamp) {
3999
+ this.lastThemeUpdate = timestamp;
4000
+ }
4001
+ setFileNameToGeneratedCssNameMap(fileName, generatedCssName) {
4002
+ this.fileNameToGeneratedCssNameMap.set(fileName, generatedCssName);
4003
+ }
4004
+ getGeneratedCssName(fileName) {
4005
+ return this.fileNameToGeneratedCssNameMap.get(fileName);
4006
+ }
4007
+ };
4008
+ const store = new Store();
3985
4009
  const __dirname$1 = dirname(fileURLToPath(import.meta.url));
3986
4010
  const getUserTheme = async () => {
4011
+ if (store.getUserTheme()) return store.getUserTheme();
3987
4012
  try {
3988
4013
  let userThemeFilePath = path$1.resolve(process.cwd(), "flair.theme.ts");
3989
4014
  if (!existsSync$1(userThemeFilePath)) userThemeFilePath = path$1.resolve(process.cwd(), "flair.theme.js");
@@ -3999,10 +4024,17 @@ const getUserTheme = async () => {
3999
4024
  });
4000
4025
  const cacheBuster = Date.now();
4001
4026
  const userTheme = await import(`${pathToFileURL(outFile).href}?update=${cacheBuster}`);
4002
- if (userTheme.default) return {
4003
- theme: userTheme.default,
4004
- originalPath: userThemeFilePath
4005
- };
4027
+ if (userTheme.default) {
4028
+ store.setUserTheme({
4029
+ theme: userTheme.default,
4030
+ originalPath: userThemeFilePath
4031
+ });
4032
+ return {
4033
+ theme: userTheme.default,
4034
+ originalPath: userThemeFilePath
4035
+ };
4036
+ }
4037
+ store.setUserTheme(null);
4006
4038
  return null;
4007
4039
  } catch (error) {
4008
4040
  console.error("Error loading user theme:", error);
@@ -4010,53 +4042,60 @@ const getUserTheme = async () => {
4010
4042
  }
4011
4043
  };
4012
4044
  const require$1 = module$1.createRequire(import.meta.url);
4013
- /**
4014
- * Initialize the shared plugin context
4015
- */
4016
- async function initializeSharedContext(options = {}) {
4017
- const { buildThemeFile } = options;
4018
- const fileNameToGeneratedCssNameMap = /* @__PURE__ */ new Map();
4045
+ const getGeneratedCssDir = () => {
4019
4046
  const flairThemeFile = require$1.resolve("@flairjs/client/theme.css");
4020
- const flairGeneratedCssDir = path.resolve(flairThemeFile, "../generated-css");
4021
- if (!existsSync(flairGeneratedCssDir)) await mkdir(flairGeneratedCssDir);
4022
- else {
4023
- await rm(flairGeneratedCssDir, {
4024
- recursive: true,
4025
- force: true
4026
- });
4027
- await mkdir(flairGeneratedCssDir);
4047
+ return path.resolve(flairThemeFile, "../generated-css");
4048
+ };
4049
+ const setupGeneratedCssDir = async () => {
4050
+ const flairGeneratedCssDir = getGeneratedCssDir();
4051
+ try {
4052
+ if (!existsSync(flairGeneratedCssDir)) await mkdir(flairGeneratedCssDir);
4053
+ else {
4054
+ await rm(flairGeneratedCssDir, {
4055
+ recursive: true,
4056
+ force: true
4057
+ });
4058
+ await mkdir(flairGeneratedCssDir);
4059
+ }
4060
+ } catch (err) {
4061
+ if (err?.code === "EEXIST") return flairGeneratedCssDir;
4062
+ else if (existsSync(flairGeneratedCssDir)) return flairGeneratedCssDir;
4063
+ console.error(`[flairjs] Could not create generated CSS directory: ${flairGeneratedCssDir}`, err);
4064
+ return null;
4028
4065
  }
4066
+ return flairGeneratedCssDir;
4067
+ };
4068
+ const setupUserThemeFile = async ({ buildThemeFile }) => {
4069
+ const flairThemeFile = require$1.resolve("@flairjs/client/theme.css");
4029
4070
  let userTheme = await getUserTheme();
4030
4071
  const buildThemeCSS = buildThemeFile ?? buildThemeTokens;
4031
4072
  if (userTheme) {
4032
4073
  const themeCSS = buildThemeCSS(userTheme.theme);
4074
+ store.setLastThemeUpdate(Date.now());
4033
4075
  await writeFile(flairThemeFile, themeCSS, "utf-8");
4034
4076
  watch(userTheme.originalPath, async () => {
4035
4077
  userTheme = await getUserTheme();
4078
+ store.setLastThemeUpdate(Date.now());
4036
4079
  if (!userTheme) return;
4037
4080
  const themeCSS$1 = buildThemeCSS(userTheme.theme);
4038
4081
  await writeFile(flairThemeFile, themeCSS$1, "utf-8");
4039
4082
  });
4040
4083
  }
4041
- const refreshCssFile = (filePath) => {
4042
- if (fileNameToGeneratedCssNameMap.has(filePath)) {
4043
- const previousGeneratedCssName = fileNameToGeneratedCssNameMap.get(filePath);
4044
- setTimeout(() => {
4045
- rm(path.join(flairGeneratedCssDir, previousGeneratedCssName));
4046
- }, 2e3);
4047
- }
4048
- };
4049
- return {
4050
- flairThemeFile,
4051
- flairGeneratedCssDir,
4052
- userTheme,
4053
- buildThemeCSS,
4054
- refreshCssFile
4055
- };
4056
- }
4084
+ return userTheme;
4085
+ };
4086
+ const removeOutdatedCssFiles = async (sourceFilePath, cssFilePath, { flairGeneratedCssDir }) => {
4087
+ const previousGeneratedCssName = store.getGeneratedCssName(sourceFilePath);
4088
+ if (previousGeneratedCssName && previousGeneratedCssName !== cssFilePath) setTimeout(() => {
4089
+ rm(path.join(flairGeneratedCssDir, previousGeneratedCssName), { force: true });
4090
+ }, 2e3);
4091
+ else store.setFileNameToGeneratedCssNameMap(sourceFilePath, cssFilePath);
4092
+ };
4057
4093
  function shouldProcessFile(id, include, exclude) {
4058
- const isIncluded = (0, import_picomatch.default)(include || ["**/*.{js,ts,jsx,tsx}"]);
4059
- const isExcluded = (0, import_picomatch.default)(exclude || ["node_modules/**"]);
4094
+ const normalizePatterns = (patterns, defaults) => {
4095
+ return (patterns ? Array.isArray(patterns) ? patterns : [patterns] : defaults).map((pattern) => pattern.replace(/\\/g, "/"));
4096
+ };
4097
+ const isIncluded = (0, import_picomatch.default)(normalizePatterns(include, ["**/*.{js,ts,jsx,tsx}"]));
4098
+ const isExcluded = (0, import_picomatch.default)(normalizePatterns(exclude, ["node_modules/**"]));
4060
4099
  if (!isIncluded(id)) return false;
4061
4100
  if (isExcluded(id)) return false;
4062
4101
  return true;
@@ -4102,24 +4141,44 @@ const transformCode = (code, filePath, options) => {
4102
4141
 
4103
4142
  //#endregion
4104
4143
  //#region src/index.ts
4144
+ var initialized = false;
4105
4145
  function flairJsLoader(source, sourceMap) {
4106
4146
  return __awaiter(this, void 0, void 0, function() {
4107
- var callback, options, context$1, fileName, result;
4108
- var _a$1, _b;
4109
- return __generator(this, function(_c) {
4110
- switch (_c.label) {
4147
+ var callback, options, cssGeneratedDir, userTheme, fileName, result;
4148
+ var _a$1;
4149
+ return __generator(this, function(_b) {
4150
+ switch (_b.label) {
4111
4151
  case 0:
4112
4152
  callback = this.async();
4153
+ options = this.getOptions() || {};
4113
4154
  if (!callback) {
4114
4155
  console.error("@flairjs/webpack-loader requires async support");
4115
4156
  return [2];
4116
4157
  }
4117
- options = this.getOptions() || {};
4118
- return [4, initializeSharedContext(options)];
4158
+ cssGeneratedDir = null;
4159
+ userTheme = null;
4160
+ if (!!initialized) return [3, 3];
4161
+ return [4, setupGeneratedCssDir()];
4119
4162
  case 1:
4120
- context$1 = _c.sent();
4163
+ cssGeneratedDir = _b.sent();
4164
+ return [4, setupUserThemeFile({ buildThemeFile: options.buildThemeFile })];
4165
+ case 2:
4166
+ userTheme = _b.sent();
4167
+ initialized = true;
4168
+ return [3, 5];
4169
+ case 3:
4170
+ cssGeneratedDir = getGeneratedCssDir();
4171
+ return [4, getUserTheme()];
4172
+ case 4:
4173
+ userTheme = _b.sent();
4174
+ _b.label = 5;
4175
+ case 5:
4121
4176
  fileName = this.resourcePath;
4122
4177
  if (!shouldProcessFile(fileName, options === null || options === void 0 ? void 0 : options.include, options === null || options === void 0 ? void 0 : options.exclude)) return [2, callback(null, source, sourceMap)];
4178
+ if (!cssGeneratedDir) {
4179
+ console.error("[flairjs] Could not find generated CSS directory. Skipping processing.");
4180
+ return [2, callback(null, source, sourceMap)];
4181
+ }
4123
4182
  try {
4124
4183
  result = transformCode(source, fileName, {
4125
4184
  appendTimestampToCssFile: true,
@@ -4127,13 +4186,13 @@ function flairJsLoader(source, sourceMap) {
4127
4186
  cssPreprocessor: (options === null || options === void 0 ? void 0 : options.cssPreprocessor) ? function(css) {
4128
4187
  return options.cssPreprocessor(css, fileName);
4129
4188
  } : void 0,
4130
- theme: (_a$1 = context$1.userTheme) === null || _a$1 === void 0 ? void 0 : _a$1.theme,
4131
- useTheme: !!context$1.userTheme,
4132
- cssOutDir: context$1.flairGeneratedCssDir
4189
+ theme: userTheme === null || userTheme === void 0 ? void 0 : userTheme.theme,
4190
+ useTheme: !!userTheme,
4191
+ cssOutDir: cssGeneratedDir
4133
4192
  });
4134
4193
  if (!result) return [2, callback(null, source, sourceMap)];
4135
- if (result.generatedCssName) context$1.refreshCssFile(result.generatedCssName);
4136
- callback(null, result.code, result.sourcemap ? JSON.parse((_b = result.sourcemap) !== null && _b !== void 0 ? _b : "{}") : sourceMap);
4194
+ if (result.generatedCssName) removeOutdatedCssFiles(fileName, result.generatedCssName, { flairGeneratedCssDir: cssGeneratedDir });
4195
+ callback(null, result.code, result.sourcemap ? JSON.parse((_a$1 = result.sourcemap) !== null && _a$1 !== void 0 ? _a$1 : "{}") : sourceMap);
4137
4196
  } catch (error) {
4138
4197
  console.error("[@flairjs/webpack-loader]", error);
4139
4198
  callback(error, source, sourceMap);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flairjs/webpack-loader",
3
- "version": "0.0.1-beta.2",
3
+ "version": "0.0.1-beta.3",
4
4
  "main": "./dist/cjs/index.js",
5
5
  "module": "./dist/esm/index.js",
6
6
  "types": "./dist/types/index.d.ts",
@@ -22,7 +22,7 @@
22
22
  "rolldown": "1.0.0-beta.37",
23
23
  "typescript": "^5.8.2",
24
24
  "webpack": "^5.101.0",
25
- "@flairjs/bundler-shared": "0.0.1-beta.5",
25
+ "@flairjs/bundler-shared": "0.0.1-beta.6",
26
26
  "@flairjs/core": "0.0.1-beta.4"
27
27
  },
28
28
  "dependencies": {