@konomi-app/k2 3.4.0 → 4.0.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/plugin.js CHANGED
@@ -1,19 +1,13 @@
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
- });
8
2
 
9
3
  // src/plugin.ts
10
- import { program as program10 } from "commander";
4
+ import { program as program9 } from "commander";
11
5
 
12
6
  // src/commands/plugin-build.ts
13
7
  import { program } from "commander";
14
8
  import fs3 from "fs-extra";
15
9
  import path5 from "path";
16
- import chalk2 from "chalk";
10
+ import chalk from "chalk";
17
11
 
18
12
  // src/lib/constants.ts
19
13
  import path from "path";
@@ -30,11 +24,11 @@ var DEFAULT_PORT = 32767;
30
24
  // src/lib/import.ts
31
25
  import { pathToFileURL } from "url";
32
26
  import path2 from "path";
33
- var esmImport = (path16) => {
27
+ var esmImport = (path17) => {
34
28
  if (process.platform === "win32") {
35
- return import(pathToFileURL(path16).toString());
29
+ return import(pathToFileURL(path17).toString());
36
30
  } else {
37
- return import(path16);
31
+ return import(path17);
38
32
  }
39
33
  };
40
34
  var importK2PluginConfig = async (configFileName) => {
@@ -114,16 +108,16 @@ var watchTailwindCSS = async (params) => {
114
108
  watcher.on("error", (error) => {
115
109
  console.error("Error watching Tailwind CSS:", error);
116
110
  });
117
- watcher.on("add", (path16) => {
111
+ watcher.on("add", (path17) => {
118
112
  debouncedProcessChanges.call("add");
119
113
  });
120
- watcher.on("change", (path16) => {
114
+ watcher.on("change", (path17) => {
121
115
  debouncedProcessChanges.call("change");
122
116
  });
123
- watcher.on("unlink", (path16) => {
117
+ watcher.on("unlink", (path17) => {
124
118
  debouncedProcessChanges.call("unlink");
125
119
  });
126
- watcher.on("unlinkDir", (path16) => {
120
+ watcher.on("unlinkDir", (path17) => {
127
121
  debouncedProcessChanges.call("unlink");
128
122
  });
129
123
  return watcher;
@@ -158,179 +152,115 @@ async function lint() {
158
152
  }
159
153
  }
160
154
 
161
- // src/lib/vite.ts
162
- import chalk from "chalk";
163
- import fs2 from "fs-extra";
164
- import os from "os";
155
+ // src/lib/rsbuild.ts
156
+ import { createRsbuild } from "@rsbuild/core";
165
157
  import path4 from "path";
166
- import { build as viteBuild } from "vite";
167
- var DEFAULT_CONCURRENCY = Math.max(1, os.cpus().length - 1);
168
- async function parallelLimit(items, concurrency, fn) {
169
- const results = [];
170
- const executing = [];
171
- for (const item of items) {
172
- const promise = fn(item).then((result) => {
173
- results.push(result);
174
- });
175
- const e = promise.then(() => {
176
- executing.splice(executing.indexOf(e), 1);
177
- });
178
- executing.push(e);
179
- if (executing.length >= concurrency) {
180
- await Promise.race(executing);
158
+ import fs2 from "fs-extra";
159
+ async function buildWithRsbuild(params) {
160
+ const { entries, outDir, minify = true, sourcemap = false, injectStyles = true } = params;
161
+ const sourceMapConfig = sourcemap === "inline" ? "cheap-module-source-map" : sourcemap ? "source-map" : false;
162
+ const rsbuild = await createRsbuild({
163
+ rsbuildConfig: {
164
+ source: { entry: entries },
165
+ output: {
166
+ target: "web",
167
+ distPath: { root: outDir, js: "" },
168
+ filename: { js: "[name].js" },
169
+ filenameHash: false,
170
+ cleanDistPath: true,
171
+ injectStyles,
172
+ sourceMap: { js: sourceMapConfig },
173
+ minify
174
+ },
175
+ performance: {
176
+ chunkSplit: { strategy: "all-in-one" }
177
+ },
178
+ tools: {
179
+ htmlPlugin: false
180
+ }
181
181
  }
182
- }
183
- await Promise.all(executing);
184
- return results;
182
+ });
183
+ await rsbuild.build();
185
184
  }
186
- var createViteConfig = (config2 = {}) => {
187
- const plugins = [...config2.plugins ?? []];
188
- try {
189
- const tsconfigPaths = __require("vite-tsconfig-paths");
190
- plugins.push(tsconfigPaths.default ? tsconfigPaths.default() : tsconfigPaths());
191
- } catch {
192
- }
193
- const mode = config2.mode ?? "production";
194
- return {
195
- ...config2,
196
- configFile: false,
197
- // ソースマップ関連のエラーメッセージを抑制
198
- logLevel: config2.logLevel ?? "warn",
199
- // ブラウザ向けにNode.js固有のオブジェクトをビルド時に解決
200
- define: {
201
- "process.env.NODE_ENV": JSON.stringify(mode),
202
- "process.env": JSON.stringify({}),
203
- ...config2.define
185
+ async function startRsbuildDevServer(params) {
186
+ const { entries, outDir, port, https, publicDir, onFirstCompile, onRecompile } = params;
187
+ const rsbuildConfig = {
188
+ source: { entry: entries },
189
+ output: {
190
+ target: "web",
191
+ distPath: { root: outDir, js: "" },
192
+ filename: { js: "[name].js" },
193
+ filenameHash: false,
194
+ cleanDistPath: false,
195
+ injectStyles: true,
196
+ sourceMap: { js: "cheap-module-source-map" },
197
+ minify: false
204
198
  },
205
- build: {
206
- ...config2.build,
207
- // ブラウザ向けターゲット
208
- target: config2.build?.target ?? "es2020",
209
- cssCodeSplit: false,
210
- rollupOptions: {
211
- ...config2.build?.rollupOptions,
212
- onwarn: (warning, warn) => {
213
- if (["MODULE_LEVEL_DIRECTIVE"].includes(warning.code ?? "")) {
214
- return;
215
- }
216
- if (warning.message?.includes("sourcemap") || warning.code === "SOURCEMAP_ERROR") {
217
- return;
218
- }
219
- warn(warning);
220
- }
221
- }
199
+ performance: {
200
+ chunkSplit: { strategy: "all-in-one" }
222
201
  },
223
- plugins,
224
- resolve: {
225
- ...config2.resolve,
226
- alias: {
227
- "@": path4.resolve(process.cwd(), "src"),
228
- ...config2.resolve?.alias
229
- }
202
+ tools: {
203
+ htmlPlugin: false
204
+ },
205
+ server: {
206
+ port,
207
+ host: "0.0.0.0",
208
+ ...https ? { https } : {},
209
+ ...publicDir && fs2.existsSync(publicDir) ? { publicDir: { name: publicDir } } : {}
210
+ },
211
+ dev: {
212
+ writeToDisk: true
230
213
  }
231
214
  };
232
- };
233
- async function buildEntriesWithVite(params) {
234
- const {
235
- entries,
236
- outDir,
237
- mode = "production",
238
- sourcemap = false,
239
- minify = true,
240
- viteConfig = {},
241
- concurrency = DEFAULT_CONCURRENCY
242
- } = params;
243
- const entryNames = Object.keys(entries);
244
- if (entryNames.length === 1) {
245
- const name = entryNames[0];
246
- await buildSingleEntry({
247
- name,
248
- entryPath: entries[name],
249
- outDir,
250
- mode,
251
- sourcemap,
252
- minify,
253
- viteConfig
254
- });
255
- return;
256
- }
257
- await parallelLimit(entryNames, concurrency, async (name) => {
258
- await buildSingleEntry({
259
- name,
260
- entryPath: entries[name],
261
- outDir,
262
- mode,
263
- sourcemap,
264
- minify,
265
- viteConfig
266
- });
267
- });
268
- }
269
- async function buildSingleEntry(params) {
270
- const { name, entryPath, outDir, mode, sourcemap, minify, viteConfig } = params;
271
- const config2 = createViteConfig({
272
- ...viteConfig,
273
- mode,
274
- build: {
275
- ...viteConfig.build,
276
- rollupOptions: {
277
- ...viteConfig.build?.rollupOptions,
278
- input: entryPath,
279
- output: {
280
- entryFileNames: `${name}.js`,
281
- assetFileNames: `${name}.[ext]`,
282
- // 外部ライブラリのソースマップを無視して警告を抑制
283
- sourcemapIgnoreList: (relativeSourcePath) => {
284
- return relativeSourcePath.includes("node_modules");
285
- },
286
- ...viteConfig.build?.rollupOptions?.output
215
+ const rsbuild = await createRsbuild({ rsbuildConfig });
216
+ if (onFirstCompile || onRecompile) {
217
+ rsbuild.addPlugins([
218
+ {
219
+ name: "k2-dev-hooks",
220
+ setup(api) {
221
+ api.onDevCompileDone(async ({ isFirstCompile }) => {
222
+ if (isFirstCompile && onFirstCompile) {
223
+ await onFirstCompile();
224
+ } else if (!isFirstCompile && onRecompile) {
225
+ await onRecompile();
226
+ }
227
+ });
287
228
  }
288
- },
289
- outDir,
290
- emptyOutDir: false,
291
- sourcemap,
292
- minify,
293
- cssCodeSplit: false
294
- }
295
- });
296
- await viteBuild(config2);
297
- }
298
- var ENTRY_FILE_NAMES = ["index.ts", "index.tsx", "index.js", "index.jsx", "index.mjs"];
299
- function findEntryPoint(basePath) {
300
- for (const filename of ENTRY_FILE_NAMES) {
301
- const entryPath = path4.join(basePath, filename);
302
- if (fs2.existsSync(entryPath)) {
303
- return entryPath;
304
- }
305
- }
306
- if (fs2.existsSync(basePath) && fs2.statSync(basePath).isFile()) {
307
- return basePath;
229
+ }
230
+ ]);
308
231
  }
309
- return null;
232
+ const result = await rsbuild.startDevServer();
233
+ return {
234
+ port: result.port,
235
+ close: result.server.close
236
+ };
310
237
  }
311
- function getPluginEntryPoints(options) {
238
+ function getPluginEntryPoints(params) {
239
+ const { configEntry, desktopEntry } = params;
312
240
  const entries = {};
313
- const configPath = findEntryPoint(options.configEntry);
314
- if (configPath) {
315
- entries["config"] = configPath;
316
- } else {
317
- console.log(chalk.yellow(` \u26A0 Config entry not found: ${options.configEntry}`));
241
+ for (const ext of ["index.ts", "index.tsx", "index.js", "index.jsx"]) {
242
+ const configPath = path4.join(configEntry, ext);
243
+ if (fs2.existsSync(configPath)) {
244
+ entries.config = configPath;
245
+ break;
246
+ }
318
247
  }
319
- const desktopPath = findEntryPoint(options.desktopEntry);
320
- if (desktopPath) {
321
- entries["desktop"] = desktopPath;
322
- } else {
323
- console.log(chalk.yellow(` \u26A0 Desktop entry not found: ${options.desktopEntry}`));
248
+ for (const ext of ["index.ts", "index.tsx", "index.js", "index.jsx"]) {
249
+ const desktopPath = path4.join(desktopEntry, ext);
250
+ if (fs2.existsSync(desktopPath)) {
251
+ entries.desktop = desktopPath;
252
+ break;
253
+ }
324
254
  }
325
255
  return entries;
326
256
  }
327
257
 
328
258
  // src/commands/plugin-build.ts
329
259
  function command() {
330
- program.command("build").description("Build the project for production with Vite.").action(action);
260
+ program.command("build").description("Build the plugin for production with rsbuild.").action(action);
331
261
  }
332
262
  async function action() {
333
- console.group("\u{1F373} Build the project for production");
263
+ console.group("\u{1F373} Build the plugin for production");
334
264
  try {
335
265
  const config2 = await importK2PluginConfig();
336
266
  if (config2?.lint?.build) {
@@ -340,6 +270,24 @@ async function action() {
340
270
  if (!fs3.existsSync(PLUGIN_CONTENTS_DIRECTORY)) {
341
271
  await fs3.mkdir(PLUGIN_CONTENTS_DIRECTORY, { recursive: true });
342
272
  }
273
+ if (config2.tailwind?.css && config2.tailwind?.config) {
274
+ const tailwindConfig = await getTailwindConfig(config2.tailwind);
275
+ const inputFile = getTailwindInputCss(config2.tailwind);
276
+ await outputCss({
277
+ inputPath: inputFile.config,
278
+ outputPath: path5.join(PLUGIN_CONTENTS_DIRECTORY, "config.css"),
279
+ config: tailwindConfig.config,
280
+ minify: true
281
+ });
282
+ console.log("\u2728 Built config.css");
283
+ await outputCss({
284
+ inputPath: inputFile.desktop,
285
+ outputPath: path5.join(PLUGIN_CONTENTS_DIRECTORY, "desktop.css"),
286
+ config: tailwindConfig.desktop,
287
+ minify: true
288
+ });
289
+ console.log("\u2728 Built desktop.css");
290
+ }
343
291
  const entries = getPluginEntryPoints({
344
292
  configEntry: path5.resolve("src", "config"),
345
293
  desktopEntry: path5.resolve("src", "desktop")
@@ -348,36 +296,15 @@ async function action() {
348
296
  if (entryNames.length === 0) {
349
297
  throw new Error("No entry points found for plugin. Check src/config and src/desktop paths.");
350
298
  }
351
- console.log(chalk2.gray(` Entry points: ${entryNames.join(", ")}`));
352
- const buildTasks = [];
353
- if (config2.tailwind?.css && config2.tailwind?.config) {
354
- const tailwindConfig = await getTailwindConfig(config2.tailwind);
355
- const inputFile = getTailwindInputCss(config2.tailwind);
356
- buildTasks.push(
357
- outputCss({
358
- inputPath: inputFile.config,
359
- outputPath: path5.join(PLUGIN_CONTENTS_DIRECTORY, "config.css"),
360
- config: tailwindConfig.config,
361
- minify: true
362
- }).then(() => console.log("\u2728 Built config.css")),
363
- outputCss({
364
- inputPath: inputFile.desktop,
365
- outputPath: path5.join(PLUGIN_CONTENTS_DIRECTORY, "desktop.css"),
366
- config: tailwindConfig.desktop,
367
- minify: true
368
- }).then(() => console.log("\u2728 Built desktop.css"))
369
- );
370
- }
371
- buildTasks.push(
372
- buildEntriesWithVite({
373
- entries,
374
- outDir: PLUGIN_CONTENTS_DIRECTORY,
375
- mode: "production",
376
- sourcemap: false,
377
- minify: true
378
- }).then(() => console.log("\u2728 Built desktop.js and config.js"))
379
- );
380
- await Promise.all(buildTasks);
299
+ console.log(chalk.gray(` Entry points: ${entryNames.join(", ")}`));
300
+ await buildWithRsbuild({
301
+ entries,
302
+ outDir: PLUGIN_CONTENTS_DIRECTORY,
303
+ minify: true,
304
+ sourcemap: false,
305
+ injectStyles: true
306
+ });
307
+ console.log("\u2728 Built desktop.js and config.js");
381
308
  console.log("\u2728 Build success.");
382
309
  } catch (error) {
383
310
  throw error;
@@ -386,65 +313,245 @@ async function action() {
386
313
  }
387
314
  }
388
315
 
389
- // src/commands/plugin-esbuild.ts
390
- import { program as program2 } from "commander";
391
- function command2() {
392
- program2.command("esbuild").description(
393
- "[DEPRECATED] Build the project for production with esbuild. (Use `plugin build` instead.)"
394
- ).action(action);
395
- }
396
-
397
316
  // src/commands/plugin-dev/index.ts
398
- import { program as program3 } from "commander";
399
- import { createServer } from "vite";
317
+ import { program as program2 } from "commander";
400
318
  import fs10 from "fs-extra";
401
319
  import path13 from "path";
402
- import chalk5 from "chalk";
403
-
404
- // src/lib/exec.ts
405
- import { exec as defaultExec } from "child_process";
406
- import { promisify } from "util";
407
- var exec = promisify(defaultExec);
320
+ import chalk4 from "chalk";
408
321
 
409
- // src/lib/cert.ts
322
+ // src/lib/cert/index.ts
410
323
  import fs4 from "fs-extra";
324
+ import path7 from "path";
325
+
326
+ // src/lib/cert/cert.ts
327
+ import forge from "node-forge";
328
+ import net from "net";
329
+ var { md, pki } = forge;
330
+ function createCertificate(serial, publicKey, subject, issuer, extensions, validity, signWith) {
331
+ const cert = pki.createCertificate();
332
+ cert.serialNumber = Buffer.from(serial).toString("hex");
333
+ cert.publicKey = publicKey;
334
+ cert.setSubject(subject);
335
+ cert.setIssuer(issuer);
336
+ cert.setExtensions(extensions);
337
+ cert.validity.notBefore = /* @__PURE__ */ new Date();
338
+ cert.validity.notAfter = /* @__PURE__ */ new Date();
339
+ cert.validity.notAfter.setDate(cert.validity.notAfter.getDate() + validity);
340
+ cert.sign(signWith, md.sha256.create());
341
+ return cert;
342
+ }
343
+ function generateCertInternal(params) {
344
+ const { subject, issuer, extensions, validity, signWith } = params;
345
+ const serial = Math.floor(Math.random() * 95e3 + 5e4).toString();
346
+ const keyPair = pki.rsa.generateKeyPair(2048);
347
+ const privateKey = signWith ? pki.privateKeyFromPem(signWith) : keyPair.privateKey;
348
+ const cert = createCertificate(
349
+ serial,
350
+ keyPair.publicKey,
351
+ subject,
352
+ issuer,
353
+ extensions,
354
+ validity,
355
+ privateKey
356
+ );
357
+ return {
358
+ key: pki.privateKeyToPem(keyPair.privateKey),
359
+ cert: pki.certificateToPem(cert)
360
+ };
361
+ }
362
+ function createCA(params = {}) {
363
+ const {
364
+ organization = "K2 Development CA",
365
+ countryCode = "JP",
366
+ state = "Tokyo",
367
+ locality = "Tokyo",
368
+ validity = 7300
369
+ } = params;
370
+ const attributes = [
371
+ { name: "commonName", value: organization },
372
+ { name: "countryName", value: countryCode },
373
+ { name: "stateOrProvinceName", value: state },
374
+ { name: "localityName", value: locality },
375
+ { name: "organizationName", value: organization }
376
+ ];
377
+ const extensions = [
378
+ { name: "basicConstraints", cA: true, critical: true },
379
+ { name: "keyUsage", keyCertSign: true, critical: true }
380
+ ];
381
+ return generateCertInternal({
382
+ subject: attributes,
383
+ issuer: attributes,
384
+ extensions,
385
+ validity
386
+ });
387
+ }
388
+ function createCert(params) {
389
+ const { ca, domains, validity = 7300 } = params;
390
+ const attributes = [{ name: "commonName", value: domains[0] }];
391
+ const extensions = [
392
+ { name: "basicConstraints", cA: false, critical: true },
393
+ {
394
+ name: "keyUsage",
395
+ digitalSignature: true,
396
+ keyEncipherment: true,
397
+ critical: true
398
+ },
399
+ { name: "extKeyUsage", serverAuth: true, clientAuth: true },
400
+ {
401
+ name: "subjectAltName",
402
+ altNames: domains.map((domain) => {
403
+ const TYPE_DOMAIN = 2;
404
+ const TYPE_IP = 7;
405
+ return net.isIP(domain) ? { type: TYPE_IP, ip: domain } : { type: TYPE_DOMAIN, value: domain };
406
+ })
407
+ }
408
+ ];
409
+ const caCert = pki.certificateFromPem(ca.cert.toString());
410
+ return generateCertInternal({
411
+ subject: attributes,
412
+ issuer: caCert.subject.attributes,
413
+ extensions,
414
+ validity,
415
+ signWith: ca.key.toString()
416
+ });
417
+ }
418
+
419
+ // src/lib/cert/constants.ts
411
420
  import path6 from "path";
421
+ var PKG_NAME = "k2";
422
+ var isSupported = process.platform === "darwin" || process.platform === "linux" || process.platform === "win32";
423
+ function getApplicationConfigPath(name) {
424
+ if (process.platform === "darwin") {
425
+ return path6.join(process.env.HOME, "Library", "Application Support", name);
426
+ }
427
+ if (process.platform === "win32") {
428
+ return process.env.LOCALAPPDATA ? path6.join(process.env.LOCALAPPDATA, name) : path6.join(process.env.USERPROFILE, "Local Settings", "Application Data", name);
429
+ }
430
+ return process.env.XDG_CONFIG_HOME ? path6.join(process.env.XDG_CONFIG_HOME, name) : path6.join(process.env.HOME, ".config", name);
431
+ }
432
+ var pkgDir = getApplicationConfigPath(PKG_NAME);
433
+ var rootCAPath = path6.resolve(pkgDir, "rootCA.pem");
434
+ var rootCAKeyPath = path6.resolve(pkgDir, "rootCA-key.pem");
435
+
436
+ // src/lib/cert/platforms.ts
437
+ import { spawnSync } from "child_process";
438
+
439
+ // src/lib/logger.ts
440
+ var PKG_NAME2 = "@konomi-app/k2";
441
+ function createLogger(prefix = PKG_NAME2) {
442
+ return {
443
+ log: (...args) => console.log(`[${prefix}]`, ...args),
444
+ info: (...args) => console.info(`[${prefix}]`, ...args),
445
+ warn: (...args) => console.warn(`[${prefix}]`, ...args),
446
+ error: (...args) => console.error(`[${prefix}]`, ...args)
447
+ };
448
+ }
449
+ var logger_default = createLogger();
450
+
451
+ // src/lib/cert/platforms.ts
452
+ function addToTrustStoresDarwin(certPath) {
453
+ logger_default.log("Adding certificate to trusted store. Admin rights may be required.");
454
+ spawnSync(
455
+ "sudo",
456
+ [
457
+ "security",
458
+ "add-trusted-cert",
459
+ "-d",
460
+ "-r",
461
+ "trustRoot",
462
+ "-k",
463
+ "/Library/Keychains/System.keychain",
464
+ "-p",
465
+ "ssl",
466
+ "-p",
467
+ "basic",
468
+ certPath
469
+ ],
470
+ { stdio: "inherit" }
471
+ );
472
+ }
473
+ var targetCA = `/usr/local/share/ca-certificates/${PKG_NAME}.crt`;
474
+ function addToTrustStoresLinux(certPath) {
475
+ logger_default.log("Adding certificate to trusted store. Admin rights may be required.");
476
+ spawnSync("sudo", ["cp", certPath, targetCA]);
477
+ spawnSync("sudo", ["update-ca-certificates"]);
478
+ }
479
+ function addToTrustStoresWin32(certPath) {
480
+ spawnSync("certutil", ["-addstore", "-user", "root", certPath], {
481
+ stdio: "inherit"
482
+ });
483
+ }
484
+ function addToTrustStores(certPath) {
485
+ switch (process.platform) {
486
+ case "darwin":
487
+ return addToTrustStoresDarwin(certPath);
488
+ case "linux":
489
+ return addToTrustStoresLinux(certPath);
490
+ case "win32":
491
+ return addToTrustStoresWin32(certPath);
492
+ }
493
+ }
494
+
495
+ // src/lib/cert/index.ts
412
496
  var CERT_KEY_FILENAME = "localhost-key.pem";
413
497
  var CERT_FILENAME = "localhost-cert.pem";
414
- var generateCert = async (outDir) => {
415
- await fs4.ensureDir(outDir);
416
- const { stdout } = await exec(`mkcert localhost 127.0.0.1 ::1`);
417
- [
418
- { input: "localhost+2.pem", output: CERT_FILENAME },
419
- { input: "localhost+2-key.pem", output: CERT_KEY_FILENAME }
420
- ].forEach(({ input, output }) => {
421
- if (fs4.existsSync(input)) {
422
- fs4.moveSync(`./${input}`, path6.join(outDir, output), {
423
- overwrite: true
424
- });
498
+ function install(options = {}) {
499
+ const { validity = 7300 } = options;
500
+ if (!isSupported) {
501
+ throw new Error(`Platform not supported: "${process.platform}"`);
502
+ }
503
+ if (!fs4.existsSync(rootCAPath) && !fs4.existsSync(rootCAKeyPath)) {
504
+ const ca = createCA({ validity });
505
+ fs4.outputFileSync(rootCAPath, ca.cert);
506
+ fs4.outputFileSync(rootCAKeyPath, ca.key);
507
+ try {
508
+ addToTrustStores(rootCAPath);
509
+ } catch {
510
+ console.warn(
511
+ "\u26A0 Failed to add CA to system trust store. You may need to trust the certificate manually."
512
+ );
425
513
  }
426
- });
427
- return { stdout };
428
- };
514
+ }
515
+ }
516
+ function certificateFor(requestedDomains = []) {
517
+ const validity = 7300;
518
+ install({ validity });
519
+ const requests = Array.isArray(requestedDomains) ? requestedDomains : [requestedDomains];
520
+ const domains = [
521
+ .../* @__PURE__ */ new Set(["localhost", "localhost.localdomain", "127.0.0.1", "0.0.0.0", "::1", ...requests])
522
+ ];
523
+ const ca = {
524
+ cert: fs4.readFileSync(rootCAPath),
525
+ key: fs4.readFileSync(rootCAKeyPath)
526
+ };
527
+ return createCert({ ca, domains, validity });
528
+ }
529
+ function generateCert(outDir) {
530
+ fs4.ensureDirSync(outDir);
531
+ const result = certificateFor();
532
+ fs4.outputFileSync(path7.join(outDir, CERT_FILENAME), result.cert);
533
+ fs4.outputFileSync(path7.join(outDir, CERT_KEY_FILENAME), result.key);
534
+ return result;
535
+ }
429
536
  function hasCertificates(certDir) {
430
- return fs4.existsSync(path6.join(certDir, CERT_KEY_FILENAME)) && fs4.existsSync(path6.join(certDir, CERT_FILENAME));
537
+ return fs4.existsSync(path7.join(certDir, CERT_KEY_FILENAME)) && fs4.existsSync(path7.join(certDir, CERT_FILENAME));
431
538
  }
432
539
  function loadCertificates(certDir) {
433
540
  return {
434
- key: fs4.readFileSync(path6.join(certDir, CERT_KEY_FILENAME)),
435
- cert: fs4.readFileSync(path6.join(certDir, CERT_FILENAME))
541
+ key: fs4.readFileSync(path7.join(certDir, CERT_KEY_FILENAME)),
542
+ cert: fs4.readFileSync(path7.join(certDir, CERT_FILENAME))
436
543
  };
437
544
  }
438
545
 
439
546
  // src/lib/plugin-manifest.ts
440
547
  import fs5 from "fs-extra";
441
- import path7 from "path";
548
+ import path8 from "path";
442
549
  import merge from "deepmerge";
443
550
  var outputManifest = async (env, options) => {
444
551
  const config2 = options?.config || await importK2PluginConfig();
445
552
  const merged = merge(config2.manifest.base, config2.manifest[env] || {});
446
553
  await fs5.mkdirs(PLUGIN_CONTENTS_DIRECTORY);
447
- await fs5.writeJson(path7.join(PLUGIN_CONTENTS_DIRECTORY, "manifest.json"), merged);
554
+ await fs5.writeJson(path8.join(PLUGIN_CONTENTS_DIRECTORY, "manifest.json"), merged);
448
555
  return merged;
449
556
  };
450
557
 
@@ -479,21 +586,21 @@ var getManifest = async (params) => {
479
586
  };
480
587
 
481
588
  // src/commands/plugin-dev/tailwind.ts
482
- import path8 from "path";
589
+ import path9 from "path";
483
590
  import "tailwindcss";
484
- import chalk3 from "chalk";
591
+ import chalk2 from "chalk";
485
592
  async function buildTailwindCSS(params) {
486
593
  const { inputFile, outputFileName, config: config2 } = params;
487
- const inputPath = path8.resolve(inputFile);
488
- const outputPath = path8.join(PLUGIN_DEVELOPMENT_DIRECTORY, outputFileName);
594
+ const inputPath = path9.resolve(inputFile);
595
+ const outputPath = path9.join(PLUGIN_DEVELOPMENT_DIRECTORY, outputFileName);
489
596
  return watchTailwindCSS({
490
597
  input: inputPath,
491
598
  output: outputPath,
492
599
  config: config2,
493
600
  onChanges: ({ output, type }) => {
494
- const outputFileName2 = path8.basename(output);
601
+ const outputFileName2 = path9.basename(output);
495
602
  console.log(
496
- chalk3.hex("#e5e7eb")(`${(/* @__PURE__ */ new Date()).toLocaleTimeString()} `) + chalk3.cyan(`[css] `) + outputFileName2 + (type === "init" ? " init" : ` rebuilt`)
603
+ chalk2.hex("#e5e7eb")(`${(/* @__PURE__ */ new Date()).toLocaleTimeString()} `) + chalk2.cyan(`[css] `) + outputFileName2 + (type === "init" ? " init" : ` rebuilt`)
497
604
  );
498
605
  }
499
606
  });
@@ -518,20 +625,17 @@ var watchCss = async (pluginConfig) => {
518
625
  ]);
519
626
  };
520
627
 
521
- // src/commands/plugin-dev/upload.ts
522
- import packer from "@kintone/plugin-packer";
523
-
524
628
  // src/lib/plugin-contents.ts
525
629
  import fs6 from "fs-extra";
526
- import path9 from "path";
630
+ import path10 from "path";
527
631
  import htmlMinifier from "html-minifier";
528
632
  var copyPluginContents = async (params = {}) => {
529
- const { inputDir = path9.join("src", "contents"), outputDir = PLUGIN_CONTENTS_DIRECTORY } = params;
633
+ const { inputDir = path10.join("src", "contents"), outputDir = PLUGIN_CONTENTS_DIRECTORY } = params;
530
634
  if (!fs6.existsSync(inputDir)) {
531
635
  await fs6.mkdir(inputDir, { recursive: true });
532
636
  }
533
637
  await fs6.copy(inputDir, outputDir, { overwrite: true });
534
- const configHtmlPath = path9.join(outputDir, "config.html");
638
+ const configHtmlPath = path10.join(outputDir, "config.html");
535
639
  if (!fs6.existsSync(configHtmlPath)) {
536
640
  throw new Error(`Plugin HTML file not found. Create "config.html" in ${inputDir}.`);
537
641
  }
@@ -550,208 +654,165 @@ var copyPluginContents = async (params = {}) => {
550
654
  };
551
655
 
552
656
  // src/lib/zip.ts
553
- import archiver from "archiver";
657
+ import fs8 from "fs-extra";
658
+ import path11 from "path";
659
+ import { zipSync } from "fflate";
660
+
661
+ // src/lib/rsa.ts
662
+ import forge2 from "node-forge";
554
663
  import fs7 from "fs-extra";
555
- import path10 from "path";
556
- import invariant2 from "tiny-invariant";
557
- var outputContentsZip = async (manifest) => {
558
- const archive = archiver("zip", { zlib: { level: 9 } });
559
- archive.on("warning", (error) => {
560
- if (error.code === "ENOENT") {
561
- console.warn(error);
664
+ function sign(contents, privateKeyPem) {
665
+ const key = forge2.pki.privateKeyFromPem(privateKeyPem);
666
+ const md2 = forge2.md.sha1.create();
667
+ md2.update(contents.toString("binary"));
668
+ const signature = key.sign(md2);
669
+ return Buffer.from(signature, "binary");
670
+ }
671
+ function getPublicKeyDer(privateKeyPem) {
672
+ const privateKey = forge2.pki.privateKeyFromPem(privateKeyPem);
673
+ const publicKey = forge2.pki.rsa.setPublicKey(privateKey.n, privateKey.e);
674
+ const publicKeyAsn1 = forge2.pki.publicKeyToAsn1(publicKey);
675
+ const publicKeyDerBytes = forge2.asn1.toDer(publicKeyAsn1).getBytes();
676
+ return Buffer.from(publicKeyDerBytes, "binary");
677
+ }
678
+ function generatePPK(ppkPath) {
679
+ const keypair = forge2.pki.rsa.generateKeyPair(1024);
680
+ const privateKey = forge2.pki.privateKeyToPem(keypair.privateKey);
681
+ fs7.outputFileSync(ppkPath, privateKey);
682
+ return privateKey;
683
+ }
684
+ function generatePluginId(publicKeyDer) {
685
+ const md2 = forge2.md.sha256.create();
686
+ md2.update(publicKeyDer.toString("binary"));
687
+ const hash = Buffer.from(md2.digest().bytes(), "binary");
688
+ const hexDigest = hash.subarray(0, 16).toString("hex");
689
+ return hexDigest.replace(/[0-9a-f]/g, (c) => "abcdefghijklmnop"["0123456789abcdef".indexOf(c)]);
690
+ }
691
+
692
+ // src/lib/zip.ts
693
+ function sourceList(manifest) {
694
+ const sourceTypes = [
695
+ ["desktop", "js"],
696
+ ["desktop", "css"],
697
+ ["mobile", "js"],
698
+ ["mobile", "css"],
699
+ ["config", "js"],
700
+ ["config", "css"]
701
+ ];
702
+ const list = sourceTypes.map(([type, ext]) => manifest[type]?.[ext]).filter(Boolean).reduce((a, b) => a.concat(b), []).filter((file) => !/^https?:\/\//.test(file));
703
+ if (manifest.config?.html) list.push(manifest.config.html);
704
+ list.push(manifest.icon);
705
+ return Array.from(new Set(list));
706
+ }
707
+ function zipFiles(files) {
708
+ const zipObj = {};
709
+ for (const [fileName, fileContent] of Object.entries(files)) {
710
+ let content;
711
+ if (Buffer.isBuffer(fileContent)) {
712
+ content = new Uint8Array(fileContent);
713
+ } else if (typeof fileContent === "string") {
714
+ const fileData = fs8.readFileSync(fileContent);
715
+ content = new Uint8Array(fileData);
562
716
  } else {
563
- throw error;
717
+ throw new Error(`Unsupported file content type for file: ${fileName}`);
564
718
  }
565
- });
566
- const outputZipPath = path10.join(PLUGIN_WORKSPACE_DIRECTORY, "contents.zip");
567
- const outputZipStream = fs7.createWriteStream(outputZipPath);
568
- outputZipStream.on("close", () => {
569
- console.log(`\u{1F4E6} ${archive.pointer()} total bytes`);
570
- });
571
- outputZipStream.on("end", function() {
572
- console.log("\u{1F4E6} Data has been drained");
573
- });
574
- const filterLocalContent = (file) => {
575
- return !/^https?:\/\//.test(file);
576
- };
577
- invariant2(manifest.config?.html, "manifest.config.html is required");
578
- const targetFiles = [
579
- "manifest.json",
580
- .../* @__PURE__ */ new Set([
581
- manifest.icon,
582
- manifest.config.html,
583
- ...(manifest.desktop?.js || []).filter(filterLocalContent),
584
- ...(manifest.desktop?.css || []).filter(filterLocalContent),
585
- ...(manifest.mobile?.js || []).filter(filterLocalContent),
586
- ...(manifest.mobile?.css || []).filter(filterLocalContent),
587
- ...(manifest.config.js || []).filter(filterLocalContent),
588
- ...(manifest.config.css || []).filter(filterLocalContent)
589
- ])
590
- ];
719
+ zipObj[fileName] = content;
720
+ }
721
+ const zipped = zipSync(zipObj);
722
+ return Buffer.from(zipped);
723
+ }
724
+ function createContentsZip(contentsDir, manifest, fileContents = {}) {
725
+ const files = sourceList(manifest).reduce((acc, file) => {
726
+ acc[file] = fileContents[file] || path11.join(contentsDir, file);
727
+ return acc;
728
+ }, {});
729
+ files["manifest.json"] = Buffer.from(JSON.stringify(manifest, null, 2));
730
+ const targetFiles = Object.keys(files);
591
731
  console.group("\u{1F4C1} Target files");
592
732
  targetFiles.forEach((file, i) => {
593
733
  const prefix = i === targetFiles.length - 1 ? "\u2514\u2500" : "\u251C\u2500";
594
734
  console.log(`${prefix} \u{1F4C4} ${file}`);
595
735
  });
596
736
  console.groupEnd();
597
- for (const file of targetFiles) {
598
- const filePath = path10.join(PLUGIN_CONTENTS_DIRECTORY, file);
599
- if (!fs7.existsSync(filePath)) {
600
- throw new Error(`${filePath} does not exist`);
601
- }
602
- archive.file(filePath, { name: file });
737
+ return zipFiles(files);
738
+ }
739
+ function createContentsZipFromDir(manifest) {
740
+ return createContentsZip(PLUGIN_CONTENTS_DIRECTORY, manifest);
741
+ }
742
+ function createPluginZip(params) {
743
+ const { ppkPath, contentsZip } = params;
744
+ let ppkContent;
745
+ if (fs8.existsSync(ppkPath)) {
746
+ ppkContent = fs8.readFileSync(ppkPath, "utf-8");
747
+ } else {
748
+ ppkContent = generatePPK(ppkPath);
603
749
  }
604
- archive.pipe(outputZipStream);
605
- await archive.finalize();
606
- await new Promise((resolve) => outputZipStream.on("close", resolve));
607
- };
608
- var getContentsZipBuffer = async () => {
609
- const outputZipPath = path10.join(PLUGIN_WORKSPACE_DIRECTORY, "contents.zip");
610
- return fs7.readFile(outputZipPath);
611
- };
750
+ const signature = sign(contentsZip, ppkContent);
751
+ const publicKeyDer = getPublicKeyDer(ppkContent);
752
+ const pluginId = generatePluginId(publicKeyDer);
753
+ const pluginZip = zipFiles({
754
+ "contents.zip": contentsZip,
755
+ PUBKEY: publicKeyDer,
756
+ SIGNATURE: signature
757
+ });
758
+ return { zip: pluginZip, id: pluginId, privateKey: ppkContent };
759
+ }
612
760
  var getZipFileNameSuffix = (env) => {
613
761
  return env === "prod" ? "" : `-${env}`;
614
762
  };
615
763
 
616
- // src/commands/plugin-dev/upload.ts
617
- import fs9 from "fs-extra";
618
- import path12 from "path";
619
-
620
764
  // src/lib/kintone-api-client.ts
621
765
  import { config } from "dotenv";
622
- var KintoneApiClient = class {
623
- #baseUrl;
624
- #authHeader;
625
- constructor() {
626
- config();
627
- const {
628
- KINTONE_BASE_URL,
629
- KINTONE_USERNAME,
630
- KINTONE_PASSWORD,
631
- KINTONE_BASIC_AUTH_USERNAME = "",
632
- KINTONE_BASIC_AUTH_PASSWORD = ""
633
- } = process.env;
634
- if (!KINTONE_BASE_URL || !KINTONE_USERNAME || !KINTONE_PASSWORD) {
635
- throw new Error(`.env\u306E\u8A2D\u5B9A\u304C\u4E0D\u5341\u5206\u3067\u3059\u3002\u4EE5\u4E0B\u306E\u30D1\u30E9\u30E1\u30FC\u30BF\u306F\u5FC5\u9808\u3067\u3059
766
+ import { KintoneRestAPIClient } from "@kintone/rest-api-client";
767
+ function createKintoneClient() {
768
+ config();
769
+ const {
770
+ KINTONE_BASE_URL,
771
+ KINTONE_USERNAME,
772
+ KINTONE_PASSWORD,
773
+ KINTONE_BASIC_AUTH_USERNAME,
774
+ KINTONE_BASIC_AUTH_PASSWORD
775
+ } = process.env;
776
+ if (!KINTONE_BASE_URL || !KINTONE_USERNAME || !KINTONE_PASSWORD) {
777
+ throw new Error(`.env\u306E\u8A2D\u5B9A\u304C\u4E0D\u5341\u5206\u3067\u3059\u3002\u4EE5\u4E0B\u306E\u30D1\u30E9\u30E1\u30FC\u30BF\u306F\u5FC5\u9808\u3067\u3059
636
778
  KINTONE_BASE_URL
637
779
  KINTONE_USERNAME
638
780
  KINTONE_PASSWORD`);
639
- }
640
- const authHeader = {
641
- "X-Cybozu-Authorization": Buffer.from(`${KINTONE_USERNAME}:${KINTONE_PASSWORD}`).toString(
642
- "base64"
643
- ),
644
- ...KINTONE_BASIC_AUTH_USERNAME && KINTONE_BASIC_AUTH_PASSWORD && {
645
- Authorization: `Basic ${Buffer.from(
646
- `${KINTONE_BASIC_AUTH_USERNAME}:${KINTONE_BASIC_AUTH_PASSWORD}`
647
- ).toString("base64")}`
648
- }
649
- };
650
- this.#baseUrl = KINTONE_BASE_URL;
651
- this.#authHeader = authHeader;
652
781
  }
653
- getEndpointUrl(path16) {
654
- return `${this.#baseUrl}${path16}`;
655
- }
656
- async upload(params) {
657
- const { blob, fileName } = params;
658
- const form = new FormData();
659
- form.append("file", blob, fileName);
660
- const uploadResult = await fetch(this.getEndpointUrl("/k/v1/file.json"), {
661
- method: "POST",
662
- headers: this.#authHeader,
663
- body: form
664
- });
665
- const { fileKey } = await uploadResult.json();
666
- return fileKey;
667
- }
668
- async getPlugins(params = {}) {
669
- const url = new URL(this.getEndpointUrl("/k/v1/plugins.json"));
670
- if (params.offset) {
671
- url.searchParams.set("offset", String(params.offset));
672
- }
673
- if (params.limit) {
674
- url.searchParams.set("limit", String(params.limit));
675
- }
676
- const pluginResponse = await fetch(url.toString(), {
677
- headers: this.#authHeader
678
- });
679
- return pluginResponse.json();
680
- }
681
- async getAllPlugins() {
682
- const plugins = [];
683
- let offset = 0;
684
- let limit = 100;
685
- let hasMore = true;
686
- while (hasMore) {
687
- const { plugins: currentPlugins } = await this.getPlugins({ offset, limit });
688
- plugins.push(...currentPlugins);
689
- if (currentPlugins.length < limit) {
690
- hasMore = false;
691
- } else {
692
- offset += limit;
782
+ return new KintoneRestAPIClient({
783
+ baseUrl: KINTONE_BASE_URL,
784
+ auth: {
785
+ username: KINTONE_USERNAME,
786
+ password: KINTONE_PASSWORD
787
+ },
788
+ ...KINTONE_BASIC_AUTH_USERNAME && KINTONE_BASIC_AUTH_PASSWORD ? {
789
+ basicAuth: {
790
+ username: KINTONE_BASIC_AUTH_USERNAME,
791
+ password: KINTONE_BASIC_AUTH_PASSWORD
693
792
  }
694
- }
695
- return plugins;
696
- }
697
- async addPlugin(params) {
698
- const { fileKey } = params;
699
- const pluginResponse = await fetch(this.getEndpointUrl("/k/v1/plugin.json"), {
700
- method: "POST",
701
- headers: {
702
- "Content-Type": "application/json",
703
- ...this.#authHeader
704
- },
705
- body: JSON.stringify({
706
- fileKey
707
- })
708
- });
709
- return pluginResponse.json();
710
- }
711
- async updatePlugin(params) {
712
- const pluginResponse = await fetch(this.getEndpointUrl("/k/v1/plugin.json"), {
713
- method: "PUT",
714
- headers: {
715
- "Content-Type": "application/json",
716
- ...this.#authHeader
717
- },
718
- body: JSON.stringify(params)
719
- });
720
- return pluginResponse.json();
721
- }
722
- };
723
-
724
- // src/lib/utils.ts
725
- import fs8 from "fs-extra";
726
- import path11 from "path";
727
- var isEnv = (env) => {
728
- return ["prod", "dev", "standalone"].includes(env);
729
- };
730
- var apiUploadZip = async (params) => {
731
- const { env, pluginId } = params;
732
- const kc = new KintoneApiClient();
733
- const zipFileName = `plugin${getZipFileNameSuffix(env)}.zip`;
734
- const zipFile = new Blob([await fs8.readFile(path11.join(PLUGIN_WORKSPACE_DIRECTORY, zipFileName))]);
735
- const fileKey = await kc.upload({ blob: zipFile, fileName: zipFileName });
736
- const plugins = await kc.getAllPlugins();
737
- const plugin = plugins.find((p) => p.id === pluginId);
738
- if (plugin) {
739
- const json = await kc.updatePlugin({ id: pluginId, fileKey });
740
- if ("errors" in json && json.errors) {
741
- console.error((json.errors.id?.messages ?? []).map((m) => `Error: ${m}`).join("\n"));
742
- }
793
+ } : {}
794
+ });
795
+ }
796
+ async function uploadPlugin(params) {
797
+ const client = createKintoneClient();
798
+ const { fileKey } = await client.file.uploadFile({
799
+ file: { name: params.file.name, data: new Uint8Array(params.file.data) }
800
+ });
801
+ const { plugins } = await client.plugin.getPlugins({ offset: 0, limit: 100 });
802
+ const isUpdate = plugins.some(({ id }) => id === params.pluginId);
803
+ if (isUpdate) {
804
+ await client.plugin.updatePlugin({ id: params.pluginId, fileKey });
743
805
  return { method: "PUT" };
744
806
  }
745
- const result = await kc.addPlugin({ fileKey });
746
- if ("code" in result) {
747
- console.error(`Error: ${result.message}`);
748
- }
807
+ await client.plugin.installPlugin({ fileKey });
749
808
  return { method: "POST" };
750
- };
809
+ }
751
810
 
752
811
  // src/commands/plugin-dev/upload.ts
753
- import chokider from "chokidar";
754
- import chalk4 from "chalk";
812
+ import fs9 from "fs-extra";
813
+ import path12 from "path";
814
+ import chokidar2 from "chokidar";
815
+ import chalk3 from "chalk";
755
816
  var watchContentsAndUploadZip = async (params) => {
756
817
  const { manifest, ppkPath } = params;
757
818
  let initialScanComplete = false;
@@ -762,30 +823,34 @@ var watchContentsAndUploadZip = async (params) => {
762
823
  }
763
824
  await copyPluginContents();
764
825
  console.log(
765
- chalk4.hex("#e5e7eb")(`${(/* @__PURE__ */ new Date()).toLocaleTimeString()} `) + chalk4.cyan(`[contents] `) + `updated`
826
+ chalk3.hex("#e5e7eb")(`${(/* @__PURE__ */ new Date()).toLocaleTimeString()} `) + chalk3.cyan(`[contents] `) + `updated`
766
827
  );
767
828
  } catch (error) {
768
829
  console.error("Error copying plugin contents:", error);
769
830
  return;
770
831
  }
771
832
  try {
772
- await outputContentsZip(manifest);
773
- const buffer = await getContentsZipBuffer();
774
- const pluginPrivateKey = await fs9.readFile(path12.resolve(ppkPath), "utf8");
775
- const output = await packer(buffer, pluginPrivateKey);
833
+ const contentsZip = createContentsZipFromDir(manifest);
834
+ const { zip, id: pluginId } = createPluginZip({
835
+ ppkPath: path12.resolve(ppkPath),
836
+ contentsZip
837
+ });
776
838
  const zipFileName = `plugin${getZipFileNameSuffix("dev")}.zip`;
777
- await fs9.writeFile(path12.join(PLUGIN_WORKSPACE_DIRECTORY, zipFileName), output.plugin);
778
- const { method } = await apiUploadZip({ env: "dev", pluginId: output.id });
839
+ await fs9.writeFile(path12.join(PLUGIN_WORKSPACE_DIRECTORY, zipFileName), zip);
840
+ const { method } = await uploadPlugin({
841
+ pluginId,
842
+ file: { name: zipFileName, data: zip }
843
+ });
779
844
  console.log(
780
- chalk4.hex("#e5e7eb")(`${(/* @__PURE__ */ new Date()).toLocaleTimeString()} `) + chalk4.cyan(`[upload] `) + `uploaded ${method === "POST" ? "(new)" : "(update)"}`
845
+ chalk3.hex("#e5e7eb")(`${(/* @__PURE__ */ new Date()).toLocaleTimeString()} `) + chalk3.cyan(`[upload] `) + `uploaded ${method === "POST" ? "(new)" : "(update)"}`
781
846
  );
782
847
  } catch (error) {
783
848
  console.log(
784
- chalk4.hex("#e5e7eb")(`${(/* @__PURE__ */ new Date()).toLocaleTimeString()} `) + chalk4.cyan(`[upload] `) + chalk4.red(`failed`) + chalk4.hex("#e5e7eb")(`: ${error?.message ?? "Unknown error"}`)
849
+ chalk3.hex("#e5e7eb")(`${(/* @__PURE__ */ new Date()).toLocaleTimeString()} `) + chalk3.cyan(`[upload] `) + chalk3.red(`failed`) + chalk3.hex("#e5e7eb")(`: ${error?.message ?? "Unknown error"}`)
785
850
  );
786
851
  }
787
852
  };
788
- const contentsWatcher = chokider.watch(["src/contents/**/*"], {
853
+ const contentsWatcher = chokidar2.watch(["src/contents/**/*"], {
789
854
  ignored: /node_modules/,
790
855
  persistent: true
791
856
  });
@@ -799,12 +864,12 @@ var watchContentsAndUploadZip = async (params) => {
799
864
  };
800
865
 
801
866
  // src/commands/plugin-dev/index.ts
802
- function command3() {
803
- program3.command("dev").option(
867
+ function command2() {
868
+ program2.command("dev").option(
804
869
  "-p, --ppk <ppk>",
805
870
  ".ppk file path",
806
871
  path13.join(PLUGIN_WORKSPACE_DIRECTORY, "private.ppk")
807
- ).option("-c, --cert-dir <certDir>", "Certificate directory", PLUGIN_WORKSPACE_DIRECTORY).description("Start development server with Vite.").action(action2);
872
+ ).option("-c, --cert-dir <certDir>", "Certificate directory", PLUGIN_WORKSPACE_DIRECTORY).description("Start development server with rsbuild.").action(action2);
808
873
  }
809
874
  async function action2(options) {
810
875
  console.group("\u{1F373} Start development server");
@@ -818,15 +883,12 @@ async function action2(options) {
818
883
  }
819
884
  const port = config2.server?.port ?? DEFAULT_PORT;
820
885
  if (!hasCertificates(certDirPath)) {
821
- console.log(chalk5.yellow("\u{1F4DC} SSL certificates not found. Generating..."));
886
+ console.log(chalk4.yellow("\u{1F4DC} SSL certificates not found. Generating with node-forge..."));
822
887
  try {
823
- await generateCert(certDirPath);
824
- console.log(chalk5.green("\u2705 SSL certificates generated successfully"));
888
+ generateCert(certDirPath);
889
+ console.log(chalk4.green("\u2705 SSL certificates generated successfully"));
825
890
  } catch (error) {
826
- console.log(
827
- chalk5.red("\u274C Failed to generate SSL certificates. Make sure mkcert is installed.")
828
- );
829
- console.log(chalk5.gray(" Install mkcert: https://github.com/FiloSottile/mkcert"));
891
+ console.log(chalk4.red("\u274C Failed to generate SSL certificates."));
830
892
  throw error;
831
893
  }
832
894
  }
@@ -840,83 +902,28 @@ async function action2(options) {
840
902
  if (entryNames.length === 0) {
841
903
  throw new Error("No entry points found for plugin. Check src/config and src/desktop paths.");
842
904
  }
843
- console.log(chalk5.gray(` Entry points: ${entryNames.join(", ")}`));
905
+ console.log(chalk4.gray(` Entry points: ${entryNames.join(", ")}`));
844
906
  const { key, cert } = loadCertificates(certDirPath);
845
- console.log(chalk5.gray(" Building..."));
846
- await buildEntriesWithVite({
907
+ const { port: actualPort } = await startRsbuildDevServer({
847
908
  entries,
848
909
  outDir: outputDir,
849
- mode: "development",
850
- sourcemap: "inline",
851
- minify: false
852
- });
853
- const serverConfig = createViteConfig({
854
- root: outputDir,
855
- server: {
856
- port,
857
- https: { key, cert }
858
- }
859
- });
860
- const server = await createServer(serverConfig);
861
- await server.listen();
862
- console.log(chalk5.green(`
910
+ port,
911
+ https: { key, cert },
912
+ publicDir: outputDir,
913
+ onFirstCompile: () => {
914
+ console.log(chalk4.green(`
863
915
  \u2728 Plugin development server ready!`));
864
- console.log(chalk5.cyan(` Local: https://localhost:${port}`));
865
- console.log(chalk5.gray(` Output: ${outputDir}`));
866
- console.log(chalk5.gray(` Files: config.js, desktop.js`));
867
- console.log(chalk5.gray("\n Watching for changes...\n"));
868
- const chokidar2 = await import("chokidar");
869
- const watchDirs = [
870
- path13.resolve("src", "config"),
871
- path13.resolve("src", "desktop"),
872
- path13.resolve("src", "lib")
873
- ].filter((dir) => fs10.existsSync(dir));
874
- console.log(chalk5.gray(` Watching directories: ${watchDirs.join(", ")}`));
875
- const watcher = chokidar2.watch(watchDirs, {
876
- ignored: /node_modules/,
877
- persistent: true,
878
- ignoreInitial: true
879
- });
880
- const watchExtensions = [".ts", ".tsx", ".js", ".jsx", ".css", ".scss"];
881
- const shouldRebuild = (filePath) => {
882
- const ext = path13.extname(filePath).toLowerCase();
883
- return watchExtensions.includes(ext);
884
- };
885
- const rebuild = async () => {
886
- console.log(chalk5.gray(` ${(/* @__PURE__ */ new Date()).toLocaleTimeString()} Rebuilding...`));
887
- await buildEntriesWithVite({
888
- entries,
889
- outDir: outputDir,
890
- mode: "development",
891
- sourcemap: "inline",
892
- minify: false
893
- });
894
- console.log(chalk5.gray(` ${(/* @__PURE__ */ new Date()).toLocaleTimeString()} Rebuild complete`));
895
- };
896
- watcher.on("ready", () => {
897
- console.log(chalk5.green(" \u2713 File watcher ready"));
898
- });
899
- watcher.on("change", (filePath) => {
900
- if (shouldRebuild(filePath)) {
901
- console.log(chalk5.cyan(` [change] ${filePath}`));
902
- rebuild();
903
- }
904
- });
905
- watcher.on("add", (filePath) => {
906
- if (shouldRebuild(filePath)) {
907
- console.log(chalk5.cyan(` [add] ${filePath}`));
908
- rebuild();
909
- }
910
- });
911
- watcher.on("unlink", (filePath) => {
912
- if (shouldRebuild(filePath)) {
913
- console.log(chalk5.cyan(` [unlink] ${filePath}`));
914
- rebuild();
916
+ console.log(chalk4.cyan(` Local: https://localhost:${actualPort}`));
917
+ console.log(chalk4.gray(` Output: ${outputDir}`));
918
+ console.log(chalk4.gray(` Files: config.js, desktop.js`));
919
+ console.log(chalk4.gray("\n Watching for changes...\n"));
920
+ },
921
+ onRecompile: () => {
922
+ console.log(
923
+ chalk4.hex("#e5e7eb")(`${(/* @__PURE__ */ new Date()).toLocaleTimeString()} `) + chalk4.cyan(`[rsbuild] `) + `rebuild complete`
924
+ );
915
925
  }
916
926
  });
917
- watcher.on("error", (error) => {
918
- console.error(chalk5.red(` Watcher error: ${error}`));
919
- });
920
927
  Promise.all([watchContentsAndUploadZip({ manifest, ppkPath }), watchCss(config2)]);
921
928
  } catch (error) {
922
929
  throw error;
@@ -926,18 +933,15 @@ async function action2(options) {
926
933
  }
927
934
 
928
935
  // src/commands/plugin-genkey.ts
929
- import { program as program4 } from "commander";
930
-
931
- // src/commands/genkey-base.ts
932
- async function action3(options) {
933
- const { output } = options;
934
- console.group("\u{1F373} Generate SSL key for localhost");
936
+ import { program as program3 } from "commander";
937
+ function command3() {
938
+ program3.command("genkey").description("Generate SSL certificate for localhost using node-forge.").action(action3);
939
+ }
940
+ async function action3() {
941
+ console.group("\u{1F373} Generate SSL certificate for localhost");
935
942
  try {
936
- const { stdout } = await generateCert(output);
937
- if (stdout) {
938
- console.log(stdout);
939
- }
940
- console.log(`\u{1F511} key generation success. Output to ./${output}`);
943
+ generateCert(PLUGIN_WORKSPACE_DIRECTORY);
944
+ console.log(`\u{1F511} Certificate generated. Output to ./${PLUGIN_WORKSPACE_DIRECTORY}`);
941
945
  } catch (error) {
942
946
  throw error;
943
947
  } finally {
@@ -945,44 +949,29 @@ async function action3(options) {
945
949
  }
946
950
  }
947
951
 
948
- // src/commands/plugin-genkey.ts
949
- function command4() {
950
- program4.command("genkey").description("Generate SSL key for localhost. (Require mkcert)").action(action4);
951
- }
952
- async function action4() {
953
- await action3({ output: PLUGIN_WORKSPACE_DIRECTORY });
954
- }
955
-
956
952
  // src/commands/plugin-init.ts
957
- import { program as program5 } from "commander";
953
+ import { program as program4 } from "commander";
958
954
  import fs11 from "fs-extra";
959
955
  import path14 from "path";
960
- import packer2 from "@kintone/plugin-packer";
961
- function command5() {
962
- program5.command("init").description("generate private.ppk and kitting config").action(action5);
956
+ function command4() {
957
+ program4.command("init").description("generate private.ppk and kitting config").action(action4);
963
958
  }
964
- async function action5() {
959
+ async function action4() {
965
960
  console.group("\u{1F373} Executing plugin initialization setup");
966
961
  try {
967
962
  const manifest = await outputManifest("dev");
968
963
  console.log("\u{1F4DD} manifest.json generated");
969
964
  await copyPluginContents();
970
965
  console.log("\u{1F4C1} contents copied");
971
- let privateKey;
972
- const keyPath = path14.join(PLUGIN_WORKSPACE_DIRECTORY, "private.ppk");
973
- if (fs11.existsSync(keyPath)) {
974
- privateKey = await fs11.readFile(keyPath, "utf8");
975
- }
976
- await outputContentsZip(manifest);
977
- const buffer = await getContentsZipBuffer();
978
- const output = await packer2(buffer, privateKey);
979
- if (!privateKey) {
980
- await fs11.writeFile(path14.join(PLUGIN_WORKSPACE_DIRECTORY, "private.ppk"), output.privateKey);
966
+ const ppkPath = path14.join(PLUGIN_WORKSPACE_DIRECTORY, "private.ppk");
967
+ const contentsZip = createContentsZipFromDir(manifest);
968
+ const { zip, privateKey } = createPluginZip({ ppkPath, contentsZip });
969
+ if (!fs11.existsSync(ppkPath)) {
981
970
  console.log("\u{1F511} private.ppk generated");
982
971
  } else {
983
972
  console.log("\u{1F511} private.ppk already exists. The existing private.ppk will be used.");
984
973
  }
985
- await fs11.writeFile(path14.join(PLUGIN_WORKSPACE_DIRECTORY, "plugin.zip"), output.plugin);
974
+ await fs11.writeFile(path14.join(PLUGIN_WORKSPACE_DIRECTORY, "plugin.zip"), zip);
986
975
  console.log("\u{1F4E6} plugin.zip generated");
987
976
  console.log("\u2728 Plugin initialization setup completed! zip file path is ./.plugin/plugin.zip");
988
977
  } catch (error) {
@@ -993,11 +982,11 @@ async function action5() {
993
982
  }
994
983
 
995
984
  // src/commands/manifest/index.ts
996
- import { program as program6 } from "commander";
997
- function command6() {
998
- program6.command("manifest").option("-e, --env <env>", "create manifest", "prod").action(action6);
985
+ import { program as program5 } from "commander";
986
+ function command5() {
987
+ program5.command("manifest").option("-e, --env <env>", "create manifest", "prod").action(action5);
999
988
  }
1000
- async function action6(options) {
989
+ async function action5(options) {
1001
990
  console.group("\u{1F680} Executing manifest generation");
1002
991
  try {
1003
992
  const { env } = options;
@@ -1016,12 +1005,12 @@ async function action6(options) {
1016
1005
  }
1017
1006
 
1018
1007
  // src/commands/test/index.ts
1019
- import { program as program7 } from "commander";
1008
+ import { program as program6 } from "commander";
1020
1009
  import fs12 from "fs-extra";
1021
- function command7() {
1022
- program7.command("test").description("test").action(action7);
1010
+ function command6() {
1011
+ program6.command("test").description("test").action(action6);
1023
1012
  }
1024
- async function action7() {
1013
+ async function action6() {
1025
1014
  console.group("package.json");
1026
1015
  const packageJson = fs12.readJSONSync("package.json");
1027
1016
  console.log("package.json detected");
@@ -1033,18 +1022,26 @@ async function action7() {
1033
1022
  }
1034
1023
 
1035
1024
  // src/commands/plugin-zip.ts
1036
- import { program as program8 } from "commander";
1025
+ import { program as program7 } from "commander";
1026
+ import fs14 from "fs-extra";
1027
+ import path16 from "path";
1028
+
1029
+ // src/lib/utils.ts
1037
1030
  import fs13 from "fs-extra";
1038
1031
  import path15 from "path";
1039
- import packer3 from "@kintone/plugin-packer";
1040
- function command8() {
1041
- program8.command("zip").description("generate plugin zip").option("-e, --env <env>", "plugin environment (dev, prod, standalone)", "prod").option(
1032
+ var isEnv = (env) => {
1033
+ return ["prod", "dev", "standalone"].includes(env);
1034
+ };
1035
+
1036
+ // src/commands/plugin-zip.ts
1037
+ function command7() {
1038
+ program7.command("zip").description("generate plugin zip").option("-e, --env <env>", "plugin environment (dev, prod, standalone)", "prod").option(
1042
1039
  "-p, --ppk <ppk>",
1043
1040
  ".ppk file path",
1044
- path15.join(PLUGIN_WORKSPACE_DIRECTORY, "private.ppk")
1045
- ).action(action8);
1041
+ path16.join(PLUGIN_WORKSPACE_DIRECTORY, "private.ppk")
1042
+ ).action(action7);
1046
1043
  }
1047
- async function action8(options) {
1044
+ async function action7(options) {
1048
1045
  console.group("\u{1F373} Executing plugin zip generation");
1049
1046
  try {
1050
1047
  const { env, ppk: ppkPath } = options;
@@ -1055,18 +1052,17 @@ async function action8(options) {
1055
1052
  console.log("\u{1F4C1} contents copied");
1056
1053
  const manifest = await outputManifest(env);
1057
1054
  console.log(`\u{1F4DD} manifest.json generated (${env})`);
1058
- await outputContentsZip(manifest);
1055
+ const contentsZip = createContentsZipFromDir(manifest);
1059
1056
  console.log("\u{1F4E6} contents.zip generated");
1060
- const buffer = await getContentsZipBuffer();
1061
- const privateKey = await fs13.readFile(path15.resolve(ppkPath), "utf8");
1062
- const output = await packer3(buffer, privateKey);
1057
+ const { zip, id } = createPluginZip({ ppkPath: path16.resolve(ppkPath), contentsZip });
1063
1058
  const zipFileName = `plugin${getZipFileNameSuffix(env)}.zip`;
1064
- await fs13.writeFile(path15.join(PLUGIN_WORKSPACE_DIRECTORY, zipFileName), output.plugin);
1059
+ await fs14.writeFile(path16.join(PLUGIN_WORKSPACE_DIRECTORY, zipFileName), zip);
1065
1060
  console.log("\u{1F4E6} plugin.zip generated");
1066
1061
  const version = String(manifest.version);
1067
- await fs13.writeFile(path15.join(PLUGIN_WORKSPACE_DIRECTORY, "version"), version);
1062
+ await fs14.writeFile(path16.join(PLUGIN_WORKSPACE_DIRECTORY, "version"), version);
1068
1063
  console.log(`\u{1F4DD} version file generated (${version})`);
1069
1064
  console.log(`\u2728 Plugin zip generation completed! zip file path is ./.plugin/${zipFileName}`);
1065
+ console.log(` Plugin ID: ${id}`);
1070
1066
  } catch (error) {
1071
1067
  throw error;
1072
1068
  } finally {
@@ -1075,11 +1071,11 @@ async function action8(options) {
1075
1071
  }
1076
1072
 
1077
1073
  // src/commands/lint.ts
1078
- import { program as program9 } from "commander";
1079
- function command9() {
1080
- program9.command("lint").description("Lint source files").option("-c, --config <config>", "Config file path").action(action9);
1074
+ import { program as program8 } from "commander";
1075
+ function command8() {
1076
+ program8.command("lint").description("Lint source files").option("-c, --config <config>", "Config file path").action(action8);
1081
1077
  }
1082
- async function action9(options) {
1078
+ async function action8(options) {
1083
1079
  try {
1084
1080
  lint();
1085
1081
  } catch (error) {
@@ -1089,7 +1085,7 @@ async function action9(options) {
1089
1085
  }
1090
1086
 
1091
1087
  // src/plugin.ts
1092
- program10.name("plugin").version("1.12.0").description("\u{1F373} kintone kitchen \u{1F373} for kintone plugin");
1088
+ program9.name("plugin").version("4.0.0").description("\u{1F373} kintone kitchen \u{1F373} for kintone plugin");
1093
1089
  command();
1094
1090
  command2();
1095
1091
  command3();
@@ -1098,6 +1094,5 @@ command5();
1098
1094
  command6();
1099
1095
  command7();
1100
1096
  command8();
1101
- command9();
1102
- program10.parse(process.argv);
1097
+ program9.parse(process.argv);
1103
1098
  //# sourceMappingURL=plugin.js.map