@produck/agent-toolkit 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 +67 -0
- package/bin/agent-toolkit.mjs +414 -0
- package/package.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# @produck/agent-toolkit
|
|
2
|
+
|
|
3
|
+
Central CLI toolkit for organization-level AI execution workflows.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
- agent-toolkit preflight
|
|
8
|
+
- agent-toolkit run-capture
|
|
9
|
+
- agent-toolkit summarize-log
|
|
10
|
+
- agent-toolkit validate-commit-msg
|
|
11
|
+
|
|
12
|
+
## Examples
|
|
13
|
+
|
|
14
|
+
Run preflight checks:
|
|
15
|
+
|
|
16
|
+
npm exec --package=@produck/agent-toolkit@latest \
|
|
17
|
+
agent-toolkit preflight --cwd . --require package.json --ensure-dir logs
|
|
18
|
+
|
|
19
|
+
Capture long output safely:
|
|
20
|
+
|
|
21
|
+
npm exec --package=@produck/agent-toolkit@latest \
|
|
22
|
+
agent-toolkit run-capture --cwd . --cmd "npm run test" --out logs/test.log
|
|
23
|
+
|
|
24
|
+
Summarize captured output:
|
|
25
|
+
|
|
26
|
+
npm exec --package=@produck/agent-toolkit@latest \
|
|
27
|
+
agent-toolkit summarize-log --file logs/test.log --match "FAIL|ERROR"
|
|
28
|
+
|
|
29
|
+
Validate commit message format:
|
|
30
|
+
|
|
31
|
+
npm exec --package=@produck/agent-toolkit@latest \
|
|
32
|
+
agent-toolkit validate-commit-msg --file .git/COMMIT_EDITMSG
|
|
33
|
+
|
|
34
|
+
## Local verification
|
|
35
|
+
|
|
36
|
+
From repository root:
|
|
37
|
+
|
|
38
|
+
npm --prefix tools/agent-toolkit run verify
|
|
39
|
+
npm --prefix tools/agent-toolkit run pack:check
|
|
40
|
+
|
|
41
|
+
## Manual publish
|
|
42
|
+
|
|
43
|
+
Dry-run publish:
|
|
44
|
+
|
|
45
|
+
npm --prefix tools/agent-toolkit run publish:dry-run
|
|
46
|
+
|
|
47
|
+
Publish latest:
|
|
48
|
+
|
|
49
|
+
npm --prefix tools/agent-toolkit run publish:latest
|
|
50
|
+
|
|
51
|
+
## GitHub workflow
|
|
52
|
+
|
|
53
|
+
Repository includes manual workflow:
|
|
54
|
+
|
|
55
|
+
- .github/workflows/publish-agent-toolkit.yml
|
|
56
|
+
|
|
57
|
+
Workflow behavior:
|
|
58
|
+
|
|
59
|
+
- Always runs verify, pack:check, and publish:dry-run.
|
|
60
|
+
- Does not publish to npm.
|
|
61
|
+
- Used as release gate before manual publish.
|
|
62
|
+
|
|
63
|
+
Release policy:
|
|
64
|
+
|
|
65
|
+
- Default organization usage is @latest.
|
|
66
|
+
- Run verify and publish:dry-run before publish:latest.
|
|
67
|
+
- Keep rollback option by republishing previous stable version if needed.
|
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { spawn } from 'node:child_process';
|
|
5
|
+
|
|
6
|
+
const ALLOWED_TAGS = ['INIT', 'ADD', 'REMOVE', 'FIX', 'REFACTOR', 'UPGRADE'];
|
|
7
|
+
const ALLOWED_TARGETS = ['docs', 'test', 'ci', 'deps', 'api', 'schema', 'infra'];
|
|
8
|
+
|
|
9
|
+
function parseCommonArgs(argv) {
|
|
10
|
+
const positional = [];
|
|
11
|
+
const options = {};
|
|
12
|
+
|
|
13
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
14
|
+
const token = argv[i];
|
|
15
|
+
if (token.startsWith('--')) {
|
|
16
|
+
const next = argv[i + 1];
|
|
17
|
+
if (!next || next.startsWith('--')) {
|
|
18
|
+
if (!options[token]) {
|
|
19
|
+
options[token] = [];
|
|
20
|
+
}
|
|
21
|
+
options[token].push(true);
|
|
22
|
+
} else {
|
|
23
|
+
if (!options[token]) {
|
|
24
|
+
options[token] = [];
|
|
25
|
+
}
|
|
26
|
+
options[token].push(next);
|
|
27
|
+
i += 1;
|
|
28
|
+
}
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
positional.push(token);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return { positional, options };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function getSingle(options, key, fallback = '') {
|
|
38
|
+
if (!options[key] || options[key].length === 0) {
|
|
39
|
+
return fallback;
|
|
40
|
+
}
|
|
41
|
+
return String(options[key][options[key].length - 1]);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function getMulti(options, key) {
|
|
45
|
+
if (!options[key]) {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
return options[key].map((v) => String(v));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function hasFlag(options, key) {
|
|
52
|
+
return Boolean(options[key]);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function printMainHelp() {
|
|
56
|
+
console.log([
|
|
57
|
+
'agent-toolkit commands:',
|
|
58
|
+
' preflight',
|
|
59
|
+
' run-capture',
|
|
60
|
+
' summarize-log',
|
|
61
|
+
' validate-commit-msg',
|
|
62
|
+
'',
|
|
63
|
+
'Use:',
|
|
64
|
+
' agent-toolkit <command> --help',
|
|
65
|
+
].join('\n'));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function printPreflightHelp() {
|
|
69
|
+
console.log([
|
|
70
|
+
'Usage:',
|
|
71
|
+
' agent-toolkit preflight [--cwd <dir>] [--require <path>] ...',
|
|
72
|
+
' [--ensure-dir <path>] ... [--json <file>]',
|
|
73
|
+
].join('\n'));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function printRunCaptureHelp() {
|
|
77
|
+
console.log([
|
|
78
|
+
'Usage:',
|
|
79
|
+
' agent-toolkit run-capture --out <logFile> --cmd <command>',
|
|
80
|
+
' [--cwd <directory>] [--meta <metaFile>] [--allow-pipe]',
|
|
81
|
+
].join('\n'));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function printSummarizeHelp() {
|
|
85
|
+
console.log([
|
|
86
|
+
'Usage:',
|
|
87
|
+
' agent-toolkit summarize-log --file <logFile>',
|
|
88
|
+
' [--last <lineCount>] [--match <regex>] [--max <lineCount>]',
|
|
89
|
+
].join('\n'));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function printValidateHelp() {
|
|
93
|
+
console.log([
|
|
94
|
+
'Usage:',
|
|
95
|
+
' agent-toolkit validate-commit-msg --file <message-file>',
|
|
96
|
+
'',
|
|
97
|
+
'Rules:',
|
|
98
|
+
' - Every line must start with [TAG]',
|
|
99
|
+
' - No empty lines are allowed',
|
|
100
|
+
' - Optional target form: [TAG] <target>: <summary>',
|
|
101
|
+
].join('\n'));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function runPreflight(options) {
|
|
105
|
+
const cwd = path.resolve(getSingle(options, '--cwd', process.cwd()));
|
|
106
|
+
const required = getMulti(options, '--require');
|
|
107
|
+
const ensureDir = getMulti(options, '--ensure-dir');
|
|
108
|
+
const jsonFile = getSingle(options, '--json', '');
|
|
109
|
+
|
|
110
|
+
if (!fs.existsSync(cwd)) {
|
|
111
|
+
console.error(`CWD does not exist: ${cwd}`);
|
|
112
|
+
process.exit(2);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const report = {
|
|
116
|
+
cwd,
|
|
117
|
+
required: [],
|
|
118
|
+
ensuredDirectories: [],
|
|
119
|
+
ok: true,
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
for (const rel of required) {
|
|
123
|
+
const resolved = path.resolve(cwd, rel);
|
|
124
|
+
const exists = fs.existsSync(resolved);
|
|
125
|
+
report.required.push({ path: rel, resolved, exists });
|
|
126
|
+
if (!exists) {
|
|
127
|
+
report.ok = false;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
for (const rel of ensureDir) {
|
|
132
|
+
const resolved = path.resolve(cwd, rel);
|
|
133
|
+
fs.mkdirSync(resolved, { recursive: true });
|
|
134
|
+
report.ensuredDirectories.push({ path: rel, resolved, created: true });
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (jsonFile) {
|
|
138
|
+
const out = path.resolve(cwd, jsonFile);
|
|
139
|
+
fs.mkdirSync(path.dirname(out), { recursive: true });
|
|
140
|
+
fs.writeFileSync(out, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
144
|
+
if (!report.ok) {
|
|
145
|
+
process.exit(2);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function runCapture(options) {
|
|
150
|
+
const out = getSingle(options, '--out', '');
|
|
151
|
+
const cmd = getSingle(options, '--cmd', '');
|
|
152
|
+
const cwd = path.resolve(getSingle(options, '--cwd', process.cwd()));
|
|
153
|
+
const meta = getSingle(options, '--meta', '');
|
|
154
|
+
const allowPipe = hasFlag(options, '--allow-pipe');
|
|
155
|
+
|
|
156
|
+
if (!out || !cmd) {
|
|
157
|
+
printRunCaptureHelp();
|
|
158
|
+
process.exit(2);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!allowPipe && cmd.includes('|')) {
|
|
162
|
+
console.error('Blocked command containing pipe. Use --allow-pipe if needed.');
|
|
163
|
+
process.exit(2);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const outPath = path.resolve(out);
|
|
167
|
+
const metaPath = meta ? path.resolve(meta) : `${outPath}.meta.json`;
|
|
168
|
+
|
|
169
|
+
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
170
|
+
fs.mkdirSync(path.dirname(metaPath), { recursive: true });
|
|
171
|
+
|
|
172
|
+
const startAt = Date.now();
|
|
173
|
+
const outStream = fs.createWriteStream(outPath, { encoding: 'utf8' });
|
|
174
|
+
|
|
175
|
+
outStream.write(`# command: ${cmd}\n`);
|
|
176
|
+
outStream.write(`# cwd: ${cwd}\n`);
|
|
177
|
+
outStream.write(`# startedAt: ${new Date(startAt).toISOString()}\n\n`);
|
|
178
|
+
|
|
179
|
+
const child = spawn(cmd, {
|
|
180
|
+
cwd,
|
|
181
|
+
shell: true,
|
|
182
|
+
env: process.env,
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
let stdoutBytes = 0;
|
|
186
|
+
let stderrBytes = 0;
|
|
187
|
+
|
|
188
|
+
child.stdout.on('data', (chunk) => {
|
|
189
|
+
stdoutBytes += chunk.length;
|
|
190
|
+
outStream.write(chunk);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
child.stderr.on('data', (chunk) => {
|
|
194
|
+
stderrBytes += chunk.length;
|
|
195
|
+
outStream.write(chunk);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
child.on('error', (error) => {
|
|
199
|
+
outStream.write(`\n[agent-toolkit] spawn error: ${error.message}\n`);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
child.on('close', (code, signal) => {
|
|
203
|
+
const endAt = Date.now();
|
|
204
|
+
const durationMs = endAt - startAt;
|
|
205
|
+
|
|
206
|
+
outStream.write('\n');
|
|
207
|
+
outStream.write(`# finishedAt: ${new Date(endAt).toISOString()}\n`);
|
|
208
|
+
outStream.write(`# exitCode: ${String(code)}\n`);
|
|
209
|
+
outStream.write(`# signal: ${signal ? String(signal) : 'none'}\n`);
|
|
210
|
+
outStream.end();
|
|
211
|
+
|
|
212
|
+
const report = {
|
|
213
|
+
command: cmd,
|
|
214
|
+
cwd,
|
|
215
|
+
startedAt: new Date(startAt).toISOString(),
|
|
216
|
+
finishedAt: new Date(endAt).toISOString(),
|
|
217
|
+
durationMs,
|
|
218
|
+
exitCode: code,
|
|
219
|
+
signal,
|
|
220
|
+
stdoutBytes,
|
|
221
|
+
stderrBytes,
|
|
222
|
+
outputFile: outPath,
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
fs.writeFileSync(metaPath, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
|
|
226
|
+
|
|
227
|
+
if (typeof code === 'number') {
|
|
228
|
+
process.exit(code);
|
|
229
|
+
}
|
|
230
|
+
process.exit(1);
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function runSummarize(options) {
|
|
235
|
+
const file = getSingle(options, '--file', '');
|
|
236
|
+
const last = Number(getSingle(options, '--last', '0')) || 0;
|
|
237
|
+
const match = getSingle(options, '--match', '');
|
|
238
|
+
const max = Number(getSingle(options, '--max', '200')) || 200;
|
|
239
|
+
|
|
240
|
+
if (!file) {
|
|
241
|
+
printSummarizeHelp();
|
|
242
|
+
process.exit(2);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const filePath = path.resolve(file);
|
|
246
|
+
if (!fs.existsSync(filePath)) {
|
|
247
|
+
console.error(`Log file does not exist: ${filePath}`);
|
|
248
|
+
process.exit(2);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const raw = fs.readFileSync(filePath, 'utf8');
|
|
252
|
+
const allLines = raw.split(/\r?\n/);
|
|
253
|
+
|
|
254
|
+
let lines = allLines;
|
|
255
|
+
let mode = 'all';
|
|
256
|
+
|
|
257
|
+
if (match) {
|
|
258
|
+
const pattern = new RegExp(match, 'i');
|
|
259
|
+
lines = allLines.filter((line) => pattern.test(line));
|
|
260
|
+
mode = 'match';
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (last > 0) {
|
|
264
|
+
lines = lines.slice(-last);
|
|
265
|
+
mode = mode === 'match' ? 'match+last' : 'last';
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (max > 0 && lines.length > max) {
|
|
269
|
+
lines = lines.slice(0, max);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const header = [
|
|
273
|
+
`# file: ${filePath}`,
|
|
274
|
+
`# totalLines: ${allLines.length}`,
|
|
275
|
+
`# selectedLines: ${lines.length}`,
|
|
276
|
+
`# mode: ${mode}`,
|
|
277
|
+
'',
|
|
278
|
+
].join('\n');
|
|
279
|
+
|
|
280
|
+
process.stdout.write(header);
|
|
281
|
+
process.stdout.write(lines.join('\n'));
|
|
282
|
+
process.stdout.write('\n');
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function validateCommitLine(line, lineNo) {
|
|
286
|
+
if (line.trim() === '') {
|
|
287
|
+
return `Line ${lineNo}: empty line is not allowed`;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const head = line.match(/^\[([A-Z]+)\]\s+/);
|
|
291
|
+
if (!head) {
|
|
292
|
+
return `Line ${lineNo}: must start with [TAG] followed by a space`;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const tag = head[1];
|
|
296
|
+
if (!ALLOWED_TAGS.includes(tag)) {
|
|
297
|
+
return `Line ${lineNo}: tag [${tag}] is not allowed`;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const rest = line.slice(head[0].length);
|
|
301
|
+
if (rest.trim() === '') {
|
|
302
|
+
return `Line ${lineNo}: summary is required after tag`;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const targetMatch = rest.match(/^<([^>]+)>:\s+(.+)$/);
|
|
306
|
+
if (targetMatch) {
|
|
307
|
+
const target = targetMatch[1];
|
|
308
|
+
const summary = targetMatch[2];
|
|
309
|
+
if (!ALLOWED_TARGETS.includes(target)) {
|
|
310
|
+
return `Line ${lineNo}: target <${target}> is not allowed`;
|
|
311
|
+
}
|
|
312
|
+
if (summary.trim() === '') {
|
|
313
|
+
return `Line ${lineNo}: summary is required after target`;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function runValidateCommitMsg(options) {
|
|
321
|
+
const file = getSingle(options, '--file', '');
|
|
322
|
+
if (!file) {
|
|
323
|
+
printValidateHelp();
|
|
324
|
+
process.exit(2);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const filePath = path.resolve(file);
|
|
328
|
+
if (!fs.existsSync(filePath)) {
|
|
329
|
+
console.error(`Message file not found: ${filePath}`);
|
|
330
|
+
process.exit(2);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const raw = fs.readFileSync(filePath, 'utf8').replace(/\r\n/g, '\n');
|
|
334
|
+
const lines = raw.endsWith('\n') ? raw.slice(0, -1).split('\n') : raw.split('\n');
|
|
335
|
+
|
|
336
|
+
if (lines.length === 0 || (lines.length === 1 && lines[0].trim() === '')) {
|
|
337
|
+
console.error('Commit message is empty');
|
|
338
|
+
process.exit(2);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const errors = [];
|
|
342
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
343
|
+
const err = validateCommitLine(lines[i], i + 1);
|
|
344
|
+
if (err) {
|
|
345
|
+
errors.push(err);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (errors.length > 0) {
|
|
350
|
+
console.error('Commit message validation failed:');
|
|
351
|
+
for (const err of errors) {
|
|
352
|
+
console.error(`- ${err}`);
|
|
353
|
+
}
|
|
354
|
+
process.exit(1);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
console.log('Commit message validation passed');
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function main() {
|
|
361
|
+
const parsed = parseCommonArgs(process.argv.slice(2));
|
|
362
|
+
const command = parsed.positional[0] || '';
|
|
363
|
+
const options = parsed.options;
|
|
364
|
+
|
|
365
|
+
if (!command || command === '--help' || command === '-h') {
|
|
366
|
+
printMainHelp();
|
|
367
|
+
process.exit(0);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (hasFlag(options, '--help') || hasFlag(options, '-h')) {
|
|
371
|
+
if (command === 'preflight') {
|
|
372
|
+
printPreflightHelp();
|
|
373
|
+
process.exit(0);
|
|
374
|
+
}
|
|
375
|
+
if (command === 'run-capture') {
|
|
376
|
+
printRunCaptureHelp();
|
|
377
|
+
process.exit(0);
|
|
378
|
+
}
|
|
379
|
+
if (command === 'summarize-log') {
|
|
380
|
+
printSummarizeHelp();
|
|
381
|
+
process.exit(0);
|
|
382
|
+
}
|
|
383
|
+
if (command === 'validate-commit-msg') {
|
|
384
|
+
printValidateHelp();
|
|
385
|
+
process.exit(0);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (command === 'preflight') {
|
|
390
|
+
runPreflight(options);
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if (command === 'run-capture') {
|
|
395
|
+
runCapture(options);
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (command === 'summarize-log') {
|
|
400
|
+
runSummarize(options);
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (command === 'validate-commit-msg') {
|
|
405
|
+
runValidateCommitMsg(options);
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
console.error(`Unknown command: ${command}`);
|
|
410
|
+
printMainHelp();
|
|
411
|
+
process.exit(2);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@produck/agent-toolkit",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Central CLI toolkit for organization AI execution workflows",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/produck/.github.git",
|
|
9
|
+
"directory": "tools/agent-toolkit"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"agent-toolkit": "./bin/agent-toolkit.mjs"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"verify": "node ./bin/agent-toolkit.mjs --help && node ./bin/agent-toolkit.mjs preflight --cwd . --require package.json",
|
|
16
|
+
"pack:check": "npm pack --dry-run",
|
|
17
|
+
"publish:dry-run": "npm publish --dry-run --access public",
|
|
18
|
+
"publish:latest": "npm publish --access public"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"bin"
|
|
22
|
+
],
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18.0.0"
|
|
28
|
+
},
|
|
29
|
+
"license": "MIT"
|
|
30
|
+
}
|