foresthouse 1.1.0-dev.2 → 1.1.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 +1 -0
- package/dist/cli.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{react-GTkYqQLE.mjs → react-xFA5HmqF.mjs} +75 -142
- package/dist/react-xFA5HmqF.mjs.map +1 -0
- package/package.json +2 -1
- package/dist/react-GTkYqQLE.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/foresthouse)
|
|
4
4
|
[](https://codecov.io/gh/async3619/foresthouse)
|
|
5
|
+
[](https://codspeed.io/async3619/foresthouse?utm_source=badge)
|
|
5
6
|
[](https://www.npmjs.com/package/foresthouse)
|
|
6
7
|
|
|
7
8
|
`foresthouse` is a modern TypeScript-first Node.js CLI that can print source import trees, React usage trees, and package-manifest dependency trees.
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as printReactUsageTree, c as printPackageDependencyTree, f as analyzeReactUsage, g as analyzePackageDependencies, h as analyzePackageDependencyDiff, i as graphToSerializablePackageTree, m as isSourceCodeFile, n as graphToSerializableTree, o as printDependencyTree, p as analyzeDependencies, r as diffGraphToSerializablePackageTree, s as printPackageDependencyDiffTree, t as graphToSerializableReactTree } from "./react-
|
|
2
|
+
import { a as printReactUsageTree, c as printPackageDependencyTree, f as analyzeReactUsage, g as analyzePackageDependencies, h as analyzePackageDependencyDiff, i as graphToSerializablePackageTree, m as isSourceCodeFile, n as graphToSerializableTree, o as printDependencyTree, p as analyzeDependencies, r as diffGraphToSerializablePackageTree, s as printPackageDependencyDiffTree, t as graphToSerializableReactTree } from "./react-xFA5HmqF.mjs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import path from "node:path";
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as printReactUsageTree, c as printPackageDependencyTree, d as getReactUsageRoots, f as analyzeReactUsage, g as analyzePackageDependencies, h as analyzePackageDependencyDiff, i as graphToSerializablePackageTree, l as getFilteredUsages, n as graphToSerializableTree, o as printDependencyTree, p as analyzeDependencies, r as diffGraphToSerializablePackageTree, s as printPackageDependencyDiffTree, t as graphToSerializableReactTree, u as getReactUsageEntries } from "./react-
|
|
1
|
+
import { a as printReactUsageTree, c as printPackageDependencyTree, d as getReactUsageRoots, f as analyzeReactUsage, g as analyzePackageDependencies, h as analyzePackageDependencyDiff, i as graphToSerializablePackageTree, l as getFilteredUsages, n as graphToSerializableTree, o as printDependencyTree, p as analyzeDependencies, r as diffGraphToSerializablePackageTree, s as printPackageDependencyDiffTree, t as graphToSerializableReactTree, u as getReactUsageEntries } from "./react-xFA5HmqF.mjs";
|
|
2
2
|
export { analyzeDependencies, analyzePackageDependencies, analyzePackageDependencyDiff, analyzeReactUsage, diffGraphToSerializablePackageTree, getFilteredUsages, getReactUsageEntries, getReactUsageRoots, graphToSerializablePackageTree, graphToSerializableReactTree, graphToSerializableTree, printDependencyTree, printPackageDependencyDiffTree, printPackageDependencyTree, printReactUsageTree };
|
|
@@ -246,11 +246,11 @@ function listSubdirectories$1(directory) {
|
|
|
246
246
|
}
|
|
247
247
|
function createWorkspaceSegmentMatcher$1(segment) {
|
|
248
248
|
if (!segment.includes("*")) return (name) => name === segment;
|
|
249
|
-
const escapedSegment = escapeRegExp(segment).replaceAll("*", "[^/]*");
|
|
249
|
+
const escapedSegment = escapeRegExp$1(segment).replaceAll("*", "[^/]*");
|
|
250
250
|
const pattern = new RegExp(`^${escapedSegment}$`);
|
|
251
251
|
return (name) => pattern.test(name);
|
|
252
252
|
}
|
|
253
|
-
function escapeRegExp(value) {
|
|
253
|
+
function escapeRegExp$1(value) {
|
|
254
254
|
return value.replaceAll(/[|\\{}()[\]^$+?.]/g, "\\$&");
|
|
255
255
|
}
|
|
256
256
|
function isRecord$1(value) {
|
|
@@ -760,20 +760,6 @@ function getCommandErrorMessage(error) {
|
|
|
760
760
|
}
|
|
761
761
|
//#endregion
|
|
762
762
|
//#region src/typescript/program.ts
|
|
763
|
-
function createProgram(entryFile, compilerOptions, currentDirectory) {
|
|
764
|
-
const host = ts.createCompilerHost(compilerOptions, true);
|
|
765
|
-
host.getCurrentDirectory = () => currentDirectory;
|
|
766
|
-
if (ts.sys.realpath !== void 0) host.realpath = ts.sys.realpath;
|
|
767
|
-
return ts.createProgram({
|
|
768
|
-
rootNames: [entryFile],
|
|
769
|
-
options: compilerOptions,
|
|
770
|
-
host
|
|
771
|
-
});
|
|
772
|
-
}
|
|
773
|
-
function createSourceFile(filePath) {
|
|
774
|
-
const sourceText = fs.readFileSync(filePath, "utf8");
|
|
775
|
-
return ts.createSourceFile(filePath, sourceText, ts.ScriptTarget.Latest, true, getScriptKind(filePath));
|
|
776
|
-
}
|
|
777
763
|
function createModuleResolutionHost(currentDirectory) {
|
|
778
764
|
return {
|
|
779
765
|
fileExists: ts.sys.fileExists,
|
|
@@ -784,17 +770,6 @@ function createModuleResolutionHost(currentDirectory) {
|
|
|
784
770
|
...ts.sys.realpath === void 0 ? {} : { realpath: ts.sys.realpath }
|
|
785
771
|
};
|
|
786
772
|
}
|
|
787
|
-
function getScriptKind(filePath) {
|
|
788
|
-
switch (path.extname(filePath).toLowerCase()) {
|
|
789
|
-
case ".js":
|
|
790
|
-
case ".mjs":
|
|
791
|
-
case ".cjs": return ts.ScriptKind.JS;
|
|
792
|
-
case ".jsx": return ts.ScriptKind.JSX;
|
|
793
|
-
case ".tsx": return ts.ScriptKind.TSX;
|
|
794
|
-
case ".json": return ts.ScriptKind.JSON;
|
|
795
|
-
default: return ts.ScriptKind.TS;
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
773
|
//#endregion
|
|
799
774
|
//#region src/typescript/config.ts
|
|
800
775
|
const nearestConfigCache = /* @__PURE__ */ new Map();
|
|
@@ -1142,79 +1117,11 @@ function resolveExistingPath(cwd, entryFile) {
|
|
|
1142
1117
|
return normalizedPath;
|
|
1143
1118
|
}
|
|
1144
1119
|
//#endregion
|
|
1145
|
-
//#region src/analyzers/import/unused.ts
|
|
1146
|
-
function collectUnusedImports(sourceFile, checker) {
|
|
1147
|
-
const importUsage = /* @__PURE__ */ new Map();
|
|
1148
|
-
const symbolToImportDeclaration = /* @__PURE__ */ new Map();
|
|
1149
|
-
const importedLocalNames = /* @__PURE__ */ new Set();
|
|
1150
|
-
sourceFile.statements.forEach((statement) => {
|
|
1151
|
-
if (!ts.isImportDeclaration(statement) || statement.importClause === void 0) return;
|
|
1152
|
-
const identifiers = getImportBindingIdentifiers(statement.importClause);
|
|
1153
|
-
if (identifiers.length === 0) return;
|
|
1154
|
-
importUsage.set(statement, {
|
|
1155
|
-
canTrack: false,
|
|
1156
|
-
used: false
|
|
1157
|
-
});
|
|
1158
|
-
identifiers.forEach((identifier) => {
|
|
1159
|
-
importedLocalNames.add(identifier.text);
|
|
1160
|
-
const symbol = tryGetSymbolAtLocation(checker, identifier);
|
|
1161
|
-
if (symbol === void 0) return;
|
|
1162
|
-
symbolToImportDeclaration.set(symbol, statement);
|
|
1163
|
-
const state = importUsage.get(statement);
|
|
1164
|
-
if (state !== void 0) state.canTrack = true;
|
|
1165
|
-
});
|
|
1166
|
-
});
|
|
1167
|
-
function visit(node) {
|
|
1168
|
-
if (ts.isImportDeclaration(node)) return;
|
|
1169
|
-
if (ts.isIdentifier(node) && importedLocalNames.has(node.text) && isReferenceIdentifier(node)) {
|
|
1170
|
-
const symbol = tryGetSymbolAtLocation(checker, node);
|
|
1171
|
-
const declaration = symbol === void 0 ? void 0 : symbolToImportDeclaration.get(symbol);
|
|
1172
|
-
if (declaration !== void 0) {
|
|
1173
|
-
const state = importUsage.get(declaration);
|
|
1174
|
-
if (state !== void 0) state.used = true;
|
|
1175
|
-
}
|
|
1176
|
-
}
|
|
1177
|
-
ts.forEachChild(node, visit);
|
|
1178
|
-
}
|
|
1179
|
-
visit(sourceFile);
|
|
1180
|
-
return new Map([...importUsage.entries()].map(([declaration, state]) => [declaration, state.canTrack && !state.used]));
|
|
1181
|
-
}
|
|
1182
|
-
function getImportBindingIdentifiers(importClause) {
|
|
1183
|
-
const identifiers = [];
|
|
1184
|
-
if (importClause.name !== void 0) identifiers.push(importClause.name);
|
|
1185
|
-
const namedBindings = importClause.namedBindings;
|
|
1186
|
-
if (namedBindings === void 0) return identifiers;
|
|
1187
|
-
if (ts.isNamespaceImport(namedBindings)) {
|
|
1188
|
-
identifiers.push(namedBindings.name);
|
|
1189
|
-
return identifiers;
|
|
1190
|
-
}
|
|
1191
|
-
namedBindings.elements.forEach((element) => {
|
|
1192
|
-
identifiers.push(element.name);
|
|
1193
|
-
});
|
|
1194
|
-
return identifiers;
|
|
1195
|
-
}
|
|
1196
|
-
function isReferenceIdentifier(node) {
|
|
1197
|
-
const parent = node.parent;
|
|
1198
|
-
if (ts.isPropertyAccessExpression(parent) && parent.name === node) return false;
|
|
1199
|
-
if (ts.isQualifiedName(parent) && parent.right === node) return false;
|
|
1200
|
-
if (ts.isPropertyAssignment(parent) && parent.name === node) return false;
|
|
1201
|
-
if (ts.isBindingElement(parent) && parent.propertyName === node) return false;
|
|
1202
|
-
if (ts.isJsxAttribute(parent) && parent.name === node) return false;
|
|
1203
|
-
if (ts.isExportSpecifier(parent)) return parent.propertyName === node || parent.propertyName === void 0;
|
|
1204
|
-
return true;
|
|
1205
|
-
}
|
|
1206
|
-
function tryGetSymbolAtLocation(checker, node) {
|
|
1207
|
-
try {
|
|
1208
|
-
return checker.getSymbolAtLocation(node);
|
|
1209
|
-
} catch {
|
|
1210
|
-
return;
|
|
1211
|
-
}
|
|
1212
|
-
}
|
|
1213
|
-
//#endregion
|
|
1214
1120
|
//#region src/analyzers/import/references.ts
|
|
1215
|
-
function collectModuleReferences(
|
|
1121
|
+
function collectModuleReferences(filePath, sourceText, trackUnusedImports) {
|
|
1122
|
+
const parseResult = parseSync(filePath, sourceText);
|
|
1123
|
+
const mod = parseResult.module;
|
|
1216
1124
|
const references = /* @__PURE__ */ new Map();
|
|
1217
|
-
const unusedImports = checker === void 0 ? /* @__PURE__ */ new Map() : collectUnusedImports(sourceFile, checker);
|
|
1218
1125
|
function addReference(specifier, referenceKind, isTypeOnly, unused) {
|
|
1219
1126
|
const key = `${referenceKind}:${isTypeOnly ? "type" : "value"}:${specifier}`;
|
|
1220
1127
|
const existing = references.get(key);
|
|
@@ -1232,26 +1139,76 @@ function collectModuleReferences(sourceFile, checker) {
|
|
|
1232
1139
|
unused
|
|
1233
1140
|
});
|
|
1234
1141
|
}
|
|
1142
|
+
for (const imp of mod.staticImports) {
|
|
1143
|
+
const specifier = imp.moduleRequest.value;
|
|
1144
|
+
const isTypeOnly = imp.entries.length > 0 && imp.entries.every((e) => e.isType);
|
|
1145
|
+
let unused = false;
|
|
1146
|
+
if (trackUnusedImports && imp.entries.length > 0) {
|
|
1147
|
+
const localNames = imp.entries.map((e) => e.localName.value);
|
|
1148
|
+
unused = !isAnyNameUsedAfter(imp.end, localNames, sourceText);
|
|
1149
|
+
}
|
|
1150
|
+
addReference(specifier, "import", isTypeOnly, unused);
|
|
1151
|
+
}
|
|
1152
|
+
for (const exp of mod.staticExports) {
|
|
1153
|
+
const reExportEntry = exp.entries.find((e) => e.moduleRequest !== null);
|
|
1154
|
+
if (reExportEntry?.moduleRequest != null) {
|
|
1155
|
+
const specifier = reExportEntry.moduleRequest.value;
|
|
1156
|
+
addReference(specifier, "export", exp.entries.every((e) => e.isType), false);
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
for (const di of mod.dynamicImports) {
|
|
1160
|
+
const req = di.moduleRequest;
|
|
1161
|
+
if (req.start != null && req.end != null) {
|
|
1162
|
+
const specifier = extractStringLiteral(sourceText, req.start, req.end);
|
|
1163
|
+
if (specifier !== void 0) addReference(specifier, "dynamic-import", false, false);
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
if (sourceText.includes("require(")) collectRequireReferences(parseResult.program.body, addReference);
|
|
1167
|
+
return [...references.values()];
|
|
1168
|
+
}
|
|
1169
|
+
function isAnyNameUsedAfter(afterPosition, names, sourceText) {
|
|
1170
|
+
const restOfFile = sourceText.slice(afterPosition);
|
|
1171
|
+
return names.some((name) => {
|
|
1172
|
+
return new RegExp(`\\b${escapeRegExp(name)}\\b`).test(restOfFile);
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
function escapeRegExp(string) {
|
|
1176
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1177
|
+
}
|
|
1178
|
+
function extractStringLiteral(sourceText, start, end) {
|
|
1179
|
+
const raw = sourceText.slice(start, end);
|
|
1180
|
+
if (raw.startsWith("'") && raw.endsWith("'") || raw.startsWith("\"") && raw.endsWith("\"") || raw.startsWith("`") && raw.endsWith("`") && !raw.includes("${")) return raw.slice(1, -1);
|
|
1181
|
+
}
|
|
1182
|
+
function collectRequireReferences(body, addReference) {
|
|
1235
1183
|
function visit(node) {
|
|
1236
|
-
if (
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
const
|
|
1240
|
-
if (
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1184
|
+
if (node === null || node === void 0 || typeof node !== "object") return;
|
|
1185
|
+
const n = node;
|
|
1186
|
+
if (n.type === "TSImportEqualsDeclaration") {
|
|
1187
|
+
const moduleRef = n.moduleReference;
|
|
1188
|
+
if (moduleRef?.type === "TSExternalModuleReference") {
|
|
1189
|
+
const expr = moduleRef.expression;
|
|
1190
|
+
if (expr?.type === "Literal" && typeof expr.value === "string") {
|
|
1191
|
+
addReference(expr.value, "import-equals", false, false);
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1245
1194
|
}
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1195
|
+
}
|
|
1196
|
+
if (n.type === "CallExpression") {
|
|
1197
|
+
const callee = n.callee;
|
|
1198
|
+
const args = n.arguments;
|
|
1199
|
+
if (callee?.type === "Identifier" && callee.name === "require" && Array.isArray(args) && args.length === 1) {
|
|
1200
|
+
const arg = args[0];
|
|
1201
|
+
if (arg?.type === "Literal" && typeof arg.value === "string") {
|
|
1202
|
+
addReference(arg.value, "require", false, false);
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1249
1205
|
}
|
|
1250
1206
|
}
|
|
1251
|
-
|
|
1207
|
+
for (const value of Object.values(n)) if (Array.isArray(value)) {
|
|
1208
|
+
for (const item of value) if (item && typeof item === "object" && "type" in item) visit(item);
|
|
1209
|
+
} else if (value && typeof value === "object" && "type" in value) visit(value);
|
|
1252
1210
|
}
|
|
1253
|
-
visit(
|
|
1254
|
-
return [...references.values()];
|
|
1211
|
+
for (const stmt of body) visit(stmt);
|
|
1255
1212
|
}
|
|
1256
1213
|
//#endregion
|
|
1257
1214
|
//#region src/analyzers/import/resolver.ts
|
|
@@ -1351,8 +1308,6 @@ function buildDependencyGraph(entryConfigs, options) {
|
|
|
1351
1308
|
var DependencyGraphBuilder = class {
|
|
1352
1309
|
nodes = /* @__PURE__ */ new Map();
|
|
1353
1310
|
configCache = /* @__PURE__ */ new Map();
|
|
1354
|
-
programCache = /* @__PURE__ */ new Map();
|
|
1355
|
-
checkerCache = /* @__PURE__ */ new Map();
|
|
1356
1311
|
resolverCache = /* @__PURE__ */ new Map();
|
|
1357
1312
|
resolutionCache = /* @__PURE__ */ new Map();
|
|
1358
1313
|
packageRootCache = /* @__PURE__ */ new Map();
|
|
@@ -1376,18 +1331,13 @@ var DependencyGraphBuilder = class {
|
|
|
1376
1331
|
const normalizedPath = normalizeFilePath(filePath);
|
|
1377
1332
|
if (this.nodes.has(normalizedPath)) return;
|
|
1378
1333
|
const config = this.getConfigForFile(normalizedPath);
|
|
1379
|
-
const
|
|
1380
|
-
const dependencies = collectModuleReferences(this.getSourceFileForFile(normalizedPath, config), checker).map((reference) => this.resolveDependencyWithCache(reference, normalizedPath, config, entryConfigPath));
|
|
1334
|
+
const dependencies = collectModuleReferences(normalizedPath, fs.readFileSync(normalizedPath, "utf8"), this.options.trackUnusedImports).map((reference) => this.resolveDependencyWithCache(reference, normalizedPath, config, entryConfigPath));
|
|
1381
1335
|
this.nodes.set(normalizedPath, {
|
|
1382
1336
|
id: normalizedPath,
|
|
1383
1337
|
dependencies
|
|
1384
1338
|
});
|
|
1385
1339
|
for (const dependency of dependencies) if (dependency.kind === "source") this.visitFile(dependency.target, entryConfigPath);
|
|
1386
1340
|
}
|
|
1387
|
-
getSourceFileForFile(filePath, config) {
|
|
1388
|
-
if (!this.options.trackUnusedImports) return createSourceFile(filePath);
|
|
1389
|
-
return this.getProgramForFile(filePath, config).getSourceFile(filePath) ?? createSourceFile(filePath);
|
|
1390
|
-
}
|
|
1391
1341
|
getConfigForFile(filePath) {
|
|
1392
1342
|
const directory = path.dirname(filePath);
|
|
1393
1343
|
const cached = this.configCache.get(directory);
|
|
@@ -1396,29 +1346,12 @@ var DependencyGraphBuilder = class {
|
|
|
1396
1346
|
this.configCache.set(directory, loaded);
|
|
1397
1347
|
return loaded;
|
|
1398
1348
|
}
|
|
1399
|
-
|
|
1400
|
-
const cacheKey = this.getProgramCacheKey(filePath, config);
|
|
1401
|
-
const cached = this.programCache.get(cacheKey);
|
|
1402
|
-
if (cached !== void 0) return cached;
|
|
1403
|
-
const currentDirectory = config.path === void 0 ? path.dirname(filePath) : path.dirname(config.path);
|
|
1404
|
-
const program = createProgram(filePath, config.compilerOptions, currentDirectory);
|
|
1405
|
-
this.programCache.set(cacheKey, program);
|
|
1406
|
-
return program;
|
|
1407
|
-
}
|
|
1408
|
-
getCheckerForFile(filePath, config) {
|
|
1409
|
-
const cacheKey = this.getProgramCacheKey(filePath, config);
|
|
1410
|
-
const cached = this.checkerCache.get(cacheKey);
|
|
1411
|
-
if (cached !== void 0) return cached;
|
|
1412
|
-
const checker = this.getProgramForFile(filePath, config).getTypeChecker();
|
|
1413
|
-
this.checkerCache.set(cacheKey, checker);
|
|
1414
|
-
return checker;
|
|
1415
|
-
}
|
|
1416
|
-
getProgramCacheKey(filePath, config) {
|
|
1349
|
+
getConfigCacheKey(filePath, config) {
|
|
1417
1350
|
return config.path ?? `default:${path.dirname(filePath)}`;
|
|
1418
1351
|
}
|
|
1419
1352
|
getResolverForFile(filePath) {
|
|
1420
1353
|
const config = this.getConfigForFile(filePath);
|
|
1421
|
-
const cacheKey = this.
|
|
1354
|
+
const cacheKey = this.getConfigCacheKey(filePath, config);
|
|
1422
1355
|
const cached = this.resolverCache.get(cacheKey);
|
|
1423
1356
|
if (cached !== void 0) return cached;
|
|
1424
1357
|
const resolver = new ResolverFactory({
|
|
@@ -1472,7 +1405,7 @@ var DependencyGraphBuilder = class {
|
|
|
1472
1405
|
const scopeKey = entryConfigPath ?? "";
|
|
1473
1406
|
if (isPackageLikeImport(specifier)) {
|
|
1474
1407
|
const packageRoot = this.getPackageRoot(containingFile) ?? path.dirname(containingFile);
|
|
1475
|
-
return `package:${this.
|
|
1408
|
+
return `package:${this.getConfigCacheKey(containingFile, config)}:${packageRoot}:${specifier}:${scopeKey}`;
|
|
1476
1409
|
}
|
|
1477
1410
|
return `path:${path.dirname(containingFile)}:${specifier}:${scopeKey}`;
|
|
1478
1411
|
}
|
|
@@ -2892,4 +2825,4 @@ function formatReactNodeFilePath(filePath, kind, cwd) {
|
|
|
2892
2825
|
//#endregion
|
|
2893
2826
|
export { printReactUsageTree as a, printPackageDependencyTree as c, getReactUsageRoots as d, analyzeReactUsage as f, analyzePackageDependencies as g, analyzePackageDependencyDiff as h, graphToSerializablePackageTree as i, getFilteredUsages as l, isSourceCodeFile as m, graphToSerializableTree as n, printDependencyTree as o, analyzeDependencies as p, diffGraphToSerializablePackageTree as r, printPackageDependencyDiffTree as s, graphToSerializableReactTree as t, getReactUsageEntries as u };
|
|
2894
2827
|
|
|
2895
|
-
//# sourceMappingURL=react-
|
|
2828
|
+
//# sourceMappingURL=react-xFA5HmqF.mjs.map
|