@4399ywkf/core 5.1.6 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -879,7 +879,7 @@ function createMockMiddleware(mockPath, options) {
879
879
  scanMockFiles(mockPath);
880
880
  return async (_req, _res, next) => {
881
881
  if (delay > 0) {
882
- await new Promise((resolve5) => setTimeout(resolve5, delay));
882
+ await new Promise((resolve6) => setTimeout(resolve6, delay));
883
883
  }
884
884
  next();
885
885
  };
@@ -1833,11 +1833,11 @@ var zustandPlugin = createPlugin((options = {}) => ({
1833
1833
  const hooks = {
1834
1834
  modifyRspackConfig(rspackConfig) {
1835
1835
  logger.info("Zustand \u5DF2\u542F\u7528");
1836
- const resolve5 = rspackConfig.resolve || {};
1837
- const alias = resolve5.alias || {};
1836
+ const resolve6 = rspackConfig.resolve || {};
1837
+ const alias = resolve6.alias || {};
1838
1838
  alias["@store"] = storePath;
1839
- resolve5.alias = alias;
1840
- rspackConfig.resolve = resolve5;
1839
+ resolve6.alias = alias;
1840
+ rspackConfig.resolve = resolve6;
1841
1841
  return rspackConfig;
1842
1842
  },
1843
1843
  generateFiles(_ctx) {
@@ -2175,7 +2175,9 @@ var defaultConfig = {
2175
2175
  tools: {},
2176
2176
  env: {
2177
2177
  publicEnvFile: "config/env/.env.public",
2178
- envDir: "config/env"
2178
+ envDir: "config/env",
2179
+ expose: [],
2180
+ exposePrefixes: ["YWKF_PUBLIC_", "NEXT_PUBLIC_"]
2179
2181
  },
2180
2182
  alias: {},
2181
2183
  plugins: []
@@ -3437,6 +3439,69 @@ var YwkfGeneratorPlugin = class {
3437
3439
  }
3438
3440
  };
3439
3441
 
3442
+ // src/rspack/client-env.ts
3443
+ import { existsSync as existsSync12, readFileSync as readFileSync4 } from "fs";
3444
+ import { resolve as resolve3 } from "path";
3445
+ import dotenv from "dotenv";
3446
+ var FRAMEWORK_ENV_KEYS = [
3447
+ "APP_CNAME",
3448
+ "APP_HOST",
3449
+ "APP_MODE",
3450
+ "APP_NAME",
3451
+ "APP_PORT",
3452
+ "DEBUG",
3453
+ "NODE_ENV",
3454
+ "OUTPUT_PATH",
3455
+ "PUBLIC_PATH",
3456
+ "YWKF_BUILD_ID",
3457
+ "YWKF_PREFIX_CLS"
3458
+ ];
3459
+ var DEFAULT_EXPOSE_PREFIXES = ["YWKF_PUBLIC_", "NEXT_PUBLIC_"];
3460
+ var SECRET_KEY_PATTERN = /TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|PRIVATE|AUTH|ACCESS_KEY|API_KEY|SIGNING_KEY/i;
3461
+ var SECRET_VALUE_PATTERN = /^(sntry[su]_|sk-|ghp_|gho_|ghu_|ghs_|github_pat_|glpat-|xox[abprs]-|AKIA|ya29\.)/;
3462
+ function readEnvFileKeys(filePath) {
3463
+ if (!existsSync12(filePath)) return [];
3464
+ try {
3465
+ return Object.keys(dotenv.parse(readFileSync4(filePath, "utf-8")));
3466
+ } catch {
3467
+ return [];
3468
+ }
3469
+ }
3470
+ function collectClientEnvKeys(options) {
3471
+ const { cwd, env = {}, mode = process.env.APP_MODE || "development" } = options;
3472
+ const keys = new Set(FRAMEWORK_ENV_KEYS);
3473
+ const files = [
3474
+ env.publicEnvFile ?? "config/env/.env.public",
3475
+ ".env.public",
3476
+ ".env",
3477
+ `${env.envDir ?? "config/env"}/.env.${mode}`,
3478
+ `.env.${mode}`
3479
+ ];
3480
+ for (const file of files) {
3481
+ for (const key of readEnvFileKeys(resolve3(cwd, file))) keys.add(key);
3482
+ }
3483
+ for (const key of env.expose ?? []) keys.add(key);
3484
+ return keys;
3485
+ }
3486
+ function buildClientEnv(options) {
3487
+ const { cwd, env = {}, mode, processEnv = process.env } = options;
3488
+ const prefixes = env.exposePrefixes ?? DEFAULT_EXPOSE_PREFIXES;
3489
+ const allowed = collectClientEnvKeys({ cwd, env, mode });
3490
+ const result = {};
3491
+ const dropped = [];
3492
+ for (const [key, value] of Object.entries(processEnv)) {
3493
+ if (value === void 0) continue;
3494
+ const isAllowed = allowed.has(key) || prefixes.some((prefix) => key.startsWith(prefix));
3495
+ if (!isAllowed) continue;
3496
+ if (SECRET_KEY_PATTERN.test(key) || SECRET_VALUE_PATTERN.test(value)) {
3497
+ dropped.push(key);
3498
+ continue;
3499
+ }
3500
+ result[key] = value;
3501
+ }
3502
+ return { env: result, dropped };
3503
+ }
3504
+
3440
3505
  // src/rspack/base.ts
3441
3506
  var require2 = createRequire(import.meta.url);
3442
3507
  var __dirname = dirname(fileURLToPath(import.meta.url));
@@ -3455,6 +3520,12 @@ function createBaseConfig(config, cwd, options = {}) {
3455
3520
  const { resolveApp } = createPathResolver(cwd);
3456
3521
  const { appName, appCName, output, html, alias: userAlias, microFrontend, router, reactCompiler } = config;
3457
3522
  const buildId = resolveYwkfBuildId(appName);
3523
+ const { env: clientEnv, dropped: droppedEnvKeys } = buildClientEnv({ cwd, env: config.env });
3524
+ if (droppedEnvKeys.length > 0) {
3525
+ console.warn(
3526
+ `[ywkf] \u4EE5\u4E0B\u73AF\u5883\u53D8\u91CF\u7591\u4F3C\u5BC6\u94A5,\u5DF2\u4ECE\u5BA2\u6237\u7AEF\u4EA7\u7269\u4E2D\u5254\u9664:${droppedEnvKeys.join(", ")}\u3002\u5982\u786E\u4E3A\u516C\u5F00\u914D\u7F6E,\u8BF7\u91CD\u547D\u540D\u6216\u8C03\u6574 env.expose\u3002`
3527
+ );
3528
+ }
3458
3529
  const ywkfOutputDir = resolveApp(".ywkf");
3459
3530
  const defaultAlias = {
3460
3531
  "@": resolveApp("src"),
@@ -3579,7 +3650,10 @@ function createBaseConfig(config, cwd, options = {}) {
3579
3650
  }),
3580
3651
  new rspack2.DefinePlugin({
3581
3652
  "globalThis.__YWKF_BUILD_ID__": JSON.stringify(buildId),
3582
- "process.env": JSON.stringify(process.env)
3653
+ // 只内联白名单内的公开配置。整包 process.env 会把构建机环境(CI 凭据、内网地址)
3654
+ // 写进公网可下载的产物,见 client-env.ts。外层括号不可省:该值以 `{` 开头,
3655
+ // `() => process.env.X` 会被替换成 `() => {…}` 而当成函数块体,导致整条 chunk 语法失败。
3656
+ "process.env": `(${JSON.stringify(clientEnv)})`
3583
3657
  }),
3584
3658
  new rspack2.HtmlRspackPlugin({
3585
3659
  template: resolveApp(html.template ?? "public/index.html"),
@@ -4097,28 +4171,28 @@ function createRspackConfig(config, cwd, options = {}) {
4097
4171
  }
4098
4172
 
4099
4173
  // src/cli/env.ts
4100
- import { existsSync as existsSync12, readFileSync as readFileSync4 } from "fs";
4101
- import { resolve as resolve3 } from "path";
4102
- import dotenv from "dotenv";
4174
+ import { existsSync as existsSync13, readFileSync as readFileSync5 } from "fs";
4175
+ import { resolve as resolve4 } from "path";
4176
+ import dotenv2 from "dotenv";
4103
4177
  function preloadEnv(cwd, mode, nodeEnv) {
4104
4178
  process.env.NODE_ENV = nodeEnv;
4105
4179
  process.env.APP_MODE = mode;
4106
4180
  const defaultPaths = [
4107
- resolve3(cwd, "config/env/.env.public"),
4108
- resolve3(cwd, ".env.public"),
4109
- resolve3(cwd, ".env")
4181
+ resolve4(cwd, "config/env/.env.public"),
4182
+ resolve4(cwd, ".env.public"),
4183
+ resolve4(cwd, ".env")
4110
4184
  ];
4111
4185
  for (const envPath of defaultPaths) {
4112
- if (existsSync12(envPath)) {
4113
- dotenv.config({ path: envPath });
4186
+ if (existsSync13(envPath)) {
4187
+ dotenv2.config({ path: envPath });
4114
4188
  break;
4115
4189
  }
4116
4190
  }
4117
- const modeEnvPaths = [resolve3(cwd, `config/env/.env.${mode}`), resolve3(cwd, `.env.${mode}`)];
4191
+ const modeEnvPaths = [resolve4(cwd, `config/env/.env.${mode}`), resolve4(cwd, `.env.${mode}`)];
4118
4192
  for (const envPath of modeEnvPaths) {
4119
- if (existsSync12(envPath)) {
4120
- const envContent = readFileSync4(envPath, "utf-8");
4121
- const parsed = dotenv.parse(envContent);
4193
+ if (existsSync13(envPath)) {
4194
+ const envContent = readFileSync5(envPath, "utf-8");
4195
+ const parsed = dotenv2.parse(envContent);
4122
4196
  for (const key in parsed) {
4123
4197
  process.env[key] = parsed[key];
4124
4198
  }
@@ -4130,14 +4204,14 @@ function preloadEnv(cwd, mode, nodeEnv) {
4130
4204
  }
4131
4205
  function loadEnv(config, cwd, mode, nodeEnv) {
4132
4206
  const { env } = config;
4133
- const publicEnvPath = resolve3(cwd, env.publicEnvFile ?? "config/env/.env.public");
4134
- if (existsSync12(publicEnvPath)) {
4135
- dotenv.config({ path: publicEnvPath });
4136
- }
4137
- const modeEnvPath = resolve3(cwd, env.envDir ?? "config/env", `.env.${mode}`);
4138
- if (existsSync12(modeEnvPath)) {
4139
- const envContent = readFileSync4(modeEnvPath, "utf-8");
4140
- const parsed = dotenv.parse(envContent);
4207
+ const publicEnvPath = resolve4(cwd, env.publicEnvFile ?? "config/env/.env.public");
4208
+ if (existsSync13(publicEnvPath)) {
4209
+ dotenv2.config({ path: publicEnvPath });
4210
+ }
4211
+ const modeEnvPath = resolve4(cwd, env.envDir ?? "config/env", `.env.${mode}`);
4212
+ if (existsSync13(modeEnvPath)) {
4213
+ const envContent = readFileSync5(modeEnvPath, "utf-8");
4214
+ const parsed = dotenv2.parse(envContent);
4141
4215
  for (const key in parsed) {
4142
4216
  process.env[key] = parsed[key];
4143
4217
  }
@@ -4415,7 +4489,7 @@ async function build(options = {}) {
4415
4489
  rspackConfig.stats = "none";
4416
4490
  rspackConfig.infrastructureLogging = { level: "none" };
4417
4491
  const compiler = rspack4(rspackConfig);
4418
- const stats = await new Promise((resolve5, reject) => {
4492
+ const stats = await new Promise((resolve6, reject) => {
4419
4493
  compiler.run((err, stats2) => {
4420
4494
  if (err) {
4421
4495
  reject(err);
@@ -4425,13 +4499,13 @@ async function build(options = {}) {
4425
4499
  reject(new Error("Build failed: no stats available"));
4426
4500
  return;
4427
4501
  }
4428
- resolve5(stats2);
4502
+ resolve6(stats2);
4429
4503
  });
4430
4504
  });
4431
- await new Promise((resolve5, reject) => {
4505
+ await new Promise((resolve6, reject) => {
4432
4506
  compiler.close((err) => {
4433
4507
  if (err) reject(err);
4434
- else resolve5();
4508
+ else resolve6();
4435
4509
  });
4436
4510
  });
4437
4511
  const hasErrors = stats.hasErrors();
@@ -4473,7 +4547,7 @@ var PortInUseError = class extends Error {
4473
4547
  }
4474
4548
  };
4475
4549
  function ensurePortAvailable(port, host) {
4476
- return new Promise((resolve5, reject) => {
4550
+ return new Promise((resolve6, reject) => {
4477
4551
  const server = net.createServer();
4478
4552
  server.once("error", (err) => {
4479
4553
  if (err.code === "EADDRINUSE") {
@@ -4483,7 +4557,7 @@ function ensurePortAvailable(port, host) {
4483
4557
  }
4484
4558
  });
4485
4559
  server.once("listening", () => {
4486
- server.close(() => resolve5());
4560
+ server.close(() => resolve6());
4487
4561
  });
4488
4562
  server.listen(port, host);
4489
4563
  });
@@ -4531,8 +4605,8 @@ function parseWindowsNetstatPid(stdout, port) {
4531
4605
  }
4532
4606
 
4533
4607
  // src/cli/restart-watcher.ts
4534
- import { existsSync as existsSync13, watch as watch2 } from "fs";
4535
- import { resolve as resolve4 } from "path";
4608
+ import { existsSync as existsSync14, watch as watch2 } from "fs";
4609
+ import { resolve as resolve5 } from "path";
4536
4610
  function isTriggerFile(filename, mode) {
4537
4611
  if (!filename) return false;
4538
4612
  if (CONFIG_FILES.includes(filename)) return true;
@@ -4562,8 +4636,8 @@ function watchForRestart(opts) {
4562
4636
  }, debounceMs);
4563
4637
  };
4564
4638
  watchers.push(watch2(cwd, { recursive: false }, (_event, filename) => trigger(filename)));
4565
- const envDir = resolve4(cwd, "config/env");
4566
- if (existsSync13(envDir)) {
4639
+ const envDir = resolve5(cwd, "config/env");
4640
+ if (existsSync14(envDir)) {
4567
4641
  watchers.push(watch2(envDir, { recursive: false }, (_event, filename) => trigger(filename)));
4568
4642
  }
4569
4643
  return {
@@ -4670,10 +4744,10 @@ async function startDevServer(cwd, config) {
4670
4744
  if (closed) return;
4671
4745
  closed = true;
4672
4746
  await server.stop();
4673
- await new Promise((resolve5, reject) => {
4747
+ await new Promise((resolve6, reject) => {
4674
4748
  compiler.close((err) => {
4675
4749
  if (err) reject(err);
4676
- else resolve5();
4750
+ else resolve6();
4677
4751
  });
4678
4752
  });
4679
4753
  };