@konomi-app/k2 0.9.0 → 0.10.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.
@@ -0,0 +1,54 @@
1
+ import { program } from 'commander';
2
+ import fs from 'fs-extra';
3
+ import path from 'path';
4
+ import { CONFIG_FILE_NAME, DEFAULT_PORT, DEVELOPMENT_DIRECTORY, WORKSPACE_DIRECTORY, } from '../../lib/constants.js';
5
+ import base from '../dev-base-esbuild.js';
6
+ import { importK2Config } from '../../lib/import.js';
7
+ import { watchCss } from './tailwind.js';
8
+ export default function command() {
9
+ program
10
+ .command('dev')
11
+ .description('Start development server.')
12
+ .option('-i, --input <input>', 'Input directory', 'src/apps')
13
+ .option('-o, --outdir <outdir>', 'Output directory.', DEVELOPMENT_DIRECTORY)
14
+ .option('-c, --certdir <certdir>', 'Certificate directory', WORKSPACE_DIRECTORY)
15
+ .option('-p, --port <port>', 'Port number')
16
+ .action(action);
17
+ }
18
+ export async function action(options) {
19
+ const { certdir, outdir, port: specifiedPort, input } = options;
20
+ console.group('🍳 Start development server');
21
+ try {
22
+ console.log(`📂 Output directory: ${outdir}`);
23
+ console.log(`🔑 Certificate directory: ${certdir}`);
24
+ let k2Config = null;
25
+ try {
26
+ k2Config = await importK2Config();
27
+ }
28
+ catch (error) {
29
+ console.log(`⚙ ${CONFIG_FILE_NAME} not found. use default settings.`);
30
+ }
31
+ const port = Number(specifiedPort ?? k2Config?.server?.port ?? DEFAULT_PORT);
32
+ await Promise.all([build({ certdir, outdir, port, input }), watchCss(k2Config?.plugin ?? {})]);
33
+ }
34
+ catch (error) {
35
+ throw error;
36
+ }
37
+ finally {
38
+ console.groupEnd();
39
+ }
40
+ }
41
+ const build = async (params) => {
42
+ const { outdir, certdir, port, input } = params;
43
+ const srcDir = path.resolve(input);
44
+ const dirs = fs.readdirSync(srcDir);
45
+ const entryPoints = dirs.reduce((acc, dir) => {
46
+ for (const filename of ['index.ts', 'index.js', 'index.mjs']) {
47
+ if (fs.existsSync(path.join(srcDir, dir, filename))) {
48
+ return [...acc, { in: path.join(srcDir, dir, filename), out: dir }];
49
+ }
50
+ }
51
+ return acc;
52
+ }, []);
53
+ return base({ port, entryPoints, certDir: certdir, staticDir: outdir });
54
+ };
@@ -0,0 +1,29 @@
1
+ import path from 'path';
2
+ import { PLUGIN_DEVELOPMENT_DIRECTORY } from '../../lib/constants.js';
3
+ import chalk from 'chalk';
4
+ import { getTailwindConfigFromK2Config, watchTailwindCSS } from '../../lib/tailwind.js';
5
+ async function buildTailwindCSS(params) {
6
+ const { inputFile, outputFileName, config } = params;
7
+ const inputPath = path.resolve(inputFile);
8
+ const outputPath = path.join(PLUGIN_DEVELOPMENT_DIRECTORY, outputFileName);
9
+ return watchTailwindCSS({
10
+ input: inputPath,
11
+ output: outputPath,
12
+ config,
13
+ onChanges: ({ input, output, type }) => {
14
+ const outputFileName = path.basename(output);
15
+ console.log(chalk.hex('#e5e7eb')(`${new Date().toLocaleTimeString()} `) +
16
+ chalk.cyan(`[css] `) +
17
+ outputFileName +
18
+ (type === 'init' ? ' init' : ` rebuilt`));
19
+ },
20
+ });
21
+ }
22
+ export const watchCss = async (k2Config) => {
23
+ if (!k2Config.tailwind?.css || !k2Config.tailwind?.config) {
24
+ return;
25
+ }
26
+ const tailwindConfig = await getTailwindConfigFromK2Config(k2Config.tailwind);
27
+ const inputFile = path.resolve(k2Config.tailwind.css);
28
+ return buildTailwindCSS({ inputFile, outputFileName: 'styles.css', config: tailwindConfig });
29
+ };
@@ -18,6 +18,7 @@ export async function action() {
18
18
  const config = await importPluginConfig();
19
19
  if (config?.lint?.build) {
20
20
  await lint();
21
+ console.log('✨ Lint success.');
21
22
  }
22
23
  if (!fs.existsSync(PLUGIN_CONTENTS_DIRECTORY)) {
23
24
  await fs.mkdir(PLUGIN_CONTENTS_DIRECTORY, { recursive: true });
@@ -1,11 +1,12 @@
1
1
  import { program } from 'commander';
2
- import { importPluginConfig } from '../../lib/import.js';
2
+ import fs from 'fs-extra';
3
3
  import path from 'path';
4
4
  import { DEFAULT_PORT, PLUGIN_DEVELOPMENT_DIRECTORY, PLUGIN_WORKSPACE_DIRECTORY, } from '../../lib/constants.js';
5
+ import { importPluginConfig } from '../../lib/import.js';
5
6
  import base from '../dev-base-esbuild.js';
6
7
  import { getManifest } from './create-manifest.js';
7
- import { watchContentsAndUploadZip } from './upload.js';
8
8
  import { watchCss } from './tailwind.js';
9
+ import { watchContentsAndUploadZip } from './upload.js';
9
10
  export default function command() {
10
11
  program
11
12
  .command('dev')
@@ -18,6 +19,9 @@ export async function action(options) {
18
19
  try {
19
20
  const { ppk: ppkPath } = options;
20
21
  const config = await importPluginConfig();
22
+ if (!fs.existsSync(PLUGIN_DEVELOPMENT_DIRECTORY)) {
23
+ await fs.mkdir(PLUGIN_DEVELOPMENT_DIRECTORY, { recursive: true });
24
+ }
21
25
  const port = config.server?.port ?? DEFAULT_PORT;
22
26
  const manifest = await getManifest({ config, port });
23
27
  console.log(`📝 manifest.json generated`);
@@ -1,43 +1,23 @@
1
1
  import path from 'path';
2
2
  import { PLUGIN_DEVELOPMENT_DIRECTORY } from '../../lib/constants.js';
3
- import chokidar from 'chokidar';
4
3
  import chalk from 'chalk';
5
- import { getTailwindConfig, outputCss } from '../../lib/tailwind.js';
4
+ import { getTailwindConfig, watchTailwindCSS } from '../../lib/tailwind.js';
6
5
  async function buildTailwindCSS(params) {
7
6
  const { inputFile, outputFileName, config } = params;
8
7
  const inputPath = path.resolve(inputFile);
9
8
  const outputPath = path.join(PLUGIN_DEVELOPMENT_DIRECTORY, outputFileName);
10
- const watcher = chokidar.watch([...(config.content ?? ['./src/**/*.{ts,tsx}']), inputPath], {
11
- ignored: /node_modules/,
12
- persistent: true,
13
- awaitWriteFinish: {
14
- stabilityThreshold: 2000,
15
- pollInterval: 100,
16
- },
17
- });
18
- let initialScanComplete = false;
19
- const listener = async (type, path) => {
20
- try {
21
- if (type === 'add' && !initialScanComplete) {
22
- return;
23
- }
24
- await outputCss({ inputPath, outputPath, config });
9
+ return watchTailwindCSS({
10
+ input: inputPath,
11
+ output: outputPath,
12
+ config,
13
+ onChanges: ({ output, type }) => {
14
+ const outputFileName = path.basename(output);
25
15
  console.log(chalk.hex('#e5e7eb')(`${new Date().toLocaleTimeString()} `) +
26
16
  chalk.cyan(`[css] `) +
27
17
  outputFileName +
28
18
  (type === 'init' ? ' init' : ` rebuilt`));
29
- }
30
- catch (error) {
31
- console.error('Error building Tailwind CSS:', error);
32
- }
33
- };
34
- watcher.on('ready', async () => {
35
- initialScanComplete = true;
36
- await listener('init');
19
+ },
37
20
  });
38
- watcher.on('change', (path) => listener('change', path));
39
- watcher.on('add', (path) => listener('add', path));
40
- watcher.on('unlink', () => listener('unlink'));
41
21
  }
42
22
  export const watchCss = async (pluginConfig) => {
43
23
  if (!pluginConfig.tailwind?.css || !pluginConfig.tailwind?.config) {
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { program } from 'commander';
3
3
  import build from './commands/build.js';
4
4
  import viteBuild from './commands/build-vite.js';
5
- import dev from './commands/dev.js';
5
+ import dev from './commands/dev/index.js';
6
6
  import viteDev from './commands/dev-vite.js';
7
7
  import genkey from './commands/genkey.js';
8
8
  import esbuildBuild from './commands/build-esbuild.js';
@@ -1,6 +1,8 @@
1
1
  import path from 'path';
2
2
  export const WORKSPACE_DIRECTORY = '.k2';
3
3
  export const DEVELOPMENT_DIRECTORY = path.join(WORKSPACE_DIRECTORY, 'dev');
4
+ export const CONFIG_FILE_NAME = 'k2.config.mjs';
5
+ export const PLUGIN_CONFIG_FILE_NAME = 'plugin.config.mjs';
4
6
  /** kintoneプラグインの一時ファイルを管理するフォルダ */
5
7
  export const PLUGIN_WORKSPACE_DIRECTORY = '.plugin';
6
8
  /** kintoneプラグインのcontents.zipに格納するファイルを管理するフォルダ */
@@ -1,4 +1,5 @@
1
1
  import { pathToFileURL } from 'url';
2
+ import { CONFIG_FILE_NAME, PLUGIN_CONFIG_FILE_NAME } from './constants.js';
2
3
  export const esmImport = (path) => {
3
4
  if (process.platform === 'win32') {
4
5
  return import(pathToFileURL(path).toString());
@@ -7,6 +8,9 @@ export const esmImport = (path) => {
7
8
  return import(path);
8
9
  }
9
10
  };
10
- export const importPluginConfig = async () => {
11
- return (await esmImport('plugin.config.mjs')).default;
11
+ export const importK2Config = async (configFileName) => {
12
+ return (await esmImport(configFileName ?? CONFIG_FILE_NAME)).default;
13
+ };
14
+ export const importPluginConfig = async (configFileName) => {
15
+ return (await esmImport(configFileName ?? PLUGIN_CONFIG_FILE_NAME)).default;
12
16
  };
@@ -5,6 +5,12 @@ import postcss from 'postcss';
5
5
  import tailwindcss from 'tailwindcss';
6
6
  import invariant from 'tiny-invariant';
7
7
  import { esmImport } from './import.js';
8
+ import chokidar from 'chokidar';
9
+ export const getTailwindConfigFromK2Config = async (k2Config) => {
10
+ invariant(k2Config?.config, 'tailwind.config is required');
11
+ const config = (await esmImport(path.resolve(k2Config?.config))).default;
12
+ return config;
13
+ };
8
14
  export const getTailwindConfig = async (config) => {
9
15
  invariant(config?.config, 'tailwind.config is required');
10
16
  const { config: configPath } = config;
@@ -26,3 +32,36 @@ export const outputCss = async (params) => {
26
32
  await fs.writeFile(`${outputPath}.map`, result.map.toString());
27
33
  }
28
34
  };
35
+ export const watchTailwindCSS = async (params) => {
36
+ const { input, output, config } = params;
37
+ const watcher = chokidar.watch([...(config.content ?? ['./src/**/*.{ts,tsx}']), input], {
38
+ ignored: /node_modules/,
39
+ persistent: true,
40
+ awaitWriteFinish: {
41
+ stabilityThreshold: 2000,
42
+ pollInterval: 100,
43
+ },
44
+ });
45
+ let initialScanComplete = false;
46
+ const listener = async (type, path) => {
47
+ try {
48
+ if (type === 'add' && !initialScanComplete) {
49
+ return;
50
+ }
51
+ await outputCss({ inputPath: input, outputPath: output, config });
52
+ if (params.onChanges) {
53
+ params.onChanges({ input, output, type });
54
+ }
55
+ }
56
+ catch (error) {
57
+ console.error('Error building Tailwind CSS:', error);
58
+ }
59
+ };
60
+ watcher.on('ready', async () => {
61
+ initialScanComplete = true;
62
+ await listener('init');
63
+ });
64
+ watcher.on('change', (path) => listener('change', path));
65
+ watcher.on('add', (path) => listener('add', path));
66
+ watcher.on('unlink', () => listener('unlink'));
67
+ };
package/dist/lib/zip.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import archiver from 'archiver';
2
2
  import fs from 'fs-extra';
3
3
  import path from 'path';
4
+ import invariant from 'tiny-invariant';
4
5
  import { PLUGIN_CONTENTS_DIRECTORY, PLUGIN_WORKSPACE_DIRECTORY } from './constants.js';
5
6
  export const outputContentsZip = async (manifest) => {
6
7
  const archive = archiver('zip', { zlib: { level: 9 } });
@@ -9,13 +10,9 @@ export const outputContentsZip = async (manifest) => {
9
10
  const filterLocalContent = (file) => {
10
11
  return !/^https?:\/\//.test(file);
11
12
  };
12
- archive.file(path.join(PLUGIN_CONTENTS_DIRECTORY, 'manifest.json'), {
13
- name: 'manifest.json',
14
- });
15
- if (!manifest.config) {
16
- throw new Error('manifest.config is required');
17
- }
13
+ invariant(manifest.config?.html, 'manifest.config.html is required');
18
14
  const targetFiles = [
15
+ 'manifest.json',
19
16
  ...new Set([
20
17
  manifest.icon,
21
18
  manifest.config.html,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@konomi-app/k2",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "kintone sdk",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",
@@ -66,4 +66,4 @@
66
66
  "@types/html-minifier": "^4",
67
67
  "typescript": "*"
68
68
  }
69
- }
69
+ }
@@ -1,35 +0,0 @@
1
- import express from 'express';
2
- import fs from 'fs-extra';
3
- import { createServer } from 'https';
4
- import path from 'path';
5
- import { generateCert } from '../lib/cert.js';
6
- import { buildWithEsbuild } from '../lib/esbuild.js';
7
- export default function action(params) {
8
- const { entryPoints, staticDir, certDir, port } = params;
9
- return Promise.all([build({ entryPoints, staticDir }), server({ port, certDir, staticDir })]);
10
- }
11
- async function build(params) {
12
- const { entryPoints, staticDir: outdir } = params;
13
- return buildWithEsbuild({ entryPoints, outdir, watch: true });
14
- }
15
- async function server(params) {
16
- const { certDir, port, staticDir } = params;
17
- const app = express();
18
- app.use(express.static(staticDir));
19
- const privateKeyPath = path.join(certDir, 'localhost-key.pem');
20
- const certificatePath = path.join(certDir, 'localhost-cert.pem');
21
- if (!fs.existsSync(privateKeyPath) || !fs.existsSync(certificatePath)) {
22
- await generateCert(certDir);
23
- console.log('🔑 Certificate generated');
24
- }
25
- const privateKey = fs.readFileSync(privateKeyPath);
26
- const certificate = fs.readFileSync(certificatePath);
27
- const server = createServer({ key: privateKey, cert: certificate }, app);
28
- const res = server.listen(port);
29
- res.on('error', (error) => {
30
- console.error(error);
31
- });
32
- res.on('listening', () => {
33
- console.log(`🚀 Server started! https://localhost:${port}`);
34
- });
35
- }
@@ -1,45 +0,0 @@
1
- import { program } from 'commander';
2
- import fs from 'fs-extra';
3
- import path from 'path';
4
- import { DEFAULT_PORT, DEVELOPMENT_DIRECTORY, WORKSPACE_DIRECTORY } from '../lib/constants.js';
5
- import base from './dev-base-esbuild.js';
6
- export default function command() {
7
- program
8
- .command('dev')
9
- .description('Start development server.')
10
- .option('-i, --input <input>', 'Input directory', 'src/apps')
11
- .option('-o, --outdir <outdir>', 'Output directory.', DEVELOPMENT_DIRECTORY)
12
- .option('-c, --certdir <certdir>', 'Certificate directory', WORKSPACE_DIRECTORY)
13
- .option('-p, --port <port>', 'Port number', DEFAULT_PORT.toString())
14
- .action(action);
15
- }
16
- export async function action(options) {
17
- const { certdir, outdir, port, input } = options;
18
- console.group('🍳 Start development server');
19
- try {
20
- console.log(`📂 Output directory: ${outdir}`);
21
- console.log(`🔑 Certificate directory: ${certdir}`);
22
- const srcDir = path.resolve(input);
23
- const dirs = fs.readdirSync(srcDir);
24
- const entryPoints = dirs.reduce((acc, dir) => {
25
- for (const filename of ['index.ts', 'index.js', 'index.mjs']) {
26
- if (fs.existsSync(path.join(srcDir, dir, filename))) {
27
- return [...acc, { in: path.join(srcDir, dir, filename), out: dir }];
28
- }
29
- }
30
- return acc;
31
- }, []);
32
- await base({
33
- port: Number(port),
34
- entryPoints,
35
- certDir: certdir,
36
- staticDir: outdir,
37
- });
38
- }
39
- catch (error) {
40
- throw error;
41
- }
42
- finally {
43
- console.groupEnd();
44
- }
45
- }