@goqoo/trunks 1.1.0 → 1.2.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.ja.md CHANGED
@@ -1,4 +1,4 @@
1
- # trunks
1
+ # Trunks
2
2
 
3
3
  [![Node.js](https://img.shields.io/badge/Node.js-20+-339933?style=flat&logo=node.js)](https://nodejs.org/)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -99,11 +99,20 @@ KINTONE_PASSWORD=your-password
99
99
  KINTONE_API_TOKEN=your-api-token
100
100
  ```
101
101
 
102
- > **注意**: 設定ファイルに認証情報を直書きする場合は、設定ファイルを `.gitignore` に追加して、バージョン管理に機密情報がコミットされないようにしてください。環境変数(`.env` ファイル)または標準入力の使用を推奨します。
102
+ `~/.netrc` に認証情報を保存することもできます:
103
+
104
+ ```
105
+ machine example.cybozu.com
106
+ login your-username
107
+ password your-password
108
+ account basic-user:basic-password
109
+ ```
110
+
111
+ > **注意**: 設定ファイルに認証情報を直書きする場合は、設定ファイルを `.gitignore` に追加して、バージョン管理に機密情報がコミットされないようにしてください。環境変数(`.env` ファイル)、`~/.netrc`、または標準入力の使用を推奨します。
103
112
 
104
113
  #### パスワード
105
114
 
106
- 認証情報は設定ファイル、環境変数 `KINTONE_USERNAME` と `KINTONE_PASSWORD`、または標準入力から取得します(この優先順位)。
115
+ 認証情報は設定ファイル、`~/.netrc`、環境変数 `KINTONE_USERNAME` と `KINTONE_PASSWORD`、または標準入力から取得します(この優先順位)。
107
116
 
108
117
  ```typescript
109
118
  auth: { type: 'password' },
@@ -171,18 +180,10 @@ pfx: {
171
180
 
172
181
  ## CLI
173
182
 
174
- ### コマンド
175
-
176
- ```bash
177
- trunks init # 対話形式で trunks.config.ts を作成
178
- trunks generate # 型定義を生成(デフォルトコマンド)
179
- trunks # 'trunks generate' と同じ
180
- ```
181
-
182
183
  ### オプション
183
184
 
184
185
  ```bash
185
- trunks generate [options]
186
+ trunks [options]
186
187
 
187
188
  Options:
188
189
  -c, --config <path> 設定ファイルのパス
@@ -198,6 +199,7 @@ Options:
198
199
  -g, --guest-space-id <id> ゲストスペース ID
199
200
  -n, --namespace <namespace> TypeScript namespace
200
201
  -f, --format Prettier でフォーマット
202
+ -d, --debug エラー時に詳細情報を表示
201
203
  --proxy <host:port> プロキシサーバー
202
204
  --basic-auth-username <username> Basic 認証ユーザー名
203
205
  --basic-auth-password <password> Basic 認証パスワード
@@ -255,7 +257,7 @@ yarn dev
255
257
 
256
258
  - [@kintone/dts-gen](https://github.com/kintone/js-sdk/tree/main/packages/dts-gen) - 型定義生成の本体
257
259
  - [Gyuma](https://github.com/nicecai/gyuma) - kintone の OAuth 認証
258
- - [gotenks](https://github.com/goqoo-on-kintone/gotenks) - kintone TypeScript 型を Go 型に変換
260
+ - [Gotenks](https://github.com/goqoo-on-kintone/gotenks) - kintone TypeScript 型を Go 型に変換
259
261
 
260
262
  ## ライセンス
261
263
 
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # trunks
1
+ # Trunks
2
2
 
3
3
  [![Node.js](https://img.shields.io/badge/Node.js-20+-339933?style=flat&logo=node.js)](https://nodejs.org/)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -99,11 +99,20 @@ KINTONE_PASSWORD=your-password
99
99
  KINTONE_API_TOKEN=your-api-token
100
100
  ```
101
101
 
102
- > **Warning**: If you write credentials directly in the config file, make sure to add the config file to `.gitignore` to avoid committing sensitive information to version control. Using environment variables (`.env` file) or stdin prompts is recommended.
102
+ Credentials can also be stored in `~/.netrc`:
103
+
104
+ ```
105
+ machine example.cybozu.com
106
+ login your-username
107
+ password your-password
108
+ account basic-user:basic-password
109
+ ```
110
+
111
+ > **Warning**: If you write credentials directly in the config file, make sure to add the config file to `.gitignore` to avoid committing sensitive information to version control. Using environment variables (`.env` file), `~/.netrc`, or stdin prompts is recommended.
103
112
 
104
113
  #### Password
105
114
 
106
- Credentials are read from the config file, environment variables `KINTONE_USERNAME` and `KINTONE_PASSWORD`, or prompted via stdin (in that order of priority).
115
+ Credentials are read from the config file, `~/.netrc`, environment variables `KINTONE_USERNAME` and `KINTONE_PASSWORD`, or prompted via stdin (in that order of priority).
107
116
 
108
117
  ```typescript
109
118
  auth: { type: 'password' },
@@ -171,18 +180,10 @@ pfx: {
171
180
 
172
181
  ## CLI
173
182
 
174
- ### Commands
175
-
176
- ```bash
177
- trunks init # Create trunks.config.ts interactively
178
- trunks generate # Generate type definitions (default command)
179
- trunks # Same as 'trunks generate'
180
- ```
181
-
182
183
  ### Options
183
184
 
184
185
  ```bash
185
- trunks generate [options]
186
+ trunks [options]
186
187
 
187
188
  Options:
188
189
  -c, --config <path> Path to config file
@@ -198,6 +199,7 @@ Options:
198
199
  -g, --guest-space-id <id> Guest space ID
199
200
  -n, --namespace <namespace> TypeScript namespace
200
201
  -f, --format Format output with Prettier
202
+ -d, --debug Show detailed output on error
201
203
  --proxy <host:port> Proxy server
202
204
  --basic-auth-username <username> Basic auth username
203
205
  --basic-auth-password <password> Basic auth password
@@ -255,7 +257,7 @@ yarn dev
255
257
 
256
258
  - [@kintone/dts-gen](https://github.com/kintone/js-sdk/tree/main/packages/dts-gen) - The underlying type definition generator
257
259
  - [Gyuma](https://github.com/nicecai/gyuma) - OAuth authentication for Kintone
258
- - [gotenks](https://github.com/goqoo-on-kintone/gotenks) - Convert kintone TypeScript types to Go types
260
+ - [Gotenks](https://github.com/goqoo-on-kintone/gotenks) - Convert kintone TypeScript types to Go types
259
261
 
260
262
  ## License
261
263
 
package/dist/cli.js CHANGED
@@ -59,6 +59,8 @@ function buildConfigFromOptions(options) {
59
59
  config.namespace = options.namespace;
60
60
  if (options.format)
61
61
  config.format = true;
62
+ if (options.debug)
63
+ config.debug = true;
62
64
  // プロキシ設定
63
65
  if (options.proxy) {
64
66
  config.proxy = parseProxyOption(options.proxy);
@@ -72,28 +74,38 @@ function buildConfigFromOptions(options) {
72
74
  }
73
75
  return config;
74
76
  }
75
- const program = new Command();
76
- program
77
- .name('trunks')
78
- .description('Generate TypeScript type definitions for multiple Kintone apps')
79
- .version(version);
80
- // init コマンド
81
- program
82
- .command('init')
83
- .description('Create a new trunks.config.ts interactively')
84
- .action(async () => {
77
+ // 型定義生成のアクション
78
+ async function generateAction(options) {
85
79
  try {
86
- await init();
80
+ let config;
81
+ // --hostと--appが指定されている場合はCLIオプションから設定を構築
82
+ if (options.host && Object.keys(options.app).length > 0) {
83
+ config = buildConfigFromOptions(options);
84
+ }
85
+ else if (options.host || Object.keys(options.app).length > 0) {
86
+ // 片方だけ指定されている場合はエラー
87
+ throw new Error('Both --host and --app are required for CLI-only mode');
88
+ }
89
+ else {
90
+ // 設定ファイルから読み込み
91
+ config = await loadConfig(options.config ? undefined : process.cwd());
92
+ }
93
+ // --debug オプションはCLI引数を優先
94
+ if (options.debug)
95
+ config.debug = true;
96
+ await generate(config);
87
97
  }
88
98
  catch (error) {
89
99
  console.error(chalk.red('Error:'), error instanceof Error ? error.message : error);
90
100
  process.exit(1);
91
101
  }
92
- });
93
- // generate コマンド(デフォルト)
102
+ }
103
+ const program = new Command();
94
104
  program
95
- .command('generate', { isDefault: true })
96
- .description('Generate type definitions for all configured apps')
105
+ .name('trunks')
106
+ .description('Generate TypeScript type definitions for multiple Kintone apps')
107
+ .version(version)
108
+ // 設定ファイル
97
109
  .option('-c, --config <path>', 'Path to config file')
98
110
  // ワンライナー実行用オプション
99
111
  .option('-H, --host <host>', 'Kintone host (e.g., example.cybozu.com)')
@@ -108,25 +120,18 @@ program
108
120
  .option('-g, --guest-space-id <id>', 'Guest space ID')
109
121
  .option('-n, --namespace <namespace>', 'TypeScript namespace')
110
122
  .option('-f, --format', 'Format output with Prettier')
123
+ .option('-d, --debug', 'Show detailed output on error')
111
124
  .option('--proxy <host:port>', 'Proxy server')
112
125
  .option('--basic-auth-username <username>', 'Basic auth username')
113
126
  .option('--basic-auth-password <password>', 'Basic auth password')
114
- .action(async (options) => {
127
+ .action(generateAction);
128
+ // init コマンド
129
+ program
130
+ .command('init')
131
+ .description('Create a new trunks.config.ts interactively')
132
+ .action(async () => {
115
133
  try {
116
- let config;
117
- // --hostと--appが指定されている場合はCLIオプションから設定を構築
118
- if (options.host && Object.keys(options.app).length > 0) {
119
- config = buildConfigFromOptions(options);
120
- }
121
- else if (options.host || Object.keys(options.app).length > 0) {
122
- // 片方だけ指定されている場合はエラー
123
- throw new Error('Both --host and --app are required for CLI-only mode');
124
- }
125
- else {
126
- // 設定ファイルから読み込み
127
- config = await loadConfig(options.config ? undefined : process.cwd());
128
- }
129
- await generate(config);
134
+ await init();
130
135
  }
131
136
  catch (error) {
132
137
  console.error(chalk.red('Error:'), error instanceof Error ? error.message : error);
package/dist/generate.js CHANGED
@@ -3,7 +3,19 @@ import { mkdirSync } from 'fs';
3
3
  import * as readline from 'readline';
4
4
  import chalk from 'chalk';
5
5
  import { kebabCase, pascalCase } from 'change-case';
6
+ import { Netrc } from 'netrc-parser';
6
7
  import { getOauthToken } from './oauth.js';
8
+ function getNetrcCredentials(host) {
9
+ try {
10
+ const netrc = new Netrc();
11
+ netrc.loadSync();
12
+ return netrc.machines[host] ?? {};
13
+ }
14
+ catch {
15
+ // netrcファイルが存在しない場合などは空を返す
16
+ return {};
17
+ }
18
+ }
7
19
  // npx prettierが実行可能かチェック
8
20
  function isPrettierAvailable() {
9
21
  const result = spawnSync('npx', ['prettier', '--version'], {
@@ -88,11 +100,13 @@ function promptPassword(question) {
88
100
  // 認証引数を構築
89
101
  async function buildAuthArgs(config) {
90
102
  const args = {};
103
+ // netrcから認証情報を取得(OAuth以外で使用)
104
+ const netrcCreds = config.auth.type !== 'oauth' ? getNetrcCredentials(config.host) : {};
91
105
  switch (config.auth.type) {
92
106
  case 'password': {
93
- // 設定ファイル → 環境変数 → 標準入力の優先順位
94
- let username = config.auth.username ?? process.env.KINTONE_USERNAME;
95
- let password = config.auth.password ?? process.env.KINTONE_PASSWORD;
107
+ // 設定ファイル → netrc → 環境変数 → 標準入力の優先順位
108
+ let username = config.auth.username ?? netrcCreds.login ?? process.env.KINTONE_USERNAME;
109
+ let password = config.auth.password ?? netrcCreds.password ?? process.env.KINTONE_PASSWORD;
96
110
  // 未設定の場合は標準入力で取得
97
111
  if (!username) {
98
112
  username = await prompt('Kintone Username: ');
@@ -118,7 +132,7 @@ async function buildAuthArgs(config) {
118
132
  break;
119
133
  }
120
134
  case 'api-token': {
121
- // 設定ファイル → 環境変数 → 標準入力の優先順位
135
+ // 設定ファイル → 環境変数 → 標準入力の優先順位(APIトークンはnetrc非対応)
122
136
  let token = config.auth.token ?? process.env.KINTONE_API_TOKEN;
123
137
  if (!token) {
124
138
  token = await promptPassword('Kintone API Token: ');
@@ -130,11 +144,19 @@ async function buildAuthArgs(config) {
130
144
  break;
131
145
  }
132
146
  }
133
- // Basic認証
147
+ // Basic認証(設定ファイル → netrc)
134
148
  if (config.basicAuth) {
135
149
  args['basic-auth-username'] = config.basicAuth.username;
136
150
  args['basic-auth-password'] = config.basicAuth.password;
137
151
  }
152
+ else if (netrcCreds.account) {
153
+ // netrcのaccountフィールドからBasic認証を取得(user:password形式)
154
+ const [basicUser, basicPass] = netrcCreds.account.split(':');
155
+ if (basicUser && basicPass) {
156
+ args['basic-auth-username'] = basicUser;
157
+ args['basic-auth-password'] = basicPass;
158
+ }
159
+ }
138
160
  // プロキシ
139
161
  if (config.proxy) {
140
162
  args['proxy'] = `http://${config.proxy.host}:${config.proxy.port}`;
@@ -155,8 +177,20 @@ function extractKintoneError(output) {
155
177
  }
156
178
  return null;
157
179
  }
180
+ // 認証情報をマスクした引数を返す(デバッグ表示用)
181
+ function maskSensitiveArgs(args) {
182
+ const sensitiveKeys = ['password', 'api-token', 'oauth-token', 'basic-auth-password'];
183
+ return args.map((arg) => {
184
+ for (const key of sensitiveKeys) {
185
+ if (arg.startsWith(`--${key}=`)) {
186
+ return `--${key}=****`;
187
+ }
188
+ }
189
+ return arg;
190
+ });
191
+ }
158
192
  // 単一アプリの型定義を生成
159
- function generateForApp(appName, appId, config, authArgs, outDir) {
193
+ function generateForApp(appName, appId, config, authArgs, outDir, debug) {
160
194
  return new Promise((resolve) => {
161
195
  const outputPath = `${outDir}/${kebabCase(appName)}-fields.d.ts`;
162
196
  const args = {
@@ -200,6 +234,20 @@ function generateForApp(appName, appId, config, authArgs, outDir) {
200
234
  else {
201
235
  console.error(chalk.red(`Error [${appName}]:`), `kintone-dts-gen exited with code ${code}`);
202
236
  }
237
+ // デバッグモードの場合は詳細を表示
238
+ if (debug) {
239
+ console.error(chalk.gray('\n--- Debug Info ---'));
240
+ console.error(chalk.gray('Command:'), 'npx kintone-dts-gen', maskSensitiveArgs(cliArgs).join(' '));
241
+ if (stdout.trim()) {
242
+ console.error(chalk.gray('stdout:'));
243
+ console.error(chalk.gray(stdout));
244
+ }
245
+ if (stderr.trim()) {
246
+ console.error(chalk.gray('stderr:'));
247
+ console.error(chalk.gray(stderr));
248
+ }
249
+ console.error(chalk.gray('--- End Debug Info ---\n'));
250
+ }
203
251
  resolve({ success: false, output: outputPath });
204
252
  }
205
253
  else {
@@ -209,6 +257,9 @@ function generateForApp(appName, appId, config, authArgs, outDir) {
209
257
  });
210
258
  proc.on('error', (err) => {
211
259
  console.error(chalk.red(`Error [${appName}]:`), err.message);
260
+ if (debug) {
261
+ console.error(chalk.gray('Stack:'), err.stack);
262
+ }
212
263
  resolve({ success: false, output: outputPath });
213
264
  });
214
265
  });
@@ -223,9 +274,10 @@ export async function generate(config) {
223
274
  const usePrettier = config.format === true && isPrettierAvailable();
224
275
  console.info(chalk.cyan(`Generating type definitions for ${apps.length} app(s)...`));
225
276
  // 順次実行(並列だとコンソール出力が混在する)
277
+ const debug = config.debug === true;
226
278
  const results = [];
227
279
  for (const [appName, appId] of apps) {
228
- const result = await generateForApp(appName, appId, config, authArgs, outDir);
280
+ const result = await generateForApp(appName, appId, config, authArgs, outDir, debug);
229
281
  results.push(result);
230
282
  // 成功したファイルをPrettierでフォーマット
231
283
  if (result.success && usePrettier) {
package/dist/types.d.ts CHANGED
@@ -40,5 +40,6 @@ export type Config = {
40
40
  guestSpaceId?: number;
41
41
  namespace?: string;
42
42
  format?: boolean;
43
+ debug?: boolean;
43
44
  };
44
45
  export declare const defineConfig: (config: Config) => Config;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goqoo/trunks",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "A CLI wrapper for @kintone/dts-gen that generates type definitions for multiple Kintone apps",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -55,6 +55,7 @@
55
55
  "commander": "^13.0.0",
56
56
  "dotenv": "^17.3.1",
57
57
  "gyuma": "^0.6.1",
58
- "jiti": "^2.4.0"
58
+ "jiti": "^2.4.0",
59
+ "netrc-parser": "^3.1.6"
59
60
  }
60
61
  }