@multiplatform.one/utils 7.83.0 → 7.83.2
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/dev.cjs +84 -5
- package/lib/dev.mjs +83 -6
- package/package.json +1 -1
- package/src/dev.spec.ts +76 -0
- package/src/dev.ts +96 -1
- package/types/dev.d.ts +15 -0
- package/types/dev.d.ts.map +1 -1
package/lib/dev.cjs
CHANGED
|
@@ -167,6 +167,78 @@ function lookupProjectRoot() {
|
|
|
167
167
|
return _projectRoot;
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
|
+
const webConditionOrder = [
|
|
171
|
+
"import",
|
|
172
|
+
"default",
|
|
173
|
+
"require"
|
|
174
|
+
];
|
|
175
|
+
const skippedConditions = new Set(["types", "react-native"]);
|
|
176
|
+
const tsSourcePattern = /\.(c|m)?tsx?$/;
|
|
177
|
+
function collectExportTargets(target, out) {
|
|
178
|
+
if (typeof target === "string") {
|
|
179
|
+
out.push(target);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (!target) return;
|
|
183
|
+
if (Array.isArray(target)) {
|
|
184
|
+
for (const item of target) collectExportTargets(item, out);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (typeof target.source === "string") out.push(target.source);
|
|
188
|
+
const keys = Object.keys(target).filter((k) => k !== "source" && !skippedConditions.has(k));
|
|
189
|
+
const ordered = [...webConditionOrder.filter((k) => keys.includes(k)), ...keys.filter((k) => !webConditionOrder.includes(k))];
|
|
190
|
+
for (const key of ordered) collectExportTargets(target[key], out);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* The file a web build should compile for one `exports` entry: its `source`
|
|
194
|
+
* condition, else the first TypeScript file among its web conditions, else
|
|
195
|
+
* the first existing file (css, a prebuilt .mjs), so the package-name alias
|
|
196
|
+
* never swallows a subpath it cannot see.
|
|
197
|
+
*/
|
|
198
|
+
function resolveExportSource(pkgDir, target) {
|
|
199
|
+
const candidates = [];
|
|
200
|
+
collectExportTargets(target, candidates);
|
|
201
|
+
const existing = candidates.map((c) => node_path.default.resolve(pkgDir, c)).filter((c) => !c.endsWith(".d.ts") && node_fs.default.existsSync(c) && node_fs.default.statSync(c).isFile());
|
|
202
|
+
return existing.find((c) => tsSourcePattern.test(c)) ?? existing[0];
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* The file a subpath declares when none of its targets is on disk yet, such
|
|
206
|
+
* as a prebuilt `./dist/...` asset in an unbuilt tree. Aliasing it keeps the
|
|
207
|
+
* bare package alias from rewriting the subpath into `src/index.ts/<subpath>`,
|
|
208
|
+
* so a missing build fails on the real path. Types-only subpaths get none.
|
|
209
|
+
*/
|
|
210
|
+
function declaredExportTarget(pkgDir, target) {
|
|
211
|
+
const candidates = [];
|
|
212
|
+
collectExportTargets(target, candidates);
|
|
213
|
+
const runtime = candidates.find((c) => !c.endsWith(".d.ts"));
|
|
214
|
+
return runtime ? node_path.default.resolve(pkgDir, runtime) : void 0;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Vite `resolve.alias` entries for one package's `exports` subpaths:
|
|
218
|
+
* `<name>/<subpath>` → its source file, and a `./dir/*` pattern → the directory.
|
|
219
|
+
*/
|
|
220
|
+
function packageSubpathSourceAliases(pkgName, pkgDir, exportsField) {
|
|
221
|
+
const aliases = {};
|
|
222
|
+
if (!exportsField || typeof exportsField !== "object" || Array.isArray(exportsField)) return aliases;
|
|
223
|
+
for (const [key, target] of Object.entries(exportsField)) {
|
|
224
|
+
if (key === "." || key === "./package.json" || !key.startsWith("./")) continue;
|
|
225
|
+
if (key.endsWith("/*")) {
|
|
226
|
+
const pattern = key.slice(2, -2);
|
|
227
|
+
if (pattern.includes("*")) continue;
|
|
228
|
+
const targets = [];
|
|
229
|
+
collectExportTargets(target, targets);
|
|
230
|
+
const dirTarget = targets.find((t) => t.endsWith("/*"));
|
|
231
|
+
if (!dirTarget) continue;
|
|
232
|
+
const dir = node_path.default.resolve(pkgDir, dirTarget.slice(0, -2));
|
|
233
|
+
if (node_fs.default.existsSync(dir) && node_fs.default.statSync(dir).isDirectory()) aliases[`${pkgName}/${pattern}`] = dir;
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
if (key.includes("*")) continue;
|
|
237
|
+
const file = resolveExportSource(pkgDir, target) ?? declaredExportTarget(pkgDir, target);
|
|
238
|
+
if (file) aliases[`${pkgName}/${key.slice(2)}`] = file;
|
|
239
|
+
}
|
|
240
|
+
return aliases;
|
|
241
|
+
}
|
|
170
242
|
/**
|
|
171
243
|
* Map every public/* workspace package (and its subpath exports) to its TS
|
|
172
244
|
* source. Without this, packages whose exports point at dist (e.g. table)
|
|
@@ -198,11 +270,16 @@ function workspaceSourceAliases(workspaceRoot) {
|
|
|
198
270
|
if (!pkg.name) continue;
|
|
199
271
|
const main = resolveSource(pkgDir, "index");
|
|
200
272
|
if (main) aliases[pkg.name] = main;
|
|
201
|
-
if (pkg.exports && typeof pkg.exports === "object")
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
273
|
+
if (pkg.exports && typeof pkg.exports === "object") {
|
|
274
|
+
const exported = packageSubpathSourceAliases(pkg.name, pkgDir, pkg.exports);
|
|
275
|
+
for (const key of Object.keys(pkg.exports)) {
|
|
276
|
+
if (key === "." || key === "./package.json" || node_path.default.extname(key)) continue;
|
|
277
|
+
const subpath = key.replace(/^\.\//, "");
|
|
278
|
+
const declared = exported[`${pkg.name}/${subpath}`];
|
|
279
|
+
const resolved = (declared && tsSourcePattern.test(declared) ? declared : void 0) ?? resolveSource(pkgDir, subpath);
|
|
280
|
+
if (resolved) aliases[`${pkg.name}/${subpath}`] = resolved;
|
|
281
|
+
}
|
|
282
|
+
for (const [find, replacement] of Object.entries(exported)) aliases[find] ??= replacement;
|
|
206
283
|
}
|
|
207
284
|
} catch {}
|
|
208
285
|
}
|
|
@@ -292,7 +369,9 @@ exports.lookupProjectRoot = lookupProjectRoot;
|
|
|
292
369
|
exports.lookupTamaguiModules = lookupTamaguiModules;
|
|
293
370
|
exports.lookupTranspileModules = lookupTranspileModules;
|
|
294
371
|
exports.oneServerOnlyBrowserStub = oneServerOnlyBrowserStub;
|
|
372
|
+
exports.packageSubpathSourceAliases = packageSubpathSourceAliases;
|
|
295
373
|
exports.resolveConfig = resolveConfig;
|
|
374
|
+
exports.resolveExportSource = resolveExportSource;
|
|
296
375
|
exports.stubExpoTypeDeclarations = stubExpoTypeDeclarations;
|
|
297
376
|
exports.waitForFrappe = waitForFrappe;
|
|
298
377
|
exports.waitForKeycloak = waitForKeycloak;
|
package/lib/dev.mjs
CHANGED
|
@@ -139,6 +139,78 @@ function lookupProjectRoot() {
|
|
|
139
139
|
return _projectRoot;
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
|
+
const webConditionOrder = [
|
|
143
|
+
"import",
|
|
144
|
+
"default",
|
|
145
|
+
"require"
|
|
146
|
+
];
|
|
147
|
+
const skippedConditions = new Set(["types", "react-native"]);
|
|
148
|
+
const tsSourcePattern = /\.(c|m)?tsx?$/;
|
|
149
|
+
function collectExportTargets(target, out) {
|
|
150
|
+
if (typeof target === "string") {
|
|
151
|
+
out.push(target);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (!target) return;
|
|
155
|
+
if (Array.isArray(target)) {
|
|
156
|
+
for (const item of target) collectExportTargets(item, out);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (typeof target.source === "string") out.push(target.source);
|
|
160
|
+
const keys = Object.keys(target).filter((k) => k !== "source" && !skippedConditions.has(k));
|
|
161
|
+
const ordered = [...webConditionOrder.filter((k) => keys.includes(k)), ...keys.filter((k) => !webConditionOrder.includes(k))];
|
|
162
|
+
for (const key of ordered) collectExportTargets(target[key], out);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The file a web build should compile for one `exports` entry: its `source`
|
|
166
|
+
* condition, else the first TypeScript file among its web conditions, else
|
|
167
|
+
* the first existing file (css, a prebuilt .mjs), so the package-name alias
|
|
168
|
+
* never swallows a subpath it cannot see.
|
|
169
|
+
*/
|
|
170
|
+
function resolveExportSource(pkgDir, target) {
|
|
171
|
+
const candidates = [];
|
|
172
|
+
collectExportTargets(target, candidates);
|
|
173
|
+
const existing = candidates.map((c) => path.resolve(pkgDir, c)).filter((c) => !c.endsWith(".d.ts") && fs.existsSync(c) && fs.statSync(c).isFile());
|
|
174
|
+
return existing.find((c) => tsSourcePattern.test(c)) ?? existing[0];
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* The file a subpath declares when none of its targets is on disk yet, such
|
|
178
|
+
* as a prebuilt `./dist/...` asset in an unbuilt tree. Aliasing it keeps the
|
|
179
|
+
* bare package alias from rewriting the subpath into `src/index.ts/<subpath>`,
|
|
180
|
+
* so a missing build fails on the real path. Types-only subpaths get none.
|
|
181
|
+
*/
|
|
182
|
+
function declaredExportTarget(pkgDir, target) {
|
|
183
|
+
const candidates = [];
|
|
184
|
+
collectExportTargets(target, candidates);
|
|
185
|
+
const runtime = candidates.find((c) => !c.endsWith(".d.ts"));
|
|
186
|
+
return runtime ? path.resolve(pkgDir, runtime) : void 0;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Vite `resolve.alias` entries for one package's `exports` subpaths:
|
|
190
|
+
* `<name>/<subpath>` → its source file, and a `./dir/*` pattern → the directory.
|
|
191
|
+
*/
|
|
192
|
+
function packageSubpathSourceAliases(pkgName, pkgDir, exportsField) {
|
|
193
|
+
const aliases = {};
|
|
194
|
+
if (!exportsField || typeof exportsField !== "object" || Array.isArray(exportsField)) return aliases;
|
|
195
|
+
for (const [key, target] of Object.entries(exportsField)) {
|
|
196
|
+
if (key === "." || key === "./package.json" || !key.startsWith("./")) continue;
|
|
197
|
+
if (key.endsWith("/*")) {
|
|
198
|
+
const pattern = key.slice(2, -2);
|
|
199
|
+
if (pattern.includes("*")) continue;
|
|
200
|
+
const targets = [];
|
|
201
|
+
collectExportTargets(target, targets);
|
|
202
|
+
const dirTarget = targets.find((t) => t.endsWith("/*"));
|
|
203
|
+
if (!dirTarget) continue;
|
|
204
|
+
const dir = path.resolve(pkgDir, dirTarget.slice(0, -2));
|
|
205
|
+
if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()) aliases[`${pkgName}/${pattern}`] = dir;
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
if (key.includes("*")) continue;
|
|
209
|
+
const file = resolveExportSource(pkgDir, target) ?? declaredExportTarget(pkgDir, target);
|
|
210
|
+
if (file) aliases[`${pkgName}/${key.slice(2)}`] = file;
|
|
211
|
+
}
|
|
212
|
+
return aliases;
|
|
213
|
+
}
|
|
142
214
|
/**
|
|
143
215
|
* Map every public/* workspace package (and its subpath exports) to its TS
|
|
144
216
|
* source. Without this, packages whose exports point at dist (e.g. table)
|
|
@@ -170,11 +242,16 @@ function workspaceSourceAliases(workspaceRoot) {
|
|
|
170
242
|
if (!pkg.name) continue;
|
|
171
243
|
const main = resolveSource(pkgDir, "index");
|
|
172
244
|
if (main) aliases[pkg.name] = main;
|
|
173
|
-
if (pkg.exports && typeof pkg.exports === "object")
|
|
174
|
-
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
245
|
+
if (pkg.exports && typeof pkg.exports === "object") {
|
|
246
|
+
const exported = packageSubpathSourceAliases(pkg.name, pkgDir, pkg.exports);
|
|
247
|
+
for (const key of Object.keys(pkg.exports)) {
|
|
248
|
+
if (key === "." || key === "./package.json" || path.extname(key)) continue;
|
|
249
|
+
const subpath = key.replace(/^\.\//, "");
|
|
250
|
+
const declared = exported[`${pkg.name}/${subpath}`];
|
|
251
|
+
const resolved = (declared && tsSourcePattern.test(declared) ? declared : void 0) ?? resolveSource(pkgDir, subpath);
|
|
252
|
+
if (resolved) aliases[`${pkg.name}/${subpath}`] = resolved;
|
|
253
|
+
}
|
|
254
|
+
for (const [find, replacement] of Object.entries(exported)) aliases[find] ??= replacement;
|
|
178
255
|
}
|
|
179
256
|
} catch {}
|
|
180
257
|
}
|
|
@@ -259,4 +336,4 @@ function stubExpoTypeDeclarations() {
|
|
|
259
336
|
}
|
|
260
337
|
|
|
261
338
|
//#endregion
|
|
262
|
-
export { formatServiceList, lookupProjectRoot, lookupTamaguiModules, lookupTranspileModules, oneServerOnlyBrowserStub, resolveConfig, stubExpoTypeDeclarations, waitForFrappe, waitForKeycloak, waitForMariaDB, waitForPostgres, waitServices, workspaceSourceAliases };
|
|
339
|
+
export { formatServiceList, lookupProjectRoot, lookupTamaguiModules, lookupTranspileModules, oneServerOnlyBrowserStub, packageSubpathSourceAliases, resolveConfig, resolveExportSource, stubExpoTypeDeclarations, waitForFrappe, waitForKeycloak, waitForMariaDB, waitForPostgres, waitServices, workspaceSourceAliases };
|
package/package.json
CHANGED
package/src/dev.spec.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
lookupTamaguiModules,
|
|
15
15
|
lookupTranspileModules,
|
|
16
16
|
resolveConfig,
|
|
17
|
+
workspaceSourceAliases,
|
|
17
18
|
} from "./dev";
|
|
18
19
|
|
|
19
20
|
let fixtureRoot: string;
|
|
@@ -137,3 +138,78 @@ describe("resolveConfig", () => {
|
|
|
137
138
|
expect(resolveConfig([])).toEqual({});
|
|
138
139
|
});
|
|
139
140
|
});
|
|
141
|
+
|
|
142
|
+
describe("workspaceSourceAliases", () => {
|
|
143
|
+
function writeFile(file: string, text = "export {};\n"): void {
|
|
144
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
145
|
+
fs.writeFileSync(file, text);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function fixtureWorkspace(): string {
|
|
149
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "mpo-dev-aliases-"));
|
|
150
|
+
const theme = path.join(root, "public/theme");
|
|
151
|
+
writePkg(theme, {
|
|
152
|
+
name: "@x/theme",
|
|
153
|
+
exports: {
|
|
154
|
+
"./package.json": "./package.json",
|
|
155
|
+
"./src/*": "./src/*",
|
|
156
|
+
".": { source: "./src/index.ts", default: "./src/index.ts" },
|
|
157
|
+
"./scale-attribute": {
|
|
158
|
+
source: "./src/theme/scale/scaleAttribute.ts",
|
|
159
|
+
types: "./types/theme/scale/scaleAttribute.d.ts",
|
|
160
|
+
default: "./src/theme/scale/scaleAttribute.ts",
|
|
161
|
+
},
|
|
162
|
+
"./ramps": { types: "./types/ramps.d.ts", default: "./dist/ramps.mjs" },
|
|
163
|
+
"./icons": { default: "./dist/icons.mjs" },
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
writeFile(path.join(theme, "src/index.ts"));
|
|
167
|
+
writeFile(path.join(theme, "src/theme/scale/scaleAttribute.ts"));
|
|
168
|
+
writeFile(path.join(theme, "src/ramps.ts"));
|
|
169
|
+
writeFile(path.join(theme, "dist/ramps.mjs"));
|
|
170
|
+
return root;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
it("aliases an exported subpath whose name is not its path to the export's source", () => {
|
|
174
|
+
const root = fixtureWorkspace();
|
|
175
|
+
const aliases = workspaceSourceAliases(root);
|
|
176
|
+
expect(aliases["@x/theme/scale-attribute"]).toBe(
|
|
177
|
+
path.join(root, "public/theme/src/theme/scale/scaleAttribute.ts"),
|
|
178
|
+
);
|
|
179
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("keeps the source guess over a dist-only export target", () => {
|
|
183
|
+
const root = fixtureWorkspace();
|
|
184
|
+
expect(workspaceSourceAliases(root)["@x/theme/ramps"]).toBe(
|
|
185
|
+
path.join(root, "public/theme/src/ramps.ts"),
|
|
186
|
+
);
|
|
187
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("aliases an unbuilt subpath to its declared target, not src/index.ts/<subpath>", () => {
|
|
191
|
+
const root = fixtureWorkspace();
|
|
192
|
+
expect(workspaceSourceAliases(root)["@x/theme/icons"]).toBe(
|
|
193
|
+
path.join(root, "public/theme/dist/icons.mjs"),
|
|
194
|
+
);
|
|
195
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it("puts every subpath before the bare package name", () => {
|
|
199
|
+
const root = fixtureWorkspace();
|
|
200
|
+
const keys = Object.keys(workspaceSourceAliases(root));
|
|
201
|
+
const bare = keys.indexOf("@x/theme");
|
|
202
|
+
expect(bare).toBeGreaterThan(-1);
|
|
203
|
+
for (const key of keys.filter((k) => k.startsWith("@x/theme/"))) {
|
|
204
|
+
expect(keys.indexOf(key)).toBeLessThan(bare);
|
|
205
|
+
}
|
|
206
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it("resolves the theme's scale-attribute subpath in this workspace", () => {
|
|
210
|
+
const repo = path.resolve(__dirname, "../../..");
|
|
211
|
+
expect(workspaceSourceAliases(repo)["@multiplatform.one/theme/scale-attribute"]).toBe(
|
|
212
|
+
path.join(repo, "public/theme/src/theme/scale/scaleAttribute.ts"),
|
|
213
|
+
);
|
|
214
|
+
});
|
|
215
|
+
});
|
package/src/dev.ts
CHANGED
|
@@ -100,6 +100,94 @@ export function lookupProjectRoot() {
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
export type ExportTarget = string | null | ExportTarget[] | { [condition: string]: ExportTarget };
|
|
104
|
+
|
|
105
|
+
const webConditionOrder = ["import", "default", "require"];
|
|
106
|
+
const skippedConditions = new Set(["types", "react-native"]);
|
|
107
|
+
const tsSourcePattern = /\.(c|m)?tsx?$/;
|
|
108
|
+
|
|
109
|
+
function collectExportTargets(target: ExportTarget, out: string[]): void {
|
|
110
|
+
if (typeof target === "string") {
|
|
111
|
+
out.push(target);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (!target) return;
|
|
115
|
+
if (Array.isArray(target)) {
|
|
116
|
+
for (const item of target) collectExportTargets(item, out);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (typeof target.source === "string") out.push(target.source);
|
|
120
|
+
const keys = Object.keys(target).filter((k) => k !== "source" && !skippedConditions.has(k));
|
|
121
|
+
const ordered = [
|
|
122
|
+
...webConditionOrder.filter((k) => keys.includes(k)),
|
|
123
|
+
...keys.filter((k) => !webConditionOrder.includes(k)),
|
|
124
|
+
];
|
|
125
|
+
for (const key of ordered) collectExportTargets(target[key], out);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The file a web build should compile for one `exports` entry: its `source`
|
|
130
|
+
* condition, else the first TypeScript file among its web conditions, else
|
|
131
|
+
* the first existing file (css, a prebuilt .mjs), so the package-name alias
|
|
132
|
+
* never swallows a subpath it cannot see.
|
|
133
|
+
*/
|
|
134
|
+
export function resolveExportSource(pkgDir: string, target: ExportTarget): string | undefined {
|
|
135
|
+
const candidates: string[] = [];
|
|
136
|
+
collectExportTargets(target, candidates);
|
|
137
|
+
const existing = candidates
|
|
138
|
+
.map((c) => path.resolve(pkgDir, c))
|
|
139
|
+
.filter((c) => !c.endsWith(".d.ts") && fs.existsSync(c) && fs.statSync(c).isFile());
|
|
140
|
+
return existing.find((c) => tsSourcePattern.test(c)) ?? existing[0];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The file a subpath declares when none of its targets is on disk yet, such
|
|
145
|
+
* as a prebuilt `./dist/...` asset in an unbuilt tree. Aliasing it keeps the
|
|
146
|
+
* bare package alias from rewriting the subpath into `src/index.ts/<subpath>`,
|
|
147
|
+
* so a missing build fails on the real path. Types-only subpaths get none.
|
|
148
|
+
*/
|
|
149
|
+
function declaredExportTarget(pkgDir: string, target: ExportTarget): string | undefined {
|
|
150
|
+
const candidates: string[] = [];
|
|
151
|
+
collectExportTargets(target, candidates);
|
|
152
|
+
const runtime = candidates.find((c) => !c.endsWith(".d.ts"));
|
|
153
|
+
return runtime ? path.resolve(pkgDir, runtime) : undefined;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Vite `resolve.alias` entries for one package's `exports` subpaths:
|
|
158
|
+
* `<name>/<subpath>` → its source file, and a `./dir/*` pattern → the directory.
|
|
159
|
+
*/
|
|
160
|
+
export function packageSubpathSourceAliases(
|
|
161
|
+
pkgName: string,
|
|
162
|
+
pkgDir: string,
|
|
163
|
+
exportsField: unknown,
|
|
164
|
+
): Record<string, string> {
|
|
165
|
+
const aliases: Record<string, string> = {};
|
|
166
|
+
if (!exportsField || typeof exportsField !== "object" || Array.isArray(exportsField)) {
|
|
167
|
+
return aliases;
|
|
168
|
+
}
|
|
169
|
+
for (const [key, target] of Object.entries(exportsField as Record<string, ExportTarget>)) {
|
|
170
|
+
if (key === "." || key === "./package.json" || !key.startsWith("./")) continue;
|
|
171
|
+
if (key.endsWith("/*")) {
|
|
172
|
+
const pattern = key.slice(2, -2);
|
|
173
|
+
if (pattern.includes("*")) continue;
|
|
174
|
+
const targets: string[] = [];
|
|
175
|
+
collectExportTargets(target, targets);
|
|
176
|
+
const dirTarget = targets.find((t) => t.endsWith("/*"));
|
|
177
|
+
if (!dirTarget) continue;
|
|
178
|
+
const dir = path.resolve(pkgDir, dirTarget.slice(0, -2));
|
|
179
|
+
if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()) {
|
|
180
|
+
aliases[`${pkgName}/${pattern}`] = dir;
|
|
181
|
+
}
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (key.includes("*")) continue;
|
|
185
|
+
const file = resolveExportSource(pkgDir, target) ?? declaredExportTarget(pkgDir, target);
|
|
186
|
+
if (file) aliases[`${pkgName}/${key.slice(2)}`] = file;
|
|
187
|
+
}
|
|
188
|
+
return aliases;
|
|
189
|
+
}
|
|
190
|
+
|
|
103
191
|
/**
|
|
104
192
|
* Map every public/* workspace package (and its subpath exports) to its TS
|
|
105
193
|
* source. Without this, packages whose exports point at dist (e.g. table)
|
|
@@ -138,12 +226,19 @@ export function workspaceSourceAliases(workspaceRoot?: string): Record<string, s
|
|
|
138
226
|
const main = resolveSource(pkgDir, "index");
|
|
139
227
|
if (main) aliases[pkg.name] = main;
|
|
140
228
|
if (pkg.exports && typeof pkg.exports === "object") {
|
|
229
|
+
const exported = packageSubpathSourceAliases(pkg.name, pkgDir, pkg.exports);
|
|
141
230
|
for (const key of Object.keys(pkg.exports)) {
|
|
142
231
|
if (key === "." || key === "./package.json" || path.extname(key)) continue;
|
|
143
232
|
const subpath = key.replace(/^\.\//, "");
|
|
144
|
-
const
|
|
233
|
+
const declared = exported[`${pkg.name}/${subpath}`];
|
|
234
|
+
const resolved =
|
|
235
|
+
(declared && tsSourcePattern.test(declared) ? declared : undefined) ??
|
|
236
|
+
resolveSource(pkgDir, subpath);
|
|
145
237
|
if (resolved) aliases[`${pkg.name}/${subpath}`] = resolved;
|
|
146
238
|
}
|
|
239
|
+
for (const [find, replacement] of Object.entries(exported)) {
|
|
240
|
+
aliases[find] ??= replacement;
|
|
241
|
+
}
|
|
147
242
|
}
|
|
148
243
|
} catch {}
|
|
149
244
|
}
|
package/types/dev.d.ts
CHANGED
|
@@ -9,6 +9,21 @@ export declare function lookupTranspileModules(packageDirs?: string[], { log }?:
|
|
|
9
9
|
export declare function lookupTamaguiModules(packageDirs?: string[], { log }?: LookupTamaguiModulesOptions): any[];
|
|
10
10
|
export declare function resolveConfig(keys?: string[]): Record<string, string | undefined>;
|
|
11
11
|
export declare function lookupProjectRoot(): string;
|
|
12
|
+
export type ExportTarget = string | null | ExportTarget[] | {
|
|
13
|
+
[condition: string]: ExportTarget;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* The file a web build should compile for one `exports` entry: its `source`
|
|
17
|
+
* condition, else the first TypeScript file among its web conditions, else
|
|
18
|
+
* the first existing file (css, a prebuilt .mjs), so the package-name alias
|
|
19
|
+
* never swallows a subpath it cannot see.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveExportSource(pkgDir: string, target: ExportTarget): string | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Vite `resolve.alias` entries for one package's `exports` subpaths:
|
|
24
|
+
* `<name>/<subpath>` → its source file, and a `./dir/*` pattern → the directory.
|
|
25
|
+
*/
|
|
26
|
+
export declare function packageSubpathSourceAliases(pkgName: string, pkgDir: string, exportsField: unknown): Record<string, string>;
|
|
12
27
|
/**
|
|
13
28
|
* Map every public/* workspace package (and its subpath exports) to its TS
|
|
14
29
|
* source. Without this, packages whose exports point at dist (e.g. table)
|
package/types/dev.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../src/dev.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAInC,MAAM,WAAW,6BAA6B;IAC5C,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,2BAA2B;IAC1C,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,wBAAgB,sBAAsB,CACpC,WAAW,CAAC,EAAE,MAAM,EAAE,EACtB,EAAE,GAAU,EAAE,GAAE,6BAAkC,SA0BnD;AAED,wBAAgB,oBAAoB,CAClC,WAAW,CAAC,EAAE,MAAM,EAAE,EACtB,EAAE,GAAU,EAAE,GAAE,2BAAgC,SA2BjD;AAED,wBAAgB,aAAa,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAQrF;AAGD,wBAAgB,iBAAiB,WAYhC;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../src/dev.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAInC,MAAM,WAAW,6BAA6B;IAC5C,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,2BAA2B;IAC1C,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,wBAAgB,sBAAsB,CACpC,WAAW,CAAC,EAAE,MAAM,EAAE,EACtB,EAAE,GAAU,EAAE,GAAE,6BAAkC,SA0BnD;AAED,wBAAgB,oBAAoB,CAClC,WAAW,CAAC,EAAE,MAAM,EAAE,EACtB,EAAE,GAAU,EAAE,GAAE,2BAAgC,SA2BjD;AAED,wBAAgB,aAAa,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAQrF;AAGD,wBAAgB,iBAAiB,WAYhC;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,IAAI,GAAG,YAAY,EAAE,GAAG;IAAE,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,CAAA;CAAE,CAAC;AAyBlG;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAO5F;AAeD;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,OAAO,GACpB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAyBxB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAqDrF;AA8BD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,wBAAwB,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAiCvE;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CASjD;AAED,cAAc,QAAQ,CAAC"}
|