@heybox/hb-sdk 0.5.16 → 0.5.18

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.
@@ -234,19 +234,19 @@ function requireArgument () {
234
234
 
235
235
  var command = {};
236
236
 
237
- const require$5 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-B-lA2GE7.cjs', document.baseURI).href)));
237
+ const require$5 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-CsOcGUzF.cjs', document.baseURI).href)));
238
238
  function __require$4() { return require$5("node:events"); }
239
239
 
240
- const require$4 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-B-lA2GE7.cjs', document.baseURI).href)));
240
+ const require$4 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-CsOcGUzF.cjs', document.baseURI).href)));
241
241
  function __require$3() { return require$4("node:child_process"); }
242
242
 
243
- const require$3 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-B-lA2GE7.cjs', document.baseURI).href)));
243
+ const require$3 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-CsOcGUzF.cjs', document.baseURI).href)));
244
244
  function __require$2() { return require$3("node:path"); }
245
245
 
246
- const require$2 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-B-lA2GE7.cjs', document.baseURI).href)));
246
+ const require$2 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-CsOcGUzF.cjs', document.baseURI).href)));
247
247
  function __require$1() { return require$2("node:fs"); }
248
248
 
249
- const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-B-lA2GE7.cjs', document.baseURI).href)));
249
+ const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli-chunks/index-CsOcGUzF.cjs', document.baseURI).href)));
250
250
  function __require() { return require$1("node:process"); }
251
251
 
252
252
  var help = {};
@@ -13068,10 +13068,12 @@ async function pathExists$1(filePath) {
13068
13068
  }
13069
13069
 
13070
13070
  class CliError extends Error {
13071
+ httpStatus;
13071
13072
  verboseMessage;
13072
- constructor(message, verboseMessage) {
13073
+ constructor(message, verboseMessage, options = {}) {
13073
13074
  super(message);
13074
13075
  this.name = 'CliError';
13076
+ this.httpStatus = options.httpStatus;
13075
13077
  this.verboseMessage = verboseMessage;
13076
13078
  }
13077
13079
  }
@@ -13093,8 +13095,228 @@ function readErrorMessage(error, options = {}) {
13093
13095
  return String(error);
13094
13096
  }
13095
13097
 
13098
+ /**
13099
+ * 极简 .env 文件解析器。
13100
+ *
13101
+ * 只支持 hb-sdk CLI 需要的最小语义:KEY=VALUE、空行、`#` 注释、单/双引号包裹值。
13102
+ * 不做变量插值,不展开 shell 转义,避免引入额外依赖。
13103
+ */
13104
+ /**
13105
+ * 解析 .env 文件内容为 key/value 记录,保持原始出现顺序的 key 列表。
13106
+ */
13107
+ function parseDotenvFile(content) {
13108
+ const entries = {};
13109
+ const keys = [];
13110
+ for (const rawLine of content.split(/\r?\n/)) {
13111
+ const line = stripInlineComment(rawLine).trim();
13112
+ if (!line || line.startsWith('#')) {
13113
+ continue;
13114
+ }
13115
+ const equalsIndex = line.indexOf('=');
13116
+ if (equalsIndex <= 0) {
13117
+ continue;
13118
+ }
13119
+ const key = line.slice(0, equalsIndex).trim();
13120
+ if (!isValidEnvKey(key)) {
13121
+ continue;
13122
+ }
13123
+ const rawValue = line.slice(equalsIndex + 1).trim();
13124
+ const value = unquoteDotenvValue(rawValue);
13125
+ if (!Object.prototype.hasOwnProperty.call(entries, key)) {
13126
+ keys.push(key);
13127
+ }
13128
+ entries[key] = value;
13129
+ }
13130
+ return { entries, keys };
13131
+ }
13132
+ function stripInlineComment(line) {
13133
+ // 仅处理未被引号包裹的行内注释,避免误伤值里的 #。
13134
+ let inSingle = false;
13135
+ let inDouble = false;
13136
+ for (let i = 0; i < line.length; i += 1) {
13137
+ const char = line[i];
13138
+ if (char === "'" && !inDouble) {
13139
+ inSingle = !inSingle;
13140
+ }
13141
+ else if (char === '"' && !inSingle) {
13142
+ inDouble = !inDouble;
13143
+ }
13144
+ else if (char === '#' && !inSingle && !inDouble) {
13145
+ return line.slice(0, i);
13146
+ }
13147
+ }
13148
+ return line;
13149
+ }
13150
+ function unquoteDotenvValue(value) {
13151
+ if (value.length >= 2) {
13152
+ const first = value[0];
13153
+ const last = value[value.length - 1];
13154
+ if (first === '"' && last === '"') {
13155
+ return value.slice(1, -1).replace(/\\(["\\$])/g, '$1');
13156
+ }
13157
+ if (first === "'" && last === "'") {
13158
+ return value.slice(1, -1);
13159
+ }
13160
+ }
13161
+ return value;
13162
+ }
13163
+ function isValidEnvKey(key) {
13164
+ return /^[A-Za-z_][A-Za-z0-9_]*$/.test(key);
13165
+ }
13166
+
13167
+ const DEFAULT_READ_FILE = (path) => fs$1.readFileSync(path, 'utf8');
13168
+ function resolveEnvPresetFilePath(argv, env = process.env, cwd = process.cwd()) {
13169
+ const explicit = readEnvFileArgFromArgv(argv);
13170
+ if (explicit) {
13171
+ return path.resolve(cwd, explicit);
13172
+ }
13173
+ const name = readEnvNameArgFromArgv(argv) ?? env.HB_SDK_ENV;
13174
+ if (name) {
13175
+ return path.resolve(cwd, `.env.${name}`);
13176
+ }
13177
+ return undefined;
13178
+ }
13179
+ function loadEnvPreset(argv, options = {}) {
13180
+ const targetEnv = options.env ?? process.env;
13181
+ const cwd = options.cwd ?? process.cwd();
13182
+ const readFile = options.readFile ?? DEFAULT_READ_FILE;
13183
+ const filePath = resolveEnvPresetFilePath(argv, targetEnv, cwd);
13184
+ if (!filePath) {
13185
+ return { filePath: undefined, appliedKeys: [], skippedKeys: [] };
13186
+ }
13187
+ let content;
13188
+ try {
13189
+ content = readFile(filePath);
13190
+ }
13191
+ catch {
13192
+ // 文件不存在或不可读时静默跳过,与 dotenv 默认行为一致。
13193
+ return { filePath, appliedKeys: [], skippedKeys: [] };
13194
+ }
13195
+ const { entries } = parseDotenvFile(content);
13196
+ const appliedKeys = [];
13197
+ const skippedKeys = [];
13198
+ for (const [key, value] of Object.entries(entries)) {
13199
+ if (targetEnv[key] !== undefined && targetEnv[key] !== '') {
13200
+ skippedKeys.push(key);
13201
+ continue;
13202
+ }
13203
+ targetEnv[key] = value;
13204
+ appliedKeys.push(key);
13205
+ }
13206
+ return { filePath, appliedKeys, skippedKeys };
13207
+ }
13208
+ /**
13209
+ * 从 argv 中提取 `--env-file <path>` 的值。
13210
+ * 支持 `--env-file path`、`--env-file=path` 两种写法。
13211
+ */
13212
+ function readEnvFileArgFromArgv(argv) {
13213
+ for (let i = 0; i < argv.length; i += 1) {
13214
+ const arg = argv[i];
13215
+ if (arg === '--env-file') {
13216
+ return argv[i + 1];
13217
+ }
13218
+ if (arg?.startsWith('--env-file=')) {
13219
+ return arg.slice('--env-file='.length);
13220
+ }
13221
+ }
13222
+ return undefined;
13223
+ }
13224
+ /**
13225
+ * 从 argv 中提取 `--env <name>` 的值。
13226
+ * 支持 `--env name`、`--env=name` 两种写法。
13227
+ */
13228
+ function readEnvNameArgFromArgv(argv) {
13229
+ for (let i = 0; i < argv.length; i += 1) {
13230
+ const arg = argv[i];
13231
+ if (arg === '--env') {
13232
+ return argv[i + 1];
13233
+ }
13234
+ if (arg?.startsWith('--env=')) {
13235
+ return arg.slice('--env='.length);
13236
+ }
13237
+ }
13238
+ return undefined;
13239
+ }
13240
+
13241
+ const globalHeyboxCliRequestConfig = {};
13242
+ function configureHeyboxCliRequestConfig(config) {
13243
+ const normalized = normalizeHeyboxRylaiServiceTagConfig(config);
13244
+ if (normalized.default_tag) {
13245
+ globalHeyboxCliRequestConfig.default_tag = normalized.default_tag;
13246
+ }
13247
+ else {
13248
+ delete globalHeyboxCliRequestConfig.default_tag;
13249
+ }
13250
+ if (normalized.special_tag) {
13251
+ globalHeyboxCliRequestConfig.special_tag = normalized.special_tag;
13252
+ }
13253
+ else {
13254
+ delete globalHeyboxCliRequestConfig.special_tag;
13255
+ }
13256
+ }
13257
+ function readHeyboxCliRequestConfig() {
13258
+ return normalizeHeyboxRylaiServiceTagConfig(globalHeyboxCliRequestConfig);
13259
+ }
13260
+ /**
13261
+ * 当 tag 为非空字符串时,把它设为 CLI 全局 default_tag;为空时不改动现有配置,
13262
+ * 避免清掉 env 预设阶段已注入的值。
13263
+ */
13264
+ function applyServiceTagIfNeeded(tag) {
13265
+ const normalized = normalizeHeyboxRylaiServiceTag(tag);
13266
+ if (!normalized) {
13267
+ return;
13268
+ }
13269
+ configureHeyboxCliRequestConfig({ default_tag: normalized });
13270
+ }
13271
+ function resolveHeyboxRylaiServiceTag(pathWithQuery, config = readHeyboxCliRequestConfig()) {
13272
+ const normalized = normalizeHeyboxRylaiServiceTagConfig(config);
13273
+ const pathname = pathWithQuery ? getPathname(pathWithQuery) : '';
13274
+ const specialTag = normalized.special_tag;
13275
+ if (pathname && specialTag?.path_prefix_list.some((prefix) => pathname.startsWith(prefix))) {
13276
+ return specialTag.tag_name;
13277
+ }
13278
+ return normalized.default_tag;
13279
+ }
13280
+ function normalizeHeyboxRylaiServiceTagConfig(config) {
13281
+ const defaultTag = normalizeHeyboxRylaiServiceTag(config.default_tag);
13282
+ const specialTagName = normalizeHeyboxRylaiServiceTag(config.special_tag?.tag_name);
13283
+ const pathPrefixList = config.special_tag?.path_prefix_list?.filter(isValidPathPrefix) || [];
13284
+ return {
13285
+ ...(defaultTag ? { default_tag: defaultTag } : {}),
13286
+ ...(specialTagName && pathPrefixList.length
13287
+ ? {
13288
+ special_tag: {
13289
+ tag_name: specialTagName,
13290
+ path_prefix_list: pathPrefixList,
13291
+ },
13292
+ }
13293
+ : {}),
13294
+ };
13295
+ }
13296
+ function normalizeHeyboxRylaiServiceTag(value) {
13297
+ const tag = String(value ?? '').trim();
13298
+ if (!tag) {
13299
+ return undefined;
13300
+ }
13301
+ if (/[\r\n]/.test(tag)) {
13302
+ throw new Error('x-rylai-service-tag 不允许包含换行符');
13303
+ }
13304
+ return tag;
13305
+ }
13306
+ function isValidPathPrefix(value) {
13307
+ return typeof value === 'string' && value.startsWith('/') && !/[\r\n]/.test(value);
13308
+ }
13309
+ function getPathname(pathWithQuery) {
13310
+ try {
13311
+ return new URL(pathWithQuery, 'https://api.xiaoheihe.cn').pathname;
13312
+ }
13313
+ catch {
13314
+ return '';
13315
+ }
13316
+ }
13317
+
13096
13318
  const CLI_VERSION_PLACEHOLDER = ['__HB', 'SDK', 'CLI', 'VERSION__'].join('_');
13097
- const BUILT_CLI_VERSION = '0.5.16';
13319
+ const BUILT_CLI_VERSION = '0.5.18';
13098
13320
  const PACKAGE_JSON_CANDIDATES = [
13099
13321
  path.resolve(__dirname, '..', '..', 'package.json'),
13100
13322
  path.resolve(__dirname, '..', 'package.json'),
@@ -13132,7 +13354,9 @@ async function runCli(options = {}) {
13132
13354
  const processLike = options.process ?? process;
13133
13355
  const argv = options.argv ?? process.argv;
13134
13356
  const verbose = hasVerboseArg(argv);
13357
+ const logger = resolveStandaloneLogger(options, verbose);
13135
13358
  try {
13359
+ preloadCliEnvPreset(argv, { logger });
13136
13360
  await createCliProgram(options).parseAsync(argv);
13137
13361
  }
13138
13362
  catch (error) {
@@ -13141,7 +13365,7 @@ async function runCli(options = {}) {
13141
13365
  return;
13142
13366
  }
13143
13367
  if (!(error instanceof CommanderError)) {
13144
- (options.printError ?? printError)(error, { logger: resolveStandaloneLogger(options, verbose), verbose });
13368
+ (options.printError ?? printError)(error, { logger, verbose });
13145
13369
  }
13146
13370
  processLike.exit(error instanceof CommanderError ? error.exitCode : 1);
13147
13371
  }
@@ -13165,6 +13389,8 @@ function createCliProgram(overrides = {}) {
13165
13389
  .description('hb-sdk developer tools')
13166
13390
  .version(getCliVersion())
13167
13391
  .option('-v, --verbose', '输出详细调试信息')
13392
+ .option('--env <name>', '加载项目根下 .env.<name> 预设,把其中的 HB_SDK_* 变量注入当前进程(不覆盖已有值)')
13393
+ .option('--env-file <path>', '显式指定 .env 文件路径,优先级高于 --env')
13168
13394
  .showHelpAfterError()
13169
13395
  .exitOverride();
13170
13396
  installVersionUpdateReminder(program, handlers.printUpdateReminder, resolveLogger);
@@ -13220,7 +13446,8 @@ function addRemotePublicOptions(command) {
13220
13446
  .option('--json', '以 JSON 格式输出 remote 命令结果')
13221
13447
  .option('--api-base-url <url>', 'Heybox 后台 API origin,默认读取 HB_SDK_API_BASE_URL 或生产地址')
13222
13448
  .option('--login-base-url <url>', '校验 CLI 登录态使用的登录 origin,默认读取 HB_SDK_LOGIN_BASE_URL 或生产地址')
13223
- .option('--allow-unsafe-api-base-url', '允许向非 Heybox HTTPS API origin 发送登录态,仅限本地调试'));
13449
+ .option('--allow-unsafe-api-base-url', '允许向非 Heybox HTTPS API origin 发送登录态,仅限本地调试')
13450
+ .option('--service-tag <tag>', '给 Heybox 后台请求附加 x-rylai-service-tag,默认读取 HB_SDK_SERVICE_TAG'));
13224
13451
  }
13225
13452
  function installRemoteCommands(program, handlers, resolveLogger) {
13226
13453
  const remote = addRemotePublicOptions(program.command('remote').description('管理当前项目绑定的远程 Heybox 工坊小程序'));
@@ -13357,6 +13584,7 @@ function readRemoteCommonOptions(command) {
13357
13584
  apiBaseUrl: readStringOption(options.apiBaseUrl),
13358
13585
  json: Boolean(options.json),
13359
13586
  loginBaseUrl: readStringOption(options.loginBaseUrl),
13587
+ serviceTag: readStringOption(options.serviceTag),
13360
13588
  verbose: Boolean(options.verbose),
13361
13589
  };
13362
13590
  }
@@ -13411,31 +13639,31 @@ function createCommandLoggerResolver(options) {
13411
13639
  };
13412
13640
  }
13413
13641
  const defaultClearLoginStatus = async (...args) => {
13414
- const { clearLoginStatus } = await Promise.resolve().then(function () { return require('./login-CP6xdTYa.cjs'); });
13642
+ const { clearLoginStatus } = await Promise.resolve().then(function () { return require('./login-Ct-46gLx.cjs'); });
13415
13643
  return clearLoginStatus(...args);
13416
13644
  };
13417
13645
  const defaultLoginToHeybox = async (...args) => {
13418
- const { loginToHeybox } = await Promise.resolve().then(function () { return require('./login-CP6xdTYa.cjs'); });
13646
+ const { loginToHeybox } = await Promise.resolve().then(function () { return require('./login-Ct-46gLx.cjs'); });
13419
13647
  return loginToHeybox(...args);
13420
13648
  };
13421
13649
  const defaultPrintLoginStatus = async (...args) => {
13422
- const { printLoginStatus } = await Promise.resolve().then(function () { return require('./login-CP6xdTYa.cjs'); });
13650
+ const { printLoginStatus } = await Promise.resolve().then(function () { return require('./login-Ct-46gLx.cjs'); });
13423
13651
  return printLoginStatus(...args);
13424
13652
  };
13425
13653
  const defaultRunCreateCommand = async (...args) => {
13426
- const { runCreateCommand } = await Promise.resolve().then(function () { return require('./create-DUwSoYT4.cjs'); });
13654
+ const { runCreateCommand } = await Promise.resolve().then(function () { return require('./create-OZOIdeBz.cjs'); });
13427
13655
  return runCreateCommand(...args);
13428
13656
  };
13429
13657
  const defaultRunDevCommand = async (...args) => {
13430
- const { runDevCommand } = await Promise.resolve().then(function () { return require('./dev-78XBGRX3.cjs'); });
13658
+ const { runDevCommand } = await Promise.resolve().then(function () { return require('./dev-DXz8izSJ.cjs'); });
13431
13659
  return runDevCommand(...args);
13432
13660
  };
13433
13661
  const defaultRunDoctorCommand = async (...args) => {
13434
- const { runDoctorCommand } = await Promise.resolve().then(function () { return require('./doctor-CHrjGIQ1.cjs'); });
13662
+ const { runDoctorCommand } = await Promise.resolve().then(function () { return require('./doctor-DjMSJoQ5.cjs'); });
13435
13663
  return runDoctorCommand(...args);
13436
13664
  };
13437
13665
  const defaultRunRemoteCommand = async (...args) => {
13438
- const { runRemoteCommand } = await Promise.resolve().then(function () { return require('./remote-CdEyGDRq.cjs'); }).then(function (n) { return n.remote; });
13666
+ const { runRemoteCommand } = await Promise.resolve().then(function () { return require('./remote-C77axNSw.cjs'); });
13439
13667
  return runRemoteCommand(...args);
13440
13668
  };
13441
13669
  function resolveStandaloneLogger(options, verbose) {
@@ -13493,6 +13721,25 @@ function readCommandFromActionArgs(args) {
13493
13721
  const lastArg = args[args.length - 1];
13494
13722
  return lastArg instanceof Command ? lastArg : undefined;
13495
13723
  }
13724
+ /**
13725
+ * 在 commander 解析前加载 .env 预设,把其中的 HB_SDK_* 变量注入 process.env(不覆盖已有值),
13726
+ * 并把 HB_SDK_SERVICE_TAG 同步到 CLI 全局请求配置。
13727
+ * 这样后续 resolveHeyboxApiBaseUrl / resolveHeyboxLoginBaseUrl 读 process.env 时即可拿到预设值。
13728
+ */
13729
+ function preloadCliEnvPreset(argv, options = {}) {
13730
+ const result = loadEnvPreset(argv);
13731
+ if (!result.filePath) {
13732
+ return;
13733
+ }
13734
+ options.logger?.debug(`已加载 env 预设: ${result.filePath}`);
13735
+ if (result.appliedKeys.length) {
13736
+ options.logger?.debug(`env 预设生效: ${result.appliedKeys.join(', ')}`);
13737
+ }
13738
+ if (result.skippedKeys.length) {
13739
+ options.logger?.debug(`env 预设跳过(已有值): ${result.skippedKeys.join(', ')}`);
13740
+ }
13741
+ applyServiceTagIfNeeded(process.env.HB_SDK_SERVICE_TAG);
13742
+ }
13496
13743
  function parsePositivePort(value) {
13497
13744
  const parsed = Number(value);
13498
13745
  if (!Number.isInteger(parsed) || parsed <= 0) {
@@ -13514,6 +13761,7 @@ exports.HB_SDK_SKILL_INDEX_URL = HB_SDK_SKILL_INDEX_URL;
13514
13761
  exports.HB_SDK_SKILL_INSTALL_COMMAND = HB_SDK_SKILL_INSTALL_COMMAND;
13515
13762
  exports.HB_SDK_SKILL_NAME = HB_SDK_SKILL_NAME;
13516
13763
  exports.HB_SDK_SKILL_SOURCE = HB_SDK_SKILL_SOURCE;
13764
+ exports.applyServiceTagIfNeeded = applyServiceTagIfNeeded;
13517
13765
  exports.commonjsGlobal = commonjsGlobal;
13518
13766
  exports.createCliLogger = createCliLogger;
13519
13767
  exports.createCliProgram = createCliProgram;
@@ -13523,4 +13771,5 @@ exports.readErrorMessage = readErrorMessage;
13523
13771
  exports.requireEnvPaths = requireEnvPaths;
13524
13772
  exports.requireOnetime = requireOnetime;
13525
13773
  exports.requireSafeBuffer = requireSafeBuffer;
13774
+ exports.resolveHeyboxRylaiServiceTag = resolveHeyboxRylaiServiceTag;
13526
13775
  exports.runCli = runCli;
@@ -3,9 +3,9 @@
3
3
  var promises = require('node:readline/promises');
4
4
  var node_crypto = require('node:crypto');
5
5
  var node_http = require('node:http');
6
- var session = require('./session-Cfl5cGf8.cjs');
6
+ var session = require('./session-dRGPpyS1.cjs');
7
7
  var browser = require('./browser-RAy8e8cV.cjs');
8
- var index = require('./index-B-lA2GE7.cjs');
8
+ var index = require('./index-CsOcGUzF.cjs');
9
9
  require('node:path');
10
10
  require('fs');
11
11
  require('constants');