harvask-cli 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/LICENSE +21 -0
- package/README.md +147 -0
- package/dist/api-base.js +8 -0
- package/dist/api-base.js.map +1 -0
- package/dist/api-client.js +221 -0
- package/dist/api-client.js.map +1 -0
- package/dist/cli.js +154 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/_exec.js +63 -0
- package/dist/commands/_exec.js.map +1 -0
- package/dist/commands/api/index.js +88 -0
- package/dist/commands/api/index.js.map +1 -0
- package/dist/commands/attachment/index.js +54 -0
- package/dist/commands/attachment/index.js.map +1 -0
- package/dist/commands/auth/index.js +238 -0
- package/dist/commands/auth/index.js.map +1 -0
- package/dist/commands/calendar/index.js +167 -0
- package/dist/commands/calendar/index.js.map +1 -0
- package/dist/commands/chat/index.js +97 -0
- package/dist/commands/chat/index.js.map +1 -0
- package/dist/commands/file/index.js +42 -0
- package/dist/commands/file/index.js.map +1 -0
- package/dist/commands/global-wiki/index.js +196 -0
- package/dist/commands/global-wiki/index.js.map +1 -0
- package/dist/commands/issue/builds.js +160 -0
- package/dist/commands/issue/builds.js.map +1 -0
- package/dist/commands/issue/index.js +169 -0
- package/dist/commands/issue/index.js.map +1 -0
- package/dist/commands/issue/sub.js +149 -0
- package/dist/commands/issue/sub.js.map +1 -0
- package/dist/commands/issue/subbuilds.js +174 -0
- package/dist/commands/issue/subbuilds.js.map +1 -0
- package/dist/commands/milestone/index.js +104 -0
- package/dist/commands/milestone/index.js.map +1 -0
- package/dist/commands/note/builds.js +68 -0
- package/dist/commands/note/builds.js.map +1 -0
- package/dist/commands/note/index.js +122 -0
- package/dist/commands/note/index.js.map +1 -0
- package/dist/commands/preview-config/index.js +87 -0
- package/dist/commands/preview-config/index.js.map +1 -0
- package/dist/commands/project/builds.js +78 -0
- package/dist/commands/project/builds.js.map +1 -0
- package/dist/commands/project/index.js +103 -0
- package/dist/commands/project/index.js.map +1 -0
- package/dist/commands/scheduled-task/index.js +196 -0
- package/dist/commands/scheduled-task/index.js.map +1 -0
- package/dist/commands/site-credential/index.js +23 -0
- package/dist/commands/site-credential/index.js.map +1 -0
- package/dist/commands/skill/index.js +121 -0
- package/dist/commands/skill/index.js.map +1 -0
- package/dist/commands/storage/index.js +103 -0
- package/dist/commands/storage/index.js.map +1 -0
- package/dist/commands/user/index.js +55 -0
- package/dist/commands/user/index.js.map +1 -0
- package/dist/commands/wiki/builds.js +135 -0
- package/dist/commands/wiki/builds.js.map +1 -0
- package/dist/commands/wiki/index.js +177 -0
- package/dist/commands/wiki/index.js.map +1 -0
- package/dist/commands/workflow/index.js +111 -0
- package/dist/commands/workflow/index.js.map +1 -0
- package/dist/config.js +123 -0
- package/dist/config.js.map +1 -0
- package/dist/context.js +61 -0
- package/dist/context.js.map +1 -0
- package/dist/errors/hint-map.js +81 -0
- package/dist/errors/hint-map.js.map +1 -0
- package/dist/errors/index.js +132 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/output/format.js +108 -0
- package/dist/output/format.js.map +1 -0
- package/dist/output/index.js +3 -0
- package/dist/output/index.js.map +1 -0
- package/dist/output/tty.js +22 -0
- package/dist/output/tty.js.map +1 -0
- package/dist/registry.js +47 -0
- package/dist/registry.js.map +1 -0
- package/dist/token-store.js +92 -0
- package/dist/token-store.js.map +1 -0
- package/dist/types/api.js +8 -0
- package/dist/types/api.js.map +1 -0
- package/dist/utils/bulk.js +29 -0
- package/dist/utils/bulk.js.map +1 -0
- package/dist/utils/download.js +36 -0
- package/dist/utils/download.js.map +1 -0
- package/dist/utils/file-utils.js +58 -0
- package/dist/utils/file-utils.js.map +1 -0
- package/dist/utils/input.js +66 -0
- package/dist/utils/input.js.map +1 -0
- package/dist/utils/issue-resolver.js +20 -0
- package/dist/utils/issue-resolver.js.map +1 -0
- package/dist/utils/loopback.js +86 -0
- package/dist/utils/loopback.js.map +1 -0
- package/dist/utils/pkce.js +20 -0
- package/dist/utils/pkce.js.map +1 -0
- package/dist/utils/project-resolver.js +63 -0
- package/dist/utils/project-resolver.js.map +1 -0
- package/dist/utils/prompt.js +17 -0
- package/dist/utils/prompt.js.map +1 -0
- package/dist/utils/upload.js +32 -0
- package/dist/utils/upload.js.map +1 -0
- package/package.json +44 -0
- package/skills/harvask/AGENTS.md +131 -0
- package/skills/harvask/GEMINI.md +131 -0
- package/skills/harvask/SKILL.md +134 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAqB,MAAM,aAAa,CAAC;AAClF,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAUhD,MAAM,OAAO,cAAc;IACzB,KAAK,GAAgB,EAAE,CAAC;IAEhB,MAAM,CAAoB;IAElC,IAAI,GAAG;QACL,OAAO;YACL,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YAC9B,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;YAC5B,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YAC9B,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,KAAK,IAAI,aAAa,EAAE;SACrD,CAAC;IACJ,CAAC;IAEO,YAAY;QAClB,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO;YAC3B,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;YACzB,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;SAC1B,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,YAAY;QACV,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC,MAAM,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,QAAsB,EAAE;QACrC,MAAM,MAAM,GAAG,iBAAiB,CAAC;YAC/B,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,EAAE,GAAG,KAAK,EAAE;YAC3C,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,SAAS,EAAE;SACnB,CAAC,CAAC;QACH,OAAO,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,QAAsB,EAAE;QAChC,OAAO,aAAa,CAAC;YACnB,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,EAAE,GAAG,KAAK,EAAE;YAC3C,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,SAAS,EAAE;SACnB,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ApiClientError -> Why / Hint マッピング
|
|
3
|
+
*
|
|
4
|
+
* エージェントはエラーヒントに最も依存するため、statusCode ごとに
|
|
5
|
+
* 「なぜ失敗したか(Why)」「次に何をすべきか(Hint)」を actionable に返す。
|
|
6
|
+
*/
|
|
7
|
+
export function formatValidationErrors(errors) {
|
|
8
|
+
if (!errors) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
return Object.entries(errors)
|
|
12
|
+
.map(([field, messages]) => `${field}: ${messages.join(', ')}`)
|
|
13
|
+
.join('; ');
|
|
14
|
+
}
|
|
15
|
+
export function hintFor(e) {
|
|
16
|
+
const code = e.apiError?.code;
|
|
17
|
+
const apiMessage = e.apiError?.message;
|
|
18
|
+
switch (e.statusCode) {
|
|
19
|
+
case 401:
|
|
20
|
+
return {
|
|
21
|
+
why: apiMessage ?? 'Invalid or expired token.',
|
|
22
|
+
hint: 'Run `harvask login --tenant <domain>` to obtain a fresh token.',
|
|
23
|
+
};
|
|
24
|
+
case 403:
|
|
25
|
+
if (code === 'tenant_mismatch') {
|
|
26
|
+
return {
|
|
27
|
+
why: 'Token belongs to a different tenant domain.',
|
|
28
|
+
hint: 'Use the matching --profile, or re-login against the correct tenant (harvask login --tenant <domain>).',
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
if (code === 'not_project_member') {
|
|
32
|
+
return {
|
|
33
|
+
why: 'You are not a member of this project.',
|
|
34
|
+
hint: 'Ask a project admin to add you, or pick a project you belong to (`harvask project list`).',
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (code === 'invalid_token_type') {
|
|
38
|
+
return {
|
|
39
|
+
why: 'Token is not authorized for AI Worker (MCP) access.',
|
|
40
|
+
hint: 'Re-login with the CLI (`harvask login`) to issue a CLI-scoped token.',
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
why: apiMessage ?? 'Access denied.',
|
|
45
|
+
hint: 'Check your permission/role for this resource, or re-login with the correct tenant/profile.',
|
|
46
|
+
};
|
|
47
|
+
case 404:
|
|
48
|
+
return {
|
|
49
|
+
why: apiMessage ?? 'Resource not found.',
|
|
50
|
+
hint: 'Verify the id/key (e.g. project key PRJ, issue key PRJ-123). Use `harvask project list` / `harvask issue search` to find valid ids.',
|
|
51
|
+
};
|
|
52
|
+
case 422:
|
|
53
|
+
return {
|
|
54
|
+
why: formatValidationErrors(e.apiError?.errors) ?? apiMessage ?? e.message,
|
|
55
|
+
hint: 'Fix the listed fields. See `--help` for allowed values (issue_type/priority enums, title<=255, content<=500000).',
|
|
56
|
+
};
|
|
57
|
+
case 429:
|
|
58
|
+
return {
|
|
59
|
+
why: 'Rate limited (HTTP 429).',
|
|
60
|
+
hint: 'The client retries automatically (Retry-After). If it persists, reduce request frequency.',
|
|
61
|
+
};
|
|
62
|
+
case 408:
|
|
63
|
+
case 0:
|
|
64
|
+
return {
|
|
65
|
+
why: e.message,
|
|
66
|
+
hint: 'Network/timeout error. Check connectivity and the configured API URL (`harvask whoami`).',
|
|
67
|
+
};
|
|
68
|
+
default:
|
|
69
|
+
if (e.statusCode >= 500) {
|
|
70
|
+
return {
|
|
71
|
+
why: apiMessage ?? e.message,
|
|
72
|
+
hint: 'Server error. Retry later, or use `harvask api GET <path>` with --raw to inspect the response.',
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
why: apiMessage ?? e.message,
|
|
77
|
+
hint: 'Use --raw to inspect the full response, or `harvask api <method> <path>` to debug.',
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=hint-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hint-map.js","sourceRoot":"","sources":["../../src/errors/hint-map.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,UAAU,sBAAsB,CAAC,MAAiC;IACtE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;SAC1B,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,KAAK,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;SAC9D,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,CAAiB;IACvC,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC;IAC9B,MAAM,UAAU,GAAG,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC;IAEvC,QAAQ,CAAC,CAAC,UAAU,EAAE,CAAC;QACrB,KAAK,GAAG;YACN,OAAO;gBACL,GAAG,EAAE,UAAU,IAAI,2BAA2B;gBAC9C,IAAI,EAAE,gEAAgE;aACvE,CAAC;QACJ,KAAK,GAAG;YACN,IAAI,IAAI,KAAK,iBAAiB,EAAE,CAAC;gBAC/B,OAAO;oBACL,GAAG,EAAE,6CAA6C;oBAClD,IAAI,EAAE,uGAAuG;iBAC9G,CAAC;YACJ,CAAC;YACD,IAAI,IAAI,KAAK,oBAAoB,EAAE,CAAC;gBAClC,OAAO;oBACL,GAAG,EAAE,uCAAuC;oBAC5C,IAAI,EAAE,2FAA2F;iBAClG,CAAC;YACJ,CAAC;YACD,IAAI,IAAI,KAAK,oBAAoB,EAAE,CAAC;gBAClC,OAAO;oBACL,GAAG,EAAE,qDAAqD;oBAC1D,IAAI,EAAE,sEAAsE;iBAC7E,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,GAAG,EAAE,UAAU,IAAI,gBAAgB;gBACnC,IAAI,EAAE,4FAA4F;aACnG,CAAC;QACJ,KAAK,GAAG;YACN,OAAO;gBACL,GAAG,EAAE,UAAU,IAAI,qBAAqB;gBACxC,IAAI,EAAE,qIAAqI;aAC5I,CAAC;QACJ,KAAK,GAAG;YACN,OAAO;gBACL,GAAG,EAAE,sBAAsB,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,UAAU,IAAI,CAAC,CAAC,OAAO;gBAC1E,IAAI,EAAE,kHAAkH;aACzH,CAAC;QACJ,KAAK,GAAG;YACN,OAAO;gBACL,GAAG,EAAE,0BAA0B;gBAC/B,IAAI,EAAE,2FAA2F;aAClG,CAAC;QACJ,KAAK,GAAG,CAAC;QACT,KAAK,CAAC;YACJ,OAAO;gBACL,GAAG,EAAE,CAAC,CAAC,OAAO;gBACd,IAAI,EAAE,0FAA0F;aACjG,CAAC;QACJ;YACE,IAAI,CAAC,CAAC,UAAU,IAAI,GAAG,EAAE,CAAC;gBACxB,OAAO;oBACL,GAAG,EAAE,UAAU,IAAI,CAAC,CAAC,OAAO;oBAC5B,IAAI,EAAE,gGAAgG;iBACvG,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,GAAG,EAAE,UAAU,IAAI,CAAC,CAAC,OAAO;gBAC5B,IAAI,EAAE,oFAAoF;aAC3F,CAAC;IACN,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 構造化エラー(Error / Why / Hint)
|
|
3
|
+
*
|
|
4
|
+
* 例外を「何が起きたか / なぜ / 次にどうするか」に変換して出力する。
|
|
5
|
+
* トークン等の秘密は常にマスクする。
|
|
6
|
+
*/
|
|
7
|
+
import { ApiClientError } from '../api-client.js';
|
|
8
|
+
import { ConfigError, NotAuthenticatedError } from '../config.js';
|
|
9
|
+
import { ProjectIdentifierRequiredError, ProjectKeyNotFoundError, } from '../utils/project-resolver.js';
|
|
10
|
+
import { hintFor } from './hint-map.js';
|
|
11
|
+
/**
|
|
12
|
+
* CLI 引数のローカルバリデーションエラー(buildXxxCall が throw する)。
|
|
13
|
+
*/
|
|
14
|
+
export class ValidationError extends Error {
|
|
15
|
+
constructor(message) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = 'ValidationError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 64文字級のトークンや Bearer 文字列をマスクする。
|
|
22
|
+
*/
|
|
23
|
+
export function maskSecrets(text) {
|
|
24
|
+
return (text
|
|
25
|
+
// Authorization: Bearer <token>
|
|
26
|
+
.replace(/Bearer\s+[A-Za-z0-9._~+/=-]+/gi, 'Bearer ***')
|
|
27
|
+
// JWT(header.payload.signature)
|
|
28
|
+
.replace(/eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g, '***')
|
|
29
|
+
// Laravel Sanctum 形式(id|token)
|
|
30
|
+
.replace(/\b\d+\|[A-Za-z0-9]{20,}\b/g, '***')
|
|
31
|
+
// 区切り文字(. _ -)を含む長い不透明トークンも対象に含める
|
|
32
|
+
.replace(/[A-Za-z0-9][A-Za-z0-9._-]{39,}/g, '***'));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 例外を StructuredError に変換する。
|
|
36
|
+
*/
|
|
37
|
+
export function toStructuredError(error) {
|
|
38
|
+
if (error instanceof ApiClientError) {
|
|
39
|
+
const { why, hint } = hintFor(error);
|
|
40
|
+
const title = error.statusCode > 0
|
|
41
|
+
? `${error.message} (HTTP ${error.statusCode})`
|
|
42
|
+
: error.message;
|
|
43
|
+
return { error: title, why, hint };
|
|
44
|
+
}
|
|
45
|
+
if (error instanceof ValidationError) {
|
|
46
|
+
return {
|
|
47
|
+
error: 'Invalid arguments',
|
|
48
|
+
why: error.message,
|
|
49
|
+
hint: 'See `--help` for required options and allowed values.',
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (error instanceof NotAuthenticatedError) {
|
|
53
|
+
return {
|
|
54
|
+
error: error.message,
|
|
55
|
+
hint: 'Run `harvask login --tenant <domain>` to authenticate.',
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (error instanceof ConfigError) {
|
|
59
|
+
return {
|
|
60
|
+
error: error.message,
|
|
61
|
+
hint: 'Provide --tenant/--api-url, or run `harvask login`. API URL must be https (http only for localhost / *.harvask.test).',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
if (error instanceof ProjectKeyNotFoundError) {
|
|
65
|
+
return {
|
|
66
|
+
error: error.message,
|
|
67
|
+
hint: 'Run `harvask project list` to see valid project keys.',
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (error instanceof ProjectIdentifierRequiredError) {
|
|
71
|
+
return {
|
|
72
|
+
error: error.message,
|
|
73
|
+
hint: 'Pass -p/--project with a project key (PRJ) or numeric id.',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (error instanceof Error) {
|
|
77
|
+
return { error: error.message };
|
|
78
|
+
}
|
|
79
|
+
return { error: String(error) };
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* 例外に対応する終了コードを返す(エージェントが分岐しやすいよう区別)。
|
|
83
|
+
* 1 = バリデーション/一般的な 4xx, 2 = ネットワーク/5xx, 3 = 認証(401/403)
|
|
84
|
+
*/
|
|
85
|
+
export function exitCodeFor(error) {
|
|
86
|
+
if (error instanceof NotAuthenticatedError) {
|
|
87
|
+
return 3;
|
|
88
|
+
}
|
|
89
|
+
if (error instanceof ApiClientError) {
|
|
90
|
+
if (error.statusCode === 401 || error.statusCode === 403) {
|
|
91
|
+
return 3;
|
|
92
|
+
}
|
|
93
|
+
if (error.statusCode === 0 || error.statusCode === 408 || error.statusCode >= 500) {
|
|
94
|
+
return 2;
|
|
95
|
+
}
|
|
96
|
+
return 1;
|
|
97
|
+
}
|
|
98
|
+
return 1;
|
|
99
|
+
}
|
|
100
|
+
const RED = '\x1b[31m';
|
|
101
|
+
const BOLD = '\x1b[1m';
|
|
102
|
+
const DIM = '\x1b[2m';
|
|
103
|
+
const YELLOW = '\x1b[33m';
|
|
104
|
+
const RESET = '\x1b[0m';
|
|
105
|
+
/**
|
|
106
|
+
* 構造化エラーを stderr に書き出す。
|
|
107
|
+
*/
|
|
108
|
+
export function printError(error, out) {
|
|
109
|
+
const s = toStructuredError(error);
|
|
110
|
+
s.error = maskSecrets(s.error);
|
|
111
|
+
if (s.why) {
|
|
112
|
+
s.why = maskSecrets(s.why);
|
|
113
|
+
}
|
|
114
|
+
if (s.hint) {
|
|
115
|
+
s.hint = maskSecrets(s.hint);
|
|
116
|
+
}
|
|
117
|
+
if (out.json) {
|
|
118
|
+
process.stderr.write(JSON.stringify(s, null, 2) + '\n');
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const color = out.color;
|
|
122
|
+
const lines = [];
|
|
123
|
+
lines.push(`${color ? RED + BOLD : ''}Error:${color ? RESET : ''} ${s.error}`);
|
|
124
|
+
if (s.why) {
|
|
125
|
+
lines.push(`${color ? DIM : ''}Why:${color ? RESET : ''} ${s.why}`);
|
|
126
|
+
}
|
|
127
|
+
if (s.hint) {
|
|
128
|
+
lines.push(`${color ? YELLOW : ''}Hint:${color ? RESET : ''} ${s.hint}`);
|
|
129
|
+
}
|
|
130
|
+
process.stderr.write(lines.join('\n') + '\n');
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* harvask CLI エントリポイント
|
|
4
|
+
*/
|
|
5
|
+
import { run } from './cli.js';
|
|
6
|
+
// 処理完了後は明示的に終了する。
|
|
7
|
+
// fetch(undici) の keep-alive プールやループバックサーバの接続がイベントループに
|
|
8
|
+
// 残ってプロセスが終了しない(プロンプトが返らない)のを防ぐ。
|
|
9
|
+
// POSIX では stdout/stderr が同期書き込みのため、ここで exit しても出力は欠けない。
|
|
10
|
+
run(process.argv)
|
|
11
|
+
.then(() => process.exit(process.exitCode ?? 0))
|
|
12
|
+
.catch((err) => {
|
|
13
|
+
// run() 内で捕捉しきれなかった想定外エラー
|
|
14
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
15
|
+
process.exit(1);
|
|
16
|
+
});
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,kBAAkB;AAClB,uDAAuD;AACvD,iCAAiC;AACjC,yDAAyD;AACzD,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;KACd,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;KAC/C,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACb,0BAA0B;IAC1B,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 出力整形
|
|
3
|
+
*
|
|
4
|
+
* 方針(参考記事「Notion CLI for coding agent」準拠):
|
|
5
|
+
* - デフォルトは JSON pretty-print(エージェントが構造を読みやすい)。
|
|
6
|
+
* - TTY かつ色許可時のみ ANSI で着色。--json は機械可読のため無着色。
|
|
7
|
+
* - --raw は API レスポンスを素通し(整形なし)。
|
|
8
|
+
* - --data はエンベロープ({issue:...} 等)から主要データのみ取り出す。
|
|
9
|
+
*/
|
|
10
|
+
const ENVELOPE_KEYS = [
|
|
11
|
+
'issue',
|
|
12
|
+
'issues',
|
|
13
|
+
'page',
|
|
14
|
+
'pages',
|
|
15
|
+
'project',
|
|
16
|
+
'projects',
|
|
17
|
+
'note',
|
|
18
|
+
'notes',
|
|
19
|
+
'results',
|
|
20
|
+
'members',
|
|
21
|
+
'milestone',
|
|
22
|
+
'milestones',
|
|
23
|
+
'versions',
|
|
24
|
+
'comment',
|
|
25
|
+
'comments',
|
|
26
|
+
'todo',
|
|
27
|
+
'todos',
|
|
28
|
+
'memory',
|
|
29
|
+
'memories',
|
|
30
|
+
'event',
|
|
31
|
+
'events',
|
|
32
|
+
'user',
|
|
33
|
+
'users',
|
|
34
|
+
'thread',
|
|
35
|
+
'threads',
|
|
36
|
+
'messages',
|
|
37
|
+
'workflow',
|
|
38
|
+
'workflows',
|
|
39
|
+
'scheduled_task',
|
|
40
|
+
'scheduled_tasks',
|
|
41
|
+
'stats',
|
|
42
|
+
'site_credentials',
|
|
43
|
+
'preview_config',
|
|
44
|
+
'item',
|
|
45
|
+
'folder',
|
|
46
|
+
'attachment',
|
|
47
|
+
'data',
|
|
48
|
+
];
|
|
49
|
+
/**
|
|
50
|
+
* 既知のエンベロープキーから主要データを取り出す。見つからなければそのまま返す。
|
|
51
|
+
*/
|
|
52
|
+
export function unwrapData(result) {
|
|
53
|
+
if (result && typeof result === 'object' && !Array.isArray(result)) {
|
|
54
|
+
const obj = result;
|
|
55
|
+
for (const key of ENVELOPE_KEYS) {
|
|
56
|
+
if (key in obj) {
|
|
57
|
+
return obj[key];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
const COLORS = {
|
|
64
|
+
key: '\x1b[36m', // cyan
|
|
65
|
+
str: '\x1b[32m', // green
|
|
66
|
+
num: '\x1b[33m', // yellow
|
|
67
|
+
bool: '\x1b[35m', // magenta
|
|
68
|
+
null: '\x1b[90m', // gray
|
|
69
|
+
reset: '\x1b[0m',
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* JSON 文字列を ANSI で着色する(依存追加なしの軽量実装)。
|
|
73
|
+
*/
|
|
74
|
+
export function colorizeJson(json) {
|
|
75
|
+
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false)\b|\bnull\b|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)/g, (match) => {
|
|
76
|
+
if (/^"/.test(match)) {
|
|
77
|
+
return /:\s*$/.test(match)
|
|
78
|
+
? COLORS.key + match + COLORS.reset
|
|
79
|
+
: COLORS.str + match + COLORS.reset;
|
|
80
|
+
}
|
|
81
|
+
if (/^(true|false)$/.test(match)) {
|
|
82
|
+
return COLORS.bool + match + COLORS.reset;
|
|
83
|
+
}
|
|
84
|
+
if (match === 'null') {
|
|
85
|
+
return COLORS.null + match + COLORS.reset;
|
|
86
|
+
}
|
|
87
|
+
return COLORS.num + match + COLORS.reset;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* 結果を標準出力へ整形して書き出す。
|
|
92
|
+
*/
|
|
93
|
+
export function printOutput(result, out) {
|
|
94
|
+
if (out.raw) {
|
|
95
|
+
const raw = typeof result === 'string' ? result : JSON.stringify(result);
|
|
96
|
+
process.stdout.write(raw + '\n');
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
let payload = out.data ? unwrapData(result) : result;
|
|
100
|
+
// --json かつ文字列値はオブジェクトに包む(機械可読性のため)
|
|
101
|
+
if (out.json && typeof payload === 'string') {
|
|
102
|
+
payload = { text: payload };
|
|
103
|
+
}
|
|
104
|
+
const json = JSON.stringify(payload, null, 2);
|
|
105
|
+
const useColor = out.color && !out.json;
|
|
106
|
+
process.stdout.write((useColor ? colorizeJson(json) : json) + '\n');
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/output/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/output/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TTY / 色サポートの検出
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* 標準出力がインタラクティブ(端末)か。非TTY=パイプ/エージェント想定。
|
|
6
|
+
*/
|
|
7
|
+
export function isInteractive() {
|
|
8
|
+
return Boolean(process.stdout.isTTY);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* ANSI カラーを使ってよいか。NO_COLOR は常に優先(https://no-color.org/)。
|
|
12
|
+
*/
|
|
13
|
+
export function supportsColor() {
|
|
14
|
+
if (process.env.NO_COLOR !== undefined && process.env.NO_COLOR !== '') {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
if (process.env.FORCE_COLOR !== undefined && process.env.FORCE_COLOR !== '') {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
return Boolean(process.stdout.isTTY);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=tty.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tty.js","sourceRoot":"","sources":["../../src/output/tty.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,EAAE,EAAE,CAAC;QACtE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,EAAE,EAAE,CAAC;QAC5E,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACvC,CAAC"}
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* コマンドレジストリ
|
|
3
|
+
*
|
|
4
|
+
* 各カテゴリは CategoryModule を実装し、CATEGORIES 配列に登録する。
|
|
5
|
+
* 新カテゴリ追加 = ここに import を1行足すだけ(cli.ts が自動登録する)。
|
|
6
|
+
*/
|
|
7
|
+
import { issueModule } from './commands/issue/index.js';
|
|
8
|
+
import { wikiModule } from './commands/wiki/index.js';
|
|
9
|
+
import { projectModule } from './commands/project/index.js';
|
|
10
|
+
import { noteModule } from './commands/note/index.js';
|
|
11
|
+
import { authModule } from './commands/auth/index.js';
|
|
12
|
+
import { apiModule } from './commands/api/index.js';
|
|
13
|
+
import { calendarModule } from './commands/calendar/index.js';
|
|
14
|
+
import { milestoneModule } from './commands/milestone/index.js';
|
|
15
|
+
import { globalWikiModule } from './commands/global-wiki/index.js';
|
|
16
|
+
import { userModule } from './commands/user/index.js';
|
|
17
|
+
import { siteCredentialModule } from './commands/site-credential/index.js';
|
|
18
|
+
import { previewConfigModule } from './commands/preview-config/index.js';
|
|
19
|
+
import { workflowModule } from './commands/workflow/index.js';
|
|
20
|
+
import { scheduledTaskModule } from './commands/scheduled-task/index.js';
|
|
21
|
+
import { chatModule } from './commands/chat/index.js';
|
|
22
|
+
import { fileModule } from './commands/file/index.js';
|
|
23
|
+
import { storageModule } from './commands/storage/index.js';
|
|
24
|
+
import { attachmentModule } from './commands/attachment/index.js';
|
|
25
|
+
import { skillModule } from './commands/skill/index.js';
|
|
26
|
+
export const CATEGORIES = [
|
|
27
|
+
authModule,
|
|
28
|
+
projectModule,
|
|
29
|
+
issueModule,
|
|
30
|
+
wikiModule,
|
|
31
|
+
globalWikiModule,
|
|
32
|
+
noteModule,
|
|
33
|
+
milestoneModule,
|
|
34
|
+
calendarModule,
|
|
35
|
+
userModule,
|
|
36
|
+
workflowModule,
|
|
37
|
+
scheduledTaskModule,
|
|
38
|
+
chatModule,
|
|
39
|
+
fileModule,
|
|
40
|
+
storageModule,
|
|
41
|
+
attachmentModule,
|
|
42
|
+
siteCredentialModule,
|
|
43
|
+
previewConfigModule,
|
|
44
|
+
skillModule,
|
|
45
|
+
apiModule,
|
|
46
|
+
];
|
|
47
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwBH,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,MAAM,CAAC,MAAM,UAAU,GAAqB;IAC1C,UAAU;IACV,aAAa;IACb,WAAW;IACX,UAAU;IACV,gBAAgB;IAChB,UAAU;IACV,eAAe;IACf,cAAc;IACd,UAAU;IACV,cAAc;IACd,mBAAmB;IACnB,UAAU;IACV,UAAU;IACV,aAAa;IACb,gBAAgB;IAChB,oBAAoB;IACpB,mBAAmB;IACnB,WAAW;IACX,SAAS;CACV,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* トークンストア
|
|
3
|
+
*
|
|
4
|
+
* env-paths でOS別の設定ディレクトリに tokens.json を 0o600 で保存する。
|
|
5
|
+
* 複数テナント(テナントドメインをキー)に対応し、current で既定テナントを保持する。
|
|
6
|
+
*/
|
|
7
|
+
import envPaths from 'env-paths';
|
|
8
|
+
import { existsSync, lstatSync, mkdirSync, readFileSync, writeFileSync, chmodSync, rmSync, } from 'node:fs';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
export function getStoreDir() {
|
|
11
|
+
return envPaths('harvask', { suffix: '' }).config;
|
|
12
|
+
}
|
|
13
|
+
export function getStorePath() {
|
|
14
|
+
return join(getStoreDir(), 'tokens.json');
|
|
15
|
+
}
|
|
16
|
+
export function readStore() {
|
|
17
|
+
const path = getStorePath();
|
|
18
|
+
if (!existsSync(path)) {
|
|
19
|
+
return { current: null, tenants: {} };
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const data = JSON.parse(readFileSync(path, 'utf8'));
|
|
23
|
+
return { current: data.current ?? null, tenants: data.tenants ?? {} };
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return { current: null, tenants: {} };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function writeStore(data) {
|
|
30
|
+
const dir = getStoreDir();
|
|
31
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
32
|
+
// 既存ディレクトリにも 0o700 を強制(事前に緩い権限で作られていた場合の引き締め)。
|
|
33
|
+
try {
|
|
34
|
+
chmodSync(dir, 0o700);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
/* Windows 等では無意味なため無視 */
|
|
38
|
+
}
|
|
39
|
+
const path = getStorePath();
|
|
40
|
+
// 攻撃者が tokens.json をシンボリックリンクとして事前設置し、書き込み/権限変更を別ファイルへ
|
|
41
|
+
// 飛ばすのを防ぐため、シンボリックリンクなら削除してから書く。
|
|
42
|
+
try {
|
|
43
|
+
if (lstatSync(path).isSymbolicLink()) {
|
|
44
|
+
rmSync(path);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
/* 未存在は無視 */
|
|
49
|
+
}
|
|
50
|
+
writeFileSync(path, JSON.stringify(data, null, 2) + '\n', { mode: 0o600 });
|
|
51
|
+
try {
|
|
52
|
+
chmodSync(path, 0o600);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
/* Windows 等では権限変更が無意味な場合があるため無視 */
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* テナントエントリを保存し、current に設定する。
|
|
60
|
+
*/
|
|
61
|
+
export function saveTenant(entry) {
|
|
62
|
+
const store = readStore();
|
|
63
|
+
store.tenants[entry.tenant_domain] = entry;
|
|
64
|
+
store.current = entry.tenant_domain;
|
|
65
|
+
writeStore(store);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 指定テナントを削除する。current だった場合は別テナントへ付け替える。
|
|
69
|
+
*/
|
|
70
|
+
export function removeTenant(domain) {
|
|
71
|
+
const store = readStore();
|
|
72
|
+
if (!store.tenants[domain]) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
delete store.tenants[domain];
|
|
76
|
+
if (store.current === domain) {
|
|
77
|
+
const remaining = Object.keys(store.tenants);
|
|
78
|
+
store.current = remaining.length > 0 ? remaining[0] : null;
|
|
79
|
+
}
|
|
80
|
+
writeStore(store);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* 全テナントを削除する(tokens.json を削除)。
|
|
85
|
+
*/
|
|
86
|
+
export function clearAll() {
|
|
87
|
+
const path = getStorePath();
|
|
88
|
+
if (existsSync(path)) {
|
|
89
|
+
rmSync(path);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=token-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-store.js","sourceRoot":"","sources":["../src/token-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/types/api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一括操作の共通ヘルパ(kairon utils/bulk-format.ts を CLI 向けに移植)。
|
|
3
|
+
*/
|
|
4
|
+
import { ValidationError } from '../errors/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* items が配列で 1〜50 件かを検証する。
|
|
7
|
+
*/
|
|
8
|
+
export function validateBulkItems(items) {
|
|
9
|
+
if (!Array.isArray(items)) {
|
|
10
|
+
throw new ValidationError('items must be a JSON array');
|
|
11
|
+
}
|
|
12
|
+
if (items.length === 0) {
|
|
13
|
+
throw new ValidationError('items must contain at least 1 item');
|
|
14
|
+
}
|
|
15
|
+
if (items.length > 50) {
|
|
16
|
+
throw new ValidationError(`items must be <= 50 (got ${items.length})`);
|
|
17
|
+
}
|
|
18
|
+
return items;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* atomic 指定時に ?atomic=1 を付与する。
|
|
22
|
+
*/
|
|
23
|
+
export function appendAtomic(path, atomic) {
|
|
24
|
+
if (!atomic) {
|
|
25
|
+
return path;
|
|
26
|
+
}
|
|
27
|
+
return path + (path.includes('?') ? '&' : '?') + 'atomic=1';
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=bulk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bulk.js","sourceRoot":"","sources":["../../src/utils/bulk.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,eAAe,CAAC,4BAA4B,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,eAAe,CAAC,oCAAoC,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACtB,MAAM,IAAI,eAAe,CAAC,4BAA4B,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,MAAe;IACxD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* バイナリダウンロードの保存ヘルパ。
|
|
3
|
+
*/
|
|
4
|
+
import { writeFileSync } from 'node:fs';
|
|
5
|
+
import { basename } from 'node:path';
|
|
6
|
+
import { ValidationError } from '../errors/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* 保存先パスを決める純粋関数。
|
|
9
|
+
* - --out が明示指定されていればユーザーの意図としてそのまま使う。
|
|
10
|
+
* - 無ければレスポンス(Content-Disposition)由来の filename を使うが、これはサーバ制御の
|
|
11
|
+
* 値なので basename のみに切り詰める。これにより `../../etc/passwd` や絶対パスを書かせる
|
|
12
|
+
* パストラバーサル(cwd 外への任意ファイル書き込み)を防ぐ。
|
|
13
|
+
*/
|
|
14
|
+
export function resolveOutPath(out, filename) {
|
|
15
|
+
if (out) {
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
if (!filename) {
|
|
19
|
+
throw new ValidationError('could not determine output filename; pass --out <path>');
|
|
20
|
+
}
|
|
21
|
+
// サーバ提供のファイル名はディレクトリ成分を除去し、cwd 直下に限定する。
|
|
22
|
+
const safe = basename(filename);
|
|
23
|
+
if (!safe || safe === '.' || safe === '..') {
|
|
24
|
+
throw new ValidationError('server provided an unsafe filename; pass --out <path>');
|
|
25
|
+
}
|
|
26
|
+
return safe;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* getBlob の結果をファイルに保存し、サマリを返す。
|
|
30
|
+
*/
|
|
31
|
+
export function saveBlob(blob, out) {
|
|
32
|
+
const path = resolveOutPath(out, blob.filename);
|
|
33
|
+
writeFileSync(path, Buffer.from(blob.buffer));
|
|
34
|
+
return { saved: path, bytes: blob.buffer.byteLength, content_type: blob.contentType };
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=download.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download.js","sourceRoot":"","sources":["../../src/utils/download.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,GAAuB,EAAE,QAA4B;IAClF,IAAI,GAAG,EAAE,CAAC;QACR,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,eAAe,CAAC,wDAAwD,CAAC,CAAC;IACtF,CAAC;IACD,wCAAwC;IACxC,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAChC,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAC3C,MAAM,IAAI,eAAe,CAAC,uDAAuD,CAAC,CAAC;IACrF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CACtB,IAAqE,EACrE,GAAuB;IAEvB,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAChD,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9C,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,YAAY,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;AACxF,CAAC"}
|