@tamagui/static 2.0.0-rc.3 → 2.0.0-rc.30
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/checkDeps.cjs +164 -31
- package/dist/exports.cjs +3 -0
- package/dist/extractor/bundle.cjs +72 -35
- package/dist/extractor/bundleConfig.cjs +219 -35
- package/dist/extractor/createExtractor.cjs +170 -28
- package/dist/extractor/detectModuleFormat.cjs +49 -0
- package/dist/extractor/esbuildTsconfigPaths.cjs +3 -1
- package/dist/extractor/extractToClassNames.cjs +7 -5
- package/dist/extractor/extractToNative.cjs +7 -8
- package/dist/extractor/loadTamagui.cjs +1 -1
- package/dist/getPragmaOptions.cjs +7 -3
- package/dist/index.js +26 -16
- package/dist/registerRequire.cjs +23 -14
- package/package.json +26 -22
- package/src/checkDeps.ts +305 -68
- package/src/exports.ts +1 -0
- package/src/extractor/bundle.ts +140 -37
- package/src/extractor/bundleConfig.ts +435 -61
- package/src/extractor/createExtractor.ts +261 -41
- package/src/extractor/detectModuleFormat.ts +42 -0
- package/src/extractor/esbuildTsconfigPaths.ts +6 -1
- package/src/extractor/extractToClassNames.ts +15 -9
- package/src/extractor/extractToNative.ts +32 -25
- package/src/extractor/loadTamagui.ts +2 -2
- package/src/getPragmaOptions.ts +6 -1
- package/src/registerRequire.ts +40 -8
- package/types/checkDeps.d.ts.map +1 -1
- package/types/exports.d.ts +1 -0
- package/types/exports.d.ts.map +1 -1
- package/types/extractor/bundle.d.ts +83 -1
- package/types/extractor/bundle.d.ts.map +1 -1
- package/types/extractor/bundleConfig.d.ts +15 -2
- package/types/extractor/bundleConfig.d.ts.map +1 -1
- package/types/extractor/createExtractor.d.ts.map +1 -1
- package/types/extractor/detectModuleFormat.d.ts +5 -0
- package/types/extractor/detectModuleFormat.d.ts.map +1 -0
- package/types/extractor/esbuildTsconfigPaths.d.ts +8 -0
- package/types/extractor/esbuildTsconfigPaths.d.ts.map +1 -1
- package/types/extractor/extractToClassNames.d.ts.map +1 -1
- package/types/extractor/extractToNative.d.ts.map +1 -1
- package/types/getPragmaOptions.d.ts.map +1 -1
- package/types/registerRequire.d.ts.map +1 -1
- package/dist/check-dep-versions.js +0 -389
- package/dist/check-dep-versions.js.map +0 -6
- package/dist/checkDeps.js +0 -60
- package/dist/checkDeps.js.map +0 -6
- package/dist/constants.js +0 -34
- package/dist/constants.js.map +0 -6
- package/dist/exports.js +0 -34
- package/dist/exports.js.map +0 -6
- package/dist/extractor/accessSafe.js +0 -47
- package/dist/extractor/accessSafe.js.map +0 -6
- package/dist/extractor/babelParse.js +0 -59
- package/dist/extractor/babelParse.js.map +0 -6
- package/dist/extractor/buildClassName.js +0 -72
- package/dist/extractor/buildClassName.js.map +0 -6
- package/dist/extractor/bundle.js +0 -135
- package/dist/extractor/bundle.js.map +0 -6
- package/dist/extractor/bundleConfig.js +0 -352
- package/dist/extractor/bundleConfig.js.map +0 -6
- package/dist/extractor/concatClassName.js +0 -69
- package/dist/extractor/concatClassName.js.map +0 -6
- package/dist/extractor/createEvaluator.js +0 -66
- package/dist/extractor/createEvaluator.js.map +0 -6
- package/dist/extractor/createExtractor.js +0 -1215
- package/dist/extractor/createExtractor.js.map +0 -6
- package/dist/extractor/createLogger.js +0 -32
- package/dist/extractor/createLogger.js.map +0 -6
- package/dist/extractor/ensureImportingConcat.js +0 -50
- package/dist/extractor/ensureImportingConcat.js.map +0 -6
- package/dist/extractor/errors.js +0 -22
- package/dist/extractor/errors.js.map +0 -6
- package/dist/extractor/esbuildAliasPlugin.js +0 -36
- package/dist/extractor/esbuildAliasPlugin.js.map +0 -6
- package/dist/extractor/esbuildTsconfigPaths.js +0 -79
- package/dist/extractor/esbuildTsconfigPaths.js.map +0 -6
- package/dist/extractor/evaluateAstNode.js +0 -99
- package/dist/extractor/evaluateAstNode.js.map +0 -6
- package/dist/extractor/extractHelpers.js +0 -108
- package/dist/extractor/extractHelpers.js.map +0 -6
- package/dist/extractor/extractMediaStyle.js +0 -123
- package/dist/extractor/extractMediaStyle.js.map +0 -6
- package/dist/extractor/extractToClassNames.js +0 -351
- package/dist/extractor/extractToClassNames.js.map +0 -6
- package/dist/extractor/extractToNative.js +0 -286
- package/dist/extractor/extractToNative.js.map +0 -6
- package/dist/extractor/findTopmostFunction.js +0 -32
- package/dist/extractor/findTopmostFunction.js.map +0 -6
- package/dist/extractor/generatedUid.js +0 -42
- package/dist/extractor/generatedUid.js.map +0 -6
- package/dist/extractor/getPrefixLogs.js +0 -24
- package/dist/extractor/getPrefixLogs.js.map +0 -6
- package/dist/extractor/getPropValueFromAttributes.js +0 -65
- package/dist/extractor/getPropValueFromAttributes.js.map +0 -6
- package/dist/extractor/getSourceModule.js +0 -62
- package/dist/extractor/getSourceModule.js.map +0 -6
- package/dist/extractor/getStaticBindingsForScope.js +0 -145
- package/dist/extractor/getStaticBindingsForScope.js.map +0 -6
- package/dist/extractor/getTamaguiConfigPathFromOptionsConfig.js +0 -32
- package/dist/extractor/getTamaguiConfigPathFromOptionsConfig.js.map +0 -6
- package/dist/extractor/hoistClassNames.js +0 -63
- package/dist/extractor/hoistClassNames.js.map +0 -6
- package/dist/extractor/literalToAst.js +0 -90
- package/dist/extractor/literalToAst.js.map +0 -6
- package/dist/extractor/loadFile.js +0 -14
- package/dist/extractor/loadFile.js.map +0 -6
- package/dist/extractor/loadTamagui.js +0 -306
- package/dist/extractor/loadTamagui.js.map +0 -6
- package/dist/extractor/logLines.js +0 -30
- package/dist/extractor/logLines.js.map +0 -6
- package/dist/extractor/normalizeTernaries.js +0 -61
- package/dist/extractor/normalizeTernaries.js.map +0 -6
- package/dist/extractor/propsToFontFamilyCache.js +0 -33
- package/dist/extractor/propsToFontFamilyCache.js.map +0 -6
- package/dist/extractor/regenerateConfig.js +0 -123
- package/dist/extractor/regenerateConfig.js.map +0 -6
- package/dist/extractor/removeUnusedHooks.js +0 -72
- package/dist/extractor/removeUnusedHooks.js.map +0 -6
- package/dist/extractor/timer.js +0 -38
- package/dist/extractor/timer.js.map +0 -6
- package/dist/extractor/validHTMLAttributes.js +0 -72
- package/dist/extractor/validHTMLAttributes.js.map +0 -6
- package/dist/extractor/watchTamaguiConfig.js +0 -57
- package/dist/extractor/watchTamaguiConfig.js.map +0 -6
- package/dist/getPragmaOptions.js +0 -46
- package/dist/getPragmaOptions.js.map +0 -6
- package/dist/helpers/memoize.js +0 -33
- package/dist/helpers/memoize.js.map +0 -6
- package/dist/helpers/requireTamaguiCore.js +0 -30
- package/dist/helpers/requireTamaguiCore.js.map +0 -6
- package/dist/registerRequire.js +0 -100
- package/dist/registerRequire.js.map +0 -6
- package/dist/server.js +0 -58
- package/dist/server.js.map +0 -6
- package/dist/setup.js +0 -1
- package/dist/setup.js.map +0 -6
- package/dist/types.js +0 -14
- package/dist/types.js.map +0 -6
- package/dist/worker.js +0 -72
- package/dist/worker.js.map +0 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamagui/static",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
3
|
+
"version": "2.0.0-rc.30",
|
|
4
4
|
"gitHead": "a49cc7ea6b93ba384e77a4880ae48ac4a5635c14",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"source": "src/index.ts",
|
|
@@ -16,15 +16,19 @@
|
|
|
16
16
|
"./package.json": "./package.json",
|
|
17
17
|
".": {
|
|
18
18
|
"types": "./types/index.d.ts",
|
|
19
|
-
"
|
|
20
|
-
"module": "./dist/index.cjs",
|
|
21
|
-
"import": "./dist/index.cjs"
|
|
19
|
+
"default": "./dist/index.cjs"
|
|
22
20
|
},
|
|
23
21
|
"./worker": {
|
|
24
22
|
"types": "./types/worker.d.ts",
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
"default": "./dist/worker.cjs"
|
|
24
|
+
},
|
|
25
|
+
"./checkDeps": {
|
|
26
|
+
"types": "./types/checkDeps.d.ts",
|
|
27
|
+
"default": "./dist/checkDeps.cjs"
|
|
28
|
+
},
|
|
29
|
+
"./loadTamagui": {
|
|
30
|
+
"types": "./types/extractor/loadTamagui.d.ts",
|
|
31
|
+
"default": "./dist/extractor/loadTamagui.cjs"
|
|
28
32
|
}
|
|
29
33
|
},
|
|
30
34
|
"publishConfig": {
|
|
@@ -46,19 +50,19 @@
|
|
|
46
50
|
"@babel/template": "^7.25.0",
|
|
47
51
|
"@babel/traverse": "^7.25.4",
|
|
48
52
|
"@babel/types": "^7.25.4",
|
|
49
|
-
"@tamagui/cli-color": "2.0.0-rc.
|
|
50
|
-
"@tamagui/config-default": "2.0.0-rc.
|
|
51
|
-
"@tamagui/core": "2.0.0-rc.
|
|
52
|
-
"@tamagui/fake-react-native": "2.0.0-rc.
|
|
53
|
-
"@tamagui/generate-themes": "2.0.0-rc.
|
|
54
|
-
"@tamagui/helpers": "2.0.0-rc.
|
|
55
|
-
"@tamagui/helpers-node": "2.0.0-rc.
|
|
56
|
-
"@tamagui/proxy-worm": "2.0.0-rc.
|
|
57
|
-
"@tamagui/react-native-web-internals": "2.0.0-rc.
|
|
58
|
-
"@tamagui/react-native-web-lite": "2.0.0-rc.
|
|
59
|
-
"@tamagui/shorthands": "2.0.0-rc.
|
|
60
|
-
"@tamagui/types": "2.0.0-rc.
|
|
61
|
-
"@tamagui/web": "2.0.0-rc.
|
|
53
|
+
"@tamagui/cli-color": "2.0.0-rc.30",
|
|
54
|
+
"@tamagui/config-default": "2.0.0-rc.30",
|
|
55
|
+
"@tamagui/core": "2.0.0-rc.30",
|
|
56
|
+
"@tamagui/fake-react-native": "2.0.0-rc.30",
|
|
57
|
+
"@tamagui/generate-themes": "2.0.0-rc.30",
|
|
58
|
+
"@tamagui/helpers": "2.0.0-rc.30",
|
|
59
|
+
"@tamagui/helpers-node": "2.0.0-rc.30",
|
|
60
|
+
"@tamagui/proxy-worm": "2.0.0-rc.30",
|
|
61
|
+
"@tamagui/react-native-web-internals": "2.0.0-rc.30",
|
|
62
|
+
"@tamagui/react-native-web-lite": "2.0.0-rc.30",
|
|
63
|
+
"@tamagui/shorthands": "2.0.0-rc.30",
|
|
64
|
+
"@tamagui/types": "2.0.0-rc.30",
|
|
65
|
+
"@tamagui/web": "2.0.0-rc.30",
|
|
62
66
|
"babel-literal-to-ast": "^2.1.0",
|
|
63
67
|
"browserslist": "^4.28.1",
|
|
64
68
|
"check-dependency-version-consistency": "^4.1.0",
|
|
@@ -75,7 +79,7 @@
|
|
|
75
79
|
},
|
|
76
80
|
"devDependencies": {
|
|
77
81
|
"@babel/plugin-syntax-typescript": "^7.25.4",
|
|
78
|
-
"@tamagui/build": "2.0.0-rc.
|
|
82
|
+
"@tamagui/build": "2.0.0-rc.30",
|
|
79
83
|
"@types/babel__core": "^7.20.5",
|
|
80
84
|
"@types/find-root": "^1.1.2",
|
|
81
85
|
"@types/node": "^22.1.0",
|
|
@@ -84,7 +88,7 @@
|
|
|
84
88
|
"esbuild-loader": "^4.2.2",
|
|
85
89
|
"null-loader": "^4.0.1",
|
|
86
90
|
"react": ">=19",
|
|
87
|
-
"react-native": "0.
|
|
91
|
+
"react-native": "0.83.2",
|
|
88
92
|
"typescript": "~5.9.2"
|
|
89
93
|
},
|
|
90
94
|
"peerDependencies": {
|
package/src/checkDeps.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from 'node:fs'
|
|
2
|
-
import { join } from 'node:path'
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, realpathSync } from 'node:fs'
|
|
2
|
+
import { join, relative } from 'node:path'
|
|
3
3
|
import { CDVC } from './check-dep-versions'
|
|
4
4
|
|
|
5
5
|
export enum DEPENDENCY_TYPE {
|
|
@@ -21,113 +21,350 @@ export type Options = {
|
|
|
21
21
|
ignorePathPattern?: readonly string[]
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
devDependencies?: Record<string, string>
|
|
27
|
-
optionalDependencies?: Record<string, string>
|
|
28
|
-
}
|
|
24
|
+
// critical packages that must not be duplicated at runtime
|
|
25
|
+
const CRITICAL_PACKAGES = ['@tamagui/web', '@tamagui/core', 'tamagui']
|
|
29
26
|
|
|
30
27
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
28
|
+
* Walks node_modules to find duplicate physical copies of critical tamagui packages.
|
|
29
|
+
* Detects nested node_modules that would cause multiple runtime instances.
|
|
33
30
|
*/
|
|
34
|
-
function
|
|
35
|
-
const
|
|
36
|
-
if (!existsSync(
|
|
37
|
-
|
|
31
|
+
function checkDuplicateInstalls(root: string): string {
|
|
32
|
+
const nodeModules = join(root, 'node_modules')
|
|
33
|
+
if (!existsSync(nodeModules)) return ''
|
|
34
|
+
|
|
35
|
+
const duplicates = new Map<string, string[]>()
|
|
36
|
+
|
|
37
|
+
for (const pkg of CRITICAL_PACKAGES) {
|
|
38
|
+
const locations = findAllInstances(nodeModules, pkg)
|
|
39
|
+
if (locations.length > 1) {
|
|
40
|
+
// resolve symlinks to find truly distinct copies
|
|
41
|
+
const realPaths = new Set<string>()
|
|
42
|
+
const distinctLocations: string[] = []
|
|
43
|
+
for (const loc of locations) {
|
|
44
|
+
try {
|
|
45
|
+
const real = realpathSync(loc)
|
|
46
|
+
if (!realPaths.has(real)) {
|
|
47
|
+
realPaths.add(real)
|
|
48
|
+
distinctLocations.push(relative(root, loc))
|
|
49
|
+
}
|
|
50
|
+
} catch {
|
|
51
|
+
distinctLocations.push(relative(root, loc))
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (distinctLocations.length > 1) {
|
|
55
|
+
duplicates.set(pkg, distinctLocations)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
38
58
|
}
|
|
39
59
|
|
|
40
|
-
|
|
60
|
+
if (duplicates.size === 0) return ''
|
|
41
61
|
|
|
42
|
-
|
|
43
|
-
|
|
62
|
+
const lines: string[] = [
|
|
63
|
+
'Found duplicate tamagui installations in node_modules:',
|
|
64
|
+
'',
|
|
65
|
+
'This causes multiple runtime instances, which breaks theme/config detection.',
|
|
66
|
+
'',
|
|
67
|
+
]
|
|
44
68
|
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
69
|
+
for (const [pkg, locations] of duplicates) {
|
|
70
|
+
// read versions from each location
|
|
71
|
+
lines.push(` ${pkg}:`)
|
|
72
|
+
for (const loc of locations) {
|
|
73
|
+
const pkgJsonPath = join(root, loc, 'package.json')
|
|
74
|
+
let version = '?'
|
|
75
|
+
try {
|
|
76
|
+
version = JSON.parse(readFileSync(pkgJsonPath, 'utf8')).version
|
|
77
|
+
} catch {}
|
|
78
|
+
lines.push(` ${version} at ${loc}`)
|
|
79
|
+
}
|
|
80
|
+
lines.push('')
|
|
49
81
|
}
|
|
50
82
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
83
|
+
lines.push("Fix: run your package manager's dedupe command:")
|
|
84
|
+
lines.push(' bun install (bun auto-dedupes)')
|
|
85
|
+
lines.push(' npx yarn-deduplicate && yarn install')
|
|
86
|
+
lines.push(' npm dedupe')
|
|
87
|
+
lines.push('')
|
|
88
|
+
lines.push("If that doesn't help, delete node_modules and lockfile, then reinstall.")
|
|
89
|
+
|
|
90
|
+
return lines.join('\n')
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Recursively find all instances of a package in node_modules.
|
|
95
|
+
* Handles both scoped (@tamagui/web) and unscoped (tamagui) packages.
|
|
96
|
+
*/
|
|
97
|
+
function findAllInstances(
|
|
98
|
+
nodeModulesDir: string,
|
|
99
|
+
packageName: string,
|
|
100
|
+
found: string[] = [],
|
|
101
|
+
depth = 0
|
|
102
|
+
): string[] {
|
|
103
|
+
// don't go too deep, typical hoisting issues show up within a few levels
|
|
104
|
+
if (depth > 4 || !existsSync(nodeModulesDir)) return found
|
|
105
|
+
|
|
106
|
+
const pkgDir = join(nodeModulesDir, ...packageName.split('/'))
|
|
107
|
+
if (existsSync(join(pkgDir, 'package.json'))) {
|
|
108
|
+
found.push(pkgDir)
|
|
55
109
|
}
|
|
56
110
|
|
|
57
|
-
|
|
111
|
+
// scan nested node_modules inside direct children
|
|
112
|
+
try {
|
|
113
|
+
const entries = readdirSync(nodeModulesDir)
|
|
114
|
+
for (const entry of entries) {
|
|
115
|
+
if (entry.startsWith('.')) continue
|
|
116
|
+
|
|
117
|
+
if (entry.startsWith('@')) {
|
|
118
|
+
// scoped packages have another level
|
|
119
|
+
const scopeDir = join(nodeModulesDir, entry)
|
|
120
|
+
try {
|
|
121
|
+
const scopeEntries = readdirSync(scopeDir)
|
|
122
|
+
for (const scopeEntry of scopeEntries) {
|
|
123
|
+
const nested = join(scopeDir, scopeEntry, 'node_modules')
|
|
124
|
+
if (existsSync(nested)) {
|
|
125
|
+
findAllInstances(nested, packageName, found, depth + 1)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
} catch {}
|
|
129
|
+
} else {
|
|
130
|
+
const nested = join(nodeModulesDir, entry, 'node_modules')
|
|
131
|
+
if (existsSync(nested)) {
|
|
132
|
+
findAllInstances(nested, packageName, found, depth + 1)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
} catch {}
|
|
137
|
+
|
|
138
|
+
return found
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Checks lockfile for multiple resolved versions of tamagui packages.
|
|
143
|
+
* Supports bun.lock, yarn.lock, and package-lock.json.
|
|
144
|
+
*/
|
|
145
|
+
function checkLockfileDuplicates(root: string): string {
|
|
146
|
+
const bunLock = join(root, 'bun.lock')
|
|
147
|
+
const yarnLock = join(root, 'yarn.lock')
|
|
148
|
+
const npmLock = join(root, 'package-lock.json')
|
|
149
|
+
|
|
150
|
+
if (existsSync(bunLock)) return checkBunLockDuplicates(bunLock)
|
|
151
|
+
if (existsSync(yarnLock)) return checkYarnLockDuplicates(yarnLock)
|
|
152
|
+
if (existsSync(npmLock)) return checkNpmLockDuplicates(npmLock)
|
|
153
|
+
|
|
154
|
+
return ''
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function checkBunLockDuplicates(lockPath: string): string {
|
|
158
|
+
try {
|
|
159
|
+
const content = readFileSync(lockPath, 'utf8')
|
|
160
|
+
const duplicates = new Map<string, Set<string>>()
|
|
161
|
+
const criticalSet = new Set(CRITICAL_PACKAGES)
|
|
162
|
+
|
|
163
|
+
// match patterns like "@tamagui/web@version" or "tamagui@version" in resolved entries
|
|
164
|
+
// bun.lock format: "package@version": ["resolved-url", ...]
|
|
165
|
+
const packagePattern = /["'](@tamagui\/[\w-]+|tamagui)@([^"'\s,]+)["']/g
|
|
166
|
+
let match: RegExpExecArray | null
|
|
167
|
+
while ((match = packagePattern.exec(content)) !== null) {
|
|
168
|
+
const name = match[1]
|
|
169
|
+
const version = match[2]
|
|
170
|
+
if (version.startsWith('workspace:')) continue
|
|
171
|
+
// only flag critical packages — leaf packages can safely differ
|
|
172
|
+
if (!criticalSet.has(name)) continue
|
|
173
|
+
if (!duplicates.has(name)) duplicates.set(name, new Set())
|
|
174
|
+
duplicates.get(name)!.add(version)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return formatLockfileDuplicates(duplicates, 'bun.lock')
|
|
178
|
+
} catch {
|
|
58
179
|
return ''
|
|
59
180
|
}
|
|
181
|
+
}
|
|
60
182
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
183
|
+
function checkYarnLockDuplicates(lockPath: string): string {
|
|
184
|
+
try {
|
|
185
|
+
const content = readFileSync(lockPath, 'utf8')
|
|
186
|
+
const duplicates = new Map<string, Set<string>>()
|
|
187
|
+
const criticalSet = new Set(CRITICAL_PACKAGES)
|
|
188
|
+
|
|
189
|
+
// yarn.lock format:
|
|
190
|
+
// "@tamagui/web@^1.0.0":
|
|
191
|
+
// version "1.0.1"
|
|
192
|
+
const entryPattern = /^"?(@tamagui\/[\w-]+|tamagui)@[^":\n]+[":]?\s*$/gm
|
|
193
|
+
const versionPattern = /^\s+version\s+"([^"]+)"/gm
|
|
194
|
+
|
|
195
|
+
let entryMatch: RegExpExecArray | null
|
|
196
|
+
while ((entryMatch = entryPattern.exec(content)) !== null) {
|
|
197
|
+
const name = entryMatch[1]
|
|
198
|
+
if (!criticalSet.has(name)) continue
|
|
199
|
+
versionPattern.lastIndex = entryMatch.index
|
|
200
|
+
const verMatch = versionPattern.exec(content)
|
|
201
|
+
if (verMatch) {
|
|
202
|
+
if (!duplicates.has(name)) duplicates.set(name, new Set())
|
|
203
|
+
duplicates.get(name)!.add(verMatch[1])
|
|
204
|
+
}
|
|
66
205
|
}
|
|
67
|
-
|
|
206
|
+
|
|
207
|
+
return formatLockfileDuplicates(duplicates, 'yarn.lock')
|
|
208
|
+
} catch {
|
|
209
|
+
return ''
|
|
68
210
|
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function checkNpmLockDuplicates(lockPath: string): string {
|
|
214
|
+
try {
|
|
215
|
+
const lock = JSON.parse(readFileSync(lockPath, 'utf8'))
|
|
216
|
+
const duplicates = new Map<string, Set<string>>()
|
|
217
|
+
const criticalSet = new Set(CRITICAL_PACKAGES)
|
|
69
218
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
219
|
+
// package-lock.json v2/v3 uses "packages" map with path keys
|
|
220
|
+
const packages = lock.packages || {}
|
|
221
|
+
for (const [path, info] of Object.entries(packages) as [string, any][]) {
|
|
222
|
+
if (!path) continue // skip root
|
|
223
|
+
const name = info.name || path.split('node_modules/').pop()
|
|
224
|
+
if (!name) continue
|
|
225
|
+
if (!criticalSet.has(name)) continue
|
|
226
|
+
const version = info.version
|
|
227
|
+
if (version) {
|
|
228
|
+
if (!duplicates.has(name)) duplicates.set(name, new Set())
|
|
229
|
+
duplicates.get(name)!.add(version)
|
|
230
|
+
}
|
|
76
231
|
}
|
|
77
|
-
versionGroups.get(normalized)!.push(`${dep.name}@${dep.version}`)
|
|
78
|
-
}
|
|
79
232
|
|
|
80
|
-
|
|
81
|
-
|
|
233
|
+
return formatLockfileDuplicates(duplicates, 'package-lock.json')
|
|
234
|
+
} catch {
|
|
82
235
|
return ''
|
|
83
236
|
}
|
|
237
|
+
}
|
|
84
238
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
for (const [
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
lines.push(` - ${pkg}`)
|
|
239
|
+
function formatLockfileDuplicates(
|
|
240
|
+
duplicates: Map<string, Set<string>>,
|
|
241
|
+
lockfileName: string
|
|
242
|
+
): string {
|
|
243
|
+
// filter to only packages with multiple versions
|
|
244
|
+
const multiVersion = new Map<string, string[]>()
|
|
245
|
+
for (const [name, versions] of duplicates) {
|
|
246
|
+
if (versions.size > 1) {
|
|
247
|
+
multiVersion.set(name, [...versions].sort())
|
|
95
248
|
}
|
|
96
249
|
}
|
|
97
250
|
|
|
251
|
+
if (multiVersion.size === 0) return ''
|
|
252
|
+
|
|
253
|
+
const lines: string[] = [`Found multiple resolved versions in ${lockfileName}:`, '']
|
|
254
|
+
|
|
255
|
+
for (const [name, versions] of multiVersion) {
|
|
256
|
+
lines.push(` ${name}: ${versions.join(', ')}`)
|
|
257
|
+
}
|
|
258
|
+
|
|
98
259
|
lines.push('')
|
|
99
260
|
lines.push(
|
|
100
|
-
'
|
|
261
|
+
'Multiple versions cause duplicate runtime instances, breaking config/theme detection.'
|
|
101
262
|
)
|
|
102
|
-
lines.push('
|
|
263
|
+
lines.push('Fix: ensure all tamagui packages use the same version range, then dedupe.')
|
|
103
264
|
|
|
104
265
|
return lines.join('\n')
|
|
105
266
|
}
|
|
106
267
|
|
|
268
|
+
/**
|
|
269
|
+
* Checks that a tamagui config file exists in common locations.
|
|
270
|
+
*/
|
|
271
|
+
function checkConfigExists(root: string): string {
|
|
272
|
+
const configNames = [
|
|
273
|
+
'tamagui.config.ts',
|
|
274
|
+
'tamagui.config.tsx',
|
|
275
|
+
'tamagui.config.js',
|
|
276
|
+
'tamagui.config.mjs',
|
|
277
|
+
'tamagui.config.cjs',
|
|
278
|
+
]
|
|
279
|
+
|
|
280
|
+
const searchDirs = [root, join(root, 'src'), join(root, 'app'), join(root, 'config')]
|
|
281
|
+
|
|
282
|
+
for (const dir of searchDirs) {
|
|
283
|
+
for (const name of configNames) {
|
|
284
|
+
if (existsSync(join(dir, name))) {
|
|
285
|
+
return ''
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// check if tamagui.build.ts references a config path
|
|
291
|
+
const buildConfigNames = [
|
|
292
|
+
'tamagui.build.ts',
|
|
293
|
+
'tamagui.build.js',
|
|
294
|
+
'tamagui.build.mjs',
|
|
295
|
+
'tamagui.build.cjs',
|
|
296
|
+
]
|
|
297
|
+
for (const name of buildConfigNames) {
|
|
298
|
+
const buildPath = join(root, name)
|
|
299
|
+
if (existsSync(buildPath)) {
|
|
300
|
+
try {
|
|
301
|
+
const content = readFileSync(buildPath, 'utf8')
|
|
302
|
+
const match = content.match(/config\s*:\s*['"`]([^'"`]+)['"`]/)
|
|
303
|
+
if (match) {
|
|
304
|
+
const configPath = join(root, match[1])
|
|
305
|
+
if (existsSync(configPath)) return ''
|
|
306
|
+
}
|
|
307
|
+
} catch {}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// also check if there's a tamagui config referenced in package.json
|
|
312
|
+
const pkgJsonPath = join(root, 'package.json')
|
|
313
|
+
if (existsSync(pkgJsonPath)) {
|
|
314
|
+
try {
|
|
315
|
+
const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf8'))
|
|
316
|
+
if (pkg.tamagui?.config) {
|
|
317
|
+
const configPath = join(root, pkg.tamagui.config)
|
|
318
|
+
if (existsSync(configPath)) return ''
|
|
319
|
+
}
|
|
320
|
+
} catch {}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// check if this is a monorepo root (has workspaces) - skip config check for root
|
|
324
|
+
if (existsSync(pkgJsonPath)) {
|
|
325
|
+
try {
|
|
326
|
+
const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf8'))
|
|
327
|
+
if (pkg.workspaces) return ''
|
|
328
|
+
} catch {}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return [
|
|
332
|
+
'No tamagui.config file found.',
|
|
333
|
+
'',
|
|
334
|
+
'Tamagui requires a config file (e.g. tamagui.config.ts) that calls createTamagui().',
|
|
335
|
+
'Without it, components will throw "Can\'t find Tamagui configuration" at runtime.',
|
|
336
|
+
'',
|
|
337
|
+
'See: https://tamagui.dev/docs/core/configuration',
|
|
338
|
+
].join('\n')
|
|
339
|
+
}
|
|
340
|
+
|
|
107
341
|
export async function checkDeps(root: string) {
|
|
108
|
-
|
|
109
|
-
const tamaguiMismatchSummary = checkTamaguiPackageVersions(root)
|
|
342
|
+
const issues: string[] = []
|
|
110
343
|
|
|
111
|
-
//
|
|
344
|
+
// 1. check for dependency version mismatches across workspace packages
|
|
112
345
|
const workspaceMismatchSummary = new CDVC(root).toMismatchSummary()
|
|
346
|
+
if (workspaceMismatchSummary) issues.push(workspaceMismatchSummary)
|
|
347
|
+
|
|
348
|
+
// 2. check lockfile for duplicate resolved versions of critical packages
|
|
349
|
+
const lockfileSummary = checkLockfileDuplicates(root)
|
|
350
|
+
if (lockfileSummary) issues.push(lockfileSummary)
|
|
113
351
|
|
|
114
|
-
|
|
115
|
-
const
|
|
352
|
+
// 3. check for duplicate physical installations in node_modules
|
|
353
|
+
const duplicatesSummary = checkDuplicateInstalls(root)
|
|
354
|
+
if (duplicatesSummary) issues.push(duplicatesSummary)
|
|
116
355
|
|
|
117
|
-
|
|
356
|
+
// 4. check that a config file exists
|
|
357
|
+
const configSummary = checkConfigExists(root)
|
|
358
|
+
if (configSummary) issues.push(configSummary)
|
|
359
|
+
|
|
360
|
+
if (issues.length === 0) {
|
|
118
361
|
console.info(`Tamagui dependencies look good ✅`)
|
|
119
362
|
process.exit(0)
|
|
120
363
|
}
|
|
121
364
|
|
|
122
|
-
|
|
123
|
-
console.error(
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (hasWorkspaceMismatch) {
|
|
127
|
-
if (hasTamaguiMismatch) {
|
|
128
|
-
console.error('') // Add spacing between error sections
|
|
129
|
-
}
|
|
130
|
-
console.error(workspaceMismatchSummary)
|
|
365
|
+
for (let i = 0; i < issues.length; i++) {
|
|
366
|
+
if (i > 0) console.error('')
|
|
367
|
+
console.error(issues[i])
|
|
131
368
|
}
|
|
132
369
|
|
|
133
370
|
process.exit(1)
|
package/src/exports.ts
CHANGED
|
@@ -11,4 +11,5 @@ export * from './extractor/loadTamagui'
|
|
|
11
11
|
export * from './extractor/watchTamaguiConfig'
|
|
12
12
|
export * from './extractor/createLogger'
|
|
13
13
|
export * from './registerRequire'
|
|
14
|
+
export { detectModuleFormat, clearFormatCache } from './extractor/detectModuleFormat'
|
|
14
15
|
export * from './getPragmaOptions'
|