@tsed/cli 7.4.0 → 7.5.0-rc.2

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.
@@ -0,0 +1,42 @@
1
+ import { register } from "node:module";
2
+ import { join } from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+ const EXT = process.env.CLI_MODE === "ts" ? "ts" : "js";
5
+ register(pathToFileURL(join(import.meta.dirname, `../loaders/alias.hook.${EXT}`)), {
6
+ parentURL: import.meta.dirname,
7
+ data: {
8
+ "@tsed/core": import.meta.resolve("@tsed/core"),
9
+ "@tsed/di": import.meta.resolve("@tsed/di"),
10
+ "@tsed/schema": import.meta.resolve("@tsed/schema"),
11
+ "@tsed/cli-core": import.meta.resolve("@tsed/cli-core"),
12
+ "@tsed/cli": import.meta.resolve("@tsed/cli")
13
+ },
14
+ transferList: []
15
+ });
16
+ const { tools, commands, resources, CliCore, PKG, TEMPLATE_DIR, ArchitectureConvention, ProjectConvention } = await import("../index.js");
17
+ CliCore.bootstrap({
18
+ name: "tsed",
19
+ pkg: PKG,
20
+ templateDir: TEMPLATE_DIR,
21
+ plugins: true,
22
+ updateNotifier: true,
23
+ checkPrecondition: true,
24
+ commands,
25
+ tools,
26
+ resources,
27
+ defaultProjectPreferences() {
28
+ return {
29
+ convention: ProjectConvention.DEFAULT,
30
+ architecture: ArchitectureConvention.DEFAULT
31
+ };
32
+ },
33
+ project: {
34
+ reinstallAfterRun: true
35
+ },
36
+ logger: {
37
+ level: "info"
38
+ }
39
+ }).catch((error) => {
40
+ console.error(error);
41
+ process.exit(-1);
42
+ });
@@ -0,0 +1,23 @@
1
+ import { spawn } from "node:child_process";
2
+ import process from "node:process";
3
+ import { fileURLToPath } from "node:url";
4
+ function runNode(cmd, args) {
5
+ return new Promise((resolve, reject) => {
6
+ const child = spawn(cmd, args, {
7
+ env: process.env,
8
+ stdio: "inherit"
9
+ });
10
+ child.on("error", reject);
11
+ child.on("exit", (code) => {
12
+ if (code === 0) {
13
+ resolve();
14
+ return;
15
+ }
16
+ reject(new Error(`vite build exited with code ${code}`));
17
+ });
18
+ });
19
+ }
20
+ export async function build(rawArgs = process.argv.slice(2)) {
21
+ const viteBin = fileURLToPath(import.meta.resolve("vite/bin/vite.js"));
22
+ await runNode(process.execPath, [viteBin, "build", ...rawArgs]);
23
+ }
@@ -0,0 +1,130 @@
1
+ import { spawn } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import process from "node:process";
4
+ import { fileURLToPath } from "node:url";
5
+ import { normalizePath } from "@tsed/cli-core";
6
+ import { logger } from "@tsed/di";
7
+ const RUN_MODE = "TSED_VITE_RUN_MODE";
8
+ function parseWatchValue(args) {
9
+ if (args.includes("--no-watch")) {
10
+ return false;
11
+ }
12
+ const watchIndex = args.findIndex((arg) => arg === "--watch" || arg.startsWith("--watch="));
13
+ if (watchIndex === -1) {
14
+ return true;
15
+ }
16
+ const watchArg = args[watchIndex];
17
+ if (watchArg === "--watch") {
18
+ const nextValue = args[watchIndex + 1];
19
+ if (!nextValue || nextValue.startsWith("-")) {
20
+ return true;
21
+ }
22
+ return nextValue !== "false";
23
+ }
24
+ if (watchArg === "--watch=false") {
25
+ return false;
26
+ }
27
+ if (watchArg === "--watch=true") {
28
+ return true;
29
+ }
30
+ return true;
31
+ }
32
+ function assertViteProject() {
33
+ const configFile = normalizePath("vite.config.ts");
34
+ if (!existsSync(configFile)) {
35
+ throw new Error("tsed dev is only available for ViteRuntime projects. Missing vite.config.ts in the current directory.");
36
+ }
37
+ }
38
+ async function createViteDevServer() {
39
+ // @ts-ignore
40
+ const { createServer } = await import("vite");
41
+ return createServer({
42
+ configFile: normalizePath("vite.config.ts"),
43
+ server: {
44
+ middlewareMode: true,
45
+ hmr: false,
46
+ ws: false
47
+ }
48
+ });
49
+ }
50
+ async function runViteApp() {
51
+ const vite = await createViteDevServer();
52
+ const shutdown = async () => {
53
+ await vite.close();
54
+ process.exit(0);
55
+ };
56
+ process.on("SIGINT", shutdown);
57
+ process.on("SIGTERM", shutdown);
58
+ await vite.ssrLoadModule("/src/index.ts");
59
+ await new Promise(() => { });
60
+ }
61
+ async function runViteController(rawArgs) {
62
+ const runnerFile = fileURLToPath(import.meta.url);
63
+ const watch = parseWatchValue(rawArgs);
64
+ const vite = await createViteDevServer();
65
+ let childProcess;
66
+ let restarting = false;
67
+ let queued = false;
68
+ const startChild = () => {
69
+ childProcess = spawn(process.execPath, [runnerFile, ...rawArgs], {
70
+ env: {
71
+ ...process.env,
72
+ [RUN_MODE]: "app"
73
+ },
74
+ stdio: "inherit"
75
+ });
76
+ };
77
+ const stopChild = async () => {
78
+ if (!childProcess || childProcess.killed) {
79
+ return;
80
+ }
81
+ await new Promise((resolve) => {
82
+ childProcess.once("exit", resolve);
83
+ childProcess.kill("SIGTERM");
84
+ });
85
+ };
86
+ const restartChild = async (reason, file = "") => {
87
+ if (restarting) {
88
+ queued = true;
89
+ return;
90
+ }
91
+ restarting = true;
92
+ const suffix = file ? `: ${file}` : "";
93
+ logger().info(`[tsed-dev] restart (${reason})${suffix}`);
94
+ await stopChild();
95
+ startChild();
96
+ restarting = false;
97
+ if (queued) {
98
+ queued = false;
99
+ await restartChild("queued");
100
+ }
101
+ };
102
+ if (watch) {
103
+ vite.watcher.on("all", async (event, file) => {
104
+ if (!file || file.includes("node_modules") || file.includes(".git") || file.includes("/dist/")) {
105
+ return;
106
+ }
107
+ if (["add", "change", "unlink"].includes(event)) {
108
+ await restartChild(event, file);
109
+ }
110
+ });
111
+ }
112
+ vite.watcher.once("ready", () => {
113
+ startChild();
114
+ });
115
+ const shutdown = async () => {
116
+ await stopChild();
117
+ await vite.close();
118
+ process.exit(0);
119
+ };
120
+ process.on("SIGINT", shutdown);
121
+ process.on("SIGTERM", shutdown);
122
+ await new Promise(() => { });
123
+ }
124
+ export async function dev(rawArgs = process.argv.slice(2)) {
125
+ if (process.env[RUN_MODE] === "app") {
126
+ await runViteApp();
127
+ return;
128
+ }
129
+ await runViteController(rawArgs);
130
+ }
@@ -1,44 +1,32 @@
1
1
  #!/usr/bin/env node
2
- import "./ts-mode.js";
3
- import { register } from "node:module";
4
- import { join } from "node:path";
5
- import { pathToFileURL } from "node:url";
6
2
  const EXT = process.env.CLI_MODE === "ts" ? "ts" : "js";
7
- register(pathToFileURL(join(import.meta.dirname, `../loaders/alias.hook.${EXT}`)), {
8
- parentURL: import.meta.dirname,
9
- data: {
10
- "@tsed/core": import.meta.resolve("@tsed/core"),
11
- "@tsed/di": import.meta.resolve("@tsed/di"),
12
- "@tsed/schema": import.meta.resolve("@tsed/schema"),
13
- "@tsed/cli-core": import.meta.resolve("@tsed/cli-core"),
14
- "@tsed/cli": import.meta.resolve("@tsed/cli")
15
- },
16
- transferList: []
17
- });
18
- const { tools, commands, resources, CliCore, PKG, TEMPLATE_DIR, ArchitectureConvention, ProjectConvention } = await import("../index.js");
19
- CliCore.bootstrap({
20
- name: "tsed",
21
- pkg: PKG,
22
- templateDir: TEMPLATE_DIR,
23
- plugins: true,
24
- updateNotifier: true,
25
- checkPrecondition: true,
26
- commands,
27
- tools,
28
- resources,
29
- defaultProjectPreferences() {
30
- return {
31
- convention: ProjectConvention.DEFAULT,
32
- architecture: ArchitectureConvention.DEFAULT
33
- };
34
- },
35
- project: {
36
- reinstallAfterRun: true
37
- },
38
- logger: {
39
- level: "info"
40
- }
41
- }).catch((error) => {
42
- console.error(error);
43
- process.exit(-1);
44
- });
3
+ const [, , commandName, ...rawArgs] = process.argv;
4
+ switch (commandName) {
5
+ case "dev":
6
+ try {
7
+ const { dev } = await import("./tsed-dev.js");
8
+ await dev(rawArgs);
9
+ process.exit(0);
10
+ }
11
+ catch (error) {
12
+ console.error(error);
13
+ process.exit(1);
14
+ }
15
+ break;
16
+ case "build":
17
+ try {
18
+ const { build } = await import("./tsed-build.js");
19
+ await build(rawArgs);
20
+ process.exit(0);
21
+ }
22
+ catch (error) {
23
+ console.error(error);
24
+ process.exit(1);
25
+ }
26
+ break;
27
+ default:
28
+ await import("./ts-mode.js");
29
+ await import(`./boot.${EXT}`);
30
+ break;
31
+ }
32
+ export {};
@@ -14,6 +14,7 @@ import { PlatformsModule } from "../../platforms/PlatformsModule.js";
14
14
  import { RuntimesModule } from "../../runtimes/RuntimesModule.js";
15
15
  import { BunRuntime } from "../../runtimes/supports/BunRuntime.js";
16
16
  import { NodeRuntime } from "../../runtimes/supports/NodeRuntime.js";
17
+ import { ViteRuntime } from "../../runtimes/supports/ViteRuntime.js";
17
18
  import { CliProjectService } from "../../services/CliProjectService.js";
18
19
  import { anonymizePaths } from "../../services/mappers/anonymizePaths.js";
19
20
  import { FeaturesMap, FeatureType } from "./config/FeaturesPrompt.js";
@@ -143,7 +144,8 @@ export class InitCmd {
143
144
  ...ctx,
144
145
  node: runtime instanceof NodeRuntime,
145
146
  bun: runtime instanceof BunRuntime,
146
- compiled: runtime instanceof NodeRuntime && runtime.isCompiled()
147
+ vite: runtime instanceof ViteRuntime,
148
+ compiled: runtime.isCompiled()
147
149
  };
148
150
  return [
149
151
  {
@@ -329,6 +329,10 @@ export const FeaturesMap = {
329
329
  [FeatureType.LINT_STAGED]: {
330
330
  name: "Lint on commit"
331
331
  },
332
+ vite: {
333
+ name: "Node.js + Vite",
334
+ checked: false
335
+ },
332
336
  node: {
333
337
  name: "Node.js + SWC",
334
338
  checked: true
@@ -345,17 +349,17 @@ export const FeaturesMap = {
345
349
  name: "Bun.js",
346
350
  checked: false
347
351
  },
348
- yarn: {
349
- name: "Yarn",
350
- checked: true
352
+ npm: {
353
+ name: "NPM",
354
+ checked: false
351
355
  },
352
356
  yarn_berry: {
353
357
  name: "Yarn Berry",
354
358
  checked: false
355
359
  },
356
- npm: {
357
- name: "NPM",
358
- checked: false
360
+ yarn: {
361
+ name: "Yarn",
362
+ checked: true
359
363
  },
360
364
  pnpm: {
361
365
  name: "PNPM",
@@ -512,7 +516,7 @@ export const FeaturesPrompt = (availableRuntimes, availablePackageManagers) => [
512
516
  message: "Choose the package manager:",
513
517
  type: "list",
514
518
  name: "packageManager",
515
- when: hasValue("runtime", ["node", "babel", "swc", "webpack"]),
519
+ when: hasValue("runtime", ["vite", "node", "babel", "swc", "webpack"]),
516
520
  choices: availablePackageManagers
517
521
  }
518
522
  ];
@@ -274,6 +274,10 @@ export const InitSchema = () => {
274
274
  .enums(availableRuntimes)
275
275
  .prompt("Choose the runtime:")
276
276
  .choices([
277
+ {
278
+ label: "Node.js + Vite",
279
+ value: "vite"
280
+ },
277
281
  {
278
282
  label: "Node.js + SWC",
279
283
  value: "node"
@@ -2,9 +2,13 @@ import { cleanObject, isFunction } from "@tsed/core";
2
2
  import { FeaturesMap, FeaturesPrompt } from "../config/FeaturesPrompt.js";
3
3
  function mapChoices(item, options) {
4
4
  return item.choices.map((choice) => {
5
- const { checked } = FeaturesMap[choice];
5
+ const config = FeaturesMap[choice];
6
+ if (!config) {
7
+ throw new Error(`Unknown init prompt choice "${choice}" for prompt "${item.name}"`);
8
+ }
9
+ const { checked } = config;
6
10
  return cleanObject({
7
- ...FeaturesMap[choice],
11
+ ...config,
8
12
  value: choice,
9
13
  checked: isFunction(checked) ? checked(options) : checked
10
14
  });
@@ -8,8 +8,8 @@ export const ProjectPreferenceSchema = s
8
8
  packageManager: s.string().enum(PackageManager).description("Used project manager to install dependencies"),
9
9
  runtime: s
10
10
  .string()
11
- .enum("node", "babel", "swc", "webpack", "bun")
12
- .description("The javascript runtime used to start application (node, node + webpack, node + swc, node + babel, bun)"),
11
+ .enum("vite", "node", "babel", "swc", "webpack", "bun")
12
+ .description("The javascript runtime used to start application (node, node + webpack, node + swc, node + babel, bun, vite)"),
13
13
  platform: s.string().enum(PlatformType).description("Node.js framework used to run server (Express, Koa, Fastify)")
14
14
  })
15
15
  .optional()
@@ -1,6 +1,5 @@
1
1
  import { CliFs, command, inject, normalizePath, ProjectPackageJson } from "@tsed/cli-core";
2
2
  import { taskLogger } from "@tsed/cli-tasks";
3
- import { logger } from "@tsed/di";
4
3
  import { CliRunScript } from "../../services/CliRunScript.js";
5
4
  export class RunCmd {
6
5
  constructor() {
@@ -4,6 +4,7 @@ import { BabelRuntime } from "./supports/BabelRuntime.js";
4
4
  import { BaseRuntime } from "./supports/BaseRuntime.js";
5
5
  import { BunRuntime } from "./supports/BunRuntime.js";
6
6
  import { NodeRuntime } from "./supports/NodeRuntime.js";
7
+ import { ViteRuntime } from "./supports/ViteRuntime.js";
7
8
  import { WebpackRuntime } from "./supports/WebpackRuntime.js";
8
9
  export class RuntimesModule {
9
10
  constructor() {
@@ -41,4 +42,4 @@ export class RuntimesModule {
41
42
  };
42
43
  }
43
44
  }
44
- injectable(RuntimesModule).imports([NodeRuntime, BabelRuntime, WebpackRuntime, BunRuntime]);
45
+ injectable(RuntimesModule).imports([ViteRuntime, NodeRuntime, BabelRuntime, WebpackRuntime, BunRuntime]);
@@ -3,4 +3,5 @@ export * from "./supports/BabelRuntime.js";
3
3
  export * from "./supports/BaseRuntime.js";
4
4
  export * from "./supports/BunRuntime.js";
5
5
  export * from "./supports/NodeRuntime.js";
6
+ export * from "./supports/ViteRuntime.js";
6
7
  export * from "./supports/WebpackRuntime.js";
@@ -0,0 +1,30 @@
1
+ import { injectable } from "@tsed/di";
2
+ import { BaseRuntime } from "./BaseRuntime.js";
3
+ export class ViteRuntime extends BaseRuntime {
4
+ constructor() {
5
+ super(...arguments);
6
+ this.name = "vite";
7
+ this.cmd = "node";
8
+ this.order = -1;
9
+ }
10
+ files() {
11
+ return ["vite.config.ts"];
12
+ }
13
+ compile() {
14
+ return "tsed build";
15
+ }
16
+ startDev() {
17
+ return "tsed dev";
18
+ }
19
+ startProd(args) {
20
+ return `node ${args}`;
21
+ }
22
+ devDependencies() {
23
+ return {
24
+ "@tsed/cli": "{{cliVersion}}",
25
+ typescript: "latest",
26
+ vite: "latest"
27
+ };
28
+ }
29
+ }
30
+ injectable(ViteRuntime).type("runtime");