@multiplatform.one/config 7.8.0 → 7.11.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/lib/index.js +2 -2
- package/lib/{storybook-B3oEWyc-.js → storybook-CGNSgSBS.js} +1 -1
- package/lib/storybook.js +1 -1
- package/lib/{vite-DCmObTtC.js → vite-D6vMjPwv.js} +1 -1
- package/lib/vite.js +2 -2
- package/lib/{workspacePublicPackages-DdJxvtWd.js → workspacePublicPackages-B4FGgRYG.js} +16 -1
- package/package.json +3 -3
- package/src/singletonDepAliases.spec.ts +64 -0
- package/src/singletonDepAliases.ts +20 -0
- package/types/singletonDepAliases.d.ts.map +1 -1
package/lib/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as createViteConfig } from "./vite-
|
|
2
|
-
import { t as createStorybookViteConfig } from "./storybook-
|
|
1
|
+
import { t as createViteConfig } from "./vite-D6vMjPwv.js";
|
|
2
|
+
import { t as createStorybookViteConfig } from "./storybook-CGNSgSBS.js";
|
|
3
3
|
import { n as tamaguiWorkspacePathsFile, t as ensureTamaguiWorkspacePaths } from "./tamaguiWorkspacePaths-ZIcqybtn.js";
|
|
4
4
|
import { createVitestConfig } from "./vitest.js";
|
|
5
5
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as withSingletonDepAliases, r as resolvePackageMainSource, t as discoverPublicPackageRoots } from "./workspacePublicPackages-
|
|
1
|
+
import { i as withSingletonDepAliases, r as resolvePackageMainSource, t as discoverPublicPackageRoots } from "./workspacePublicPackages-B4FGgRYG.js";
|
|
2
2
|
import { t as ensureTamaguiWorkspacePaths } from "./tamaguiWorkspacePaths-ZIcqybtn.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import fs from "node:fs";
|
package/lib/storybook.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as withSingletonDepAliases, t as discoverPublicPackageRoots } from "./workspacePublicPackages-
|
|
1
|
+
import { i as withSingletonDepAliases, t as discoverPublicPackageRoots } from "./workspacePublicPackages-B4FGgRYG.js";
|
|
2
2
|
import { t as ensureTamaguiWorkspacePaths } from "./tamaguiWorkspacePaths-ZIcqybtn.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import fs from "node:fs";
|
package/lib/vite.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createViteConfig } from "./vite-
|
|
2
|
-
import { n as publicPackageViteSourceAliases, t as discoverPublicPackageRoots } from "./workspacePublicPackages-
|
|
1
|
+
import { t as createViteConfig } from "./vite-D6vMjPwv.js";
|
|
2
|
+
import { n as publicPackageViteSourceAliases, t as discoverPublicPackageRoots } from "./workspacePublicPackages-B4FGgRYG.js";
|
|
3
3
|
|
|
4
4
|
export { createViteConfig, discoverPublicPackageRoots, publicPackageViteSourceAliases };
|
|
@@ -64,13 +64,28 @@ import path from "node:path";
|
|
|
64
64
|
* mounting a data-bound panel threw `Cannot read properties of null (reading
|
|
65
65
|
* 'useSyncExternalStore')` on every load, and so did every data-bound page
|
|
66
66
|
* after it.
|
|
67
|
+
*
|
|
68
|
+
* MPO-288. THE CRITERION, so the next addition is a decision against a rule
|
|
69
|
+
* rather than a guess. A package belongs here when a second module record
|
|
70
|
+
* would break it: it holds state at module scope, it subscribes an external
|
|
71
|
+
* store, or it provides a React context consumers compare by identity.
|
|
72
|
+
* Grepping the installed package for `useSyncExternalStore` is a cheap test
|
|
73
|
+
* for the second clause, and `singletonDepAliases.spec.ts` re-runs it against
|
|
74
|
+
* the tree so a tanstack upgrade is checked rather than assumed. It is one
|
|
75
|
+
* clause and not the whole rule: `@tanstack/db` references the hook nowhere
|
|
76
|
+
* and is pinned anyway, for the collection registry it holds at module scope.
|
|
77
|
+
*
|
|
78
|
+
* `@tanstack/react-query` references the hook in 25 shipped files and is not
|
|
79
|
+
* listed. That is recorded rather than settled — no split has been observed
|
|
80
|
+
* there, and pinning it reaches further than this measurement does.
|
|
67
81
|
*/
|
|
68
82
|
const CONTEXT_SINGLETONS = [
|
|
69
83
|
"react-cookie",
|
|
70
84
|
"@tamagui/core",
|
|
71
85
|
"@tamagui/web",
|
|
72
86
|
"@tanstack/db",
|
|
73
|
-
"@tanstack/react-db"
|
|
87
|
+
"@tanstack/react-db",
|
|
88
|
+
"@tanstack/react-store"
|
|
74
89
|
];
|
|
75
90
|
/**
|
|
76
91
|
* Vite `resolve.alias` entries pinning each context singleton to one directory.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiplatform.one/config",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.11.0",
|
|
4
4
|
"description": "Shared build and test configuration presets for multiplatform.one",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"config",
|
|
@@ -95,14 +95,14 @@
|
|
|
95
95
|
"access": "public"
|
|
96
96
|
},
|
|
97
97
|
"dependencies": {
|
|
98
|
+
"@multiplatform.one/utils": "7.11.0",
|
|
98
99
|
"@tamagui/vite-plugin": "2.7.6",
|
|
99
100
|
"@vitejs/plugin-react": "^6.0.1",
|
|
100
101
|
"dotenv": "^17.4.2",
|
|
101
102
|
"vite": "^8.0.10",
|
|
102
103
|
"vite-plugin-external": "^6.2.2",
|
|
103
104
|
"vite-plugin-i18next-loader": "^3.1.3",
|
|
104
|
-
"vitest": "^4.1.5"
|
|
105
|
-
"@multiplatform.one/utils": "7.8.0"
|
|
105
|
+
"vitest": "^4.1.5"
|
|
106
106
|
},
|
|
107
107
|
"devDependencies": {
|
|
108
108
|
"tsdown": "^0.21.10",
|
|
@@ -67,6 +67,18 @@ describe("singletonDepAliases", () => {
|
|
|
67
67
|
expect(fs.existsSync(path.join(aliases["@tanstack/react-db"], "package.json"))).toBe(true);
|
|
68
68
|
});
|
|
69
69
|
|
|
70
|
+
it("pins the react half of the store pair, which is the one that calls the hook (MPO-288)", () => {
|
|
71
|
+
// The same split as react-db, measured the same way: @tanstack/store has
|
|
72
|
+
// zero references to useSyncExternalStore and @tanstack/react-store has
|
|
73
|
+
// three, all of them useSelector, which is what useStore calls.
|
|
74
|
+
// public/store and public/forms both reach React through it, so a second
|
|
75
|
+
// record subscribes a store nothing armed.
|
|
76
|
+
const aliases = singletonDepAliases(workspaceRoot);
|
|
77
|
+
expect(aliases["@tanstack/react-store"]).toBeTruthy();
|
|
78
|
+
expect(path.isAbsolute(aliases["@tanstack/react-store"])).toBe(true);
|
|
79
|
+
expect(fs.existsSync(path.join(aliases["@tanstack/react-store"], "package.json"))).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
|
|
70
82
|
it("omits packages that are not installed", () => {
|
|
71
83
|
// Resolution runs against the given root, so a consumer without the
|
|
72
84
|
// package gets no alias rather than a broken one.
|
|
@@ -141,3 +153,55 @@ describe("createViteConfig context singletons (MPO-225)", () => {
|
|
|
141
153
|
expect(alias.tamagui).toBeUndefined();
|
|
142
154
|
});
|
|
143
155
|
});
|
|
156
|
+
|
|
157
|
+
describe("CONTEXT_SINGLETONS membership, measured rather than recited (MPO-288)", () => {
|
|
158
|
+
const aliases = singletonDepAliases(workspaceRoot);
|
|
159
|
+
|
|
160
|
+
it("pins every tanstack half that subscribes an external store", () => {
|
|
161
|
+
for (const pkg of ["@tanstack/react-store", "@tanstack/react-db"]) {
|
|
162
|
+
expect(subscribesExternalStore(pkg), `${pkg} must reference the hook`).toBe(true);
|
|
163
|
+
expect(aliases[pkg], `${pkg} subscribes and must be pinned`).toBeTruthy();
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it("leaves the pacer pair off, which the same measurement confirms", () => {
|
|
168
|
+
for (const pkg of ["@tanstack/pacer", "@tanstack/react-pacer"]) {
|
|
169
|
+
expect(subscribesExternalStore(pkg), `${pkg} must not reference the hook`).toBe(false);
|
|
170
|
+
expect(aliases[pkg], `${pkg} has no measured reason to be pinned`).toBeUndefined();
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it("does not treat the grep as the whole rule", () => {
|
|
175
|
+
// @tanstack/db is pinned and references the hook nowhere: it holds the
|
|
176
|
+
// collection registry at module scope, which is a different clause of the
|
|
177
|
+
// criterion and one no grep can see. @tanstack/store carries no such
|
|
178
|
+
// registry, so silence there means what it says.
|
|
179
|
+
expect(subscribesExternalStore("@tanstack/db")).toBe(false);
|
|
180
|
+
expect(aliases["@tanstack/db"]).toBeTruthy();
|
|
181
|
+
expect(subscribesExternalStore("@tanstack/store")).toBe(false);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Whether an installed package references `useSyncExternalStore` in anything
|
|
187
|
+
* it ships. The cheap half of the membership rule, re-run against the tree so
|
|
188
|
+
* the next tanstack upgrade is checked rather than assumed.
|
|
189
|
+
*/
|
|
190
|
+
function subscribesExternalStore(pkgName: string): boolean {
|
|
191
|
+
const dir = path.join(workspaceRoot, "node_modules", ...pkgName.split("/"));
|
|
192
|
+
return fs.existsSync(dir) && referencesHook(dir);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function referencesHook(dir: string): boolean {
|
|
196
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
197
|
+
if (entry.name === "node_modules") continue;
|
|
198
|
+
const full = path.join(dir, entry.name);
|
|
199
|
+
if (fs.statSync(full).isDirectory()) {
|
|
200
|
+
if (referencesHook(full)) return true;
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
if (!/\.(?:js|cjs|mjs|ts|tsx)$/.test(entry.name)) continue;
|
|
204
|
+
if (fs.readFileSync(full, "utf8").includes("useSyncExternalStore")) return true;
|
|
205
|
+
}
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
@@ -63,6 +63,20 @@ import path from "node:path";
|
|
|
63
63
|
* mounting a data-bound panel threw `Cannot read properties of null (reading
|
|
64
64
|
* 'useSyncExternalStore')` on every load, and so did every data-bound page
|
|
65
65
|
* after it.
|
|
66
|
+
*
|
|
67
|
+
* MPO-288. THE CRITERION, so the next addition is a decision against a rule
|
|
68
|
+
* rather than a guess. A package belongs here when a second module record
|
|
69
|
+
* would break it: it holds state at module scope, it subscribes an external
|
|
70
|
+
* store, or it provides a React context consumers compare by identity.
|
|
71
|
+
* Grepping the installed package for `useSyncExternalStore` is a cheap test
|
|
72
|
+
* for the second clause, and `singletonDepAliases.spec.ts` re-runs it against
|
|
73
|
+
* the tree so a tanstack upgrade is checked rather than assumed. It is one
|
|
74
|
+
* clause and not the whole rule: `@tanstack/db` references the hook nowhere
|
|
75
|
+
* and is pinned anyway, for the collection registry it holds at module scope.
|
|
76
|
+
*
|
|
77
|
+
* `@tanstack/react-query` references the hook in 25 shipped files and is not
|
|
78
|
+
* listed. That is recorded rather than settled — no split has been observed
|
|
79
|
+
* there, and pinning it reaches further than this measurement does.
|
|
66
80
|
*/
|
|
67
81
|
const CONTEXT_SINGLETONS: readonly string[] = [
|
|
68
82
|
"react-cookie",
|
|
@@ -78,6 +92,12 @@ const CONTEXT_SINGLETONS: readonly string[] = [
|
|
|
78
92
|
// exactly where it was. MPO-225 named @tanstack/db; the measurement says
|
|
79
93
|
// the pair has to travel together.
|
|
80
94
|
"@tanstack/react-db",
|
|
95
|
+
// Measured at 0.11.0: @tanstack/store references useSyncExternalStore in
|
|
96
|
+
// nothing it ships and @tanstack/react-store in three, all useSelector,
|
|
97
|
+
// which is the call behind useStore. public/store and public/forms both
|
|
98
|
+
// reach React through it, so a second record would subscribe a store
|
|
99
|
+
// nothing armed — the null read MPO-225 reported, one package family over.
|
|
100
|
+
"@tanstack/react-store",
|
|
81
101
|
];
|
|
82
102
|
|
|
83
103
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"singletonDepAliases.d.ts","sourceRoot":"","sources":["../src/singletonDepAliases.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"singletonDepAliases.d.ts","sourceRoot":"","sources":["../src/singletonDepAliases.ts"],"names":[],"mappings":"AAsGA;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,GAAE,MAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUxF;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,IAAI,GAAE,MAAsB,EAC5B,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACrC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB"}
|