@bamboocss/vite 1.48.3 → 1.48.4

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/index.cjs CHANGED
@@ -200,6 +200,8 @@ const createCompilationHost = (options = {}) => {
200
200
  };
201
201
  //#endregion
202
202
  //#region src/static-session.ts
203
+ /** Store one semantic class token in the selector spelling used by reachability sets. */
204
+ const selectorClassName = (token) => token.includes("\\") ? token : (0, _bamboocss_shared.esc)(token);
203
205
  const createStaticCompilationSession = () => {
204
206
  const session = {
205
207
  utilityLayer: "utilities",
@@ -227,7 +229,7 @@ const createStaticCompilationSession = () => {
227
229
  markClassUsed(className) {
228
230
  for (const token of className.split(" ")) {
229
231
  if (!token) continue;
230
- session.usedClasses.add(token.includes("\\") ? token : (0, _bamboocss_shared.esc)(token));
232
+ session.usedClasses.add(selectorClassName(token));
231
233
  }
232
234
  }
233
235
  };
@@ -932,6 +934,11 @@ const bamboocss = (options = {}) => {
932
934
  return /* @__PURE__ */ new Error(`bamboocss: cached transform metadata for ${JSON.stringify(id)} in the ${JSON.stringify(environment)} environment ${problem}.\n\nBamboo cannot safely rebuild from this entry because cached JavaScript may still name CSS classes whose rules would be dropped. Restart Vite to invalidate its in-memory transform cache. If this persists, clear Vite's cache directory and rebuild.`);
933
935
  };
934
936
  const transformStateByEnvironment = /* @__PURE__ */ new Map();
937
+ /** States currently materialized in the shared CSS session's reachability projection. */
938
+ const projectedTransformStates = /* @__PURE__ */ new Set();
939
+ const projectedUsedClassCounts = /* @__PURE__ */ new Map();
940
+ const projectedTransformedFileCounts = /* @__PURE__ */ new Map();
941
+ let projectedCssLoadedCount = 0;
935
942
  /**
936
943
  * One fold per file content per change event, shared across environments and hooks.
937
944
  *
@@ -997,6 +1004,8 @@ const bamboocss = (options = {}) => {
997
1004
  const environmentName = (context) => environmentOf(context)?.name ?? "default";
998
1005
  const newEnvironmentState = () => ({
999
1006
  transformArtifactsByModule: /* @__PURE__ */ new Map(),
1007
+ usedClassCounts: /* @__PURE__ */ new Map(),
1008
+ transformedFileCounts: /* @__PURE__ */ new Map(),
1000
1009
  dependentsByDependency: /* @__PURE__ */ new Map(),
1001
1010
  dependenciesByModule: /* @__PURE__ */ new Map(),
1002
1011
  filesByModule: /* @__PURE__ */ new Map(),
@@ -1011,6 +1020,8 @@ const bamboocss = (options = {}) => {
1011
1020
  });
1012
1021
  const cloneEnvironmentState = (state) => ({
1013
1022
  transformArtifactsByModule: new Map(state.transformArtifactsByModule),
1023
+ usedClassCounts: new Map(state.usedClassCounts),
1024
+ transformedFileCounts: new Map(state.transformedFileCounts),
1014
1025
  dependentsByDependency: new Map([...state.dependentsByDependency].map(([dependency, dependents]) => [dependency, new Set(dependents)])),
1015
1026
  dependenciesByModule: new Map([...state.dependenciesByModule].map(([moduleId, dependencies]) => [moduleId, new Set(dependencies)])),
1016
1027
  filesByModule: new Map(state.filesByModule),
@@ -1137,10 +1148,43 @@ const bamboocss = (options = {}) => {
1137
1148
  if (!assets.length) return void 0;
1138
1149
  return digest(JSON.stringify(assets.sort()));
1139
1150
  };
1140
- /** Add one detached transform contribution to the global reachability projection. */
1141
- const applyStaticTransformContribution = (artifact) => {
1142
- if (artifact.transformedFile) staticSession.transformedFiles.add((0, node_path.resolve)(artifact.file));
1143
- for (const className of artifact.classNames) staticSession.markClassUsed(className);
1151
+ const adjustContributionCount = (counts, value, delta) => {
1152
+ const next = (counts.get(value) ?? 0) + delta;
1153
+ if (next < 0) throw new Error(`bamboocss: internal contribution count underflow for ${JSON.stringify(value)}`);
1154
+ if (next > 0) counts.set(value, next);
1155
+ else counts.delete(value);
1156
+ return next;
1157
+ };
1158
+ /** Update the projection index for one module contribution without scanning its siblings. */
1159
+ const adjustTransformContribution = (state, artifact, delta) => {
1160
+ if (artifact.transformedFile) adjustContributionCount(state.transformedFileCounts, (0, node_path.resolve)(artifact.file), delta);
1161
+ for (const classNames of artifact.classNames) for (const token of classNames.split(" ")) if (token) adjustContributionCount(state.usedClassCounts, selectorClassName(token), delta);
1162
+ };
1163
+ const replaceTransformArtifact = (state, artifact) => {
1164
+ const previous = state.transformArtifactsByModule.get(artifact.moduleId);
1165
+ if (previous) adjustTransformContribution(state, previous, -1);
1166
+ state.transformArtifactsByModule.set(artifact.moduleId, artifact);
1167
+ adjustTransformContribution(state, artifact, 1);
1168
+ };
1169
+ const deleteTransformArtifact = (state, moduleId) => {
1170
+ const previous = state.transformArtifactsByModule.get(moduleId);
1171
+ if (!previous) return false;
1172
+ adjustTransformContribution(state, previous, -1);
1173
+ return state.transformArtifactsByModule.delete(moduleId);
1174
+ };
1175
+ const adjustProjectedTransformState = (state, delta) => {
1176
+ for (const className of state.usedClassCounts.keys()) {
1177
+ const next = adjustContributionCount(projectedUsedClassCounts, className, delta);
1178
+ if (next === 1 && delta === 1) staticSession.usedClasses.add(className);
1179
+ else if (next === 0) staticSession.usedClasses.delete(className);
1180
+ }
1181
+ for (const file of state.transformedFileCounts.keys()) {
1182
+ const next = adjustContributionCount(projectedTransformedFileCounts, file, delta);
1183
+ if (next === 1 && delta === 1) staticSession.transformedFiles.add(file);
1184
+ else if (next === 0) staticSession.transformedFiles.delete(file);
1185
+ }
1186
+ if (state.cssLoaded) projectedCssLoadedCount += delta;
1187
+ if (projectedCssLoadedCount < 0) throw new Error("bamboocss: internal stylesheet contribution count underflow");
1144
1188
  };
1145
1189
  /**
1146
1190
  * Re-derive the two global sets CSS pruning consumes from environment-owned artifacts.
@@ -1167,13 +1211,12 @@ const bamboocss = (options = {}) => {
1167
1211
  return states;
1168
1212
  };
1169
1213
  const rebuildStaticTransformContributions = (candidateEnvironment, candidateState) => {
1170
- staticSession.transformedFiles.clear();
1171
- staticSession.usedClasses.clear();
1172
- staticSession.cssLoaded = false;
1173
- for (const state of contributionStates(candidateEnvironment, candidateState)) {
1174
- if (state.cssLoaded) staticSession.cssLoaded = true;
1175
- for (const artifact of state.transformArtifactsByModule.values()) applyStaticTransformContribution(artifact);
1176
- }
1214
+ const nextStates = new Set(contributionStates(candidateEnvironment, candidateState));
1215
+ for (const state of projectedTransformStates) if (!nextStates.has(state)) adjustProjectedTransformState(state, -1);
1216
+ for (const state of nextStates) if (!projectedTransformStates.has(state)) adjustProjectedTransformState(state, 1);
1217
+ projectedTransformStates.clear();
1218
+ for (const state of nextStates) projectedTransformStates.add(state);
1219
+ staticSession.cssLoaded = projectedCssLoadedCount > 0;
1177
1220
  };
1178
1221
  /**
1179
1222
  * Snapshot which reported classes Bamboo actually extracted for this JavaScript generation.
@@ -1185,9 +1228,8 @@ const bamboocss = (options = {}) => {
1185
1228
  const ownedClassesForState = (state) => {
1186
1229
  const extracted = new Map([...staticSession.prunableClasses].map((className) => [require_class_name.bare(className), className]));
1187
1230
  const owned = /* @__PURE__ */ new Set();
1188
- for (const artifact of state.transformArtifactsByModule.values()) for (const reported of artifact.classNames) for (const token of reported.split(" ")) {
1189
- if (!token) continue;
1190
- const extractedClass = extracted.get(require_class_name.bare(token));
1231
+ for (const className of state.usedClassCounts.keys()) {
1232
+ const extractedClass = extracted.get(require_class_name.bare(className));
1191
1233
  if (extractedClass !== void 0) owned.add(extractedClass);
1192
1234
  }
1193
1235
  return owned;
@@ -1421,7 +1463,7 @@ const bamboocss = (options = {}) => {
1421
1463
  /** Apply every per-build fact established by one trusted or validated transform artifact. */
1422
1464
  const commitTransformArtifact = (state, artifact) => {
1423
1465
  const { file, moduleId } = artifact;
1424
- state.transformArtifactsByModule.set(moduleId, artifact);
1466
+ replaceTransformArtifact(state, artifact);
1425
1467
  recordFoldDependencies(state, moduleId, file, artifact.dependencies);
1426
1468
  if (artifact.signature) state.foldSignatures.set(moduleId, artifact.signature);
1427
1469
  else {
@@ -2019,7 +2061,7 @@ const bamboocss = (options = {}) => {
2019
2061
  recordFoldDependencies(state, moduleId, moduleFile, []);
2020
2062
  state.foldSignatures.delete(moduleId);
2021
2063
  state.foldInputsByModule.delete(moduleId);
2022
- state.transformArtifactsByModule.delete(moduleId);
2064
+ deleteTransformArtifact(state, moduleId);
2023
2065
  state.filesByModule.delete(moduleId);
2024
2066
  }
2025
2067
  return;
@@ -2246,7 +2288,7 @@ const bamboocss = (options = {}) => {
2246
2288
  });
2247
2289
  if (!compiled) return null;
2248
2290
  if ("unparsed" in compiled) {
2249
- state.transformArtifactsByModule.delete(id);
2291
+ deleteTransformArtifact(state, id);
2250
2292
  recordFoldDependencies(state, id, filePath, []);
2251
2293
  state.foldSignatures.delete(id);
2252
2294
  state.foldInputsByModule.delete(id);
package/dist/index.mjs CHANGED
@@ -195,6 +195,8 @@ const createCompilationHost = (options = {}) => {
195
195
  };
196
196
  //#endregion
197
197
  //#region src/static-session.ts
198
+ /** Store one semantic class token in the selector spelling used by reachability sets. */
199
+ const selectorClassName = (token) => token.includes("\\") ? token : esc(token);
198
200
  const createStaticCompilationSession = () => {
199
201
  const session = {
200
202
  utilityLayer: "utilities",
@@ -222,7 +224,7 @@ const createStaticCompilationSession = () => {
222
224
  markClassUsed(className) {
223
225
  for (const token of className.split(" ")) {
224
226
  if (!token) continue;
225
- session.usedClasses.add(token.includes("\\") ? token : esc(token));
227
+ session.usedClasses.add(selectorClassName(token));
226
228
  }
227
229
  }
228
230
  };
@@ -927,6 +929,11 @@ const bamboocss = (options = {}) => {
927
929
  return /* @__PURE__ */ new Error(`bamboocss: cached transform metadata for ${JSON.stringify(id)} in the ${JSON.stringify(environment)} environment ${problem}.\n\nBamboo cannot safely rebuild from this entry because cached JavaScript may still name CSS classes whose rules would be dropped. Restart Vite to invalidate its in-memory transform cache. If this persists, clear Vite's cache directory and rebuild.`);
928
930
  };
929
931
  const transformStateByEnvironment = /* @__PURE__ */ new Map();
932
+ /** States currently materialized in the shared CSS session's reachability projection. */
933
+ const projectedTransformStates = /* @__PURE__ */ new Set();
934
+ const projectedUsedClassCounts = /* @__PURE__ */ new Map();
935
+ const projectedTransformedFileCounts = /* @__PURE__ */ new Map();
936
+ let projectedCssLoadedCount = 0;
930
937
  /**
931
938
  * One fold per file content per change event, shared across environments and hooks.
932
939
  *
@@ -992,6 +999,8 @@ const bamboocss = (options = {}) => {
992
999
  const environmentName = (context) => environmentOf(context)?.name ?? "default";
993
1000
  const newEnvironmentState = () => ({
994
1001
  transformArtifactsByModule: /* @__PURE__ */ new Map(),
1002
+ usedClassCounts: /* @__PURE__ */ new Map(),
1003
+ transformedFileCounts: /* @__PURE__ */ new Map(),
995
1004
  dependentsByDependency: /* @__PURE__ */ new Map(),
996
1005
  dependenciesByModule: /* @__PURE__ */ new Map(),
997
1006
  filesByModule: /* @__PURE__ */ new Map(),
@@ -1006,6 +1015,8 @@ const bamboocss = (options = {}) => {
1006
1015
  });
1007
1016
  const cloneEnvironmentState = (state) => ({
1008
1017
  transformArtifactsByModule: new Map(state.transformArtifactsByModule),
1018
+ usedClassCounts: new Map(state.usedClassCounts),
1019
+ transformedFileCounts: new Map(state.transformedFileCounts),
1009
1020
  dependentsByDependency: new Map([...state.dependentsByDependency].map(([dependency, dependents]) => [dependency, new Set(dependents)])),
1010
1021
  dependenciesByModule: new Map([...state.dependenciesByModule].map(([moduleId, dependencies]) => [moduleId, new Set(dependencies)])),
1011
1022
  filesByModule: new Map(state.filesByModule),
@@ -1132,10 +1143,43 @@ const bamboocss = (options = {}) => {
1132
1143
  if (!assets.length) return void 0;
1133
1144
  return digest(JSON.stringify(assets.sort()));
1134
1145
  };
1135
- /** Add one detached transform contribution to the global reachability projection. */
1136
- const applyStaticTransformContribution = (artifact) => {
1137
- if (artifact.transformedFile) staticSession.transformedFiles.add(resolve(artifact.file));
1138
- for (const className of artifact.classNames) staticSession.markClassUsed(className);
1146
+ const adjustContributionCount = (counts, value, delta) => {
1147
+ const next = (counts.get(value) ?? 0) + delta;
1148
+ if (next < 0) throw new Error(`bamboocss: internal contribution count underflow for ${JSON.stringify(value)}`);
1149
+ if (next > 0) counts.set(value, next);
1150
+ else counts.delete(value);
1151
+ return next;
1152
+ };
1153
+ /** Update the projection index for one module contribution without scanning its siblings. */
1154
+ const adjustTransformContribution = (state, artifact, delta) => {
1155
+ if (artifact.transformedFile) adjustContributionCount(state.transformedFileCounts, resolve(artifact.file), delta);
1156
+ for (const classNames of artifact.classNames) for (const token of classNames.split(" ")) if (token) adjustContributionCount(state.usedClassCounts, selectorClassName(token), delta);
1157
+ };
1158
+ const replaceTransformArtifact = (state, artifact) => {
1159
+ const previous = state.transformArtifactsByModule.get(artifact.moduleId);
1160
+ if (previous) adjustTransformContribution(state, previous, -1);
1161
+ state.transformArtifactsByModule.set(artifact.moduleId, artifact);
1162
+ adjustTransformContribution(state, artifact, 1);
1163
+ };
1164
+ const deleteTransformArtifact = (state, moduleId) => {
1165
+ const previous = state.transformArtifactsByModule.get(moduleId);
1166
+ if (!previous) return false;
1167
+ adjustTransformContribution(state, previous, -1);
1168
+ return state.transformArtifactsByModule.delete(moduleId);
1169
+ };
1170
+ const adjustProjectedTransformState = (state, delta) => {
1171
+ for (const className of state.usedClassCounts.keys()) {
1172
+ const next = adjustContributionCount(projectedUsedClassCounts, className, delta);
1173
+ if (next === 1 && delta === 1) staticSession.usedClasses.add(className);
1174
+ else if (next === 0) staticSession.usedClasses.delete(className);
1175
+ }
1176
+ for (const file of state.transformedFileCounts.keys()) {
1177
+ const next = adjustContributionCount(projectedTransformedFileCounts, file, delta);
1178
+ if (next === 1 && delta === 1) staticSession.transformedFiles.add(file);
1179
+ else if (next === 0) staticSession.transformedFiles.delete(file);
1180
+ }
1181
+ if (state.cssLoaded) projectedCssLoadedCount += delta;
1182
+ if (projectedCssLoadedCount < 0) throw new Error("bamboocss: internal stylesheet contribution count underflow");
1139
1183
  };
1140
1184
  /**
1141
1185
  * Re-derive the two global sets CSS pruning consumes from environment-owned artifacts.
@@ -1162,13 +1206,12 @@ const bamboocss = (options = {}) => {
1162
1206
  return states;
1163
1207
  };
1164
1208
  const rebuildStaticTransformContributions = (candidateEnvironment, candidateState) => {
1165
- staticSession.transformedFiles.clear();
1166
- staticSession.usedClasses.clear();
1167
- staticSession.cssLoaded = false;
1168
- for (const state of contributionStates(candidateEnvironment, candidateState)) {
1169
- if (state.cssLoaded) staticSession.cssLoaded = true;
1170
- for (const artifact of state.transformArtifactsByModule.values()) applyStaticTransformContribution(artifact);
1171
- }
1209
+ const nextStates = new Set(contributionStates(candidateEnvironment, candidateState));
1210
+ for (const state of projectedTransformStates) if (!nextStates.has(state)) adjustProjectedTransformState(state, -1);
1211
+ for (const state of nextStates) if (!projectedTransformStates.has(state)) adjustProjectedTransformState(state, 1);
1212
+ projectedTransformStates.clear();
1213
+ for (const state of nextStates) projectedTransformStates.add(state);
1214
+ staticSession.cssLoaded = projectedCssLoadedCount > 0;
1172
1215
  };
1173
1216
  /**
1174
1217
  * Snapshot which reported classes Bamboo actually extracted for this JavaScript generation.
@@ -1180,9 +1223,8 @@ const bamboocss = (options = {}) => {
1180
1223
  const ownedClassesForState = (state) => {
1181
1224
  const extracted = new Map([...staticSession.prunableClasses].map((className) => [bare(className), className]));
1182
1225
  const owned = /* @__PURE__ */ new Set();
1183
- for (const artifact of state.transformArtifactsByModule.values()) for (const reported of artifact.classNames) for (const token of reported.split(" ")) {
1184
- if (!token) continue;
1185
- const extractedClass = extracted.get(bare(token));
1226
+ for (const className of state.usedClassCounts.keys()) {
1227
+ const extractedClass = extracted.get(bare(className));
1186
1228
  if (extractedClass !== void 0) owned.add(extractedClass);
1187
1229
  }
1188
1230
  return owned;
@@ -1416,7 +1458,7 @@ const bamboocss = (options = {}) => {
1416
1458
  /** Apply every per-build fact established by one trusted or validated transform artifact. */
1417
1459
  const commitTransformArtifact = (state, artifact) => {
1418
1460
  const { file, moduleId } = artifact;
1419
- state.transformArtifactsByModule.set(moduleId, artifact);
1461
+ replaceTransformArtifact(state, artifact);
1420
1462
  recordFoldDependencies(state, moduleId, file, artifact.dependencies);
1421
1463
  if (artifact.signature) state.foldSignatures.set(moduleId, artifact.signature);
1422
1464
  else {
@@ -2014,7 +2056,7 @@ const bamboocss = (options = {}) => {
2014
2056
  recordFoldDependencies(state, moduleId, moduleFile, []);
2015
2057
  state.foldSignatures.delete(moduleId);
2016
2058
  state.foldInputsByModule.delete(moduleId);
2017
- state.transformArtifactsByModule.delete(moduleId);
2059
+ deleteTransformArtifact(state, moduleId);
2018
2060
  state.filesByModule.delete(moduleId);
2019
2061
  }
2020
2062
  return;
@@ -2241,7 +2283,7 @@ const bamboocss = (options = {}) => {
2241
2283
  });
2242
2284
  if (!compiled) return null;
2243
2285
  if ("unparsed" in compiled) {
2244
- state.transformArtifactsByModule.delete(id);
2286
+ deleteTransformArtifact(state, id);
2245
2287
  recordFoldDependencies(state, id, filePath, []);
2246
2288
  state.foldSignatures.delete(id);
2247
2289
  state.foldInputsByModule.delete(id);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bamboocss/vite",
3
- "version": "1.48.3",
3
+ "version": "1.48.4",
4
4
  "description": "Vite integration for Bamboo CSS",
5
5
  "homepage": "https://bamboocss.com",
6
6
  "license": "MIT",
@@ -42,18 +42,18 @@
42
42
  "postcss": "8.5.26",
43
43
  "postcss-selector-parser": "7.1.5",
44
44
  "ts-morph": "28.0.0",
45
- "@bamboocss/config": "1.48.3",
46
- "@bamboocss/extractor": "1.48.3",
47
- "@bamboocss/shared": "1.48.3",
48
- "@bamboocss/node": "1.48.3",
49
- "@bamboocss/core": "1.48.3",
50
- "@bamboocss/logger": "1.48.3",
51
- "@bamboocss/types": "1.48.3"
45
+ "@bamboocss/config": "1.48.4",
46
+ "@bamboocss/core": "1.48.4",
47
+ "@bamboocss/node": "1.48.4",
48
+ "@bamboocss/extractor": "1.48.4",
49
+ "@bamboocss/logger": "1.48.4",
50
+ "@bamboocss/types": "1.48.4",
51
+ "@bamboocss/shared": "1.48.4"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@jridgewell/trace-mapping": "^0.3.31",
55
55
  "vite": "7.2.6",
56
- "@bamboocss/fixture": "1.48.3"
56
+ "@bamboocss/fixture": "1.48.4"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "vite": ">=5"