@konomi-app/k2 0.1.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/README.md +3 -0
- package/dist/commands/build/index.js +30 -0
- package/dist/commands/dev/index.js +112 -0
- package/dist/commands/genkey/index.js +25 -0
- package/dist/commands/init/index.js +47 -0
- package/dist/commands/manifest/index.js +28 -0
- package/dist/commands/test/index.js +16 -0
- package/dist/commands/upload/index.js +30 -0
- package/dist/commands/vite-dev/index.js +48 -0
- package/dist/commands/zip/index.js +43 -0
- package/dist/index.js +20 -0
- package/dist/lib/cert.js +15 -0
- package/dist/lib/constants.js +5 -0
- package/dist/lib/esbuild.js +60 -0
- package/dist/lib/exec.js +3 -0
- package/dist/lib/import.js +12 -0
- package/dist/lib/plugin-contents.js +19 -0
- package/dist/lib/plugin-manifest.js +25 -0
- package/dist/lib/utils.js +25 -0
- package/dist/lib/vite.js +41 -0
- package/dist/lib/zip.js +46 -0
- package/dist/plugin.js +20 -0
- package/package.json +49 -0
- package/types/index.d.ts +1 -0
- package/types/plugin.d.ts +86 -0
- package/types.d.ts +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { program } from 'commander';
|
|
2
|
+
import { build } from 'vite';
|
|
3
|
+
import { importPluginConfig } from '../../lib/import.js';
|
|
4
|
+
import { getViteConfig } from '../../lib/vite.js';
|
|
5
|
+
import { CONTENTS_DIRECTORY } from '../../lib/constants.js';
|
|
6
|
+
export default function command() {
|
|
7
|
+
program
|
|
8
|
+
.command('build')
|
|
9
|
+
.description("Build the project for production. (It's a wrapper of Vite build command.)")
|
|
10
|
+
.action(action);
|
|
11
|
+
}
|
|
12
|
+
export async function action() {
|
|
13
|
+
console.group('🚀 Build the project for production');
|
|
14
|
+
try {
|
|
15
|
+
const config = await importPluginConfig();
|
|
16
|
+
const viteConfig = getViteConfig(config);
|
|
17
|
+
await build({
|
|
18
|
+
...viteConfig,
|
|
19
|
+
mode: 'production',
|
|
20
|
+
build: { ...viteConfig.build, outDir: CONTENTS_DIRECTORY },
|
|
21
|
+
});
|
|
22
|
+
console.log('✨ Build success.');
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
console.groupEnd();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { program } from 'commander';
|
|
2
|
+
import { importPluginConfig } from '../../lib/import.js';
|
|
3
|
+
import express from 'express';
|
|
4
|
+
import { createServer } from 'https';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { DEFAULT_PORT, DEVELOPMENT_DIRECTORY, WORKSPACE_DIRECTORY, } from '../../lib/constants.js';
|
|
7
|
+
import fs from 'fs-extra';
|
|
8
|
+
import { outputManifest } from '../../lib/plugin-manifest.js';
|
|
9
|
+
import { copyPluginContents } from '../../lib/plugin-contents.js';
|
|
10
|
+
import chokider from 'chokidar';
|
|
11
|
+
import { generateCert } from '../../lib/cert.js';
|
|
12
|
+
import { getContentsZipBuffer, getZipFileNameSuffix, outputContentsZip, } from '../../lib/zip.js';
|
|
13
|
+
import packer from '@kintone/plugin-packer';
|
|
14
|
+
import { uploadZip } from '../../lib/utils.js';
|
|
15
|
+
import { buildWithEsbuild } from '../../lib/esbuild.js';
|
|
16
|
+
export default function command() {
|
|
17
|
+
program
|
|
18
|
+
.command('dev')
|
|
19
|
+
.description('Start development server.')
|
|
20
|
+
.action(action);
|
|
21
|
+
}
|
|
22
|
+
export async function action() {
|
|
23
|
+
console.group('🚀 Start development server');
|
|
24
|
+
try {
|
|
25
|
+
const config = await importPluginConfig();
|
|
26
|
+
const port = config.server?.port ?? DEFAULT_PORT;
|
|
27
|
+
const manifest = await outputManifest('dev', {
|
|
28
|
+
config: {
|
|
29
|
+
...config,
|
|
30
|
+
manifest: {
|
|
31
|
+
...config.manifest,
|
|
32
|
+
dev: {
|
|
33
|
+
config: {
|
|
34
|
+
...config.manifest?.dev?.config,
|
|
35
|
+
js: [`https://localhost:${port}/config.js`],
|
|
36
|
+
css: [`https://localhost:${port}/config.css`],
|
|
37
|
+
},
|
|
38
|
+
desktop: {
|
|
39
|
+
...config.manifest?.dev?.desktop,
|
|
40
|
+
js: [`https://localhost:${port}/desktop.js`],
|
|
41
|
+
css: [`https://localhost:${port}/desktop.css`],
|
|
42
|
+
},
|
|
43
|
+
mobile: {
|
|
44
|
+
...config.manifest?.dev?.mobile,
|
|
45
|
+
js: [`https://localhost:${port}/desktop.js`],
|
|
46
|
+
css: [`https://localhost:${port}/desktop.css`],
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
console.log(`📝 manifest.json generated`);
|
|
53
|
+
const contentsListener = async () => {
|
|
54
|
+
try {
|
|
55
|
+
await copyPluginContents();
|
|
56
|
+
console.log('📁 contents updated');
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error('📁 contents update failed');
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
await contentsListener();
|
|
63
|
+
const watcher = chokider.watch(['src/contents/**/*'], {
|
|
64
|
+
ignored: /node_modules/,
|
|
65
|
+
persistent: true,
|
|
66
|
+
});
|
|
67
|
+
watcher.on('change', contentsListener);
|
|
68
|
+
watcher.on('add', contentsListener);
|
|
69
|
+
watcher.on('unlink', contentsListener);
|
|
70
|
+
await outputContentsZip(manifest);
|
|
71
|
+
const buffer = await getContentsZipBuffer();
|
|
72
|
+
const pluginPrivateKey = await fs.readFile(path.join(WORKSPACE_DIRECTORY, 'private.ppk'), 'utf8');
|
|
73
|
+
const output = await packer(buffer, pluginPrivateKey);
|
|
74
|
+
const zipFileName = `plugin${getZipFileNameSuffix('dev')}.zip`;
|
|
75
|
+
await fs.writeFile(path.join(WORKSPACE_DIRECTORY, zipFileName), output.plugin);
|
|
76
|
+
uploadZip('dev').then(({ stdout, stderr }) => {
|
|
77
|
+
console.log(stdout);
|
|
78
|
+
console.error(stderr);
|
|
79
|
+
});
|
|
80
|
+
const app = express();
|
|
81
|
+
app.use(express.static(DEVELOPMENT_DIRECTORY));
|
|
82
|
+
const privateKeyPath = path.join(WORKSPACE_DIRECTORY, 'localhost-key.pem');
|
|
83
|
+
const certificatePath = path.join(WORKSPACE_DIRECTORY, 'localhost-cert.pem');
|
|
84
|
+
if (!fs.existsSync(privateKeyPath) || !fs.existsSync(certificatePath)) {
|
|
85
|
+
await generateCert(WORKSPACE_DIRECTORY);
|
|
86
|
+
console.log('🔑 Certificate generated');
|
|
87
|
+
}
|
|
88
|
+
const privateKey = fs.readFileSync(privateKeyPath);
|
|
89
|
+
const certificate = fs.readFileSync(certificatePath);
|
|
90
|
+
const server = createServer({ key: privateKey, cert: certificate }, app);
|
|
91
|
+
const res = server.listen(port);
|
|
92
|
+
buildWithEsbuild({
|
|
93
|
+
entryPoints: ['desktop', 'config'].map((dir) => ({
|
|
94
|
+
in: path.join('src', dir, 'index.ts'),
|
|
95
|
+
out: dir,
|
|
96
|
+
})),
|
|
97
|
+
outdir: DEVELOPMENT_DIRECTORY,
|
|
98
|
+
});
|
|
99
|
+
res.on('error', (error) => {
|
|
100
|
+
console.error(error);
|
|
101
|
+
});
|
|
102
|
+
res.on('listening', () => {
|
|
103
|
+
console.log(`🚀 Server started! https://localhost:${port}`);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
console.groupEnd();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { program } from 'commander';
|
|
2
|
+
import { generateCert } from '../../lib/cert.js';
|
|
3
|
+
import { WORKSPACE_DIRECTORY } from '../../lib/constants.js';
|
|
4
|
+
export default function command() {
|
|
5
|
+
program
|
|
6
|
+
.command('genkey')
|
|
7
|
+
.description('Generate SSL key for localhost. (Require mkcert)')
|
|
8
|
+
.option('-o, --output <output>', 'Output directory.', WORKSPACE_DIRECTORY)
|
|
9
|
+
.action(action);
|
|
10
|
+
}
|
|
11
|
+
export async function action(options) {
|
|
12
|
+
const { output } = options;
|
|
13
|
+
console.group('🔑 Generate SSL key for localhost');
|
|
14
|
+
try {
|
|
15
|
+
const { stdout } = await generateCert(output);
|
|
16
|
+
console.log(stdout);
|
|
17
|
+
console.log('key generation success.');
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
console.groupEnd();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { program } from 'commander';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import packer from '@kintone/plugin-packer';
|
|
5
|
+
import { outputManifest } from '../../lib/plugin-manifest.js';
|
|
6
|
+
import { WORKSPACE_DIRECTORY } from '../../lib/constants.js';
|
|
7
|
+
import { getContentsZipBuffer, outputContentsZip } from '../../lib/zip.js';
|
|
8
|
+
import { copyPluginContents } from '../../lib/plugin-contents.js';
|
|
9
|
+
export default function command() {
|
|
10
|
+
program
|
|
11
|
+
.command('init')
|
|
12
|
+
.description('generate private.ppk and kitting config')
|
|
13
|
+
.action(action);
|
|
14
|
+
}
|
|
15
|
+
export async function action() {
|
|
16
|
+
console.group('🚀 Executing plugin initialization setup');
|
|
17
|
+
try {
|
|
18
|
+
const manifest = await outputManifest('dev');
|
|
19
|
+
console.log('📝 manifest.json generated');
|
|
20
|
+
await copyPluginContents();
|
|
21
|
+
console.log('📁 contents copied');
|
|
22
|
+
let privateKey;
|
|
23
|
+
const keyPath = path.join(WORKSPACE_DIRECTORY, 'private.ppk');
|
|
24
|
+
if (fs.existsSync(keyPath)) {
|
|
25
|
+
privateKey = await fs.readFile(keyPath, 'utf8');
|
|
26
|
+
}
|
|
27
|
+
await outputContentsZip(manifest);
|
|
28
|
+
const buffer = await getContentsZipBuffer();
|
|
29
|
+
const output = await packer(buffer, privateKey);
|
|
30
|
+
if (!privateKey) {
|
|
31
|
+
await fs.writeFile(path.join(WORKSPACE_DIRECTORY, 'private.ppk'), output.privateKey);
|
|
32
|
+
console.log('🔐 private.ppk generated');
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
console.log('🔐 private.ppk already exists. The existing private.ppk will be used.');
|
|
36
|
+
}
|
|
37
|
+
await fs.writeFile(path.join(WORKSPACE_DIRECTORY, 'plugin.zip'), output.plugin);
|
|
38
|
+
console.log('📦 plugin.zip generated');
|
|
39
|
+
console.log('✨ Plugin initialization setup completed! zip file path is ./.plugin/plugin.zip');
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
console.groupEnd();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { program } from 'commander';
|
|
2
|
+
import { outputManifest } from '../../lib/plugin-manifest.js';
|
|
3
|
+
import { copyPluginContents } from '../../lib/plugin-contents.js';
|
|
4
|
+
export default function command() {
|
|
5
|
+
program
|
|
6
|
+
.command('manifest')
|
|
7
|
+
.option('-e, --env <env>', 'create manifest', 'prod')
|
|
8
|
+
.action(action);
|
|
9
|
+
}
|
|
10
|
+
async function action(options) {
|
|
11
|
+
console.group('🚀 Executing manifest generation');
|
|
12
|
+
try {
|
|
13
|
+
const { env } = options;
|
|
14
|
+
if (env !== 'prod' && env !== 'dev' && env !== 'standalone') {
|
|
15
|
+
throw new Error('Invalid environment');
|
|
16
|
+
}
|
|
17
|
+
await copyPluginContents();
|
|
18
|
+
console.log('📁 contents copied');
|
|
19
|
+
await outputManifest(env);
|
|
20
|
+
console.log(`📝 manifest.json generated (${env})`);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
console.groupEnd();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { program } from 'commander';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import { esmImport } from '../../lib/import.js';
|
|
4
|
+
export default function command() {
|
|
5
|
+
program.command('test').description('test').action(action);
|
|
6
|
+
}
|
|
7
|
+
export async function action() {
|
|
8
|
+
console.group('package.json');
|
|
9
|
+
const packageJson = fs.readJSONSync('package.json');
|
|
10
|
+
console.log('package.json detected');
|
|
11
|
+
console.groupEnd();
|
|
12
|
+
console.group('Config');
|
|
13
|
+
const config = await esmImport('plugin.config.mjs');
|
|
14
|
+
console.log('plugin.config.mjs detected', config);
|
|
15
|
+
console.groupEnd();
|
|
16
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { program } from 'commander';
|
|
2
|
+
import { config } from 'dotenv';
|
|
3
|
+
import { isEnv, uploadZip } from '../../lib/utils.js';
|
|
4
|
+
export default function command() {
|
|
5
|
+
program
|
|
6
|
+
.command('upload')
|
|
7
|
+
.description('upload plugin.zip to your kintone')
|
|
8
|
+
.option('-e, --env <env>', 'plugin environment (dev, prod, standalone)', 'prod')
|
|
9
|
+
.action(action);
|
|
10
|
+
}
|
|
11
|
+
async function action(options) {
|
|
12
|
+
console.group('🚀 Uploading plugin.zip to your kintone');
|
|
13
|
+
try {
|
|
14
|
+
config();
|
|
15
|
+
const { env } = options;
|
|
16
|
+
if (!isEnv(env)) {
|
|
17
|
+
throw new Error('Invalid environment');
|
|
18
|
+
}
|
|
19
|
+
const { stderr } = await uploadZip(env);
|
|
20
|
+
if (stderr) {
|
|
21
|
+
console.error(JSON.stringify(stderr, null, 2));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
console.groupEnd();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { program } from 'commander';
|
|
2
|
+
import { createServer, build } from 'vite';
|
|
3
|
+
import { importPluginConfig } from '../../lib/import.js';
|
|
4
|
+
import { getViteConfig } from '../../lib/vite.js';
|
|
5
|
+
import chokidar from 'chokidar';
|
|
6
|
+
import { DEVELOPMENT_DIRECTORY } from '../../lib/constants.js';
|
|
7
|
+
export default function command() {
|
|
8
|
+
program
|
|
9
|
+
.command('dev')
|
|
10
|
+
.description('Start development server.')
|
|
11
|
+
.action(action);
|
|
12
|
+
}
|
|
13
|
+
export async function action() {
|
|
14
|
+
console.group('🚀 Start development server');
|
|
15
|
+
try {
|
|
16
|
+
const config = await importPluginConfig();
|
|
17
|
+
const watcher = chokidar.watch(['src/**/*.{ts,js,jsx,tsx}'], {
|
|
18
|
+
ignored: /node_modules/,
|
|
19
|
+
persistent: true,
|
|
20
|
+
});
|
|
21
|
+
const viteConfig = getViteConfig(config);
|
|
22
|
+
const listener = async () => build({
|
|
23
|
+
...viteConfig,
|
|
24
|
+
mode: 'development',
|
|
25
|
+
build: {
|
|
26
|
+
...viteConfig.build,
|
|
27
|
+
sourcemap: 'inline',
|
|
28
|
+
chunkSizeWarningLimit: 8192,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
await listener();
|
|
32
|
+
watcher.on('change', listener);
|
|
33
|
+
watcher.on('add', listener);
|
|
34
|
+
watcher.on('unlink', listener);
|
|
35
|
+
const server = await createServer({
|
|
36
|
+
...viteConfig,
|
|
37
|
+
root: DEVELOPMENT_DIRECTORY,
|
|
38
|
+
});
|
|
39
|
+
await server.listen();
|
|
40
|
+
server.printUrls();
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
console.groupEnd();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { program } from 'commander';
|
|
2
|
+
import { outputManifest } from '../../lib/plugin-manifest.js';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { WORKSPACE_DIRECTORY } from '../../lib/constants.js';
|
|
6
|
+
import packer from '@kintone/plugin-packer';
|
|
7
|
+
import { getContentsZipBuffer, getZipFileNameSuffix, outputContentsZip, } from '../../lib/zip.js';
|
|
8
|
+
import { copyPluginContents } from '../../lib/plugin-contents.js';
|
|
9
|
+
import { isEnv } from '../../lib/utils.js';
|
|
10
|
+
export default function command() {
|
|
11
|
+
program
|
|
12
|
+
.command('zip')
|
|
13
|
+
.description('generate plugin zip')
|
|
14
|
+
.option('-e, --env <env>', 'plugin environment (dev, prod, standalone)', 'prod')
|
|
15
|
+
.action(action);
|
|
16
|
+
}
|
|
17
|
+
async function action(options) {
|
|
18
|
+
console.group('🚀 Executing plugin zip generation');
|
|
19
|
+
try {
|
|
20
|
+
const { env } = options;
|
|
21
|
+
if (!isEnv(env)) {
|
|
22
|
+
throw new Error('Invalid environment');
|
|
23
|
+
}
|
|
24
|
+
await copyPluginContents();
|
|
25
|
+
console.log('📁 contents copied');
|
|
26
|
+
const manifest = await outputManifest(env);
|
|
27
|
+
console.log(`📝 manifest.json generated (${env})`);
|
|
28
|
+
await outputContentsZip(manifest);
|
|
29
|
+
const buffer = await getContentsZipBuffer();
|
|
30
|
+
const privateKey = await fs.readFile(path.join(WORKSPACE_DIRECTORY, 'private.ppk'), 'utf8');
|
|
31
|
+
const output = await packer(buffer, privateKey);
|
|
32
|
+
const zipFileName = `plugin${getZipFileNameSuffix(env)}.zip`;
|
|
33
|
+
await fs.writeFile(path.join(WORKSPACE_DIRECTORY, zipFileName), output.plugin);
|
|
34
|
+
console.log('📦 plugin.zip generated');
|
|
35
|
+
console.log(`✨ Plugin zip generation completed! zip file path is ./.plugin/${zipFileName}`);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
console.groupEnd();
|
|
42
|
+
}
|
|
43
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { program } from 'commander';
|
|
3
|
+
import build from './commands/build/index.js';
|
|
4
|
+
import dev from './commands/dev/index.js';
|
|
5
|
+
import genkey from './commands/genkey/index.js';
|
|
6
|
+
import init from './commands/init/index.js';
|
|
7
|
+
import manifest from './commands/manifest/index.js';
|
|
8
|
+
import test from './commands/test/index.js';
|
|
9
|
+
import upload from './commands/upload/index.js';
|
|
10
|
+
import zip from './commands/zip/index.js';
|
|
11
|
+
program.name('k2').version('0.1.0').description('');
|
|
12
|
+
build();
|
|
13
|
+
dev();
|
|
14
|
+
genkey();
|
|
15
|
+
init();
|
|
16
|
+
manifest();
|
|
17
|
+
test();
|
|
18
|
+
upload();
|
|
19
|
+
zip();
|
|
20
|
+
program.parse(process.argv);
|
package/dist/lib/cert.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { exec } from './exec.js';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
export const generateCert = async (outDir) => {
|
|
5
|
+
const { stdout } = await exec(`mkcert localhost`);
|
|
6
|
+
[
|
|
7
|
+
{ input: 'localhost.pem', output: 'localhost-cert.pem' },
|
|
8
|
+
{ input: 'localhost-key.pem', output: 'localhost-key.pem' },
|
|
9
|
+
].forEach(({ input, output }) => {
|
|
10
|
+
fs.moveSync(`./${input}`, path.join(outDir, output), {
|
|
11
|
+
overwrite: true,
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
return { stdout };
|
|
15
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import esbuild from 'esbuild';
|
|
3
|
+
import { compile } from 'sass';
|
|
4
|
+
import { resolve } from 'path';
|
|
5
|
+
export const getSassPlugin = () => {
|
|
6
|
+
const pluginName = 'esbuild-plugin-sass';
|
|
7
|
+
return {
|
|
8
|
+
name: pluginName,
|
|
9
|
+
setup(build) {
|
|
10
|
+
build.onResolve({ filter: /\.s[ac]ss$/ }, (args) => ({
|
|
11
|
+
path: resolve(args.resolveDir, args.path),
|
|
12
|
+
namespace: pluginName,
|
|
13
|
+
}));
|
|
14
|
+
build.onLoad({ filter: /.*/, namespace: pluginName }, async (args) => {
|
|
15
|
+
try {
|
|
16
|
+
const result = compile(args.path);
|
|
17
|
+
return {
|
|
18
|
+
contents: result.css,
|
|
19
|
+
loader: 'css',
|
|
20
|
+
watchFiles: [args.path],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
return {
|
|
25
|
+
pluginName,
|
|
26
|
+
errors: [
|
|
27
|
+
{
|
|
28
|
+
text: error instanceof Error
|
|
29
|
+
? error.message
|
|
30
|
+
: JSON.stringify(error),
|
|
31
|
+
pluginName,
|
|
32
|
+
location: { file: args.path, namespace: pluginName },
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
export const buildWithEsbuild = async (params) => {
|
|
42
|
+
const { entryPoints, outdir } = params;
|
|
43
|
+
const context = await esbuild.context({
|
|
44
|
+
entryPoints,
|
|
45
|
+
bundle: true,
|
|
46
|
+
sourcemap: 'inline',
|
|
47
|
+
platform: 'browser',
|
|
48
|
+
outdir,
|
|
49
|
+
plugins: [
|
|
50
|
+
{
|
|
51
|
+
name: 'on-end',
|
|
52
|
+
setup: ({ onEnd }) => onEnd(() => console.log(chalk.hex('#d1d5db')(`${new Date().toLocaleTimeString()} `) +
|
|
53
|
+
chalk.cyan(`[content] `) +
|
|
54
|
+
`Compiled successfully.`)),
|
|
55
|
+
},
|
|
56
|
+
getSassPlugin(),
|
|
57
|
+
],
|
|
58
|
+
});
|
|
59
|
+
context.watch();
|
|
60
|
+
};
|
package/dist/lib/exec.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { pathToFileURL } from 'url';
|
|
2
|
+
export const esmImport = (path) => {
|
|
3
|
+
if (process.platform === 'win32') {
|
|
4
|
+
return import(pathToFileURL(path).toString());
|
|
5
|
+
}
|
|
6
|
+
else {
|
|
7
|
+
return import(path);
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
export const importPluginConfig = async () => {
|
|
11
|
+
return (await esmImport('plugin.config.mjs')).default;
|
|
12
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { CONTENTS_DIRECTORY } from './constants.js';
|
|
4
|
+
import htmlMinifier from 'html-minifier';
|
|
5
|
+
export const copyPluginContents = async () => {
|
|
6
|
+
await fs.copySync(path.join('src', 'contents'), path.join(CONTENTS_DIRECTORY), { overwrite: true });
|
|
7
|
+
const html = await fs.readFile(path.join(CONTENTS_DIRECTORY, 'config.html'), 'utf8');
|
|
8
|
+
const minified = htmlMinifier.minify(html, {
|
|
9
|
+
minifyCSS: true,
|
|
10
|
+
collapseWhitespace: true,
|
|
11
|
+
removeComments: true,
|
|
12
|
+
removeOptionalTags: true,
|
|
13
|
+
removeRedundantAttributes: true,
|
|
14
|
+
removeScriptTypeAttributes: true,
|
|
15
|
+
removeTagWhitespace: true,
|
|
16
|
+
useShortDoctype: true,
|
|
17
|
+
});
|
|
18
|
+
await fs.writeFile(path.join(CONTENTS_DIRECTORY, 'config.html'), minified);
|
|
19
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { CONTENTS_DIRECTORY } from './constants.js';
|
|
2
|
+
import { importPluginConfig } from './import.js';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
function merge(src, dst) {
|
|
6
|
+
return Object.entries(src).reduce((acc, [key, value]) => {
|
|
7
|
+
if (!dst[key]) {
|
|
8
|
+
return { ...acc, [key]: value };
|
|
9
|
+
}
|
|
10
|
+
if (typeof dst[key] === 'string') {
|
|
11
|
+
return { ...acc, [key]: dst[key] };
|
|
12
|
+
}
|
|
13
|
+
if (Array.isArray(value) && Array.isArray(dst[key])) {
|
|
14
|
+
return { ...acc, [key]: [...value, ...dst[key]] };
|
|
15
|
+
}
|
|
16
|
+
return { ...acc, [key]: merge(src[key], dst[key]) };
|
|
17
|
+
}, {});
|
|
18
|
+
}
|
|
19
|
+
export const outputManifest = async (env, options) => {
|
|
20
|
+
const config = options?.config || (await importPluginConfig());
|
|
21
|
+
const merged = merge(config.manifest.base, config.manifest[env] || {});
|
|
22
|
+
await fs.mkdirs(CONTENTS_DIRECTORY);
|
|
23
|
+
await fs.writeJson(path.join(CONTENTS_DIRECTORY, 'manifest.json'), merged);
|
|
24
|
+
return merged;
|
|
25
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { WORKSPACE_DIRECTORY } from './constants.js';
|
|
2
|
+
import { exec } from './exec.js';
|
|
3
|
+
import { getZipFileNameSuffix } from './zip.js';
|
|
4
|
+
import { config } from 'dotenv';
|
|
5
|
+
export const isEnv = (env) => {
|
|
6
|
+
return ['prod', 'dev', 'standalone'].includes(env);
|
|
7
|
+
};
|
|
8
|
+
export const uploadZip = async (env) => {
|
|
9
|
+
config();
|
|
10
|
+
const { KINTONE_BASE_URL, KINTONE_USERNAME, KINTONE_PASSWORD, KINTONE_BASIC_AUTH_USERNAME = '', KINTONE_BASIC_AUTH_PASSWORD = '', } = process.env;
|
|
11
|
+
if (!KINTONE_BASE_URL || !KINTONE_USERNAME || !KINTONE_PASSWORD) {
|
|
12
|
+
throw new Error(`.envの設定が不十分です。以下のパラメータは必須です
|
|
13
|
+
KINTONE_BASE_URL
|
|
14
|
+
KINTONE_USERNAME
|
|
15
|
+
KINTONE_PASSWORD
|
|
16
|
+
`);
|
|
17
|
+
}
|
|
18
|
+
const zipFileName = `plugin${getZipFileNameSuffix(env)}.zip`;
|
|
19
|
+
let command = `kintone-plugin-uploader ${WORKSPACE_DIRECTORY}/${zipFileName} --base-url ${KINTONE_BASE_URL} --username ${KINTONE_USERNAME} --password ${KINTONE_PASSWORD}`;
|
|
20
|
+
if (KINTONE_BASIC_AUTH_USERNAME && KINTONE_BASIC_AUTH_PASSWORD) {
|
|
21
|
+
command += ` --basic-auth-username ${KINTONE_BASIC_AUTH_USERNAME} --basic-auth-password ${KINTONE_BASIC_AUTH_PASSWORD}`;
|
|
22
|
+
}
|
|
23
|
+
command += ' --watch --waiting-dialog-ms 3000';
|
|
24
|
+
return exec(command);
|
|
25
|
+
};
|
package/dist/lib/vite.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import { DEFAULT_PORT, DEVELOPMENT_DIRECTORY, WORKSPACE_DIRECTORY, } from './constants.js';
|
|
4
|
+
import tsconfigPaths from 'vite-tsconfig-paths';
|
|
5
|
+
export const getViteConfig = (config) => {
|
|
6
|
+
return {
|
|
7
|
+
configFile: false,
|
|
8
|
+
build: {
|
|
9
|
+
outDir: DEVELOPMENT_DIRECTORY,
|
|
10
|
+
emptyOutDir: true,
|
|
11
|
+
rollupOptions: {
|
|
12
|
+
input: {
|
|
13
|
+
config: path.join('src', 'config', 'index.ts'),
|
|
14
|
+
desktop: path.join('src', 'desktop', 'index.ts'),
|
|
15
|
+
},
|
|
16
|
+
output: {
|
|
17
|
+
entryFileNames: '[name].js',
|
|
18
|
+
chunkFileNames: '[name].js',
|
|
19
|
+
assetFileNames: '[name].[ext]',
|
|
20
|
+
},
|
|
21
|
+
onwarn: (warning, warn) => {
|
|
22
|
+
if (['MODULE_LEVEL_DIRECTIVE'].includes(warning.code ?? '')) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
warn(warning);
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
plugins: [tsconfigPaths()],
|
|
30
|
+
server: {
|
|
31
|
+
port: config.server?.port ?? DEFAULT_PORT,
|
|
32
|
+
https: {
|
|
33
|
+
key: fs.readFileSync(path.join(WORKSPACE_DIRECTORY, 'localhost-key.pem')),
|
|
34
|
+
cert: fs.readFileSync(path.join(WORKSPACE_DIRECTORY, 'localhost-cert.pem')),
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
resolve: {
|
|
38
|
+
alias: { '@': path.resolve('src') },
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
};
|
package/dist/lib/zip.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import archiver from 'archiver';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { CONTENTS_DIRECTORY, WORKSPACE_DIRECTORY } from './constants.js';
|
|
5
|
+
export const outputContentsZip = async (manifest) => {
|
|
6
|
+
const archive = archiver('zip', { zlib: { level: 9 } });
|
|
7
|
+
const outputZipPath = path.join(WORKSPACE_DIRECTORY, 'contents.zip');
|
|
8
|
+
const outputZipStream = fs.createWriteStream(outputZipPath);
|
|
9
|
+
const filterLocalContent = (file) => {
|
|
10
|
+
return !/^https?:\/\//.test(file);
|
|
11
|
+
};
|
|
12
|
+
archive.file(path.join(CONTENTS_DIRECTORY, 'manifest.json'), {
|
|
13
|
+
name: 'manifest.json',
|
|
14
|
+
});
|
|
15
|
+
if (!manifest.config) {
|
|
16
|
+
throw new Error('manifest.config is required');
|
|
17
|
+
}
|
|
18
|
+
const targetFiles = [
|
|
19
|
+
...new Set([
|
|
20
|
+
manifest.icon,
|
|
21
|
+
manifest.config.html,
|
|
22
|
+
...(manifest.desktop?.js || []).filter(filterLocalContent),
|
|
23
|
+
...(manifest.desktop?.css || []).filter(filterLocalContent),
|
|
24
|
+
...(manifest.mobile?.js || []).filter(filterLocalContent),
|
|
25
|
+
...(manifest.mobile?.css || []).filter(filterLocalContent),
|
|
26
|
+
...(manifest.config.js || []).filter(filterLocalContent),
|
|
27
|
+
...(manifest.config.css || []).filter(filterLocalContent),
|
|
28
|
+
]),
|
|
29
|
+
];
|
|
30
|
+
targetFiles.forEach((file) => {
|
|
31
|
+
const filePath = path.join(CONTENTS_DIRECTORY, file);
|
|
32
|
+
if (!fs.existsSync(filePath)) {
|
|
33
|
+
throw new Error(`${filePath} does not exist`);
|
|
34
|
+
}
|
|
35
|
+
archive.file(filePath, { name: file });
|
|
36
|
+
});
|
|
37
|
+
archive.pipe(outputZipStream);
|
|
38
|
+
await archive.finalize();
|
|
39
|
+
};
|
|
40
|
+
export const getContentsZipBuffer = async () => {
|
|
41
|
+
const outputZipPath = path.join(WORKSPACE_DIRECTORY, 'contents.zip');
|
|
42
|
+
return fs.readFile(outputZipPath);
|
|
43
|
+
};
|
|
44
|
+
export const getZipFileNameSuffix = (env) => {
|
|
45
|
+
return env === 'prod' ? '' : `-${env}`;
|
|
46
|
+
};
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { program } from 'commander';
|
|
3
|
+
import build from './commands/build/index.js';
|
|
4
|
+
import dev from './commands/dev/index.js';
|
|
5
|
+
import genkey from './commands/genkey/index.js';
|
|
6
|
+
import init from './commands/init/index.js';
|
|
7
|
+
import manifest from './commands/manifest/index.js';
|
|
8
|
+
import test from './commands/test/index.js';
|
|
9
|
+
import upload from './commands/upload/index.js';
|
|
10
|
+
import zip from './commands/zip/index.js';
|
|
11
|
+
program.name('plugin').version('0.0.1').description('');
|
|
12
|
+
build();
|
|
13
|
+
dev();
|
|
14
|
+
genkey();
|
|
15
|
+
init();
|
|
16
|
+
manifest();
|
|
17
|
+
test();
|
|
18
|
+
upload();
|
|
19
|
+
zip();
|
|
20
|
+
program.parse(process.argv);
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@konomi-app/k2",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "kintone sdk",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"k2": "./dist/index.js",
|
|
9
|
+
"plugin": "./dist/plugin.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"bin",
|
|
13
|
+
"dist",
|
|
14
|
+
"types",
|
|
15
|
+
"types.d.ts"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"prepare": "npm run build",
|
|
19
|
+
"build": "rmdir /s /q dist & tsc",
|
|
20
|
+
"dev": "tsc -w",
|
|
21
|
+
"watch": "tsc -w"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [],
|
|
24
|
+
"author": "",
|
|
25
|
+
"license": "ISC",
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@kintone/plugin-packer": "^8",
|
|
28
|
+
"@kintone/plugin-uploader": "^9",
|
|
29
|
+
"archiver": "^7",
|
|
30
|
+
"chalk": "^5",
|
|
31
|
+
"chokidar": "^3",
|
|
32
|
+
"commander": "^12",
|
|
33
|
+
"dotenv": "^16",
|
|
34
|
+
"esbuild": "^0.21",
|
|
35
|
+
"express": "^4",
|
|
36
|
+
"fs-extra": "^11",
|
|
37
|
+
"html-minifier": "^4",
|
|
38
|
+
"sass": "^1",
|
|
39
|
+
"vite": "^5",
|
|
40
|
+
"vite-tsconfig-paths": "^4"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/archiver": "*",
|
|
44
|
+
"@types/express": "^4.17.21",
|
|
45
|
+
"@types/fs-extra": "*",
|
|
46
|
+
"@types/html-minifier": "^4",
|
|
47
|
+
"typescript": "*"
|
|
48
|
+
}
|
|
49
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference path="plugin.d.ts" />
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
type Locales = {
|
|
2
|
+
/** 日本語 */
|
|
3
|
+
ja: string;
|
|
4
|
+
/** 英語 */
|
|
5
|
+
en: string;
|
|
6
|
+
/** 簡体字中国語 */
|
|
7
|
+
zh: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
type Resources = {
|
|
11
|
+
/**
|
|
12
|
+
* プラグインのJavaScriptファイル
|
|
13
|
+
*
|
|
14
|
+
* URLの配列
|
|
15
|
+
*/
|
|
16
|
+
js: string[];
|
|
17
|
+
/**
|
|
18
|
+
* プラグインのCSSファイル
|
|
19
|
+
*
|
|
20
|
+
* URLの配列
|
|
21
|
+
*/
|
|
22
|
+
css: string[];
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
declare namespace Plugin {
|
|
26
|
+
namespace Meta {
|
|
27
|
+
type Env = 'dev' | 'prod' | 'standalone';
|
|
28
|
+
|
|
29
|
+
type Manifest = {
|
|
30
|
+
type: 'APP';
|
|
31
|
+
manifest_version: 1;
|
|
32
|
+
version: number | string;
|
|
33
|
+
/**
|
|
34
|
+
* プラグインの名前
|
|
35
|
+
*
|
|
36
|
+
* インストール時、プラグイン一覧画面で表示されます
|
|
37
|
+
*/
|
|
38
|
+
name: Locales;
|
|
39
|
+
/**
|
|
40
|
+
* プラグインの説明
|
|
41
|
+
*
|
|
42
|
+
* インストール時、プラグイン一覧画面で表示されます
|
|
43
|
+
*/
|
|
44
|
+
description?: Locales;
|
|
45
|
+
icon: string;
|
|
46
|
+
homepage_url?: Partial<Locales>;
|
|
47
|
+
desktop?: Partial<Resources>;
|
|
48
|
+
mobile?: Partial<Resources>;
|
|
49
|
+
config?: Partial<Resources> & {
|
|
50
|
+
/** ファイルの種類 (js/css/html) をキーとする設定画面用カスタマイズファイルと設定情報 */
|
|
51
|
+
html?: string;
|
|
52
|
+
/**
|
|
53
|
+
* 設定画面で設定必須とするパラメータの配列
|
|
54
|
+
*
|
|
55
|
+
* ASCIIで1文字以上64文字以下
|
|
56
|
+
*/
|
|
57
|
+
required_params?: string[];
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 公開しているプラグインテンプレートで使用する設定ファイル
|
|
63
|
+
*
|
|
64
|
+
* @see {@link https://github.com/local-bias/kintone-plugin-template | kintone-plugin-template}
|
|
65
|
+
*/
|
|
66
|
+
type Config = {
|
|
67
|
+
id: string;
|
|
68
|
+
version?: 1;
|
|
69
|
+
manifest: {
|
|
70
|
+
base: Manifest;
|
|
71
|
+
dev?: Partial<Manifest>;
|
|
72
|
+
prod?: Partial<Manifest>;
|
|
73
|
+
standalone?: Partial<Manifest>;
|
|
74
|
+
};
|
|
75
|
+
pluginReleasePageUrl?: string;
|
|
76
|
+
inquiriesPageUrl?: string;
|
|
77
|
+
promotionPageUrl?: string;
|
|
78
|
+
bannerPageUrl?: string;
|
|
79
|
+
config_params?: Record<string, any>;
|
|
80
|
+
server?: {
|
|
81
|
+
/** 0から65535までのポート番号 */
|
|
82
|
+
port?: number;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
package/types.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference path="types/index.d.ts" />
|