@konomi-app/k2 3.4.1 → 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,188 +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
- format: "iife",
283
- // 外部ライブラリのソースマップを無視して警告を抑制
284
- sourcemapIgnoreList: (relativeSourcePath) => {
285
- return relativeSourcePath.includes("node_modules");
286
- },
287
- ...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
+ });
288
228
  }
289
- },
290
- outDir,
291
- emptyOutDir: false,
292
- sourcemap,
293
- minify,
294
- cssCodeSplit: false
295
- }
296
- });
297
- await viteBuild(config2);
298
- const outputPath = path4.join(outDir, `${name}.js`);
299
- if (fs2.existsSync(outputPath)) {
300
- const content = await fs2.readFile(outputPath, "utf-8");
301
- const wrapped = `(function(){
302
- ${content}
303
- })();`;
304
- await fs2.writeFile(outputPath, wrapped);
305
- }
306
- }
307
- var ENTRY_FILE_NAMES = ["index.ts", "index.tsx", "index.js", "index.jsx", "index.mjs"];
308
- function findEntryPoint(basePath) {
309
- for (const filename of ENTRY_FILE_NAMES) {
310
- const entryPath = path4.join(basePath, filename);
311
- if (fs2.existsSync(entryPath)) {
312
- return entryPath;
313
- }
314
- }
315
- if (fs2.existsSync(basePath) && fs2.statSync(basePath).isFile()) {
316
- return basePath;
229
+ }
230
+ ]);
317
231
  }
318
- return null;
232
+ const result = await rsbuild.startDevServer();
233
+ return {
234
+ port: result.port,
235
+ close: result.server.close
236
+ };
319
237
  }
320
- function getPluginEntryPoints(options) {
238
+ function getPluginEntryPoints(params) {
239
+ const { configEntry, desktopEntry } = params;
321
240
  const entries = {};
322
- const configPath = findEntryPoint(options.configEntry);
323
- if (configPath) {
324
- entries["config"] = configPath;
325
- } else {
326
- 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
+ }
327
247
  }
328
- const desktopPath = findEntryPoint(options.desktopEntry);
329
- if (desktopPath) {
330
- entries["desktop"] = desktopPath;
331
- } else {
332
- 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
+ }
333
254
  }
334
255
  return entries;
335
256
  }
336
257
 
337
258
  // src/commands/plugin-build.ts
338
259
  function command() {
339
- 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);
340
261
  }
341
262
  async function action() {
342
- console.group("\u{1F373} Build the project for production");
263
+ console.group("\u{1F373} Build the plugin for production");
343
264
  try {
344
265
  const config2 = await importK2PluginConfig();
345
266
  if (config2?.lint?.build) {
@@ -349,6 +270,24 @@ async function action() {
349
270
  if (!fs3.existsSync(PLUGIN_CONTENTS_DIRECTORY)) {
350
271
  await fs3.mkdir(PLUGIN_CONTENTS_DIRECTORY, { recursive: true });
351
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
+ }
352
291
  const entries = getPluginEntryPoints({
353
292
  configEntry: path5.resolve("src", "config"),
354
293
  desktopEntry: path5.resolve("src", "desktop")
@@ -357,36 +296,15 @@ async function action() {
357
296
  if (entryNames.length === 0) {
358
297
  throw new Error("No entry points found for plugin. Check src/config and src/desktop paths.");
359
298
  }
360
- console.log(chalk2.gray(` Entry points: ${entryNames.join(", ")}`));
361
- const buildTasks = [];
362
- if (config2.tailwind?.css && config2.tailwind?.config) {
363
- const tailwindConfig = await getTailwindConfig(config2.tailwind);
364
- const inputFile = getTailwindInputCss(config2.tailwind);
365
- buildTasks.push(
366
- outputCss({
367
- inputPath: inputFile.config,
368
- outputPath: path5.join(PLUGIN_CONTENTS_DIRECTORY, "config.css"),
369
- config: tailwindConfig.config,
370
- minify: true
371
- }).then(() => console.log("\u2728 Built config.css")),
372
- outputCss({
373
- inputPath: inputFile.desktop,
374
- outputPath: path5.join(PLUGIN_CONTENTS_DIRECTORY, "desktop.css"),
375
- config: tailwindConfig.desktop,
376
- minify: true
377
- }).then(() => console.log("\u2728 Built desktop.css"))
378
- );
379
- }
380
- buildTasks.push(
381
- buildEntriesWithVite({
382
- entries,
383
- outDir: PLUGIN_CONTENTS_DIRECTORY,
384
- mode: "production",
385
- sourcemap: false,
386
- minify: true
387
- }).then(() => console.log("\u2728 Built desktop.js and config.js"))
388
- );
389
- 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");
390
308
  console.log("\u2728 Build success.");
391
309
  } catch (error) {
392
310
  throw error;
@@ -395,65 +313,245 @@ async function action() {
395
313
  }
396
314
  }
397
315
 
398
- // src/commands/plugin-esbuild.ts
399
- import { program as program2 } from "commander";
400
- function command2() {
401
- program2.command("esbuild").description(
402
- "[DEPRECATED] Build the project for production with esbuild. (Use `plugin build` instead.)"
403
- ).action(action);
404
- }
405
-
406
316
  // src/commands/plugin-dev/index.ts
407
- import { program as program3 } from "commander";
408
- import { createServer } from "vite";
317
+ import { program as program2 } from "commander";
409
318
  import fs10 from "fs-extra";
410
319
  import path13 from "path";
411
- import chalk5 from "chalk";
412
-
413
- // src/lib/exec.ts
414
- import { exec as defaultExec } from "child_process";
415
- import { promisify } from "util";
416
- var exec = promisify(defaultExec);
320
+ import chalk4 from "chalk";
417
321
 
418
- // src/lib/cert.ts
322
+ // src/lib/cert/index.ts
419
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
420
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
421
496
  var CERT_KEY_FILENAME = "localhost-key.pem";
422
497
  var CERT_FILENAME = "localhost-cert.pem";
423
- var generateCert = async (outDir) => {
424
- await fs4.ensureDir(outDir);
425
- const { stdout } = await exec(`mkcert localhost 127.0.0.1 ::1`);
426
- [
427
- { input: "localhost+2.pem", output: CERT_FILENAME },
428
- { input: "localhost+2-key.pem", output: CERT_KEY_FILENAME }
429
- ].forEach(({ input, output }) => {
430
- if (fs4.existsSync(input)) {
431
- fs4.moveSync(`./${input}`, path6.join(outDir, output), {
432
- overwrite: true
433
- });
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
+ );
434
513
  }
435
- });
436
- return { stdout };
437
- };
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
+ }
438
536
  function hasCertificates(certDir) {
439
- 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));
440
538
  }
441
539
  function loadCertificates(certDir) {
442
540
  return {
443
- key: fs4.readFileSync(path6.join(certDir, CERT_KEY_FILENAME)),
444
- 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))
445
543
  };
446
544
  }
447
545
 
448
546
  // src/lib/plugin-manifest.ts
449
547
  import fs5 from "fs-extra";
450
- import path7 from "path";
548
+ import path8 from "path";
451
549
  import merge from "deepmerge";
452
550
  var outputManifest = async (env, options) => {
453
551
  const config2 = options?.config || await importK2PluginConfig();
454
552
  const merged = merge(config2.manifest.base, config2.manifest[env] || {});
455
553
  await fs5.mkdirs(PLUGIN_CONTENTS_DIRECTORY);
456
- await fs5.writeJson(path7.join(PLUGIN_CONTENTS_DIRECTORY, "manifest.json"), merged);
554
+ await fs5.writeJson(path8.join(PLUGIN_CONTENTS_DIRECTORY, "manifest.json"), merged);
457
555
  return merged;
458
556
  };
459
557
 
@@ -488,21 +586,21 @@ var getManifest = async (params) => {
488
586
  };
489
587
 
490
588
  // src/commands/plugin-dev/tailwind.ts
491
- import path8 from "path";
589
+ import path9 from "path";
492
590
  import "tailwindcss";
493
- import chalk3 from "chalk";
591
+ import chalk2 from "chalk";
494
592
  async function buildTailwindCSS(params) {
495
593
  const { inputFile, outputFileName, config: config2 } = params;
496
- const inputPath = path8.resolve(inputFile);
497
- const outputPath = path8.join(PLUGIN_DEVELOPMENT_DIRECTORY, outputFileName);
594
+ const inputPath = path9.resolve(inputFile);
595
+ const outputPath = path9.join(PLUGIN_DEVELOPMENT_DIRECTORY, outputFileName);
498
596
  return watchTailwindCSS({
499
597
  input: inputPath,
500
598
  output: outputPath,
501
599
  config: config2,
502
600
  onChanges: ({ output, type }) => {
503
- const outputFileName2 = path8.basename(output);
601
+ const outputFileName2 = path9.basename(output);
504
602
  console.log(
505
- 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`)
506
604
  );
507
605
  }
508
606
  });
@@ -527,20 +625,17 @@ var watchCss = async (pluginConfig) => {
527
625
  ]);
528
626
  };
529
627
 
530
- // src/commands/plugin-dev/upload.ts
531
- import packer from "@kintone/plugin-packer";
532
-
533
628
  // src/lib/plugin-contents.ts
534
629
  import fs6 from "fs-extra";
535
- import path9 from "path";
630
+ import path10 from "path";
536
631
  import htmlMinifier from "html-minifier";
537
632
  var copyPluginContents = async (params = {}) => {
538
- const { inputDir = path9.join("src", "contents"), outputDir = PLUGIN_CONTENTS_DIRECTORY } = params;
633
+ const { inputDir = path10.join("src", "contents"), outputDir = PLUGIN_CONTENTS_DIRECTORY } = params;
539
634
  if (!fs6.existsSync(inputDir)) {
540
635
  await fs6.mkdir(inputDir, { recursive: true });
541
636
  }
542
637
  await fs6.copy(inputDir, outputDir, { overwrite: true });
543
- const configHtmlPath = path9.join(outputDir, "config.html");
638
+ const configHtmlPath = path10.join(outputDir, "config.html");
544
639
  if (!fs6.existsSync(configHtmlPath)) {
545
640
  throw new Error(`Plugin HTML file not found. Create "config.html" in ${inputDir}.`);
546
641
  }
@@ -559,208 +654,165 @@ var copyPluginContents = async (params = {}) => {
559
654
  };
560
655
 
561
656
  // src/lib/zip.ts
562
- 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";
563
663
  import fs7 from "fs-extra";
564
- import path10 from "path";
565
- import invariant2 from "tiny-invariant";
566
- var outputContentsZip = async (manifest) => {
567
- const archive = archiver("zip", { zlib: { level: 9 } });
568
- archive.on("warning", (error) => {
569
- if (error.code === "ENOENT") {
570
- 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);
571
716
  } else {
572
- throw error;
717
+ throw new Error(`Unsupported file content type for file: ${fileName}`);
573
718
  }
574
- });
575
- const outputZipPath = path10.join(PLUGIN_WORKSPACE_DIRECTORY, "contents.zip");
576
- const outputZipStream = fs7.createWriteStream(outputZipPath);
577
- outputZipStream.on("close", () => {
578
- console.log(`\u{1F4E6} ${archive.pointer()} total bytes`);
579
- });
580
- outputZipStream.on("end", function() {
581
- console.log("\u{1F4E6} Data has been drained");
582
- });
583
- const filterLocalContent = (file) => {
584
- return !/^https?:\/\//.test(file);
585
- };
586
- invariant2(manifest.config?.html, "manifest.config.html is required");
587
- const targetFiles = [
588
- "manifest.json",
589
- .../* @__PURE__ */ new Set([
590
- manifest.icon,
591
- manifest.config.html,
592
- ...(manifest.desktop?.js || []).filter(filterLocalContent),
593
- ...(manifest.desktop?.css || []).filter(filterLocalContent),
594
- ...(manifest.mobile?.js || []).filter(filterLocalContent),
595
- ...(manifest.mobile?.css || []).filter(filterLocalContent),
596
- ...(manifest.config.js || []).filter(filterLocalContent),
597
- ...(manifest.config.css || []).filter(filterLocalContent)
598
- ])
599
- ];
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);
600
731
  console.group("\u{1F4C1} Target files");
601
732
  targetFiles.forEach((file, i) => {
602
733
  const prefix = i === targetFiles.length - 1 ? "\u2514\u2500" : "\u251C\u2500";
603
734
  console.log(`${prefix} \u{1F4C4} ${file}`);
604
735
  });
605
736
  console.groupEnd();
606
- for (const file of targetFiles) {
607
- const filePath = path10.join(PLUGIN_CONTENTS_DIRECTORY, file);
608
- if (!fs7.existsSync(filePath)) {
609
- throw new Error(`${filePath} does not exist`);
610
- }
611
- 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);
612
749
  }
613
- archive.pipe(outputZipStream);
614
- await archive.finalize();
615
- await new Promise((resolve) => outputZipStream.on("close", resolve));
616
- };
617
- var getContentsZipBuffer = async () => {
618
- const outputZipPath = path10.join(PLUGIN_WORKSPACE_DIRECTORY, "contents.zip");
619
- return fs7.readFile(outputZipPath);
620
- };
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
+ }
621
760
  var getZipFileNameSuffix = (env) => {
622
761
  return env === "prod" ? "" : `-${env}`;
623
762
  };
624
763
 
625
- // src/commands/plugin-dev/upload.ts
626
- import fs9 from "fs-extra";
627
- import path12 from "path";
628
-
629
764
  // src/lib/kintone-api-client.ts
630
765
  import { config } from "dotenv";
631
- var KintoneApiClient = class {
632
- #baseUrl;
633
- #authHeader;
634
- constructor() {
635
- config();
636
- const {
637
- KINTONE_BASE_URL,
638
- KINTONE_USERNAME,
639
- KINTONE_PASSWORD,
640
- KINTONE_BASIC_AUTH_USERNAME = "",
641
- KINTONE_BASIC_AUTH_PASSWORD = ""
642
- } = process.env;
643
- if (!KINTONE_BASE_URL || !KINTONE_USERNAME || !KINTONE_PASSWORD) {
644
- 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
645
778
  KINTONE_BASE_URL
646
779
  KINTONE_USERNAME
647
780
  KINTONE_PASSWORD`);
648
- }
649
- const authHeader = {
650
- "X-Cybozu-Authorization": Buffer.from(`${KINTONE_USERNAME}:${KINTONE_PASSWORD}`).toString(
651
- "base64"
652
- ),
653
- ...KINTONE_BASIC_AUTH_USERNAME && KINTONE_BASIC_AUTH_PASSWORD && {
654
- Authorization: `Basic ${Buffer.from(
655
- `${KINTONE_BASIC_AUTH_USERNAME}:${KINTONE_BASIC_AUTH_PASSWORD}`
656
- ).toString("base64")}`
657
- }
658
- };
659
- this.#baseUrl = KINTONE_BASE_URL;
660
- this.#authHeader = authHeader;
661
781
  }
662
- getEndpointUrl(path16) {
663
- return `${this.#baseUrl}${path16}`;
664
- }
665
- async upload(params) {
666
- const { blob, fileName } = params;
667
- const form = new FormData();
668
- form.append("file", blob, fileName);
669
- const uploadResult = await fetch(this.getEndpointUrl("/k/v1/file.json"), {
670
- method: "POST",
671
- headers: this.#authHeader,
672
- body: form
673
- });
674
- const { fileKey } = await uploadResult.json();
675
- return fileKey;
676
- }
677
- async getPlugins(params = {}) {
678
- const url = new URL(this.getEndpointUrl("/k/v1/plugins.json"));
679
- if (params.offset) {
680
- url.searchParams.set("offset", String(params.offset));
681
- }
682
- if (params.limit) {
683
- url.searchParams.set("limit", String(params.limit));
684
- }
685
- const pluginResponse = await fetch(url.toString(), {
686
- headers: this.#authHeader
687
- });
688
- return pluginResponse.json();
689
- }
690
- async getAllPlugins() {
691
- const plugins = [];
692
- let offset = 0;
693
- let limit = 100;
694
- let hasMore = true;
695
- while (hasMore) {
696
- const { plugins: currentPlugins } = await this.getPlugins({ offset, limit });
697
- plugins.push(...currentPlugins);
698
- if (currentPlugins.length < limit) {
699
- hasMore = false;
700
- } else {
701
- 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
702
792
  }
703
- }
704
- return plugins;
705
- }
706
- async addPlugin(params) {
707
- const { fileKey } = params;
708
- const pluginResponse = await fetch(this.getEndpointUrl("/k/v1/plugin.json"), {
709
- method: "POST",
710
- headers: {
711
- "Content-Type": "application/json",
712
- ...this.#authHeader
713
- },
714
- body: JSON.stringify({
715
- fileKey
716
- })
717
- });
718
- return pluginResponse.json();
719
- }
720
- async updatePlugin(params) {
721
- const pluginResponse = await fetch(this.getEndpointUrl("/k/v1/plugin.json"), {
722
- method: "PUT",
723
- headers: {
724
- "Content-Type": "application/json",
725
- ...this.#authHeader
726
- },
727
- body: JSON.stringify(params)
728
- });
729
- return pluginResponse.json();
730
- }
731
- };
732
-
733
- // src/lib/utils.ts
734
- import fs8 from "fs-extra";
735
- import path11 from "path";
736
- var isEnv = (env) => {
737
- return ["prod", "dev", "standalone"].includes(env);
738
- };
739
- var apiUploadZip = async (params) => {
740
- const { env, pluginId } = params;
741
- const kc = new KintoneApiClient();
742
- const zipFileName = `plugin${getZipFileNameSuffix(env)}.zip`;
743
- const zipFile = new Blob([await fs8.readFile(path11.join(PLUGIN_WORKSPACE_DIRECTORY, zipFileName))]);
744
- const fileKey = await kc.upload({ blob: zipFile, fileName: zipFileName });
745
- const plugins = await kc.getAllPlugins();
746
- const plugin = plugins.find((p) => p.id === pluginId);
747
- if (plugin) {
748
- const json = await kc.updatePlugin({ id: pluginId, fileKey });
749
- if ("errors" in json && json.errors) {
750
- console.error((json.errors.id?.messages ?? []).map((m) => `Error: ${m}`).join("\n"));
751
- }
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 });
752
805
  return { method: "PUT" };
753
806
  }
754
- const result = await kc.addPlugin({ fileKey });
755
- if ("code" in result) {
756
- console.error(`Error: ${result.message}`);
757
- }
807
+ await client.plugin.installPlugin({ fileKey });
758
808
  return { method: "POST" };
759
- };
809
+ }
760
810
 
761
811
  // src/commands/plugin-dev/upload.ts
762
- import chokider from "chokidar";
763
- 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";
764
816
  var watchContentsAndUploadZip = async (params) => {
765
817
  const { manifest, ppkPath } = params;
766
818
  let initialScanComplete = false;
@@ -771,30 +823,34 @@ var watchContentsAndUploadZip = async (params) => {
771
823
  }
772
824
  await copyPluginContents();
773
825
  console.log(
774
- chalk4.hex("#e5e7eb")(`${(/* @__PURE__ */ new Date()).toLocaleTimeString()} `) + chalk4.cyan(`[contents] `) + `updated`
826
+ chalk3.hex("#e5e7eb")(`${(/* @__PURE__ */ new Date()).toLocaleTimeString()} `) + chalk3.cyan(`[contents] `) + `updated`
775
827
  );
776
828
  } catch (error) {
777
829
  console.error("Error copying plugin contents:", error);
778
830
  return;
779
831
  }
780
832
  try {
781
- await outputContentsZip(manifest);
782
- const buffer = await getContentsZipBuffer();
783
- const pluginPrivateKey = await fs9.readFile(path12.resolve(ppkPath), "utf8");
784
- 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
+ });
785
838
  const zipFileName = `plugin${getZipFileNameSuffix("dev")}.zip`;
786
- await fs9.writeFile(path12.join(PLUGIN_WORKSPACE_DIRECTORY, zipFileName), output.plugin);
787
- 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
+ });
788
844
  console.log(
789
- 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)"}`
790
846
  );
791
847
  } catch (error) {
792
848
  console.log(
793
- 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"}`)
794
850
  );
795
851
  }
796
852
  };
797
- const contentsWatcher = chokider.watch(["src/contents/**/*"], {
853
+ const contentsWatcher = chokidar2.watch(["src/contents/**/*"], {
798
854
  ignored: /node_modules/,
799
855
  persistent: true
800
856
  });
@@ -808,12 +864,12 @@ var watchContentsAndUploadZip = async (params) => {
808
864
  };
809
865
 
810
866
  // src/commands/plugin-dev/index.ts
811
- function command3() {
812
- program3.command("dev").option(
867
+ function command2() {
868
+ program2.command("dev").option(
813
869
  "-p, --ppk <ppk>",
814
870
  ".ppk file path",
815
871
  path13.join(PLUGIN_WORKSPACE_DIRECTORY, "private.ppk")
816
- ).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);
817
873
  }
818
874
  async function action2(options) {
819
875
  console.group("\u{1F373} Start development server");
@@ -827,15 +883,12 @@ async function action2(options) {
827
883
  }
828
884
  const port = config2.server?.port ?? DEFAULT_PORT;
829
885
  if (!hasCertificates(certDirPath)) {
830
- 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..."));
831
887
  try {
832
- await generateCert(certDirPath);
833
- console.log(chalk5.green("\u2705 SSL certificates generated successfully"));
888
+ generateCert(certDirPath);
889
+ console.log(chalk4.green("\u2705 SSL certificates generated successfully"));
834
890
  } catch (error) {
835
- console.log(
836
- chalk5.red("\u274C Failed to generate SSL certificates. Make sure mkcert is installed.")
837
- );
838
- console.log(chalk5.gray(" Install mkcert: https://github.com/FiloSottile/mkcert"));
891
+ console.log(chalk4.red("\u274C Failed to generate SSL certificates."));
839
892
  throw error;
840
893
  }
841
894
  }
@@ -849,83 +902,28 @@ async function action2(options) {
849
902
  if (entryNames.length === 0) {
850
903
  throw new Error("No entry points found for plugin. Check src/config and src/desktop paths.");
851
904
  }
852
- console.log(chalk5.gray(` Entry points: ${entryNames.join(", ")}`));
905
+ console.log(chalk4.gray(` Entry points: ${entryNames.join(", ")}`));
853
906
  const { key, cert } = loadCertificates(certDirPath);
854
- console.log(chalk5.gray(" Building..."));
855
- await buildEntriesWithVite({
907
+ const { port: actualPort } = await startRsbuildDevServer({
856
908
  entries,
857
909
  outDir: outputDir,
858
- mode: "development",
859
- sourcemap: "inline",
860
- minify: false
861
- });
862
- const serverConfig = createViteConfig({
863
- root: outputDir,
864
- server: {
865
- port,
866
- https: { key, cert }
867
- }
868
- });
869
- const server = await createServer(serverConfig);
870
- await server.listen();
871
- console.log(chalk5.green(`
910
+ port,
911
+ https: { key, cert },
912
+ publicDir: outputDir,
913
+ onFirstCompile: () => {
914
+ console.log(chalk4.green(`
872
915
  \u2728 Plugin development server ready!`));
873
- console.log(chalk5.cyan(` Local: https://localhost:${port}`));
874
- console.log(chalk5.gray(` Output: ${outputDir}`));
875
- console.log(chalk5.gray(` Files: config.js, desktop.js`));
876
- console.log(chalk5.gray("\n Watching for changes...\n"));
877
- const chokidar2 = await import("chokidar");
878
- const watchDirs = [
879
- path13.resolve("src", "config"),
880
- path13.resolve("src", "desktop"),
881
- path13.resolve("src", "lib")
882
- ].filter((dir) => fs10.existsSync(dir));
883
- console.log(chalk5.gray(` Watching directories: ${watchDirs.join(", ")}`));
884
- const watcher = chokidar2.watch(watchDirs, {
885
- ignored: /node_modules/,
886
- persistent: true,
887
- ignoreInitial: true
888
- });
889
- const watchExtensions = [".ts", ".tsx", ".js", ".jsx", ".css", ".scss"];
890
- const shouldRebuild = (filePath) => {
891
- const ext = path13.extname(filePath).toLowerCase();
892
- return watchExtensions.includes(ext);
893
- };
894
- const rebuild = async () => {
895
- console.log(chalk5.gray(` ${(/* @__PURE__ */ new Date()).toLocaleTimeString()} Rebuilding...`));
896
- await buildEntriesWithVite({
897
- entries,
898
- outDir: outputDir,
899
- mode: "development",
900
- sourcemap: "inline",
901
- minify: false
902
- });
903
- console.log(chalk5.gray(` ${(/* @__PURE__ */ new Date()).toLocaleTimeString()} Rebuild complete`));
904
- };
905
- watcher.on("ready", () => {
906
- console.log(chalk5.green(" \u2713 File watcher ready"));
907
- });
908
- watcher.on("change", (filePath) => {
909
- if (shouldRebuild(filePath)) {
910
- console.log(chalk5.cyan(` [change] ${filePath}`));
911
- rebuild();
912
- }
913
- });
914
- watcher.on("add", (filePath) => {
915
- if (shouldRebuild(filePath)) {
916
- console.log(chalk5.cyan(` [add] ${filePath}`));
917
- rebuild();
918
- }
919
- });
920
- watcher.on("unlink", (filePath) => {
921
- if (shouldRebuild(filePath)) {
922
- console.log(chalk5.cyan(` [unlink] ${filePath}`));
923
- 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
+ );
924
925
  }
925
926
  });
926
- watcher.on("error", (error) => {
927
- console.error(chalk5.red(` Watcher error: ${error}`));
928
- });
929
927
  Promise.all([watchContentsAndUploadZip({ manifest, ppkPath }), watchCss(config2)]);
930
928
  } catch (error) {
931
929
  throw error;
@@ -935,18 +933,15 @@ async function action2(options) {
935
933
  }
936
934
 
937
935
  // src/commands/plugin-genkey.ts
938
- import { program as program4 } from "commander";
939
-
940
- // src/commands/genkey-base.ts
941
- async function action3(options) {
942
- const { output } = options;
943
- 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");
944
942
  try {
945
- const { stdout } = await generateCert(output);
946
- if (stdout) {
947
- console.log(stdout);
948
- }
949
- 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}`);
950
945
  } catch (error) {
951
946
  throw error;
952
947
  } finally {
@@ -954,44 +949,29 @@ async function action3(options) {
954
949
  }
955
950
  }
956
951
 
957
- // src/commands/plugin-genkey.ts
958
- function command4() {
959
- program4.command("genkey").description("Generate SSL key for localhost. (Require mkcert)").action(action4);
960
- }
961
- async function action4() {
962
- await action3({ output: PLUGIN_WORKSPACE_DIRECTORY });
963
- }
964
-
965
952
  // src/commands/plugin-init.ts
966
- import { program as program5 } from "commander";
953
+ import { program as program4 } from "commander";
967
954
  import fs11 from "fs-extra";
968
955
  import path14 from "path";
969
- import packer2 from "@kintone/plugin-packer";
970
- function command5() {
971
- 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);
972
958
  }
973
- async function action5() {
959
+ async function action4() {
974
960
  console.group("\u{1F373} Executing plugin initialization setup");
975
961
  try {
976
962
  const manifest = await outputManifest("dev");
977
963
  console.log("\u{1F4DD} manifest.json generated");
978
964
  await copyPluginContents();
979
965
  console.log("\u{1F4C1} contents copied");
980
- let privateKey;
981
- const keyPath = path14.join(PLUGIN_WORKSPACE_DIRECTORY, "private.ppk");
982
- if (fs11.existsSync(keyPath)) {
983
- privateKey = await fs11.readFile(keyPath, "utf8");
984
- }
985
- await outputContentsZip(manifest);
986
- const buffer = await getContentsZipBuffer();
987
- const output = await packer2(buffer, privateKey);
988
- if (!privateKey) {
989
- 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)) {
990
970
  console.log("\u{1F511} private.ppk generated");
991
971
  } else {
992
972
  console.log("\u{1F511} private.ppk already exists. The existing private.ppk will be used.");
993
973
  }
994
- await fs11.writeFile(path14.join(PLUGIN_WORKSPACE_DIRECTORY, "plugin.zip"), output.plugin);
974
+ await fs11.writeFile(path14.join(PLUGIN_WORKSPACE_DIRECTORY, "plugin.zip"), zip);
995
975
  console.log("\u{1F4E6} plugin.zip generated");
996
976
  console.log("\u2728 Plugin initialization setup completed! zip file path is ./.plugin/plugin.zip");
997
977
  } catch (error) {
@@ -1002,11 +982,11 @@ async function action5() {
1002
982
  }
1003
983
 
1004
984
  // src/commands/manifest/index.ts
1005
- import { program as program6 } from "commander";
1006
- function command6() {
1007
- 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);
1008
988
  }
1009
- async function action6(options) {
989
+ async function action5(options) {
1010
990
  console.group("\u{1F680} Executing manifest generation");
1011
991
  try {
1012
992
  const { env } = options;
@@ -1025,12 +1005,12 @@ async function action6(options) {
1025
1005
  }
1026
1006
 
1027
1007
  // src/commands/test/index.ts
1028
- import { program as program7 } from "commander";
1008
+ import { program as program6 } from "commander";
1029
1009
  import fs12 from "fs-extra";
1030
- function command7() {
1031
- program7.command("test").description("test").action(action7);
1010
+ function command6() {
1011
+ program6.command("test").description("test").action(action6);
1032
1012
  }
1033
- async function action7() {
1013
+ async function action6() {
1034
1014
  console.group("package.json");
1035
1015
  const packageJson = fs12.readJSONSync("package.json");
1036
1016
  console.log("package.json detected");
@@ -1042,18 +1022,26 @@ async function action7() {
1042
1022
  }
1043
1023
 
1044
1024
  // src/commands/plugin-zip.ts
1045
- 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
1046
1030
  import fs13 from "fs-extra";
1047
1031
  import path15 from "path";
1048
- import packer3 from "@kintone/plugin-packer";
1049
- function command8() {
1050
- 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(
1051
1039
  "-p, --ppk <ppk>",
1052
1040
  ".ppk file path",
1053
- path15.join(PLUGIN_WORKSPACE_DIRECTORY, "private.ppk")
1054
- ).action(action8);
1041
+ path16.join(PLUGIN_WORKSPACE_DIRECTORY, "private.ppk")
1042
+ ).action(action7);
1055
1043
  }
1056
- async function action8(options) {
1044
+ async function action7(options) {
1057
1045
  console.group("\u{1F373} Executing plugin zip generation");
1058
1046
  try {
1059
1047
  const { env, ppk: ppkPath } = options;
@@ -1064,18 +1052,17 @@ async function action8(options) {
1064
1052
  console.log("\u{1F4C1} contents copied");
1065
1053
  const manifest = await outputManifest(env);
1066
1054
  console.log(`\u{1F4DD} manifest.json generated (${env})`);
1067
- await outputContentsZip(manifest);
1055
+ const contentsZip = createContentsZipFromDir(manifest);
1068
1056
  console.log("\u{1F4E6} contents.zip generated");
1069
- const buffer = await getContentsZipBuffer();
1070
- const privateKey = await fs13.readFile(path15.resolve(ppkPath), "utf8");
1071
- const output = await packer3(buffer, privateKey);
1057
+ const { zip, id } = createPluginZip({ ppkPath: path16.resolve(ppkPath), contentsZip });
1072
1058
  const zipFileName = `plugin${getZipFileNameSuffix(env)}.zip`;
1073
- await fs13.writeFile(path15.join(PLUGIN_WORKSPACE_DIRECTORY, zipFileName), output.plugin);
1059
+ await fs14.writeFile(path16.join(PLUGIN_WORKSPACE_DIRECTORY, zipFileName), zip);
1074
1060
  console.log("\u{1F4E6} plugin.zip generated");
1075
1061
  const version = String(manifest.version);
1076
- await fs13.writeFile(path15.join(PLUGIN_WORKSPACE_DIRECTORY, "version"), version);
1062
+ await fs14.writeFile(path16.join(PLUGIN_WORKSPACE_DIRECTORY, "version"), version);
1077
1063
  console.log(`\u{1F4DD} version file generated (${version})`);
1078
1064
  console.log(`\u2728 Plugin zip generation completed! zip file path is ./.plugin/${zipFileName}`);
1065
+ console.log(` Plugin ID: ${id}`);
1079
1066
  } catch (error) {
1080
1067
  throw error;
1081
1068
  } finally {
@@ -1084,11 +1071,11 @@ async function action8(options) {
1084
1071
  }
1085
1072
 
1086
1073
  // src/commands/lint.ts
1087
- import { program as program9 } from "commander";
1088
- function command9() {
1089
- 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);
1090
1077
  }
1091
- async function action9(options) {
1078
+ async function action8(options) {
1092
1079
  try {
1093
1080
  lint();
1094
1081
  } catch (error) {
@@ -1098,7 +1085,7 @@ async function action9(options) {
1098
1085
  }
1099
1086
 
1100
1087
  // src/plugin.ts
1101
- 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");
1102
1089
  command();
1103
1090
  command2();
1104
1091
  command3();
@@ -1107,6 +1094,5 @@ command5();
1107
1094
  command6();
1108
1095
  command7();
1109
1096
  command8();
1110
- command9();
1111
- program10.parse(process.argv);
1097
+ program9.parse(process.argv);
1112
1098
  //# sourceMappingURL=plugin.js.map