@10stars/config 17.0.8 → 17.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@10stars/config",
3
- "version": "17.0.8",
3
+ "version": "17.0.9",
4
4
  "private": false,
5
5
  "bin": {
6
6
  "config": "./src/index.ts"
package/src/index.ts CHANGED
@@ -8,8 +8,7 @@ import { dedupeRemote, linkRemote } from "./linking/link-remote"
8
8
  import { setupOverrides } from "./manage-overrides"
9
9
  import { resetColorIndex } from "./run/colors"
10
10
  import { runConcurrently, type CommandConfig } from "./run/runner"
11
- import { setupSideEffects } from "./vanilla-extract/manage-side-effects"
12
- import { patchVanillaExtract } from "./vanilla-extract/patch-vanilla-extract"
11
+ import { isVanillaExtractInstalled, setupSideEffects } from "./vanilla-extract/manage-side-effects"
13
12
  import { setupVSCode } from "./vscode-config"
14
13
 
15
14
  const cwd = process.env.PWD!
@@ -45,8 +44,6 @@ const actions = {
45
44
  prepare: {
46
45
  info: `Runs husky and links packages`,
47
46
  action: async () => {
48
- const veInstalled = await patchVanillaExtract(cwd) // patch VE before the CI guard: builds (incl. CI) need the `css.ts`-only filter in node_modules
49
-
50
47
  await linkSelf(cwd) // before the CI guard: CI app builds also self-import `<pkg>/src/…`
51
48
 
52
49
  if (process.env.CI) return
@@ -59,7 +56,7 @@ const actions = {
59
56
  exec(`husky`) // husky is intended only for local development (not in CI)
60
57
  await setupVSCode(cwd) // create/update .vscode directory with standardized extensions.json and settings.json
61
58
  await setupOverrides(cwd) // sync standardized package.json overrides
62
- await setupSideEffects(cwd, veInstalled) // CSS-protect VE repos; `sideEffects: false` for non-VE libs
59
+ await setupSideEffects(cwd, isVanillaExtractInstalled(cwd)) // CSS-protect VE repos; `sideEffects: false` for non-VE libs
63
60
 
64
61
  const config = await getConfig()
65
62
  if (config?.linkPackages) {
@@ -5,7 +5,6 @@ import { promisify } from "node:util"
5
5
 
6
6
  import type * as TF from "type-fest"
7
7
 
8
- import { patchVanillaExtract } from "../vanilla-extract/patch-vanilla-extract"
9
8
  import { dedupeSingletons, linkSelf } from "./link-packages"
10
9
 
11
10
  interface Config {
@@ -64,23 +63,15 @@ const tryGit = (args: string[], cwd?: string): string | null => {
64
63
  }
65
64
  }
66
65
 
67
- // --ignore-scripts: a sibling is only a dependency here, so skip the bulk of its postinstall
68
- // (`config prepare` husky/vscode/etc.); the cross-repo `@types/*` dedupe runs once via the
69
- // consumer's `dedupe` afterwards. We DO re-run the two install-time steps a sibling's own tree
70
- // needs when it's consumed as a `file:` dep:
71
- // - linkSelf: restore its self-symlink so `<self>/src/…` self-imports resolve at realpath in the
72
- // flat-peer layout. (Workspace-root siblings, e.g. backend-api, get subpackage self-links from
73
- // bun's own workspace linking, so linkSelf no-ops on them.)
74
- // - patchVanillaExtract: rewrite the VE `cssFileFilter` in the sibling's OWN node_modules. The
75
- // consumer's build resolves `@vanilla-extract/vite-plugin`/`integration` from a workspace
76
- // sibling's hoisted node_modules (e.g. `@bundling/frontend-dev-mode` → ../bundling/node_modules),
77
- // and the consumer's own patch skips symlinked siblings — so without this the build loads an
78
- // unpatched filter, our `css.ts` modules go untransformed, and prerender throws "Styles were
79
- // unable to be assigned to a file". No-op for siblings without VE.
66
+ // --ignore-scripts: a sibling is only a dependency here, so skip its postinstall (`config prepare`)
67
+ // — nothing builds it (typecheck doesn't run VE) and the cross-repo `@types/*` dedupe runs once via
68
+ // the consumer's `dedupe` afterwards. We still restore the one thing a sibling's own src needs: its
69
+ // self-symlink, so `<self>/src/…` self-imports resolve at realpath in the flat-peer layout.
70
+ // (Workspace-root siblings, e.g. backend-api, get their subpackage self-links from bun's own
71
+ // workspace linking, so linkSelf no-ops on them.)
80
72
  const bunInstall = async (cwd: string): Promise<void> => {
81
73
  await execFileAsync(`bun`, [`install`, `--ignore-scripts`], { cwd })
82
74
  await linkSelf(cwd)
83
- await patchVanillaExtract(cwd)
84
75
  }
85
76
 
86
77
  const exists = (p: string): Promise<boolean> =>
@@ -1,15 +1,30 @@
1
1
  import { execSync } from "node:child_process"
2
2
  import fs from "node:fs/promises"
3
+ import { createRequire } from "node:module"
3
4
  import path from "node:path"
4
5
 
5
6
  import type * as TF from "type-fest"
6
7
 
8
+ /**
9
+ * Whether Vanilla Extract is installed for `cwd` — resolved from `@vanilla-extract/integration`
10
+ * (pulled in by the vite-plugin/compiler), the same signal the old on-disk patch keyed off. Gates
11
+ * `setupSideEffects` so only VE repos get their `css.ts`/`.css` imports protected from tree-shaking.
12
+ */
13
+ export const isVanillaExtractInstalled = (cwd: string): boolean => {
14
+ try {
15
+ createRequire(path.join(cwd, `package.json`)).resolve(`@vanilla-extract/integration`)
16
+ return true
17
+ } catch {
18
+ return false
19
+ }
20
+ }
21
+
7
22
  // VE `css.ts` modules and raw `.css` files inject styles purely as a side effect — a global reset,
8
23
  // theme-var override or `@font-face` is imported for that effect alone (no used exports). A
9
24
  // `sideEffects: false` package tree-shakes such a bare import away, shipping an unstyled build (and,
10
25
  // on SSR, a hydration mismatch — React #418 — since the server-rendered markup no longer matches).
11
- // Listing them keeps them alive. `css.ts` mirrors the single-filename VE convention (see
12
- // patch-vanilla-extract); `.tsx`/`.js` css variants aren't used in these repos.
26
+ // Listing them keeps them alive. `css.ts` mirrors the single-filename VE convention; `.tsx`/`.js`
27
+ // css variants aren't used in these repos.
13
28
  const CSS_SIDE_EFFECTS = [`**/css.ts`, `**/*.css`]
14
29
 
15
30
  /**
@@ -1,89 +0,0 @@
1
- import fs from "node:fs/promises"
2
- import path from "node:path"
3
-
4
- // Vanilla Extract hardcodes its file filter as a `const` regex in @vanilla-extract/integration and
5
- // imports it into both its vite-plugin and its compiler — there's no option to customize it. We
6
- // rewrite the regex on disk so ONLY `css.ts` (our single-filename convention) is treated as a VE
7
- // module; the conventional `.css.ts` suffix is intentionally no longer matched.
8
- // original: matches any `*.css.ts` (a `.` may precede `css`)
9
- // patched: matches a `css.ts` filename (only start-of-path or a separator may precede `css`)
10
- const ORIGINAL = String.raw`/\.css\.(js|cjs|mjs|jsx|ts|tsx)(\?used)?$/`
11
- const PATCHED = String.raw`/(?:^|[/\\])css\.(js|cjs|mjs|jsx|ts|tsx)(\?used)?$/`
12
-
13
- /**
14
- * Rewrite VE's `cssFileFilter` to a `css.ts`-only matcher in every installed copy.
15
- *
16
- * Runs on `prepare` (postinstall), so it re-applies after each `bun install` re-materializes
17
- * node_modules. Idempotent, and a no-op for repos without VE (e.g. backend-only). If VE is present
18
- * but the filter definition can't be found, it throws: a silent miss would stop every `css.ts` from
19
- * compiling, so a VE build change must surface at install time rather than as missing styles.
20
- *
21
- * @returns whether VE is installed here — the caller uses it to gate `css.ts` side-effect handling.
22
- */
23
- export const patchVanillaExtract = async (cwd: string): Promise<boolean> => {
24
- const nodeModules = path.join(cwd, `node_modules`)
25
-
26
- // Collect every real `@vanilla-extract/integration/dist/*.js`. VE always sits directly under a
27
- // `node_modules` dir, so we read each node_modules' own integration/dist and recurse ONLY into
28
- // *nested* node_modules — never into package source trees. (A flat hoisted tree is hundreds of
29
- // packages; recursing each one's dist/esm/cjs/… was the bulk of the old cost.) Symlinks are
30
- // skipped: a `file:` self-dep links node_modules/<pkg> -> repo root, so following links recurses
31
- // forever — also why Bun.Glob (which follows links even with `followSymlinks: false`) can't be
32
- // used. A linked sibling patches its own VE during its own install; this repo's copy is hoisted
33
- // as a real dir, so real-dir-only descent finds every copy that this install must patch.
34
- const findFiles = async (dir: string, out: string[] = []): Promise<string[]> => {
35
- const distDir = path.join(dir, `@vanilla-extract`, `integration`, `dist`)
36
- for (const entry of await fs.readdir(distDir, { withFileTypes: true }).catch(() => [])) {
37
- if (entry.isFile() && entry.name.endsWith(`.js`)) out.push(path.join(distDir, entry.name))
38
- }
39
-
40
- for (const entry of await fs.readdir(dir, { withFileTypes: true }).catch(() => [])) {
41
- if (entry.isSymbolicLink() || !entry.isDirectory()) continue
42
- const pkgDir = path.join(dir, entry.name)
43
- if (entry.name.startsWith(`@`)) {
44
- // scoped packages nest a level deeper: node_modules/@scope/<pkg>/node_modules
45
- for (const scoped of await fs.readdir(pkgDir, { withFileTypes: true }).catch(() => [])) {
46
- if (scoped.isSymbolicLink() || !scoped.isDirectory()) continue
47
- await findFiles(path.join(pkgDir, scoped.name, `node_modules`), out)
48
- }
49
- } else {
50
- await findFiles(path.join(pkgDir, `node_modules`), out)
51
- }
52
- }
53
- return out
54
- }
55
-
56
- let integrationFound = false
57
- let definitionFound = false
58
- const patched: string[] = []
59
-
60
- for (const file of await findFiles(nodeModules)) {
61
- integrationFound = true
62
- const content = await fs.readFile(file, `utf8`)
63
-
64
- if (content.includes(PATCHED)) {
65
- definitionFound = true // already patched by an earlier run
66
- continue
67
- }
68
- if (!content.includes(ORIGINAL)) continue // entry stub / file without the filter definition
69
-
70
- definitionFound = true
71
- await fs.writeFile(file, content.replaceAll(ORIGINAL, PATCHED))
72
- patched.push(path.relative(nodeModules, file))
73
- }
74
-
75
- if (!integrationFound) return false // VE not installed here
76
-
77
- if (!definitionFound) {
78
- throw new Error(
79
- `@10stars/config: found @vanilla-extract/integration but not its cssFileFilter definition — ` +
80
- `the VE build likely changed. Update ORIGINAL in src/vanilla-extract/patch-vanilla-extract.ts.`,
81
- )
82
- }
83
-
84
- if (patched.length) {
85
- console.info(`Patched @vanilla-extract file filter to css.ts (${patched.length} file(s))`)
86
- }
87
-
88
- return true
89
- }