@simplysm/sd-cli 14.0.4 → 14.0.6

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.
Files changed (46) hide show
  1. package/README.md +1 -1
  2. package/dist/commands/check.d.ts.map +1 -1
  3. package/dist/commands/check.js +10 -10
  4. package/dist/commands/check.js.map +1 -1
  5. package/dist/commands/lint.d.ts.map +1 -1
  6. package/dist/commands/lint.js +1 -4
  7. package/dist/commands/lint.js.map +1 -1
  8. package/dist/commands/replace-deps.js +1 -1
  9. package/dist/commands/replace-deps.js.map +1 -1
  10. package/dist/index.d.ts +1 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +2 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
  15. package/dist/orchestrators/BuildOrchestrator.js +52 -45
  16. package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
  17. package/dist/orchestrators/DevWatchOrchestrator.js +24 -24
  18. package/dist/orchestrators/DevWatchOrchestrator.js.map +1 -1
  19. package/dist/utils/output-utils.js +1 -1
  20. package/dist/utils/output-utils.js.map +1 -1
  21. package/dist/utils/package-utils.js +3 -3
  22. package/dist/utils/package-utils.js.map +1 -1
  23. package/dist/utils/rebuild-manager.js +3 -3
  24. package/dist/utils/rebuild-manager.js.map +1 -1
  25. package/dist/utils/replace-deps.js +11 -11
  26. package/dist/utils/replace-deps.js.map +1 -1
  27. package/dist/utils/worker-utils.js +1 -1
  28. package/dist/utils/worker-utils.js.map +1 -1
  29. package/dist/workers/server-build.worker.js +2 -2
  30. package/dist/workers/server-build.worker.js.map +1 -1
  31. package/dist/workers/server-runtime.worker.js +13 -13
  32. package/dist/workers/server-runtime.worker.js.map +1 -1
  33. package/package.json +4 -4
  34. package/src/commands/check.ts +12 -11
  35. package/src/commands/lint.ts +1 -3
  36. package/src/commands/replace-deps.ts +1 -1
  37. package/src/index.ts +3 -0
  38. package/src/orchestrators/BuildOrchestrator.ts +52 -45
  39. package/src/orchestrators/DevWatchOrchestrator.ts +24 -24
  40. package/src/utils/output-utils.ts +1 -1
  41. package/src/utils/package-utils.ts +3 -3
  42. package/src/utils/rebuild-manager.ts +3 -3
  43. package/src/utils/replace-deps.ts +11 -11
  44. package/src/utils/worker-utils.ts +1 -1
  45. package/src/workers/server-build.worker.ts +2 -2
  46. package/src/workers/server-runtime.worker.ts +13 -13
@@ -90,9 +90,9 @@ export class DevWatchOrchestrator {
90
90
  }
91
91
 
92
92
  async initialize(): Promise<void> {
93
- this._logger.debug(`${this._options.mode} start`, { targets: this._options.targets });
93
+ this._logger.debug(`${this._options.mode} 시작`, { targets: this._options.targets });
94
94
 
95
- // Load sd.config.ts
95
+ // sd.config.ts 로드
96
96
  let sdConfig: SdConfig;
97
97
  try {
98
98
  sdConfig = await loadSdConfig({
@@ -100,9 +100,9 @@ export class DevWatchOrchestrator {
100
100
  dev: true,
101
101
  options: this._options.options,
102
102
  });
103
- this._logger.debug("sd.config.ts loaded");
103
+ this._logger.debug("sd.config.ts 로드 완료");
104
104
  } catch (err) {
105
- this._logger.error(`Failed to load sd.config.ts: ${err instanceof Error ? err.message : err}`);
105
+ this._logger.error(`sd.config.ts 로드 실패: ${err instanceof Error ? err.message : err}`);
106
106
  process.exitCode = 1;
107
107
  throw err;
108
108
  }
@@ -147,8 +147,8 @@ export class DevWatchOrchestrator {
147
147
  // Check if there are packages to process
148
148
  const totalPackages = this._libraryPackages.length + this._serverPackages.length + this._watchHookPackages.length + this._clientPackages.length;
149
149
  if (totalPackages === 0) {
150
- const modeLabel = this._options.mode === "watch" ? "watch" : "develop";
151
- process.stdout.write(`⚠ No packages to ${modeLabel}.\n`);
150
+ const modeLabel = this._options.mode === "watch" ? "워치" : "개발";
151
+ process.stdout.write(`⚠ ${modeLabel} 대상 패키지가 없습니다.\n`);
152
152
  return;
153
153
  }
154
154
 
@@ -245,7 +245,7 @@ export class DevWatchOrchestrator {
245
245
  return;
246
246
  }
247
247
 
248
- process.stdout.write("⏳ Shutting down...\n");
248
+ process.stdout.write("⏳ 종료 중...\n");
249
249
 
250
250
  const shutdownTasks: Array<Promise<void>> = [];
251
251
 
@@ -274,7 +274,7 @@ export class DevWatchOrchestrator {
274
274
  this._watchHookWatchers.length = 0;
275
275
  this._replaceDepWatcher?.dispose();
276
276
 
277
- process.stdout.write("✔ Done\n");
277
+ process.stdout.write("✔ 종료 완료\n");
278
278
  }
279
279
 
280
280
  // --- Watch mode ---
@@ -289,12 +289,12 @@ export class DevWatchOrchestrator {
289
289
  }
290
290
 
291
291
  // Start all engines
292
- this._logger.start("Running initial build...");
292
+ this._logger.start("초기 빌드 실행 중...");
293
293
  const watchPromises: Array<Promise<void>> = [];
294
294
  watchPromises.push(...this._libraryEngines.map((e) => e.startWatch({ js: true, dts: true, lint: true })));
295
295
 
296
296
  await Promise.allSettled(watchPromises);
297
- this._logger.success("Initial build completed");
297
+ this._logger.success("초기 빌드 실행 완료");
298
298
 
299
299
  // Print initial build results
300
300
  printErrors(this._resultCollector.toMap());
@@ -314,7 +314,7 @@ export class DevWatchOrchestrator {
314
314
  });
315
315
  this._watchHookWatchers.push(watcher);
316
316
 
317
- this._logger.success(`Watch hook started: ${pkg.name}`);
317
+ this._logger.success(`워치 시작됨: ${pkg.name}`);
318
318
  }
319
319
  }
320
320
 
@@ -329,11 +329,11 @@ export class DevWatchOrchestrator {
329
329
  this._watchHookChildren.set(pkgName, child);
330
330
 
331
331
  child.on("error", (err) => {
332
- this._logger.error(`Watch hook error (${pkgName}): ${err.message}`);
332
+ this._logger.error(`[${pkgName}] 워치 훅 에러: ${err.message}`);
333
333
  });
334
334
  child.on("close", (code) => {
335
335
  if (code !== 0 && code !== null) {
336
- this._logger.warn(`Watch hook (${pkgName}) exited with code ${String(code)}`);
336
+ this._logger.warn(`[${pkgName}] 워치 훅이 코드 ${String(code)}로 종료됨`);
337
337
  }
338
338
  });
339
339
  }
@@ -342,7 +342,7 @@ export class DevWatchOrchestrator {
342
342
 
343
343
  private async _startDevMode(): Promise<void> {
344
344
  // Start client and server engines in parallel
345
- this._logger.debug("Starting initial build (Promise.allSettled)");
345
+ this._logger.debug("초기 빌드 시작");
346
346
  const initialBuildPromises: Array<{ name: string; promise: Promise<void> }> = [];
347
347
 
348
348
  for (const [name, engine] of this._clientEngines) {
@@ -366,9 +366,9 @@ export class DevWatchOrchestrator {
366
366
  initialResults.forEach((result, index) => {
367
367
  const taskName = initialBuildPromises[index].name;
368
368
  if (result.status === "rejected") {
369
- this._logger.debug(`[${taskName}] Initial build failed:`, result.reason);
369
+ this._logger.debug(`[${taskName}] 초기 빌드 실패:`, result.reason);
370
370
  } else {
371
- this._logger.debug(`[${taskName}] Initial build completed`);
371
+ this._logger.debug(`[${taskName}] 초기 빌드 완료`);
372
372
  }
373
373
  });
374
374
 
@@ -400,7 +400,7 @@ export class DevWatchOrchestrator {
400
400
  try {
401
401
  await this._startServerRuntime(name, mainJsPath, { ...this._baseEnv, ...config.env }, clientPorts);
402
402
  } catch (err) {
403
- this._logger.error(`[${name}] Error starting Server Runtime:`, errNs.message(err));
403
+ this._logger.error(`[${name}] 서버 런타임 시작 실패:`, errNs.message(err));
404
404
  this._resultCollector.add({
405
405
  name,
406
406
  target: "server",
@@ -427,7 +427,7 @@ export class DevWatchOrchestrator {
427
427
  await cap.run(devServerUrl);
428
428
  } catch (err) {
429
429
  this._logger.error(
430
- `[${name}] Capacitor run failed: ${errNs.message(err)}`,
430
+ `[${name}] Capacitor 실행 실패: ${errNs.message(err)}`,
431
431
  );
432
432
  }
433
433
  }
@@ -440,14 +440,14 @@ export class DevWatchOrchestrator {
440
440
  await elc.run(devServerUrl);
441
441
  } catch (err) {
442
442
  this._logger.error(
443
- `[${name}] Electron run failed: ${errNs.message(err)}`,
443
+ `[${name}] Electron 실행 실패: ${errNs.message(err)}`,
444
444
  );
445
445
  this._resultCollector.add({
446
446
  name,
447
447
  target: "client",
448
448
  type: "build",
449
449
  status: "error",
450
- message: `Electron run failed: ${errNs.message(err)}`,
450
+ message: `Electron 실행 실패: ${errNs.message(err)}`,
451
451
  });
452
452
  }
453
453
  })();
@@ -469,7 +469,7 @@ export class DevWatchOrchestrator {
469
469
  restartPromises.push(
470
470
  this._startServerRuntime(name, mainJsPath, { ...this._baseEnv, ...config.env }, clientPorts)
471
471
  .catch((err: unknown) => {
472
- this._logger.error(`[${name}] Error starting Server Runtime:`, errNs.message(err));
472
+ this._logger.error(`[${name}] 서버 런타임 시작 실패:`, errNs.message(err));
473
473
  this._resultCollector.add({
474
474
  name,
475
475
  target: "server",
@@ -519,12 +519,12 @@ export class DevWatchOrchestrator {
519
519
  env?: Record<string, string>,
520
520
  clientPorts?: Record<string, number>,
521
521
  ): Promise<void> {
522
- this._logger.debug(`[${serverName}] _startServerRuntime: ${mainJsPath}`);
522
+ this._logger.debug(`[${serverName}] 서버 런타임 시작: ${mainJsPath}`);
523
523
 
524
524
  // Terminate existing runtime
525
525
  const existingRuntime = this._serverRuntimeWorkers.get(serverName);
526
526
  if (existingRuntime != null) {
527
- this._logger.info(`[${serverName}] Restarting server...`);
527
+ this._logger.info(`[${serverName}] 서버 재시작 중...`);
528
528
  await existingRuntime.terminate();
529
529
  }
530
530
 
@@ -560,7 +560,7 @@ export class DevWatchOrchestrator {
560
560
  runtimeWorker
561
561
  .start({ mainJsPath, clientPorts, env })
562
562
  .catch((err: unknown) => {
563
- this._logger.error(`[${serverName}] Server Runtime Worker crashed:`, errNs.message(err));
563
+ this._logger.error(`[${serverName}] 서버 런타임 워커 비정상 종료:`, errNs.message(err));
564
564
  this._resultCollector.add({
565
565
  name: serverName,
566
566
  target: "server",
@@ -25,7 +25,7 @@ export function printErrors(results: Map<string, BuildResult>): void {
25
25
  if (result.message != null && result.message !== "") {
26
26
  consola.error(formatBuildMessages(result.name, typeLabel, [result.message]));
27
27
  } else {
28
- consola.error(`${result.name} (${typeLabel})`);
28
+ consola.error(`[${result.name}] (${typeLabel}) 실패`);
29
29
  }
30
30
  }
31
31
  }
@@ -113,7 +113,7 @@ export function collectDeps(
113
113
  replaceDepsConfig?: Record<string, string>,
114
114
  ): DepsResult {
115
115
  const startTime = performance.now();
116
- logger.debug("[collectDeps] Starting dependency collection...");
116
+ logger.debug("의존성 수집 시작");
117
117
  const rootPkgJsonPath = path.join(cwd, "package.json");
118
118
  const rootPkgJson = JSON.parse(fs.readFileSync(rootPkgJsonPath, "utf-8")) as { name: string };
119
119
  const scopeMatch = rootPkgJson.name.match(/^(@[^/]+)\//);
@@ -170,7 +170,7 @@ export function collectDeps(
170
170
 
171
171
  traverse(pkgDir);
172
172
  logger.debug(
173
- `[collectDeps] Done: workspace=${String(workspaceDeps.length)}, replace=${String(replaceDeps.length)} (${Math.round(performance.now() - startTime)}ms)`,
173
+ `의존성 수집 완료: workspace=${String(workspaceDeps.length)}, replace=${String(replaceDeps.length)} (${Math.round(performance.now() - startTime)}ms)`,
174
174
  );
175
175
  return { workspaceDeps, replaceDeps };
176
176
  }
@@ -347,7 +347,7 @@ export function classifyDevPackages(
347
347
  serverClientsMap.set(clientConfig.server, clients);
348
348
  } else {
349
349
  process.stdout.write(
350
- `⚠ Client "${name}" server "${clientConfig.server}" not in dev targets running as standalone.\n`,
350
+ `⚠ 클라이언트 "${name}" 서버 "${clientConfig.server}" dev 대상에 없어 독립 실행됩니다.\n`,
351
351
  );
352
352
  }
353
353
  }
@@ -45,7 +45,7 @@ export class RebuildManager extends EventEmitter<RebuildManagerEvents> {
45
45
 
46
46
  const tasks = Array.from(batchBuilds.entries());
47
47
  const titles = tasks.map(([, { title }]) => title).join(", ");
48
- this._logger.start(`Rebuilding... (${titles})`);
48
+ this._logger.start(`리빌드 실행 중... (${titles})`);
49
49
 
50
50
  const results = await Promise.allSettled(tasks.map(([, { promise }]) => promise));
51
51
 
@@ -54,11 +54,11 @@ export class RebuildManager extends EventEmitter<RebuildManagerEvents> {
54
54
  const failed = results.filter((r): r is PromiseRejectedResult => r.status === "rejected");
55
55
  if (failed.length > 0) {
56
56
  for (const result of failed) {
57
- this._logger.error("Error during rebuild", { error: String(result.reason) });
57
+ this._logger.error("리빌드 에러 발생", { error: String(result.reason) });
58
58
  }
59
59
  }
60
60
 
61
- this._logger.success(`Rebuild completed (${titles})`);
61
+ this._logger.success(`리빌드 실행 완료 (${titles})`);
62
62
 
63
63
  this.emit("batchComplete");
64
64
 
@@ -199,7 +199,7 @@ async function resolveAllReplaceDepEntries(
199
199
  try {
200
200
  await fs.promises.access(resolvedSourcePath);
201
201
  } catch {
202
- logger.warn(`Source path does not exist, skipping: ${resolvedSourcePath}`);
202
+ logger.warn(`소스 경로가 존재하지 않아 건너뜀: ${resolvedSourcePath}`);
203
203
  continue;
204
204
  }
205
205
 
@@ -244,7 +244,7 @@ export async function setupReplaceDeps(
244
244
  const logger = consola.withTag("sd:cli:replace-deps");
245
245
  let setupCount = 0;
246
246
 
247
- logger.start("Setting up replace-deps");
247
+ logger.start("replace-deps 설정 중...");
248
248
 
249
249
  const entries = await resolveAllReplaceDepEntries(projectRoot, replaceDeps, logger);
250
250
 
@@ -255,11 +255,11 @@ export async function setupReplaceDeps(
255
255
 
256
256
  setupCount += 1;
257
257
  } catch (err) {
258
- logger.error(`Copy replace failed (${targetName}): ${err instanceof Error ? err.message : err}`);
258
+ logger.error(`[${targetName}] 복사 실패: ${err instanceof Error ? err.message : err}`);
259
259
  }
260
260
  }
261
261
 
262
- logger.success(`Replaced ${setupCount} dependencies`);
262
+ logger.success(`replace-deps 설정 완료 (${setupCount} 의존성 교체)`);
263
263
 
264
264
  // Run postinstall scripts from replaced packages
265
265
  for (const { targetName, resolvedSourcePath, actualTargetPath } of entries) {
@@ -269,13 +269,13 @@ export async function setupReplaceDeps(
269
269
  const postinstall = pkgJson.scripts?.postinstall as string | undefined;
270
270
  if (postinstall == null) continue;
271
271
 
272
- logger.warn(`Running postinstall script for ${targetName}: ${postinstall}`);
273
- logger.start(`Running postinstall for ${targetName}`);
272
+ logger.warn(`[${targetName}] postinstall 스크립트 실행: ${postinstall}`);
273
+ logger.start(`[${targetName}] postinstall 실행 중...`);
274
274
  await promisify(exec)(postinstall, { cwd: actualTargetPath });
275
- logger.success(`postinstall done: ${targetName}`);
275
+ logger.success(`[${targetName}] postinstall 실행 완료`);
276
276
  } catch (err) {
277
277
  logger.error(
278
- `postinstall failed (${targetName}): ${err instanceof Error ? err.message : err}`,
278
+ `[${targetName}] postinstall 실패: ${err instanceof Error ? err.message : err}`,
279
279
  );
280
280
  }
281
281
  }
@@ -305,7 +305,7 @@ export async function watchReplaceDeps(
305
305
  const watchers: FsWatcher[] = [];
306
306
  const watchedSources = new Set<string>();
307
307
 
308
- logger.start(`Watching ${entries.length} replace-deps target(s)`);
308
+ logger.start(`replace-deps 워치 시작 중... (${entries.length} 대상)`);
309
309
 
310
310
  for (const entry of entries) {
311
311
  if (watchedSources.has(entry.resolvedSourcePath)) continue;
@@ -359,7 +359,7 @@ export async function watchReplaceDeps(
359
359
  }
360
360
  } catch (err) {
361
361
  logger.error(
362
- `Copy failed (${e.targetName}/${relativePath}): ${err instanceof Error ? err.message : err}`,
362
+ `[${e.targetName}] 복사 실패 (${relativePath}): ${err instanceof Error ? err.message : err}`,
363
363
  );
364
364
  }
365
365
  }
@@ -369,7 +369,7 @@ export async function watchReplaceDeps(
369
369
  watchers.push(watcher);
370
370
  }
371
371
 
372
- logger.success(`Replace-deps watch ready`);
372
+ logger.success("replace-deps 워치 준비 완료");
373
373
 
374
374
  return {
375
375
  entries,
@@ -33,7 +33,7 @@ export function registerCleanupHandlers(
33
33
  process.exit(0);
34
34
  })
35
35
  .catch((err) => {
36
- logger.error("cleanup failed", err);
36
+ logger.error("정리 작업 실패", err);
37
37
  process.exit(1);
38
38
  });
39
39
  };
@@ -142,7 +142,7 @@ async function cleanup(): Promise<void> {
142
142
  * Uses single-pass dependency tree traversal via collectAllDependencyExternals.
143
143
  */
144
144
  function collectAllExternals(pkgDir: string, manualExternals?: string[]): string[] {
145
- logger.debug("[externals] Scanning dependency tree (single pass)...");
145
+ logger.debug("의존성 트리 스캔 중...");
146
146
  const { optionalPeerDeps, nativeModules } = collectAllDependencyExternals(pkgDir);
147
147
 
148
148
  const manual = manualExternals ?? [];
@@ -638,7 +638,7 @@ async function startWatch(info: ServerWatchInfo): Promise<void> {
638
638
  const result = await rebuildAll();
639
639
  sender.send("build", result);
640
640
  } else {
641
- logger.debug("Changed files not included in build, skipping rebuild");
641
+ logger.debug("변경된 파일이 빌드에 포함되지 않아 리빌드 건너뜀");
642
642
  }
643
643
  } catch (err) {
644
644
  sender.send("error", { message: errNs.message(err) });
@@ -63,7 +63,7 @@ async function cleanup(): Promise<void> {
63
63
  // Catch runtime errors that occur after server listen() and send them as a custom "error" event
64
64
  // (Without this handler, the worker will crash but dev.ts's buildResolver won't be called, causing listr to hang)
65
65
  process.on("uncaughtException", (err) => {
66
- logger.error("Unhandled server runtime error", err);
66
+ logger.error("서버 런타임 미처리 에러", err);
67
67
  sender.send("error", {
68
68
  message: errNs.message(err),
69
69
  });
@@ -72,7 +72,7 @@ process.on("uncaughtException", (err) => {
72
72
  });
73
73
 
74
74
  process.on("unhandledRejection", (reason) => {
75
- logger.error("Unhandled server runtime promise rejection", reason);
75
+ logger.error("서버 런타임 미처리 Promise 거부", reason);
76
76
  sender.send("error", {
77
77
  message: errNs.message(reason),
78
78
  });
@@ -127,10 +127,10 @@ async function start(info: ServerRuntimeStartInfo): Promise<void> {
127
127
  }
128
128
 
129
129
  // Import main.js (must export a server instance)
130
- logger.debug("[start] Importing main.js...");
130
+ logger.debug("main.js 임포트 중...");
131
131
  let stepStart = performance.now();
132
132
  const module = await import(pathToFileURL(info.mainJsPath).href);
133
- logger.debug(`[start] main.js imported (${Math.round(performance.now() - stepStart)}ms)`);
133
+ logger.debug(`main.js 임포트 완료 (${Math.round(performance.now() - stepStart)}ms)`);
134
134
  const server = module.server;
135
135
 
136
136
  if (server == null) {
@@ -143,7 +143,7 @@ async function start(info: ServerRuntimeStartInfo): Promise<void> {
143
143
  // Register client proxies (before listen)
144
144
  if (info.clientPorts != null && Object.keys(info.clientPorts).length > 0) {
145
145
  for (const [name, port] of Object.entries(info.clientPorts)) {
146
- logger.debug(`[start] Registering proxy: /${name} -> http://127.0.0.1:${String(port)}`);
146
+ logger.debug(`프록시 등록: /${name} http://127.0.0.1:${String(port)}`);
147
147
  await server.fastify.register(proxy, {
148
148
  prefix: `/${name}`,
149
149
  upstream: `http://127.0.0.1:${port}`,
@@ -154,31 +154,31 @@ async function start(info: ServerRuntimeStartInfo): Promise<void> {
154
154
  }
155
155
 
156
156
  // Find available port (auto-increment on port conflict)
157
- logger.debug("[start] Finding available port...");
157
+ logger.debug("사용 가능한 포트 탐색 중...");
158
158
  stepStart = performance.now();
159
159
  const originalPort = server.options.port;
160
160
  const availablePort = await findAvailablePort(originalPort);
161
161
  if (availablePort !== originalPort) {
162
- logger.info(`Port ${originalPort} in use, changing to ${availablePort}`);
162
+ logger.info(`포트 ${originalPort} 사용 중, ${availablePort}로 변경`);
163
163
  server.options.port = availablePort;
164
164
  }
165
165
  logger.debug(
166
- `[start] Port ${String(availablePort)} available (${Math.round(performance.now() - stepStart)}ms)`,
166
+ `포트 ${String(availablePort)} 사용 가능 (${Math.round(performance.now() - stepStart)}ms)`,
167
167
  );
168
168
 
169
- // Start server
170
- logger.debug("[start] Starting server listen...");
169
+ // 서버 시작
170
+ logger.debug("서버 리슨 시작...");
171
171
  stepStart = performance.now();
172
172
  await server.listen();
173
- logger.debug(`[start] Server listening (${Math.round(performance.now() - stepStart)}ms)`);
173
+ logger.debug(`서버 리슨 완료 (${Math.round(performance.now() - stepStart)}ms)`);
174
174
 
175
175
  logger.debug(
176
- `[start] Total runtime startup: ${Math.round(performance.now() - startTime)}ms`,
176
+ `런타임 시작 시간: ${Math.round(performance.now() - startTime)}ms`,
177
177
  );
178
178
 
179
179
  sender.send("serverReady", { port: server.options.port });
180
180
  } catch (err) {
181
- logger.error("Server Runtime startup failed", err);
181
+ logger.error("서버 런타임 시작 실패", err);
182
182
  sender.send("error", {
183
183
  message: errNs.message(err),
184
184
  });