@lark-apaas/fullstack-cli 1.1.61-alpha.20260818172555 → 1.1.61-alpha.20260819082510
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/dist/index.js +168 -3482
- package/package.json +1 -4
- package/templates/scripts/dev.js +79 -429
- package/templates/scripts/dev.sh +0 -2
- package/templates/tsconfig.dev.json +7 -0
- package/dist/client-dependency-graph.d.ts +0 -37
- package/dist/client-dependency-graph.js +0 -466
- package/templates/scripts/cache-generation-preflight.mjs +0 -1346
- package/templates/scripts/cache-generation-prune.mjs +0 -174
- package/templates/scripts/cache-runtime-coordinator.mjs +0 -487
- package/templates/scripts/patch-vite-dependency-graph-hash.mjs +0 -141
- package/templates/scripts/server-cache-module-resolver.cjs +0 -63
- package/templates/scripts/server-cache-runtime.mjs +0 -681
- package/templates/scripts/server-startup-runtime.mjs +0 -496
- package/templates/scripts/server-transition-runtime.mjs +0 -655
- package/templates/scripts/vite-cache-runtime.mjs +0 -3100
- package/templates/scripts/workspace-client-runtime.mjs +0 -176
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import fs29 from "fs";
|
|
3
|
+
import path25 from "path";
|
|
4
4
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
5
|
+
import { config as dotenvConfig } from "dotenv";
|
|
5
6
|
|
|
6
7
|
// src/cli.ts
|
|
7
8
|
import { Command } from "commander";
|
|
@@ -2553,20 +2554,6 @@ function buildDefaultRules(opts) {
|
|
|
2553
2554
|
command: "fullstack-cli action-plugin init",
|
|
2554
2555
|
overwrite: false
|
|
2555
2556
|
},
|
|
2556
|
-
// Cache generation keeps workspace source live and only snapshots the
|
|
2557
|
-
// automatically traced Nest runtime dependencies.
|
|
2558
|
-
{
|
|
2559
|
-
type: "add-script",
|
|
2560
|
-
name: "build:server-runtime-dependencies:from-dist",
|
|
2561
|
-
command: "fullstack-cli build server-runtime-dependencies",
|
|
2562
|
-
overwrite: true
|
|
2563
|
-
},
|
|
2564
|
-
{
|
|
2565
|
-
type: "patch-script",
|
|
2566
|
-
name: "build:cache:from-dist",
|
|
2567
|
-
to: "npm run build:server-runtime-dependencies:from-dist && fullstack-cli build app-runtime-manifest --runtime-manifest-file ${MIAODA_PLATFORM_RUNTIME_MANIFEST:-/opt/miaoda/preview-runtime/runtime-manifest.json} && npm run build:vite-cache && fullstack-cli build cache-generation --runtime-manifest-file ${MIAODA_PLATFORM_RUNTIME_MANIFEST:-/opt/miaoda/preview-runtime/runtime-manifest.json}",
|
|
2568
|
-
ifStartsWith: "npm run build:server-cache:from-dist"
|
|
2569
|
-
},
|
|
2570
2557
|
// 6. 替换 drizzle.config.ts(仅当文件存在时)
|
|
2571
2558
|
{
|
|
2572
2559
|
from: "templates/drizzle.config.ts",
|
|
@@ -2617,14 +2604,35 @@ function defaultProfile(opts) {
|
|
|
2617
2604
|
return {
|
|
2618
2605
|
sync: buildDefaultRules(opts),
|
|
2619
2606
|
// 文件权限设置(所有 .sh 文件设置为可执行:'**/*.sh': 0o755)
|
|
2620
|
-
|
|
2621
|
-
// platform template tracks the executable bit. `npm run dev` executes
|
|
2622
|
-
// scripts/dev.sh directly, so repairing the mode is part of sync's
|
|
2623
|
-
// platform contract rather than an image-entrypoint side effect.
|
|
2624
|
-
permissions: { "**/*.sh": 493 },
|
|
2607
|
+
permissions: {},
|
|
2625
2608
|
activateGitHooks: true
|
|
2626
2609
|
};
|
|
2627
2610
|
}
|
|
2611
|
+
function nestFullstackProfile(opts) {
|
|
2612
|
+
const base = defaultProfile(opts);
|
|
2613
|
+
return {
|
|
2614
|
+
...base,
|
|
2615
|
+
sync: [
|
|
2616
|
+
...base.sync,
|
|
2617
|
+
// dev 专用 tsconfig:只打开 noEmitOnError,其余继承 tsconfig.node.json
|
|
2618
|
+
{
|
|
2619
|
+
from: "templates/tsconfig.dev.json",
|
|
2620
|
+
to: "tsconfig.dev.json",
|
|
2621
|
+
type: "file",
|
|
2622
|
+
overwrite: true
|
|
2623
|
+
},
|
|
2624
|
+
// 让 dev:server 用上它。ifStartsWith 精确限定为平台模板生成的形态,
|
|
2625
|
+
// 用户真正改写过的 dev:server 保持原样(改写后仅退化为 message 文案不够精确,
|
|
2626
|
+
// ready/failed 判定不受影响)。
|
|
2627
|
+
{
|
|
2628
|
+
type: "patch-script",
|
|
2629
|
+
name: "dev:server",
|
|
2630
|
+
to: "NODE_ENV=development nest start --watch -p tsconfig.dev.json",
|
|
2631
|
+
ifStartsWith: "NODE_ENV=development nest start --watch"
|
|
2632
|
+
}
|
|
2633
|
+
]
|
|
2634
|
+
};
|
|
2635
|
+
}
|
|
2628
2636
|
function emptyProfile() {
|
|
2629
2637
|
return {
|
|
2630
2638
|
sync: [],
|
|
@@ -2641,7 +2649,7 @@ function viteReactProfile() {
|
|
|
2641
2649
|
}
|
|
2642
2650
|
var SYNC_PROFILES = {
|
|
2643
2651
|
"design-stack": defaultProfile,
|
|
2644
|
-
"nestjs-react-fullstack":
|
|
2652
|
+
"nestjs-react-fullstack": nestFullstackProfile,
|
|
2645
2653
|
"vite-react": viteReactProfile,
|
|
2646
2654
|
html: emptyProfile,
|
|
2647
2655
|
// design-html 与 html 同语义:空 sync + 不激活 git hooks(彻底 no-op)
|
|
@@ -3519,26 +3527,6 @@ function resolveGrayscaleVersions(_cwd, configJson) {
|
|
|
3519
3527
|
return versions;
|
|
3520
3528
|
}
|
|
3521
3529
|
|
|
3522
|
-
// src/utils/npm-child.ts
|
|
3523
|
-
function sanitizedNpmEnv(source = process.env) {
|
|
3524
|
-
const env = { ...source };
|
|
3525
|
-
for (const key of [
|
|
3526
|
-
"FORCE_AUTHN_INNERAPI_DOMAIN",
|
|
3527
|
-
"FORCE_AUTHN_ACCESS_SECRET",
|
|
3528
|
-
"FORCE_AUTHN_ACCESS_KEY",
|
|
3529
|
-
"NODE_OPTIONS",
|
|
3530
|
-
"NODE_PATH",
|
|
3531
|
-
"BASH_ENV",
|
|
3532
|
-
"ENV",
|
|
3533
|
-
"NPM_CONFIG_IGNORE_SCRIPTS",
|
|
3534
|
-
"npm_config_ignore_scripts"
|
|
3535
|
-
]) {
|
|
3536
|
-
delete env[key];
|
|
3537
|
-
}
|
|
3538
|
-
env.npm_config_ignore_scripts = "true";
|
|
3539
|
-
return env;
|
|
3540
|
-
}
|
|
3541
|
-
|
|
3542
3530
|
// src/commands/upgrade/deps/run.handler.ts
|
|
3543
3531
|
function parseSemver(version) {
|
|
3544
3532
|
const match = version.match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
@@ -3597,9 +3585,8 @@ function upgradePackages(packages, version, cwd) {
|
|
|
3597
3585
|
packages.forEach((pkg2) => {
|
|
3598
3586
|
const target = `${pkg2}@${version}`;
|
|
3599
3587
|
console.log(`[fullstack-cli] Installing ${target}...`);
|
|
3600
|
-
const result = spawnSync4("npm", ["install", target
|
|
3588
|
+
const result = spawnSync4("npm", ["install", target], {
|
|
3601
3589
|
cwd,
|
|
3602
|
-
env: sanitizedNpmEnv(),
|
|
3603
3590
|
stdio: "inherit"
|
|
3604
3591
|
});
|
|
3605
3592
|
if (result.error || result.status !== 0) {
|
|
@@ -3610,9 +3597,8 @@ function upgradePackages(packages, version, cwd) {
|
|
|
3610
3597
|
console.log("[fullstack-cli] Upgrading to latest compatible versions...");
|
|
3611
3598
|
packages.forEach((pkg2) => {
|
|
3612
3599
|
console.log(`[fullstack-cli] Updating ${pkg2}...`);
|
|
3613
|
-
const result = spawnSync4("npm", ["update", pkg2
|
|
3600
|
+
const result = spawnSync4("npm", ["update", pkg2], {
|
|
3614
3601
|
cwd,
|
|
3615
|
-
env: sanitizedNpmEnv(),
|
|
3616
3602
|
stdio: "inherit"
|
|
3617
3603
|
});
|
|
3618
3604
|
if (result.error || result.status !== 0) {
|
|
@@ -3672,9 +3658,8 @@ function installGrayscaleVersions(packages, grayscaleVersions, cwd, dryRun, mode
|
|
|
3672
3658
|
}
|
|
3673
3659
|
const targets = upgradePlan.map(({ pkg: pkg2, version }) => `${pkg2}@${version}`);
|
|
3674
3660
|
console.log(`[fullstack-cli] Installing ${targets.join(" ")}...`);
|
|
3675
|
-
const result = spawnSync4("npm", ["install", ...targets
|
|
3661
|
+
const result = spawnSync4("npm", ["install", ...targets], {
|
|
3676
3662
|
cwd,
|
|
3677
|
-
env: sanitizedNpmEnv(),
|
|
3678
3663
|
stdio: "inherit"
|
|
3679
3664
|
});
|
|
3680
3665
|
if (result.error || result.status !== 0) {
|
|
@@ -3866,96 +3851,28 @@ var upgradeCommand = {
|
|
|
3866
3851
|
|
|
3867
3852
|
// src/commands/action-plugin/utils.ts
|
|
3868
3853
|
import fs13 from "fs";
|
|
3869
|
-
import os from "os";
|
|
3870
|
-
import path12 from "path";
|
|
3871
|
-
import { spawnSync as spawnSync6 } from "child_process";
|
|
3872
|
-
|
|
3873
|
-
// src/commands/action-plugin/validation.ts
|
|
3874
3854
|
import path11 from "path";
|
|
3875
|
-
|
|
3876
|
-
var REGISTRY_PACKAGE_NAME = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/;
|
|
3877
|
-
var PLUGIN_VERSION = /^(?:latest|[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z][0-9A-Za-z.-]*)?(?:\+[0-9A-Za-z][0-9A-Za-z.-]*)?)$/;
|
|
3878
|
-
var PEER_DEP_RANGE = /^[0-9A-Za-z*^~<>=|.\-\s]+$/;
|
|
3879
|
-
function assertScopedPackageName(value, label = "package name") {
|
|
3880
|
-
if (typeof value !== "string" || !SCOPED_PACKAGE_NAME.test(value)) {
|
|
3881
|
-
throw new Error(`Invalid ${label}: ${String(value)}`);
|
|
3882
|
-
}
|
|
3883
|
-
}
|
|
3884
|
-
function assertRegistryPackageName(value, label = "package name") {
|
|
3885
|
-
if (typeof value !== "string" || !REGISTRY_PACKAGE_NAME.test(value)) {
|
|
3886
|
-
throw new Error(`Invalid ${label}: ${String(value)}`);
|
|
3887
|
-
}
|
|
3888
|
-
}
|
|
3889
|
-
function assertPluginVersion(value) {
|
|
3890
|
-
if (typeof value !== "string" || !PLUGIN_VERSION.test(value)) {
|
|
3891
|
-
throw new Error(`Invalid plugin version: ${String(value)}`);
|
|
3892
|
-
}
|
|
3893
|
-
}
|
|
3894
|
-
function assertSafePeerDependencySpec(value) {
|
|
3895
|
-
if (typeof value !== "string") {
|
|
3896
|
-
throw new Error(`Invalid peer dependency spec: ${String(value)}`);
|
|
3897
|
-
}
|
|
3898
|
-
const spec = value.trim();
|
|
3899
|
-
const lower = spec.toLowerCase();
|
|
3900
|
-
if (spec.length === 0 || !PEER_DEP_RANGE.test(spec) || lower.startsWith("file:") || lower.startsWith("git") || lower.startsWith("http:") || lower.startsWith("https:") || lower.startsWith("npm:") || spec.includes("/") || spec.includes("\\")) {
|
|
3901
|
-
throw new Error(`Invalid peer dependency spec: ${value}`);
|
|
3902
|
-
}
|
|
3903
|
-
}
|
|
3904
|
-
function resolveContainedPath(root, ...segments) {
|
|
3905
|
-
const resolvedRoot = path11.resolve(root);
|
|
3906
|
-
const resolved = path11.resolve(resolvedRoot, ...segments);
|
|
3907
|
-
if (!resolved.startsWith(`${resolvedRoot}${path11.sep}`)) {
|
|
3908
|
-
throw new Error(`Resolved path escapes allowed root: ${resolved}`);
|
|
3909
|
-
}
|
|
3910
|
-
return resolved;
|
|
3911
|
-
}
|
|
3912
|
-
|
|
3913
|
-
// src/commands/action-plugin/utils.ts
|
|
3855
|
+
import { spawnSync as spawnSync6, execSync as execSync2 } from "child_process";
|
|
3914
3856
|
function parsePluginName(input) {
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
`Invalid plugin name format: ${input}. Expected format: @scope/name or @scope/name@version`
|
|
3918
|
-
);
|
|
3919
|
-
}
|
|
3920
|
-
const versionSeparator = input.lastIndexOf("@");
|
|
3921
|
-
const hasVersion = versionSeparator > 0;
|
|
3922
|
-
const name = hasVersion ? input.slice(0, versionSeparator) : input;
|
|
3923
|
-
const version = hasVersion ? input.slice(versionSeparator + 1) : "latest";
|
|
3924
|
-
try {
|
|
3925
|
-
assertScopedPackageName(name, "plugin name");
|
|
3926
|
-
assertPluginVersion(version);
|
|
3927
|
-
} catch {
|
|
3857
|
+
const match = input.match(/^(@[^/]+\/[^@]+)(?:@(.+))?$/);
|
|
3858
|
+
if (!match) {
|
|
3928
3859
|
throw new Error(
|
|
3929
3860
|
`Invalid plugin name format: ${input}. Expected format: @scope/name or @scope/name@version`
|
|
3930
3861
|
);
|
|
3931
3862
|
}
|
|
3932
3863
|
return {
|
|
3933
|
-
name,
|
|
3934
|
-
version
|
|
3864
|
+
name: match[1],
|
|
3865
|
+
version: match[2] || "latest"
|
|
3935
3866
|
};
|
|
3936
3867
|
}
|
|
3937
3868
|
function getProjectRoot() {
|
|
3938
3869
|
return process.cwd();
|
|
3939
3870
|
}
|
|
3940
|
-
function assertRealDirectoryIfExists(directory, label) {
|
|
3941
|
-
if (!fs13.existsSync(directory)) {
|
|
3942
|
-
return;
|
|
3943
|
-
}
|
|
3944
|
-
const stat = fs13.lstatSync(directory);
|
|
3945
|
-
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
3946
|
-
throw new Error(`${label} must be a real directory`);
|
|
3947
|
-
}
|
|
3948
|
-
}
|
|
3949
3871
|
function getPackageJsonPath() {
|
|
3950
|
-
return
|
|
3872
|
+
return path11.join(getProjectRoot(), "package.json");
|
|
3951
3873
|
}
|
|
3952
3874
|
function getPluginPath(pluginName) {
|
|
3953
|
-
|
|
3954
|
-
const nodeModulesPath = path12.resolve(getProjectRoot(), "node_modules");
|
|
3955
|
-
const pluginPath = resolveContainedPath(nodeModulesPath, pluginName);
|
|
3956
|
-
assertRealDirectoryIfExists(nodeModulesPath, "node_modules");
|
|
3957
|
-
assertRealDirectoryIfExists(path12.dirname(pluginPath), "plugin scope directory");
|
|
3958
|
-
return pluginPath;
|
|
3875
|
+
return path11.join(getProjectRoot(), "node_modules", pluginName);
|
|
3959
3876
|
}
|
|
3960
3877
|
function readPackageJson2() {
|
|
3961
3878
|
const pkgPath = getPackageJsonPath();
|
|
@@ -3994,7 +3911,6 @@ function npmInstall(tgzPath) {
|
|
|
3994
3911
|
console.log(`[action-plugin] Running npm install ${tgzPath}...`);
|
|
3995
3912
|
const result = spawnSync6("npm", ["install", tgzPath, "--no-save", "--no-package-lock", "--ignore-scripts"], {
|
|
3996
3913
|
cwd: getProjectRoot(),
|
|
3997
|
-
env: sanitizedNpmEnv(),
|
|
3998
3914
|
stdio: "inherit"
|
|
3999
3915
|
});
|
|
4000
3916
|
if (result.error) {
|
|
@@ -4005,7 +3921,7 @@ function npmInstall(tgzPath) {
|
|
|
4005
3921
|
}
|
|
4006
3922
|
}
|
|
4007
3923
|
function getPackageVersion(pluginName) {
|
|
4008
|
-
const pkgJsonPath =
|
|
3924
|
+
const pkgJsonPath = path11.join(getPluginPath(pluginName), "package.json");
|
|
4009
3925
|
if (!fs13.existsSync(pkgJsonPath)) {
|
|
4010
3926
|
return null;
|
|
4011
3927
|
}
|
|
@@ -4018,7 +3934,7 @@ function getPackageVersion(pluginName) {
|
|
|
4018
3934
|
}
|
|
4019
3935
|
}
|
|
4020
3936
|
function readPluginPackageJson(pluginPath) {
|
|
4021
|
-
const pkgJsonPath =
|
|
3937
|
+
const pkgJsonPath = path11.join(pluginPath, "package.json");
|
|
4022
3938
|
if (!fs13.existsSync(pkgJsonPath)) {
|
|
4023
3939
|
return null;
|
|
4024
3940
|
}
|
|
@@ -4030,39 +3946,29 @@ function readPluginPackageJson(pluginPath) {
|
|
|
4030
3946
|
}
|
|
4031
3947
|
}
|
|
4032
3948
|
function extractTgzToNodeModules(tgzPath, pluginName) {
|
|
4033
|
-
|
|
4034
|
-
const
|
|
4035
|
-
const
|
|
4036
|
-
const scopeDir = path12.dirname(targetDir);
|
|
4037
|
-
if (!fs13.existsSync(nodeModulesPath)) {
|
|
4038
|
-
fs13.mkdirSync(nodeModulesPath, { recursive: true });
|
|
4039
|
-
}
|
|
4040
|
-
assertRealDirectoryIfExists(nodeModulesPath, "node_modules");
|
|
3949
|
+
const nodeModulesPath = path11.join(getProjectRoot(), "node_modules");
|
|
3950
|
+
const targetDir = path11.join(nodeModulesPath, pluginName);
|
|
3951
|
+
const scopeDir = path11.dirname(targetDir);
|
|
4041
3952
|
if (!fs13.existsSync(scopeDir)) {
|
|
4042
3953
|
fs13.mkdirSync(scopeDir, { recursive: true });
|
|
4043
3954
|
}
|
|
4044
|
-
assertRealDirectoryIfExists(scopeDir, "plugin scope directory");
|
|
4045
3955
|
if (fs13.existsSync(targetDir)) {
|
|
4046
3956
|
fs13.rmSync(targetDir, { recursive: true });
|
|
4047
3957
|
}
|
|
4048
|
-
const tempDir =
|
|
3958
|
+
const tempDir = path11.join(nodeModulesPath, ".cache", "fullstack-cli", "extract-temp");
|
|
3959
|
+
if (fs13.existsSync(tempDir)) {
|
|
3960
|
+
fs13.rmSync(tempDir, { recursive: true });
|
|
3961
|
+
}
|
|
3962
|
+
fs13.mkdirSync(tempDir, { recursive: true });
|
|
4049
3963
|
try {
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
});
|
|
4053
|
-
if (tarResult.error) {
|
|
4054
|
-
throw new Error(`Failed to extract plugin archive: ${tarResult.error.message}`);
|
|
4055
|
-
}
|
|
4056
|
-
if (tarResult.status !== 0) {
|
|
4057
|
-
throw new Error(`Failed to extract plugin archive: tar exited with code ${tarResult.status}`);
|
|
4058
|
-
}
|
|
4059
|
-
const extractedDir = path12.join(tempDir, "package");
|
|
3964
|
+
execSync2(`tar -xzf "${tgzPath}" -C "${tempDir}"`, { stdio: "pipe" });
|
|
3965
|
+
const extractedDir = path11.join(tempDir, "package");
|
|
4060
3966
|
if (fs13.existsSync(extractedDir)) {
|
|
4061
3967
|
fs13.renameSync(extractedDir, targetDir);
|
|
4062
3968
|
} else {
|
|
4063
3969
|
const files = fs13.readdirSync(tempDir);
|
|
4064
3970
|
if (files.length === 1) {
|
|
4065
|
-
fs13.renameSync(
|
|
3971
|
+
fs13.renameSync(path11.join(tempDir, files[0]), targetDir);
|
|
4066
3972
|
} else {
|
|
4067
3973
|
throw new Error("Unexpected tgz structure");
|
|
4068
3974
|
}
|
|
@@ -4079,11 +3985,9 @@ function checkMissingPeerDeps(peerDeps) {
|
|
|
4079
3985
|
return [];
|
|
4080
3986
|
}
|
|
4081
3987
|
const missing = [];
|
|
4082
|
-
const nodeModulesPath =
|
|
3988
|
+
const nodeModulesPath = path11.join(getProjectRoot(), "node_modules");
|
|
4083
3989
|
for (const [depName, _version] of Object.entries(peerDeps)) {
|
|
4084
|
-
|
|
4085
|
-
assertSafePeerDependencySpec(_version);
|
|
4086
|
-
const depPath = resolveContainedPath(nodeModulesPath, depName);
|
|
3990
|
+
const depPath = path11.join(nodeModulesPath, depName);
|
|
4087
3991
|
if (!fs13.existsSync(depPath)) {
|
|
4088
3992
|
missing.push(depName);
|
|
4089
3993
|
}
|
|
@@ -4094,13 +3998,9 @@ function installMissingDeps(deps) {
|
|
|
4094
3998
|
if (deps.length === 0) {
|
|
4095
3999
|
return;
|
|
4096
4000
|
}
|
|
4097
|
-
for (const depName of deps) {
|
|
4098
|
-
assertRegistryPackageName(depName, "peer dependency name");
|
|
4099
|
-
}
|
|
4100
4001
|
console.log(`[action-plugin] Installing missing dependencies: ${deps.join(", ")}`);
|
|
4101
|
-
const result = spawnSync6("npm", ["install", ...deps, "--no-save", "--no-package-lock"
|
|
4002
|
+
const result = spawnSync6("npm", ["install", ...deps, "--no-save", "--no-package-lock"], {
|
|
4102
4003
|
cwd: getProjectRoot(),
|
|
4103
|
-
env: sanitizedNpmEnv(),
|
|
4104
4004
|
stdio: "inherit"
|
|
4105
4005
|
});
|
|
4106
4006
|
if (result.error) {
|
|
@@ -4111,7 +4011,6 @@ function installMissingDeps(deps) {
|
|
|
4111
4011
|
}
|
|
4112
4012
|
}
|
|
4113
4013
|
function removePluginDirectory(pluginName) {
|
|
4114
|
-
assertScopedPackageName(pluginName, "plugin name");
|
|
4115
4014
|
const pluginPath = getPluginPath(pluginName);
|
|
4116
4015
|
if (fs13.existsSync(pluginPath)) {
|
|
4117
4016
|
fs13.rmSync(pluginPath, { recursive: true });
|
|
@@ -4122,12 +4021,9 @@ function removePluginDirectory(pluginName) {
|
|
|
4122
4021
|
// src/commands/action-plugin/api-client.ts
|
|
4123
4022
|
import { HttpClient as HttpClient2 } from "@lark-apaas/http-client";
|
|
4124
4023
|
import fs14 from "fs";
|
|
4125
|
-
import
|
|
4024
|
+
import path12 from "path";
|
|
4126
4025
|
var PLUGIN_CACHE_DIR = "node_modules/.cache/fullstack-cli/plugins";
|
|
4127
4026
|
async function getPluginVersions(keys, latestOnly = true) {
|
|
4128
|
-
for (const key of keys) {
|
|
4129
|
-
assertScopedPackageName(key, "plugin key");
|
|
4130
|
-
}
|
|
4131
4027
|
const client = getHttpClient();
|
|
4132
4028
|
const response = await client.post(`/api/v1/studio/innerapi/plugins/-/versions/batch_get?keys=${keys.join(",")}&latest_only=${latestOnly}`);
|
|
4133
4029
|
if (!response.ok || response.status !== 200) {
|
|
@@ -4141,8 +4037,6 @@ async function getPluginVersions(keys, latestOnly = true) {
|
|
|
4141
4037
|
return result.data.pluginVersions;
|
|
4142
4038
|
}
|
|
4143
4039
|
async function getPluginVersion(pluginKey, requestedVersion) {
|
|
4144
|
-
assertScopedPackageName(pluginKey, "plugin key");
|
|
4145
|
-
assertPluginVersion(requestedVersion);
|
|
4146
4040
|
const isLatest = requestedVersion === "latest";
|
|
4147
4041
|
const versions = await getPluginVersions([pluginKey], isLatest);
|
|
4148
4042
|
const pluginVersions = versions[pluginKey];
|
|
@@ -4150,7 +4044,6 @@ async function getPluginVersion(pluginKey, requestedVersion) {
|
|
|
4150
4044
|
throw new Error(`Plugin not found: ${pluginKey}`);
|
|
4151
4045
|
}
|
|
4152
4046
|
if (isLatest) {
|
|
4153
|
-
assertPluginVersion(pluginVersions[0].version);
|
|
4154
4047
|
return pluginVersions[0];
|
|
4155
4048
|
}
|
|
4156
4049
|
const targetVersion = pluginVersions.find((v) => v.version === requestedVersion);
|
|
@@ -4162,8 +4055,10 @@ async function getPluginVersion(pluginKey, requestedVersion) {
|
|
|
4162
4055
|
return targetVersion;
|
|
4163
4056
|
}
|
|
4164
4057
|
function parsePluginKey(key) {
|
|
4165
|
-
|
|
4166
|
-
|
|
4058
|
+
const match = key.match(/^(@[^/]+)\/(.+)$/);
|
|
4059
|
+
if (!match) {
|
|
4060
|
+
throw new Error(`Invalid plugin key format: ${key}`);
|
|
4061
|
+
}
|
|
4167
4062
|
return { scope: match[1], name: match[2] };
|
|
4168
4063
|
}
|
|
4169
4064
|
async function downloadFromInner(pluginKey, version) {
|
|
@@ -4190,32 +4085,19 @@ async function downloadFromPublic(downloadURL) {
|
|
|
4190
4085
|
return Buffer.from(arrayBuffer);
|
|
4191
4086
|
}
|
|
4192
4087
|
function getPluginCacheDir() {
|
|
4193
|
-
return
|
|
4088
|
+
return path12.join(process.cwd(), PLUGIN_CACHE_DIR);
|
|
4194
4089
|
}
|
|
4195
4090
|
function ensureCacheDir() {
|
|
4196
4091
|
const cacheDir = getPluginCacheDir();
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
let current = projectRoot;
|
|
4200
|
-
for (const segment of relative.split(path13.sep)) {
|
|
4201
|
-
current = path13.join(current, segment);
|
|
4202
|
-
if (fs14.existsSync(current)) {
|
|
4203
|
-
const stat = fs14.lstatSync(current);
|
|
4204
|
-
if (!stat.isDirectory() || stat.isSymbolicLink()) {
|
|
4205
|
-
throw new Error(`Plugin cache path must be a real directory: ${current}`);
|
|
4206
|
-
}
|
|
4207
|
-
} else {
|
|
4208
|
-
fs14.mkdirSync(current);
|
|
4209
|
-
}
|
|
4092
|
+
if (!fs14.existsSync(cacheDir)) {
|
|
4093
|
+
fs14.mkdirSync(cacheDir, { recursive: true });
|
|
4210
4094
|
}
|
|
4211
4095
|
}
|
|
4212
4096
|
function getTempFilePath(pluginKey, version) {
|
|
4213
|
-
assertScopedPackageName(pluginKey, "plugin key");
|
|
4214
|
-
assertPluginVersion(version);
|
|
4215
4097
|
ensureCacheDir();
|
|
4216
4098
|
const safeKey = pluginKey.replace(/[/@]/g, "_");
|
|
4217
4099
|
const filename = `${safeKey}@${version}.tgz`;
|
|
4218
|
-
return
|
|
4100
|
+
return path12.join(getPluginCacheDir(), filename);
|
|
4219
4101
|
}
|
|
4220
4102
|
var MAX_RETRIES = 2;
|
|
4221
4103
|
async function withRetry(operation, description, maxRetries = MAX_RETRIES) {
|
|
@@ -4263,12 +4145,10 @@ async function downloadPlugin(pluginKey, requestedVersion) {
|
|
|
4263
4145
|
function cleanupTempFile(tgzPath) {
|
|
4264
4146
|
}
|
|
4265
4147
|
function getCachePath(pluginKey, version) {
|
|
4266
|
-
assertScopedPackageName(pluginKey, "plugin key");
|
|
4267
|
-
assertPluginVersion(version);
|
|
4268
4148
|
ensureCacheDir();
|
|
4269
4149
|
const safeKey = pluginKey.replace(/[/@]/g, "_");
|
|
4270
4150
|
const filename = `${safeKey}@${version}.tgz`;
|
|
4271
|
-
return
|
|
4151
|
+
return path12.join(getPluginCacheDir(), filename);
|
|
4272
4152
|
}
|
|
4273
4153
|
function hasCachedPlugin(pluginKey, version) {
|
|
4274
4154
|
const cachePath = getCachePath(pluginKey, version);
|
|
@@ -4287,7 +4167,7 @@ function listCachedPlugins() {
|
|
|
4287
4167
|
if (!match) continue;
|
|
4288
4168
|
const [, rawName, version] = match;
|
|
4289
4169
|
const name = rawName.replace(/^_/, "@").replace(/_/, "/");
|
|
4290
|
-
const filePath =
|
|
4170
|
+
const filePath = path12.join(cacheDir, file);
|
|
4291
4171
|
const stat = fs14.statSync(filePath);
|
|
4292
4172
|
result.push({
|
|
4293
4173
|
name,
|
|
@@ -4308,7 +4188,7 @@ function cleanAllCache() {
|
|
|
4308
4188
|
let count = 0;
|
|
4309
4189
|
for (const file of files) {
|
|
4310
4190
|
if (file.endsWith(".tgz")) {
|
|
4311
|
-
fs14.unlinkSync(
|
|
4191
|
+
fs14.unlinkSync(path12.join(cacheDir, file));
|
|
4312
4192
|
count++;
|
|
4313
4193
|
}
|
|
4314
4194
|
}
|
|
@@ -4325,12 +4205,12 @@ function cleanPluginCache(pluginKey, version) {
|
|
|
4325
4205
|
for (const file of files) {
|
|
4326
4206
|
if (version) {
|
|
4327
4207
|
if (file === `${safeKey}@${version}.tgz`) {
|
|
4328
|
-
fs14.unlinkSync(
|
|
4208
|
+
fs14.unlinkSync(path12.join(cacheDir, file));
|
|
4329
4209
|
count++;
|
|
4330
4210
|
}
|
|
4331
4211
|
} else {
|
|
4332
4212
|
if (file.startsWith(`${safeKey}@`) && file.endsWith(".tgz")) {
|
|
4333
|
-
fs14.unlinkSync(
|
|
4213
|
+
fs14.unlinkSync(path12.join(cacheDir, file));
|
|
4334
4214
|
count++;
|
|
4335
4215
|
}
|
|
4336
4216
|
}
|
|
@@ -4341,8 +4221,6 @@ function cleanPluginCache(pluginKey, version) {
|
|
|
4341
4221
|
// src/commands/action-plugin/init.handler.ts
|
|
4342
4222
|
async function installOneForInit(name, version) {
|
|
4343
4223
|
try {
|
|
4344
|
-
assertScopedPackageName(name, "plugin name");
|
|
4345
|
-
assertPluginVersion(version);
|
|
4346
4224
|
const installedVersion = getPackageVersion(name);
|
|
4347
4225
|
if (installedVersion === version) {
|
|
4348
4226
|
return { name, version, success: true, skipped: true };
|
|
@@ -4761,24 +4639,24 @@ var actionPluginCommandGroup = {
|
|
|
4761
4639
|
// src/commands/capability/utils.ts
|
|
4762
4640
|
import fs15 from "fs";
|
|
4763
4641
|
import { createRequire as createRequire2 } from "module";
|
|
4764
|
-
import
|
|
4642
|
+
import path13 from "path";
|
|
4765
4643
|
var CAPABILITIES_DIR = "server/capabilities";
|
|
4766
4644
|
var SHARED_CAPABILITIES_DIR = "shared/capabilities";
|
|
4767
4645
|
function getProjectRoot2() {
|
|
4768
4646
|
return process.cwd();
|
|
4769
4647
|
}
|
|
4770
4648
|
function getCapabilitiesDir() {
|
|
4771
|
-
const sharedDir =
|
|
4649
|
+
const sharedDir = path13.join(getProjectRoot2(), SHARED_CAPABILITIES_DIR);
|
|
4772
4650
|
if (fs15.existsSync(sharedDir)) {
|
|
4773
4651
|
return sharedDir;
|
|
4774
4652
|
}
|
|
4775
|
-
return
|
|
4653
|
+
return path13.join(getProjectRoot2(), CAPABILITIES_DIR);
|
|
4776
4654
|
}
|
|
4777
4655
|
function getCapabilityPath(id) {
|
|
4778
|
-
return
|
|
4656
|
+
return path13.join(getCapabilitiesDir(), `${id}.json`);
|
|
4779
4657
|
}
|
|
4780
4658
|
function getPluginManifestPath(pluginKey) {
|
|
4781
|
-
return
|
|
4659
|
+
return path13.join(getProjectRoot2(), "node_modules", pluginKey, "manifest.json");
|
|
4782
4660
|
}
|
|
4783
4661
|
function capabilitiesDirExists() {
|
|
4784
4662
|
return fs15.existsSync(getCapabilitiesDir());
|
|
@@ -4845,7 +4723,7 @@ function hasValidParamsSchema(paramsSchema) {
|
|
|
4845
4723
|
}
|
|
4846
4724
|
async function loadPlugin(pluginKey) {
|
|
4847
4725
|
try {
|
|
4848
|
-
const userRequire = createRequire2(
|
|
4726
|
+
const userRequire = createRequire2(path13.join(getProjectRoot2(), "package.json"));
|
|
4849
4727
|
const resolvedPath = userRequire.resolve(pluginKey);
|
|
4850
4728
|
const pluginModule = await import(resolvedPath);
|
|
4851
4729
|
const pluginPackage = pluginModule.default ?? pluginModule;
|
|
@@ -5009,8 +4887,8 @@ import { execFile } from "child_process";
|
|
|
5009
4887
|
|
|
5010
4888
|
// src/commands/component/registry-preparer.ts
|
|
5011
4889
|
import fs16 from "fs";
|
|
5012
|
-
import
|
|
5013
|
-
import
|
|
4890
|
+
import path14 from "path";
|
|
4891
|
+
import os from "os";
|
|
5014
4892
|
|
|
5015
4893
|
// src/commands/component/service.ts
|
|
5016
4894
|
import { mapValues } from "es-toolkit";
|
|
@@ -5065,7 +4943,7 @@ async function sendInstallEvent(key) {
|
|
|
5065
4943
|
}
|
|
5066
4944
|
|
|
5067
4945
|
// src/commands/component/registry-preparer.ts
|
|
5068
|
-
var REGISTRY_TEMP_DIR =
|
|
4946
|
+
var REGISTRY_TEMP_DIR = path14.join(os.tmpdir(), "miaoda-registry");
|
|
5069
4947
|
function parseComponentKey(key) {
|
|
5070
4948
|
const match = key.match(/^@([^/]+)\/(.+)$/);
|
|
5071
4949
|
if (!match) {
|
|
@@ -5077,7 +4955,7 @@ function parseComponentKey(key) {
|
|
|
5077
4955
|
}
|
|
5078
4956
|
function getLocalRegistryPath(key) {
|
|
5079
4957
|
const { scope, name } = parseComponentKey(key);
|
|
5080
|
-
return
|
|
4958
|
+
return path14.join(REGISTRY_TEMP_DIR, scope, `${name}.json`);
|
|
5081
4959
|
}
|
|
5082
4960
|
function ensureDir(dirPath) {
|
|
5083
4961
|
if (!fs16.existsSync(dirPath)) {
|
|
@@ -5114,7 +4992,7 @@ async function prepareRecursive(key, visited) {
|
|
|
5114
4992
|
registryDependencies: deps.map((dep) => getLocalRegistryPath(dep))
|
|
5115
4993
|
};
|
|
5116
4994
|
const localPath = getLocalRegistryPath(key);
|
|
5117
|
-
ensureDir(
|
|
4995
|
+
ensureDir(path14.dirname(localPath));
|
|
5118
4996
|
fs16.writeFileSync(localPath, JSON.stringify(rewrittenItem, null, 2), "utf-8");
|
|
5119
4997
|
debug("\u4FDD\u5B58\u5230: %s", localPath);
|
|
5120
4998
|
}
|
|
@@ -5305,11 +5183,11 @@ var componentCommandGroup = {
|
|
|
5305
5183
|
|
|
5306
5184
|
// src/commands/migration/version-manager.ts
|
|
5307
5185
|
import fs17 from "fs";
|
|
5308
|
-
import
|
|
5186
|
+
import path15 from "path";
|
|
5309
5187
|
var PACKAGE_JSON = "package.json";
|
|
5310
5188
|
var VERSION_FIELD = "migrationVersion";
|
|
5311
5189
|
function getPackageJsonPath2() {
|
|
5312
|
-
return
|
|
5190
|
+
return path15.join(process.cwd(), PACKAGE_JSON);
|
|
5313
5191
|
}
|
|
5314
5192
|
function getCurrentVersion() {
|
|
5315
5193
|
const pkgPath = getPackageJsonPath2();
|
|
@@ -5328,26 +5206,26 @@ function setCurrentVersion(version) {
|
|
|
5328
5206
|
|
|
5329
5207
|
// src/commands/migration/versions/v001_capability/json-migrator/detector.ts
|
|
5330
5208
|
import fs19 from "fs";
|
|
5331
|
-
import
|
|
5209
|
+
import path17 from "path";
|
|
5332
5210
|
|
|
5333
5211
|
// src/commands/migration/versions/v001_capability/utils.ts
|
|
5334
5212
|
import fs18 from "fs";
|
|
5335
|
-
import
|
|
5213
|
+
import path16 from "path";
|
|
5336
5214
|
var CAPABILITIES_DIR2 = "server/capabilities";
|
|
5337
5215
|
function getProjectRoot3() {
|
|
5338
5216
|
return process.cwd();
|
|
5339
5217
|
}
|
|
5340
5218
|
function getCapabilitiesDir2() {
|
|
5341
|
-
return
|
|
5219
|
+
return path16.join(getProjectRoot3(), CAPABILITIES_DIR2);
|
|
5342
5220
|
}
|
|
5343
5221
|
function getPluginManifestPath2(pluginKey) {
|
|
5344
|
-
return
|
|
5222
|
+
return path16.join(getProjectRoot3(), "node_modules", pluginKey, "manifest.json");
|
|
5345
5223
|
}
|
|
5346
5224
|
|
|
5347
5225
|
// src/commands/migration/versions/v001_capability/json-migrator/detector.ts
|
|
5348
5226
|
function detectJsonMigration() {
|
|
5349
5227
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
5350
|
-
const oldFilePath =
|
|
5228
|
+
const oldFilePath = path17.join(capabilitiesDir, "capabilities.json");
|
|
5351
5229
|
if (!fs19.existsSync(oldFilePath)) {
|
|
5352
5230
|
return {
|
|
5353
5231
|
needsMigration: false,
|
|
@@ -5407,7 +5285,7 @@ async function check(options) {
|
|
|
5407
5285
|
|
|
5408
5286
|
// src/commands/migration/versions/v001_capability/json-migrator/index.ts
|
|
5409
5287
|
import fs20 from "fs";
|
|
5410
|
-
import
|
|
5288
|
+
import path18 from "path";
|
|
5411
5289
|
|
|
5412
5290
|
// src/commands/migration/versions/v001_capability/mapping.ts
|
|
5413
5291
|
var DEFAULT_PLUGIN_VERSION = "1.0.0";
|
|
@@ -5647,7 +5525,7 @@ function loadExistingCapabilities() {
|
|
|
5647
5525
|
continue;
|
|
5648
5526
|
}
|
|
5649
5527
|
try {
|
|
5650
|
-
const filePath =
|
|
5528
|
+
const filePath = path18.join(capabilitiesDir, file);
|
|
5651
5529
|
const content = fs20.readFileSync(filePath, "utf-8");
|
|
5652
5530
|
const capability = JSON.parse(content);
|
|
5653
5531
|
if (capability.id && capability.pluginKey) {
|
|
@@ -5706,7 +5584,7 @@ async function migrateJsonFiles(options) {
|
|
|
5706
5584
|
}
|
|
5707
5585
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
5708
5586
|
for (const cap of newCapabilities) {
|
|
5709
|
-
const filePath =
|
|
5587
|
+
const filePath = path18.join(capabilitiesDir, `${cap.id}.json`);
|
|
5710
5588
|
const content = JSON.stringify(cap, null, 2);
|
|
5711
5589
|
fs20.writeFileSync(filePath, content, "utf-8");
|
|
5712
5590
|
console.log(` \u2713 Created: ${cap.id}.json`);
|
|
@@ -5800,12 +5678,12 @@ async function installPlugins(capabilities, options) {
|
|
|
5800
5678
|
}
|
|
5801
5679
|
|
|
5802
5680
|
// src/commands/migration/versions/v001_capability/code-migrator/index.ts
|
|
5803
|
-
import
|
|
5681
|
+
import path20 from "path";
|
|
5804
5682
|
import { Project as Project3 } from "ts-morph";
|
|
5805
5683
|
|
|
5806
5684
|
// src/commands/migration/versions/v001_capability/code-migrator/scanner.ts
|
|
5807
5685
|
import fs22 from "fs";
|
|
5808
|
-
import
|
|
5686
|
+
import path19 from "path";
|
|
5809
5687
|
var EXCLUDED_DIRS = [
|
|
5810
5688
|
"node_modules",
|
|
5811
5689
|
"dist",
|
|
@@ -5822,7 +5700,7 @@ var EXCLUDED_PATTERNS = [
|
|
|
5822
5700
|
function scanDirectory(dir, files = []) {
|
|
5823
5701
|
const entries = fs22.readdirSync(dir, { withFileTypes: true });
|
|
5824
5702
|
for (const entry of entries) {
|
|
5825
|
-
const fullPath =
|
|
5703
|
+
const fullPath = path19.join(dir, entry.name);
|
|
5826
5704
|
if (entry.isDirectory()) {
|
|
5827
5705
|
if (EXCLUDED_DIRS.includes(entry.name)) {
|
|
5828
5706
|
continue;
|
|
@@ -5838,7 +5716,7 @@ function scanDirectory(dir, files = []) {
|
|
|
5838
5716
|
return files;
|
|
5839
5717
|
}
|
|
5840
5718
|
function scanServerFiles() {
|
|
5841
|
-
const serverDir =
|
|
5719
|
+
const serverDir = path19.join(getProjectRoot3(), "server");
|
|
5842
5720
|
if (!fs22.existsSync(serverDir)) {
|
|
5843
5721
|
return [];
|
|
5844
5722
|
}
|
|
@@ -6222,7 +6100,7 @@ function analyzeFile(project, filePath, actionNameMap) {
|
|
|
6222
6100
|
const callSites = analyzeCallSites(sourceFile, imports);
|
|
6223
6101
|
const classInfo = analyzeClass(sourceFile);
|
|
6224
6102
|
const { canMigrate, reason } = canAutoMigrate(classInfo);
|
|
6225
|
-
const relativePath =
|
|
6103
|
+
const relativePath = path20.relative(getProjectRoot3(), filePath);
|
|
6226
6104
|
return {
|
|
6227
6105
|
filePath: relativePath,
|
|
6228
6106
|
imports,
|
|
@@ -6233,7 +6111,7 @@ function analyzeFile(project, filePath, actionNameMap) {
|
|
|
6233
6111
|
};
|
|
6234
6112
|
}
|
|
6235
6113
|
function migrateFile(project, analysis, dryRun) {
|
|
6236
|
-
const absolutePath =
|
|
6114
|
+
const absolutePath = path20.join(getProjectRoot3(), analysis.filePath);
|
|
6237
6115
|
if (!analysis.canAutoMigrate) {
|
|
6238
6116
|
return {
|
|
6239
6117
|
filePath: analysis.filePath,
|
|
@@ -6337,12 +6215,12 @@ function getSuggestion(analysis) {
|
|
|
6337
6215
|
|
|
6338
6216
|
// src/commands/migration/versions/v001_capability/cleanup.ts
|
|
6339
6217
|
import fs23 from "fs";
|
|
6340
|
-
import
|
|
6218
|
+
import path21 from "path";
|
|
6341
6219
|
function cleanupOldFiles(capabilities, dryRun) {
|
|
6342
6220
|
const deletedFiles = [];
|
|
6343
6221
|
const errors = [];
|
|
6344
6222
|
const capabilitiesDir = getCapabilitiesDir2();
|
|
6345
|
-
const oldJsonPath =
|
|
6223
|
+
const oldJsonPath = path21.join(capabilitiesDir, "capabilities.json");
|
|
6346
6224
|
if (fs23.existsSync(oldJsonPath)) {
|
|
6347
6225
|
try {
|
|
6348
6226
|
if (!dryRun) {
|
|
@@ -6354,7 +6232,7 @@ function cleanupOldFiles(capabilities, dryRun) {
|
|
|
6354
6232
|
}
|
|
6355
6233
|
}
|
|
6356
6234
|
for (const cap of capabilities) {
|
|
6357
|
-
const tsFilePath =
|
|
6235
|
+
const tsFilePath = path21.join(capabilitiesDir, `${cap.id}.ts`);
|
|
6358
6236
|
if (fs23.existsSync(tsFilePath)) {
|
|
6359
6237
|
try {
|
|
6360
6238
|
if (!dryRun) {
|
|
@@ -6375,7 +6253,7 @@ function cleanupOldFiles(capabilities, dryRun) {
|
|
|
6375
6253
|
|
|
6376
6254
|
// src/commands/migration/versions/v001_capability/report-generator.ts
|
|
6377
6255
|
import fs24 from "fs";
|
|
6378
|
-
import
|
|
6256
|
+
import path22 from "path";
|
|
6379
6257
|
var REPORT_FILE = "capability-migration-report.md";
|
|
6380
6258
|
function printSummary(result) {
|
|
6381
6259
|
const { jsonMigration, pluginInstallation, codeMigration, cleanup } = result;
|
|
@@ -6541,11 +6419,11 @@ async function generateReport(result) {
|
|
|
6541
6419
|
if (!fs24.existsSync(logDir)) {
|
|
6542
6420
|
return;
|
|
6543
6421
|
}
|
|
6544
|
-
const reportDir =
|
|
6422
|
+
const reportDir = path22.join(logDir, "migration");
|
|
6545
6423
|
if (!fs24.existsSync(reportDir)) {
|
|
6546
6424
|
fs24.mkdirSync(reportDir, { recursive: true });
|
|
6547
6425
|
}
|
|
6548
|
-
const reportPath =
|
|
6426
|
+
const reportPath = path22.join(reportDir, REPORT_FILE);
|
|
6549
6427
|
fs24.writeFileSync(reportPath, lines.join("\n"), "utf-8");
|
|
6550
6428
|
console.log(`\u{1F4C4} Report generated: ${reportPath}`);
|
|
6551
6429
|
}
|
|
@@ -7078,7 +6956,7 @@ var migrationCommand = {
|
|
|
7078
6956
|
};
|
|
7079
6957
|
|
|
7080
6958
|
// src/commands/read-logs/index.ts
|
|
7081
|
-
import
|
|
6959
|
+
import path23 from "path";
|
|
7082
6960
|
|
|
7083
6961
|
// src/commands/read-logs/std-utils.ts
|
|
7084
6962
|
import fs25 from "fs";
|
|
@@ -7980,30 +7858,30 @@ async function readLogsJsonResult(options) {
|
|
|
7980
7858
|
};
|
|
7981
7859
|
}
|
|
7982
7860
|
function resolveLogFilePath(logDir, type) {
|
|
7983
|
-
const base =
|
|
7861
|
+
const base = path23.isAbsolute(logDir) ? logDir : path23.join(process.cwd(), logDir);
|
|
7984
7862
|
if (type === "server") {
|
|
7985
|
-
return
|
|
7863
|
+
return path23.join(base, "server.log");
|
|
7986
7864
|
}
|
|
7987
7865
|
if (type === "trace") {
|
|
7988
|
-
return
|
|
7866
|
+
return path23.join(base, "trace.log");
|
|
7989
7867
|
}
|
|
7990
7868
|
if (type === "server-std") {
|
|
7991
|
-
return
|
|
7869
|
+
return path23.join(base, "server.std.log");
|
|
7992
7870
|
}
|
|
7993
7871
|
if (type === "client-std") {
|
|
7994
|
-
return
|
|
7872
|
+
return path23.join(base, "client.std.log");
|
|
7995
7873
|
}
|
|
7996
7874
|
if (type === "dev") {
|
|
7997
|
-
return
|
|
7875
|
+
return path23.join(base, "dev.log");
|
|
7998
7876
|
}
|
|
7999
7877
|
if (type === "dev-std") {
|
|
8000
|
-
return
|
|
7878
|
+
return path23.join(base, "dev.std.log");
|
|
8001
7879
|
}
|
|
8002
7880
|
if (type === "install-dep-std") {
|
|
8003
|
-
return
|
|
7881
|
+
return path23.join(base, "install-dep.std.log");
|
|
8004
7882
|
}
|
|
8005
7883
|
if (type === "browser") {
|
|
8006
|
-
return
|
|
7884
|
+
return path23.join(base, "browser.log");
|
|
8007
7885
|
}
|
|
8008
7886
|
throw new Error(`Unsupported log type: ${type}`);
|
|
8009
7887
|
}
|
|
@@ -8181,8 +8059,8 @@ function camelToKebab(str) {
|
|
|
8181
8059
|
|
|
8182
8060
|
// src/commands/build/upload-static.handler.ts
|
|
8183
8061
|
import * as fs28 from "fs";
|
|
8184
|
-
import * as
|
|
8185
|
-
import * as
|
|
8062
|
+
import * as os2 from "os";
|
|
8063
|
+
import * as path24 from "path";
|
|
8186
8064
|
import { execFileSync } from "child_process";
|
|
8187
8065
|
function readCredentialsFromEnv() {
|
|
8188
8066
|
const uploadPrefix = process.env.STATIC_UPLOAD_PREFIX;
|
|
@@ -8206,7 +8084,7 @@ async function uploadStatic(options) {
|
|
|
8206
8084
|
endpoint = UPLOAD_STATIC_DEFAULTS.endpoint,
|
|
8207
8085
|
region = UPLOAD_STATIC_DEFAULTS.region
|
|
8208
8086
|
} = options;
|
|
8209
|
-
const resolvedStaticDir =
|
|
8087
|
+
const resolvedStaticDir = path24.resolve(staticDir);
|
|
8210
8088
|
if (!fs28.existsSync(resolvedStaticDir)) {
|
|
8211
8089
|
console.error(`${LOG_PREFIX} \u76EE\u5F55\u4E0D\u5B58\u5728: ${resolvedStaticDir}\uFF0C\u8DF3\u8FC7\u4E0A\u4F20`);
|
|
8212
8090
|
return;
|
|
@@ -8240,7 +8118,7 @@ async function uploadStatic(options) {
|
|
|
8240
8118
|
({ AccessKeyID: accessKeyID, SecretAccessKey: secretAccessKey, SessionToken: sessionToken } = uploadCredential);
|
|
8241
8119
|
}
|
|
8242
8120
|
console.error(`${LOG_PREFIX} \u4E0A\u4F20\u76EE\u6807: ${uploadPrefix}`);
|
|
8243
|
-
const confPath =
|
|
8121
|
+
const confPath = path24.join(os2.tmpdir(), `.tosutilconfig-static-${process.pid}`);
|
|
8244
8122
|
fs28.writeFileSync(confPath, "");
|
|
8245
8123
|
try {
|
|
8246
8124
|
console.error(`${LOG_PREFIX} \u914D\u7F6E tosutil...`);
|
|
@@ -8275,7 +8153,7 @@ async function uploadStatic(options) {
|
|
|
8275
8153
|
}
|
|
8276
8154
|
}
|
|
8277
8155
|
function resolveTosutilPath(tosutilPath) {
|
|
8278
|
-
if (
|
|
8156
|
+
if (path24.isAbsolute(tosutilPath)) {
|
|
8279
8157
|
return fs28.existsSync(tosutilPath) ? tosutilPath : null;
|
|
8280
8158
|
}
|
|
8281
8159
|
try {
|
|
@@ -8368,3254 +8246,62 @@ async function preUploadStatic(options) {
|
|
|
8368
8246
|
}
|
|
8369
8247
|
}
|
|
8370
8248
|
|
|
8371
|
-
// src/commands/build/
|
|
8372
|
-
|
|
8373
|
-
|
|
8374
|
-
|
|
8375
|
-
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
import { spawn as spawn2 } from "child_process";
|
|
8379
|
-
import { createHash } from "crypto";
|
|
8380
|
-
import { build } from "esbuild";
|
|
8381
|
-
import { parse } from "acorn";
|
|
8382
|
-
import { simple as walkSimple } from "acorn-walk";
|
|
8383
|
-
var OPTIONAL_NEST_DEPENDENCIES = [
|
|
8384
|
-
"@nestjs/microservices",
|
|
8385
|
-
"@nestjs/microservices/microservices-module",
|
|
8386
|
-
"@nestjs/websockets/socket-module",
|
|
8387
|
-
"@node-rs/xxhash",
|
|
8388
|
-
"fsevents"
|
|
8389
|
-
];
|
|
8390
|
-
var BUILTINS = /* @__PURE__ */ new Set([
|
|
8391
|
-
...builtinModules,
|
|
8392
|
-
...builtinModules.map((name) => `node:${name}`)
|
|
8393
|
-
]);
|
|
8394
|
-
var DEFAULT_COMPILED_ENTRIES = [
|
|
8395
|
-
"dist/server/main.js",
|
|
8396
|
-
"dist/main.js"
|
|
8397
|
-
];
|
|
8398
|
-
var BUILD_ONLY_SERVER_CACHE_PACKAGES = [
|
|
8399
|
-
"@lark-apaas/nestjs-openapi-devtools",
|
|
8400
|
-
"@hey-api/openapi-ts",
|
|
8401
|
-
"typescript",
|
|
8402
|
-
"jiti",
|
|
8403
|
-
"nypm"
|
|
8404
|
-
];
|
|
8405
|
-
function workspaceSourceSha256(projectRoot) {
|
|
8406
|
-
const files = [];
|
|
8407
|
-
const visit = (directory) => {
|
|
8408
|
-
if (!fs29.existsSync(directory)) return;
|
|
8409
|
-
for (const entry of fs29.readdirSync(directory, { withFileTypes: true })) {
|
|
8410
|
-
const candidate = path26.join(directory, entry.name);
|
|
8411
|
-
if (entry.isSymbolicLink()) continue;
|
|
8412
|
-
if (entry.isDirectory()) visit(candidate);
|
|
8413
|
-
else if (entry.isFile()) files.push(candidate);
|
|
8414
|
-
}
|
|
8415
|
-
};
|
|
8416
|
-
for (const root of ["server", "shared", "src"]) {
|
|
8417
|
-
visit(path26.join(projectRoot, root));
|
|
8418
|
-
}
|
|
8419
|
-
const hash = createHash("sha256");
|
|
8420
|
-
for (const file of files.sort()) {
|
|
8421
|
-
hash.update(path26.relative(projectRoot, file).split(path26.sep).join("/"));
|
|
8422
|
-
hash.update("\0");
|
|
8423
|
-
hash.update(fs29.readFileSync(file));
|
|
8424
|
-
hash.update("\0");
|
|
8425
|
-
}
|
|
8426
|
-
return hash.digest("hex");
|
|
8427
|
-
}
|
|
8428
|
-
function absolute(root, candidate) {
|
|
8429
|
-
return path26.isAbsolute(candidate) ? candidate : path26.resolve(root, candidate);
|
|
8430
|
-
}
|
|
8431
|
-
function isPathInside(root, candidate) {
|
|
8432
|
-
const relative = path26.relative(root, candidate);
|
|
8433
|
-
return relative === "" || !relative.startsWith("..") && !path26.isAbsolute(relative);
|
|
8434
|
-
}
|
|
8435
|
-
function validateOwnedServerOutput(projectRoot, outfile, metadataFile) {
|
|
8436
|
-
const cacheRoot = path26.join(projectRoot, ".miaoda-cache");
|
|
8437
|
-
if (!isPathInside(cacheRoot, outfile) || path26.basename(path26.dirname(outfile)) !== "server" || path26.basename(outfile) !== "server.bundle.cjs" || metadataFile !== `${outfile}.meta.json`) {
|
|
8438
|
-
return "server cache output must be <projectRoot>/.miaoda-cache/**/server/server.bundle.cjs with adjacent metadata";
|
|
8439
|
-
}
|
|
8440
|
-
let current = path26.dirname(outfile);
|
|
8441
|
-
while (current !== projectRoot) {
|
|
8442
|
-
if (fs29.existsSync(current) && fs29.lstatSync(current).isSymbolicLink()) {
|
|
8443
|
-
return `server cache output directory symlink is unsupported: ${current}`;
|
|
8444
|
-
}
|
|
8445
|
-
const parent = path26.dirname(current);
|
|
8446
|
-
if (parent === current || !isPathInside(projectRoot, parent)) {
|
|
8447
|
-
return "server cache output escaped project root";
|
|
8448
|
-
}
|
|
8449
|
-
current = parent;
|
|
8450
|
-
}
|
|
8451
|
-
return void 0;
|
|
8452
|
-
}
|
|
8453
|
-
function resolveCompiledEntry(projectRoot, requestedEntry) {
|
|
8454
|
-
if (requestedEntry) {
|
|
8455
|
-
const entry = absolute(projectRoot, requestedEntry);
|
|
8456
|
-
return fs29.existsSync(entry) ? { entry, reasons: [] } : { reasons: [`compiled entry missing: ${entry}`] };
|
|
8457
|
-
}
|
|
8458
|
-
const candidates = DEFAULT_COMPILED_ENTRIES.map(
|
|
8459
|
-
(candidate) => absolute(projectRoot, candidate)
|
|
8460
|
-
).filter((candidate) => fs29.existsSync(candidate));
|
|
8461
|
-
if (candidates.length === 1) return { entry: candidates[0], reasons: [] };
|
|
8462
|
-
if (candidates.length > 1) {
|
|
8463
|
-
return {
|
|
8464
|
-
reasons: [
|
|
8465
|
-
`compiled entry is ambiguous; pass --entry explicitly: ${candidates.join(", ")}`
|
|
8466
|
-
]
|
|
8467
|
-
};
|
|
8468
|
-
}
|
|
8469
|
-
return {
|
|
8470
|
-
reasons: [
|
|
8471
|
-
`compiled entry missing; checked: ${DEFAULT_COMPILED_ENTRIES.map(
|
|
8472
|
-
(candidate) => absolute(projectRoot, candidate)
|
|
8473
|
-
).join(", ")}`
|
|
8474
|
-
]
|
|
8475
|
-
};
|
|
8476
|
-
}
|
|
8477
|
-
function optionalDependencyStubPlugin() {
|
|
8478
|
-
const escaped = OPTIONAL_NEST_DEPENDENCIES.map(
|
|
8479
|
-
(name) => name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
|
8480
|
-
);
|
|
8481
|
-
const filter = new RegExp(`^(?:${escaped.join("|")})$`);
|
|
8482
|
-
return {
|
|
8483
|
-
name: "miaoda-optional-nest-dependency-stubs",
|
|
8484
|
-
setup(esbuild) {
|
|
8485
|
-
esbuild.onResolve({ filter }, (args) => ({
|
|
8486
|
-
path: args.path,
|
|
8487
|
-
namespace: "miaoda-optional-nest-dependency"
|
|
8488
|
-
}));
|
|
8489
|
-
esbuild.onLoad(
|
|
8490
|
-
{ filter: /.*/, namespace: "miaoda-optional-nest-dependency" },
|
|
8491
|
-
(args) => ({
|
|
8492
|
-
contents: `const error = new Error(${JSON.stringify(
|
|
8493
|
-
`Optional dependency is unavailable in cache runtime: ${args.path}`
|
|
8494
|
-
)}); error.code = 'MODULE_NOT_FOUND'; throw error;`,
|
|
8495
|
-
loader: "js"
|
|
8496
|
-
})
|
|
8497
|
-
);
|
|
8498
|
-
}
|
|
8499
|
-
};
|
|
8500
|
-
}
|
|
8501
|
-
function classTransformerStorageResolver(projectRoot) {
|
|
8502
|
-
const projectRequire = createRequire3(path26.join(projectRoot, "package.json"));
|
|
8503
|
-
return {
|
|
8504
|
-
name: "miaoda-class-transformer-storage-resolver",
|
|
8505
|
-
setup(esbuild) {
|
|
8506
|
-
esbuild.onResolve({ filter: /^class-transformer\/storage$/ }, () => {
|
|
8507
|
-
try {
|
|
8508
|
-
return {
|
|
8509
|
-
path: projectRequire.resolve("class-transformer/cjs/storage.js")
|
|
8510
|
-
};
|
|
8511
|
-
} catch {
|
|
8512
|
-
return void 0;
|
|
8513
|
-
}
|
|
8514
|
-
});
|
|
8515
|
-
}
|
|
8516
|
-
};
|
|
8517
|
-
}
|
|
8518
|
-
function resolveProjectPackage(projectRoot, specifier) {
|
|
8519
|
-
return createRequire3(path26.join(projectRoot, "package.json")).resolve(
|
|
8520
|
-
specifier
|
|
8521
|
-
);
|
|
8522
|
-
}
|
|
8523
|
-
function fullstackNestRuntimeResolver(projectRoot) {
|
|
8524
|
-
return {
|
|
8525
|
-
name: "miaoda-fullstack-nest-runtime-resolver",
|
|
8526
|
-
setup(esbuild) {
|
|
8527
|
-
esbuild.onResolve(
|
|
8528
|
-
{ filter: /^@lark-apaas\/fullstack-nestjs-core$/ },
|
|
8529
|
-
() => {
|
|
8530
|
-
try {
|
|
8531
|
-
return {
|
|
8532
|
-
path: resolveProjectPackage(
|
|
8533
|
-
projectRoot,
|
|
8534
|
-
"@lark-apaas/fullstack-nestjs-core/runtime"
|
|
8535
|
-
)
|
|
8536
|
-
};
|
|
8537
|
-
} catch (runtimeError) {
|
|
8538
|
-
try {
|
|
8539
|
-
return {
|
|
8540
|
-
path: resolveProjectPackage(
|
|
8541
|
-
projectRoot,
|
|
8542
|
-
"@lark-apaas/fullstack-nestjs-core"
|
|
8543
|
-
)
|
|
8544
|
-
};
|
|
8545
|
-
} catch (rootError) {
|
|
8546
|
-
return {
|
|
8547
|
-
errors: [
|
|
8548
|
-
{
|
|
8549
|
-
text: `@lark-apaas/fullstack-nestjs-core cannot be resolved from the project: runtime=${runtimeError instanceof Error ? runtimeError.message : String(runtimeError)}; root=${rootError instanceof Error ? rootError.message : String(rootError)}`
|
|
8550
|
-
}
|
|
8551
|
-
]
|
|
8552
|
-
};
|
|
8553
|
-
}
|
|
8554
|
-
}
|
|
8555
|
-
}
|
|
8556
|
-
);
|
|
8557
|
-
}
|
|
8558
|
-
};
|
|
8559
|
-
}
|
|
8560
|
-
function legacyFullstackNestOpenApiStub(projectRoot) {
|
|
8561
|
-
let runtimeOnlyEntryAvailable = false;
|
|
8562
|
-
try {
|
|
8563
|
-
resolveProjectPackage(
|
|
8564
|
-
projectRoot,
|
|
8565
|
-
"@lark-apaas/fullstack-nestjs-core/runtime"
|
|
8566
|
-
);
|
|
8567
|
-
runtimeOnlyEntryAvailable = true;
|
|
8568
|
-
} catch {
|
|
8569
|
-
}
|
|
8570
|
-
return {
|
|
8571
|
-
name: "miaoda-legacy-nest-openapi-stub",
|
|
8572
|
-
setup(esbuild) {
|
|
8573
|
-
if (runtimeOnlyEntryAvailable) return;
|
|
8574
|
-
esbuild.onResolve(
|
|
8575
|
-
{ filter: /^@lark-apaas\/nestjs-openapi-devtools$/ },
|
|
8576
|
-
() => ({
|
|
8577
|
-
path: "@lark-apaas/nestjs-openapi-devtools",
|
|
8578
|
-
namespace: "miaoda-legacy-nest-openapi-stub"
|
|
8579
|
-
})
|
|
8580
|
-
);
|
|
8581
|
-
esbuild.onLoad(
|
|
8582
|
-
{ filter: /.*/, namespace: "miaoda-legacy-nest-openapi-stub" },
|
|
8583
|
-
() => ({
|
|
8584
|
-
contents: "class DisabledOpenApiModule { static async mount() {} }\nmodule.exports = { DevToolsModule: DisabledOpenApiModule, DevToolsV2Module: DisabledOpenApiModule };",
|
|
8585
|
-
loader: "js"
|
|
8586
|
-
})
|
|
8587
|
-
);
|
|
8588
|
-
}
|
|
8589
|
-
};
|
|
8590
|
-
}
|
|
8591
|
-
function rejectNativeAddonsPlugin() {
|
|
8592
|
-
return {
|
|
8593
|
-
name: "miaoda-reject-native-addons",
|
|
8594
|
-
setup(esbuild) {
|
|
8595
|
-
esbuild.onResolve({ filter: /\.node$/ }, (args) => {
|
|
8596
|
-
if (args.path.startsWith(".") && fs29.existsSync(path26.resolve(args.resolveDir, `${args.path}.js`))) {
|
|
8597
|
-
return void 0;
|
|
8598
|
-
}
|
|
8599
|
-
return {
|
|
8600
|
-
errors: [
|
|
8601
|
-
{
|
|
8602
|
-
text: `native addons are unsupported in the server cache bundle: ${args.path}`
|
|
8603
|
-
}
|
|
8604
|
-
]
|
|
8605
|
-
};
|
|
8606
|
-
});
|
|
8607
|
-
}
|
|
8608
|
-
};
|
|
8609
|
-
}
|
|
8610
|
-
function findPackageRoot(entryPath) {
|
|
8611
|
-
let current = path26.dirname(entryPath);
|
|
8612
|
-
while (current !== path26.dirname(current)) {
|
|
8613
|
-
if (fs29.existsSync(path26.join(current, "package.json"))) return current;
|
|
8614
|
-
current = path26.dirname(current);
|
|
8615
|
-
}
|
|
8616
|
-
return void 0;
|
|
8617
|
-
}
|
|
8618
|
-
function canonicalSourcePath(projectRoot, sourcePath) {
|
|
8619
|
-
const relativeOrigin = path26.relative(projectRoot, sourcePath).split(path26.sep).join("/");
|
|
8620
|
-
const nestedPackageMarker = "/node_modules/";
|
|
8621
|
-
const nestedPackageIndex = relativeOrigin.lastIndexOf(nestedPackageMarker);
|
|
8622
|
-
const firstPackageIndex = relativeOrigin.indexOf("node_modules/");
|
|
8623
|
-
if (nestedPackageIndex >= 0) {
|
|
8624
|
-
return `node_modules/${relativeOrigin.slice(
|
|
8625
|
-
nestedPackageIndex + nestedPackageMarker.length
|
|
8626
|
-
)}`;
|
|
8627
|
-
}
|
|
8628
|
-
return firstPackageIndex > 0 ? relativeOrigin.slice(firstPackageIndex) : relativeOrigin;
|
|
8629
|
-
}
|
|
8630
|
-
function parseJavaScriptSource(source) {
|
|
8631
|
-
try {
|
|
8632
|
-
return parse(source, {
|
|
8633
|
-
ecmaVersion: "latest",
|
|
8634
|
-
sourceType: "module",
|
|
8635
|
-
allowHashBang: true,
|
|
8636
|
-
locations: true
|
|
8637
|
-
});
|
|
8638
|
-
} catch {
|
|
8639
|
-
return parse(source, {
|
|
8640
|
-
ecmaVersion: "latest",
|
|
8641
|
-
sourceType: "script",
|
|
8642
|
-
allowHashBang: true,
|
|
8643
|
-
allowReturnOutsideFunction: true,
|
|
8644
|
-
locations: true
|
|
8249
|
+
// src/commands/build/index.ts
|
|
8250
|
+
var getTokenCommand = {
|
|
8251
|
+
name: "get-token",
|
|
8252
|
+
description: "Get artifact upload credential (STI token)",
|
|
8253
|
+
register(program) {
|
|
8254
|
+
program.command(this.name).description(this.description).requiredOption("--app-id <id>", "Application ID").requiredOption("--scene <scene>", "Build scene (pipeline, static)").option("--commit-id <id>", "Git commit ID (required for pipeline scene)").action(async (options) => {
|
|
8255
|
+
await getToken(options);
|
|
8645
8256
|
});
|
|
8646
8257
|
}
|
|
8647
|
-
}
|
|
8648
|
-
|
|
8649
|
-
|
|
8650
|
-
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
|
|
8654
|
-
|
|
8655
|
-
}
|
|
8656
|
-
return void 0;
|
|
8657
|
-
}
|
|
8658
|
-
function isImportMetaUrl(node) {
|
|
8659
|
-
return Boolean(
|
|
8660
|
-
node?.type === "MemberExpression" && staticPropertyName(node) === "url" && node.object?.type === "MetaProperty" && node.object.meta?.name === "import" && node.object.property?.name === "meta"
|
|
8661
|
-
);
|
|
8662
|
-
}
|
|
8663
|
-
function isBundleDirectoryExpression(node) {
|
|
8664
|
-
if (!node) return false;
|
|
8665
|
-
if (node.type === "Identifier" && node.name === "__dirname") return true;
|
|
8666
|
-
if (node.type !== "CallExpression") return false;
|
|
8667
|
-
const property = staticPropertyName(node.callee);
|
|
8668
|
-
if (property === "dirname" && (node.arguments[0]?.type === "Identifier" && node.arguments[0].name === "__filename" ? true : node.arguments[0]?.type === "CallExpression" && staticPropertyName(node.arguments[0].callee) === "fileURLToPath" && isImportMetaUrl(node.arguments[0].arguments[0]))) {
|
|
8669
|
-
return true;
|
|
8670
|
-
}
|
|
8671
|
-
return false;
|
|
8672
|
-
}
|
|
8673
|
-
function canonicalRuntimeAssetPath(candidate) {
|
|
8674
|
-
const normalized = candidate.split(path26.sep).join("/");
|
|
8675
|
-
if (!normalized || normalized === "." || normalized !== path26.posix.normalize(normalized) || normalized.startsWith("../") || path26.posix.isAbsolute(normalized) || normalized.includes("\\")) {
|
|
8676
|
-
return void 0;
|
|
8677
|
-
}
|
|
8678
|
-
return normalized;
|
|
8679
|
-
}
|
|
8680
|
-
function resolveRuntimeAssetExpression(projectRoot, sourcePath, node) {
|
|
8681
|
-
const direct = staticStringValue(node);
|
|
8682
|
-
if (direct !== void 0 && !path26.isAbsolute(direct)) {
|
|
8683
|
-
const destination2 = canonicalRuntimeAssetPath(direct);
|
|
8684
|
-
return destination2 ? { source: path26.resolve(projectRoot, direct), destination: destination2 } : void 0;
|
|
8685
|
-
}
|
|
8686
|
-
if (node?.type === "NewExpression" && node.callee?.type === "Identifier" && node.callee.name === "URL") {
|
|
8687
|
-
const relative2 = staticStringValue(node.arguments[0]);
|
|
8688
|
-
if (relative2 && isImportMetaUrl(node.arguments[1])) {
|
|
8689
|
-
const destination2 = canonicalRuntimeAssetPath(
|
|
8690
|
-
relative2.replace(/^\.\//, "")
|
|
8691
|
-
);
|
|
8692
|
-
return destination2 ? {
|
|
8693
|
-
source: path26.resolve(path26.dirname(sourcePath), relative2),
|
|
8694
|
-
destination: destination2
|
|
8695
|
-
} : void 0;
|
|
8696
|
-
}
|
|
8697
|
-
}
|
|
8698
|
-
if (node?.type !== "CallExpression") return void 0;
|
|
8699
|
-
const property = staticPropertyName(node.callee);
|
|
8700
|
-
if (!["join", "resolve"].includes(property ?? "")) return void 0;
|
|
8701
|
-
if (!isBundleDirectoryExpression(node.arguments[0])) return void 0;
|
|
8702
|
-
const segments = node.arguments.slice(1).map(staticStringValue);
|
|
8703
|
-
if (segments.some((segment) => segment === void 0)) return void 0;
|
|
8704
|
-
const relative = path26.join(...segments);
|
|
8705
|
-
const destination = canonicalRuntimeAssetPath(relative);
|
|
8706
|
-
return destination ? {
|
|
8707
|
-
source: path26.resolve(path26.dirname(sourcePath), relative),
|
|
8708
|
-
destination
|
|
8709
|
-
} : void 0;
|
|
8710
|
-
}
|
|
8711
|
-
function isFsModuleSpecifier(node) {
|
|
8712
|
-
return ["fs", "node:fs"].includes(staticStringValue(node) ?? "");
|
|
8713
|
-
}
|
|
8714
|
-
function containsFsModuleLoad(node) {
|
|
8715
|
-
if (!node) return false;
|
|
8716
|
-
if (node.type === "CallExpression" && node.callee?.type === "Identifier" && node.callee.name === "require" && isFsModuleSpecifier(node.arguments[0])) {
|
|
8717
|
-
return true;
|
|
8718
|
-
}
|
|
8719
|
-
if (node.type === "CallExpression") {
|
|
8720
|
-
return node.arguments.some(
|
|
8721
|
-
(argument) => containsFsModuleLoad(argument)
|
|
8722
|
-
);
|
|
8723
|
-
}
|
|
8724
|
-
if (node.type === "MemberExpression") {
|
|
8725
|
-
return containsFsModuleLoad(node.object);
|
|
8726
|
-
}
|
|
8727
|
-
if (node.type === "ChainExpression") {
|
|
8728
|
-
return containsFsModuleLoad(node.expression);
|
|
8729
|
-
}
|
|
8730
|
-
return false;
|
|
8731
|
-
}
|
|
8732
|
-
function rootIdentifier(node) {
|
|
8733
|
-
let current = node;
|
|
8734
|
-
while (current?.type === "MemberExpression") current = current.object;
|
|
8735
|
-
return current?.type === "Identifier" ? current.name : void 0;
|
|
8736
|
-
}
|
|
8737
|
-
function collectFsBindings(ast, runtimeFsMethods) {
|
|
8738
|
-
const namespaces = /* @__PURE__ */ new Set();
|
|
8739
|
-
const methods = /* @__PURE__ */ new Set();
|
|
8740
|
-
walkSimple(ast, {
|
|
8741
|
-
ImportDeclaration(node) {
|
|
8742
|
-
if (!isFsModuleSpecifier(node.source)) return;
|
|
8743
|
-
for (const specifier of node.specifiers ?? []) {
|
|
8744
|
-
if (specifier.type === "ImportDefaultSpecifier" || specifier.type === "ImportNamespaceSpecifier") {
|
|
8745
|
-
namespaces.add(specifier.local.name);
|
|
8746
|
-
continue;
|
|
8747
|
-
}
|
|
8748
|
-
if (specifier.type !== "ImportSpecifier") continue;
|
|
8749
|
-
const imported = specifier.imported.type === "Identifier" ? specifier.imported.name : specifier.imported.value;
|
|
8750
|
-
if (typeof imported === "string" && runtimeFsMethods.has(imported)) {
|
|
8751
|
-
methods.add(specifier.local.name);
|
|
8752
|
-
}
|
|
8753
|
-
}
|
|
8754
|
-
},
|
|
8755
|
-
VariableDeclarator(node) {
|
|
8756
|
-
if (!containsFsModuleLoad(node.init)) return;
|
|
8757
|
-
if (node.id?.type === "Identifier") {
|
|
8758
|
-
const importedMethod = staticPropertyName(node.init);
|
|
8759
|
-
if (importedMethod && runtimeFsMethods.has(importedMethod)) {
|
|
8760
|
-
methods.add(node.id.name);
|
|
8761
|
-
} else {
|
|
8762
|
-
namespaces.add(node.id.name);
|
|
8763
|
-
}
|
|
8764
|
-
return;
|
|
8765
|
-
}
|
|
8766
|
-
if (node.id?.type === "ObjectPattern") {
|
|
8767
|
-
for (const property of node.id.properties ?? []) {
|
|
8768
|
-
if (property.type === "RestElement") continue;
|
|
8769
|
-
const imported = property.key.type === "Identifier" ? property.key.name : staticStringValue(property.key);
|
|
8770
|
-
const local = property.value.type === "Identifier" ? property.value.name : void 0;
|
|
8771
|
-
if (typeof imported === "string" && runtimeFsMethods.has(imported) && typeof local === "string") {
|
|
8772
|
-
methods.add(local);
|
|
8773
|
-
}
|
|
8774
|
-
}
|
|
8775
|
-
}
|
|
8776
|
-
}
|
|
8777
|
-
});
|
|
8778
|
-
return { namespaces, methods };
|
|
8779
|
-
}
|
|
8780
|
-
function resolveFsMethod(callee, bindings, runtimeFsMethods) {
|
|
8781
|
-
if (callee.type === "Identifier" && bindings.methods.has(callee.name)) {
|
|
8782
|
-
return callee.name;
|
|
8783
|
-
}
|
|
8784
|
-
const method = staticPropertyName(callee);
|
|
8785
|
-
if (!method || !runtimeFsMethods.has(method)) return void 0;
|
|
8786
|
-
if (callee.type !== "MemberExpression") return void 0;
|
|
8787
|
-
if (containsFsModuleLoad(callee.object)) return method;
|
|
8788
|
-
const root = rootIdentifier(callee.object);
|
|
8789
|
-
return root && bindings.namespaces.has(root) ? method : void 0;
|
|
8790
|
-
}
|
|
8791
|
-
function isChildProcessModuleSpecifier(node) {
|
|
8792
|
-
return ["child_process", "node:child_process"].includes(
|
|
8793
|
-
staticStringValue(node) ?? ""
|
|
8794
|
-
);
|
|
8795
|
-
}
|
|
8796
|
-
function containsChildProcessLoad(node) {
|
|
8797
|
-
if (!node) return false;
|
|
8798
|
-
if (node.type === "CallExpression" && node.callee?.type === "Identifier" && node.callee.name === "require" && isChildProcessModuleSpecifier(node.arguments[0])) {
|
|
8799
|
-
return true;
|
|
8258
|
+
};
|
|
8259
|
+
var uploadStaticCommand = {
|
|
8260
|
+
name: "upload-static",
|
|
8261
|
+
description: "Upload shared/static files to TOS",
|
|
8262
|
+
register(program) {
|
|
8263
|
+
program.command(this.name).description(this.description).requiredOption("--app-id <id>", "Application ID").option("--static-dir <dir>", "Static files directory", UPLOAD_STATIC_DEFAULTS.staticDir).option("--tosutil-path <path>", "Path to tosutil binary", UPLOAD_STATIC_DEFAULTS.tosutilPath).option("--endpoint <endpoint>", "TOS endpoint", UPLOAD_STATIC_DEFAULTS.endpoint).option("--region <region>", "TOS region", UPLOAD_STATIC_DEFAULTS.region).action(async (options) => {
|
|
8264
|
+
await uploadStatic(options);
|
|
8265
|
+
});
|
|
8800
8266
|
}
|
|
8801
|
-
|
|
8802
|
-
|
|
8267
|
+
};
|
|
8268
|
+
var preUploadStaticCommand = {
|
|
8269
|
+
name: "pre-upload-static",
|
|
8270
|
+
description: "Get TOS upload info and output as env vars for build.sh eval",
|
|
8271
|
+
register(program) {
|
|
8272
|
+
program.command(this.name).description(this.description).requiredOption("--app-id <id>", "Application ID").action(async (options) => {
|
|
8273
|
+
await preUploadStatic(options);
|
|
8274
|
+
});
|
|
8803
8275
|
}
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
|
|
8808
|
-
|
|
8809
|
-
|
|
8810
|
-
|
|
8811
|
-
|
|
8812
|
-
|
|
8813
|
-
|
|
8814
|
-
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
|
|
8818
|
-
|
|
8819
|
-
|
|
8820
|
-
|
|
8821
|
-
|
|
8822
|
-
|
|
8823
|
-
|
|
8824
|
-
|
|
8825
|
-
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
for (const property of node.id.properties ?? []) {
|
|
8830
|
-
const imported = property.type !== "RestElement" && property.key?.type === "Identifier" ? property.key.name : property.type !== "RestElement" ? staticStringValue(property.key) : void 0;
|
|
8831
|
-
if (property.type !== "RestElement" && imported === "fork" && property.value?.type === "Identifier") {
|
|
8832
|
-
methods.add(property.value.name);
|
|
8833
|
-
}
|
|
8834
|
-
}
|
|
8835
|
-
}
|
|
8836
|
-
}
|
|
8837
|
-
});
|
|
8838
|
-
return { namespaces, methods };
|
|
8839
|
-
}
|
|
8840
|
-
function isChildProcessFork(callee, bindings) {
|
|
8841
|
-
if (callee.type === "Identifier") return bindings.methods.has(callee.name);
|
|
8842
|
-
if (callee.type !== "MemberExpression" || staticPropertyName(callee) !== "fork") {
|
|
8843
|
-
return false;
|
|
8276
|
+
};
|
|
8277
|
+
var buildCommandGroup = {
|
|
8278
|
+
name: "build",
|
|
8279
|
+
description: "Build related commands",
|
|
8280
|
+
commands: [getTokenCommand, uploadStaticCommand, preUploadStaticCommand]
|
|
8281
|
+
};
|
|
8282
|
+
|
|
8283
|
+
// src/commands/index.ts
|
|
8284
|
+
var commands = [
|
|
8285
|
+
genDbSchemaCommand,
|
|
8286
|
+
syncCommand,
|
|
8287
|
+
upgradeCommand,
|
|
8288
|
+
actionPluginCommandGroup,
|
|
8289
|
+
capabilityCommandGroup,
|
|
8290
|
+
componentCommandGroup,
|
|
8291
|
+
migrationCommand,
|
|
8292
|
+
readLogsCommand,
|
|
8293
|
+
buildCommandGroup
|
|
8294
|
+
];
|
|
8295
|
+
|
|
8296
|
+
// src/index.ts
|
|
8297
|
+
for (const filename of [".env.local", ".env"]) {
|
|
8298
|
+
const envPath = path25.join(process.cwd(), filename);
|
|
8299
|
+
if (fs29.existsSync(envPath)) {
|
|
8300
|
+
dotenvConfig({ path: envPath });
|
|
8844
8301
|
}
|
|
8845
|
-
if (containsChildProcessLoad(callee.object)) return true;
|
|
8846
|
-
const root = rootIdentifier(callee.object);
|
|
8847
|
-
return Boolean(root && bindings.namespaces.has(root));
|
|
8848
8302
|
}
|
|
8849
|
-
|
|
8850
|
-
|
|
8851
|
-
const warnings = [];
|
|
8852
|
-
const runtimeFsMethods = /* @__PURE__ */ new Set([
|
|
8853
|
-
"readFile",
|
|
8854
|
-
"readFileSync",
|
|
8855
|
-
"createReadStream",
|
|
8856
|
-
"open",
|
|
8857
|
-
"openSync"
|
|
8858
|
-
]);
|
|
8859
|
-
for (const input of Object.keys(metafile.inputs).sort()) {
|
|
8860
|
-
if (!/\.(?:cjs|mjs|js)$/.test(input)) continue;
|
|
8861
|
-
const sourcePath = path26.resolve(projectRoot, input);
|
|
8862
|
-
if (!fs29.existsSync(sourcePath) || !fs29.statSync(sourcePath).isFile()) {
|
|
8863
|
-
continue;
|
|
8864
|
-
}
|
|
8865
|
-
const source = fs29.readFileSync(sourcePath, "utf8");
|
|
8866
|
-
const origin = canonicalSourcePath(projectRoot, sourcePath);
|
|
8867
|
-
const ast = parseJavaScriptSource(source);
|
|
8868
|
-
const fsBindings = collectFsBindings(ast, runtimeFsMethods);
|
|
8869
|
-
const childProcessBindings = collectChildProcessForkBindings(ast);
|
|
8870
|
-
const recordRuntimeAsset = (expressionNode) => {
|
|
8871
|
-
const resolved = resolveRuntimeAssetExpression(
|
|
8872
|
-
projectRoot,
|
|
8873
|
-
sourcePath,
|
|
8874
|
-
expressionNode
|
|
8875
|
-
);
|
|
8876
|
-
if (resolved && fs29.existsSync(resolved.source)) {
|
|
8877
|
-
candidates.push({ ...resolved, origin });
|
|
8878
|
-
return;
|
|
8879
|
-
}
|
|
8880
|
-
const expression = source.slice(
|
|
8881
|
-
expressionNode?.start ?? 0,
|
|
8882
|
-
expressionNode?.end ?? source.length
|
|
8883
|
-
);
|
|
8884
|
-
warnings.push({
|
|
8885
|
-
kind: resolved ? "missing-runtime-asset" : "dynamic-runtime-asset",
|
|
8886
|
-
source: origin,
|
|
8887
|
-
expressionHash: createHash("sha256").update(expression).digest("hex").slice(0, 16),
|
|
8888
|
-
message: resolved ? `Static runtime asset is unavailable at build time: ${resolved.destination}` : "Runtime asset path cannot be determined statically"
|
|
8889
|
-
});
|
|
8890
|
-
};
|
|
8891
|
-
walkSimple(ast, {
|
|
8892
|
-
CallExpression(node) {
|
|
8893
|
-
const method = resolveFsMethod(
|
|
8894
|
-
node.callee,
|
|
8895
|
-
fsBindings,
|
|
8896
|
-
runtimeFsMethods
|
|
8897
|
-
);
|
|
8898
|
-
if (method || isChildProcessFork(node.callee, childProcessBindings)) {
|
|
8899
|
-
recordRuntimeAsset(node.arguments[0]);
|
|
8900
|
-
}
|
|
8901
|
-
},
|
|
8902
|
-
NewExpression(node) {
|
|
8903
|
-
if (node.callee?.type === "Identifier" && node.callee.name === "URL" && isImportMetaUrl(node.arguments[1])) {
|
|
8904
|
-
recordRuntimeAsset(node);
|
|
8905
|
-
return;
|
|
8906
|
-
}
|
|
8907
|
-
if (node.callee?.type === "Identifier" && ["Worker", "SharedWorker"].includes(node.callee.name)) {
|
|
8908
|
-
recordRuntimeAsset(node.arguments[0]);
|
|
8909
|
-
}
|
|
8910
|
-
}
|
|
8911
|
-
});
|
|
8912
|
-
}
|
|
8913
|
-
for (const configured of configuredAssets) {
|
|
8914
|
-
if (typeof configured?.source !== "string" || !configured.source || typeof configured?.path !== "string") {
|
|
8915
|
-
throw new Error("configured runtime asset must include source and path");
|
|
8916
|
-
}
|
|
8917
|
-
const destination = canonicalRuntimeAssetPath(configured.path);
|
|
8918
|
-
if (!destination) {
|
|
8919
|
-
throw new Error(
|
|
8920
|
-
`configured runtime asset path is invalid: ${configured.path}`
|
|
8921
|
-
);
|
|
8922
|
-
}
|
|
8923
|
-
const source = path26.resolve(projectRoot, configured.source);
|
|
8924
|
-
if (!isPathInside(projectRoot, source) || !fs29.existsSync(source)) {
|
|
8925
|
-
throw new Error(
|
|
8926
|
-
`configured runtime asset source is invalid: ${configured.source}`
|
|
8927
|
-
);
|
|
8928
|
-
}
|
|
8929
|
-
candidates.push({ source, destination, origin: "package.json" });
|
|
8930
|
-
}
|
|
8931
|
-
const published = /* @__PURE__ */ new Map();
|
|
8932
|
-
const assertNoSymlinkPath = (source) => {
|
|
8933
|
-
const relative = path26.relative(projectRoot, source);
|
|
8934
|
-
if (!relative || relative.startsWith("..") || path26.isAbsolute(relative)) {
|
|
8935
|
-
throw new Error(`server runtime asset source escaped project: ${source}`);
|
|
8936
|
-
}
|
|
8937
|
-
let current = projectRoot;
|
|
8938
|
-
for (const segment of relative.split(path26.sep)) {
|
|
8939
|
-
current = path26.join(current, segment);
|
|
8940
|
-
if (fs29.lstatSync(current).isSymbolicLink()) {
|
|
8941
|
-
throw new Error(
|
|
8942
|
-
`server runtime asset symlink is unsupported: ${current}`
|
|
8943
|
-
);
|
|
8944
|
-
}
|
|
8945
|
-
}
|
|
8946
|
-
};
|
|
8947
|
-
const publishFile = (source, destination) => {
|
|
8948
|
-
const assetPath = canonicalRuntimeAssetPath(destination);
|
|
8949
|
-
if (!assetPath) {
|
|
8950
|
-
throw new Error(`server runtime asset path is invalid: ${destination}`);
|
|
8951
|
-
}
|
|
8952
|
-
assertNoSymlinkPath(source);
|
|
8953
|
-
const target = path26.join(bundleDirectory, ...assetPath.split("/"));
|
|
8954
|
-
const content = fs29.readFileSync(source);
|
|
8955
|
-
const sha2563 = createHash("sha256").update(content).digest("hex");
|
|
8956
|
-
const existing = published.get(assetPath);
|
|
8957
|
-
if (existing && existing.sha256 !== sha2563) {
|
|
8958
|
-
throw new Error(`server runtime asset collision: ${assetPath}`);
|
|
8959
|
-
}
|
|
8960
|
-
if (!existing) {
|
|
8961
|
-
fs29.mkdirSync(path26.dirname(target), { recursive: true });
|
|
8962
|
-
fs29.writeFileSync(target, content);
|
|
8963
|
-
published.set(assetPath, {
|
|
8964
|
-
path: assetPath,
|
|
8965
|
-
sha256: sha2563,
|
|
8966
|
-
size: content.length
|
|
8967
|
-
});
|
|
8968
|
-
}
|
|
8969
|
-
};
|
|
8970
|
-
const publishCandidate = (source, destination) => {
|
|
8971
|
-
assertNoSymlinkPath(source);
|
|
8972
|
-
const stat = fs29.lstatSync(source);
|
|
8973
|
-
if (stat.isSymbolicLink()) {
|
|
8974
|
-
throw new Error(`server runtime asset symlink is unsupported: ${source}`);
|
|
8975
|
-
}
|
|
8976
|
-
if (stat.isFile()) {
|
|
8977
|
-
publishFile(source, destination);
|
|
8978
|
-
return;
|
|
8979
|
-
}
|
|
8980
|
-
if (!stat.isDirectory()) {
|
|
8981
|
-
throw new Error(`server runtime asset type is unsupported: ${source}`);
|
|
8982
|
-
}
|
|
8983
|
-
for (const entry of fs29.readdirSync(source, { withFileTypes: true })) {
|
|
8984
|
-
publishCandidate(
|
|
8985
|
-
path26.join(source, entry.name),
|
|
8986
|
-
path26.posix.join(destination, entry.name)
|
|
8987
|
-
);
|
|
8988
|
-
}
|
|
8989
|
-
};
|
|
8990
|
-
for (const candidate of candidates.sort(
|
|
8991
|
-
(left, right) => left.destination.localeCompare(right.destination)
|
|
8992
|
-
)) {
|
|
8993
|
-
publishCandidate(candidate.source, candidate.destination);
|
|
8994
|
-
}
|
|
8995
|
-
return {
|
|
8996
|
-
assets: Array.from(published.values()).sort(
|
|
8997
|
-
(left, right) => left.path.localeCompare(right.path)
|
|
8998
|
-
),
|
|
8999
|
-
warnings: warnings.filter(
|
|
9000
|
-
(warning, index, all) => all.findIndex(
|
|
9001
|
-
(item) => item.kind === warning.kind && item.source === warning.source && item.expressionHash === warning.expressionHash
|
|
9002
|
-
) === index
|
|
9003
|
-
).sort(
|
|
9004
|
-
(left, right) => `${left.source}:${left.expressionHash}`.localeCompare(
|
|
9005
|
-
`${right.source}:${right.expressionHash}`
|
|
9006
|
-
)
|
|
9007
|
-
)
|
|
9008
|
-
};
|
|
9009
|
-
}
|
|
9010
|
-
function resolveStaticActionPlugins(projectRoot, configuredPlugins) {
|
|
9011
|
-
const projectRequire = createRequire3(path26.join(projectRoot, "package.json"));
|
|
9012
|
-
const plugins = [];
|
|
9013
|
-
const reasons = [];
|
|
9014
|
-
for (const [name, configuredVersion] of Object.entries(
|
|
9015
|
-
configuredPlugins
|
|
9016
|
-
).sort(([left], [right]) => left.localeCompare(right))) {
|
|
9017
|
-
if (typeof configuredVersion !== "string" || configuredVersion === "") {
|
|
9018
|
-
reasons.push(`Action Plugin ${name} has an invalid configured version`);
|
|
9019
|
-
continue;
|
|
9020
|
-
}
|
|
9021
|
-
try {
|
|
9022
|
-
const entry = projectRequire.resolve(name);
|
|
9023
|
-
const packageRoot2 = findPackageRoot(entry);
|
|
9024
|
-
if (!packageRoot2) {
|
|
9025
|
-
reasons.push(`Action Plugin package root not found: ${name}`);
|
|
9026
|
-
continue;
|
|
9027
|
-
}
|
|
9028
|
-
const packageJson = JSON.parse(
|
|
9029
|
-
fs29.readFileSync(path26.join(packageRoot2, "package.json"), "utf8")
|
|
9030
|
-
);
|
|
9031
|
-
if (packageJson.name !== name) {
|
|
9032
|
-
reasons.push(
|
|
9033
|
-
`Action Plugin package name mismatch: configured=${name} installed=${packageJson.name ?? "<missing>"}`
|
|
9034
|
-
);
|
|
9035
|
-
continue;
|
|
9036
|
-
}
|
|
9037
|
-
if (packageJson.version !== configuredVersion) {
|
|
9038
|
-
reasons.push(
|
|
9039
|
-
`Action Plugin version mismatch: ${name} configured=${configuredVersion} installed=${packageJson.version ?? "<missing>"}`
|
|
9040
|
-
);
|
|
9041
|
-
continue;
|
|
9042
|
-
}
|
|
9043
|
-
const manifestPath = path26.join(packageRoot2, "manifest.json");
|
|
9044
|
-
if (!fs29.existsSync(manifestPath)) {
|
|
9045
|
-
reasons.push(`Action Plugin manifest is missing: ${name}`);
|
|
9046
|
-
continue;
|
|
9047
|
-
}
|
|
9048
|
-
const manifest = JSON.parse(fs29.readFileSync(manifestPath, "utf8"));
|
|
9049
|
-
if (manifest.name !== void 0 && manifest.name !== name) {
|
|
9050
|
-
reasons.push(
|
|
9051
|
-
`Action Plugin manifest name mismatch: configured=${name} manifest=${String(manifest.name)}`
|
|
9052
|
-
);
|
|
9053
|
-
continue;
|
|
9054
|
-
}
|
|
9055
|
-
if (manifest.version !== void 0 && manifest.version !== configuredVersion) {
|
|
9056
|
-
reasons.push(
|
|
9057
|
-
`Action Plugin manifest version mismatch: ${name} configured=${configuredVersion} manifest=${String(manifest.version)}`
|
|
9058
|
-
);
|
|
9059
|
-
continue;
|
|
9060
|
-
}
|
|
9061
|
-
plugins.push({ name, version: configuredVersion, entry, manifest });
|
|
9062
|
-
} catch (error) {
|
|
9063
|
-
reasons.push(
|
|
9064
|
-
`Action Plugin cannot be statically resolved: ${name}: ${error instanceof Error ? error.message : String(error)}`
|
|
9065
|
-
);
|
|
9066
|
-
}
|
|
9067
|
-
}
|
|
9068
|
-
return { plugins, reasons };
|
|
9069
|
-
}
|
|
9070
|
-
function staticActionPluginRegistry(projectRoot, plugins, actionPluginProbe) {
|
|
9071
|
-
if (plugins.length === 0) {
|
|
9072
|
-
return { name: "miaoda-static-action-plugin-registry", setup() {
|
|
9073
|
-
} };
|
|
9074
|
-
}
|
|
9075
|
-
const capabilityEntry = resolveProjectPackage(
|
|
9076
|
-
projectRoot,
|
|
9077
|
-
"@lark-apaas/nestjs-capability"
|
|
9078
|
-
);
|
|
9079
|
-
const registryEntries = plugins.map(
|
|
9080
|
-
(plugin, index) => `[${JSON.stringify(plugin.name)}, { version: ${JSON.stringify(plugin.version)}, manifest: ${JSON.stringify(plugin.manifest)}, pluginPackage: __miaodaActionPlugin${index} }]`
|
|
9081
|
-
).join(",\n");
|
|
9082
|
-
const staticImports = plugins.map(
|
|
9083
|
-
(plugin, index) => `const __miaodaActionPlugin${index} = require(${JSON.stringify(plugin.entry)});`
|
|
9084
|
-
).join("\n");
|
|
9085
|
-
const contents = `
|
|
9086
|
-
const __miaodaCapability = require(${JSON.stringify(capabilityEntry)});
|
|
9087
|
-
${staticImports}
|
|
9088
|
-
const __miaodaActionPluginRegistry = new Map([${registryEntries}]);
|
|
9089
|
-
const __miaodaActionPluginProbe = ${JSON.stringify(actionPluginProbe ?? null)};
|
|
9090
|
-
if (process.env.MIAODA_SERVER_CACHE_PROBE === 'true') {
|
|
9091
|
-
for (const [__miaodaPluginKey, __miaodaRegistration] of __miaodaActionPluginRegistry) {
|
|
9092
|
-
const __miaodaPluginPackage = __miaodaRegistration.pluginPackage.default ?? __miaodaRegistration.pluginPackage;
|
|
9093
|
-
if (typeof __miaodaPluginPackage.create !== 'function') {
|
|
9094
|
-
throw new Error('MIAODA_ACTION_PLUGIN_PROBE_CREATE_MISSING:' + __miaodaPluginKey);
|
|
9095
|
-
}
|
|
9096
|
-
}
|
|
9097
|
-
console.error('MIAODA_ACTION_PLUGIN_REGISTRY_OK:' + __miaodaActionPluginRegistry.size);
|
|
9098
|
-
}
|
|
9099
|
-
if (process.env.MIAODA_SERVER_CACHE_PROBE === 'true' && __miaodaActionPluginProbe) {
|
|
9100
|
-
const __miaodaProbeRegistration = __miaodaActionPluginRegistry.get(__miaodaActionPluginProbe.key);
|
|
9101
|
-
if (!__miaodaProbeRegistration) {
|
|
9102
|
-
throw new Error('MIAODA_ACTION_PLUGIN_PROBE_NOT_REGISTERED:' + __miaodaActionPluginProbe.key);
|
|
9103
|
-
}
|
|
9104
|
-
const __miaodaProbePackage = __miaodaProbeRegistration.pluginPackage.default ?? __miaodaProbeRegistration.pluginPackage;
|
|
9105
|
-
if (typeof __miaodaProbePackage.create !== 'function') {
|
|
9106
|
-
throw new Error('MIAODA_ACTION_PLUGIN_PROBE_CREATE_MISSING:' + __miaodaActionPluginProbe.key);
|
|
9107
|
-
}
|
|
9108
|
-
Promise.resolve(__miaodaProbePackage.create(__miaodaActionPluginProbe.config))
|
|
9109
|
-
.then(() => console.error('MIAODA_ACTION_PLUGIN_PROBE_OK:' + __miaodaActionPluginProbe.key))
|
|
9110
|
-
.catch(error => {
|
|
9111
|
-
console.error('MIAODA_ACTION_PLUGIN_PROBE_FAILED:' + __miaodaActionPluginProbe.key + ':' + (error?.message ?? String(error)));
|
|
9112
|
-
process.exitCode = 1;
|
|
9113
|
-
});
|
|
9114
|
-
}
|
|
9115
|
-
const __miaodaPluginLoader = __miaodaCapability.PluginLoaderService;
|
|
9116
|
-
if (typeof __miaodaPluginLoader !== 'function') {
|
|
9117
|
-
throw new Error('MIAODA_STATIC_ACTION_PLUGIN_REGISTRY_UNSUPPORTED');
|
|
9118
|
-
}
|
|
9119
|
-
const __miaodaPluginLoaderPrototype = __miaodaPluginLoader.prototype;
|
|
9120
|
-
__miaodaPluginLoaderPrototype.getManifest = function getStaticManifest(pluginKey) {
|
|
9121
|
-
return __miaodaActionPluginRegistry.get(pluginKey)?.manifest ?? null;
|
|
9122
|
-
};
|
|
9123
|
-
__miaodaPluginLoaderPrototype.createPluginInstance = async function createStaticPluginInstance(pluginKey, config) {
|
|
9124
|
-
const registered = __miaodaActionPluginRegistry.get(pluginKey);
|
|
9125
|
-
if (!registered) throw new __miaodaCapability.PluginNotFoundError(pluginKey);
|
|
9126
|
-
const pluginPackage = registered.pluginPackage.default ?? registered.pluginPackage;
|
|
9127
|
-
if (typeof pluginPackage.create !== 'function') {
|
|
9128
|
-
throw new __miaodaCapability.PluginLoadError(pluginKey, 'Plugin does not export create() function');
|
|
9129
|
-
}
|
|
9130
|
-
return pluginPackage.create(config);
|
|
9131
|
-
};
|
|
9132
|
-
__miaodaPluginLoaderPrototype.isPluginInstalled = function isStaticPluginInstalled(pluginKey) {
|
|
9133
|
-
return __miaodaActionPluginRegistry.has(pluginKey);
|
|
9134
|
-
};
|
|
9135
|
-
__miaodaPluginLoaderPrototype.clearCache = function clearStaticPluginCache(pluginKey) {
|
|
9136
|
-
if (pluginKey) {
|
|
9137
|
-
this.pluginInstances?.delete(pluginKey);
|
|
9138
|
-
this.manifestCache?.delete(pluginKey);
|
|
9139
|
-
return;
|
|
9140
|
-
}
|
|
9141
|
-
this.pluginInstances?.clear();
|
|
9142
|
-
this.manifestCache?.clear();
|
|
9143
|
-
};
|
|
9144
|
-
module.exports = __miaodaCapability;
|
|
9145
|
-
`;
|
|
9146
|
-
return {
|
|
9147
|
-
name: "miaoda-static-action-plugin-registry",
|
|
9148
|
-
setup(esbuild) {
|
|
9149
|
-
esbuild.onResolve({ filter: /^@lark-apaas\/nestjs-capability$/ }, () => ({
|
|
9150
|
-
path: "@lark-apaas/nestjs-capability",
|
|
9151
|
-
namespace: "miaoda-static-action-plugin-registry"
|
|
9152
|
-
}));
|
|
9153
|
-
esbuild.onLoad(
|
|
9154
|
-
{
|
|
9155
|
-
filter: /.*/,
|
|
9156
|
-
namespace: "miaoda-static-action-plugin-registry"
|
|
9157
|
-
},
|
|
9158
|
-
() => ({ contents, loader: "js", resolveDir: projectRoot })
|
|
9159
|
-
);
|
|
9160
|
-
}
|
|
9161
|
-
};
|
|
9162
|
-
}
|
|
9163
|
-
function collectExternalImports(metafile, outfile, projectRoot) {
|
|
9164
|
-
const realOutfile = fs29.existsSync(outfile) ? fs29.realpathSync(outfile) : path26.resolve(outfile);
|
|
9165
|
-
const output = Object.entries(metafile.outputs).find(([candidate]) => {
|
|
9166
|
-
const resolvedCandidate = path26.resolve(projectRoot, candidate);
|
|
9167
|
-
return resolvedCandidate === path26.resolve(outfile) || fs29.existsSync(resolvedCandidate) && fs29.realpathSync(resolvedCandidate) === realOutfile;
|
|
9168
|
-
})?.[1];
|
|
9169
|
-
if (!output) return [];
|
|
9170
|
-
const externalImports = new Set(
|
|
9171
|
-
output.imports.filter((item) => item.external).map((item) => item.path).filter((item) => !BUILTINS.has(item) && !item.startsWith("node:"))
|
|
9172
|
-
);
|
|
9173
|
-
if (fs29.existsSync(outfile)) {
|
|
9174
|
-
const ast = parseJavaScriptSource(fs29.readFileSync(outfile, "utf8"));
|
|
9175
|
-
walkSimple(ast, {
|
|
9176
|
-
CallExpression(node) {
|
|
9177
|
-
if (staticPropertyName(node.callee) !== "resolve" || node.callee?.type !== "MemberExpression" || node.callee.object?.type !== "Identifier" || !["require", "__require"].includes(node.callee.object.name)) {
|
|
9178
|
-
return;
|
|
9179
|
-
}
|
|
9180
|
-
const specifier = staticStringValue(node.arguments?.[0]);
|
|
9181
|
-
if (!specifier || specifier.startsWith(".") || specifier.startsWith("/") || specifier.startsWith("#") || BUILTINS.has(specifier) || specifier.startsWith("node:")) {
|
|
9182
|
-
return;
|
|
9183
|
-
}
|
|
9184
|
-
externalImports.add(specifier);
|
|
9185
|
-
}
|
|
9186
|
-
});
|
|
9187
|
-
}
|
|
9188
|
-
return Array.from(externalImports).sort();
|
|
9189
|
-
}
|
|
9190
|
-
function collectBuildOnlyInputs(projectRoot, metafile) {
|
|
9191
|
-
return Array.from(
|
|
9192
|
-
new Set(
|
|
9193
|
-
Object.keys(metafile.inputs).flatMap((input) => {
|
|
9194
|
-
const source = canonicalSourcePath(
|
|
9195
|
-
projectRoot,
|
|
9196
|
-
path26.resolve(projectRoot, input)
|
|
9197
|
-
);
|
|
9198
|
-
const normalized = `/${source.replace(/^\.\//, "")}/`;
|
|
9199
|
-
return BUILD_ONLY_SERVER_CACHE_PACKAGES.filter(
|
|
9200
|
-
(packageName) => normalized.includes(`/node_modules/${packageName}/`)
|
|
9201
|
-
);
|
|
9202
|
-
})
|
|
9203
|
-
)
|
|
9204
|
-
).sort();
|
|
9205
|
-
}
|
|
9206
|
-
function isStaticString(node) {
|
|
9207
|
-
if (!node) return false;
|
|
9208
|
-
if (node.type === "Literal") return typeof node.value === "string";
|
|
9209
|
-
return node.type === "TemplateLiteral" && node.expressions.length === 0;
|
|
9210
|
-
}
|
|
9211
|
-
function staticPropertyName(node) {
|
|
9212
|
-
if (node?.type !== "MemberExpression") return void 0;
|
|
9213
|
-
if (!node.computed && node.property.type === "Identifier") {
|
|
9214
|
-
return node.property.name;
|
|
9215
|
-
}
|
|
9216
|
-
if (node.computed && node.property.type === "Literal" && typeof node.property.value === "string") {
|
|
9217
|
-
return node.property.value;
|
|
9218
|
-
}
|
|
9219
|
-
return void 0;
|
|
9220
|
-
}
|
|
9221
|
-
function collectDynamicImportWarnings(projectRoot, metafile) {
|
|
9222
|
-
const warnings = [];
|
|
9223
|
-
const sourceInputs = Object.keys(metafile.inputs).filter((input) => /\.(?:cjs|mjs|js)$/.test(input)).sort();
|
|
9224
|
-
for (const input of sourceInputs) {
|
|
9225
|
-
const sourcePath = path26.resolve(projectRoot, input);
|
|
9226
|
-
if (!fs29.existsSync(sourcePath) || !fs29.statSync(sourcePath).isFile()) {
|
|
9227
|
-
continue;
|
|
9228
|
-
}
|
|
9229
|
-
const source = fs29.readFileSync(sourcePath, "utf8");
|
|
9230
|
-
const ast = parseJavaScriptSource(source);
|
|
9231
|
-
const origin = canonicalSourcePath(projectRoot, sourcePath);
|
|
9232
|
-
const fingerprint = (kind, node, message) => {
|
|
9233
|
-
const expression = source.slice(node.start, node.end);
|
|
9234
|
-
const hash = createHash("sha256").update(expression).digest("hex").slice(0, 16);
|
|
9235
|
-
warnings.push({ kind, source: origin, expressionHash: hash, message });
|
|
9236
|
-
};
|
|
9237
|
-
walkSimple(ast, {
|
|
9238
|
-
CallExpression(node) {
|
|
9239
|
-
if (node.callee.type === "Identifier" && node.callee.name === "require" && !isStaticString(node.arguments[0])) {
|
|
9240
|
-
fingerprint(
|
|
9241
|
-
"dynamic-require",
|
|
9242
|
-
node,
|
|
9243
|
-
"Variable module loading remains in bundle"
|
|
9244
|
-
);
|
|
9245
|
-
}
|
|
9246
|
-
const property = staticPropertyName(node.callee);
|
|
9247
|
-
const resolverObject = node.callee.type === "MemberExpression" ? node.callee.object : void 0;
|
|
9248
|
-
if (node.callee.type === "Identifier" && node.callee.name === "createRequire") {
|
|
9249
|
-
fingerprint(
|
|
9250
|
-
"create-require",
|
|
9251
|
-
node,
|
|
9252
|
-
"Runtime module resolver is created in bundle"
|
|
9253
|
-
);
|
|
9254
|
-
} else if (property === "resolve" && resolverObject?.type === "Identifier" && resolverObject.name === "require" && !isStaticString(node.arguments[0])) {
|
|
9255
|
-
fingerprint(
|
|
9256
|
-
"dynamic-require-resolve",
|
|
9257
|
-
node,
|
|
9258
|
-
"Variable require.resolve target remains in bundle"
|
|
9259
|
-
);
|
|
9260
|
-
} else if (property === "resolve" && resolverObject?.type === "Identifier" && ["import", "module"].includes(resolverObject.name) && !isStaticString(node.arguments[0])) {
|
|
9261
|
-
fingerprint(
|
|
9262
|
-
"runtime-module-resolution",
|
|
9263
|
-
node,
|
|
9264
|
-
"Variable runtime module resolution remains in bundle"
|
|
9265
|
-
);
|
|
9266
|
-
}
|
|
9267
|
-
},
|
|
9268
|
-
ImportExpression(node) {
|
|
9269
|
-
if (!isStaticString(node.source)) {
|
|
9270
|
-
fingerprint(
|
|
9271
|
-
"dynamic-import",
|
|
9272
|
-
node,
|
|
9273
|
-
"Variable dynamic import remains in bundle"
|
|
9274
|
-
);
|
|
9275
|
-
}
|
|
9276
|
-
}
|
|
9277
|
-
});
|
|
9278
|
-
}
|
|
9279
|
-
return warnings.filter(
|
|
9280
|
-
(warning, index, all) => all.findIndex(
|
|
9281
|
-
(item) => item.kind === warning.kind && item.source === warning.source && item.expressionHash === warning.expressionHash
|
|
9282
|
-
) === index
|
|
9283
|
-
).sort(
|
|
9284
|
-
(left, right) => `${left.kind}:${left.source}:${left.expressionHash}`.localeCompare(
|
|
9285
|
-
`${right.kind}:${right.source}:${right.expressionHash}`
|
|
9286
|
-
)
|
|
9287
|
-
);
|
|
9288
|
-
}
|
|
9289
|
-
async function reservePort() {
|
|
9290
|
-
return new Promise((resolve2, reject) => {
|
|
9291
|
-
const server = net.createServer();
|
|
9292
|
-
server.once("error", reject);
|
|
9293
|
-
server.listen(0, "127.0.0.1", () => {
|
|
9294
|
-
const address = server.address();
|
|
9295
|
-
if (!address || typeof address === "string") {
|
|
9296
|
-
server.close(() => reject(new Error("unable to reserve probe port")));
|
|
9297
|
-
return;
|
|
9298
|
-
}
|
|
9299
|
-
server.close((error) => error ? reject(error) : resolve2(address.port));
|
|
9300
|
-
});
|
|
9301
|
-
});
|
|
9302
|
-
}
|
|
9303
|
-
function resolveLegacyCapabilityProbe(projectRoot) {
|
|
9304
|
-
const capabilitiesRoot = path26.join(projectRoot, "server", "capabilities");
|
|
9305
|
-
if (!fs29.existsSync(capabilitiesRoot)) {
|
|
9306
|
-
return { files: [], expectedIds: [] };
|
|
9307
|
-
}
|
|
9308
|
-
const rootStat = fs29.lstatSync(capabilitiesRoot);
|
|
9309
|
-
if (!rootStat.isDirectory() || rootStat.isSymbolicLink()) {
|
|
9310
|
-
throw new Error(
|
|
9311
|
-
"legacy capability probe directory must be a regular directory"
|
|
9312
|
-
);
|
|
9313
|
-
}
|
|
9314
|
-
const realProjectRoot = fs29.realpathSync(projectRoot);
|
|
9315
|
-
const realCapabilitiesRoot = fs29.realpathSync(capabilitiesRoot);
|
|
9316
|
-
if (!isPathInside(realProjectRoot, realCapabilitiesRoot)) {
|
|
9317
|
-
throw new Error("legacy capability probe directory escaped project root");
|
|
9318
|
-
}
|
|
9319
|
-
const files = [];
|
|
9320
|
-
const expectedIds = [];
|
|
9321
|
-
for (const name of fs29.readdirSync(realCapabilitiesRoot).sort()) {
|
|
9322
|
-
if (!name.endsWith(".json")) continue;
|
|
9323
|
-
const source = path26.join(realCapabilitiesRoot, name);
|
|
9324
|
-
const stat = fs29.lstatSync(source);
|
|
9325
|
-
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
9326
|
-
throw new Error(`legacy capability probe file is unsafe: ${name}`);
|
|
9327
|
-
}
|
|
9328
|
-
const parsed = JSON.parse(fs29.readFileSync(source, "utf8"));
|
|
9329
|
-
if (typeof parsed.id !== "string" || parsed.id.length === 0) {
|
|
9330
|
-
throw new Error(`legacy capability probe file has no id: ${name}`);
|
|
9331
|
-
}
|
|
9332
|
-
files.push({ source, name });
|
|
9333
|
-
expectedIds.push(parsed.id);
|
|
9334
|
-
}
|
|
9335
|
-
return { files, expectedIds };
|
|
9336
|
-
}
|
|
9337
|
-
function resolveAvailabilityProbeConfig(projectRoot, configured) {
|
|
9338
|
-
if (configured === void 0) {
|
|
9339
|
-
const configuredBasePath = process.env.CLIENT_BASE_PATH;
|
|
9340
|
-
const basePath = typeof configuredBasePath === "string" && configuredBasePath.startsWith("/") && !configuredBasePath.startsWith("//") ? configuredBasePath : "/";
|
|
9341
|
-
const normalizedBasePath = basePath === "/" ? "" : basePath.replace(/\/+$/, "");
|
|
9342
|
-
const capabilityPath = `${normalizedBasePath}/__innerapi__/capability/list`;
|
|
9343
|
-
return {
|
|
9344
|
-
readiness: { path: capabilityPath, expectedStatus: 200 },
|
|
9345
|
-
business: {
|
|
9346
|
-
path: capabilityPath,
|
|
9347
|
-
expectedStatus: 200,
|
|
9348
|
-
bodyIncludes: '"status_code":"0"'
|
|
9349
|
-
},
|
|
9350
|
-
legacyCapabilityProbe: resolveLegacyCapabilityProbe(projectRoot)
|
|
9351
|
-
};
|
|
9352
|
-
}
|
|
9353
|
-
if (!configured?.readiness || !configured.business) {
|
|
9354
|
-
throw new Error(
|
|
9355
|
-
"miaodaCache.availabilityProbe.readiness and business are required"
|
|
9356
|
-
);
|
|
9357
|
-
}
|
|
9358
|
-
const normalize = (name, value) => {
|
|
9359
|
-
const requestPath = value?.path;
|
|
9360
|
-
const expectedStatus = value?.expectedStatus;
|
|
9361
|
-
if (typeof requestPath !== "string" || !requestPath.startsWith("/") || requestPath.startsWith("//") || !Number.isSafeInteger(expectedStatus) || expectedStatus < 100 || expectedStatus > 599 || value?.bodyIncludes !== void 0 && typeof value.bodyIncludes !== "string") {
|
|
9362
|
-
throw new Error(`invalid ${name} availability probe configuration`);
|
|
9363
|
-
}
|
|
9364
|
-
return {
|
|
9365
|
-
path: requestPath,
|
|
9366
|
-
expectedStatus,
|
|
9367
|
-
...value?.bodyIncludes ? { bodyIncludes: value.bodyIncludes } : {}
|
|
9368
|
-
};
|
|
9369
|
-
};
|
|
9370
|
-
return {
|
|
9371
|
-
readiness: normalize("readiness", configured.readiness),
|
|
9372
|
-
business: normalize("business", configured.business)
|
|
9373
|
-
};
|
|
9374
|
-
}
|
|
9375
|
-
function requestHttp(port, request) {
|
|
9376
|
-
return new Promise((resolve2, reject) => {
|
|
9377
|
-
const clientRequest = http.request(
|
|
9378
|
-
{
|
|
9379
|
-
host: "127.0.0.1",
|
|
9380
|
-
port,
|
|
9381
|
-
path: request.path,
|
|
9382
|
-
method: "GET",
|
|
9383
|
-
timeout: 1e3,
|
|
9384
|
-
headers: { connection: "close" }
|
|
9385
|
-
},
|
|
9386
|
-
(response) => {
|
|
9387
|
-
let body = "";
|
|
9388
|
-
response.setEncoding("utf8");
|
|
9389
|
-
response.on("data", (chunk) => {
|
|
9390
|
-
body = `${body}${String(chunk)}`.slice(0, 64 * 1024);
|
|
9391
|
-
});
|
|
9392
|
-
response.once(
|
|
9393
|
-
"end",
|
|
9394
|
-
() => resolve2({ status: response.statusCode ?? 0, body })
|
|
9395
|
-
);
|
|
9396
|
-
}
|
|
9397
|
-
);
|
|
9398
|
-
clientRequest.once("timeout", () => {
|
|
9399
|
-
clientRequest.destroy(new Error("HTTP probe timed out"));
|
|
9400
|
-
});
|
|
9401
|
-
clientRequest.once("error", reject);
|
|
9402
|
-
clientRequest.end();
|
|
9403
|
-
});
|
|
9404
|
-
}
|
|
9405
|
-
function requestMatches(response, request) {
|
|
9406
|
-
return response.status === request.expectedStatus && (request.bodyIncludes === void 0 || response.body.includes(request.bodyIncludes));
|
|
9407
|
-
}
|
|
9408
|
-
async function terminateProcessGroup(child) {
|
|
9409
|
-
if (child.exitCode !== null || child.signalCode !== null) return;
|
|
9410
|
-
const exited = new Promise(
|
|
9411
|
-
(resolve2) => child.once("exit", () => resolve2())
|
|
9412
|
-
);
|
|
9413
|
-
try {
|
|
9414
|
-
child.kill("SIGTERM");
|
|
9415
|
-
} catch {
|
|
9416
|
-
}
|
|
9417
|
-
await Promise.race([
|
|
9418
|
-
exited,
|
|
9419
|
-
new Promise((resolve2) => setTimeout(resolve2, 500))
|
|
9420
|
-
]);
|
|
9421
|
-
if (child.exitCode === null && child.signalCode === null) {
|
|
9422
|
-
try {
|
|
9423
|
-
process.kill(-child.pid, "SIGKILL");
|
|
9424
|
-
} catch {
|
|
9425
|
-
child.kill("SIGKILL");
|
|
9426
|
-
}
|
|
9427
|
-
await exited;
|
|
9428
|
-
}
|
|
9429
|
-
}
|
|
9430
|
-
async function runAvailabilityProbe(bundleFile, runtimeAssets, timeoutMs, config, actionPluginCount, actionPluginProbeKey) {
|
|
9431
|
-
const probeRoot = fs29.mkdtempSync(
|
|
9432
|
-
path26.join(os4.tmpdir(), "server-cache-probe-")
|
|
9433
|
-
);
|
|
9434
|
-
const isolatedBundle = path26.join(probeRoot, "server.bundle.cjs");
|
|
9435
|
-
fs29.copyFileSync(bundleFile, isolatedBundle);
|
|
9436
|
-
for (const asset of runtimeAssets) {
|
|
9437
|
-
const source = path26.join(
|
|
9438
|
-
path26.dirname(bundleFile),
|
|
9439
|
-
...asset.path.split("/")
|
|
9440
|
-
);
|
|
9441
|
-
const destination = path26.join(probeRoot, ...asset.path.split("/"));
|
|
9442
|
-
fs29.mkdirSync(path26.dirname(destination), { recursive: true });
|
|
9443
|
-
fs29.copyFileSync(source, destination);
|
|
9444
|
-
}
|
|
9445
|
-
if (config.legacyCapabilityProbe) {
|
|
9446
|
-
const capabilityRoot = path26.join(probeRoot, "server", "capabilities");
|
|
9447
|
-
fs29.mkdirSync(capabilityRoot, { recursive: true });
|
|
9448
|
-
for (const file of config.legacyCapabilityProbe.files) {
|
|
9449
|
-
fs29.copyFileSync(file.source, path26.join(capabilityRoot, file.name));
|
|
9450
|
-
}
|
|
9451
|
-
}
|
|
9452
|
-
const port = await reservePort();
|
|
9453
|
-
let stdout = "";
|
|
9454
|
-
let stderr = "";
|
|
9455
|
-
let responseText = "";
|
|
9456
|
-
const checks = [];
|
|
9457
|
-
const startedAt = Date.now();
|
|
9458
|
-
const child = spawn2(process.execPath, [isolatedBundle], {
|
|
9459
|
-
cwd: probeRoot,
|
|
9460
|
-
detached: true,
|
|
9461
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
9462
|
-
env: {
|
|
9463
|
-
...process.env,
|
|
9464
|
-
NODE_PATH: "",
|
|
9465
|
-
// The cache bundle serves the development preview. Probe the same module
|
|
9466
|
-
// graph instead of forcing production mode, which disables Miaoda's
|
|
9467
|
-
// internal capability route and produces a false HTTP 500.
|
|
9468
|
-
NODE_ENV: "development",
|
|
9469
|
-
SERVER_HOST: "127.0.0.1",
|
|
9470
|
-
SERVER_PORT: String(port),
|
|
9471
|
-
MIAODA_SERVER_CACHE_PROBE: "true",
|
|
9472
|
-
DEPRECATED_SKIP_INIT_DB_CONNECTION: process.env.DEPRECATED_SKIP_INIT_DB_CONNECTION ?? "true",
|
|
9473
|
-
FORCE_AUTHN_INNERAPI_DOMAIN: process.env.FORCE_AUTHN_INNERAPI_DOMAIN ?? "http://127.0.0.1",
|
|
9474
|
-
FORCE_AUTHN_ACCESS_KEY: process.env.FORCE_AUTHN_ACCESS_KEY ?? "server-cache-probe",
|
|
9475
|
-
FORCE_AUTHN_ACCESS_SECRET: process.env.FORCE_AUTHN_ACCESS_SECRET ?? "server-cache-probe"
|
|
9476
|
-
}
|
|
9477
|
-
});
|
|
9478
|
-
child.stdout?.setEncoding("utf8");
|
|
9479
|
-
child.stdout?.on("data", (chunk) => {
|
|
9480
|
-
stdout = `${stdout}${String(chunk)}`.slice(-8 * 1024);
|
|
9481
|
-
});
|
|
9482
|
-
child.stderr?.setEncoding("utf8");
|
|
9483
|
-
child.stderr?.on("data", (chunk) => {
|
|
9484
|
-
stderr = `${stderr}${String(chunk)}`.slice(-8 * 1024);
|
|
9485
|
-
});
|
|
9486
|
-
try {
|
|
9487
|
-
const nodeModulesPresent = fs29.existsSync(
|
|
9488
|
-
path26.join(probeRoot, "node_modules")
|
|
9489
|
-
);
|
|
9490
|
-
checks.push({
|
|
9491
|
-
name: "isolated-node-modules",
|
|
9492
|
-
success: !nodeModulesPresent,
|
|
9493
|
-
message: nodeModulesPresent ? "node_modules unexpectedly exists in isolated probe directory" : "node_modules is absent"
|
|
9494
|
-
});
|
|
9495
|
-
const runtimeAssetsReadable = runtimeAssets.every((asset) => {
|
|
9496
|
-
const file = path26.join(probeRoot, ...asset.path.split("/"));
|
|
9497
|
-
return fs29.existsSync(file) && fs29.statSync(file).isFile() && fs29.statSync(file).size === asset.size && createHash("sha256").update(fs29.readFileSync(file)).digest("hex") === asset.sha256;
|
|
9498
|
-
});
|
|
9499
|
-
checks.push({
|
|
9500
|
-
name: "runtime-assets",
|
|
9501
|
-
success: runtimeAssetsReadable,
|
|
9502
|
-
message: runtimeAssetsReadable ? `${runtimeAssets.length} runtime assets are readable` : "runtime asset integrity check failed in isolated directory"
|
|
9503
|
-
});
|
|
9504
|
-
let readinessResponse;
|
|
9505
|
-
let lastReadinessError = "";
|
|
9506
|
-
while (Date.now() - startedAt < timeoutMs && child.exitCode === null && child.signalCode === null) {
|
|
9507
|
-
try {
|
|
9508
|
-
const response = await requestHttp(port, config.readiness);
|
|
9509
|
-
responseText = `${responseText}
|
|
9510
|
-
${response.body}`.slice(-64 * 1024);
|
|
9511
|
-
readinessResponse = response;
|
|
9512
|
-
if (requestMatches(response, config.readiness)) break;
|
|
9513
|
-
lastReadinessError = `unexpected HTTP ${response.status}`;
|
|
9514
|
-
} catch (error) {
|
|
9515
|
-
lastReadinessError = error instanceof Error ? error.message : String(error);
|
|
9516
|
-
}
|
|
9517
|
-
await new Promise((resolve2) => setTimeout(resolve2, 25));
|
|
9518
|
-
}
|
|
9519
|
-
if (child.exitCode !== null || child.signalCode !== null) {
|
|
9520
|
-
await new Promise((resolve2) => setTimeout(resolve2, 50));
|
|
9521
|
-
}
|
|
9522
|
-
const readinessSuccess = Boolean(
|
|
9523
|
-
readinessResponse && requestMatches(readinessResponse, config.readiness)
|
|
9524
|
-
);
|
|
9525
|
-
const startupMs = Date.now() - startedAt;
|
|
9526
|
-
checks.push({
|
|
9527
|
-
name: "http-readiness",
|
|
9528
|
-
success: readinessSuccess,
|
|
9529
|
-
path: config.readiness.path,
|
|
9530
|
-
status: readinessResponse?.status,
|
|
9531
|
-
elapsedMs: startupMs,
|
|
9532
|
-
...!readinessSuccess ? {
|
|
9533
|
-
message: child.exitCode !== null ? `process exited before readiness: ${child.exitCode}` : lastReadinessError || "HTTP readiness timed out"
|
|
9534
|
-
} : {}
|
|
9535
|
-
});
|
|
9536
|
-
let businessResponse;
|
|
9537
|
-
let businessError = "";
|
|
9538
|
-
if (readinessSuccess) {
|
|
9539
|
-
try {
|
|
9540
|
-
businessResponse = await requestHttp(port, config.business);
|
|
9541
|
-
responseText = `${responseText}
|
|
9542
|
-
${businessResponse.body}`.slice(
|
|
9543
|
-
-64 * 1024
|
|
9544
|
-
);
|
|
9545
|
-
} catch (error) {
|
|
9546
|
-
businessError = error instanceof Error ? error.message : String(error);
|
|
9547
|
-
}
|
|
9548
|
-
}
|
|
9549
|
-
const businessSuccess = Boolean(
|
|
9550
|
-
businessResponse && requestMatches(businessResponse, config.business)
|
|
9551
|
-
);
|
|
9552
|
-
checks.push({
|
|
9553
|
-
name: "business-api",
|
|
9554
|
-
success: businessSuccess,
|
|
9555
|
-
path: config.business.path,
|
|
9556
|
-
status: businessResponse?.status,
|
|
9557
|
-
...!businessSuccess ? {
|
|
9558
|
-
message: businessError || (businessResponse ? `expected HTTP ${config.business.expectedStatus}${config.business.bodyIncludes ? ` containing ${JSON.stringify(config.business.bodyIncludes)}` : ""}, received HTTP ${businessResponse.status}` : "business API was not requested because readiness failed")
|
|
9559
|
-
} : {}
|
|
9560
|
-
});
|
|
9561
|
-
if (config.legacyCapabilityProbe) {
|
|
9562
|
-
let actualIds = [];
|
|
9563
|
-
let capabilityError = "";
|
|
9564
|
-
try {
|
|
9565
|
-
const payload = JSON.parse(businessResponse?.body ?? "");
|
|
9566
|
-
actualIds = (payload.data?.capabilities ?? []).map((capability) => capability.id).filter((id) => typeof id === "string").sort();
|
|
9567
|
-
} catch (error) {
|
|
9568
|
-
capabilityError = error instanceof Error ? error.message : String(error);
|
|
9569
|
-
}
|
|
9570
|
-
const expectedIds = [...config.legacyCapabilityProbe.expectedIds].sort();
|
|
9571
|
-
const missingIds = expectedIds.filter((id) => !actualIds.includes(id));
|
|
9572
|
-
checks.push({
|
|
9573
|
-
name: "capability-configs",
|
|
9574
|
-
success: businessSuccess && capabilityError.length === 0 && missingIds.length === 0,
|
|
9575
|
-
message: capabilityError.length > 0 ? `capability response is invalid JSON: ${capabilityError}` : missingIds.length > 0 ? `capability response missed: ${missingIds.join(", ")}` : `${expectedIds.length} workspace capability configs loaded`
|
|
9576
|
-
});
|
|
9577
|
-
}
|
|
9578
|
-
if (actionPluginCount > 0) {
|
|
9579
|
-
const marker = `MIAODA_ACTION_PLUGIN_REGISTRY_OK:${actionPluginCount}`;
|
|
9580
|
-
const markerDeadline = Date.now() + Math.min(1e3, timeoutMs);
|
|
9581
|
-
while (!stderr.includes(marker) && Date.now() < markerDeadline) {
|
|
9582
|
-
await new Promise((resolve2) => setTimeout(resolve2, 10));
|
|
9583
|
-
}
|
|
9584
|
-
checks.push({
|
|
9585
|
-
name: "action-plugin-registry",
|
|
9586
|
-
success: stderr.includes(marker),
|
|
9587
|
-
message: stderr.includes(marker) ? `${actionPluginCount} static Action Plugin packages registered` : `static Action Plugin registry marker missing: expected ${actionPluginCount}`
|
|
9588
|
-
});
|
|
9589
|
-
}
|
|
9590
|
-
if (actionPluginProbeKey) {
|
|
9591
|
-
const marker = `MIAODA_ACTION_PLUGIN_PROBE_OK:${actionPluginProbeKey}`;
|
|
9592
|
-
const markerDeadline = Date.now() + Math.min(1e3, timeoutMs);
|
|
9593
|
-
while (!stderr.includes(marker) && Date.now() < markerDeadline) {
|
|
9594
|
-
await new Promise((resolve2) => setTimeout(resolve2, 10));
|
|
9595
|
-
}
|
|
9596
|
-
checks.push({
|
|
9597
|
-
name: "action-plugin-instantiation",
|
|
9598
|
-
success: stderr.includes(marker),
|
|
9599
|
-
message: stderr.includes(marker) ? `static Action Plugin instantiated: ${actionPluginProbeKey}` : `static Action Plugin probe marker missing: ${actionPluginProbeKey}`
|
|
9600
|
-
});
|
|
9601
|
-
}
|
|
9602
|
-
await new Promise((resolve2) => setTimeout(resolve2, 25));
|
|
9603
|
-
checks.push({
|
|
9604
|
-
name: "process-alive",
|
|
9605
|
-
success: child.exitCode === null && child.signalCode === null,
|
|
9606
|
-
...child.exitCode !== null ? { message: `process exited with code ${child.exitCode}` } : {}
|
|
9607
|
-
});
|
|
9608
|
-
const moduleNotFound = /MODULE_NOT_FOUND/.test(
|
|
9609
|
-
`${stdout}
|
|
9610
|
-
${stderr}
|
|
9611
|
-
${responseText}`
|
|
9612
|
-
);
|
|
9613
|
-
checks.push({
|
|
9614
|
-
name: "module-resolution",
|
|
9615
|
-
success: !moduleNotFound,
|
|
9616
|
-
...moduleNotFound ? { message: "MODULE_NOT_FOUND appeared in stderr or HTTP response" } : {}
|
|
9617
|
-
});
|
|
9618
|
-
const success = checks.every((check2) => check2.success);
|
|
9619
|
-
return {
|
|
9620
|
-
success,
|
|
9621
|
-
nodeModulesPresent,
|
|
9622
|
-
port,
|
|
9623
|
-
startupMs,
|
|
9624
|
-
checks,
|
|
9625
|
-
...stdout.trim() ? { stdout: stdout.trim() } : {},
|
|
9626
|
-
...stderr.trim() ? { stderr: stderr.trim() } : {}
|
|
9627
|
-
};
|
|
9628
|
-
} finally {
|
|
9629
|
-
await terminateProcessGroup(child);
|
|
9630
|
-
fs29.rmSync(probeRoot, { recursive: true, force: true });
|
|
9631
|
-
}
|
|
9632
|
-
}
|
|
9633
|
-
async function buildServerCacheBundle(options) {
|
|
9634
|
-
const startedAt = Date.now();
|
|
9635
|
-
const projectRoot = path26.resolve(options.projectRoot);
|
|
9636
|
-
const outfile = absolute(
|
|
9637
|
-
projectRoot,
|
|
9638
|
-
options.outfile ?? ".miaoda-cache/server/server.bundle.cjs"
|
|
9639
|
-
);
|
|
9640
|
-
const metadataFile = absolute(
|
|
9641
|
-
projectRoot,
|
|
9642
|
-
options.metadataFile ?? `${outfile}.meta.json`
|
|
9643
|
-
);
|
|
9644
|
-
const fail = (reasons) => ({
|
|
9645
|
-
built: false,
|
|
9646
|
-
reasons,
|
|
9647
|
-
elapsedMs: Date.now() - startedAt
|
|
9648
|
-
});
|
|
9649
|
-
const outputValidationError = validateOwnedServerOutput(
|
|
9650
|
-
projectRoot,
|
|
9651
|
-
outfile,
|
|
9652
|
-
metadataFile
|
|
9653
|
-
);
|
|
9654
|
-
if (outputValidationError) return fail([outputValidationError]);
|
|
9655
|
-
const serverOutputRoot = path26.dirname(outfile);
|
|
9656
|
-
fs29.rmSync(serverOutputRoot, { recursive: true, force: true });
|
|
9657
|
-
const resolvedEntry = resolveCompiledEntry(projectRoot, options.entry);
|
|
9658
|
-
if (!resolvedEntry.entry) return fail(resolvedEntry.reasons);
|
|
9659
|
-
const entry = resolvedEntry.entry;
|
|
9660
|
-
if (outfile === entry || metadataFile === entry || outfile === metadataFile) {
|
|
9661
|
-
return fail(["bundle output conflicts with an input or metadata file"]);
|
|
9662
|
-
}
|
|
9663
|
-
const packageJsonPath = path26.join(projectRoot, "package.json");
|
|
9664
|
-
if (!fs29.existsSync(packageJsonPath)) {
|
|
9665
|
-
return fail([`package.json missing: ${packageJsonPath}`]);
|
|
9666
|
-
}
|
|
9667
|
-
const packageJson = JSON.parse(fs29.readFileSync(packageJsonPath, "utf8"));
|
|
9668
|
-
let availabilityProbeConfig;
|
|
9669
|
-
try {
|
|
9670
|
-
availabilityProbeConfig = resolveAvailabilityProbeConfig(
|
|
9671
|
-
projectRoot,
|
|
9672
|
-
packageJson.miaodaCache?.availabilityProbe
|
|
9673
|
-
);
|
|
9674
|
-
} catch (error) {
|
|
9675
|
-
return fail([error instanceof Error ? error.message : String(error)]);
|
|
9676
|
-
}
|
|
9677
|
-
const actionPluginResolution = resolveStaticActionPlugins(
|
|
9678
|
-
projectRoot,
|
|
9679
|
-
packageJson.actionPlugins ?? {}
|
|
9680
|
-
);
|
|
9681
|
-
if (actionPluginResolution.reasons.length > 0) {
|
|
9682
|
-
return fail(actionPluginResolution.reasons);
|
|
9683
|
-
}
|
|
9684
|
-
const actionPlugins = actionPluginResolution.plugins;
|
|
9685
|
-
const configuredActionPluginProbe = packageJson.miaodaCache?.actionPluginProbe;
|
|
9686
|
-
const actionPluginProbe = configuredActionPluginProbe === void 0 ? void 0 : typeof configuredActionPluginProbe.key === "string" && configuredActionPluginProbe.key ? {
|
|
9687
|
-
key: configuredActionPluginProbe.key,
|
|
9688
|
-
config: configuredActionPluginProbe.config
|
|
9689
|
-
} : null;
|
|
9690
|
-
if (actionPluginProbe === null) {
|
|
9691
|
-
return fail(["Action Plugin probe key is invalid"]);
|
|
9692
|
-
}
|
|
9693
|
-
if (actionPluginProbe && !actionPlugins.some((plugin) => plugin.name === actionPluginProbe.key)) {
|
|
9694
|
-
return fail([
|
|
9695
|
-
`Action Plugin probe is not configured in actionPlugins: ${actionPluginProbe.key}`
|
|
9696
|
-
]);
|
|
9697
|
-
}
|
|
9698
|
-
fs29.mkdirSync(path26.dirname(serverOutputRoot), { recursive: true });
|
|
9699
|
-
const tempRoot = fs29.mkdtempSync(
|
|
9700
|
-
path26.join(path26.dirname(serverOutputRoot), ".server-build-")
|
|
9701
|
-
);
|
|
9702
|
-
const tempOutfile = path26.join(tempRoot, "server.bundle.cjs");
|
|
9703
|
-
try {
|
|
9704
|
-
const result = await build({
|
|
9705
|
-
absWorkingDir: projectRoot,
|
|
9706
|
-
entryPoints: [entry],
|
|
9707
|
-
outfile: tempOutfile,
|
|
9708
|
-
bundle: true,
|
|
9709
|
-
platform: "node",
|
|
9710
|
-
format: "cjs",
|
|
9711
|
-
target: "node22",
|
|
9712
|
-
treeShaking: true,
|
|
9713
|
-
keepNames: true,
|
|
9714
|
-
legalComments: "none",
|
|
9715
|
-
sourcemap: false,
|
|
9716
|
-
metafile: true,
|
|
9717
|
-
logLevel: "silent",
|
|
9718
|
-
define: {
|
|
9719
|
-
"import.meta.url": "__miaoda_server_cache_import_meta_url__"
|
|
9720
|
-
},
|
|
9721
|
-
banner: {
|
|
9722
|
-
js: 'const __miaoda_server_cache_import_meta_url__ = require("node:url").pathToFileURL(__filename).href;'
|
|
9723
|
-
},
|
|
9724
|
-
plugins: [
|
|
9725
|
-
rejectNativeAddonsPlugin(),
|
|
9726
|
-
fullstackNestRuntimeResolver(projectRoot),
|
|
9727
|
-
legacyFullstackNestOpenApiStub(projectRoot),
|
|
9728
|
-
staticActionPluginRegistry(
|
|
9729
|
-
projectRoot,
|
|
9730
|
-
actionPlugins,
|
|
9731
|
-
actionPluginProbe ?? void 0
|
|
9732
|
-
),
|
|
9733
|
-
classTransformerStorageResolver(projectRoot),
|
|
9734
|
-
optionalDependencyStubPlugin()
|
|
9735
|
-
]
|
|
9736
|
-
});
|
|
9737
|
-
if (!result.metafile) return fail(["esbuild metafile missing"]);
|
|
9738
|
-
for (const warning of result.warnings) {
|
|
9739
|
-
console.warn(
|
|
9740
|
-
`[server-cache-bundle] WARN ${JSON.stringify({
|
|
9741
|
-
kind: "esbuild-warning",
|
|
9742
|
-
message: warning.text,
|
|
9743
|
-
location: warning.location
|
|
9744
|
-
})}`
|
|
9745
|
-
);
|
|
9746
|
-
}
|
|
9747
|
-
const nativeInputs = Object.keys(result.metafile.inputs).filter(
|
|
9748
|
-
(input) => input.endsWith(".node")
|
|
9749
|
-
);
|
|
9750
|
-
if (nativeInputs.length > 0) {
|
|
9751
|
-
return fail([
|
|
9752
|
-
`native addons are unsupported: ${nativeInputs.join(", ")}`
|
|
9753
|
-
]);
|
|
9754
|
-
}
|
|
9755
|
-
const externalImports = collectExternalImports(
|
|
9756
|
-
result.metafile,
|
|
9757
|
-
tempOutfile,
|
|
9758
|
-
projectRoot
|
|
9759
|
-
);
|
|
9760
|
-
if (externalImports.length > 0) {
|
|
9761
|
-
return fail([`external imports remain: ${externalImports.join(", ")}`]);
|
|
9762
|
-
}
|
|
9763
|
-
const buildOnlyInputs = collectBuildOnlyInputs(
|
|
9764
|
-
projectRoot,
|
|
9765
|
-
result.metafile
|
|
9766
|
-
);
|
|
9767
|
-
if (buildOnlyInputs.length > 0) {
|
|
9768
|
-
return fail([
|
|
9769
|
-
`build-only packages entered server cache bundle: ${buildOnlyInputs.join(", ")}`
|
|
9770
|
-
]);
|
|
9771
|
-
}
|
|
9772
|
-
const configuredRuntimeAssets = [
|
|
9773
|
-
...packageJson.miaodaCache?.runtimeAssets ?? [],
|
|
9774
|
-
...availabilityProbeConfig.legacyCapabilityProbe?.files.length ? [
|
|
9775
|
-
{
|
|
9776
|
-
source: "server/capabilities",
|
|
9777
|
-
path: "server/capabilities"
|
|
9778
|
-
}
|
|
9779
|
-
] : []
|
|
9780
|
-
];
|
|
9781
|
-
const materializedRuntimeAssets = materializeServerRuntimeAssets(
|
|
9782
|
-
projectRoot,
|
|
9783
|
-
result.metafile,
|
|
9784
|
-
tempRoot,
|
|
9785
|
-
configuredRuntimeAssets
|
|
9786
|
-
);
|
|
9787
|
-
const runtimeAssets = materializedRuntimeAssets.assets;
|
|
9788
|
-
const runtimeAssetWarnings = materializedRuntimeAssets.warnings;
|
|
9789
|
-
const dynamicImportWarnings = collectDynamicImportWarnings(
|
|
9790
|
-
projectRoot,
|
|
9791
|
-
result.metafile
|
|
9792
|
-
);
|
|
9793
|
-
for (const warning of [...dynamicImportWarnings, ...runtimeAssetWarnings]) {
|
|
9794
|
-
console.warn(`[server-cache-bundle] WARN ${JSON.stringify(warning)}`);
|
|
9795
|
-
}
|
|
9796
|
-
const availabilityProbe = await runAvailabilityProbe(
|
|
9797
|
-
tempOutfile,
|
|
9798
|
-
runtimeAssets,
|
|
9799
|
-
options.probeTimeoutMs ?? 3e4,
|
|
9800
|
-
availabilityProbeConfig,
|
|
9801
|
-
actionPlugins.length,
|
|
9802
|
-
actionPluginProbe?.key
|
|
9803
|
-
);
|
|
9804
|
-
if (!availabilityProbe.success || availabilityProbe.nodeModulesPresent) {
|
|
9805
|
-
return fail([
|
|
9806
|
-
"isolated node_modules-free availability probe failed",
|
|
9807
|
-
...availabilityProbe.checks.filter((check2) => !check2.success).map(
|
|
9808
|
-
(check2) => `${check2.name}: ${check2.message ?? `HTTP ${check2.status ?? "unavailable"}`}`
|
|
9809
|
-
),
|
|
9810
|
-
...availabilityProbe.stderr ? [availabilityProbe.stderr] : [],
|
|
9811
|
-
...availabilityProbe.stdout ? [availabilityProbe.stdout] : []
|
|
9812
|
-
]);
|
|
9813
|
-
}
|
|
9814
|
-
const bundleSha256 = createHash("sha256").update(fs29.readFileSync(tempOutfile)).digest("hex");
|
|
9815
|
-
const sealedAvailabilityProbe = {
|
|
9816
|
-
success: availabilityProbe.success,
|
|
9817
|
-
nodeModulesPresent: availabilityProbe.nodeModulesPresent,
|
|
9818
|
-
startupMs: availabilityProbe.startupMs,
|
|
9819
|
-
checks: availabilityProbe.checks,
|
|
9820
|
-
...availabilityProbe.stderr ? { stderr: availabilityProbe.stderr } : {}
|
|
9821
|
-
};
|
|
9822
|
-
const metadata = {
|
|
9823
|
-
schemaVersion: 2,
|
|
9824
|
-
entry: path26.relative(projectRoot, entry).split(path26.sep).join("/"),
|
|
9825
|
-
outfile: "server/server.bundle.cjs",
|
|
9826
|
-
nodeVersion: process.version,
|
|
9827
|
-
nodeModuleAbi: process.versions.modules,
|
|
9828
|
-
platform: process.platform,
|
|
9829
|
-
arch: process.arch,
|
|
9830
|
-
bundleBytes: fs29.statSync(tempOutfile).size,
|
|
9831
|
-
bundleSha256,
|
|
9832
|
-
inputFiles: Object.keys(result.metafile.inputs).length,
|
|
9833
|
-
workspaceSourceSha256: workspaceSourceSha256(projectRoot),
|
|
9834
|
-
externalImports,
|
|
9835
|
-
dynamicImportWarnings,
|
|
9836
|
-
runtimeAssetWarnings,
|
|
9837
|
-
actionPlugins: actionPlugins.map(({ name, version }) => ({
|
|
9838
|
-
name,
|
|
9839
|
-
version
|
|
9840
|
-
})),
|
|
9841
|
-
runtimeAssets,
|
|
9842
|
-
availabilityProbe: sealedAvailabilityProbe,
|
|
9843
|
-
consumable: true
|
|
9844
|
-
};
|
|
9845
|
-
fs29.writeFileSync(
|
|
9846
|
-
path26.join(tempRoot, path26.basename(metadataFile)),
|
|
9847
|
-
`${JSON.stringify(metadata, null, 2)}
|
|
9848
|
-
`
|
|
9849
|
-
);
|
|
9850
|
-
fs29.mkdirSync(path26.dirname(serverOutputRoot), { recursive: true });
|
|
9851
|
-
fs29.renameSync(tempRoot, serverOutputRoot);
|
|
9852
|
-
return {
|
|
9853
|
-
built: true,
|
|
9854
|
-
outfile,
|
|
9855
|
-
metadataFile,
|
|
9856
|
-
bundleBytes: metadata.bundleBytes,
|
|
9857
|
-
inputFiles: metadata.inputFiles,
|
|
9858
|
-
externalImports,
|
|
9859
|
-
dynamicImportWarnings,
|
|
9860
|
-
runtimeAssetWarnings,
|
|
9861
|
-
runtimeAssets,
|
|
9862
|
-
actionPlugins: actionPlugins.map(({ name, version }) => ({
|
|
9863
|
-
name,
|
|
9864
|
-
version
|
|
9865
|
-
})),
|
|
9866
|
-
availabilityProbe,
|
|
9867
|
-
reasons: [],
|
|
9868
|
-
elapsedMs: Date.now() - startedAt
|
|
9869
|
-
};
|
|
9870
|
-
} catch (error) {
|
|
9871
|
-
fs29.rmSync(serverOutputRoot, { recursive: true, force: true });
|
|
9872
|
-
return fail([error instanceof Error ? error.message : String(error)]);
|
|
9873
|
-
} finally {
|
|
9874
|
-
fs29.rmSync(tempRoot, { recursive: true, force: true });
|
|
9875
|
-
}
|
|
9876
|
-
}
|
|
9877
|
-
|
|
9878
|
-
// src/commands/build/server-runtime-dependencies.handler.ts
|
|
9879
|
-
import crypto from "crypto";
|
|
9880
|
-
import fs30 from "fs";
|
|
9881
|
-
import path27 from "path";
|
|
9882
|
-
import { createRequire as createRequire4 } from "module";
|
|
9883
|
-
import { nodeFileTrace } from "@vercel/nft";
|
|
9884
|
-
var DEFAULT_COMPILED_ENTRIES2 = [
|
|
9885
|
-
"dist/server/main.js",
|
|
9886
|
-
"dist/main.js"
|
|
9887
|
-
];
|
|
9888
|
-
var DEFAULT_SOURCE_ENTRIES = ["server/main.ts", "src/main.ts"];
|
|
9889
|
-
var TRANSITION_BOOTSTRAP_SPECIFIERS = [
|
|
9890
|
-
"ts-node/register/transpile-only",
|
|
9891
|
-
"tsconfig-paths/register"
|
|
9892
|
-
];
|
|
9893
|
-
var TRANSITION_TOOLCHAIN_TRACE_SPECIFIERS = ["typescript"];
|
|
9894
|
-
var PROJECT_ROOT_TOKEN = "${MIAODA_WORKSPACE_ROOT}";
|
|
9895
|
-
function isPathInside2(root, candidate) {
|
|
9896
|
-
const relative = path27.relative(root, candidate);
|
|
9897
|
-
return relative === "" || !relative.startsWith("..") && !path27.isAbsolute(relative);
|
|
9898
|
-
}
|
|
9899
|
-
function sha256(file) {
|
|
9900
|
-
return crypto.createHash("sha256").update(fs30.readFileSync(file)).digest("hex");
|
|
9901
|
-
}
|
|
9902
|
-
function resolveExistingFile(projectRoot, requested, defaults, label) {
|
|
9903
|
-
if (requested) {
|
|
9904
|
-
const candidate = path27.resolve(projectRoot, requested);
|
|
9905
|
-
if (!fs30.existsSync(candidate) || !fs30.statSync(candidate).isFile()) {
|
|
9906
|
-
throw new Error(`${label} missing: ${candidate}`);
|
|
9907
|
-
}
|
|
9908
|
-
return candidate;
|
|
9909
|
-
}
|
|
9910
|
-
const matches = defaults.map((relative) => path27.join(projectRoot, relative)).filter((candidate) => fs30.existsSync(candidate));
|
|
9911
|
-
if (matches.length === 1) return matches[0];
|
|
9912
|
-
if (matches.length > 1) {
|
|
9913
|
-
throw new Error(
|
|
9914
|
-
`${label} is ambiguous; pass it explicitly: ${matches.join(", ")}`
|
|
9915
|
-
);
|
|
9916
|
-
}
|
|
9917
|
-
throw new Error(
|
|
9918
|
-
`${label} missing; checked: ${defaults.map((relative) => path27.join(projectRoot, relative)).join(", ")}`
|
|
9919
|
-
);
|
|
9920
|
-
}
|
|
9921
|
-
function packageLocationFromNodeModulesPath(candidate) {
|
|
9922
|
-
const parts = candidate.split(/[\\/]+/);
|
|
9923
|
-
const nodeModulesIndex = parts.lastIndexOf("node_modules");
|
|
9924
|
-
if (nodeModulesIndex < 0 || nodeModulesIndex + 1 >= parts.length) {
|
|
9925
|
-
return void 0;
|
|
9926
|
-
}
|
|
9927
|
-
const first = parts[nodeModulesIndex + 1];
|
|
9928
|
-
let name;
|
|
9929
|
-
let packageEnd;
|
|
9930
|
-
if (first.startsWith("@")) {
|
|
9931
|
-
const second = parts[nodeModulesIndex + 2];
|
|
9932
|
-
if (!second) return void 0;
|
|
9933
|
-
name = `${first}/${second}`;
|
|
9934
|
-
packageEnd = nodeModulesIndex + 3;
|
|
9935
|
-
} else {
|
|
9936
|
-
name = first;
|
|
9937
|
-
packageEnd = nodeModulesIndex + 2;
|
|
9938
|
-
}
|
|
9939
|
-
return {
|
|
9940
|
-
name,
|
|
9941
|
-
relativeRoot: parts.slice(0, packageEnd).join("/")
|
|
9942
|
-
};
|
|
9943
|
-
}
|
|
9944
|
-
function packageRoot(nodeModulesRoot, packageName) {
|
|
9945
|
-
return path27.join(nodeModulesRoot, ...packageName.split("/"));
|
|
9946
|
-
}
|
|
9947
|
-
function readPackage(nodeModulesRoot, packageName) {
|
|
9948
|
-
const packageFile = path27.join(
|
|
9949
|
-
packageRoot(nodeModulesRoot, packageName),
|
|
9950
|
-
"package.json"
|
|
9951
|
-
);
|
|
9952
|
-
if (!fs30.existsSync(packageFile)) {
|
|
9953
|
-
throw new Error(`runtime package is missing: ${packageName}`);
|
|
9954
|
-
}
|
|
9955
|
-
return JSON.parse(fs30.readFileSync(packageFile, "utf8"));
|
|
9956
|
-
}
|
|
9957
|
-
function parseJsonc(file, projectRequire) {
|
|
9958
|
-
const typescript = projectRequire("typescript");
|
|
9959
|
-
const parsed = typescript.parseConfigFileTextToJson(
|
|
9960
|
-
file,
|
|
9961
|
-
fs30.readFileSync(file, "utf8")
|
|
9962
|
-
);
|
|
9963
|
-
if (parsed.error || !parsed.config) {
|
|
9964
|
-
throw new Error(
|
|
9965
|
-
`tsconfig is invalid: ${file}: ${String(parsed.error?.messageText ?? "")}`
|
|
9966
|
-
);
|
|
9967
|
-
}
|
|
9968
|
-
return parsed.config;
|
|
9969
|
-
}
|
|
9970
|
-
function resolveTsconfigPackageEntries(projectRoot, projectRequire) {
|
|
9971
|
-
const entries = /* @__PURE__ */ new Set();
|
|
9972
|
-
const visited = /* @__PURE__ */ new Set();
|
|
9973
|
-
const initial = ["tsconfig.node.json", "tsconfig.json"].map((relative) => path27.join(projectRoot, relative)).find((file) => fs30.existsSync(file));
|
|
9974
|
-
if (!initial) return [];
|
|
9975
|
-
const visit = (file) => {
|
|
9976
|
-
const resolvedFile = fs30.realpathSync(file);
|
|
9977
|
-
if (visited.has(resolvedFile)) return;
|
|
9978
|
-
visited.add(resolvedFile);
|
|
9979
|
-
const config = parseJsonc(resolvedFile, projectRequire);
|
|
9980
|
-
if (typeof config.extends !== "string" || !config.extends) return;
|
|
9981
|
-
const specifier = config.extends;
|
|
9982
|
-
if (specifier.startsWith(".") || path27.isAbsolute(specifier)) {
|
|
9983
|
-
const candidate = path27.resolve(path27.dirname(resolvedFile), specifier);
|
|
9984
|
-
const configFile = fs30.existsSync(candidate) ? candidate : `${candidate}.json`;
|
|
9985
|
-
if (!fs30.existsSync(configFile)) {
|
|
9986
|
-
throw new Error(`tsconfig extends file is missing: ${specifier}`);
|
|
9987
|
-
}
|
|
9988
|
-
visit(configFile);
|
|
9989
|
-
return;
|
|
9990
|
-
}
|
|
9991
|
-
let entry;
|
|
9992
|
-
try {
|
|
9993
|
-
entry = projectRequire.resolve(specifier);
|
|
9994
|
-
} catch {
|
|
9995
|
-
try {
|
|
9996
|
-
entry = projectRequire.resolve(`${specifier}.json`);
|
|
9997
|
-
} catch {
|
|
9998
|
-
throw new Error(`tsconfig extends package is missing: ${specifier}`);
|
|
9999
|
-
}
|
|
10000
|
-
}
|
|
10001
|
-
entries.add(entry);
|
|
10002
|
-
if (entry.endsWith(".json")) visit(entry);
|
|
10003
|
-
};
|
|
10004
|
-
visit(initial);
|
|
10005
|
-
return [...entries];
|
|
10006
|
-
}
|
|
10007
|
-
function transitionCompilerOptions(projectRoot, projectRequire) {
|
|
10008
|
-
const configFile = ["tsconfig.node.json", "tsconfig.json"].map((relative) => path27.join(projectRoot, relative)).find((file) => fs30.existsSync(file));
|
|
10009
|
-
if (!configFile) throw new Error("server tsconfig is missing");
|
|
10010
|
-
const typescript = projectRequire("typescript");
|
|
10011
|
-
let fatalDiagnostic = "";
|
|
10012
|
-
const parsed = typescript.getParsedCommandLineOfConfigFile(
|
|
10013
|
-
configFile,
|
|
10014
|
-
{},
|
|
10015
|
-
{
|
|
10016
|
-
...typescript.sys,
|
|
10017
|
-
onUnRecoverableConfigFileDiagnostic: (diagnostic) => {
|
|
10018
|
-
fatalDiagnostic = typescript.flattenDiagnosticMessageText(
|
|
10019
|
-
diagnostic.messageText,
|
|
10020
|
-
"\n"
|
|
10021
|
-
);
|
|
10022
|
-
}
|
|
10023
|
-
}
|
|
10024
|
-
);
|
|
10025
|
-
const errors = parsed?.errors.filter((error) => error.category === typescript.DiagnosticCategory.Error).map(
|
|
10026
|
-
(error) => typescript.flattenDiagnosticMessageText(error.messageText, "\n")
|
|
10027
|
-
);
|
|
10028
|
-
if (!parsed || fatalDiagnostic || errors?.length) {
|
|
10029
|
-
throw new Error(
|
|
10030
|
-
`server tsconfig cannot be resolved: ${fatalDiagnostic || errors?.join("; ") || configFile}`
|
|
10031
|
-
);
|
|
10032
|
-
}
|
|
10033
|
-
const tokeniseProjectPaths = (value) => {
|
|
10034
|
-
if (typeof value === "string" && path27.isAbsolute(value)) {
|
|
10035
|
-
if (!isPathInside2(projectRoot, value)) {
|
|
10036
|
-
throw new Error(`server compiler option path escaped project: ${value}`);
|
|
10037
|
-
}
|
|
10038
|
-
const relative = path27.relative(projectRoot, value).split(path27.sep).join("/");
|
|
10039
|
-
return relative ? `${PROJECT_ROOT_TOKEN}/${relative}` : PROJECT_ROOT_TOKEN;
|
|
10040
|
-
}
|
|
10041
|
-
if (Array.isArray(value)) return value.map(tokeniseProjectPaths);
|
|
10042
|
-
if (value && typeof value === "object") {
|
|
10043
|
-
return Object.fromEntries(
|
|
10044
|
-
Object.entries(value).map(([key, entry]) => [
|
|
10045
|
-
key,
|
|
10046
|
-
tokeniseProjectPaths(entry)
|
|
10047
|
-
])
|
|
10048
|
-
);
|
|
10049
|
-
}
|
|
10050
|
-
return value;
|
|
10051
|
-
};
|
|
10052
|
-
return tokeniseProjectPaths(
|
|
10053
|
-
Object.fromEntries(typescript.serializeCompilerOptions(parsed.options))
|
|
10054
|
-
);
|
|
10055
|
-
}
|
|
10056
|
-
function collectDeclaredPluginClosure(nodeModulesRoot, seeds) {
|
|
10057
|
-
const selected = new Set(seeds);
|
|
10058
|
-
const pending = [...selected];
|
|
10059
|
-
while (pending.length > 0) {
|
|
10060
|
-
const packageName = pending.shift();
|
|
10061
|
-
const packageJson = readPackage(nodeModulesRoot, packageName);
|
|
10062
|
-
const declared = {
|
|
10063
|
-
...packageJson.dependencies ?? {},
|
|
10064
|
-
...packageJson.optionalDependencies ?? {},
|
|
10065
|
-
...packageJson.peerDependencies ?? {}
|
|
10066
|
-
};
|
|
10067
|
-
for (const dependencyName of Object.keys(declared)) {
|
|
10068
|
-
if (!fs30.existsSync(packageRoot(nodeModulesRoot, dependencyName))) {
|
|
10069
|
-
const optional = packageJson.peerDependenciesMeta?.[dependencyName]?.optional === true || Object.hasOwn(packageJson.optionalDependencies ?? {}, dependencyName);
|
|
10070
|
-
if (optional) continue;
|
|
10071
|
-
throw new Error(
|
|
10072
|
-
`ActionPlugin runtime dependency ${dependencyName} required by ${packageName} is missing`
|
|
10073
|
-
);
|
|
10074
|
-
}
|
|
10075
|
-
if (!selected.has(dependencyName)) {
|
|
10076
|
-
selected.add(dependencyName);
|
|
10077
|
-
pending.push(dependencyName);
|
|
10078
|
-
}
|
|
10079
|
-
}
|
|
10080
|
-
}
|
|
10081
|
-
return selected;
|
|
10082
|
-
}
|
|
10083
|
-
function copyDereferenced(source, destination) {
|
|
10084
|
-
const stat = fs30.lstatSync(source);
|
|
10085
|
-
if (stat.isSymbolicLink()) {
|
|
10086
|
-
copyDereferenced(fs30.realpathSync(source), destination);
|
|
10087
|
-
return;
|
|
10088
|
-
}
|
|
10089
|
-
if (stat.isDirectory()) {
|
|
10090
|
-
fs30.mkdirSync(destination, { recursive: true });
|
|
10091
|
-
for (const entry of fs30.readdirSync(source)) {
|
|
10092
|
-
copyDereferenced(
|
|
10093
|
-
path27.join(source, entry),
|
|
10094
|
-
path27.join(destination, entry)
|
|
10095
|
-
);
|
|
10096
|
-
}
|
|
10097
|
-
return;
|
|
10098
|
-
}
|
|
10099
|
-
if (!stat.isFile()) {
|
|
10100
|
-
throw new Error(`unsupported runtime dependency file: ${source}`);
|
|
10101
|
-
}
|
|
10102
|
-
fs30.mkdirSync(path27.dirname(destination), { recursive: true });
|
|
10103
|
-
fs30.copyFileSync(source, destination);
|
|
10104
|
-
fs30.chmodSync(destination, stat.mode & 511);
|
|
10105
|
-
}
|
|
10106
|
-
function listRuntimeFiles(nodeModulesRoot) {
|
|
10107
|
-
const files = [];
|
|
10108
|
-
const visit = (directory) => {
|
|
10109
|
-
for (const entry of fs30.readdirSync(directory, { withFileTypes: true })) {
|
|
10110
|
-
const candidate = path27.join(directory, entry.name);
|
|
10111
|
-
if (entry.isSymbolicLink()) {
|
|
10112
|
-
throw new Error(`runtime dependency cache contains symlink: ${candidate}`);
|
|
10113
|
-
}
|
|
10114
|
-
if (entry.isDirectory()) {
|
|
10115
|
-
visit(candidate);
|
|
10116
|
-
} else if (entry.isFile()) {
|
|
10117
|
-
files.push({
|
|
10118
|
-
path: path27.relative(nodeModulesRoot, candidate).split(path27.sep).join("/"),
|
|
10119
|
-
sha256: sha256(candidate),
|
|
10120
|
-
size: fs30.statSync(candidate).size
|
|
10121
|
-
});
|
|
10122
|
-
}
|
|
10123
|
-
}
|
|
10124
|
-
};
|
|
10125
|
-
visit(nodeModulesRoot);
|
|
10126
|
-
return files.sort((left, right) => left.path.localeCompare(right.path));
|
|
10127
|
-
}
|
|
10128
|
-
function stableTreeSha256(files) {
|
|
10129
|
-
return crypto.createHash("sha256").update(JSON.stringify(files)).digest("hex");
|
|
10130
|
-
}
|
|
10131
|
-
function validateOutput(projectRoot, outdir, metadataFile) {
|
|
10132
|
-
const expectedRoot = path27.join(projectRoot, ".miaoda-cache");
|
|
10133
|
-
if (!isPathInside2(expectedRoot, outdir) || path27.basename(outdir) !== "node_modules" || path27.basename(path27.dirname(outdir)) !== "server" || metadataFile !== path27.join(path27.dirname(outdir), "dependencies.json")) {
|
|
10134
|
-
throw new Error(
|
|
10135
|
-
"server runtime dependency output must be a .miaoda-cache/**/server/node_modules directory with adjacent dependencies.json"
|
|
10136
|
-
);
|
|
10137
|
-
}
|
|
10138
|
-
}
|
|
10139
|
-
async function buildServerRuntimeDependencies(options) {
|
|
10140
|
-
const startedAt = Date.now();
|
|
10141
|
-
const projectRoot = fs30.realpathSync(path27.resolve(options.projectRoot));
|
|
10142
|
-
const outdir = path27.resolve(
|
|
10143
|
-
projectRoot,
|
|
10144
|
-
options.outdir ?? ".miaoda-cache/server/node_modules"
|
|
10145
|
-
);
|
|
10146
|
-
const metadataFile = path27.resolve(
|
|
10147
|
-
projectRoot,
|
|
10148
|
-
options.metadataFile ?? path27.join(path27.dirname(outdir), "dependencies.json")
|
|
10149
|
-
);
|
|
10150
|
-
const stagingRoot = path27.join(
|
|
10151
|
-
path27.dirname(outdir),
|
|
10152
|
-
`.dependencies-staging-${process.pid}-${Date.now()}`
|
|
10153
|
-
);
|
|
10154
|
-
const stagingNodeModules = path27.join(stagingRoot, "node_modules");
|
|
10155
|
-
const serverOutputRoot = path27.dirname(outdir);
|
|
10156
|
-
try {
|
|
10157
|
-
validateOutput(projectRoot, outdir, metadataFile);
|
|
10158
|
-
fs30.rmSync(serverOutputRoot, { recursive: true, force: true });
|
|
10159
|
-
fs30.mkdirSync(serverOutputRoot, { recursive: true });
|
|
10160
|
-
const compiledEntry = resolveExistingFile(
|
|
10161
|
-
projectRoot,
|
|
10162
|
-
options.entry,
|
|
10163
|
-
DEFAULT_COMPILED_ENTRIES2,
|
|
10164
|
-
"compiled Nest entry"
|
|
10165
|
-
);
|
|
10166
|
-
const sourceEntry = resolveExistingFile(
|
|
10167
|
-
projectRoot,
|
|
10168
|
-
options.sourceEntry,
|
|
10169
|
-
DEFAULT_SOURCE_ENTRIES,
|
|
10170
|
-
"Nest source entry"
|
|
10171
|
-
);
|
|
10172
|
-
const projectPackageFile = path27.join(projectRoot, "package.json");
|
|
10173
|
-
const projectNodeModules = path27.join(projectRoot, "node_modules");
|
|
10174
|
-
if (!fs30.existsSync(projectPackageFile) || !fs30.existsSync(projectNodeModules)) {
|
|
10175
|
-
throw new Error("project package.json or node_modules is missing");
|
|
10176
|
-
}
|
|
10177
|
-
const projectPackage = JSON.parse(
|
|
10178
|
-
fs30.readFileSync(projectPackageFile, "utf8")
|
|
10179
|
-
);
|
|
10180
|
-
const projectRequire = createRequire4(projectPackageFile);
|
|
10181
|
-
const configuredPlatformRuntimeRoot = process.env.MIAODA_PLATFORM_RUNTIME_ROOT;
|
|
10182
|
-
const platformNodeModules = configuredPlatformRuntimeRoot ? path27.join(
|
|
10183
|
-
fs30.realpathSync(path27.resolve(configuredPlatformRuntimeRoot)),
|
|
10184
|
-
"node_modules"
|
|
10185
|
-
) : void 0;
|
|
10186
|
-
if (platformNodeModules && (!fs30.existsSync(platformNodeModules) || !fs30.statSync(platformNodeModules).isDirectory())) {
|
|
10187
|
-
throw new Error(
|
|
10188
|
-
`platform runtime node_modules is missing: ${platformNodeModules}`
|
|
10189
|
-
);
|
|
10190
|
-
}
|
|
10191
|
-
const traceBase = platformNodeModules ? path27.parse(projectRoot).root : projectRoot;
|
|
10192
|
-
const bootstrapEntries = TRANSITION_BOOTSTRAP_SPECIFIERS.map((specifier) => {
|
|
10193
|
-
try {
|
|
10194
|
-
return projectRequire.resolve(specifier);
|
|
10195
|
-
} catch {
|
|
10196
|
-
throw new Error(`transition bootstrap module is missing: ${specifier}`);
|
|
10197
|
-
}
|
|
10198
|
-
});
|
|
10199
|
-
const toolchainTraceEntries = TRANSITION_TOOLCHAIN_TRACE_SPECIFIERS.map(
|
|
10200
|
-
(specifier) => {
|
|
10201
|
-
try {
|
|
10202
|
-
return projectRequire.resolve(specifier);
|
|
10203
|
-
} catch {
|
|
10204
|
-
throw new Error(`transition toolchain module is missing: ${specifier}`);
|
|
10205
|
-
}
|
|
10206
|
-
}
|
|
10207
|
-
);
|
|
10208
|
-
const actionPluginNames = Object.keys(projectPackage.actionPlugins ?? {});
|
|
10209
|
-
const actionPluginEntries = actionPluginNames.map((name) => {
|
|
10210
|
-
try {
|
|
10211
|
-
return projectRequire.resolve(name);
|
|
10212
|
-
} catch {
|
|
10213
|
-
throw new Error(`ActionPlugin entry is missing: ${name}`);
|
|
10214
|
-
}
|
|
10215
|
-
});
|
|
10216
|
-
const tsconfigPackageEntries = resolveTsconfigPackageEntries(
|
|
10217
|
-
projectRoot,
|
|
10218
|
-
projectRequire
|
|
10219
|
-
);
|
|
10220
|
-
const compilerOptions = transitionCompilerOptions(
|
|
10221
|
-
projectRoot,
|
|
10222
|
-
projectRequire
|
|
10223
|
-
);
|
|
10224
|
-
const trace = await nodeFileTrace(
|
|
10225
|
-
[
|
|
10226
|
-
compiledEntry,
|
|
10227
|
-
...bootstrapEntries,
|
|
10228
|
-
...toolchainTraceEntries,
|
|
10229
|
-
...tsconfigPackageEntries,
|
|
10230
|
-
...actionPluginEntries
|
|
10231
|
-
],
|
|
10232
|
-
{
|
|
10233
|
-
base: traceBase,
|
|
10234
|
-
processCwd: projectRoot,
|
|
10235
|
-
ts: false,
|
|
10236
|
-
conditions: ["node", "development"]
|
|
10237
|
-
}
|
|
10238
|
-
);
|
|
10239
|
-
const tracedFiles = /* @__PURE__ */ new Map();
|
|
10240
|
-
const packageLocations = /* @__PURE__ */ new Map();
|
|
10241
|
-
const addTracedFile = (candidate) => {
|
|
10242
|
-
let source = path27.isAbsolute(candidate) ? candidate : path27.resolve(traceBase, candidate);
|
|
10243
|
-
if (!fs30.existsSync(source)) {
|
|
10244
|
-
return;
|
|
10245
|
-
}
|
|
10246
|
-
const sourceStat = fs30.lstatSync(source);
|
|
10247
|
-
if (sourceStat.isSymbolicLink()) {
|
|
10248
|
-
const realSource = fs30.realpathSync(source);
|
|
10249
|
-
if (fs30.statSync(realSource).isDirectory()) {
|
|
10250
|
-
if (platformNodeModules && isPathInside2(platformNodeModules, realSource)) {
|
|
10251
|
-
return;
|
|
10252
|
-
}
|
|
10253
|
-
throw new Error(`runtime dependency symlink is not trusted: ${source}`);
|
|
10254
|
-
}
|
|
10255
|
-
source = realSource;
|
|
10256
|
-
}
|
|
10257
|
-
const sourceNodeModules = [projectNodeModules, platformNodeModules].filter((root) => Boolean(root)).find((root) => isPathInside2(root, source));
|
|
10258
|
-
if (!sourceNodeModules) {
|
|
10259
|
-
return;
|
|
10260
|
-
}
|
|
10261
|
-
const relativeNodeModulesPath = path27.relative(sourceNodeModules, source);
|
|
10262
|
-
const logicalProjectPath = path27.join("node_modules", relativeNodeModulesPath).split(path27.sep).join("/");
|
|
10263
|
-
const location = packageLocationFromNodeModulesPath(logicalProjectPath);
|
|
10264
|
-
if (!location) return;
|
|
10265
|
-
const sourceRoot = path27.join(
|
|
10266
|
-
sourceNodeModules,
|
|
10267
|
-
...location.relativeRoot.replace(/^node_modules\//, "").split("/")
|
|
10268
|
-
);
|
|
10269
|
-
const destinationRoot = path27.join(
|
|
10270
|
-
stagingNodeModules,
|
|
10271
|
-
...location.relativeRoot.replace(/^node_modules\//, "").split("/")
|
|
10272
|
-
);
|
|
10273
|
-
packageLocations.set(location.relativeRoot, {
|
|
10274
|
-
name: location.name,
|
|
10275
|
-
destinationRoot
|
|
10276
|
-
});
|
|
10277
|
-
const addFile = (file, destination) => {
|
|
10278
|
-
const previous = tracedFiles.get(destination);
|
|
10279
|
-
if (previous && fs30.realpathSync(previous) !== fs30.realpathSync(file) && sha256(previous) !== sha256(file)) {
|
|
10280
|
-
throw new Error(
|
|
10281
|
-
`runtime dependency destination conflict: ${destination}`
|
|
10282
|
-
);
|
|
10283
|
-
}
|
|
10284
|
-
tracedFiles.set(destination, file);
|
|
10285
|
-
};
|
|
10286
|
-
addFile(
|
|
10287
|
-
source,
|
|
10288
|
-
path27.join(stagingNodeModules, relativeNodeModulesPath)
|
|
10289
|
-
);
|
|
10290
|
-
addFile(
|
|
10291
|
-
path27.join(sourceRoot, "package.json"),
|
|
10292
|
-
path27.join(destinationRoot, "package.json")
|
|
10293
|
-
);
|
|
10294
|
-
};
|
|
10295
|
-
for (const file of trace.fileList) {
|
|
10296
|
-
addTracedFile(file);
|
|
10297
|
-
}
|
|
10298
|
-
for (const specifier of TRANSITION_BOOTSTRAP_SPECIFIERS) {
|
|
10299
|
-
addTracedFile(projectRequire.resolve(specifier));
|
|
10300
|
-
}
|
|
10301
|
-
for (const specifier of TRANSITION_TOOLCHAIN_TRACE_SPECIFIERS) {
|
|
10302
|
-
addTracedFile(projectRequire.resolve(specifier));
|
|
10303
|
-
}
|
|
10304
|
-
for (const entry of tsconfigPackageEntries) {
|
|
10305
|
-
addTracedFile(entry);
|
|
10306
|
-
}
|
|
10307
|
-
const pluginClosure = collectDeclaredPluginClosure(
|
|
10308
|
-
projectNodeModules,
|
|
10309
|
-
actionPluginNames
|
|
10310
|
-
);
|
|
10311
|
-
fs30.rmSync(stagingRoot, { recursive: true, force: true });
|
|
10312
|
-
fs30.mkdirSync(stagingNodeModules, { recursive: true });
|
|
10313
|
-
for (const [destination, source] of [...tracedFiles.entries()].sort(
|
|
10314
|
-
([left], [right]) => left.localeCompare(right)
|
|
10315
|
-
)) {
|
|
10316
|
-
if (!fs30.existsSync(source) || !fs30.statSync(source).isFile()) {
|
|
10317
|
-
throw new Error(`traced runtime dependency file is missing: ${source}`);
|
|
10318
|
-
}
|
|
10319
|
-
copyDereferenced(source, destination);
|
|
10320
|
-
}
|
|
10321
|
-
for (const packageName of [...pluginClosure].sort()) {
|
|
10322
|
-
const sourceRoot = packageRoot(projectNodeModules, packageName);
|
|
10323
|
-
const destinationRoot = packageRoot(stagingNodeModules, packageName);
|
|
10324
|
-
packageLocations.set(`node_modules/${packageName}`, {
|
|
10325
|
-
name: packageName,
|
|
10326
|
-
destinationRoot
|
|
10327
|
-
});
|
|
10328
|
-
fs30.rmSync(destinationRoot, { recursive: true, force: true });
|
|
10329
|
-
copyDereferenced(sourceRoot, destinationRoot);
|
|
10330
|
-
}
|
|
10331
|
-
const files = listRuntimeFiles(stagingNodeModules);
|
|
10332
|
-
const packages = [...packageLocations.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([, location]) => ({
|
|
10333
|
-
name: location.name,
|
|
10334
|
-
version: String(
|
|
10335
|
-
JSON.parse(
|
|
10336
|
-
fs30.readFileSync(
|
|
10337
|
-
path27.join(location.destinationRoot, "package.json"),
|
|
10338
|
-
"utf8"
|
|
10339
|
-
)
|
|
10340
|
-
).version ?? ""
|
|
10341
|
-
)
|
|
10342
|
-
}));
|
|
10343
|
-
if (packages.some((pkg2) => !pkg2.version)) {
|
|
10344
|
-
throw new Error("runtime dependency package version is missing");
|
|
10345
|
-
}
|
|
10346
|
-
const actionPlugins = actionPluginNames.sort().map((name) => {
|
|
10347
|
-
const installedVersion = String(
|
|
10348
|
-
readPackage(stagingNodeModules, name).version ?? ""
|
|
10349
|
-
);
|
|
10350
|
-
const declaredVersion = String(projectPackage.actionPlugins[name]);
|
|
10351
|
-
if (!installedVersion || declaredVersion !== installedVersion) {
|
|
10352
|
-
throw new Error(
|
|
10353
|
-
`ActionPlugin version mismatch: ${name} declared=${declaredVersion} installed=${installedVersion}`
|
|
10354
|
-
);
|
|
10355
|
-
}
|
|
10356
|
-
return { name, version: installedVersion };
|
|
10357
|
-
});
|
|
10358
|
-
const metadata = {
|
|
10359
|
-
schemaVersion: 1,
|
|
10360
|
-
sourceEntry: path27.relative(projectRoot, sourceEntry).split(path27.sep).join("/"),
|
|
10361
|
-
compiledEntry: path27.relative(projectRoot, compiledEntry).split(path27.sep).join("/"),
|
|
10362
|
-
nodeVersion: process.version,
|
|
10363
|
-
nodeModuleAbi: process.versions.modules,
|
|
10364
|
-
platform: process.platform,
|
|
10365
|
-
arch: process.arch,
|
|
10366
|
-
bootstrapModules: [...TRANSITION_BOOTSTRAP_SPECIFIERS],
|
|
10367
|
-
transitionCompilerOptions: compilerOptions,
|
|
10368
|
-
packages,
|
|
10369
|
-
actionPlugins,
|
|
10370
|
-
files,
|
|
10371
|
-
treeSha256: stableTreeSha256(files),
|
|
10372
|
-
fileCount: files.length,
|
|
10373
|
-
totalBytes: files.reduce((total, file) => total + file.size, 0)
|
|
10374
|
-
};
|
|
10375
|
-
fs30.writeFileSync(
|
|
10376
|
-
path27.join(stagingRoot, "dependencies.json"),
|
|
10377
|
-
`${JSON.stringify(metadata, null, 2)}
|
|
10378
|
-
`
|
|
10379
|
-
);
|
|
10380
|
-
fs30.rmSync(outdir, { recursive: true, force: true });
|
|
10381
|
-
fs30.rmSync(metadataFile, { force: true });
|
|
10382
|
-
fs30.renameSync(stagingNodeModules, outdir);
|
|
10383
|
-
fs30.renameSync(path27.join(stagingRoot, "dependencies.json"), metadataFile);
|
|
10384
|
-
fs30.rmSync(stagingRoot, { recursive: true, force: true });
|
|
10385
|
-
return {
|
|
10386
|
-
built: true,
|
|
10387
|
-
outdir,
|
|
10388
|
-
metadataFile,
|
|
10389
|
-
packages,
|
|
10390
|
-
actionPlugins,
|
|
10391
|
-
fileCount: metadata.fileCount,
|
|
10392
|
-
totalBytes: metadata.totalBytes,
|
|
10393
|
-
elapsedMs: Date.now() - startedAt,
|
|
10394
|
-
reasons: []
|
|
10395
|
-
};
|
|
10396
|
-
} catch (error) {
|
|
10397
|
-
fs30.rmSync(serverOutputRoot, { recursive: true, force: true });
|
|
10398
|
-
return {
|
|
10399
|
-
built: false,
|
|
10400
|
-
elapsedMs: Date.now() - startedAt,
|
|
10401
|
-
reasons: [error instanceof Error ? error.message : String(error)]
|
|
10402
|
-
};
|
|
10403
|
-
}
|
|
10404
|
-
}
|
|
10405
|
-
|
|
10406
|
-
// src/commands/build/app-runtime-manifest.handler.ts
|
|
10407
|
-
import fs32 from "fs";
|
|
10408
|
-
import path29 from "path";
|
|
10409
|
-
|
|
10410
|
-
// src/client-dependency-graph.ts
|
|
10411
|
-
import crypto2 from "crypto";
|
|
10412
|
-
import fs31 from "fs";
|
|
10413
|
-
import path28 from "path";
|
|
10414
|
-
import { builtinModules as builtinModules2 } from "module";
|
|
10415
|
-
import { Node as Node11, Project as Project4, SyntaxKind as SyntaxKind7 } from "ts-morph";
|
|
10416
|
-
var BUILTIN_MODULES = /* @__PURE__ */ new Set([
|
|
10417
|
-
...builtinModules2,
|
|
10418
|
-
...builtinModules2.map((name) => `node:${name}`)
|
|
10419
|
-
]);
|
|
10420
|
-
var SOURCE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
10421
|
-
var STYLE_EXTENSIONS = [
|
|
10422
|
-
".css",
|
|
10423
|
-
".less",
|
|
10424
|
-
".sass",
|
|
10425
|
-
".scss",
|
|
10426
|
-
".styl",
|
|
10427
|
-
".stylus"
|
|
10428
|
-
];
|
|
10429
|
-
function packageNameFromSpecifier(specifier) {
|
|
10430
|
-
if (!specifier || specifier.startsWith(".") || specifier.startsWith("/") || specifier.startsWith("\0") || specifier.includes("://") || BUILTIN_MODULES.has(specifier)) {
|
|
10431
|
-
return void 0;
|
|
10432
|
-
}
|
|
10433
|
-
const parts = specifier.split("/");
|
|
10434
|
-
return specifier.startsWith("@") ? parts.length >= 2 ? `${parts[0]}/${parts[1]}` : void 0 : parts[0];
|
|
10435
|
-
}
|
|
10436
|
-
function isStyleSpecifier(specifier) {
|
|
10437
|
-
return STYLE_EXTENSIONS.some(
|
|
10438
|
-
(extension) => new RegExp(`\\${extension}(?:$|\\?)`, "i").test(specifier)
|
|
10439
|
-
);
|
|
10440
|
-
}
|
|
10441
|
-
function resolveLocalFile(specifier, importer, projectRoot, clientRoot) {
|
|
10442
|
-
let candidate;
|
|
10443
|
-
if (specifier.startsWith("@/")) {
|
|
10444
|
-
candidate = path28.join(clientRoot, "src", specifier.slice(2));
|
|
10445
|
-
} else if (specifier.startsWith("@client/")) {
|
|
10446
|
-
candidate = path28.join(clientRoot, specifier.slice("@client/".length));
|
|
10447
|
-
} else if (specifier.startsWith("@shared/")) {
|
|
10448
|
-
candidate = path28.join(
|
|
10449
|
-
projectRoot,
|
|
10450
|
-
"shared",
|
|
10451
|
-
specifier.slice("@shared/".length)
|
|
10452
|
-
);
|
|
10453
|
-
} else if (specifier.startsWith(".") || path28.isAbsolute(specifier)) {
|
|
10454
|
-
candidate = path28.resolve(path28.dirname(importer), specifier);
|
|
10455
|
-
}
|
|
10456
|
-
if (!candidate) return void 0;
|
|
10457
|
-
const projectRelative = path28.relative(projectRoot, path28.resolve(candidate));
|
|
10458
|
-
if (projectRelative === ".." || projectRelative.startsWith(`..${path28.sep}`) || path28.isAbsolute(projectRelative)) {
|
|
10459
|
-
throw new Error(
|
|
10460
|
-
`MIAODA_CLIENT_SOURCE_PATH_ESCAPE: ${specifier} from ${path28.relative(
|
|
10461
|
-
projectRoot,
|
|
10462
|
-
importer
|
|
10463
|
-
)}`
|
|
10464
|
-
);
|
|
10465
|
-
}
|
|
10466
|
-
const extensions = [...SOURCE_EXTENSIONS, ...STYLE_EXTENSIONS];
|
|
10467
|
-
const candidates = [
|
|
10468
|
-
candidate,
|
|
10469
|
-
...extensions.map((extension) => `${candidate}${extension}`),
|
|
10470
|
-
...extensions.map((extension) => path28.join(candidate, `index${extension}`))
|
|
10471
|
-
];
|
|
10472
|
-
const resolvedFile = candidates.find((file) => {
|
|
10473
|
-
try {
|
|
10474
|
-
return fs31.statSync(file).isFile();
|
|
10475
|
-
} catch {
|
|
10476
|
-
return false;
|
|
10477
|
-
}
|
|
10478
|
-
});
|
|
10479
|
-
if (!resolvedFile) return void 0;
|
|
10480
|
-
const realProjectRoot = fs31.realpathSync(projectRoot);
|
|
10481
|
-
const realFile = fs31.realpathSync(resolvedFile);
|
|
10482
|
-
const relative = path28.relative(realProjectRoot, realFile);
|
|
10483
|
-
if (relative === ".." || relative.startsWith(`..${path28.sep}`) || path28.isAbsolute(relative)) {
|
|
10484
|
-
throw new Error(`MIAODA_CLIENT_SOURCE_SYMLINK_ESCAPE: ${resolvedFile}`);
|
|
10485
|
-
}
|
|
10486
|
-
return resolvedFile;
|
|
10487
|
-
}
|
|
10488
|
-
function discoverClientSpecifiers(projectRoot, scanAllSourceFiles = false) {
|
|
10489
|
-
const clientRoot = fs31.existsSync(path28.join(projectRoot, "client")) ? path28.join(projectRoot, "client") : projectRoot;
|
|
10490
|
-
if (!fs31.existsSync(path28.join(clientRoot, "src"))) {
|
|
10491
|
-
return { specifiers: [], optimizeDependencies: [] };
|
|
10492
|
-
}
|
|
10493
|
-
const project = new Project4({
|
|
10494
|
-
skipAddingFilesFromTsConfig: true,
|
|
10495
|
-
compilerOptions: { allowJs: true, jsx: 2 }
|
|
10496
|
-
});
|
|
10497
|
-
const specifiers = /* @__PURE__ */ new Set();
|
|
10498
|
-
const optimizeDependencies = /* @__PURE__ */ new Set();
|
|
10499
|
-
const pending = SOURCE_EXTENSIONS.map(
|
|
10500
|
-
(extension) => path28.join(clientRoot, "src", `index${extension}`)
|
|
10501
|
-
).filter((file) => fs31.existsSync(file));
|
|
10502
|
-
if (scanAllSourceFiles) {
|
|
10503
|
-
const visit = (directory) => {
|
|
10504
|
-
for (const entry of fs31.readdirSync(directory, { withFileTypes: true })) {
|
|
10505
|
-
const file = path28.join(directory, entry.name);
|
|
10506
|
-
if (entry.isSymbolicLink()) {
|
|
10507
|
-
throw new Error(`MIAODA_CLIENT_SOURCE_SYMLINK_REJECTED: ${file}`);
|
|
10508
|
-
}
|
|
10509
|
-
if (entry.isDirectory()) visit(file);
|
|
10510
|
-
else if (entry.isFile() && [...SOURCE_EXTENSIONS, ...STYLE_EXTENSIONS].includes(
|
|
10511
|
-
path28.extname(file)
|
|
10512
|
-
)) {
|
|
10513
|
-
pending.push(file);
|
|
10514
|
-
}
|
|
10515
|
-
}
|
|
10516
|
-
};
|
|
10517
|
-
visit(path28.join(clientRoot, "src"));
|
|
10518
|
-
}
|
|
10519
|
-
const visited = /* @__PURE__ */ new Set();
|
|
10520
|
-
const addBare = (specifier, optimize) => {
|
|
10521
|
-
if (!packageNameFromSpecifier(specifier)) return;
|
|
10522
|
-
specifiers.add(specifier);
|
|
10523
|
-
if (optimize) optimizeDependencies.add(specifier);
|
|
10524
|
-
};
|
|
10525
|
-
const traverse = (specifier, importer, optimize = true) => {
|
|
10526
|
-
const dependency = resolveLocalFile(
|
|
10527
|
-
specifier,
|
|
10528
|
-
importer,
|
|
10529
|
-
projectRoot,
|
|
10530
|
-
clientRoot
|
|
10531
|
-
);
|
|
10532
|
-
if (dependency) pending.push(dependency);
|
|
10533
|
-
else addBare(specifier, optimize && !isStyleSpecifier(specifier));
|
|
10534
|
-
};
|
|
10535
|
-
while (pending.length > 0) {
|
|
10536
|
-
const sourcePath = path28.resolve(pending.pop());
|
|
10537
|
-
if (visited.has(sourcePath)) continue;
|
|
10538
|
-
visited.add(sourcePath);
|
|
10539
|
-
if (STYLE_EXTENSIONS.includes(path28.extname(sourcePath))) {
|
|
10540
|
-
const css = fs31.readFileSync(sourcePath, "utf8");
|
|
10541
|
-
for (const match of css.matchAll(
|
|
10542
|
-
/@(import|plugin)\s+(?:url\(\s*)?["']([^"']+)["']/g
|
|
10543
|
-
)) {
|
|
10544
|
-
traverse(match[2], sourcePath, false);
|
|
10545
|
-
}
|
|
10546
|
-
for (const match of css.matchAll(/@source\s+["']([^"']+)["']/g)) {
|
|
10547
|
-
const marker = /(?:^|[\\/])node_modules[\\/]((?:@[^\\/]+[\\/])?[^\\/*?{}]+)/.exec(
|
|
10548
|
-
match[1]
|
|
10549
|
-
);
|
|
10550
|
-
if (marker) addBare(marker[1].replace(/\\/g, "/"), false);
|
|
10551
|
-
}
|
|
10552
|
-
continue;
|
|
10553
|
-
}
|
|
10554
|
-
const sourceFile = project.addSourceFileAtPath(sourcePath);
|
|
10555
|
-
for (const declaration of sourceFile.getImportDeclarations()) {
|
|
10556
|
-
if (declaration.isTypeOnly()) continue;
|
|
10557
|
-
const namedImports = declaration.getNamedImports();
|
|
10558
|
-
const hasRuntimeBinding = Boolean(declaration.getDefaultImport()) || Boolean(declaration.getNamespaceImport()) || namedImports.length === 0 || namedImports.some((specifier) => !specifier.isTypeOnly());
|
|
10559
|
-
if (hasRuntimeBinding) {
|
|
10560
|
-
traverse(declaration.getModuleSpecifierValue(), sourcePath);
|
|
10561
|
-
}
|
|
10562
|
-
}
|
|
10563
|
-
for (const declaration of sourceFile.getExportDeclarations()) {
|
|
10564
|
-
if (declaration.isTypeOnly()) continue;
|
|
10565
|
-
const namedExports = declaration.getNamedExports();
|
|
10566
|
-
const specifier = declaration.getModuleSpecifierValue();
|
|
10567
|
-
if (specifier && (namedExports.length === 0 || namedExports.some((namedExport) => !namedExport.isTypeOnly()))) {
|
|
10568
|
-
traverse(specifier, sourcePath);
|
|
10569
|
-
}
|
|
10570
|
-
}
|
|
10571
|
-
for (const call of sourceFile.getDescendantsOfKind(
|
|
10572
|
-
SyntaxKind7.CallExpression
|
|
10573
|
-
)) {
|
|
10574
|
-
const expression = call.getExpression();
|
|
10575
|
-
const isDynamicImport = expression.getKind() === SyntaxKind7.ImportKeyword;
|
|
10576
|
-
const isRequire = Node11.isIdentifier(expression) && expression.getText() === "require";
|
|
10577
|
-
if (!isDynamicImport && !isRequire) continue;
|
|
10578
|
-
const argument = call.getArguments()[0];
|
|
10579
|
-
if (!argument || !Node11.isStringLiteral(argument)) {
|
|
10580
|
-
throw new Error(
|
|
10581
|
-
`MIAODA_CLIENT_DYNAMIC_DEPENDENCY_UNSUPPORTED: ${path28.relative(
|
|
10582
|
-
projectRoot,
|
|
10583
|
-
sourcePath
|
|
10584
|
-
)}:${call.getStartLineNumber()}`
|
|
10585
|
-
);
|
|
10586
|
-
}
|
|
10587
|
-
traverse(argument.getLiteralValue(), sourcePath);
|
|
10588
|
-
}
|
|
10589
|
-
}
|
|
10590
|
-
return {
|
|
10591
|
-
specifiers: [...specifiers].sort(),
|
|
10592
|
-
optimizeDependencies: [...optimizeDependencies].sort()
|
|
10593
|
-
};
|
|
10594
|
-
}
|
|
10595
|
-
function parentPackagePath(packagePath) {
|
|
10596
|
-
const nestedMarker = packagePath.lastIndexOf("/node_modules/");
|
|
10597
|
-
if (nestedMarker >= 0) return packagePath.slice(0, nestedMarker);
|
|
10598
|
-
return packagePath.startsWith("node_modules/") ? "" : void 0;
|
|
10599
|
-
}
|
|
10600
|
-
function resolveLockedPackagePath(packages, fromPackagePath, packageName) {
|
|
10601
|
-
let current = fromPackagePath;
|
|
10602
|
-
while (current !== void 0) {
|
|
10603
|
-
const candidate = current ? `${current}/node_modules/${packageName}` : `node_modules/${packageName}`;
|
|
10604
|
-
if (packages[candidate]?.version) return candidate;
|
|
10605
|
-
current = current ? parentPackagePath(current) : void 0;
|
|
10606
|
-
}
|
|
10607
|
-
return void 0;
|
|
10608
|
-
}
|
|
10609
|
-
function canonicalize(value) {
|
|
10610
|
-
return JSON.stringify(value);
|
|
10611
|
-
}
|
|
10612
|
-
function clientConfigFiles(projectRoot) {
|
|
10613
|
-
const fixedNames = [
|
|
10614
|
-
"vite.config.ts",
|
|
10615
|
-
"vite.config.mts",
|
|
10616
|
-
"vite.config.js",
|
|
10617
|
-
"vite.config.mjs",
|
|
10618
|
-
"vite.config.cjs",
|
|
10619
|
-
"postcss.config.js",
|
|
10620
|
-
"postcss.config.cjs",
|
|
10621
|
-
"postcss.config.mjs",
|
|
10622
|
-
"tailwind.config.ts",
|
|
10623
|
-
"tailwind.config.js",
|
|
10624
|
-
"tailwind.config.cjs",
|
|
10625
|
-
"tailwind.config.mjs",
|
|
10626
|
-
"tsconfig.json",
|
|
10627
|
-
"tsconfig.app.json",
|
|
10628
|
-
"tsconfig.node.json",
|
|
10629
|
-
".env",
|
|
10630
|
-
".env.development",
|
|
10631
|
-
".env.development.local"
|
|
10632
|
-
];
|
|
10633
|
-
const pending = fixedNames.map((name) => path28.join(projectRoot, name));
|
|
10634
|
-
for (const patchRootName of ["patches", ".yarn/patches"]) {
|
|
10635
|
-
const patchRoot = path28.join(projectRoot, patchRootName);
|
|
10636
|
-
if (!fs31.existsSync(patchRoot)) continue;
|
|
10637
|
-
const visit = (directory) => {
|
|
10638
|
-
for (const entry of fs31.readdirSync(directory, { withFileTypes: true })) {
|
|
10639
|
-
const file = path28.join(directory, entry.name);
|
|
10640
|
-
if (entry.isSymbolicLink()) {
|
|
10641
|
-
throw new Error(`MIAODA_CLIENT_CONFIG_SYMLINK_REJECTED: ${file}`);
|
|
10642
|
-
}
|
|
10643
|
-
if (entry.isDirectory()) visit(file);
|
|
10644
|
-
else if (entry.isFile()) pending.push(file);
|
|
10645
|
-
}
|
|
10646
|
-
};
|
|
10647
|
-
visit(patchRoot);
|
|
10648
|
-
}
|
|
10649
|
-
const visited = /* @__PURE__ */ new Set();
|
|
10650
|
-
const result = [];
|
|
10651
|
-
const resolveRelativeConfig = (specifier, importer) => {
|
|
10652
|
-
if (!specifier.startsWith(".")) return void 0;
|
|
10653
|
-
const candidate = path28.resolve(path28.dirname(importer), specifier);
|
|
10654
|
-
const candidates = [
|
|
10655
|
-
candidate,
|
|
10656
|
-
...[...SOURCE_EXTENSIONS, ".json"].map(
|
|
10657
|
-
(extension) => `${candidate}${extension}`
|
|
10658
|
-
),
|
|
10659
|
-
...[...SOURCE_EXTENSIONS, ".json"].map(
|
|
10660
|
-
(extension) => path28.join(candidate, `index${extension}`)
|
|
10661
|
-
)
|
|
10662
|
-
];
|
|
10663
|
-
return candidates.find((file) => {
|
|
10664
|
-
const relative = path28.relative(projectRoot, file);
|
|
10665
|
-
return relative !== ".." && !relative.startsWith(`..${path28.sep}`) && !path28.isAbsolute(relative) && fs31.existsSync(file) && fs31.statSync(file).isFile();
|
|
10666
|
-
});
|
|
10667
|
-
};
|
|
10668
|
-
while (pending.length > 0) {
|
|
10669
|
-
const file = path28.resolve(pending.pop());
|
|
10670
|
-
if (visited.has(file) || !fs31.existsSync(file) || !fs31.statSync(file).isFile()) {
|
|
10671
|
-
continue;
|
|
10672
|
-
}
|
|
10673
|
-
visited.add(file);
|
|
10674
|
-
const content = fs31.readFileSync(file);
|
|
10675
|
-
result.push({
|
|
10676
|
-
path: path28.relative(projectRoot, file),
|
|
10677
|
-
sha256: crypto2.createHash("sha256").update(content).digest("hex")
|
|
10678
|
-
});
|
|
10679
|
-
if (SOURCE_EXTENSIONS.includes(path28.extname(file))) {
|
|
10680
|
-
const source = content.toString("utf8");
|
|
10681
|
-
for (const match of source.matchAll(
|
|
10682
|
-
/(?:from\s*|import\s*\(|require\s*\()\s*["']([^"']+)["']/g
|
|
10683
|
-
)) {
|
|
10684
|
-
const dependency = resolveRelativeConfig(match[1], file);
|
|
10685
|
-
if (dependency) pending.push(dependency);
|
|
10686
|
-
}
|
|
10687
|
-
} else if (path28.extname(file) === ".json") {
|
|
10688
|
-
try {
|
|
10689
|
-
const json = JSON.parse(content.toString("utf8"));
|
|
10690
|
-
for (const specifier of [
|
|
10691
|
-
json.extends,
|
|
10692
|
-
...(json.references ?? []).map((reference) => reference.path)
|
|
10693
|
-
]) {
|
|
10694
|
-
if (!specifier) continue;
|
|
10695
|
-
const dependency = resolveRelativeConfig(specifier, file);
|
|
10696
|
-
if (dependency) pending.push(dependency);
|
|
10697
|
-
}
|
|
10698
|
-
} catch {
|
|
10699
|
-
}
|
|
10700
|
-
}
|
|
10701
|
-
}
|
|
10702
|
-
return result.sort((left, right) => left.path.localeCompare(right.path));
|
|
10703
|
-
}
|
|
10704
|
-
function clientConfigEnvironment() {
|
|
10705
|
-
const names = [
|
|
10706
|
-
"APP_FLAGS",
|
|
10707
|
-
"ASSETS_CDN_PATH",
|
|
10708
|
-
"BUILD_TOOL",
|
|
10709
|
-
"CLIENT_BASE_PATH",
|
|
10710
|
-
"DISABLE_INSPECTOR",
|
|
10711
|
-
"FORCE_FRAMEWORK_BUILD_LOOSE_MODE",
|
|
10712
|
-
"FORCE_FRAMEWORK_DOMAIN_MAIN",
|
|
10713
|
-
"FORCE_FRAMEWORK_ENVIRONMENT",
|
|
10714
|
-
"MIAODA_APP_ARCH_TYPE",
|
|
10715
|
-
"MIAODA_APP_SOURCE",
|
|
10716
|
-
"MIAODA_APP_TYPE",
|
|
10717
|
-
"MIAODA_FONTS_MIRROR_OFF",
|
|
10718
|
-
"NEED_ROUTES",
|
|
10719
|
-
"STATIC_ASSETS_BASE_URL",
|
|
10720
|
-
"__API_ROUTE_DEFINITIONS__",
|
|
10721
|
-
"__PAGE_ROUTE_DEFINITIONS__"
|
|
10722
|
-
];
|
|
10723
|
-
return Object.fromEntries(
|
|
10724
|
-
names.map((name) => [
|
|
10725
|
-
name,
|
|
10726
|
-
crypto2.createHash("sha256").update(process.env[name] ?? "").digest("hex")
|
|
10727
|
-
])
|
|
10728
|
-
);
|
|
10729
|
-
}
|
|
10730
|
-
function installedDependencyLockFile(projectRoot) {
|
|
10731
|
-
const hiddenLock = path28.join(
|
|
10732
|
-
projectRoot,
|
|
10733
|
-
"node_modules",
|
|
10734
|
-
".package-lock.json"
|
|
10735
|
-
);
|
|
10736
|
-
if (fs31.existsSync(hiddenLock)) {
|
|
10737
|
-
if (fs31.lstatSync(hiddenLock).isSymbolicLink() || !fs31.statSync(hiddenLock).isFile()) {
|
|
10738
|
-
throw new Error("MIAODA_NPM_HIDDEN_PACKAGE_LOCK_INVALID");
|
|
10739
|
-
}
|
|
10740
|
-
return hiddenLock;
|
|
10741
|
-
}
|
|
10742
|
-
return path28.join(projectRoot, "package-lock.json");
|
|
10743
|
-
}
|
|
10744
|
-
function buildClientDependencyGraph(options) {
|
|
10745
|
-
const projectRoot = path28.resolve(options.projectRoot);
|
|
10746
|
-
const packageLockFile = installedDependencyLockFile(projectRoot);
|
|
10747
|
-
const lock = JSON.parse(
|
|
10748
|
-
fs31.readFileSync(packageLockFile, "utf8")
|
|
10749
|
-
);
|
|
10750
|
-
if (!lock.packages || (lock.lockfileVersion ?? 0) < 2) {
|
|
10751
|
-
throw new Error("MIAODA_NPM_PACKAGE_LOCK_V2_REQUIRED");
|
|
10752
|
-
}
|
|
10753
|
-
const discovery = discoverClientSpecifiers(
|
|
10754
|
-
projectRoot,
|
|
10755
|
-
options.includeAllProductionDependencies === true
|
|
10756
|
-
);
|
|
10757
|
-
if (options.includeAllProductionDependencies) {
|
|
10758
|
-
const packageJson = JSON.parse(
|
|
10759
|
-
fs31.readFileSync(path28.join(projectRoot, "package.json"), "utf8")
|
|
10760
|
-
);
|
|
10761
|
-
for (const specifier of Object.keys(packageJson.dependencies ?? {})) {
|
|
10762
|
-
if (!lock.packages[`node_modules/${specifier}`]?.version) continue;
|
|
10763
|
-
if (!discovery.specifiers.includes(specifier)) {
|
|
10764
|
-
discovery.specifiers.push(specifier);
|
|
10765
|
-
}
|
|
10766
|
-
}
|
|
10767
|
-
}
|
|
10768
|
-
const implicitSpecifiers = [
|
|
10769
|
-
"react",
|
|
10770
|
-
"react-dom",
|
|
10771
|
-
"react/jsx-runtime",
|
|
10772
|
-
"react/jsx-dev-runtime",
|
|
10773
|
-
"clsx",
|
|
10774
|
-
"echarts",
|
|
10775
|
-
"echarts-for-react",
|
|
10776
|
-
"@lark-apaas/client-toolkit/runtime",
|
|
10777
|
-
...process.env.DISABLE_INSPECTOR === "true" ? [] : ["@lark-apaas/miaoda-inspector"]
|
|
10778
|
-
];
|
|
10779
|
-
for (const specifier of implicitSpecifiers) {
|
|
10780
|
-
const packageName = packageNameFromSpecifier(specifier);
|
|
10781
|
-
if (lock.packages[`node_modules/${packageName}`]?.version && !discovery.specifiers.includes(specifier)) {
|
|
10782
|
-
discovery.specifiers.push(specifier);
|
|
10783
|
-
discovery.optimizeDependencies.push(specifier);
|
|
10784
|
-
}
|
|
10785
|
-
}
|
|
10786
|
-
discovery.specifiers.sort();
|
|
10787
|
-
discovery.optimizeDependencies.sort();
|
|
10788
|
-
const entries = discovery.specifiers.map((specifier) => {
|
|
10789
|
-
const packageName = packageNameFromSpecifier(specifier);
|
|
10790
|
-
const packagePath = resolveLockedPackagePath(
|
|
10791
|
-
lock.packages,
|
|
10792
|
-
"",
|
|
10793
|
-
packageName
|
|
10794
|
-
);
|
|
10795
|
-
if (!packagePath) {
|
|
10796
|
-
throw new Error(`MIAODA_CLIENT_DEPENDENCY_LOCK_MISSING: ${specifier}`);
|
|
10797
|
-
}
|
|
10798
|
-
return { specifier, packagePath };
|
|
10799
|
-
});
|
|
10800
|
-
const pending = [...new Set(entries.map((entry) => entry.packagePath))];
|
|
10801
|
-
const graphPackages = /* @__PURE__ */ new Map();
|
|
10802
|
-
while (pending.length > 0) {
|
|
10803
|
-
const packagePath = pending.pop();
|
|
10804
|
-
if (graphPackages.has(packagePath)) continue;
|
|
10805
|
-
const lockedPackage = lock.packages[packagePath];
|
|
10806
|
-
if (!lockedPackage?.version) {
|
|
10807
|
-
throw new Error(`MIAODA_CLIENT_DEPENDENCY_LOCK_MISSING: ${packagePath}`);
|
|
10808
|
-
}
|
|
10809
|
-
const edges = {};
|
|
10810
|
-
const addEdge = (name, required) => {
|
|
10811
|
-
const resolvedPath = resolveLockedPackagePath(
|
|
10812
|
-
lock.packages,
|
|
10813
|
-
packagePath,
|
|
10814
|
-
name
|
|
10815
|
-
);
|
|
10816
|
-
if (!resolvedPath) {
|
|
10817
|
-
if (required) {
|
|
10818
|
-
throw new Error(
|
|
10819
|
-
`MIAODA_CLIENT_DEPENDENCY_EDGE_MISSING: ${packagePath} -> ${name}`
|
|
10820
|
-
);
|
|
10821
|
-
}
|
|
10822
|
-
return;
|
|
10823
|
-
}
|
|
10824
|
-
edges[name] = resolvedPath;
|
|
10825
|
-
pending.push(resolvedPath);
|
|
10826
|
-
};
|
|
10827
|
-
for (const name of Object.keys(lockedPackage.dependencies ?? {}).sort()) {
|
|
10828
|
-
addEdge(name, true);
|
|
10829
|
-
}
|
|
10830
|
-
for (const name of Object.keys(
|
|
10831
|
-
lockedPackage.optionalDependencies ?? {}
|
|
10832
|
-
).sort()) {
|
|
10833
|
-
addEdge(name, false);
|
|
10834
|
-
}
|
|
10835
|
-
for (const name of Object.keys(
|
|
10836
|
-
lockedPackage.peerDependencies ?? {}
|
|
10837
|
-
).sort()) {
|
|
10838
|
-
addEdge(
|
|
10839
|
-
name,
|
|
10840
|
-
lockedPackage.peerDependenciesMeta?.[name]?.optional !== true
|
|
10841
|
-
);
|
|
10842
|
-
}
|
|
10843
|
-
graphPackages.set(packagePath, {
|
|
10844
|
-
path: packagePath,
|
|
10845
|
-
version: lockedPackage.version,
|
|
10846
|
-
integrity: lockedPackage.integrity ?? null,
|
|
10847
|
-
edges: Object.fromEntries(
|
|
10848
|
-
Object.entries(edges).sort(
|
|
10849
|
-
([left], [right]) => left.localeCompare(right)
|
|
10850
|
-
)
|
|
10851
|
-
)
|
|
10852
|
-
});
|
|
10853
|
-
}
|
|
10854
|
-
const graph = {
|
|
10855
|
-
schemaVersion: 1,
|
|
10856
|
-
algorithm: "npm-installed-client-closure-v2",
|
|
10857
|
-
runtimeAbiHash: options.runtimeAbiHash,
|
|
10858
|
-
resolveConditions: ["browser", "development", "module", "import"],
|
|
10859
|
-
configFiles: clientConfigFiles(projectRoot),
|
|
10860
|
-
configEnvironment: clientConfigEnvironment(),
|
|
10861
|
-
entries,
|
|
10862
|
-
packages: [...graphPackages.values()].sort(
|
|
10863
|
-
(left, right) => left.path.localeCompare(right.path)
|
|
10864
|
-
)
|
|
10865
|
-
};
|
|
10866
|
-
return {
|
|
10867
|
-
graph,
|
|
10868
|
-
hash: crypto2.createHash("sha256").update(canonicalize(graph)).digest("hex"),
|
|
10869
|
-
optimizeDependencies: discovery.optimizeDependencies
|
|
10870
|
-
};
|
|
10871
|
-
}
|
|
10872
|
-
|
|
10873
|
-
// src/commands/build/app-runtime-manifest.handler.ts
|
|
10874
|
-
var VITE_PRESETS = [
|
|
10875
|
-
"@lark-apaas/coding-preset-vite-react",
|
|
10876
|
-
"@lark-apaas/coding-vite-preset",
|
|
10877
|
-
"@lark-apaas/fullstack-vite-preset"
|
|
10878
|
-
];
|
|
10879
|
-
function detectApplicationRuntime(projectRoot, packageJson) {
|
|
10880
|
-
const features = packageJson?.mclaw?.features;
|
|
10881
|
-
const declaredPackages = {
|
|
10882
|
-
...packageJson?.dependencies ?? {},
|
|
10883
|
-
...packageJson?.devDependencies ?? {}
|
|
10884
|
-
};
|
|
10885
|
-
const usesCodingVitePreset = VITE_PRESETS.slice(0, 2).some(
|
|
10886
|
-
(name) => declaredPackages[name] !== void 0
|
|
10887
|
-
);
|
|
10888
|
-
const hasServerRuntime = packageJson?.scripts?.["dev:server"] !== void 0 || declaredPackages["@nestjs/core"] !== void 0 || fs32.existsSync(path29.join(projectRoot, "server", "main.ts")) || fs32.existsSync(path29.join(projectRoot, "server", "src", "main.ts"));
|
|
10889
|
-
const hasClientOnlyMetadata = Array.isArray(features) && features.includes("client") && !features.includes("server");
|
|
10890
|
-
const applicationKind = !hasServerRuntime && (hasClientOnlyMetadata || usesCodingVitePreset) ? "frontend-only" : "fullstack";
|
|
10891
|
-
const vitePreset = VITE_PRESETS.find((name) => declaredPackages[name] !== void 0) ?? "@lark-apaas/fullstack-vite-preset";
|
|
10892
|
-
const entryCandidates = [
|
|
10893
|
-
"client/src/index.tsx",
|
|
10894
|
-
"client/src/main.tsx",
|
|
10895
|
-
"src/index.tsx",
|
|
10896
|
-
"src/main.tsx"
|
|
10897
|
-
];
|
|
10898
|
-
const clientEntry = entryCandidates.find(
|
|
10899
|
-
(relativePath) => fs32.existsSync(path29.join(projectRoot, relativePath))
|
|
10900
|
-
);
|
|
10901
|
-
if (!clientEntry) {
|
|
10902
|
-
throw new Error("client entry missing");
|
|
10903
|
-
}
|
|
10904
|
-
return {
|
|
10905
|
-
applicationKind,
|
|
10906
|
-
vitePreset,
|
|
10907
|
-
clientRoot: clientEntry.startsWith("client/") ? "client" : ".",
|
|
10908
|
-
clientEntry
|
|
10909
|
-
};
|
|
10910
|
-
}
|
|
10911
|
-
function buildAppRuntimeManifest(options) {
|
|
10912
|
-
const projectRoot = path29.resolve(options.projectRoot);
|
|
10913
|
-
const outfile = path29.resolve(
|
|
10914
|
-
projectRoot,
|
|
10915
|
-
options.outfile ?? ".miaoda-cache/app-runtime.json"
|
|
10916
|
-
);
|
|
10917
|
-
const runtimeManifestFile = path29.isAbsolute(options.runtimeManifestFile) ? options.runtimeManifestFile : path29.resolve(projectRoot, options.runtimeManifestFile);
|
|
10918
|
-
const requiredFiles = [
|
|
10919
|
-
path29.join(projectRoot, "package.json"),
|
|
10920
|
-
path29.join(projectRoot, "package-lock.json"),
|
|
10921
|
-
runtimeManifestFile
|
|
10922
|
-
];
|
|
10923
|
-
fs32.rmSync(outfile, { force: true });
|
|
10924
|
-
const missing = requiredFiles.filter((file) => !fs32.existsSync(file));
|
|
10925
|
-
if (missing.length > 0) {
|
|
10926
|
-
return {
|
|
10927
|
-
built: false,
|
|
10928
|
-
reasons: missing.map((file) => `input missing: ${file}`)
|
|
10929
|
-
};
|
|
10930
|
-
}
|
|
10931
|
-
try {
|
|
10932
|
-
const packageJson = JSON.parse(
|
|
10933
|
-
fs32.readFileSync(path29.join(projectRoot, "package.json"), "utf8")
|
|
10934
|
-
);
|
|
10935
|
-
const runtime = JSON.parse(
|
|
10936
|
-
fs32.readFileSync(runtimeManifestFile, "utf8")
|
|
10937
|
-
);
|
|
10938
|
-
if (runtime.schemaVersion !== 1 || !runtime.runtimeAbiHash) {
|
|
10939
|
-
return {
|
|
10940
|
-
built: false,
|
|
10941
|
-
reasons: ["unsupported platform runtime manifest"]
|
|
10942
|
-
};
|
|
10943
|
-
}
|
|
10944
|
-
const applicationRuntime = detectApplicationRuntime(
|
|
10945
|
-
projectRoot,
|
|
10946
|
-
packageJson
|
|
10947
|
-
);
|
|
10948
|
-
const client = buildClientDependencyGraph({
|
|
10949
|
-
projectRoot,
|
|
10950
|
-
runtimeAbiHash: runtime.runtimeAbiHash,
|
|
10951
|
-
includeAllProductionDependencies: applicationRuntime.applicationKind === "frontend-only"
|
|
10952
|
-
});
|
|
10953
|
-
const manifest = {
|
|
10954
|
-
schemaVersion: 1,
|
|
10955
|
-
runtimeAbiHash: runtime.runtimeAbiHash,
|
|
10956
|
-
...applicationRuntime,
|
|
10957
|
-
clientDependencyGraphHash: client.hash,
|
|
10958
|
-
clientDependencyGraph: client.graph,
|
|
10959
|
-
optimizeDependencies: client.optimizeDependencies
|
|
10960
|
-
};
|
|
10961
|
-
fs32.mkdirSync(path29.dirname(outfile), { recursive: true });
|
|
10962
|
-
const temporaryFile = `${outfile}.${process.pid}.${Date.now()}.tmp`;
|
|
10963
|
-
fs32.writeFileSync(temporaryFile, `${JSON.stringify(manifest, null, 2)}
|
|
10964
|
-
`);
|
|
10965
|
-
fs32.renameSync(temporaryFile, outfile);
|
|
10966
|
-
return {
|
|
10967
|
-
built: true,
|
|
10968
|
-
outfile,
|
|
10969
|
-
runtimeAbiHash: runtime.runtimeAbiHash,
|
|
10970
|
-
...applicationRuntime,
|
|
10971
|
-
clientDependencyGraphHash: client.hash,
|
|
10972
|
-
clientDependencyGraph: client.graph,
|
|
10973
|
-
optimizeDependencies: client.optimizeDependencies,
|
|
10974
|
-
reasons: []
|
|
10975
|
-
};
|
|
10976
|
-
} catch (error) {
|
|
10977
|
-
fs32.rmSync(outfile, { force: true });
|
|
10978
|
-
return {
|
|
10979
|
-
built: false,
|
|
10980
|
-
reasons: [error instanceof Error ? error.message : String(error)]
|
|
10981
|
-
};
|
|
10982
|
-
}
|
|
10983
|
-
}
|
|
10984
|
-
|
|
10985
|
-
// src/commands/build/cache-generation.handler.ts
|
|
10986
|
-
import crypto3 from "crypto";
|
|
10987
|
-
import fs33 from "fs";
|
|
10988
|
-
import path30 from "path";
|
|
10989
|
-
function sha2562(file) {
|
|
10990
|
-
return crypto3.createHash("sha256").update(fs33.readFileSync(file)).digest("hex");
|
|
10991
|
-
}
|
|
10992
|
-
function listRegularFiles(root) {
|
|
10993
|
-
const files = [];
|
|
10994
|
-
const visit = (directory) => {
|
|
10995
|
-
for (const entry of fs33.readdirSync(directory, { withFileTypes: true })) {
|
|
10996
|
-
const file = path30.join(directory, entry.name);
|
|
10997
|
-
if (entry.isSymbolicLink()) {
|
|
10998
|
-
throw new Error(`vite cache symlink is not supported: ${file}`);
|
|
10999
|
-
}
|
|
11000
|
-
if (entry.isDirectory()) {
|
|
11001
|
-
visit(file);
|
|
11002
|
-
} else if (entry.isFile()) {
|
|
11003
|
-
files.push(file);
|
|
11004
|
-
}
|
|
11005
|
-
}
|
|
11006
|
-
};
|
|
11007
|
-
visit(root);
|
|
11008
|
-
return files.sort();
|
|
11009
|
-
}
|
|
11010
|
-
var WORKSPACE_SOURCE_ROOTS = ["client", "server", "shared", "src"];
|
|
11011
|
-
var WORKSPACE_SOURCE_FILES = [
|
|
11012
|
-
".env",
|
|
11013
|
-
".env.development",
|
|
11014
|
-
".env.development.local",
|
|
11015
|
-
"drizzle.config.ts",
|
|
11016
|
-
"nest-cli.json",
|
|
11017
|
-
"postcss.config.js",
|
|
11018
|
-
"postcss.config.cjs",
|
|
11019
|
-
"postcss.config.mjs",
|
|
11020
|
-
"tailwind.config.ts",
|
|
11021
|
-
"tailwind.config.js",
|
|
11022
|
-
"tailwind.config.cjs",
|
|
11023
|
-
"tailwind.config.mjs",
|
|
11024
|
-
"tsconfig.json",
|
|
11025
|
-
"tsconfig.app.json",
|
|
11026
|
-
"tsconfig.node.json",
|
|
11027
|
-
"vite.config.ts",
|
|
11028
|
-
"vite.config.mts",
|
|
11029
|
-
"vite.config.js",
|
|
11030
|
-
"vite.config.mjs",
|
|
11031
|
-
"vite.config.cjs"
|
|
11032
|
-
];
|
|
11033
|
-
function listWorkspaceSourceFiles(projectRoot) {
|
|
11034
|
-
const files = WORKSPACE_SOURCE_ROOTS.flatMap((relativeRoot) => {
|
|
11035
|
-
const root = path30.join(projectRoot, relativeRoot);
|
|
11036
|
-
return fs33.existsSync(root) ? listRegularFiles(root) : [];
|
|
11037
|
-
});
|
|
11038
|
-
for (const relativeFile of WORKSPACE_SOURCE_FILES) {
|
|
11039
|
-
const file = path30.join(projectRoot, relativeFile);
|
|
11040
|
-
if (!fs33.existsSync(file)) continue;
|
|
11041
|
-
if (fs33.lstatSync(file).isSymbolicLink() || !fs33.statSync(file).isFile()) {
|
|
11042
|
-
throw new Error(`workspace source file is invalid: ${file}`);
|
|
11043
|
-
}
|
|
11044
|
-
files.push(file);
|
|
11045
|
-
}
|
|
11046
|
-
return [...new Set(files)].sort().map((file) => ({
|
|
11047
|
-
path: path30.relative(projectRoot, file).split(path30.sep).join("/"),
|
|
11048
|
-
sha256: sha2562(file),
|
|
11049
|
-
size: fs33.statSync(file).size
|
|
11050
|
-
}));
|
|
11051
|
-
}
|
|
11052
|
-
function canonicalJson(value) {
|
|
11053
|
-
if (Array.isArray(value)) return value.map(canonicalJson);
|
|
11054
|
-
if (value && typeof value === "object") {
|
|
11055
|
-
return Object.fromEntries(
|
|
11056
|
-
Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, child]) => [key, canonicalJson(child)])
|
|
11057
|
-
);
|
|
11058
|
-
}
|
|
11059
|
-
return value;
|
|
11060
|
-
}
|
|
11061
|
-
function workspaceBuildInputs(projectRoot) {
|
|
11062
|
-
const packageJsonFile = path30.join(projectRoot, "package.json");
|
|
11063
|
-
const packageJson = fs33.existsSync(packageJsonFile) ? JSON.parse(fs33.readFileSync(packageJsonFile, "utf8")) : {};
|
|
11064
|
-
return {
|
|
11065
|
-
// Dependency versions deliberately remain governed by the recursive
|
|
11066
|
-
// client graph and bundled server artifact. Only package.json fields that
|
|
11067
|
-
// directly change bundle construction belong in this source binding.
|
|
11068
|
-
actionPlugins: canonicalJson(packageJson.actionPlugins ?? {})
|
|
11069
|
-
};
|
|
11070
|
-
}
|
|
11071
|
-
function packageNameFromOptimizerId(id) {
|
|
11072
|
-
const specifier = id.split(" > ").at(-1) ?? id;
|
|
11073
|
-
if (!specifier || specifier.startsWith(".") || specifier.startsWith("/") || specifier.startsWith("\0") || specifier.includes("://")) {
|
|
11074
|
-
return void 0;
|
|
11075
|
-
}
|
|
11076
|
-
const parts = specifier.split("/");
|
|
11077
|
-
return specifier.startsWith("@") ? parts.length >= 2 ? `${parts[0]}/${parts[1]}` : void 0 : parts[0];
|
|
11078
|
-
}
|
|
11079
|
-
function isPathInside3(root, candidate) {
|
|
11080
|
-
const relative = path30.relative(root, candidate);
|
|
11081
|
-
return relative === "" || !relative.startsWith("..") && !path30.isAbsolute(relative);
|
|
11082
|
-
}
|
|
11083
|
-
function isCanonicalRelativeAssetPath(candidate) {
|
|
11084
|
-
return typeof candidate === "string" && candidate.length > 0 && candidate === path30.posix.normalize(candidate) && candidate !== "." && !candidate.startsWith("../") && !path30.posix.isAbsolute(candidate) && !candidate.includes("\\");
|
|
11085
|
-
}
|
|
11086
|
-
function optimizerEntryUsesRuntimePackage(options) {
|
|
11087
|
-
const variants = options.runtime.packages?.[options.packageName];
|
|
11088
|
-
if (!Array.isArray(variants) || variants.length === 0) return false;
|
|
11089
|
-
if (typeof options.entry?.src !== "string" || !options.entry.src)
|
|
11090
|
-
return false;
|
|
11091
|
-
const source = path30.isAbsolute(options.entry.src) ? options.entry.src : path30.resolve(options.projectRoot, options.entry.src);
|
|
11092
|
-
if (!fs33.existsSync(source)) return false;
|
|
11093
|
-
const realSource = fs33.realpathSync(source);
|
|
11094
|
-
const runtimeRoot = path30.dirname(path30.resolve(options.runtimeManifestFile));
|
|
11095
|
-
return variants.some((variant) => {
|
|
11096
|
-
if (typeof variant.relativePath !== "string" || !variant.relativePath) {
|
|
11097
|
-
return false;
|
|
11098
|
-
}
|
|
11099
|
-
const packageRoot2 = path30.resolve(runtimeRoot, variant.relativePath);
|
|
11100
|
-
if (!isPathInside3(runtimeRoot, packageRoot2) || !fs33.existsSync(packageRoot2)) {
|
|
11101
|
-
return false;
|
|
11102
|
-
}
|
|
11103
|
-
return isPathInside3(fs33.realpathSync(packageRoot2), realSource);
|
|
11104
|
-
});
|
|
11105
|
-
}
|
|
11106
|
-
var REQUIRED_SERVER_PROBE_CHECKS = [
|
|
11107
|
-
"isolated-node-modules",
|
|
11108
|
-
"runtime-assets",
|
|
11109
|
-
"http-readiness",
|
|
11110
|
-
"business-api",
|
|
11111
|
-
"process-alive",
|
|
11112
|
-
"module-resolution"
|
|
11113
|
-
];
|
|
11114
|
-
function serverMetadataIsConsumable(serverMetadata) {
|
|
11115
|
-
const warningsAreValid = Array.isArray(serverMetadata?.dynamicImportWarnings) && serverMetadata.dynamicImportWarnings.every(
|
|
11116
|
-
(warning) => typeof warning?.kind === "string" && typeof warning?.source === "string" && /^[a-f0-9]{16}$/.test(warning?.expressionHash ?? "") && typeof warning?.message === "string"
|
|
11117
|
-
);
|
|
11118
|
-
const runtimeAssetWarningsAreValid = Array.isArray(serverMetadata?.runtimeAssetWarnings) && serverMetadata.runtimeAssetWarnings.every(
|
|
11119
|
-
(warning) => typeof warning?.kind === "string" && typeof warning?.source === "string" && /^[a-f0-9]{16}$/.test(warning?.expressionHash ?? "") && typeof warning?.message === "string"
|
|
11120
|
-
);
|
|
11121
|
-
const actionPluginsAreValid = Array.isArray(serverMetadata?.actionPlugins) && serverMetadata.actionPlugins.every(
|
|
11122
|
-
(plugin) => typeof plugin?.name === "string" && plugin.name.length > 0 && typeof plugin?.version === "string" && plugin.version.length > 0
|
|
11123
|
-
);
|
|
11124
|
-
const checks = serverMetadata?.availabilityProbe?.checks;
|
|
11125
|
-
const checkNames = Array.isArray(checks) ? checks.map((check2) => check2?.name) : [];
|
|
11126
|
-
const checksAreValid = Array.isArray(checks) && checks.every(
|
|
11127
|
-
(check2) => typeof check2?.name === "string" && check2?.success === true
|
|
11128
|
-
) && new Set(checkNames).size === checkNames.length && REQUIRED_SERVER_PROBE_CHECKS.every((name) => checkNames.includes(name)) && (serverMetadata.actionPlugins?.length === 0 || checkNames.includes("action-plugin-registry"));
|
|
11129
|
-
return serverMetadata?.schemaVersion === 2 && serverMetadata?.consumable === true && serverMetadata?.availabilityProbe?.success === true && serverMetadata?.availabilityProbe?.nodeModulesPresent === false && checksAreValid && warningsAreValid && runtimeAssetWarningsAreValid && actionPluginsAreValid && Array.isArray(serverMetadata?.runtimeAssets) && Array.isArray(serverMetadata?.externalImports) && serverMetadata.externalImports.length === 0;
|
|
11130
|
-
}
|
|
11131
|
-
function stableServerMetadataIdentity(serverMetadata) {
|
|
11132
|
-
const availabilityProbe = serverMetadata?.availabilityProbe ?? {};
|
|
11133
|
-
const checks = Array.isArray(availabilityProbe.checks) ? availabilityProbe.checks.map((check2) => {
|
|
11134
|
-
const { elapsedMs: _elapsedMs, ...stableCheck } = check2;
|
|
11135
|
-
return stableCheck;
|
|
11136
|
-
}) : availabilityProbe.checks;
|
|
11137
|
-
const {
|
|
11138
|
-
startupMs: _startupMs,
|
|
11139
|
-
stdout: _stdout,
|
|
11140
|
-
stderr: _stderr,
|
|
11141
|
-
...stableProbe
|
|
11142
|
-
} = availabilityProbe;
|
|
11143
|
-
return canonicalJson({
|
|
11144
|
-
...serverMetadata,
|
|
11145
|
-
availabilityProbe: { ...stableProbe, checks }
|
|
11146
|
-
});
|
|
11147
|
-
}
|
|
11148
|
-
function serverDependenciesAreConsumable(serverDependencies) {
|
|
11149
|
-
if (serverDependencies?.schemaVersion !== 1 || typeof serverDependencies?.sourceEntry !== "string" || serverDependencies.sourceEntry.length === 0 || typeof serverDependencies?.compiledEntry !== "string" || serverDependencies.compiledEntry.length === 0 || !Array.isArray(serverDependencies?.bootstrapModules) || serverDependencies.bootstrapModules.length === 0 || !Array.isArray(serverDependencies?.packages) || serverDependencies.packages.length === 0 || !Array.isArray(serverDependencies?.actionPlugins) || !Array.isArray(serverDependencies?.files) || serverDependencies.files.length === 0 || !/^[a-f0-9]{64}$/.test(serverDependencies?.treeSha256 ?? "") || serverDependencies.fileCount !== serverDependencies.files.length || !Number.isSafeInteger(serverDependencies.totalBytes) || serverDependencies.totalBytes <= 0) {
|
|
11150
|
-
return false;
|
|
11151
|
-
}
|
|
11152
|
-
const packageRecordsAreValid = (packages) => packages.every(
|
|
11153
|
-
(pkg2) => typeof pkg2?.name === "string" && pkg2.name.length > 0 && typeof pkg2?.version === "string" && pkg2.version.length > 0
|
|
11154
|
-
);
|
|
11155
|
-
const paths = /* @__PURE__ */ new Set();
|
|
11156
|
-
const filesAreValid = serverDependencies.files.every((file) => {
|
|
11157
|
-
if (!isCanonicalRelativeAssetPath(file?.path) || !/^[a-f0-9]{64}$/.test(file?.sha256 ?? "") || !Number.isSafeInteger(file?.size) || file.size < 0 || paths.has(file.path)) {
|
|
11158
|
-
return false;
|
|
11159
|
-
}
|
|
11160
|
-
paths.add(file.path);
|
|
11161
|
-
return true;
|
|
11162
|
-
});
|
|
11163
|
-
const expectedTreeSha256 = crypto3.createHash("sha256").update(JSON.stringify(serverDependencies.files)).digest("hex");
|
|
11164
|
-
return packageRecordsAreValid(serverDependencies.packages) && packageRecordsAreValid(serverDependencies.actionPlugins) && filesAreValid && expectedTreeSha256 === serverDependencies.treeSha256 && serverDependencies.files.reduce(
|
|
11165
|
-
(total, file) => total + file.size,
|
|
11166
|
-
0
|
|
11167
|
-
) === serverDependencies.totalBytes;
|
|
11168
|
-
}
|
|
11169
|
-
function sealCacheGeneration(options) {
|
|
11170
|
-
const projectRoot = path30.resolve(options.projectRoot);
|
|
11171
|
-
const cacheRoot = path30.resolve(
|
|
11172
|
-
projectRoot,
|
|
11173
|
-
options.cacheRoot ?? ".miaoda-cache"
|
|
11174
|
-
);
|
|
11175
|
-
const outfile = path30.resolve(
|
|
11176
|
-
projectRoot,
|
|
11177
|
-
options.outfile ?? path30.join(cacheRoot, "generation.json")
|
|
11178
|
-
);
|
|
11179
|
-
const runtimeManifestFile = path30.isAbsolute(options.runtimeManifestFile) ? options.runtimeManifestFile : path30.resolve(projectRoot, options.runtimeManifestFile);
|
|
11180
|
-
const files = {
|
|
11181
|
-
serverBundle: path30.join(cacheRoot, "server", "server.bundle.cjs"),
|
|
11182
|
-
serverMetadata: path30.join(
|
|
11183
|
-
cacheRoot,
|
|
11184
|
-
"server",
|
|
11185
|
-
"server.bundle.cjs.meta.json"
|
|
11186
|
-
),
|
|
11187
|
-
serverDependencies: path30.join(
|
|
11188
|
-
cacheRoot,
|
|
11189
|
-
"server",
|
|
11190
|
-
"dependencies.json"
|
|
11191
|
-
),
|
|
11192
|
-
appRuntime: path30.join(cacheRoot, "app-runtime.json"),
|
|
11193
|
-
viteMetadata: path30.join(cacheRoot, "vite", "deps", "_metadata.json")
|
|
11194
|
-
};
|
|
11195
|
-
const viteRoot = path30.join(cacheRoot, "vite");
|
|
11196
|
-
fs33.rmSync(outfile, { force: true });
|
|
11197
|
-
const baseInputs = [
|
|
11198
|
-
runtimeManifestFile,
|
|
11199
|
-
files.appRuntime,
|
|
11200
|
-
files.viteMetadata
|
|
11201
|
-
];
|
|
11202
|
-
const missingBaseInputs = baseInputs.filter((file) => !fs33.existsSync(file));
|
|
11203
|
-
if (missingBaseInputs.length > 0) {
|
|
11204
|
-
return {
|
|
11205
|
-
sealed: false,
|
|
11206
|
-
reasons: missingBaseInputs.map(
|
|
11207
|
-
(file) => `cache generation input missing: ${file}`
|
|
11208
|
-
)
|
|
11209
|
-
};
|
|
11210
|
-
}
|
|
11211
|
-
let applicationKind;
|
|
11212
|
-
try {
|
|
11213
|
-
const appRuntime = JSON.parse(fs33.readFileSync(files.appRuntime, "utf8"));
|
|
11214
|
-
applicationKind = appRuntime.applicationKind === "frontend-only" ? "frontend-only" : "fullstack";
|
|
11215
|
-
} catch (error) {
|
|
11216
|
-
return {
|
|
11217
|
-
sealed: false,
|
|
11218
|
-
reasons: [error instanceof Error ? error.message : String(error)]
|
|
11219
|
-
};
|
|
11220
|
-
}
|
|
11221
|
-
const hasServerDependencies = fs33.existsSync(files.serverDependencies);
|
|
11222
|
-
const serverFiles = hasServerDependencies ? [files.serverDependencies, path30.join(cacheRoot, "server", "node_modules")] : [files.serverBundle, files.serverMetadata];
|
|
11223
|
-
const missing = (applicationKind === "fullstack" ? serverFiles : []).filter(
|
|
11224
|
-
(file) => !fs33.existsSync(file)
|
|
11225
|
-
);
|
|
11226
|
-
if (missing.length > 0) {
|
|
11227
|
-
return {
|
|
11228
|
-
sealed: false,
|
|
11229
|
-
reasons: missing.map((file) => `cache generation input missing: ${file}`)
|
|
11230
|
-
};
|
|
11231
|
-
}
|
|
11232
|
-
try {
|
|
11233
|
-
const runtime = JSON.parse(fs33.readFileSync(runtimeManifestFile, "utf8"));
|
|
11234
|
-
const appRuntime = JSON.parse(fs33.readFileSync(files.appRuntime, "utf8"));
|
|
11235
|
-
const viteMetadata = JSON.parse(
|
|
11236
|
-
fs33.readFileSync(files.viteMetadata, "utf8")
|
|
11237
|
-
);
|
|
11238
|
-
const serverMetadata = applicationKind === "fullstack" && !hasServerDependencies ? JSON.parse(fs33.readFileSync(files.serverMetadata, "utf8")) : void 0;
|
|
11239
|
-
const serverDependencies = applicationKind === "fullstack" && hasServerDependencies ? JSON.parse(fs33.readFileSync(files.serverDependencies, "utf8")) : void 0;
|
|
11240
|
-
const reasons = [];
|
|
11241
|
-
const serverRuntimeAssetFiles = [];
|
|
11242
|
-
if (runtime.schemaVersion !== 1 || !runtime.runtimeAbiHash) {
|
|
11243
|
-
reasons.push("unsupported platform runtime manifest");
|
|
11244
|
-
}
|
|
11245
|
-
if (appRuntime.schemaVersion !== 1 || appRuntime.runtimeAbiHash !== runtime.runtimeAbiHash) {
|
|
11246
|
-
reasons.push("application/runtime ABI mismatch");
|
|
11247
|
-
}
|
|
11248
|
-
if (!/^[a-f0-9]{64}$/.test(appRuntime.clientDependencyGraphHash ?? "") || appRuntime.clientDependencyGraph?.schemaVersion !== 1 || appRuntime.clientDependencyGraph?.runtimeAbiHash !== runtime.runtimeAbiHash) {
|
|
11249
|
-
reasons.push("application client dependency graph is invalid");
|
|
11250
|
-
}
|
|
11251
|
-
if (applicationKind === "fullstack" && hasServerDependencies && !serverDependenciesAreConsumable(serverDependencies)) {
|
|
11252
|
-
reasons.push("server runtime dependency metadata is not consumable");
|
|
11253
|
-
}
|
|
11254
|
-
if (applicationKind === "fullstack" && !hasServerDependencies && !serverMetadataIsConsumable(serverMetadata)) {
|
|
11255
|
-
reasons.push("server cache metadata is not consumable");
|
|
11256
|
-
}
|
|
11257
|
-
if (applicationKind === "fullstack" && !hasServerDependencies && sha2562(files.serverBundle) !== serverMetadata.bundleSha256) {
|
|
11258
|
-
reasons.push("server bundle SHA-256 mismatch");
|
|
11259
|
-
}
|
|
11260
|
-
if (applicationKind === "fullstack" && !hasServerDependencies && !Array.isArray(serverMetadata.runtimeAssets)) {
|
|
11261
|
-
reasons.push("server runtime asset manifest is missing");
|
|
11262
|
-
} else if (applicationKind === "fullstack" && !hasServerDependencies) {
|
|
11263
|
-
const runtimeAssetPaths = /* @__PURE__ */ new Set();
|
|
11264
|
-
for (const asset of serverMetadata.runtimeAssets) {
|
|
11265
|
-
if (!isCanonicalRelativeAssetPath(asset?.path)) {
|
|
11266
|
-
reasons.push(`server runtime asset path is invalid: ${asset?.path}`);
|
|
11267
|
-
continue;
|
|
11268
|
-
}
|
|
11269
|
-
if (runtimeAssetPaths.has(asset.path)) {
|
|
11270
|
-
reasons.push(
|
|
11271
|
-
`server runtime asset path is duplicated: ${asset.path}`
|
|
11272
|
-
);
|
|
11273
|
-
continue;
|
|
11274
|
-
}
|
|
11275
|
-
runtimeAssetPaths.add(asset.path);
|
|
11276
|
-
const file = path30.join(cacheRoot, "server", ...asset.path.split("/"));
|
|
11277
|
-
if (!fs33.existsSync(file) || !fs33.statSync(file).isFile()) {
|
|
11278
|
-
reasons.push(`server runtime asset is missing: ${asset.path}`);
|
|
11279
|
-
continue;
|
|
11280
|
-
}
|
|
11281
|
-
const actualSha256 = sha2562(file);
|
|
11282
|
-
const actualSize = fs33.statSync(file).size;
|
|
11283
|
-
if (asset.sha256 !== actualSha256 || asset.size !== actualSize) {
|
|
11284
|
-
reasons.push(
|
|
11285
|
-
`server runtime asset integrity mismatch: ${asset.path}`
|
|
11286
|
-
);
|
|
11287
|
-
continue;
|
|
11288
|
-
}
|
|
11289
|
-
serverRuntimeAssetFiles.push({
|
|
11290
|
-
key: `serverRuntimeAsset:${asset.path}`,
|
|
11291
|
-
file,
|
|
11292
|
-
path: asset.path
|
|
11293
|
-
});
|
|
11294
|
-
}
|
|
11295
|
-
}
|
|
11296
|
-
if (applicationKind === "fullstack" && hasServerDependencies) {
|
|
11297
|
-
const nodeModulesRoot = path30.join(cacheRoot, "server", "node_modules");
|
|
11298
|
-
const actualFiles = listRegularFiles(nodeModulesRoot).map((file) => ({
|
|
11299
|
-
path: path30.relative(nodeModulesRoot, file).split(path30.sep).join("/"),
|
|
11300
|
-
sha256: sha2562(file),
|
|
11301
|
-
size: fs33.statSync(file).size
|
|
11302
|
-
})).sort((left, right) => left.path.localeCompare(right.path));
|
|
11303
|
-
if (JSON.stringify(actualFiles) !== JSON.stringify(serverDependencies.files)) {
|
|
11304
|
-
reasons.push("server runtime dependency file set or integrity mismatch");
|
|
11305
|
-
}
|
|
11306
|
-
const currentActionPlugins = workspaceBuildInputs(projectRoot).actionPlugins;
|
|
11307
|
-
const cachedActionPlugins = Object.fromEntries(
|
|
11308
|
-
serverDependencies.actionPlugins.map(
|
|
11309
|
-
(plugin) => [
|
|
11310
|
-
plugin.name,
|
|
11311
|
-
plugin.version
|
|
11312
|
-
]
|
|
11313
|
-
)
|
|
11314
|
-
);
|
|
11315
|
-
if (JSON.stringify(currentActionPlugins) !== JSON.stringify(canonicalJson(cachedActionPlugins))) {
|
|
11316
|
-
reasons.push("server runtime ActionPlugin dependency mismatch");
|
|
11317
|
-
}
|
|
11318
|
-
}
|
|
11319
|
-
const optimizedDependencies = new Set(
|
|
11320
|
-
Object.keys(viteMetadata.optimized ?? {})
|
|
11321
|
-
);
|
|
11322
|
-
const missingViteDependencies = Array.from(
|
|
11323
|
-
new Set(appRuntime.optimizeDependencies ?? [])
|
|
11324
|
-
).filter((specifier) => !optimizedDependencies.has(specifier));
|
|
11325
|
-
if (missingViteDependencies.length > 0) {
|
|
11326
|
-
reasons.push(
|
|
11327
|
-
`vite cache dependency coverage missing: ${missingViteDependencies.join(", ")}`
|
|
11328
|
-
);
|
|
11329
|
-
}
|
|
11330
|
-
const graphPackageNames = new Set(
|
|
11331
|
-
(appRuntime.clientDependencyGraph?.entries ?? []).map(
|
|
11332
|
-
(entry) => packageNameFromOptimizerId(entry.specifier ?? "")
|
|
11333
|
-
).filter(Boolean)
|
|
11334
|
-
);
|
|
11335
|
-
const optimizerEntries = [
|
|
11336
|
-
...Object.entries(viteMetadata.optimized ?? {}),
|
|
11337
|
-
...Object.entries(viteMetadata.discovered ?? {})
|
|
11338
|
-
];
|
|
11339
|
-
const uncoveredOptimizerPackages = Array.from(
|
|
11340
|
-
new Set(
|
|
11341
|
-
optimizerEntries.flatMap(([id, entry]) => {
|
|
11342
|
-
const name = packageNameFromOptimizerId(id);
|
|
11343
|
-
if (!name || graphPackageNames.has(name)) return [];
|
|
11344
|
-
return optimizerEntryUsesRuntimePackage({
|
|
11345
|
-
projectRoot,
|
|
11346
|
-
runtimeManifestFile,
|
|
11347
|
-
runtime,
|
|
11348
|
-
packageName: name,
|
|
11349
|
-
entry
|
|
11350
|
-
}) ? [] : [name];
|
|
11351
|
-
})
|
|
11352
|
-
)
|
|
11353
|
-
).sort();
|
|
11354
|
-
if (uncoveredOptimizerPackages.length > 0) {
|
|
11355
|
-
reasons.push(
|
|
11356
|
-
`vite optimizer graph/toolchain coverage missing: ${uncoveredOptimizerPackages.join(", ")}`
|
|
11357
|
-
);
|
|
11358
|
-
}
|
|
11359
|
-
if (reasons.length > 0) return { sealed: false, reasons };
|
|
11360
|
-
const artifactFiles = {
|
|
11361
|
-
appRuntime: files.appRuntime,
|
|
11362
|
-
viteMetadata: files.viteMetadata,
|
|
11363
|
-
...applicationKind === "fullstack" ? hasServerDependencies ? { serverDependencies: files.serverDependencies } : {
|
|
11364
|
-
serverBundle: files.serverBundle,
|
|
11365
|
-
serverMetadata: files.serverMetadata
|
|
11366
|
-
} : {}
|
|
11367
|
-
};
|
|
11368
|
-
const artifacts = Object.fromEntries([
|
|
11369
|
-
...Object.entries(artifactFiles).map(([name, file]) => [
|
|
11370
|
-
name,
|
|
11371
|
-
{
|
|
11372
|
-
path: path30.relative(cacheRoot, file),
|
|
11373
|
-
sha256: sha2562(file),
|
|
11374
|
-
size: fs33.statSync(file).size
|
|
11375
|
-
}
|
|
11376
|
-
]),
|
|
11377
|
-
...serverRuntimeAssetFiles.map((asset) => [
|
|
11378
|
-
asset.key,
|
|
11379
|
-
{
|
|
11380
|
-
path: path30.posix.join("server", asset.path),
|
|
11381
|
-
sha256: sha2562(asset.file),
|
|
11382
|
-
size: fs33.statSync(asset.file).size
|
|
11383
|
-
}
|
|
11384
|
-
])
|
|
11385
|
-
]);
|
|
11386
|
-
const viteFiles = listRegularFiles(viteRoot).map((file) => ({
|
|
11387
|
-
path: path30.relative(cacheRoot, file),
|
|
11388
|
-
sha256: sha2562(file),
|
|
11389
|
-
size: fs33.statSync(file).size
|
|
11390
|
-
}));
|
|
11391
|
-
if (viteFiles.length === 0) {
|
|
11392
|
-
return { sealed: false, reasons: ["vite cache is empty"] };
|
|
11393
|
-
}
|
|
11394
|
-
const stableMetadata = applicationKind === "fullstack" && !hasServerDependencies ? JSON.stringify(stableServerMetadataIdentity(serverMetadata)) : void 0;
|
|
11395
|
-
const serverMetadataIdentity = stableMetadata ? {
|
|
11396
|
-
sha256: crypto3.createHash("sha256").update(stableMetadata).digest("hex"),
|
|
11397
|
-
size: Buffer.byteLength(stableMetadata)
|
|
11398
|
-
} : void 0;
|
|
11399
|
-
const serverDependencyFiles = applicationKind === "fullstack" && hasServerDependencies ? listRegularFiles(path30.join(cacheRoot, "server")).map((file) => ({
|
|
11400
|
-
path: path30.relative(cacheRoot, file).split(path30.sep).join("/"),
|
|
11401
|
-
sha256: sha2562(file),
|
|
11402
|
-
size: fs33.statSync(file).size
|
|
11403
|
-
})) : void 0;
|
|
11404
|
-
const identity = {
|
|
11405
|
-
schemaVersion: hasServerDependencies ? 4 : 3,
|
|
11406
|
-
runtimeAbiHash: runtime.runtimeAbiHash,
|
|
11407
|
-
applicationKind,
|
|
11408
|
-
...applicationKind === "fullstack" ? {
|
|
11409
|
-
serverRuntime: {
|
|
11410
|
-
nodeVersion: (serverDependencies ?? serverMetadata).nodeVersion,
|
|
11411
|
-
nodeModuleAbi: (serverDependencies ?? serverMetadata).nodeModuleAbi,
|
|
11412
|
-
platform: (serverDependencies ?? serverMetadata).platform,
|
|
11413
|
-
arch: (serverDependencies ?? serverMetadata).arch
|
|
11414
|
-
},
|
|
11415
|
-
...hasServerDependencies ? {
|
|
11416
|
-
serverRuntimeMode: "workspace-source-dependencies",
|
|
11417
|
-
serverFiles: serverDependencyFiles
|
|
11418
|
-
} : {}
|
|
11419
|
-
} : {},
|
|
11420
|
-
artifacts,
|
|
11421
|
-
...serverMetadataIdentity ? { serverMetadataIdentity } : {},
|
|
11422
|
-
viteFiles,
|
|
11423
|
-
...hasServerDependencies ? {} : { sourceFiles: listWorkspaceSourceFiles(projectRoot) },
|
|
11424
|
-
workspaceBuildInputs: workspaceBuildInputs(projectRoot)
|
|
11425
|
-
};
|
|
11426
|
-
const generationIdentity = serverMetadataIdentity ? {
|
|
11427
|
-
...identity,
|
|
11428
|
-
artifacts: {
|
|
11429
|
-
...identity.artifacts,
|
|
11430
|
-
serverMetadata: {
|
|
11431
|
-
...identity.artifacts.serverMetadata,
|
|
11432
|
-
...serverMetadataIdentity
|
|
11433
|
-
}
|
|
11434
|
-
}
|
|
11435
|
-
} : identity;
|
|
11436
|
-
const generationId = crypto3.createHash("sha256").update(JSON.stringify(generationIdentity)).digest("hex");
|
|
11437
|
-
fs33.mkdirSync(path30.dirname(outfile), { recursive: true });
|
|
11438
|
-
const tempFile = `${outfile}.${process.pid}.${Date.now()}.tmp`;
|
|
11439
|
-
fs33.writeFileSync(
|
|
11440
|
-
tempFile,
|
|
11441
|
-
`${JSON.stringify({ ...identity, generationId }, null, 2)}
|
|
11442
|
-
`
|
|
11443
|
-
);
|
|
11444
|
-
fs33.renameSync(tempFile, outfile);
|
|
11445
|
-
return { sealed: true, outfile, generationId, reasons: [] };
|
|
11446
|
-
} catch (error) {
|
|
11447
|
-
fs33.rmSync(outfile, { force: true });
|
|
11448
|
-
return {
|
|
11449
|
-
sealed: false,
|
|
11450
|
-
reasons: [error instanceof Error ? error.message : String(error)]
|
|
11451
|
-
};
|
|
11452
|
-
}
|
|
11453
|
-
}
|
|
11454
|
-
|
|
11455
|
-
// src/commands/build/index.ts
|
|
11456
|
-
var getTokenCommand = {
|
|
11457
|
-
name: "get-token",
|
|
11458
|
-
description: "Get artifact upload credential (STI token)",
|
|
11459
|
-
register(program) {
|
|
11460
|
-
program.command(this.name).description(this.description).requiredOption("--app-id <id>", "Application ID").requiredOption("--scene <scene>", "Build scene (pipeline, static)").option("--commit-id <id>", "Git commit ID (required for pipeline scene)").action(
|
|
11461
|
-
async (options) => {
|
|
11462
|
-
await getToken(options);
|
|
11463
|
-
}
|
|
11464
|
-
);
|
|
11465
|
-
}
|
|
11466
|
-
};
|
|
11467
|
-
var uploadStaticCommand = {
|
|
11468
|
-
name: "upload-static",
|
|
11469
|
-
description: "Upload shared/static files to TOS",
|
|
11470
|
-
register(program) {
|
|
11471
|
-
program.command(this.name).description(this.description).requiredOption("--app-id <id>", "Application ID").option(
|
|
11472
|
-
"--static-dir <dir>",
|
|
11473
|
-
"Static files directory",
|
|
11474
|
-
UPLOAD_STATIC_DEFAULTS.staticDir
|
|
11475
|
-
).option(
|
|
11476
|
-
"--tosutil-path <path>",
|
|
11477
|
-
"Path to tosutil binary",
|
|
11478
|
-
UPLOAD_STATIC_DEFAULTS.tosutilPath
|
|
11479
|
-
).option(
|
|
11480
|
-
"--endpoint <endpoint>",
|
|
11481
|
-
"TOS endpoint",
|
|
11482
|
-
UPLOAD_STATIC_DEFAULTS.endpoint
|
|
11483
|
-
).option("--region <region>", "TOS region", UPLOAD_STATIC_DEFAULTS.region).action(async (options) => {
|
|
11484
|
-
await uploadStatic(options);
|
|
11485
|
-
});
|
|
11486
|
-
}
|
|
11487
|
-
};
|
|
11488
|
-
var preUploadStaticCommand = {
|
|
11489
|
-
name: "pre-upload-static",
|
|
11490
|
-
description: "Get TOS upload info and output as env vars for build.sh eval",
|
|
11491
|
-
register(program) {
|
|
11492
|
-
program.command(this.name).description(this.description).requiredOption("--app-id <id>", "Application ID").action(async (options) => {
|
|
11493
|
-
await preUploadStatic(options);
|
|
11494
|
-
});
|
|
11495
|
-
}
|
|
11496
|
-
};
|
|
11497
|
-
var serverCacheBundleCommand = {
|
|
11498
|
-
name: "server-cache-bundle",
|
|
11499
|
-
description: "Build and probe a node_modules-free single-file NestJS cache bundle",
|
|
11500
|
-
register(program) {
|
|
11501
|
-
program.command(this.name).description(this.description).option("--project-root <dir>", "Application project root", process.cwd()).option(
|
|
11502
|
-
"--entry <file>",
|
|
11503
|
-
"Compiled Nest entry (auto-detects dist/server/main.js or dist/main.js)"
|
|
11504
|
-
).option(
|
|
11505
|
-
"--outfile <file>",
|
|
11506
|
-
"Output bundle",
|
|
11507
|
-
".miaoda-cache/server/server.bundle.cjs"
|
|
11508
|
-
).option("--metadata-file <file>", "Output metadata file").action(
|
|
11509
|
-
async (options) => {
|
|
11510
|
-
const result = await buildServerCacheBundle(options);
|
|
11511
|
-
console.log(JSON.stringify(result));
|
|
11512
|
-
if (!result.built) process.exitCode = 2;
|
|
11513
|
-
}
|
|
11514
|
-
);
|
|
11515
|
-
}
|
|
11516
|
-
};
|
|
11517
|
-
var serverRuntimeDependenciesCommand = {
|
|
11518
|
-
name: "server-runtime-dependencies",
|
|
11519
|
-
description: "Build the automatically traced npm dependency cache used by transition Nest",
|
|
11520
|
-
register(program) {
|
|
11521
|
-
program.command(this.name).description(this.description).option("--project-root <dir>", "Application project root", process.cwd()).option(
|
|
11522
|
-
"--entry <file>",
|
|
11523
|
-
"Compiled Nest entry (auto-detects dist/server/main.js or dist/main.js)"
|
|
11524
|
-
).option(
|
|
11525
|
-
"--source-entry <file>",
|
|
11526
|
-
"Workspace Nest source entry (auto-detects server/main.ts or src/main.ts)"
|
|
11527
|
-
).option(
|
|
11528
|
-
"--outdir <dir>",
|
|
11529
|
-
"Output node_modules directory",
|
|
11530
|
-
".miaoda-cache/server/node_modules"
|
|
11531
|
-
).option("--metadata-file <file>", "Output dependency metadata file").action(
|
|
11532
|
-
async (options) => {
|
|
11533
|
-
const result = await buildServerRuntimeDependencies(options);
|
|
11534
|
-
console.log(JSON.stringify(result));
|
|
11535
|
-
if (!result.built) process.exitCode = 2;
|
|
11536
|
-
}
|
|
11537
|
-
);
|
|
11538
|
-
}
|
|
11539
|
-
};
|
|
11540
|
-
var appRuntimeManifestCommand = {
|
|
11541
|
-
name: "app-runtime-manifest",
|
|
11542
|
-
description: "Freeze the browser dependency closure used by cache-only Vite",
|
|
11543
|
-
register(program) {
|
|
11544
|
-
program.command(this.name).description(this.description).option("--project-root <dir>", "Application project root", process.cwd()).requiredOption(
|
|
11545
|
-
"--runtime-manifest-file <file>",
|
|
11546
|
-
"Image platform runtime manifest"
|
|
11547
|
-
).option("--outfile <file>", "Application runtime manifest output").action(
|
|
11548
|
-
(options) => {
|
|
11549
|
-
const result = buildAppRuntimeManifest(options);
|
|
11550
|
-
console.log(JSON.stringify(result));
|
|
11551
|
-
if (!result.built) process.exitCode = 2;
|
|
11552
|
-
}
|
|
11553
|
-
);
|
|
11554
|
-
}
|
|
11555
|
-
};
|
|
11556
|
-
var cacheGenerationCommand = {
|
|
11557
|
-
name: "cache-generation",
|
|
11558
|
-
description: "Seal Vite, Nest and runtime manifests into one immutable cache generation",
|
|
11559
|
-
register(program) {
|
|
11560
|
-
program.command(this.name).description(this.description).option("--project-root <dir>", "Application project root", process.cwd()).requiredOption(
|
|
11561
|
-
"--runtime-manifest-file <file>",
|
|
11562
|
-
"Image platform runtime manifest"
|
|
11563
|
-
).option("--cache-root <dir>", "Cache root", ".miaoda-cache").option("--outfile <file>", "Generation manifest output").action(
|
|
11564
|
-
(options) => {
|
|
11565
|
-
const result = sealCacheGeneration(options);
|
|
11566
|
-
console.log(JSON.stringify(result));
|
|
11567
|
-
if (!result.sealed) process.exitCode = 2;
|
|
11568
|
-
}
|
|
11569
|
-
);
|
|
11570
|
-
}
|
|
11571
|
-
};
|
|
11572
|
-
var buildCommandGroup = {
|
|
11573
|
-
name: "build",
|
|
11574
|
-
description: "Build related commands",
|
|
11575
|
-
commands: [
|
|
11576
|
-
getTokenCommand,
|
|
11577
|
-
uploadStaticCommand,
|
|
11578
|
-
preUploadStaticCommand,
|
|
11579
|
-
serverCacheBundleCommand,
|
|
11580
|
-
serverRuntimeDependenciesCommand,
|
|
11581
|
-
appRuntimeManifestCommand,
|
|
11582
|
-
cacheGenerationCommand
|
|
11583
|
-
]
|
|
11584
|
-
};
|
|
11585
|
-
|
|
11586
|
-
// src/commands/index.ts
|
|
11587
|
-
var commands = [
|
|
11588
|
-
genDbSchemaCommand,
|
|
11589
|
-
syncCommand,
|
|
11590
|
-
upgradeCommand,
|
|
11591
|
-
actionPluginCommandGroup,
|
|
11592
|
-
capabilityCommandGroup,
|
|
11593
|
-
componentCommandGroup,
|
|
11594
|
-
migrationCommand,
|
|
11595
|
-
readLogsCommand,
|
|
11596
|
-
buildCommandGroup
|
|
11597
|
-
];
|
|
11598
|
-
|
|
11599
|
-
// src/utils/workspace-env.ts
|
|
11600
|
-
import fs34 from "fs";
|
|
11601
|
-
import path31 from "path";
|
|
11602
|
-
import { config as dotenvConfig } from "dotenv";
|
|
11603
|
-
function loadWorkspaceEnv(cwd = process.cwd(), targetEnv = process.env) {
|
|
11604
|
-
if (targetEnv.FULLSTACK_CLI_SKIP_DOTENV === "1") {
|
|
11605
|
-
return;
|
|
11606
|
-
}
|
|
11607
|
-
for (const filename of [".env.local", ".env"]) {
|
|
11608
|
-
const envPath = path31.join(cwd, filename);
|
|
11609
|
-
if (fs34.existsSync(envPath)) {
|
|
11610
|
-
dotenvConfig({ path: envPath, processEnv: targetEnv });
|
|
11611
|
-
}
|
|
11612
|
-
}
|
|
11613
|
-
}
|
|
11614
|
-
|
|
11615
|
-
// src/index.ts
|
|
11616
|
-
loadWorkspaceEnv();
|
|
11617
|
-
var __dirname = path32.dirname(fileURLToPath5(import.meta.url));
|
|
11618
|
-
var pkg = JSON.parse(fs35.readFileSync(path32.join(__dirname, "../package.json"), "utf-8"));
|
|
8303
|
+
var __dirname = path25.dirname(fileURLToPath5(import.meta.url));
|
|
8304
|
+
var pkg = JSON.parse(fs29.readFileSync(path25.join(__dirname, "../package.json"), "utf-8"));
|
|
11619
8305
|
var cli = new FullstackCLI(pkg.version);
|
|
11620
8306
|
cli.useAll(commands);
|
|
11621
8307
|
cli.run();
|