@multiplatform.one/config 7.4.0 → 7.5.0
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/README.md +27 -0
- package/lib/vitest.js +56 -17
- package/lint.d.ts +19 -0
- package/lint.mjs +778 -0
- package/oxlint.d.ts +12 -0
- package/oxlint.mjs +183 -0
- package/package.json +16 -3
- package/pin-react-require.cjs +42 -0
- package/src/lint.spec.ts +52 -0
- package/src/oxlint.spec.ts +61 -0
- package/src/vitest.spec.ts +151 -0
- package/src/vitest.ts +138 -26
- package/types/vitest.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -55,3 +55,30 @@ Extend from the tsconfig presets:
|
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
Available presets: `base.json`, `build.json`, `app.json`.
|
|
58
|
+
|
|
59
|
+
### Oxlint
|
|
60
|
+
|
|
61
|
+
Convention rules travel with the package. Consuming apps add one line:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"jsPlugins": ["@multiplatform.one/config/oxlint"]
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Then enable `mpo-conventions/no-hex-literals` on the globs you want (mpo's
|
|
70
|
+
own `oxlintrc.json` turns it on for `features/**`). Palette modules
|
|
71
|
+
(`themes/base.ts`, `themes/accent.ts`, `*palette*`) are exempt.
|
|
72
|
+
|
|
73
|
+
### Lint (node-script checks)
|
|
74
|
+
|
|
75
|
+
CSS-in-apps, features-twin, silent token no-ops, and the LC-65 size-recipe
|
|
76
|
+
pilot run through `runConventionChecks({ roots })`:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { runConventionChecks } from "@multiplatform.one/config/lint";
|
|
80
|
+
|
|
81
|
+
runConventionChecks({
|
|
82
|
+
roots: { root: process.cwd() },
|
|
83
|
+
});
|
|
84
|
+
```
|
package/lib/vitest.js
CHANGED
|
@@ -1,8 +1,33 @@
|
|
|
1
|
+
import Module from "node:module";
|
|
2
|
+
import fs from "node:fs";
|
|
1
3
|
import path from "node:path";
|
|
2
4
|
import { tamaguiPlugin } from "@tamagui/vite-plugin";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
3
6
|
import react from "@vitejs/plugin-react";
|
|
4
7
|
|
|
5
8
|
//#region src/vitest.ts
|
|
9
|
+
const pinReactRequireSetup = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../pin-react-require.cjs");
|
|
10
|
+
/**
|
|
11
|
+
* CJS `require('react')` does not go through Vite aliases. `use-sync-external-store`
|
|
12
|
+
* is a valid Node import, so Vitest leaves it external even when we ask to inline
|
|
13
|
+
* it, and Node then loads the hoisted root copy — a different inode than the
|
|
14
|
+
* `.pnpm` copy Vite binds. Patching Module._resolveFilename in the vitest
|
|
15
|
+
* process (config eval + workers that re-load this factory) makes that
|
|
16
|
+
* require land on the same physical copy as the aliases.
|
|
17
|
+
*/
|
|
18
|
+
function pinNodeReactRequire(reactDir, reactDomDir, schedulerDir) {
|
|
19
|
+
const ctor = Module;
|
|
20
|
+
if (ctor._mpoOneReact) return;
|
|
21
|
+
ctor._mpoOneReact = true;
|
|
22
|
+
const orig = ctor._resolveFilename;
|
|
23
|
+
ctor._resolveFilename = function pinned(request, parent, isMain, options) {
|
|
24
|
+
const next = request === "react" ? reactDir : request.startsWith("react/") ? path.join(reactDir, request.slice(6)) : request === "react-dom" ? reactDomDir : request.startsWith("react-dom/") ? path.join(reactDomDir, request.slice(10)) : request === "scheduler" ? schedulerDir : null;
|
|
25
|
+
if (next) try {
|
|
26
|
+
return orig.call(this, next, parent, isMain, options);
|
|
27
|
+
} catch {}
|
|
28
|
+
return orig.call(this, request, parent, isMain, options);
|
|
29
|
+
};
|
|
30
|
+
}
|
|
6
31
|
/**
|
|
7
32
|
* Creates a shared Vitest configuration for multiplatform.one packages.
|
|
8
33
|
*
|
|
@@ -49,18 +74,31 @@ function createVitestConfig(options = {}) {
|
|
|
49
74
|
resolveAliases["react-native-svg"] = "@tamagui/react-native-svg";
|
|
50
75
|
}
|
|
51
76
|
if (dedupeReact) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
77
|
+
const onePhysicalCopy = (pkg) => {
|
|
78
|
+
for (const base of [path.resolve(process.cwd(), "node_modules"), rootNodeModules]) try {
|
|
79
|
+
return fs.realpathSync(path.resolve(base, pkg));
|
|
80
|
+
} catch {}
|
|
81
|
+
return path.resolve(rootNodeModules, pkg);
|
|
82
|
+
};
|
|
83
|
+
const reactDir = onePhysicalCopy("react");
|
|
84
|
+
const reactDomDir = onePhysicalCopy("react-dom");
|
|
85
|
+
resolveAliases.react = reactDir;
|
|
86
|
+
resolveAliases["react-dom"] = reactDomDir;
|
|
87
|
+
resolveAliases["react-dom/client"] = path.join(reactDomDir, "client");
|
|
88
|
+
resolveAliases["react-dom/server"] = path.join(reactDomDir, "server");
|
|
89
|
+
resolveAliases["react/jsx-runtime"] = path.join(reactDir, "jsx-runtime");
|
|
90
|
+
resolveAliases["react/jsx-dev-runtime"] = path.join(reactDir, "jsx-dev-runtime");
|
|
91
|
+
const schedulerDir = onePhysicalCopy("scheduler");
|
|
92
|
+
resolveAliases.scheduler = schedulerDir;
|
|
93
|
+
process.env.MPO_VITEST_REACT = reactDir;
|
|
94
|
+
process.env.MPO_VITEST_REACT_DOM = reactDomDir;
|
|
95
|
+
process.env.MPO_VITEST_SCHEDULER = schedulerDir;
|
|
96
|
+
pinNodeReactRequire(reactDir, reactDomDir, schedulerDir);
|
|
59
97
|
}
|
|
60
98
|
const testConfig = {
|
|
61
99
|
environment,
|
|
62
100
|
globals: true,
|
|
63
|
-
setupFiles,
|
|
101
|
+
setupFiles: dedupeReact ? [pinReactRequireSetup, ...setupFiles] : setupFiles,
|
|
64
102
|
testTimeout,
|
|
65
103
|
coverage: {
|
|
66
104
|
provider: "v8",
|
|
@@ -88,9 +126,11 @@ function createVitestConfig(options = {}) {
|
|
|
88
126
|
"one",
|
|
89
127
|
/@tamagui\//,
|
|
90
128
|
"tamagui",
|
|
129
|
+
/@tanstack\//,
|
|
130
|
+
"use-sync-external-store",
|
|
91
131
|
...inlineDeps
|
|
92
132
|
],
|
|
93
|
-
...externalDeps.length > 0 ? { external: externalDeps } : {},
|
|
133
|
+
...externalDeps.length > 0 ? { external: [pinReactRequireSetup, ...externalDeps] } : { external: [pinReactRequireSetup] },
|
|
94
134
|
interopDefault: true
|
|
95
135
|
} }
|
|
96
136
|
};
|
|
@@ -102,8 +142,6 @@ function createVitestConfig(options = {}) {
|
|
|
102
142
|
test: testConfig,
|
|
103
143
|
resolve: {
|
|
104
144
|
extensions: [
|
|
105
|
-
".test.ts",
|
|
106
|
-
".test.tsx",
|
|
107
145
|
".web.ts",
|
|
108
146
|
".web.tsx",
|
|
109
147
|
".web.js",
|
|
@@ -123,11 +161,7 @@ function createVitestConfig(options = {}) {
|
|
|
123
161
|
...aliases
|
|
124
162
|
},
|
|
125
163
|
conditions,
|
|
126
|
-
dedupe:
|
|
127
|
-
"react",
|
|
128
|
-
"react-dom",
|
|
129
|
-
"scheduler"
|
|
130
|
-
] : []
|
|
164
|
+
dedupe: []
|
|
131
165
|
},
|
|
132
166
|
define: {
|
|
133
167
|
__DEV__: true,
|
|
@@ -135,7 +169,12 @@ function createVitestConfig(options = {}) {
|
|
|
135
169
|
process: JSON.stringify({
|
|
136
170
|
env: {
|
|
137
171
|
NODE_ENV: "test",
|
|
138
|
-
NODE_DEBUG: false
|
|
172
|
+
NODE_DEBUG: false,
|
|
173
|
+
...dedupeReact ? {
|
|
174
|
+
MPO_VITEST_REACT: process.env.MPO_VITEST_REACT,
|
|
175
|
+
MPO_VITEST_REACT_DOM: process.env.MPO_VITEST_REACT_DOM,
|
|
176
|
+
MPO_VITEST_SCHEDULER: process.env.MPO_VITEST_SCHEDULER
|
|
177
|
+
} : {}
|
|
139
178
|
},
|
|
140
179
|
platform: process.platform,
|
|
141
180
|
version: process.version,
|
package/lint.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type ConventionRoots = {
|
|
2
|
+
root?: string;
|
|
3
|
+
apps?: string;
|
|
4
|
+
features?: string;
|
|
5
|
+
public?: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type RunConventionChecksOptions = {
|
|
9
|
+
roots?: ConventionRoots;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function resolveRoots(roots?: ConventionRoots): {
|
|
13
|
+
root: string;
|
|
14
|
+
apps: string;
|
|
15
|
+
features: string;
|
|
16
|
+
public: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export function runConventionChecks(options?: RunConventionChecksOptions): number;
|