@konomi-app/k2 2.1.5 → 3.0.1

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 CHANGED
@@ -1,123 +1,47 @@
1
1
  #!/usr/bin/env node
2
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
3
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
4
+ }) : x)(function(x) {
5
+ if (typeof require !== "undefined") return require.apply(this, arguments);
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
+ });
2
8
 
3
9
  // src/index.ts
4
10
  import { program as program6 } from "commander";
5
11
 
6
12
  // src/commands/build.ts
7
13
  import { program } from "commander";
8
- import fs2 from "fs-extra";
14
+ import fs3 from "fs-extra";
9
15
  import path6 from "path";
16
+ import chalk2 from "chalk";
10
17
 
11
18
  // src/lib/constants.ts
12
19
  import path from "path";
13
20
  var WORKSPACE_DIRECTORY = ".k2";
14
21
  var DEVELOPMENT_DIRECTORY = path.join(WORKSPACE_DIRECTORY, "dev");
22
+ var PRODUCTION_DIRECTORY = path.join(WORKSPACE_DIRECTORY, "prod");
15
23
  var CONFIG_FILE_NAME = "k2.config.mjs";
16
24
  var PLUGIN_WORKSPACE_DIRECTORY = ".plugin";
17
25
  var PLUGIN_CONTENTS_DIRECTORY = path.join(PLUGIN_WORKSPACE_DIRECTORY, "contents");
18
26
  var PLUGIN_DEVELOPMENT_DIRECTORY = path.join(PLUGIN_WORKSPACE_DIRECTORY, "dev");
27
+ var PLUGIN_PRODUCTION_DIRECTORY = path.join(PLUGIN_WORKSPACE_DIRECTORY, "prod");
19
28
  var DEFAULT_PORT = 32767;
20
29
 
21
- // src/commands/build-base.ts
22
- import "webpack";
23
-
24
- // src/lib/webpack.ts
25
- import MiniCssExtractPlugin from "mini-css-extract-plugin";
26
- import path2 from "path";
27
- import { cwd } from "process";
28
- import TerserPlugin from "terser-webpack-plugin";
29
- import webpack from "webpack";
30
- import chalk from "chalk";
31
- import { TsconfigPathsPlugin } from "tsconfig-paths-webpack-plugin";
32
- var buildWithWebpack = async (props) => {
33
- const { entries, outDir } = props;
34
- const exclude = /node_modules/;
35
- const styleLoader = MiniCssExtractPlugin.loader;
36
- const tsConfigPath = path2.join(cwd(), "tsconfig.json");
37
- console.group(chalk.blue("\u{1F680} Building with Webpack..."));
38
- console.log("\u{1F527} tsconfig.json path:", tsConfigPath);
39
- console.groupEnd();
40
- return new Promise((resolve, reject) => {
41
- webpack(
42
- {
43
- mode: "production",
44
- target: ["web", "es2023"],
45
- entry: entries,
46
- resolve: {
47
- extensions: [".ts", ".tsx", ".js", ".json"],
48
- fallback: {
49
- path: false
50
- },
51
- plugins: [new TsconfigPathsPlugin({ configFile: tsConfigPath })]
52
- },
53
- cache: { type: "filesystem" },
54
- output: { filename: "[name].js", path: path2.resolve(outDir) },
55
- module: {
56
- rules: [
57
- { test: /\.tsx?$/, exclude, loader: "ts-loader" },
58
- { test: /\.css$/, use: [styleLoader, "css-loader"] },
59
- {
60
- test: /\.scss$/,
61
- use: [
62
- styleLoader,
63
- "css-loader",
64
- { loader: "sass-loader", options: { sassOptions: { outputStyle: "expanded" } } }
65
- ]
66
- }
67
- ]
68
- },
69
- plugins: [new MiniCssExtractPlugin()],
70
- optimization: {
71
- minimize: true,
72
- minimizer: [
73
- new TerserPlugin({
74
- terserOptions: { format: { comments: false } },
75
- extractComments: false
76
- })
77
- ]
78
- }
79
- },
80
- (err, stats) => {
81
- if (err) {
82
- reject(err);
83
- } else {
84
- if (stats?.compilation.errors.length) {
85
- reject(
86
- [
87
- chalk.red("\u26A0 Build failed."),
88
- ...stats.compilation.errors.map((error) => error.message)
89
- ].join("\n")
90
- );
91
- } else {
92
- resolve();
93
- }
94
- }
95
- }
96
- );
97
- });
98
- };
99
-
100
- // src/commands/build-base.ts
101
- async function action(params) {
102
- const { entries, outDir } = params;
103
- return buildWithWebpack({ entries, outDir });
104
- }
105
-
106
30
  // src/commands/build-tailwind.ts
107
- import path5 from "path";
31
+ import path4 from "path";
108
32
 
109
33
  // src/lib/import.ts
110
34
  import { pathToFileURL } from "url";
111
- import path3 from "path";
112
- var esmImport = (path12) => {
35
+ import path2 from "path";
36
+ var esmImport = (path11) => {
113
37
  if (process.platform === "win32") {
114
- return import(pathToFileURL(path12).toString());
38
+ return import(pathToFileURL(path11).toString());
115
39
  } else {
116
- return import(path12);
40
+ return import(path11);
117
41
  }
118
42
  };
119
43
  var importK2Config = async (configFileName) => {
120
- return (await esmImport(path3.resolve(configFileName ?? CONFIG_FILE_NAME))).default;
44
+ return (await esmImport(path2.resolve(configFileName ?? CONFIG_FILE_NAME))).default;
121
45
  };
122
46
 
123
47
  // src/lib/tailwind.ts
@@ -125,14 +49,14 @@ import chokidar from "chokidar";
125
49
  import cssnanoPlugin from "cssnano";
126
50
  import fs from "fs-extra";
127
51
  import { glob } from "glob";
128
- import path4 from "path";
52
+ import path3 from "path";
129
53
  import postcss from "postcss";
130
54
  import { debounce } from "remeda";
131
55
  import tailwindcss from "tailwindcss";
132
56
  import invariant from "tiny-invariant";
133
57
  var getTailwindConfigFromK2Config = async (k2Config) => {
134
58
  invariant(k2Config?.config, "tailwind.config is required");
135
- const config = (await esmImport(path4.resolve(k2Config?.config))).default;
59
+ const config = (await esmImport(path3.resolve(k2Config?.config))).default;
136
60
  return config;
137
61
  };
138
62
  var outputCss = async (params) => {
@@ -177,16 +101,16 @@ var watchTailwindCSS = async (params) => {
177
101
  watcher.on("error", (error) => {
178
102
  console.error("Error watching Tailwind CSS:", error);
179
103
  });
180
- watcher.on("add", (path12) => {
104
+ watcher.on("add", (path11) => {
181
105
  debouncedProcessChanges.call("add");
182
106
  });
183
- watcher.on("change", (path12) => {
107
+ watcher.on("change", (path11) => {
184
108
  debouncedProcessChanges.call("change");
185
109
  });
186
- watcher.on("unlink", (path12) => {
110
+ watcher.on("unlink", (path11) => {
187
111
  debouncedProcessChanges.call("unlink");
188
112
  });
189
- watcher.on("unlinkDir", (path12) => {
113
+ watcher.on("unlinkDir", (path11) => {
190
114
  debouncedProcessChanges.call("unlink");
191
115
  });
192
116
  return watcher;
@@ -197,12 +121,12 @@ var buildTailwind = async (config) => {
197
121
  if (!config.tailwind?.css || !config.tailwind?.config) {
198
122
  return;
199
123
  }
200
- const tailwindConfig = (await esmImport(path5.resolve(config.tailwind.config))).default;
201
- const inputPath = path5.resolve(config.tailwind.css);
124
+ const tailwindConfig = (await esmImport(path4.resolve(config.tailwind.config))).default;
125
+ const inputPath = path4.resolve(config.tailwind.css);
202
126
  const fileName = config.tailwind.fileName ?? "tailwind.css";
203
127
  await outputCss({
204
128
  inputPath,
205
- outputPath: path5.join(config.outDir, fileName),
129
+ outputPath: path4.join(config.outDir, fileName),
206
130
  config: tailwindConfig,
207
131
  minify: true
208
132
  });
@@ -219,28 +143,140 @@ var getDefaultK2Config = () => {
219
143
  };
220
144
  };
221
145
 
146
+ // src/lib/vite.ts
147
+ import path5 from "path";
148
+ import fs2 from "fs-extra";
149
+ import { build as viteBuild } from "vite";
150
+ import chalk from "chalk";
151
+ var createViteConfig = (config = {}) => {
152
+ const plugins = [...config.plugins ?? []];
153
+ try {
154
+ const tsconfigPaths = __require("vite-tsconfig-paths");
155
+ plugins.push(tsconfigPaths.default ? tsconfigPaths.default() : tsconfigPaths());
156
+ } catch {
157
+ }
158
+ const mode = config.mode ?? "production";
159
+ return {
160
+ ...config,
161
+ configFile: false,
162
+ // ブラウザ向けにNode.js固有のオブジェクトをビルド時に解決
163
+ define: {
164
+ "process.env.NODE_ENV": JSON.stringify(mode),
165
+ "process.env": JSON.stringify({}),
166
+ ...config.define
167
+ },
168
+ build: {
169
+ ...config.build,
170
+ // ブラウザ向けターゲット
171
+ target: config.build?.target ?? "es2020",
172
+ cssCodeSplit: false,
173
+ rollupOptions: {
174
+ ...config.build?.rollupOptions,
175
+ onwarn: (warning, warn) => {
176
+ if (["MODULE_LEVEL_DIRECTIVE"].includes(warning.code ?? "")) {
177
+ return;
178
+ }
179
+ warn(warning);
180
+ }
181
+ }
182
+ },
183
+ plugins,
184
+ resolve: {
185
+ ...config.resolve,
186
+ alias: {
187
+ "@": path5.resolve(process.cwd(), "src"),
188
+ ...config.resolve?.alias
189
+ }
190
+ }
191
+ };
192
+ };
193
+ async function buildEntriesWithVite(params) {
194
+ const {
195
+ entries,
196
+ outDir,
197
+ mode = "production",
198
+ sourcemap = false,
199
+ minify = true,
200
+ viteConfig = {}
201
+ } = params;
202
+ for (const name of Object.keys(entries)) {
203
+ const entryPath = entries[name];
204
+ const config = createViteConfig({
205
+ ...viteConfig,
206
+ mode,
207
+ build: {
208
+ ...viteConfig.build,
209
+ lib: {
210
+ entry: entryPath,
211
+ name,
212
+ fileName: () => `${name}.js`,
213
+ formats: ["iife"]
214
+ },
215
+ rollupOptions: {
216
+ ...viteConfig.build?.rollupOptions,
217
+ output: {
218
+ assetFileNames: `${name}.[ext]`,
219
+ ...viteConfig.build?.rollupOptions?.output
220
+ }
221
+ },
222
+ outDir,
223
+ emptyOutDir: false,
224
+ sourcemap,
225
+ minify,
226
+ cssCodeSplit: false
227
+ }
228
+ });
229
+ await viteBuild(config);
230
+ }
231
+ }
232
+ var ENTRY_FILE_NAMES = ["index.ts", "index.tsx", "index.js", "index.jsx", "index.mjs"];
233
+ function getEntryPointsFromDir(inputDir) {
234
+ const entries = {};
235
+ if (!fs2.existsSync(inputDir)) {
236
+ throw new Error(`Input directory not found: ${inputDir}`);
237
+ }
238
+ const dirs = fs2.readdirSync(inputDir, { withFileTypes: true });
239
+ for (const dirent of dirs) {
240
+ if (!dirent.isDirectory()) continue;
241
+ const dirName = dirent.name;
242
+ const dirPath = path5.join(inputDir, dirName);
243
+ for (const filename of ENTRY_FILE_NAMES) {
244
+ const entryPath = path5.join(dirPath, filename);
245
+ if (fs2.existsSync(entryPath)) {
246
+ entries[dirName] = entryPath;
247
+ break;
248
+ }
249
+ }
250
+ }
251
+ return entries;
252
+ }
253
+
222
254
  // src/commands/build.ts
223
255
  function command() {
224
- program.command("build").option("-o, --outdir <outdir>", "Output directory.", path6.join(WORKSPACE_DIRECTORY, "prod")).option("-i, --input <input>", "Input directory.", path6.join("src", "apps")).option("--config <config>", "k2 config file path").description("Build the project for production. (It's a wrapper of webpack build command.)").action(action2);
256
+ program.command("build").option("-o, --outdir <outdir>", "Output directory.", path6.join(WORKSPACE_DIRECTORY, "prod")).option("-i, --input <input>", "Input directory.", path6.join("src", "apps")).option("--config <config>", "k2 config file path").description("Build the project for production with Vite.").action(action);
225
257
  }
226
- async function action2(options) {
258
+ async function action(options) {
227
259
  console.group("\u{1F373} Build the project for production");
228
260
  try {
229
261
  const { outdir, input, config } = options;
230
262
  const outDir = path6.resolve(outdir);
231
- const allProjects = fs2.readdirSync(path6.resolve(input));
232
- const entries = allProjects.reduce((acc, dir) => {
233
- for (const filename of ["index.ts", "index.js", "index.mjs"]) {
234
- if (fs2.existsSync(path6.join(input, dir, filename))) {
235
- return { ...acc, [dir]: path6.join(input, dir, filename) };
236
- }
237
- }
238
- return acc;
239
- }, {});
263
+ const entries = getEntryPointsFromDir(path6.resolve(input));
264
+ const entryNames = Object.keys(entries);
265
+ if (entryNames.length === 0) {
266
+ throw new Error(`No entry points found in ${input}`);
267
+ }
268
+ console.log(chalk2.gray(` Entry points: ${entryNames.join(", ")}`));
240
269
  const k2Config = config ? await importK2Config(config) : getDefaultK2Config();
241
270
  const fullConfig = { ...k2Config, outDir };
271
+ await fs3.emptyDir(outDir);
242
272
  const results = await Promise.allSettled([
243
- action({ entries, outDir }),
273
+ buildEntriesWithVite({
274
+ entries,
275
+ outDir,
276
+ mode: "production",
277
+ sourcemap: false,
278
+ minify: true
279
+ }),
244
280
  buildTailwind(fullConfig)
245
281
  ]);
246
282
  for (const result of results) {
@@ -258,75 +294,15 @@ async function action2(options) {
258
294
 
259
295
  // src/commands/dev/index.ts
260
296
  import { program as program2 } from "commander";
261
- import "esbuild";
262
- import fs4 from "fs-extra";
297
+ import { createServer } from "vite";
298
+ import fs6 from "fs-extra";
263
299
  import path9 from "path";
264
-
265
- // src/commands/dev-base-esbuild.ts
266
- import "esbuild";
267
- import path7 from "path";
268
-
269
- // src/lib/esbuild.ts
270
- import chalk2 from "chalk";
271
- import esbuild from "esbuild";
272
- var completeBuildOptions = (params) => {
273
- return {
274
- bundle: true,
275
- platform: "browser",
276
- ...params,
277
- plugins: [...params.plugins ?? []]
278
- };
279
- };
280
- var completeDevBuildOptions = (params) => {
281
- return completeBuildOptions({
282
- ...params,
283
- plugins: [
284
- ...params.plugins ?? [],
285
- {
286
- name: "on-end",
287
- setup: ({ onEnd }) => onEnd(
288
- () => console.log(
289
- chalk2.hex("#e5e7eb")(`${(/* @__PURE__ */ new Date()).toLocaleTimeString()} `) + chalk2.cyan(`[js] `) + `rebuilt`
290
- )
291
- )
292
- }
293
- ]
294
- });
295
- };
296
- var getEsbuildContext = async (params) => {
297
- return esbuild.context(completeDevBuildOptions(params));
298
- };
299
- var buildWithEsbuild = async (params) => {
300
- const { watch = false, ...rest } = params;
301
- if (watch) {
302
- const context = await getEsbuildContext(rest);
303
- context.watch();
304
- } else {
305
- const options = completeBuildOptions(rest);
306
- await esbuild.build(options);
307
- }
308
- };
309
-
310
- // src/commands/dev-base-esbuild.ts
311
- async function action3(params) {
312
- const { entryPoints, staticDir: outdir, certDir, port } = params;
313
- const context = await getEsbuildContext({ sourcemap: "inline", entryPoints, outdir });
314
- const [_, serveResult] = await Promise.all([
315
- context.watch(),
316
- context.serve({
317
- port,
318
- keyfile: path7.join(certDir, "localhost-key.pem"),
319
- certfile: path7.join(certDir, "localhost-cert.pem"),
320
- servedir: outdir
321
- })
322
- ]);
323
- console.log(`\u{1F680} Start development server at https://localhost:${serveResult.port}`);
324
- }
300
+ import chalk4 from "chalk";
325
301
 
326
302
  // src/commands/dev/tailwind.ts
327
- import path8 from "path";
303
+ import path7 from "path";
328
304
  import chalk3 from "chalk";
329
- import fs3 from "fs-extra";
305
+ import fs4 from "fs-extra";
330
306
  var watchCss = async (params) => {
331
307
  const { k2Config, outdir } = params;
332
308
  if (!k2Config.tailwind?.css || !k2Config.tailwind?.config) {
@@ -334,17 +310,17 @@ var watchCss = async (params) => {
334
310
  return;
335
311
  }
336
312
  const tailwindConfig = await getTailwindConfigFromK2Config(k2Config.tailwind);
337
- const input = path8.resolve(k2Config.tailwind.css);
338
- const output = path8.join(outdir, "tailwind.css");
339
- if (!await fs3.pathExists(output)) {
340
- await fs3.outputFile(output, "");
313
+ const input = path7.resolve(k2Config.tailwind.css);
314
+ const output = path7.join(outdir, "tailwind.css");
315
+ if (!await fs4.pathExists(output)) {
316
+ await fs4.outputFile(output, "");
341
317
  }
342
318
  return watchTailwindCSS({
343
319
  input,
344
- output: path8.join(outdir, "tailwind.css"),
320
+ output: path7.join(outdir, "tailwind.css"),
345
321
  config: tailwindConfig,
346
322
  onChanges: ({ output: output2, type }) => {
347
- const outputFileName = path8.basename(output2);
323
+ const outputFileName = path7.basename(output2);
348
324
  console.log(
349
325
  chalk3.hex("#e5e7eb")(`${(/* @__PURE__ */ new Date()).toLocaleTimeString()} `) + chalk3.cyan(`[css] `) + outputFileName + (type === "init" ? " init" : ` rebuilt(${type})`)
350
326
  );
@@ -352,11 +328,46 @@ var watchCss = async (params) => {
352
328
  });
353
329
  };
354
330
 
331
+ // src/lib/exec.ts
332
+ import { exec as defaultExec } from "child_process";
333
+ import { promisify } from "util";
334
+ var exec = promisify(defaultExec);
335
+
336
+ // src/lib/cert.ts
337
+ import fs5 from "fs-extra";
338
+ import path8 from "path";
339
+ var CERT_KEY_FILENAME = "localhost-key.pem";
340
+ var CERT_FILENAME = "localhost-cert.pem";
341
+ var generateCert = async (outDir) => {
342
+ await fs5.ensureDir(outDir);
343
+ const { stdout } = await exec(`mkcert localhost 127.0.0.1 ::1`);
344
+ [
345
+ { input: "localhost+2.pem", output: CERT_FILENAME },
346
+ { input: "localhost+2-key.pem", output: CERT_KEY_FILENAME }
347
+ ].forEach(({ input, output }) => {
348
+ if (fs5.existsSync(input)) {
349
+ fs5.moveSync(`./${input}`, path8.join(outDir, output), {
350
+ overwrite: true
351
+ });
352
+ }
353
+ });
354
+ return { stdout };
355
+ };
356
+ function hasCertificates(certDir) {
357
+ return fs5.existsSync(path8.join(certDir, CERT_KEY_FILENAME)) && fs5.existsSync(path8.join(certDir, CERT_FILENAME));
358
+ }
359
+ function loadCertificates(certDir) {
360
+ return {
361
+ key: fs5.readFileSync(path8.join(certDir, CERT_KEY_FILENAME)),
362
+ cert: fs5.readFileSync(path8.join(certDir, CERT_FILENAME))
363
+ };
364
+ }
365
+
355
366
  // src/commands/dev/index.ts
356
367
  function command2() {
357
- program2.command("dev").description("Start development server.").option("-i, --input <input>", "Input directory", "src/apps").option("-o, --outdir <outdir>", "Output directory.", DEVELOPMENT_DIRECTORY).option("-c, --certdir <certdir>", "Certificate directory", WORKSPACE_DIRECTORY).option("--config <config>", "k2 config file path").option("-p, --port <port>", "Port number").action(action4);
368
+ program2.command("dev").description("Start development server with Vite.").option("-i, --input <input>", "Input directory", "src/apps").option("-o, --outdir <outdir>", "Output directory.", DEVELOPMENT_DIRECTORY).option("-c, --certdir <certdir>", "Certificate directory", WORKSPACE_DIRECTORY).option("--config <config>", "k2 config file path").option("-p, --port <port>", "Port number").action(action2);
358
369
  }
359
- async function action4(options) {
370
+ async function action2(options) {
360
371
  const { certdir, outdir, config, port: specifiedPort, input } = options;
361
372
  console.group("\u{1F373} Start development server");
362
373
  try {
@@ -369,60 +380,85 @@ async function action4(options) {
369
380
  console.log(`\u2699 ${CONFIG_FILE_NAME} not found. use default settings.`);
370
381
  }
371
382
  const port = Number(specifiedPort ?? k2Config?.server?.port ?? DEFAULT_PORT);
372
- await Promise.all([
373
- build({ certdir, outdir, port, input }),
374
- watchCss({ k2Config: k2Config ?? {}, outdir })
375
- ]);
383
+ const certDirPath = path9.resolve(certdir);
384
+ const outputDir = path9.resolve(outdir);
385
+ const inputDir = path9.resolve(input);
386
+ if (!hasCertificates(certDirPath)) {
387
+ console.log(chalk4.yellow("\u{1F4DC} SSL certificates not found. Generating..."));
388
+ try {
389
+ await generateCert(certDirPath);
390
+ console.log(chalk4.green("\u2705 SSL certificates generated successfully"));
391
+ } catch (error) {
392
+ console.log(
393
+ chalk4.red("\u274C Failed to generate SSL certificates. Make sure mkcert is installed.")
394
+ );
395
+ console.log(chalk4.gray(" Install mkcert: https://github.com/FiloSottile/mkcert"));
396
+ throw error;
397
+ }
398
+ }
399
+ const entries = getEntryPointsFromDir(inputDir);
400
+ const entryNames = Object.keys(entries);
401
+ if (entryNames.length === 0) {
402
+ throw new Error(`No entry points found in ${input}`);
403
+ }
404
+ console.log(chalk4.gray(` Entry points: ${entryNames.join(", ")}`));
405
+ await fs6.emptyDir(outputDir);
406
+ const { key, cert } = loadCertificates(certDirPath);
407
+ console.log(chalk4.gray(" Building..."));
408
+ await buildEntriesWithVite({
409
+ entries,
410
+ outDir: outputDir,
411
+ mode: "development",
412
+ sourcemap: "inline",
413
+ minify: false
414
+ });
415
+ const serverConfig = createViteConfig({
416
+ root: outputDir,
417
+ server: {
418
+ port,
419
+ https: { key, cert }
420
+ }
421
+ });
422
+ const server = await createServer(serverConfig);
423
+ await server.listen();
424
+ console.log(chalk4.green(`
425
+ \u2728 Development server ready!`));
426
+ console.log(chalk4.cyan(` Local: https://localhost:${port}`));
427
+ console.log(chalk4.gray(` Output: ${outputDir}`));
428
+ console.log(chalk4.gray("\n Watching for changes...\n"));
429
+ const chokidar2 = await import("chokidar");
430
+ const watcher = chokidar2.watch([`${input}/**/*.{ts,tsx,js,jsx,css,scss}`], {
431
+ ignored: /node_modules/,
432
+ persistent: true
433
+ });
434
+ const rebuild = async () => {
435
+ console.log(chalk4.gray(" Rebuilding..."));
436
+ await buildEntriesWithVite({
437
+ entries,
438
+ outDir: outputDir,
439
+ mode: "development",
440
+ sourcemap: "inline",
441
+ minify: false
442
+ });
443
+ };
444
+ watcher.on("change", rebuild);
445
+ watcher.on("add", rebuild);
446
+ watcher.on("unlink", rebuild);
447
+ if (k2Config) {
448
+ await watchCss({ k2Config, outdir });
449
+ }
376
450
  } catch (error) {
377
451
  throw error;
378
452
  } finally {
379
453
  console.groupEnd();
380
454
  }
381
455
  }
382
- var build = async (params) => {
383
- const { outdir, certdir, port, input } = params;
384
- const srcDir = path9.resolve(input);
385
- const dirs = fs4.readdirSync(srcDir);
386
- const entryPoints = dirs.reduce(
387
- (acc, dir) => {
388
- for (const filename of ["index.ts", "index.js", "index.mjs"]) {
389
- if (fs4.existsSync(path9.join(srcDir, dir, filename))) {
390
- return [...acc, { in: path9.join(srcDir, dir, filename), out: dir }];
391
- }
392
- }
393
- return acc;
394
- },
395
- []
396
- );
397
- return action3({ port, entryPoints, certDir: certdir, staticDir: outdir });
398
- };
399
456
 
400
457
  // src/commands/genkey.ts
401
458
  import { program as program3 } from "commander";
402
459
 
403
- // src/lib/exec.ts
404
- import { exec as defaultExec } from "child_process";
405
- import { promisify } from "util";
406
- var exec = promisify(defaultExec);
407
-
408
- // src/lib/cert.ts
409
- import fs5 from "fs-extra";
410
- import path10 from "path";
411
- var generateCert = async (outDir) => {
412
- const { stdout } = await exec(`mkcert localhost 127.0.0.1 ::1`);
413
- [
414
- { input: "localhost+2.pem", output: "localhost-cert.pem" },
415
- { input: "localhost+2-key.pem", output: "localhost-key.pem" }
416
- ].forEach(({ input, output }) => {
417
- fs5.moveSync(`./${input}`, path10.join(outDir, output), {
418
- overwrite: true
419
- });
420
- });
421
- return { stdout };
422
- };
423
-
424
460
  // src/commands/genkey-base.ts
425
- async function action5(options) {
461
+ async function action3(options) {
426
462
  const { output } = options;
427
463
  console.group("\u{1F373} Generate SSL key for localhost");
428
464
  try {
@@ -440,47 +476,41 @@ async function action5(options) {
440
476
 
441
477
  // src/commands/genkey.ts
442
478
  function command3() {
443
- program3.command("genkey").description("Generate SSL key for localhost. (Require mkcert)").option("-o, --output <output>", "Output directory.", WORKSPACE_DIRECTORY).action(action6);
479
+ program3.command("genkey").description("Generate SSL key for localhost. (Require mkcert)").option("-o, --output <output>", "Output directory.", WORKSPACE_DIRECTORY).action(action4);
444
480
  }
445
- async function action6(options) {
446
- await action5(options);
481
+ async function action4(options) {
482
+ await action3(options);
447
483
  }
448
484
 
449
485
  // src/commands/build-esbuild.ts
450
486
  import { program as program4 } from "commander";
451
- import fs6 from "fs-extra";
452
- import path11 from "path";
453
- import "esbuild";
487
+ import fs7 from "fs-extra";
488
+ import path10 from "path";
489
+ import chalk5 from "chalk";
454
490
  function command4() {
455
- program4.command("esbuild-build").option("-o, --outdir <outdir>", "Output directory.", path11.join(WORKSPACE_DIRECTORY, "prod")).option("-i, --input <input>", "Input directory.", path11.join("src", "apps")).option("--config <config>", "k2 config file path").description("Build the project for production. (It's a wrapper of webpack build command.)").action(action7);
491
+ program4.command("esbuild-build").option("-o, --outdir <outdir>", "Output directory.", path10.join(WORKSPACE_DIRECTORY, "prod")).option("-i, --input <input>", "Input directory.", path10.join("src", "apps")).option("--config <config>", "k2 config file path").description("Build the project for production with Vite. (Legacy command name, now uses Vite)").action(action5);
456
492
  }
457
- async function action7(options) {
493
+ async function action5(options) {
458
494
  console.group("\u{1F373} Build the project for production");
459
495
  try {
460
496
  const { outdir, input, config } = options;
461
- const outDir = path11.resolve(outdir);
462
- if (!fs6.existsSync(outDir)) {
463
- fs6.mkdirSync(outDir, { recursive: true });
497
+ const outDir = path10.resolve(outdir);
498
+ const entries = getEntryPointsFromDir(path10.resolve(input));
499
+ const entryNames = Object.keys(entries);
500
+ if (entryNames.length === 0) {
501
+ throw new Error(`No entry points found in ${input}`);
464
502
  }
465
- const allProjects = fs6.readdirSync(path11.resolve(input));
466
- const entryPoints = allProjects.reduce((acc, dir) => {
467
- for (const filename of ["index.ts", "index.js", "index.mjs"]) {
468
- if (fs6.existsSync(path11.join(input, dir, filename))) {
469
- return { ...acc, [dir]: path11.join(input, dir, filename) };
470
- }
471
- }
472
- return acc;
473
- }, {});
474
- console.log(`\u{1F4C1} ${Object.keys(entryPoints).length} entry points`);
503
+ console.log(chalk5.gray(` Entry points: ${entryNames.join(", ")}`));
504
+ await fs7.emptyDir(outDir);
475
505
  const k2Config = config ? await importK2Config(config) : getDefaultK2Config();
476
506
  const fullConfig = { ...k2Config, outDir };
477
507
  const results = await Promise.allSettled([
478
- buildWithEsbuild({
479
- entryPoints,
480
- outdir,
508
+ buildEntriesWithVite({
509
+ entries,
510
+ outDir,
511
+ mode: "production",
481
512
  sourcemap: false,
482
- minify: true,
483
- legalComments: "none"
513
+ minify: true
484
514
  }),
485
515
  buildTailwind(fullConfig)
486
516
  ]);
@@ -531,9 +561,9 @@ async function lint() {
531
561
 
532
562
  // src/commands/lint.ts
533
563
  function command5() {
534
- program5.command("lint").description("Lint source files").option("-c, --config <config>", "Config file path").action(action8);
564
+ program5.command("lint").description("Lint source files").option("-c, --config <config>", "Config file path").action(action6);
535
565
  }
536
- async function action8(options) {
566
+ async function action6(options) {
537
567
  try {
538
568
  lint();
539
569
  } catch (error) {