@tamagui/metro-plugin 2.7.7 → 3.0.0-beta.643.1
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 +12 -0
- package/dist/cjs/babel.cjs +77 -0
- package/dist/cjs/compilerCache.cjs +237 -0
- package/dist/cjs/diagnostics.cjs +41 -0
- package/dist/cjs/frontend.cjs +870 -0
- package/dist/cjs/index.cjs +102 -0
- package/dist/cjs/lowering.cjs +109 -0
- package/dist/cjs/metroResolver.cjs +197 -0
- package/dist/cjs/transformOptions.cjs +35 -0
- package/dist/cjs/transformer.cjs +142 -0
- package/dist/cjs/zeroRuntime.cjs +140 -0
- package/dist/cjs/zeroSerializer.cjs +150 -0
- package/dist/esm/babel.mjs +52 -0
- package/dist/esm/babel.mjs.map +1 -0
- package/dist/esm/compilerCache.mjs +212 -0
- package/dist/esm/compilerCache.mjs.map +1 -0
- package/dist/esm/diagnostics.mjs +18 -0
- package/dist/esm/diagnostics.mjs.map +1 -0
- package/dist/esm/frontend.mjs +839 -0
- package/dist/esm/frontend.mjs.map +1 -0
- package/dist/esm/index.mjs +64 -22
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/lowering.mjs +89 -0
- package/dist/esm/lowering.mjs.map +1 -0
- package/dist/esm/metroResolver.mjs +173 -0
- package/dist/esm/metroResolver.mjs.map +1 -0
- package/dist/esm/transformOptions.mjs +14 -0
- package/dist/esm/transformOptions.mjs.map +1 -0
- package/dist/esm/transformer.mjs +119 -0
- package/dist/esm/transformer.mjs.map +1 -0
- package/dist/esm/zeroRuntime.mjs +105 -0
- package/dist/esm/zeroRuntime.mjs.map +1 -0
- package/dist/esm/zeroSerializer.mjs +123 -0
- package/dist/esm/zeroSerializer.mjs.map +1 -0
- package/package.json +33 -5
- package/src/babel.ts +87 -0
- package/src/compilerCache.ts +346 -0
- package/src/diagnostics.ts +47 -0
- package/src/frontend.ts +1178 -0
- package/src/index.ts +117 -14
- package/src/lowering.ts +136 -0
- package/src/metroResolver.ts +209 -0
- package/src/transformOptions.ts +36 -0
- package/src/transformer.ts +210 -0
- package/src/zeroRuntime.ts +212 -0
- package/src/zeroSerializer.ts +175 -0
- package/types/babel.d.ts +28 -0
- package/types/babel.d.ts.map +11 -0
- package/types/compilerCache.d.ts +63 -0
- package/types/compilerCache.d.ts.map +11 -0
- package/types/diagnostics.d.ts +16 -0
- package/types/diagnostics.d.ts.map +11 -0
- package/types/frontend.d.ts +73 -0
- package/types/frontend.d.ts.map +11 -0
- package/types/index.d.ts +49 -32
- package/types/index.d.ts.map +11 -1
- package/types/lowering.d.ts +20 -0
- package/types/lowering.d.ts.map +11 -0
- package/types/metroResolver.d.ts +21 -0
- package/types/metroResolver.d.ts.map +11 -0
- package/types/transformOptions.d.ts +13 -0
- package/types/transformOptions.d.ts.map +11 -0
- package/types/transformer.d.ts +26 -0
- package/types/transformer.d.ts.map +11 -0
- package/types/zeroRuntime.d.ts +75 -0
- package/types/zeroRuntime.d.ts.map +11 -0
- package/types/zeroSerializer.d.ts +6 -0
- package/types/zeroSerializer.d.ts.map +11 -0
- package/dist/cjs/index.js +0 -45
- package/dist/cjs/index.js.map +0 -6
- package/dist/esm/index.js +0 -25
- package/dist/esm/index.js.map +0 -1
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync, mkdirSync, realpathSync, renameSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
4
|
+
import { compileWithUserBabel, userBabelCacheKey } from "./babel.mjs";
|
|
5
|
+
import { METRO_COMPILER_CACHE_VERSION, MetroCompilerCache, MetroCompilerCacheError } from "./compilerCache.mjs";
|
|
6
|
+
import { formatMetroCompilerDiagnostic, metroDiagnostic } from "./diagnostics.mjs";
|
|
7
|
+
import { isCompilerSourceFile } from "./metroResolver.mjs";
|
|
8
|
+
import { applyMetroCompilerPlan } from "./lowering.mjs";
|
|
9
|
+
|
|
10
|
+
function createMetroCompilerTransformer(config) {
|
|
11
|
+
const moduleIdCache = /* @__PURE__ */ new Map();
|
|
12
|
+
const missWarned = /* @__PURE__ */ new Set();
|
|
13
|
+
function cacheModuleId(filename) {
|
|
14
|
+
let id = moduleIdCache.get(filename);
|
|
15
|
+
if (!id) {
|
|
16
|
+
const absolute = isAbsolute(filename) ? filename : resolve(config.projectRoot, filename);
|
|
17
|
+
try {
|
|
18
|
+
id = realpathSync(absolute);
|
|
19
|
+
} catch {
|
|
20
|
+
id = absolute;
|
|
21
|
+
}
|
|
22
|
+
moduleIdCache.set(filename, id);
|
|
23
|
+
}
|
|
24
|
+
return id;
|
|
25
|
+
}
|
|
26
|
+
function planEligible(moduleId) {
|
|
27
|
+
return isCompilerSourceFile(moduleId) && !moduleId.includes(`${join("node_modules")}`) && existsSync(moduleId);
|
|
28
|
+
}
|
|
29
|
+
const runtimeLiteral = config.runtimeLiteral ?? "full";
|
|
30
|
+
const inlineRuntimeLiteral = ({ types }) => ({ visitor: { MemberExpression(nodePath) {
|
|
31
|
+
const node = nodePath.node;
|
|
32
|
+
if (node.computed || !types.isIdentifier(node.property, { name: "TAMAGUI_RUNTIME" }) || !types.isMemberExpression(node.object) || node.object.computed || !types.isIdentifier(node.object.object, { name: "process" }) || !types.isIdentifier(node.object.property, { name: "env" })) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
nodePath.replaceWith(types.stringLiteral(runtimeLiteral));
|
|
36
|
+
} } });
|
|
37
|
+
return {
|
|
38
|
+
async transform(argsIn) {
|
|
39
|
+
const args = {
|
|
40
|
+
...argsIn,
|
|
41
|
+
plugins: [...argsIn.plugins ?? [], inlineRuntimeLiteral]
|
|
42
|
+
};
|
|
43
|
+
const platform = typeof args.options.platform === "string" ? args.options.platform : "default";
|
|
44
|
+
const cache = new MetroCompilerCache(join(config.cacheBaseRoot, platform));
|
|
45
|
+
let tamagui = {
|
|
46
|
+
cacheHit: false,
|
|
47
|
+
diagnostics: []
|
|
48
|
+
};
|
|
49
|
+
const moduleId = cacheModuleId(args.filename);
|
|
50
|
+
try {
|
|
51
|
+
const entry = await cache.read(moduleId, args.src, (reason, detail) => {
|
|
52
|
+
if (missWarned.has(moduleId) || !planEligible(moduleId)) return;
|
|
53
|
+
missWarned.add(moduleId);
|
|
54
|
+
const diagnostic = metroDiagnostic("metro/plan-miss", `Lowering plan lookup missed for ${moduleId} (${reason}${detail ? `: ${detail}` : ""}); module ships unlowered`, { moduleId });
|
|
55
|
+
tamagui.diagnostics.push(diagnostic);
|
|
56
|
+
console.warn(formatMetroCompilerDiagnostic(diagnostic, config.projectRoot));
|
|
57
|
+
});
|
|
58
|
+
if (entry) {
|
|
59
|
+
try {
|
|
60
|
+
const lowered = await applyMetroCompilerPlan({
|
|
61
|
+
...args,
|
|
62
|
+
filename: moduleId
|
|
63
|
+
}, entry.plan, config.originalBabelTransformerPath);
|
|
64
|
+
return {
|
|
65
|
+
...lowered.compiled.result,
|
|
66
|
+
metadata: {
|
|
67
|
+
...lowered.compiled.result.metadata,
|
|
68
|
+
tamagui: {
|
|
69
|
+
cacheHit: true,
|
|
70
|
+
diagnostics: entry.diagnostics,
|
|
71
|
+
lowering: lowered.lowering
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
} catch (error) {
|
|
76
|
+
const diagnostic = metroDiagnostic("metro/cache-corrupt", `Cached lowering plan for ${args.filename} could not be applied: ${error instanceof Error ? error.message : String(error)}`, { moduleId });
|
|
77
|
+
tamagui = {
|
|
78
|
+
cacheHit: true,
|
|
79
|
+
diagnostics: [...entry.diagnostics, diagnostic]
|
|
80
|
+
};
|
|
81
|
+
console.warn(formatMetroCompilerDiagnostic(diagnostic, config.projectRoot));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
} catch (error) {
|
|
85
|
+
if (!(error instanceof MetroCompilerCacheError)) throw error;
|
|
86
|
+
tamagui.diagnostics.push(error.diagnostic);
|
|
87
|
+
console.warn(formatMetroCompilerDiagnostic(error.diagnostic, config.projectRoot));
|
|
88
|
+
}
|
|
89
|
+
const compiled = await compileWithUserBabel(config.originalBabelTransformerPath, args);
|
|
90
|
+
return {
|
|
91
|
+
...compiled.result,
|
|
92
|
+
metadata: {
|
|
93
|
+
...compiled.result.metadata,
|
|
94
|
+
tamagui
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
},
|
|
98
|
+
getCacheKey() {
|
|
99
|
+
return createHash("sha256").update(`tamagui-metro-compiler-v${METRO_COMPILER_CACHE_VERSION}`).update("\0").update(runtimeLiteral).update("\0").update(userBabelCacheKey(config.originalBabelTransformerPath)).digest("hex");
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function writeMetroCompilerTransformerBridge(transformerFactoryPath, config) {
|
|
104
|
+
const serializedConfig = JSON.stringify(config);
|
|
105
|
+
const bridgeHash = createHash("sha256").update(transformerFactoryPath).update("\0").update(serializedConfig).digest("hex");
|
|
106
|
+
const directory = join(config.cacheBaseRoot, "bridge");
|
|
107
|
+
const bridgePath = join(directory, `${bridgeHash}.cjs`);
|
|
108
|
+
const temporaryPath = `${bridgePath}.${process.pid}.tmp`;
|
|
109
|
+
const source = `'use strict'
|
|
110
|
+
module.exports = require(${JSON.stringify(transformerFactoryPath)}).createMetroCompilerTransformer(${serializedConfig})
|
|
111
|
+
`;
|
|
112
|
+
mkdirSync(directory, { recursive: true });
|
|
113
|
+
writeFileSync(temporaryPath, source, "utf8");
|
|
114
|
+
renameSync(temporaryPath, bridgePath);
|
|
115
|
+
return bridgePath;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export { createMetroCompilerTransformer, writeMetroCompilerTransformerBridge };
|
|
119
|
+
//# sourceMappingURL=transformer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transformer.js","names":[],"sources":["esm/transformer.js"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, realpathSync, renameSync, writeFileSync } from \"node:fs\";\nimport { isAbsolute, join, resolve } from \"node:path\";\nimport {\n compileWithUserBabel,\n userBabelCacheKey\n} from \"./babel\";\nimport {\n METRO_COMPILER_CACHE_VERSION,\n MetroCompilerCache,\n MetroCompilerCacheError\n} from \"./compilerCache\";\nimport {\n formatMetroCompilerDiagnostic,\n metroDiagnostic\n} from \"./diagnostics\";\nimport { isCompilerSourceFile } from \"./metroResolver\";\nimport { applyMetroCompilerPlan } from \"./lowering\";\nfunction createMetroCompilerTransformer(config) {\n const moduleIdCache = /* @__PURE__ */ new Map();\n const missWarned = /* @__PURE__ */ new Set();\n function cacheModuleId(filename) {\n let id = moduleIdCache.get(filename);\n if (!id) {\n const absolute = isAbsolute(filename) ? filename : resolve(config.projectRoot, filename);\n try {\n id = realpathSync(absolute);\n } catch {\n id = absolute;\n }\n moduleIdCache.set(filename, id);\n }\n return id;\n }\n function planEligible(moduleId) {\n return isCompilerSourceFile(moduleId) && !moduleId.includes(`${join(\"node_modules\")}`) && existsSync(moduleId);\n }\n const runtimeLiteral = config.runtimeLiteral ?? \"full\";\n const inlineRuntimeLiteral = ({ types }) => ({\n visitor: {\n MemberExpression(nodePath) {\n const node = nodePath.node;\n if (node.computed || !types.isIdentifier(node.property, { name: \"TAMAGUI_RUNTIME\" }) || !types.isMemberExpression(node.object) || node.object.computed || !types.isIdentifier(node.object.object, { name: \"process\" }) || !types.isIdentifier(node.object.property, { name: \"env\" })) {\n return;\n }\n nodePath.replaceWith(types.stringLiteral(runtimeLiteral));\n }\n }\n });\n return {\n async transform(argsIn) {\n const args = {\n ...argsIn,\n plugins: [...argsIn.plugins ?? [], inlineRuntimeLiteral]\n };\n const platform = typeof args.options.platform === \"string\" ? args.options.platform : \"default\";\n const cache = new MetroCompilerCache(join(config.cacheBaseRoot, platform));\n let tamagui = {\n cacheHit: false,\n diagnostics: []\n };\n const moduleId = cacheModuleId(args.filename);\n try {\n const entry = await cache.read(moduleId, args.src, (reason, detail) => {\n if (missWarned.has(moduleId) || !planEligible(moduleId)) return;\n missWarned.add(moduleId);\n const diagnostic = metroDiagnostic(\n \"metro/plan-miss\",\n `Lowering plan lookup missed for ${moduleId} (${reason}${detail ? `: ${detail}` : \"\"}); module ships unlowered`,\n { moduleId }\n );\n tamagui.diagnostics.push(diagnostic);\n console.warn(formatMetroCompilerDiagnostic(diagnostic, config.projectRoot));\n });\n if (entry) {\n try {\n const lowered = await applyMetroCompilerPlan(\n { ...args, filename: moduleId },\n entry.plan,\n config.originalBabelTransformerPath\n );\n return {\n ...lowered.compiled.result,\n metadata: {\n ...lowered.compiled.result.metadata,\n tamagui: {\n cacheHit: true,\n diagnostics: entry.diagnostics,\n lowering: lowered.lowering\n }\n }\n };\n } catch (error) {\n const diagnostic = metroDiagnostic(\n \"metro/cache-corrupt\",\n `Cached lowering plan for ${args.filename} could not be applied: ${error instanceof Error ? error.message : String(error)}`,\n { moduleId }\n );\n tamagui = {\n cacheHit: true,\n diagnostics: [...entry.diagnostics, diagnostic]\n };\n console.warn(formatMetroCompilerDiagnostic(diagnostic, config.projectRoot));\n }\n }\n } catch (error) {\n if (!(error instanceof MetroCompilerCacheError)) throw error;\n tamagui.diagnostics.push(error.diagnostic);\n console.warn(formatMetroCompilerDiagnostic(error.diagnostic, config.projectRoot));\n }\n const compiled = await compileWithUserBabel(\n config.originalBabelTransformerPath,\n args\n );\n return {\n ...compiled.result,\n metadata: {\n ...compiled.result.metadata,\n tamagui\n }\n };\n },\n getCacheKey() {\n return createHash(\"sha256\").update(`tamagui-metro-compiler-v${METRO_COMPILER_CACHE_VERSION}`).update(\"\\0\").update(runtimeLiteral).update(\"\\0\").update(userBabelCacheKey(config.originalBabelTransformerPath)).digest(\"hex\");\n }\n };\n}\nfunction writeMetroCompilerTransformerBridge(transformerFactoryPath, config) {\n const serializedConfig = JSON.stringify(config);\n const bridgeHash = createHash(\"sha256\").update(transformerFactoryPath).update(\"\\0\").update(serializedConfig).digest(\"hex\");\n const directory = join(config.cacheBaseRoot, \"bridge\");\n const bridgePath = join(directory, `${bridgeHash}.cjs`);\n const temporaryPath = `${bridgePath}.${process.pid}.tmp`;\n const source = `'use strict'\nmodule.exports = require(${JSON.stringify(\n transformerFactoryPath\n )}).createMetroCompilerTransformer(${serializedConfig})\n`;\n mkdirSync(directory, { recursive: true });\n writeFileSync(temporaryPath, source, \"utf8\");\n renameSync(temporaryPath, bridgePath);\n return bridgePath;\n}\nexport {\n createMetroCompilerTransformer,\n writeMetroCompilerTransformerBridge\n};\n//# sourceMappingURL=transformer.js.map\n"],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import Static from "@tamagui/static";
|
|
5
|
+
|
|
6
|
+
const ZERO_CSS_FILENAME = "tamagui-zero.css";
|
|
7
|
+
const ZERO_ISLAND_DIRNAME = "tamagui-islands";
|
|
8
|
+
const normalizePath = (value) => value.replace(/\\/g, "/");
|
|
9
|
+
const zeroModuleKey = (value) => normalizePath(value).replace(/\.(?:js|jsx|ts|tsx|mjs|cjs)$/, "");
|
|
10
|
+
function islandFragmentPath(outDir, islandId) {
|
|
11
|
+
return path.join(outDir, ZERO_ISLAND_DIRNAME, `${islandId}.css`);
|
|
12
|
+
}
|
|
13
|
+
function islandBundleHashPath(outDir, islandId) {
|
|
14
|
+
return path.join(outDir, ZERO_ISLAND_DIRNAME, `${islandId}.hash`);
|
|
15
|
+
}
|
|
16
|
+
function createMetroZeroController(options, root, islandBuild, publicDirName) {
|
|
17
|
+
const resolved = Static.resolveZeroRuntimeSync(options, root);
|
|
18
|
+
if (resolved.mode === "off") return null;
|
|
19
|
+
Static.assertZeroIntegrationSupport("metro-web", resolved);
|
|
20
|
+
const cssHref = `/${ZERO_CSS_FILENAME}`;
|
|
21
|
+
const artifact = new Static.ZeroCSSArtifact(resolved.cssPath);
|
|
22
|
+
artifact.expectIslands(resolved.islands.map((island) => island.id));
|
|
23
|
+
const configPath = path.isAbsolute(options.config || "") ? options.config : path.resolve(root, options.config || "tamagui.config.ts");
|
|
24
|
+
for (const island of resolved.islands) {
|
|
25
|
+
Static.writeIslandModules({
|
|
26
|
+
island,
|
|
27
|
+
integration: "metro-web",
|
|
28
|
+
configPath,
|
|
29
|
+
scriptUrl: `/${ZERO_ISLAND_DIRNAME}/${island.id}.js`,
|
|
30
|
+
cssHref
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
resolved,
|
|
35
|
+
artifact,
|
|
36
|
+
cssHref,
|
|
37
|
+
root,
|
|
38
|
+
publicDir: path.join(root, publicDirName),
|
|
39
|
+
islandBuild,
|
|
40
|
+
bridges: /* @__PURE__ */ new Map(),
|
|
41
|
+
violations: [],
|
|
42
|
+
transformed: /* @__PURE__ */ new Set(),
|
|
43
|
+
erasedExports: /* @__PURE__ */ new Map(),
|
|
44
|
+
isEnforcing: resolved.mode === "enforce",
|
|
45
|
+
loaderIds: new Map(resolved.islands.map((island) => [zeroModuleKey(island.loader), island.id])),
|
|
46
|
+
islandModuleIds: new Map(resolved.islands.map((island) => [zeroModuleKey(island.module), island.id])),
|
|
47
|
+
configCSS: "",
|
|
48
|
+
plansRestoredFromCache: false
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function writeIslandRuntimeShims(outDir) {
|
|
52
|
+
const directory = path.join(outDir, "runtime-shim");
|
|
53
|
+
mkdirSync(directory, { recursive: true });
|
|
54
|
+
const shims = {};
|
|
55
|
+
for (const [specifier, segments] of Object.entries(Static.ISLAND_EXTERNAL_GLOBAL_PATHS)) {
|
|
56
|
+
const file = path.join(directory, `${specifier.replace(/[^a-zA-Z0-9]+/g, "_")}.js`);
|
|
57
|
+
const source = `// generated by @tamagui/metro-plugin zero-runtime. do not edit.
|
|
58
|
+
module.exports = globalThis.${segments.join(".")}
|
|
59
|
+
`;
|
|
60
|
+
if (!existsSync(file) || readFileSync(file, "utf8") !== source) {
|
|
61
|
+
writeFileSync(file, source);
|
|
62
|
+
}
|
|
63
|
+
shims[specifier] = file;
|
|
64
|
+
}
|
|
65
|
+
return shims;
|
|
66
|
+
}
|
|
67
|
+
function finalizeMetroZero(input) {
|
|
68
|
+
const { controller } = input;
|
|
69
|
+
const outDir = controller.resolved.outDir;
|
|
70
|
+
if (controller.islandBuild) {
|
|
71
|
+
const fragment = [...controller.artifact.islandCSS(controller.islandBuild)].join("");
|
|
72
|
+
const file = islandFragmentPath(outDir, controller.islandBuild);
|
|
73
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
74
|
+
writeFileSync(file, fragment);
|
|
75
|
+
writeFileSync(islandBundleHashPath(outDir, controller.islandBuild), createHash("sha256").update(input.bundleCode).digest("hex").slice(0, 16));
|
|
76
|
+
return {
|
|
77
|
+
cssPath: file,
|
|
78
|
+
hash: "",
|
|
79
|
+
islandOutputHashes: {}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
controller.artifact.setConfigCSS(controller.configCSS);
|
|
83
|
+
const islandOutputHashes = {};
|
|
84
|
+
for (const island of controller.resolved.islands) {
|
|
85
|
+
const fragment = islandFragmentPath(outDir, island.id);
|
|
86
|
+
if (!existsSync(fragment)) {
|
|
87
|
+
throw new Error(`[tamagui zero-runtime] island "${island.id}" has not been built. Build every declared island bundle before the zero entry so the one CSS artifact can be finalized.`);
|
|
88
|
+
}
|
|
89
|
+
controller.artifact.setIslandModuleCSS(island.id, island.module, readFileSync(fragment, "utf8"));
|
|
90
|
+
const hashFile = islandBundleHashPath(outDir, island.id);
|
|
91
|
+
islandOutputHashes[island.id] = existsSync(hashFile) ? readFileSync(hashFile, "utf8") : "";
|
|
92
|
+
}
|
|
93
|
+
const written = controller.artifact.write();
|
|
94
|
+
if (!written.complete) {
|
|
95
|
+
throw new Error(`[tamagui zero-runtime] cannot derive TAMAGUI_DID_OUTPUT_CSS: the generated CSS artifact is missing ${written.missing.join(", ")}`);
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
cssPath: written.path,
|
|
99
|
+
hash: written.hash,
|
|
100
|
+
islandOutputHashes
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export { ZERO_CSS_FILENAME, ZERO_ISLAND_DIRNAME, createMetroZeroController, finalizeMetroZero, islandBundleHashPath, islandFragmentPath, writeIslandRuntimeShims, zeroModuleKey };
|
|
105
|
+
//# sourceMappingURL=zeroRuntime.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zeroRuntime.js","names":[],"sources":["esm/zeroRuntime.js"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport Static from \"@tamagui/static\";\nconst ZERO_CSS_FILENAME = \"tamagui-zero.css\";\nconst ZERO_ISLAND_DIRNAME = \"tamagui-islands\";\nconst normalizePath = (value) => value.replace(/\\\\/g, \"/\");\nconst zeroModuleKey = (value) => normalizePath(value).replace(/\\.(?:js|jsx|ts|tsx|mjs|cjs)$/, \"\");\nfunction islandFragmentPath(outDir, islandId) {\n return path.join(outDir, ZERO_ISLAND_DIRNAME, `${islandId}.css`);\n}\nfunction islandBundleHashPath(outDir, islandId) {\n return path.join(outDir, ZERO_ISLAND_DIRNAME, `${islandId}.hash`);\n}\nfunction createMetroZeroController(options, root, islandBuild, publicDirName) {\n const resolved = Static.resolveZeroRuntimeSync(options, root);\n if (resolved.mode === \"off\") return null;\n Static.assertZeroIntegrationSupport(\"metro-web\", resolved);\n const cssHref = `/${ZERO_CSS_FILENAME}`;\n const artifact = new Static.ZeroCSSArtifact(resolved.cssPath);\n artifact.expectIslands(resolved.islands.map((island) => island.id));\n const configPath = path.isAbsolute(options.config || \"\") ? options.config : path.resolve(root, options.config || \"tamagui.config.ts\");\n for (const island of resolved.islands) {\n Static.writeIslandModules({\n island,\n integration: \"metro-web\",\n configPath,\n scriptUrl: `/${ZERO_ISLAND_DIRNAME}/${island.id}.js`,\n cssHref\n });\n }\n return {\n resolved,\n artifact,\n cssHref,\n root,\n publicDir: path.join(root, publicDirName),\n islandBuild,\n bridges: /* @__PURE__ */ new Map(),\n violations: [],\n transformed: /* @__PURE__ */ new Set(),\n erasedExports: /* @__PURE__ */ new Map(),\n isEnforcing: resolved.mode === \"enforce\",\n loaderIds: new Map(\n resolved.islands.map((island) => [zeroModuleKey(island.loader), island.id])\n ),\n islandModuleIds: new Map(\n resolved.islands.map((island) => [zeroModuleKey(island.module), island.id])\n ),\n configCSS: \"\",\n plansRestoredFromCache: false\n };\n}\nfunction writeIslandRuntimeShims(outDir) {\n const directory = path.join(outDir, \"runtime-shim\");\n mkdirSync(directory, { recursive: true });\n const shims = {};\n for (const [specifier, segments] of Object.entries(\n Static.ISLAND_EXTERNAL_GLOBAL_PATHS\n )) {\n const file = path.join(directory, `${specifier.replace(/[^a-zA-Z0-9]+/g, \"_\")}.js`);\n const source = `// generated by @tamagui/metro-plugin zero-runtime. do not edit.\nmodule.exports = globalThis.${segments.join(\n \".\"\n )}\n`;\n if (!existsSync(file) || readFileSync(file, \"utf8\") !== source) {\n writeFileSync(file, source);\n }\n shims[specifier] = file;\n }\n return shims;\n}\nfunction finalizeMetroZero(input) {\n const { controller } = input;\n const outDir = controller.resolved.outDir;\n if (controller.islandBuild) {\n const fragment = [...controller.artifact.islandCSS(controller.islandBuild)].join(\"\");\n const file = islandFragmentPath(outDir, controller.islandBuild);\n mkdirSync(path.dirname(file), { recursive: true });\n writeFileSync(file, fragment);\n writeFileSync(\n islandBundleHashPath(outDir, controller.islandBuild),\n createHash(\"sha256\").update(input.bundleCode).digest(\"hex\").slice(0, 16)\n );\n return { cssPath: file, hash: \"\", islandOutputHashes: {} };\n }\n controller.artifact.setConfigCSS(controller.configCSS);\n const islandOutputHashes = {};\n for (const island of controller.resolved.islands) {\n const fragment = islandFragmentPath(outDir, island.id);\n if (!existsSync(fragment)) {\n throw new Error(\n `[tamagui zero-runtime] island \"${island.id}\" has not been built. Build every declared island bundle before the zero entry so the one CSS artifact can be finalized.`\n );\n }\n controller.artifact.setIslandModuleCSS(\n island.id,\n island.module,\n readFileSync(fragment, \"utf8\")\n );\n const hashFile = islandBundleHashPath(outDir, island.id);\n islandOutputHashes[island.id] = existsSync(hashFile) ? readFileSync(hashFile, \"utf8\") : \"\";\n }\n const written = controller.artifact.write();\n if (!written.complete) {\n throw new Error(\n `[tamagui zero-runtime] cannot derive TAMAGUI_DID_OUTPUT_CSS: the generated CSS artifact is missing ${written.missing.join(\n \", \"\n )}`\n );\n }\n return { cssPath: written.path, hash: written.hash, islandOutputHashes };\n}\nexport {\n ZERO_CSS_FILENAME,\n ZERO_ISLAND_DIRNAME,\n createMetroZeroController,\n finalizeMetroZero,\n islandBundleHashPath,\n islandFragmentPath,\n writeIslandRuntimeShims,\n zeroModuleKey\n};\n//# sourceMappingURL=zeroRuntime.js.map\n"],"mappings":"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"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { gzipSync } from "node:zlib";
|
|
5
|
+
import Static from "@tamagui/static";
|
|
6
|
+
import { ZERO_CSS_FILENAME, finalizeMetroZero, writeIslandRuntimeShims } from "./zeroRuntime.mjs";
|
|
7
|
+
|
|
8
|
+
const requireFromPlugin = createRequire(typeof __filename === "string" ? __filename : import.meta.url);
|
|
9
|
+
const baseJSBundle = requireFromPlugin("metro/private/DeltaBundler/Serializers/baseJSBundle").default;
|
|
10
|
+
const bundleToString = requireFromPlugin("metro/private/lib/bundleToString").default;
|
|
11
|
+
function applyMetroZeroRuntime(metroConfig, zero) {
|
|
12
|
+
if (zero.islandBuild) {
|
|
13
|
+
const shims = writeIslandRuntimeShims(zero.resolved.outDir);
|
|
14
|
+
const userResolveRequest = metroConfig.resolver?.resolveRequest;
|
|
15
|
+
metroConfig.resolver = {
|
|
16
|
+
...metroConfig.resolver,
|
|
17
|
+
resolveRequest(context, moduleName, platform) {
|
|
18
|
+
const shim = shims[moduleName];
|
|
19
|
+
if (shim) return {
|
|
20
|
+
type: "sourceFile",
|
|
21
|
+
filePath: shim
|
|
22
|
+
};
|
|
23
|
+
return userResolveRequest ? userResolveRequest(context, moduleName, platform) : context.resolveRequest(context, moduleName, platform);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const userSerializer = metroConfig.serializer?.customSerializer;
|
|
28
|
+
metroConfig.serializer = {
|
|
29
|
+
...metroConfig.serializer,
|
|
30
|
+
async customSerializer(entryPoint, preModules, graph, opts) {
|
|
31
|
+
const receipt = checkGraph(zero, entryPoint, graph);
|
|
32
|
+
const output = userSerializer ? await userSerializer(entryPoint, preModules, graph, opts) : bundleToString(baseJSBundle(entryPoint, preModules, graph, opts)).code;
|
|
33
|
+
const finalized = finalizeMetroZero({
|
|
34
|
+
controller: zero,
|
|
35
|
+
bundleCode: typeof output === "string" ? output : ""
|
|
36
|
+
});
|
|
37
|
+
if (!zero.islandBuild) {
|
|
38
|
+
mkdirSync(zero.publicDir, { recursive: true });
|
|
39
|
+
const css = zero.artifact.css();
|
|
40
|
+
const published = path.join(zero.publicDir, ZERO_CSS_FILENAME);
|
|
41
|
+
writeFileSync(published, css);
|
|
42
|
+
const publishFailure = Static.checkGlobalCSSArtifact({
|
|
43
|
+
cssPath: published,
|
|
44
|
+
expectedCSS: css,
|
|
45
|
+
loadedModuleIds: [published],
|
|
46
|
+
importHint: ""
|
|
47
|
+
});
|
|
48
|
+
if (publishFailure) throw new Error(publishFailure.message);
|
|
49
|
+
receipt.cssArtifact = {
|
|
50
|
+
path: zero.cssHref,
|
|
51
|
+
hash: finalized.hash
|
|
52
|
+
};
|
|
53
|
+
receipt.gzip = {
|
|
54
|
+
[ZERO_CSS_FILENAME]: gzipSync(Buffer.from(css), { level: 9 }).length,
|
|
55
|
+
bundle: gzipSync(Buffer.from(typeof output === "string" ? output : ""), { level: 9 }).length
|
|
56
|
+
};
|
|
57
|
+
const bridgeManifest = Static.canonicalizeBridgeManifest(Object.fromEntries([...zero.bridges.entries()].sort(([left], [right]) => left < right ? -1 : 1)));
|
|
58
|
+
const identityInputs = {
|
|
59
|
+
runtimeLiteral: "zero",
|
|
60
|
+
target: "web",
|
|
61
|
+
configGeneration: Static.hashBridgeManifest(zero.configCSS),
|
|
62
|
+
cssHash: finalized.hash,
|
|
63
|
+
compilerVersion: Static.ZERO_COMPILER_VERSION,
|
|
64
|
+
islandEntries: zero.resolved.islands.map((island) => island.module),
|
|
65
|
+
bridgeManifestHash: Static.hashBridgeManifest(bridgeManifest),
|
|
66
|
+
islandOutputHashes: finalized.islandOutputHashes
|
|
67
|
+
};
|
|
68
|
+
receipt.identity = Static.hashZeroIdentity(identityInputs);
|
|
69
|
+
receipt.plansRestoredFromCache = zero.plansRestoredFromCache;
|
|
70
|
+
Static.writeZeroGraphReceipt(zero.resolved.outDir, "metro-zero", receipt);
|
|
71
|
+
writeFileSync(path.join(zero.resolved.outDir, "metro-zero.bridges.json"), `${JSON.stringify({
|
|
72
|
+
identity: receipt.identity,
|
|
73
|
+
identityInputs,
|
|
74
|
+
bridges: bridgeManifest
|
|
75
|
+
}, null, 2)}
|
|
76
|
+
`);
|
|
77
|
+
if (receipt.forbidden.length) {
|
|
78
|
+
throw new Error(Static.formatZeroGraphFailure(receipt));
|
|
79
|
+
}
|
|
80
|
+
console.info(` \u27A1 [tamagui zero-runtime] ${receipt.moduleCount} modules, 0 forbidden, css ${receipt.gzip[ZERO_CSS_FILENAME]} gzip, islands: ${zero.resolved.islands.map((island) => island.id).join(", ") || "none"}`);
|
|
81
|
+
}
|
|
82
|
+
return output;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function checkGraph(zero, entryPoint, graph) {
|
|
87
|
+
const modules = [];
|
|
88
|
+
const importerEdges = /* @__PURE__ */ new Map();
|
|
89
|
+
for (const [id, module] of graph.dependencies) {
|
|
90
|
+
const importers = [...module.inverseDependencies ?? []];
|
|
91
|
+
importerEdges.set(id, importers);
|
|
92
|
+
modules.push({
|
|
93
|
+
id,
|
|
94
|
+
importers
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
const escape = Static.erasedExportEscape({
|
|
98
|
+
integration: "metro-web",
|
|
99
|
+
transformed: zero.transformed,
|
|
100
|
+
erasedExports: zero.erasedExports,
|
|
101
|
+
importersOf: importerEdges
|
|
102
|
+
});
|
|
103
|
+
if (escape) throw new Error(escape);
|
|
104
|
+
const checked = Static.checkZeroGraph({
|
|
105
|
+
entries: [entryPoint],
|
|
106
|
+
modules,
|
|
107
|
+
importerEdges,
|
|
108
|
+
root: zero.resolved.root
|
|
109
|
+
});
|
|
110
|
+
return {
|
|
111
|
+
integration: "metro-web",
|
|
112
|
+
graph: zero.islandBuild ? "island" : "zero",
|
|
113
|
+
entries: [entryPoint],
|
|
114
|
+
moduleCount: modules.length,
|
|
115
|
+
tamaguiModules: checked.tamaguiModules,
|
|
116
|
+
forbidden: checked.forbidden,
|
|
117
|
+
cssArtifact: null,
|
|
118
|
+
identity: ""
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export { applyMetroZeroRuntime };
|
|
123
|
+
//# sourceMappingURL=zeroSerializer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zeroSerializer.js","names":[],"sources":["esm/zeroSerializer.js"],"sourcesContent":["import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport path from \"node:path\";\nimport { gzipSync } from \"node:zlib\";\nimport Static from \"@tamagui/static\";\nimport {\n finalizeMetroZero,\n writeIslandRuntimeShims,\n ZERO_CSS_FILENAME\n} from \"./zeroRuntime\";\nconst requireFromPlugin = createRequire(\n typeof __filename === \"string\" ? __filename : import.meta.url\n);\nconst baseJSBundle = requireFromPlugin(\n \"metro/private/DeltaBundler/Serializers/baseJSBundle\"\n).default;\nconst bundleToString = requireFromPlugin(\"metro/private/lib/bundleToString\").default;\nfunction applyMetroZeroRuntime(metroConfig, zero) {\n if (zero.islandBuild) {\n const shims = writeIslandRuntimeShims(zero.resolved.outDir);\n const userResolveRequest = metroConfig.resolver?.resolveRequest;\n metroConfig.resolver = {\n ...metroConfig.resolver,\n resolveRequest(context, moduleName, platform) {\n const shim = shims[moduleName];\n if (shim) return { type: \"sourceFile\", filePath: shim };\n return userResolveRequest ? userResolveRequest(context, moduleName, platform) : context.resolveRequest(context, moduleName, platform);\n }\n };\n }\n const userSerializer = metroConfig.serializer?.customSerializer;\n metroConfig.serializer = {\n ...metroConfig.serializer,\n async customSerializer(entryPoint, preModules, graph, opts) {\n const receipt = checkGraph(zero, entryPoint, graph);\n const output = userSerializer ? await userSerializer(entryPoint, preModules, graph, opts) : bundleToString(baseJSBundle(entryPoint, preModules, graph, opts)).code;\n const finalized = finalizeMetroZero({\n controller: zero,\n bundleCode: typeof output === \"string\" ? output : \"\"\n });\n if (!zero.islandBuild) {\n mkdirSync(zero.publicDir, { recursive: true });\n const css = zero.artifact.css();\n const published = path.join(zero.publicDir, ZERO_CSS_FILENAME);\n writeFileSync(published, css);\n const publishFailure = Static.checkGlobalCSSArtifact({\n cssPath: published,\n expectedCSS: css,\n loadedModuleIds: [published],\n importHint: \"\"\n });\n if (publishFailure) throw new Error(publishFailure.message);\n receipt.cssArtifact = { path: zero.cssHref, hash: finalized.hash };\n receipt.gzip = {\n [ZERO_CSS_FILENAME]: gzipSync(Buffer.from(css), { level: 9 }).length,\n bundle: gzipSync(Buffer.from(typeof output === \"string\" ? output : \"\"), {\n level: 9\n }).length\n };\n const bridgeManifest = Static.canonicalizeBridgeManifest(\n Object.fromEntries(\n [...zero.bridges.entries()].sort(([left], [right]) => left < right ? -1 : 1)\n )\n );\n const identityInputs = {\n runtimeLiteral: \"zero\",\n target: \"web\",\n configGeneration: Static.hashBridgeManifest(zero.configCSS),\n cssHash: finalized.hash,\n compilerVersion: Static.ZERO_COMPILER_VERSION,\n islandEntries: zero.resolved.islands.map((island) => island.module),\n bridgeManifestHash: Static.hashBridgeManifest(bridgeManifest),\n islandOutputHashes: finalized.islandOutputHashes\n };\n receipt.identity = Static.hashZeroIdentity(identityInputs);\n receipt.plansRestoredFromCache = zero.plansRestoredFromCache;\n Static.writeZeroGraphReceipt(zero.resolved.outDir, \"metro-zero\", receipt);\n writeFileSync(\n path.join(zero.resolved.outDir, \"metro-zero.bridges.json\"),\n `${JSON.stringify(\n { identity: receipt.identity, identityInputs, bridges: bridgeManifest },\n null,\n 2\n )}\n`\n );\n if (receipt.forbidden.length) {\n throw new Error(Static.formatZeroGraphFailure(receipt));\n }\n console.info(\n ` \\u27A1 [tamagui zero-runtime] ${receipt.moduleCount} modules, 0 forbidden, css ${receipt.gzip[ZERO_CSS_FILENAME]} gzip, islands: ${zero.resolved.islands.map((island) => island.id).join(\", \") || \"none\"}`\n );\n }\n return output;\n }\n };\n}\nfunction checkGraph(zero, entryPoint, graph) {\n const modules = [];\n const importerEdges = /* @__PURE__ */ new Map();\n for (const [id, module] of graph.dependencies) {\n const importers = [...module.inverseDependencies ?? []];\n importerEdges.set(id, importers);\n modules.push({ id, importers });\n }\n const escape = Static.erasedExportEscape({\n integration: \"metro-web\",\n transformed: zero.transformed,\n erasedExports: zero.erasedExports,\n importersOf: importerEdges\n });\n if (escape) throw new Error(escape);\n const checked = Static.checkZeroGraph({\n entries: [entryPoint],\n modules,\n importerEdges,\n root: zero.resolved.root\n });\n return {\n integration: \"metro-web\",\n graph: zero.islandBuild ? \"island\" : \"zero\",\n entries: [entryPoint],\n moduleCount: modules.length,\n tamaguiModules: checked.tamaguiModules,\n forbidden: checked.forbidden,\n cssArtifact: null,\n identity: \"\"\n };\n}\nexport {\n applyMetroZeroRuntime\n};\n//# sourceMappingURL=zeroSerializer.js.map\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,30 +1,58 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamagui/metro-plugin",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-beta.643.1",
|
|
4
4
|
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"source": "src/index.ts",
|
|
6
7
|
"files": [
|
|
7
8
|
"src",
|
|
8
9
|
"types",
|
|
9
10
|
"dist"
|
|
10
11
|
],
|
|
11
|
-
"main": "dist/cjs/index.
|
|
12
|
-
"module": "dist/esm",
|
|
12
|
+
"main": "dist/cjs/index.cjs",
|
|
13
|
+
"module": "dist/esm/index.mjs",
|
|
13
14
|
"types": "./types/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
"./package.json": "./package.json",
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./types/index.d.ts",
|
|
19
|
+
"browser": "./dist/esm/index.mjs",
|
|
20
|
+
"module": "./dist/esm/index.mjs",
|
|
21
|
+
"import": "./dist/esm/index.mjs",
|
|
22
|
+
"require": "./dist/cjs/index.cjs",
|
|
23
|
+
"default": "./dist/cjs/index.cjs"
|
|
24
|
+
},
|
|
25
|
+
"./transformer": {
|
|
26
|
+
"types": "./types/transformer.d.ts",
|
|
27
|
+
"import": "./dist/esm/transformer.mjs",
|
|
28
|
+
"require": "./dist/cjs/transformer.cjs",
|
|
29
|
+
"default": "./dist/cjs/transformer.cjs"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
14
32
|
"publishConfig": {
|
|
15
33
|
"access": "public"
|
|
16
34
|
},
|
|
17
35
|
"scripts": {
|
|
18
36
|
"build": "tamagui-build --skip-native",
|
|
37
|
+
"test:web": "vitest --run --config vitest.config.ts",
|
|
19
38
|
"watch": "tamagui-build --skip-native --watch",
|
|
20
39
|
"clean": "tamagui-build clean",
|
|
21
40
|
"clean:build": "tamagui-build clean:build"
|
|
22
41
|
},
|
|
23
42
|
"dependencies": {
|
|
24
|
-
"@
|
|
43
|
+
"@jridgewell/trace-mapping": "0.3.31",
|
|
44
|
+
"@tamagui/compiler-core": "3.0.0-beta.643.1",
|
|
45
|
+
"@tamagui/static": "3.0.0-beta.643.1",
|
|
46
|
+
"ignore": "^5.3.2"
|
|
25
47
|
},
|
|
26
48
|
"devDependencies": {
|
|
27
|
-
"@tamagui/build": "
|
|
49
|
+
"@tamagui/build": "3.0.0-beta.643.1",
|
|
50
|
+
"metro": "0.84.4",
|
|
51
|
+
"metro-resolver": "0.84.4"
|
|
52
|
+
},
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"metro": "^0.84.4",
|
|
55
|
+
"metro-resolver": "^0.84.4"
|
|
28
56
|
},
|
|
29
57
|
"repository": {
|
|
30
58
|
"type": "git",
|
package/src/babel.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto'
|
|
2
|
+
import { createRequire } from 'node:module'
|
|
3
|
+
import { dirname } from 'node:path'
|
|
4
|
+
|
|
5
|
+
export interface MetroBabelTransformArgs {
|
|
6
|
+
filename: string
|
|
7
|
+
src: string
|
|
8
|
+
options: Record<string, any>
|
|
9
|
+
plugins: unknown[]
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface MetroBabelTransformResult {
|
|
13
|
+
ast: Record<string, any>
|
|
14
|
+
metadata?: Record<string, any>
|
|
15
|
+
functionMap?: unknown
|
|
16
|
+
[key: string]: unknown
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface CompiledMetroModule {
|
|
20
|
+
code: string
|
|
21
|
+
map: Record<string, any>
|
|
22
|
+
result: MetroBabelTransformResult
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type BabelTransformer = {
|
|
26
|
+
transform(
|
|
27
|
+
args: MetroBabelTransformArgs
|
|
28
|
+
): MetroBabelTransformResult | Promise<MetroBabelTransformResult>
|
|
29
|
+
getCacheKey?(): string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function asTransformer(module: any, path: string): BabelTransformer {
|
|
33
|
+
const transformer = module?.default?.transform ? module.default : module
|
|
34
|
+
if (!transformer || typeof transformer.transform !== 'function') {
|
|
35
|
+
throw new Error(`Metro Babel transformer ${path} has no transform function`)
|
|
36
|
+
}
|
|
37
|
+
return transformer
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function loadMetroBabelTransformer(path: string): BabelTransformer {
|
|
41
|
+
return asTransformer(createRequire(path)(path), path)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function compileWithUserBabel(
|
|
45
|
+
transformerPath: string,
|
|
46
|
+
args: MetroBabelTransformArgs
|
|
47
|
+
): Promise<CompiledMetroModule> {
|
|
48
|
+
const transformer = loadMetroBabelTransformer(transformerPath)
|
|
49
|
+
const result = await transformer.transform(args)
|
|
50
|
+
if (!result?.ast) {
|
|
51
|
+
throw new Error(`Metro Babel transformer ${transformerPath} returned no AST`)
|
|
52
|
+
}
|
|
53
|
+
const requireFromTransformer = createRequire(transformerPath)
|
|
54
|
+
const generatorModule = requireFromTransformer('@babel/generator')
|
|
55
|
+
const generate = generatorModule.default ?? generatorModule
|
|
56
|
+
const generated = generate(
|
|
57
|
+
result.ast,
|
|
58
|
+
{
|
|
59
|
+
comments: true,
|
|
60
|
+
compact: false,
|
|
61
|
+
retainLines: true,
|
|
62
|
+
sourceFileName: args.filename,
|
|
63
|
+
sourceMaps: true,
|
|
64
|
+
},
|
|
65
|
+
args.src
|
|
66
|
+
)
|
|
67
|
+
if (!generated || typeof generated.code !== 'string') {
|
|
68
|
+
throw new Error(`Babel generator for ${transformerPath} returned no code`)
|
|
69
|
+
}
|
|
70
|
+
if (!generated.map) {
|
|
71
|
+
throw new Error(`Babel generator for ${transformerPath} returned no source map`)
|
|
72
|
+
}
|
|
73
|
+
return { code: generated.code, map: generated.map, result }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function userBabelCacheKey(transformerPath: string): string {
|
|
77
|
+
const transformer = loadMetroBabelTransformer(transformerPath)
|
|
78
|
+
return createHash('sha256')
|
|
79
|
+
.update(transformerPath)
|
|
80
|
+
.update('\0')
|
|
81
|
+
.update(transformer.getCacheKey?.() ?? '')
|
|
82
|
+
.digest('hex')
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function transformerDirectory(transformerPath: string): string {
|
|
86
|
+
return dirname(transformerPath)
|
|
87
|
+
}
|