transone-cli 0.6.3 → 0.10.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 +20 -3
- package/README.zh-CN.md +31 -0
- package/dist/app/analyze.d.ts +2 -1
- package/dist/app/components.d.ts +4 -0
- package/dist/app/types.d.ts +3 -0
- package/dist/{build-mp-vk5ap2cw.js → build-mp-y5pwahsy.js} +824 -271
- package/dist/build-mp-y5pwahsy.js.map +24 -0
- package/dist/build.d.ts +3 -1
- package/dist/bundle-inputs.d.ts +6 -0
- package/dist/cli.d.ts +4 -2
- package/dist/cli.js +49 -16
- package/dist/cli.js.map +3 -3
- package/dist/components/discovery.d.ts +5 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/report.d.ts +48 -0
- package/dist/components/resolution.d.ts +7 -0
- package/dist/components/types.d.ts +56 -0
- package/dist/components/web.d.ts +11 -0
- package/dist/config-inputs.d.ts +4 -0
- package/dist/create.d.ts +4 -4
- package/dist/document-styles.d.ts +7 -0
- package/dist/index-2g3e5sjt.js +3388 -0
- package/dist/index-2g3e5sjt.js.map +32 -0
- package/dist/index-d51tp4y9.js +1402 -0
- package/dist/index-d51tp4y9.js.map +11 -0
- package/dist/index-j4h0wd27.js +489 -0
- package/dist/index-j4h0wd27.js.map +14 -0
- package/dist/index-xgn9fbc6.js +298 -0
- package/dist/index-xgn9fbc6.js.map +13 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.js +12 -4
- package/dist/index.js.map +2 -2
- package/dist/mp/inheritance.d.ts +17 -0
- package/dist/mp/inline.d.ts +22 -0
- package/dist/mp/methods.d.ts +1 -0
- package/dist/mp/source.d.ts +11 -0
- package/dist/mp/types.d.ts +8 -0
- package/dist/output-transaction.d.ts +19 -0
- package/dist/{project-ybacfze8.js → project-6tft5e77.js} +38 -6
- package/dist/{project-ybacfze8.js.map → project-6tft5e77.js.map} +3 -3
- package/dist/project.d.ts +2 -1
- package/dist/safe-path.d.ts +1 -0
- package/dist/scaffold.d.ts +6 -0
- package/dist/target/types.d.ts +7 -6
- package/dist/target/web-target.d.ts +1 -0
- package/dist/types.d.ts +13 -1
- package/dist/web-bundle.d.ts +17 -0
- package/dist/web-styles.d.ts +9 -0
- package/package.json +2 -2
- package/dist/build-mp-vk5ap2cw.js.map +0 -22
- package/dist/index-8k9x2k6m.js +0 -2288
- package/dist/index-8k9x2k6m.js.map +0 -27
- package/dist/index-k1qfvp0y.js +0 -19
- package/dist/index-k1qfvp0y.js.map +0 -10
- package/dist/index-yb2wsc7f.js +0 -7
- package/dist/index-yb2wsc7f.js.map +0 -9
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
__require
|
|
4
|
+
} from "./index-j4h0wd27.js";
|
|
5
|
+
|
|
6
|
+
// src/mp/ts-loader.ts
|
|
7
|
+
var tsModule = null;
|
|
8
|
+
async function loadTypescript() {
|
|
9
|
+
if (tsModule) {
|
|
10
|
+
return tsModule;
|
|
11
|
+
}
|
|
12
|
+
tsModule = await import("typescript");
|
|
13
|
+
return tsModule;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// src/output-transaction.ts
|
|
17
|
+
import { lstat as lstat2, mkdir, mkdtemp, realpath as realpath2, rename, rm } from "fs/promises";
|
|
18
|
+
import {
|
|
19
|
+
basename,
|
|
20
|
+
dirname as dirname3,
|
|
21
|
+
isAbsolute as isAbsolute2,
|
|
22
|
+
join,
|
|
23
|
+
relative as relative2,
|
|
24
|
+
resolve as resolve3,
|
|
25
|
+
sep as sep2
|
|
26
|
+
} from "path";
|
|
27
|
+
|
|
28
|
+
// src/safe-path.ts
|
|
29
|
+
import { lstat, realpath } from "fs/promises";
|
|
30
|
+
import { dirname, isAbsolute, relative, resolve, sep } from "path";
|
|
31
|
+
async function assertSafeSubdirectory(root, path, errorMessage) {
|
|
32
|
+
try {
|
|
33
|
+
const canonicalRoot = await realpath(root);
|
|
34
|
+
const canonicalPath = await canonicalizePotentialPath(path);
|
|
35
|
+
if (!isStrictSubdirectory(canonicalRoot, canonicalPath)) {
|
|
36
|
+
throw new Error(errorMessage);
|
|
37
|
+
}
|
|
38
|
+
} catch {
|
|
39
|
+
throw new Error(errorMessage);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function assertSafeSubdirectoryDoesNotContain(root, path, protectedPath, errorMessage) {
|
|
43
|
+
try {
|
|
44
|
+
const lexicalPath = resolve(path);
|
|
45
|
+
const lexicalProtectedPath = resolve(protectedPath);
|
|
46
|
+
const canonicalRoot = await realpath(root);
|
|
47
|
+
const canonicalPath = await canonicalizePotentialPath(path);
|
|
48
|
+
const canonicalProtectedPath = await realpath(protectedPath);
|
|
49
|
+
if (!isStrictSubdirectory(canonicalRoot, canonicalPath) || isPathWithinOrEqual(lexicalPath, lexicalProtectedPath) || isPathWithinOrEqual(canonicalPath, canonicalProtectedPath)) {
|
|
50
|
+
throw new Error(errorMessage);
|
|
51
|
+
}
|
|
52
|
+
} catch {
|
|
53
|
+
throw new Error(errorMessage);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async function canonicalizePotentialPath(path) {
|
|
57
|
+
const ancestor = await findExistingAncestor(path);
|
|
58
|
+
const canonicalAncestor = await realpath(ancestor);
|
|
59
|
+
return resolve(canonicalAncestor, relative(ancestor, path));
|
|
60
|
+
}
|
|
61
|
+
async function findExistingAncestor(path) {
|
|
62
|
+
let candidate = path;
|
|
63
|
+
while (candidate !== dirname(candidate)) {
|
|
64
|
+
try {
|
|
65
|
+
await lstat(candidate);
|
|
66
|
+
return candidate;
|
|
67
|
+
} catch (error) {
|
|
68
|
+
if (!isMissingPathError(error)) {
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
candidate = dirname(candidate);
|
|
73
|
+
}
|
|
74
|
+
await lstat(candidate);
|
|
75
|
+
return candidate;
|
|
76
|
+
}
|
|
77
|
+
function isMissingPathError(error) {
|
|
78
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
79
|
+
}
|
|
80
|
+
function isStrictSubdirectory(root, path) {
|
|
81
|
+
const pathFromRoot = relative(root, path);
|
|
82
|
+
return pathFromRoot !== "" && pathFromRoot !== ".." && !pathFromRoot.startsWith(`..${sep}`) && !isAbsolute(pathFromRoot);
|
|
83
|
+
}
|
|
84
|
+
function isPathWithinOrEqual(parent, candidate) {
|
|
85
|
+
const pathFromParent = relative(parent, candidate);
|
|
86
|
+
return pathFromParent === "" || pathFromParent !== ".." && !pathFromParent.startsWith(`..${sep}`) && !isAbsolute(pathFromParent);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// src/config-inputs.ts
|
|
90
|
+
import { existsSync, readFileSync, realpathSync } from "fs";
|
|
91
|
+
import { dirname as dirname2, resolve as resolve2 } from "path";
|
|
92
|
+
import ts from "typescript";
|
|
93
|
+
function typeScriptConfigInputs(root, sources, explicitConfigs = []) {
|
|
94
|
+
const inputs = new Set;
|
|
95
|
+
const visited = new Set;
|
|
96
|
+
const directories = new Set([resolve2(root)]);
|
|
97
|
+
for (const source of sources) {
|
|
98
|
+
if (/\.[cm]?[jt]sx?$/i.test(source) && !/\.d\.[cm]?ts$/i.test(source)) {
|
|
99
|
+
directories.add(dirname2(resolve2(source)));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function visit(path) {
|
|
103
|
+
if (!existsSync(path))
|
|
104
|
+
return;
|
|
105
|
+
const identity = realpathSync(path);
|
|
106
|
+
if (visited.has(identity))
|
|
107
|
+
return;
|
|
108
|
+
visited.add(identity);
|
|
109
|
+
const parsed = ts.getParsedCommandLineOfConfigFile(path, {}, {
|
|
110
|
+
...ts.sys,
|
|
111
|
+
readDirectory: () => [],
|
|
112
|
+
readFile(file) {
|
|
113
|
+
const source = ts.sys.readFile(file);
|
|
114
|
+
if (source !== undefined)
|
|
115
|
+
inputs.add(resolve2(file));
|
|
116
|
+
return source;
|
|
117
|
+
},
|
|
118
|
+
onUnRecoverableConfigFileDiagnostic() {}
|
|
119
|
+
});
|
|
120
|
+
for (const reference of parsed?.projectReferences ?? []) {
|
|
121
|
+
visit(ts.resolveProjectReferencePath(reference));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
for (const config of explicitConfigs)
|
|
125
|
+
visit(resolve2(config));
|
|
126
|
+
for (const directory of directories) {
|
|
127
|
+
const config = ts.findConfigFile(directory, ts.sys.fileExists);
|
|
128
|
+
if (config)
|
|
129
|
+
visit(config);
|
|
130
|
+
}
|
|
131
|
+
return [...inputs];
|
|
132
|
+
}
|
|
133
|
+
function transoneConfigInputs(configFile) {
|
|
134
|
+
if (!configFile)
|
|
135
|
+
return [];
|
|
136
|
+
const inputs = new Set;
|
|
137
|
+
const pending = [configFile];
|
|
138
|
+
while (pending.length > 0) {
|
|
139
|
+
const file = pending.pop();
|
|
140
|
+
if (!existsSync(file))
|
|
141
|
+
continue;
|
|
142
|
+
const path = realpathSync(file);
|
|
143
|
+
if (inputs.has(path))
|
|
144
|
+
continue;
|
|
145
|
+
inputs.add(path);
|
|
146
|
+
if (!/\.[cm]?[jt]sx?$/i.test(path))
|
|
147
|
+
continue;
|
|
148
|
+
const loader = path.endsWith(".tsx") ? "tsx" : path.endsWith(".jsx") ? "jsx" : /\.[cm]?ts$/.test(path) ? "ts" : "js";
|
|
149
|
+
for (const dependency of new Bun.Transpiler({ loader }).scanImports(readFileSync(path, "utf8"))) {
|
|
150
|
+
try {
|
|
151
|
+
const imported = Bun.resolveSync(dependency.path, dirname2(path));
|
|
152
|
+
if (existsSync(imported))
|
|
153
|
+
pending.push(imported);
|
|
154
|
+
} catch {}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return [...inputs];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// src/output-transaction.ts
|
|
161
|
+
var publicationFileSystem = { rename, rm };
|
|
162
|
+
var outputQueues = new Map;
|
|
163
|
+
async function withBuildOutput(options, generate, fileSystem = publicationFileSystem) {
|
|
164
|
+
await assertSafeBuildOutput(options);
|
|
165
|
+
const key = await canonicalizePotentialPath(resolve3(options.outDir));
|
|
166
|
+
const previous = outputQueues.get(key) ?? Promise.resolve();
|
|
167
|
+
let release;
|
|
168
|
+
const active = new Promise((done) => {
|
|
169
|
+
release = done;
|
|
170
|
+
});
|
|
171
|
+
const queued = previous.then(() => active);
|
|
172
|
+
outputQueues.set(key, queued);
|
|
173
|
+
await previous;
|
|
174
|
+
let staging;
|
|
175
|
+
try {
|
|
176
|
+
await assertSafeBuildOutput(options);
|
|
177
|
+
const outDir = resolve3(options.outDir);
|
|
178
|
+
await mkdir(dirname3(outDir), { recursive: true });
|
|
179
|
+
staging = await mkdtemp(join(dirname3(outDir), `.${basename(outDir)}.transone-`));
|
|
180
|
+
const result = await generate(staging);
|
|
181
|
+
const assetsBuilt = result.assetsBuilt.map((asset) => {
|
|
182
|
+
const path = relative2(staging, resolve3(asset));
|
|
183
|
+
if (path === "" || !isWithin(staging, resolve3(asset))) {
|
|
184
|
+
throw new Error(`Build asset must be inside the staging directory: ${asset}`);
|
|
185
|
+
}
|
|
186
|
+
return resolve3(outDir, path);
|
|
187
|
+
});
|
|
188
|
+
await assertSafeBuildOutput(options);
|
|
189
|
+
await publish(staging, outDir, fileSystem);
|
|
190
|
+
return { ...result, outDir, assetsBuilt };
|
|
191
|
+
} finally {
|
|
192
|
+
try {
|
|
193
|
+
if (staging)
|
|
194
|
+
await cleanOwnedPath(staging, fileSystem);
|
|
195
|
+
} finally {
|
|
196
|
+
release();
|
|
197
|
+
if (outputQueues.get(key) === queued)
|
|
198
|
+
outputQueues.delete(key);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function buildOutputPath(outDir, path) {
|
|
203
|
+
const target = resolve3(outDir, path);
|
|
204
|
+
if (isAbsolute2(path) || target === resolve3(outDir) || !isWithin(resolve3(outDir), target)) {
|
|
205
|
+
throw new Error(`Build file must be inside the output directory: ${path}`);
|
|
206
|
+
}
|
|
207
|
+
return target;
|
|
208
|
+
}
|
|
209
|
+
function buildInputPaths(config, entries, additional = []) {
|
|
210
|
+
return [
|
|
211
|
+
...new Set([
|
|
212
|
+
...entries,
|
|
213
|
+
...entries.map(dirname3).filter((directory) => resolve3(directory) !== resolve3(config.root)),
|
|
214
|
+
join(config.root, "src"),
|
|
215
|
+
join(config.root, "public"),
|
|
216
|
+
config.configFile ?? join(config.root, "transone.config.ts"),
|
|
217
|
+
join(config.root, "tsconfig.json"),
|
|
218
|
+
...additional,
|
|
219
|
+
...transoneConfigInputs(config.configFile),
|
|
220
|
+
...typeScriptConfigInputs(config.root, [...entries, ...additional], config.library?.tsconfigs)
|
|
221
|
+
])
|
|
222
|
+
];
|
|
223
|
+
}
|
|
224
|
+
async function assertSafeBuildOutput(options) {
|
|
225
|
+
const outDir = resolve3(options.outDir);
|
|
226
|
+
const metadata = await existingMetadata(outDir);
|
|
227
|
+
if (metadata?.isSymbolicLink()) {
|
|
228
|
+
throw new Error(`Build output must not be a symbolic link: ${outDir}`);
|
|
229
|
+
}
|
|
230
|
+
const canonicalOutput = await canonicalizePotentialPath(outDir);
|
|
231
|
+
const canonicalRoot = await realpath2(options.root);
|
|
232
|
+
if (options.requireProjectSubdirectory) {
|
|
233
|
+
await assertSafeSubdirectory(options.root, outDir, "Build output must be a subdirectory of the project root");
|
|
234
|
+
}
|
|
235
|
+
if (dirname3(canonicalOutput) === canonicalOutput || isWithin(outDir, resolve3(options.root)) || isWithin(canonicalOutput, canonicalRoot)) {
|
|
236
|
+
throw new Error(`Build output must not replace a filesystem or project root: ${outDir}`);
|
|
237
|
+
}
|
|
238
|
+
const inputs = options.protectedPaths ?? [];
|
|
239
|
+
for (const input of new Set([
|
|
240
|
+
...inputs,
|
|
241
|
+
...typeScriptConfigInputs(options.root, inputs)
|
|
242
|
+
])) {
|
|
243
|
+
const lexicalInput = resolve3(input);
|
|
244
|
+
const canonicalInput = await canonicalizePotentialPath(lexicalInput);
|
|
245
|
+
if (isWithin(outDir, lexicalInput) || isWithin(lexicalInput, outDir) || isWithin(canonicalOutput, canonicalInput) || isWithin(canonicalInput, canonicalOutput)) {
|
|
246
|
+
throw new Error(`Build output must not overlap source, public, or configuration paths: ${outDir} (${input})`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
async function publish(staging, outDir, fileSystem) {
|
|
251
|
+
const backup = `${staging}.previous`;
|
|
252
|
+
const hadPrevious = await existingMetadata(outDir) !== undefined;
|
|
253
|
+
if (hadPrevious)
|
|
254
|
+
await fileSystem.rename(outDir, backup);
|
|
255
|
+
try {
|
|
256
|
+
await fileSystem.rename(staging, outDir);
|
|
257
|
+
} catch (publicationError) {
|
|
258
|
+
if (hadPrevious) {
|
|
259
|
+
try {
|
|
260
|
+
await fileSystem.rename(backup, outDir);
|
|
261
|
+
} catch (rollbackError) {
|
|
262
|
+
const failure = new Error(`Failed to publish build output and restore the previous output. Recover previous output from ${backup}. ` + `Publication: ${String(publicationError)}. Rollback: ${String(rollbackError)}`);
|
|
263
|
+
Object.assign(failure, { errors: [publicationError, rollbackError] });
|
|
264
|
+
throw failure;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
throw publicationError;
|
|
268
|
+
}
|
|
269
|
+
if (hadPrevious)
|
|
270
|
+
await cleanOwnedPath(backup, fileSystem);
|
|
271
|
+
}
|
|
272
|
+
async function cleanOwnedPath(path, fileSystem) {
|
|
273
|
+
try {
|
|
274
|
+
await fileSystem.rm(path, { recursive: true, force: true });
|
|
275
|
+
} catch (error) {
|
|
276
|
+
try {
|
|
277
|
+
console.warn(`[transone build] Output published or build stopped, but temporary output could not be removed: ${path}`, error);
|
|
278
|
+
} catch {}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
async function existingMetadata(path) {
|
|
282
|
+
try {
|
|
283
|
+
return await lstat2(path);
|
|
284
|
+
} catch (error) {
|
|
285
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT")
|
|
286
|
+
return;
|
|
287
|
+
throw error;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
function isWithin(parent, path) {
|
|
291
|
+
const child = relative2(parent, path);
|
|
292
|
+
return child === "" || child !== ".." && !child.startsWith(`..${sep2}`) && !isAbsolute2(child);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export { loadTypescript, assertSafeSubdirectory, assertSafeSubdirectoryDoesNotContain, withBuildOutput, buildOutputPath, buildInputPaths };
|
|
296
|
+
|
|
297
|
+
//# debugId=70BD0A7AE404EDD864756E2164756E21
|
|
298
|
+
//# sourceMappingURL=index-xgn9fbc6.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/mp/ts-loader.ts", "../src/output-transaction.ts", "../src/safe-path.ts", "../src/config-inputs.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type * as tsTypes from 'typescript';\n\nlet tsModule: typeof tsTypes | null = null;\n\n/**\n * 惰性加载 TypeScript 编译器 API:只有 `transone build --target mp-*` 路径\n * 才加载,常规 build/dev 不受影响。模块级缓存避免重复加载。\n */\nexport async function loadTypescript(): Promise<typeof tsTypes> {\n if (tsModule) {\n return tsModule;\n }\n tsModule = await import('typescript');\n return tsModule;\n}\n",
|
|
6
|
+
"import { lstat, mkdir, mkdtemp, realpath, rename, rm } from 'node:fs/promises';\nimport {\n basename,\n dirname,\n isAbsolute,\n join,\n relative,\n resolve,\n sep,\n} from 'node:path';\nimport { assertSafeSubdirectory, canonicalizePotentialPath } from './safe-path';\nimport type { BuildResult, ResolvedConfig } from './types';\nimport { transoneConfigInputs, typeScriptConfigInputs } from './config-inputs';\n\ninterface BuildOutputOptions {\n root: string;\n outDir: string;\n protectedPaths?: readonly string[];\n requireProjectSubdirectory?: boolean;\n}\n\n// Only publication operations are injectable: generation and path validation always\n// use the real filesystem. This also allows reliable recovery fault tests on OSes\n// where rename failures cannot otherwise be induced without a timing race.\ninterface PublicationFileSystem {\n rename: typeof rename;\n rm: typeof rm;\n}\nconst publicationFileSystem: PublicationFileSystem = { rename, rm };\nconst outputQueues = new Map<string, Promise<void>>();\n\n/** Build privately, then replace the destination; never clean another build's files. */\nexport async function withBuildOutput(\n options: BuildOutputOptions,\n generate: (stagingDirectory: string) => Promise<BuildResult>,\n fileSystem: PublicationFileSystem = publicationFileSystem\n): Promise<BuildResult> {\n await assertSafeBuildOutput(options);\n const key = await canonicalizePotentialPath(resolve(options.outDir));\n const previous = outputQueues.get(key) ?? Promise.resolve();\n let release!: () => void;\n const active = new Promise<void>((done) => {\n release = done;\n });\n const queued = previous.then(() => active);\n outputQueues.set(key, queued);\n await previous;\n let staging: string | undefined;\n try {\n // Recheck after waiting: a previous build or external editor may have changed it.\n await assertSafeBuildOutput(options);\n const outDir = resolve(options.outDir);\n await mkdir(dirname(outDir), { recursive: true });\n staging = await mkdtemp(\n join(dirname(outDir), `.${basename(outDir)}.transone-`)\n );\n const result = await generate(staging);\n const assetsBuilt = result.assetsBuilt.map((asset) => {\n const path = relative(staging!, resolve(asset));\n if (path === '' || !isWithin(staging!, resolve(asset))) {\n throw new Error(\n `Build asset must be inside the staging directory: ${asset}`\n );\n }\n return resolve(outDir, path);\n });\n await assertSafeBuildOutput(options);\n await publish(staging, outDir, fileSystem);\n return { ...result, outDir, assetsBuilt };\n } finally {\n try {\n if (staging) await cleanOwnedPath(staging, fileSystem);\n } finally {\n release();\n if (outputQueues.get(key) === queued) outputQueues.delete(key);\n }\n }\n}\n\n/** Resolve an artifact before writing: malformed routes/generator paths cannot escape. */\nexport function buildOutputPath(outDir: string, path: string): string {\n const target = resolve(outDir, path);\n if (\n isAbsolute(path) ||\n target === resolve(outDir) ||\n !isWithin(resolve(outDir), target)\n ) {\n throw new Error(`Build file must be inside the output directory: ${path}`);\n }\n return target;\n}\n\n/** Include source directories as well as entries so output cannot erase siblings. */\nexport function buildInputPaths(\n config: ResolvedConfig,\n entries: readonly string[],\n additional: readonly string[] = []\n): string[] {\n return [\n ...new Set([\n ...entries,\n ...entries\n .map(dirname)\n .filter((directory) => resolve(directory) !== resolve(config.root)),\n join(config.root, 'src'),\n join(config.root, 'public'),\n config.configFile ?? join(config.root, 'transone.config.ts'),\n join(config.root, 'tsconfig.json'),\n ...additional,\n ...transoneConfigInputs(config.configFile),\n ...typeScriptConfigInputs(\n config.root,\n [...entries, ...additional],\n config.library?.tsconfigs\n ),\n ]),\n ];\n}\n\nasync function assertSafeBuildOutput(\n options: BuildOutputOptions\n): Promise<void> {\n const outDir = resolve(options.outDir);\n const metadata = await existingMetadata(outDir);\n if (metadata?.isSymbolicLink()) {\n throw new Error(`Build output must not be a symbolic link: ${outDir}`);\n }\n const canonicalOutput = await canonicalizePotentialPath(outDir);\n const canonicalRoot = await realpath(options.root);\n if (options.requireProjectSubdirectory) {\n await assertSafeSubdirectory(\n options.root,\n outDir,\n 'Build output must be a subdirectory of the project root'\n );\n }\n if (\n dirname(canonicalOutput) === canonicalOutput ||\n isWithin(outDir, resolve(options.root)) ||\n isWithin(canonicalOutput, canonicalRoot)\n ) {\n throw new Error(\n `Build output must not replace a filesystem or project root: ${outDir}`\n );\n }\n const inputs = options.protectedPaths ?? [];\n for (const input of new Set([\n ...inputs,\n ...typeScriptConfigInputs(options.root, inputs),\n ])) {\n const lexicalInput = resolve(input);\n const canonicalInput = await canonicalizePotentialPath(lexicalInput);\n if (\n isWithin(outDir, lexicalInput) ||\n isWithin(lexicalInput, outDir) ||\n isWithin(canonicalOutput, canonicalInput) ||\n isWithin(canonicalInput, canonicalOutput)\n ) {\n throw new Error(\n `Build output must not overlap source, public, or configuration paths: ${outDir} (${input})`\n );\n }\n }\n}\n\nasync function publish(\n staging: string,\n outDir: string,\n fileSystem: PublicationFileSystem\n): Promise<void> {\n const backup = `${staging}.previous`;\n const hadPrevious = (await existingMetadata(outDir)) !== undefined;\n if (hadPrevious) await fileSystem.rename(outDir, backup);\n try {\n await fileSystem.rename(staging, outDir);\n } catch (publicationError) {\n if (hadPrevious) {\n try {\n await fileSystem.rename(backup, outDir);\n } catch (rollbackError) {\n const failure = new Error(\n `Failed to publish build output and restore the previous output. Recover previous output from ${backup}. ` +\n `Publication: ${String(publicationError)}. Rollback: ${String(rollbackError)}`\n );\n Object.assign(failure, { errors: [publicationError, rollbackError] });\n throw failure;\n }\n }\n throw publicationError;\n }\n // Publication has succeeded. A cleanup problem must not report a failed build\n // with changed live output; keep the recoverable backup and name it explicitly.\n if (hadPrevious) await cleanOwnedPath(backup, fileSystem);\n}\n\nasync function cleanOwnedPath(\n path: string,\n fileSystem: PublicationFileSystem\n): Promise<void> {\n try {\n await fileSystem.rm(path, { recursive: true, force: true });\n } catch (error) {\n try {\n console.warn(\n `[transone build] Output published or build stopped, but temporary output could not be removed: ${path}`,\n error\n );\n } catch {\n // Diagnostic hooks must not turn a published build into a failed one.\n }\n }\n}\n\nasync function existingMetadata(\n path: string\n): Promise<Awaited<ReturnType<typeof lstat>> | undefined> {\n try {\n return await lstat(path);\n } catch (error) {\n if (\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n error.code === 'ENOENT'\n )\n return undefined;\n throw error;\n }\n}\nfunction isWithin(parent: string, path: string): boolean {\n const child = relative(parent, path);\n return (\n child === '' ||\n (child !== '..' && !child.startsWith(`..${sep}`) && !isAbsolute(child))\n );\n}\n",
|
|
7
|
+
"import { lstat, realpath } from 'node:fs/promises';\nimport { dirname, isAbsolute, relative, resolve, sep } from 'node:path';\n\nexport async function assertSafeSubdirectory(\n root: string,\n path: string,\n errorMessage: string\n): Promise<void> {\n try {\n const canonicalRoot = await realpath(root);\n const canonicalPath = await canonicalizePotentialPath(path);\n\n if (!isStrictSubdirectory(canonicalRoot, canonicalPath)) {\n throw new Error(errorMessage);\n }\n } catch {\n throw new Error(errorMessage);\n }\n}\n\nexport async function assertSafeSubdirectoryDoesNotContain(\n root: string,\n path: string,\n protectedPath: string,\n errorMessage: string\n): Promise<void> {\n try {\n const lexicalPath = resolve(path);\n const lexicalProtectedPath = resolve(protectedPath);\n const canonicalRoot = await realpath(root);\n const canonicalPath = await canonicalizePotentialPath(path);\n const canonicalProtectedPath = await realpath(protectedPath);\n\n if (\n !isStrictSubdirectory(canonicalRoot, canonicalPath) ||\n isPathWithinOrEqual(lexicalPath, lexicalProtectedPath) ||\n isPathWithinOrEqual(canonicalPath, canonicalProtectedPath)\n ) {\n throw new Error(errorMessage);\n }\n } catch {\n throw new Error(errorMessage);\n }\n}\n\nexport async function canonicalizePotentialPath(path: string): Promise<string> {\n const ancestor = await findExistingAncestor(path);\n const canonicalAncestor = await realpath(ancestor);\n return resolve(canonicalAncestor, relative(ancestor, path));\n}\n\nasync function findExistingAncestor(path: string): Promise<string> {\n let candidate = path;\n\n while (candidate !== dirname(candidate)) {\n try {\n await lstat(candidate);\n return candidate;\n } catch (error: unknown) {\n if (!isMissingPathError(error)) {\n throw error;\n }\n }\n\n candidate = dirname(candidate);\n }\n\n await lstat(candidate);\n return candidate;\n}\n\nfunction isMissingPathError(error: unknown): boolean {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n error.code === 'ENOENT'\n );\n}\n\nfunction isStrictSubdirectory(root: string, path: string): boolean {\n const pathFromRoot = relative(root, path);\n return (\n pathFromRoot !== '' &&\n pathFromRoot !== '..' &&\n !pathFromRoot.startsWith(`..${sep}`) &&\n !isAbsolute(pathFromRoot)\n );\n}\n\nfunction isPathWithinOrEqual(parent: string, candidate: string): boolean {\n const pathFromParent = relative(parent, candidate);\n return (\n pathFromParent === '' ||\n (pathFromParent !== '..' &&\n !pathFromParent.startsWith(`..${sep}`) &&\n !isAbsolute(pathFromParent))\n );\n}\n",
|
|
8
|
+
"import { existsSync, readFileSync, realpathSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\nimport ts from 'typescript';\n\n/** Read config inheritance/references without enumerating sources or making a checker. */\nexport function typeScriptConfigInputs(\n root: string,\n sources: readonly string[],\n explicitConfigs: readonly string[] = []\n): string[] {\n const inputs = new Set<string>();\n const visited = new Set<string>();\n const directories = new Set([resolve(root)]);\n for (const source of sources) {\n if (/\\.[cm]?[jt]sx?$/i.test(source) && !/\\.d\\.[cm]?ts$/i.test(source)) {\n directories.add(dirname(resolve(source)));\n }\n }\n function visit(path: string): void {\n if (!existsSync(path)) return;\n const identity = realpathSync(path);\n if (visited.has(identity)) return;\n visited.add(identity);\n const parsed = ts.getParsedCommandLineOfConfigFile(\n path,\n {},\n {\n ...ts.sys,\n // Only option-file reads matter here; source discovery belongs to the build.\n readDirectory: () => [],\n readFile(file) {\n const source = ts.sys.readFile(file);\n if (source !== undefined) inputs.add(resolve(file));\n return source;\n },\n onUnRecoverableConfigFileDiagnostic() {\n // Build/config loading retains responsibility for reporting config errors.\n },\n }\n );\n for (const reference of parsed?.projectReferences ?? []) {\n visit(ts.resolveProjectReferencePath(reference));\n }\n }\n for (const config of explicitConfigs) visit(resolve(config));\n for (const directory of directories) {\n const config = ts.findConfigFile(directory, ts.sys.fileExists);\n if (config) visit(config);\n }\n return [...inputs];\n}\n\n/** Statically declared config modules are inputs too; never import/re-execute them. */\nexport function transoneConfigInputs(configFile: string | undefined): string[] {\n if (!configFile) return [];\n const inputs = new Set<string>();\n const pending = [configFile];\n while (pending.length > 0) {\n const file = pending.pop()!;\n if (!existsSync(file)) continue;\n const path = realpathSync(file);\n if (inputs.has(path)) continue;\n inputs.add(path);\n if (!/\\.[cm]?[jt]sx?$/i.test(path)) continue;\n const loader = path.endsWith('.tsx')\n ? 'tsx'\n : path.endsWith('.jsx')\n ? 'jsx'\n : /\\.[cm]?ts$/.test(path)\n ? 'ts'\n : 'js';\n for (const dependency of new Bun.Transpiler({ loader }).scanImports(\n readFileSync(path, 'utf8')\n )) {\n try {\n const imported = Bun.resolveSync(dependency.path, dirname(path));\n if (existsSync(imported)) pending.push(imported);\n } catch {\n // Builtins and unresolved external imports do not identify local files.\n }\n }\n }\n return [...inputs];\n}\n"
|
|
9
|
+
],
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "70BD0A7AE404EDD864756E2164756E21",
|
|
12
|
+
"names": []
|
|
13
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
export { defineConfig, resolveConfig } from './config';
|
|
2
2
|
export { build } from './build';
|
|
3
|
+
export { reportComponents, formatComponentSelectionReport, } from './components/report';
|
|
4
|
+
export type { ComponentReportLocation, ComponentReportCandidate, ComponentSelectionReportRow, ComponentSelectionReport, } from './components/report';
|
|
3
5
|
export { createProject } from './create';
|
|
4
6
|
export type { CreateProjectOptions, CreateProjectResult } from './create';
|
|
5
7
|
export { startDevServer } from './server';
|
|
6
8
|
export type { StartDevServerOptions } from './server';
|
|
7
|
-
export type { BuildOptions, BuildResult, BuildConfig, LibraryConfig, MiniProgramConfig, MiniProgramConfigMap, ResolvedLibraryConfig, ProxyOptions, ResolveConfigOptions, ResolvedConfig, ServerConfig, UserConfig, UserMiniProgramConfig, MpTargetType, TargetType, } from './types';
|
|
8
|
-
export {
|
|
9
|
+
export type { BuildOptions, BuildResult, BuildConfig, LibraryConfig, MiniProgramConfig, MiniProgramConfigMap, ResolvedLibraryConfig, ProxyOptions, ResolveConfigOptions, ResolvedConfig, ServerConfig, UserConfig, UserMiniProgramConfig, MpTargetType, TargetType, TargetInput, ComponentScanConfig, } from './types';
|
|
10
|
+
export { Platform } from 'transone/platform';
|
|
11
|
+
export { TARGET_TYPES, MP_TARGET_TYPES, isTargetType, isMpTargetType, } from './target/types';
|
|
9
12
|
export type { BuildTarget } from './target/types';
|
|
10
13
|
export { targetRegistry, TargetRegistry } from './target/registry';
|
|
11
14
|
export { WebTarget } from './target/web-target';
|
package/dist/index.js
CHANGED
|
@@ -8,18 +8,23 @@ import {
|
|
|
8
8
|
build,
|
|
9
9
|
createProject,
|
|
10
10
|
defineConfig,
|
|
11
|
+
formatComponentSelectionReport,
|
|
11
12
|
isMpTargetType,
|
|
12
13
|
isTargetType,
|
|
13
14
|
mpAlipayTarget,
|
|
14
15
|
mpBytedanceTarget,
|
|
15
16
|
mpWeixinTarget,
|
|
16
17
|
mpXiaohongshuTarget,
|
|
18
|
+
reportComponents,
|
|
17
19
|
resolveConfig,
|
|
18
20
|
startDevServer,
|
|
19
21
|
targetRegistry
|
|
20
|
-
} from "./index-
|
|
21
|
-
import"./index-
|
|
22
|
-
import"./index-
|
|
22
|
+
} from "./index-2g3e5sjt.js";
|
|
23
|
+
import"./index-d51tp4y9.js";
|
|
24
|
+
import"./index-xgn9fbc6.js";
|
|
25
|
+
import {
|
|
26
|
+
Platform
|
|
27
|
+
} from "./index-j4h0wd27.js";
|
|
23
28
|
// src/target/placeholder-target.ts
|
|
24
29
|
class PlaceholderTarget {
|
|
25
30
|
type;
|
|
@@ -39,22 +44,25 @@ export {
|
|
|
39
44
|
MP_TARGET_TYPES,
|
|
40
45
|
MpTarget,
|
|
41
46
|
PlaceholderTarget,
|
|
47
|
+
Platform,
|
|
42
48
|
TARGET_TYPES,
|
|
43
49
|
TargetRegistry,
|
|
44
50
|
WebTarget,
|
|
45
51
|
build,
|
|
46
52
|
createProject,
|
|
47
53
|
defineConfig,
|
|
54
|
+
formatComponentSelectionReport,
|
|
48
55
|
isMpTargetType,
|
|
49
56
|
isTargetType,
|
|
50
57
|
mpAlipayTarget,
|
|
51
58
|
mpBytedanceTarget,
|
|
52
59
|
mpWeixinTarget,
|
|
53
60
|
mpXiaohongshuTarget,
|
|
61
|
+
reportComponents,
|
|
54
62
|
resolveConfig,
|
|
55
63
|
startDevServer,
|
|
56
64
|
targetRegistry
|
|
57
65
|
};
|
|
58
66
|
|
|
59
|
-
//# debugId=
|
|
67
|
+
//# debugId=2A701458C6F6661464756E2164756E21
|
|
60
68
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import type { BuildOptions, BuildResult, ResolvedConfig } from '../types';\nimport type { BuildTarget, TargetType } from './types';\n\n/**\n * 尚未实现的编译目标占位。\n *\n * 在编译期快速报错并给出原因(延续 TransOne 的报错策略):\n * 让\"请求了未支持的目标端\"在构建开始时即失败,而不是产出残缺工程。\n */\nexport class PlaceholderTarget implements BuildTarget {\n public constructor(\n public readonly type: TargetType,\n public readonly label: string,\n private readonly plannedMilestone: string\n ) {}\n\n public async build(\n _config: ResolvedConfig,\n _options: BuildOptions\n ): Promise<BuildResult> {\n const available = ['web']\n .map((target) => `'${target}'`)\n .join(', ');\n throw new Error(\n `Target \"${this.type}\" (${this.label}) 尚未实现,预计在 ${this.plannedMilestone} 落地。` +\n `当前可用目标端:${available}。`\n );\n }\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AASO,MAAM,kBAAyC;AAAA,EAElC;AAAA,EACA;AAAA,EACC;AAAA,EAHZ,WAAW,CACA,MACA,OACC,kBACjB;AAAA,IAHgB;AAAA,IACA;AAAA,IACC;AAAA;AAAA,OAGN,MAAK,CAChB,SACA,UACsB;AAAA,IACtB,MAAM,YAAY,CAAC,KAAK,EACrB,IAAI,CAAC,WAAW,IAAI,SAAS,EAC7B,KAAK,IAAI;AAAA,IACZ,MAAM,IAAI,MACR,WAAW,KAAK,UAAU,KAAK,2DAAmB,KAAK,wCACrD,mDAAW,iBACf;AAAA;AAEJ;",
|
|
8
|
+
"debugId": "2A701458C6F6661464756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type ts from 'typescript';
|
|
2
|
+
import type { ClassReference } from '../components/types';
|
|
3
|
+
import type { ClassSource, CompileContext } from './types';
|
|
4
|
+
export declare function reference(context: CompileContext, source: ClassSource): ClassReference | undefined;
|
|
5
|
+
export declare function selected(context: CompileContext, ref: ClassReference): ClassSource;
|
|
6
|
+
export declare function ownedMethods(context: CompileContext, source: ClassSource): Array<{
|
|
7
|
+
owner: ClassSource;
|
|
8
|
+
declaration: ts.MethodDeclaration;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function ownedMethod(context: CompileContext, source: ClassSource, name: string): {
|
|
11
|
+
owner: ClassSource;
|
|
12
|
+
declaration: ts.MethodDeclaration;
|
|
13
|
+
} | undefined;
|
|
14
|
+
export declare function parentSource(context: CompileContext, source: ClassSource): ClassSource | undefined;
|
|
15
|
+
export declare function stableTag(context: CompileContext, source: ClassSource): string;
|
|
16
|
+
/** Static constants retain their declaring module even when imported through aliases. */
|
|
17
|
+
export declare function moduleConstants(context: CompileContext, source: ClassSource): Map<string, ts.Expression>;
|
package/dist/mp/inline.d.ts
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
import type * as tsTypes from 'typescript';
|
|
1
2
|
import type { ClassSource, CompileContext } from './types';
|
|
2
3
|
/** 收集 entry 源码需要内联的相对模块 JS 文本(依赖先于使用方)。 */
|
|
3
4
|
export declare function collectInlineModules(context: CompileContext, classSource: ClassSource): string[];
|
|
5
|
+
/** Link only declarations referenced by compiled methods. Checker symbols preserve the
|
|
6
|
+
* lexical module of every parent method and avoid same-name helper collisions. */
|
|
7
|
+
export declare class MethodModuleLinker {
|
|
8
|
+
private readonly context;
|
|
9
|
+
private readonly names;
|
|
10
|
+
private readonly entries;
|
|
11
|
+
private readonly dependencies;
|
|
12
|
+
constructor(context: CompileContext);
|
|
13
|
+
modules(): string[];
|
|
14
|
+
/** Pure unused closures/constants need no execution and must not pull their
|
|
15
|
+
* otherwise unreachable platform imports into the initialization graph. */
|
|
16
|
+
private mayInitialize;
|
|
17
|
+
private orderedDependencies;
|
|
18
|
+
/** Initialization next to component families is retained only when it can
|
|
19
|
+
* touch selected module values. This excludes unused platform-only clients. */
|
|
20
|
+
private referencesLinkedValue;
|
|
21
|
+
private linkFrom;
|
|
22
|
+
rewrite<T extends tsTypes.Node>(node: T, source: tsTypes.SourceFile): T;
|
|
23
|
+
private requestReference;
|
|
24
|
+
private link;
|
|
25
|
+
}
|
package/dist/mp/methods.d.ts
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type tsTypes from 'typescript';
|
|
2
|
+
import type { ClassReference } from '../components/types';
|
|
3
|
+
import type { ClassSource, CompileContext } from './types';
|
|
4
|
+
/** Declaration identities remain owned by the build index. Their executable MP
|
|
5
|
+
* members come from the installed package's existing `source` contract. */
|
|
6
|
+
export declare function runtimeOwner(context: CompileContext, reference: ClassReference): ClassSource;
|
|
7
|
+
/** The old package.source path can be absent from the shared index entirely. */
|
|
8
|
+
export declare function loadSourceExport(context: CompileContext, entry: string, names: readonly string[]): ClassSource;
|
|
9
|
+
/** Actual package source owns its checker, including imported helpers and locals.
|
|
10
|
+
* The shared index still handles all normal application/selection references. */
|
|
11
|
+
export declare function sourceSymbolAt(context: CompileContext, node: tsTypes.Node, source?: tsTypes.SourceFile): tsTypes.Symbol | undefined;
|
package/dist/mp/types.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type * as tsTypes from 'typescript';
|
|
2
|
+
import type { ComponentIndex, ClassReference } from '../components/types';
|
|
2
3
|
import type { MpDialect } from './dialect';
|
|
3
4
|
export type UnitKind = 'page' | 'component';
|
|
4
5
|
/** 一个 Component 子类的定位信息:文件 + 类声明。 */
|
|
5
6
|
export interface ClassSource {
|
|
7
|
+
reference?: ClassReference;
|
|
8
|
+
logical?: ClassReference;
|
|
6
9
|
filePath: string;
|
|
7
10
|
source: tsTypes.SourceFile;
|
|
8
11
|
declaration: tsTypes.ClassLikeDeclaration;
|
|
@@ -45,6 +48,11 @@ export interface CompiledUnit {
|
|
|
45
48
|
}
|
|
46
49
|
/** 编译过程中的上下文:跨模块共享的文件缓存与产物缓存。 */
|
|
47
50
|
export interface CompileContext {
|
|
51
|
+
/** Per-build checker/source fallback for installed packages publishing types + source. */
|
|
52
|
+
sourcePrograms?: Map<string, tsTypes.Program>;
|
|
53
|
+
packageSources?: Map<string, ClassSource>;
|
|
54
|
+
packageComponentSources?: Set<tsTypes.SourceFile>;
|
|
55
|
+
index?: ComponentIndex;
|
|
48
56
|
ts: typeof tsTypes;
|
|
49
57
|
root: string;
|
|
50
58
|
/** 已解析的源文件缓存(绝对路径 -> SourceFile)。 */
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { rename, rm } from 'node:fs/promises';
|
|
2
|
+
import type { BuildResult, ResolvedConfig } from './types';
|
|
3
|
+
interface BuildOutputOptions {
|
|
4
|
+
root: string;
|
|
5
|
+
outDir: string;
|
|
6
|
+
protectedPaths?: readonly string[];
|
|
7
|
+
requireProjectSubdirectory?: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface PublicationFileSystem {
|
|
10
|
+
rename: typeof rename;
|
|
11
|
+
rm: typeof rm;
|
|
12
|
+
}
|
|
13
|
+
/** Build privately, then replace the destination; never clean another build's files. */
|
|
14
|
+
export declare function withBuildOutput(options: BuildOutputOptions, generate: (stagingDirectory: string) => Promise<BuildResult>, fileSystem?: PublicationFileSystem): Promise<BuildResult>;
|
|
15
|
+
/** Resolve an artifact before writing: malformed routes/generator paths cannot escape. */
|
|
16
|
+
export declare function buildOutputPath(outDir: string, path: string): string;
|
|
17
|
+
/** Include source directories as well as entries so output cannot erase siblings. */
|
|
18
|
+
export declare function buildInputPaths(config: ResolvedConfig, entries: readonly string[], additional?: readonly string[]): string[];
|
|
19
|
+
export {};
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import
|
|
2
|
+
import {
|
|
3
|
+
createWebComponentContext,
|
|
4
|
+
createWebStylesPlugin
|
|
5
|
+
} from "./index-d51tp4y9.js";
|
|
6
|
+
import"./index-j4h0wd27.js";
|
|
3
7
|
|
|
4
8
|
// ../transone/lib/dom/index.ts
|
|
5
9
|
class DOMException extends Error {
|
|
@@ -2380,11 +2384,14 @@ function toCamelCase(value) {
|
|
|
2380
2384
|
}
|
|
2381
2385
|
|
|
2382
2386
|
// src/project.ts
|
|
2387
|
+
import { mkdtemp, rm } from "fs/promises";
|
|
2388
|
+
import { tmpdir } from "os";
|
|
2389
|
+
import { join } from "path";
|
|
2383
2390
|
var PROJECT_GLOBAL_KEYS = [...DOM_GLOBAL_KEYS, "__APP__"];
|
|
2384
2391
|
var projectDomQueue = Promise.resolve();
|
|
2385
|
-
async function renderProjectHtml(config, options, entry = config.entry, route = "/") {
|
|
2392
|
+
async function renderProjectHtml(config, options, entry = config.entry, route = "/", components) {
|
|
2386
2393
|
return withProjectDom(async () => {
|
|
2387
|
-
const module = await importProjectEntry(entry);
|
|
2394
|
+
const module = await importProjectEntry(entry, config, components);
|
|
2388
2395
|
const app = module.app;
|
|
2389
2396
|
if (!app || typeof app.renderHtmlDocument !== "function") {
|
|
2390
2397
|
throw new Error(`TransOne entry ${entry} must export an app with renderHtmlDocument()`);
|
|
@@ -2422,7 +2429,32 @@ async function runWithProjectDom(callback, route, basePath) {
|
|
|
2422
2429
|
}
|
|
2423
2430
|
}
|
|
2424
2431
|
var projectEntrySequence = 0;
|
|
2425
|
-
async function importProjectEntry(entry) {
|
|
2432
|
+
async function importProjectEntry(entry, config, context) {
|
|
2433
|
+
const components = context ?? createWebComponentContext(config, entry);
|
|
2434
|
+
if (components.active) {
|
|
2435
|
+
const directory = await mkdtemp(join(tmpdir(), "transone-ssr-"));
|
|
2436
|
+
try {
|
|
2437
|
+
const result = await Bun.build({
|
|
2438
|
+
entrypoints: [components.entrypoint],
|
|
2439
|
+
target: "bun",
|
|
2440
|
+
format: "esm",
|
|
2441
|
+
outdir: directory,
|
|
2442
|
+
naming: "entry.js",
|
|
2443
|
+
packages: "bundle",
|
|
2444
|
+
plugins: [
|
|
2445
|
+
components.plugin,
|
|
2446
|
+
createWebStylesPlugin(new Set, components.transform, false)
|
|
2447
|
+
],
|
|
2448
|
+
throw: false
|
|
2449
|
+
});
|
|
2450
|
+
if (!result.success)
|
|
2451
|
+
throw new Error(`Failed to build platform document: ${result.logs.map((log) => log.message).join(`
|
|
2452
|
+
`)}`);
|
|
2453
|
+
return await import(join(directory, "entry.js"));
|
|
2454
|
+
} finally {
|
|
2455
|
+
await rm(directory, { recursive: true, force: true });
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2426
2458
|
projectEntrySequence += 1;
|
|
2427
2459
|
return await import(`${entry}?transone_entry=${projectEntrySequence}`);
|
|
2428
2460
|
}
|
|
@@ -2446,5 +2478,5 @@ export {
|
|
|
2446
2478
|
renderProjectHtml
|
|
2447
2479
|
};
|
|
2448
2480
|
|
|
2449
|
-
//# debugId=
|
|
2450
|
-
//# sourceMappingURL=project-
|
|
2481
|
+
//# debugId=554C8D2F6BAAC94864756E2164756E21
|
|
2482
|
+
//# sourceMappingURL=project-6tft5e77.js.map
|