@bluelamp/cli-token 1.0.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 ADDED
@@ -0,0 +1,44 @@
1
+ # @bluelamp/cli-token
2
+
3
+ BlueLamp CLI がローカルに保存するトークンファイル(`~/.musuhi/portal-token.enc`)の
4
+ 読み書きの**単一実装**。
5
+
6
+ 以前はこの処理が配布パッケージごとに複製されており、変更するたびに全複製を同時に
7
+ 書き換える必要があった(板#324)。複製をやめ、ここを唯一の import 元にする。
8
+
9
+ ## 使い方
10
+
11
+ ```ts
12
+ import { readCliTokenSync, tryReadCliToken } from '@bluelamp/cli-token';
13
+
14
+ // 読めなければ例外(再ログインを促したい呼び出し側向け)
15
+ const token = readCliTokenSync();
16
+
17
+ // 読めなければ null(「未設定」と同じに倒したい呼び出し側向け)
18
+ const maybe = tryReadCliToken();
19
+ ```
20
+
21
+ 失敗時の返し方が 2 種類あるのは、既存の消費側で挙動が分かれていたため。
22
+ 片方に寄せると呼び出し側の挙動が変わるので、両方を提供している。
23
+
24
+ ## API
25
+
26
+ | 種別 | 関数 |
27
+ |---|---|
28
+ | core(I/O なし) | `encryptPayload` / `decryptPayload` / `extractToken` / `validateTokenFormat` |
29
+ | shell(I/O あり) | `getTokenFilePath` / `readCliTokenSync` / `tryReadCliToken` / `loadPortalToken` / `savePortalToken` / `deletePortalToken` |
30
+
31
+ ## 制約
32
+
33
+ - **node 標準モジュール以外に依存しない**(VSCode 拡張が webpack で bundle するため)。
34
+ - i18n / console 出力をしない。利用者への通知は呼び出し側の責務。
35
+
36
+ ## 開発
37
+
38
+ ```bash
39
+ pnpm --filter @bluelamp/cli-token build
40
+ pnpm --filter @bluelamp/cli-token test
41
+ ```
42
+
43
+ テストは、このパッケージが**既存の配布済み実装と相互に読めること**を対照に取る
44
+ (自分で暗号化して自分で復号するだけでは、手順ごと取り違えていても緑になるため)。
@@ -0,0 +1,57 @@
1
+ /**
2
+ * BlueLamp CLI がローカルに保存するトークンファイルの読み書きの**単一実装**。
3
+ *
4
+ * 保存パス / 暗号手順 / 保存フォーマットはこのモジュールだけが定義する。
5
+ * 以前はこのロジックが配布パッケージごとに複製されており、変更のたびに全複製を
6
+ * 同時に書き換える必要があった(板#324)。複製をやめ、ここを唯一の import 元にする。
7
+ *
8
+ * 制約:
9
+ * - **node 標準モジュール以外に依存しない**。VSCode 拡張が webpack で bundle するため。
10
+ * - i18n / console 出力をしない。利用者への通知は呼び出し側の責務。
11
+ * - 失敗の返し方は消費側で分かれていたので、throw 版(readCliTokenSync)と
12
+ * null 版(tryReadCliToken)の両方を出す。片方に寄せると挙動が変わる。
13
+ */
14
+ /** 保存先パス。テストで HOME/USERPROFILE を差し替えられるよう呼び出し時に解決する。 */
15
+ export declare function getTokenFilePath(): string;
16
+ export interface StoredUserInfo {
17
+ id?: string;
18
+ name?: string;
19
+ email?: string;
20
+ role?: string;
21
+ language?: string;
22
+ }
23
+ export interface StoredTokenData {
24
+ token: string;
25
+ savedAt: number;
26
+ userInfo: StoredUserInfo;
27
+ version: string;
28
+ source: string;
29
+ }
30
+ export declare class CliTokenNotFoundError extends Error {
31
+ constructor(detail?: string);
32
+ }
33
+ /** 平文を `<ivHex>:<payloadHex>` にする。IV は毎回ランダム。 */
34
+ export declare function encryptPayload(plain: string): string;
35
+ /** `<ivHex>:<payloadHex>` を平文に戻す。形式不正・復号失敗は throw。 */
36
+ export declare function decryptPayload(encrypted: string): string;
37
+ /** 復号済み JSON から token を取り出す。取れなければ null(throw しない)。 */
38
+ export declare function extractToken(decryptedJson: string): string | null;
39
+ /** CLI トークンの形式検査。 */
40
+ export declare function validateTokenFormat(token: unknown): token is string;
41
+ /**
42
+ * トークンを読む。読めない場合は CliTokenNotFoundError を throw する。
43
+ * 失敗の詳細はメッセージに載るが、**復号結果そのものは決して載せない**。
44
+ */
45
+ export declare function readCliTokenSync(): string;
46
+ /**
47
+ * トークンを読む。読めない場合は null を返し、例外を投げない。
48
+ * 呼び出し側が「ファイルが無いのと同じ」に倒したい場合に使う。
49
+ */
50
+ export declare function tryReadCliToken(): string | null;
51
+ /** 保存済みデータを構造ごと読む。ファイル無し・内容不正は null、復号失敗は throw。 */
52
+ export declare function loadPortalToken(): StoredTokenData | null;
53
+ /** トークンを暗号化保存する。フォーマット不正・書込失敗は throw。 */
54
+ export declare function savePortalToken(token: string, userInfo?: StoredUserInfo): void;
55
+ /** 保存済みトークンを削除する。ファイル無しは no-op。削除失敗は throw。 */
56
+ export declare function deletePortalToken(): void;
57
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAgBH,wDAAwD;AACxD,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,MAAM,CAAC,EAAE,MAAM;CAQ5B;AAQD,iDAAiD;AACjD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAOxD;AAED,uDAAuD;AACvD,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOjE;AAED,qBAAqB;AACrB,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEnE;AAID;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAuBzC;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAM/C;AAED,oDAAoD;AACpD,wBAAgB,eAAe,IAAI,eAAe,GAAG,IAAI,CAUxD;AAED,yCAAyC;AACzC,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,GAAE,cAAmB,GAAG,IAAI,CAiBlF;AAED,+CAA+C;AAC/C,wBAAgB,iBAAiB,IAAI,IAAI,CAKxC"}
package/dist/index.js ADDED
@@ -0,0 +1,150 @@
1
+ /**
2
+ * BlueLamp CLI がローカルに保存するトークンファイルの読み書きの**単一実装**。
3
+ *
4
+ * 保存パス / 暗号手順 / 保存フォーマットはこのモジュールだけが定義する。
5
+ * 以前はこのロジックが配布パッケージごとに複製されており、変更のたびに全複製を
6
+ * 同時に書き換える必要があった(板#324)。複製をやめ、ここを唯一の import 元にする。
7
+ *
8
+ * 制約:
9
+ * - **node 標準モジュール以外に依存しない**。VSCode 拡張が webpack で bundle するため。
10
+ * - i18n / console 出力をしない。利用者への通知は呼び出し側の責務。
11
+ * - 失敗の返し方は消費側で分かれていたので、throw 版(readCliTokenSync)と
12
+ * null 版(tryReadCliToken)の両方を出す。片方に寄せると挙動が変わる。
13
+ */
14
+ import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from 'node:crypto';
15
+ import * as fs from 'node:fs';
16
+ import * as os from 'node:os';
17
+ import * as path from 'node:path';
18
+ const ALGORITHM = 'aes-256-cbc';
19
+ const KEY_SALT = 'salt';
20
+ const KEY_LENGTH = 32;
21
+ // 🚨 このリテラルは**リポジトリ内でここ 1 箇所だけ**に存在してよい。
22
+ // 複製すると露出面が増え、差し替えが同時多発の書き換えになる。
23
+ // 再発は CI(scripts/assert-cli-token-key-single-source.mjs)が赤にする。
24
+ const SECRET = 'musuhi-vscode-portal-token-key-2025';
25
+ /** 保存先パス。テストで HOME/USERPROFILE を差し替えられるよう呼び出し時に解決する。 */
26
+ export function getTokenFilePath() {
27
+ return path.join(os.homedir(), '.musuhi', 'portal-token.enc');
28
+ }
29
+ export class CliTokenNotFoundError extends Error {
30
+ constructor(detail) {
31
+ super('BlueLamp にログインしてください。ターミナルで `bluelamp1` を一度実行すると ' +
32
+ '~/.musuhi/portal-token.enc が作成されます' +
33
+ (detail ? ` (詳細: ${detail})` : ''));
34
+ this.name = 'CliTokenNotFoundError';
35
+ }
36
+ }
37
+ function derivedKey() {
38
+ return scryptSync(SECRET, KEY_SALT, KEY_LENGTH);
39
+ }
40
+ // ── functional core(I/O を持たない。ここだけで判定と変換が閉じる)──────────────
41
+ /** 平文を `<ivHex>:<payloadHex>` にする。IV は毎回ランダム。 */
42
+ export function encryptPayload(plain) {
43
+ const iv = randomBytes(16);
44
+ const cipher = createCipheriv(ALGORITHM, derivedKey(), iv);
45
+ const encrypted = cipher.update(plain, 'utf8', 'hex') + cipher.final('hex');
46
+ return `${iv.toString('hex')}:${encrypted}`;
47
+ }
48
+ /** `<ivHex>:<payloadHex>` を平文に戻す。形式不正・復号失敗は throw。 */
49
+ export function decryptPayload(encrypted) {
50
+ const parts = encrypted.split(':');
51
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
52
+ throw new Error('Invalid encrypted payload format');
53
+ }
54
+ const decipher = createDecipheriv(ALGORITHM, derivedKey(), Buffer.from(parts[0], 'hex'));
55
+ return decipher.update(parts[1], 'hex', 'utf8') + decipher.final('utf8');
56
+ }
57
+ /** 復号済み JSON から token を取り出す。取れなければ null(throw しない)。 */
58
+ export function extractToken(decryptedJson) {
59
+ try {
60
+ const parsed = JSON.parse(decryptedJson);
61
+ return typeof parsed.token === 'string' && parsed.token.length > 0 ? parsed.token : null;
62
+ }
63
+ catch {
64
+ return null;
65
+ }
66
+ }
67
+ /** CLI トークンの形式検査。 */
68
+ export function validateTokenFormat(token) {
69
+ return typeof token === 'string' && /^CLI_[a-f0-9]{64}$/i.test(token);
70
+ }
71
+ // ── imperative shell(薄い I/O 層)─────────────────────────────────────────────
72
+ /**
73
+ * トークンを読む。読めない場合は CliTokenNotFoundError を throw する。
74
+ * 失敗の詳細はメッセージに載るが、**復号結果そのものは決して載せない**。
75
+ */
76
+ export function readCliTokenSync() {
77
+ const filePath = getTokenFilePath();
78
+ if (!fs.existsSync(filePath)) {
79
+ throw new CliTokenNotFoundError(`${filePath} not found`);
80
+ }
81
+ let raw;
82
+ try {
83
+ raw = fs.readFileSync(filePath, 'utf-8');
84
+ }
85
+ catch (e) {
86
+ throw new CliTokenNotFoundError(`read failed: ${e.message}`);
87
+ }
88
+ let token;
89
+ try {
90
+ token = extractToken(decryptPayload(raw));
91
+ }
92
+ catch (e) {
93
+ throw new CliTokenNotFoundError(`decrypt failed: ${e.message}`);
94
+ }
95
+ if (token === null) {
96
+ throw new CliTokenNotFoundError('decrypt failed: token field missing');
97
+ }
98
+ return token;
99
+ }
100
+ /**
101
+ * トークンを読む。読めない場合は null を返し、例外を投げない。
102
+ * 呼び出し側が「ファイルが無いのと同じ」に倒したい場合に使う。
103
+ */
104
+ export function tryReadCliToken() {
105
+ try {
106
+ return readCliTokenSync();
107
+ }
108
+ catch {
109
+ return null;
110
+ }
111
+ }
112
+ /** 保存済みデータを構造ごと読む。ファイル無し・内容不正は null、復号失敗は throw。 */
113
+ export function loadPortalToken() {
114
+ const filePath = getTokenFilePath();
115
+ if (!fs.existsSync(filePath)) {
116
+ return null;
117
+ }
118
+ const data = JSON.parse(decryptPayload(fs.readFileSync(filePath, 'utf8')));
119
+ if (!data.token || !data.version) {
120
+ return null;
121
+ }
122
+ return data;
123
+ }
124
+ /** トークンを暗号化保存する。フォーマット不正・書込失敗は throw。 */
125
+ export function savePortalToken(token, userInfo = {}) {
126
+ if (!validateTokenFormat(token)) {
127
+ throw new Error('Invalid CLI token format');
128
+ }
129
+ const tokenData = {
130
+ token,
131
+ savedAt: Date.now(),
132
+ userInfo,
133
+ version: '1.0',
134
+ source: 'portal',
135
+ };
136
+ const filePath = getTokenFilePath();
137
+ const dir = path.dirname(filePath);
138
+ if (!fs.existsSync(dir)) {
139
+ fs.mkdirSync(dir, { recursive: true });
140
+ }
141
+ fs.writeFileSync(filePath, encryptPayload(JSON.stringify(tokenData)));
142
+ }
143
+ /** 保存済みトークンを削除する。ファイル無しは no-op。削除失敗は throw。 */
144
+ export function deletePortalToken() {
145
+ const filePath = getTokenFilePath();
146
+ if (fs.existsSync(filePath)) {
147
+ fs.unlinkSync(filePath);
148
+ }
149
+ }
150
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,MAAM,SAAS,GAAG,aAAa,CAAC;AAChC,MAAM,QAAQ,GAAG,MAAM,CAAC;AACxB,MAAM,UAAU,GAAG,EAAE,CAAC;AAEtB,yCAAyC;AACzC,oCAAoC;AACpC,kEAAkE;AAClE,MAAM,MAAM,GAAG,qCAAqC,CAAC;AAErD,wDAAwD;AACxD,MAAM,UAAU,gBAAgB;IAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAChE,CAAC;AAkBD,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,MAAe;QACzB,KAAK,CACH,mDAAmD;YACjD,oCAAoC;YACpC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CACrC,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,SAAS,UAAU;IACjB,OAAO,UAAU,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;AAClD,CAAC;AAED,6DAA6D;AAE7D,iDAAiD;AACjD,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;IAC3B,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;IAC3D,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5E,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,SAAS,EAAE,CAAC;AAC9C,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IACD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IACzF,OAAO,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC3E,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,YAAY,CAAC,aAAqB;IAChD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAwB,CAAC;QAChE,OAAO,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3F,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,qBAAqB;AACrB,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACxE,CAAC;AAED,6EAA6E;AAE7E;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;IACpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,qBAAqB,CAAC,GAAG,QAAQ,YAAY,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,qBAAqB,CAAC,gBAAiB,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,IAAI,KAAoB,CAAC;IACzB,IAAI,CAAC;QACH,KAAK,GAAG,YAAY,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,qBAAqB,CAAC,mBAAoB,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,qBAAqB,CAAC,qCAAqC,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC;QACH,OAAO,gBAAgB,EAAE,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,eAAe;IAC7B,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;IACpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAA6B,CAAC;IACvG,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAuB,CAAC;AACjC,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,eAAe,CAAC,KAAa,EAAE,WAA2B,EAAE;IAC1E,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9C,CAAC;IACD,MAAM,SAAS,GAAoB;QACjC,KAAK;QACL,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;QACnB,QAAQ;QACR,OAAO,EAAE,KAAK;QACd,MAAM,EAAE,QAAQ;KACjB,CAAC;IACF,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,iBAAiB;IAC/B,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;IACpC,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@bluelamp/cli-token",
3
+ "version": "1.0.0",
4
+ "description": "BlueLamp CLI が保存するローカルトークンファイルの読み書きの単一実装",
5
+ "keywords": [
6
+ "bluelamp",
7
+ "cli"
8
+ ],
9
+ "license": "MIT",
10
+ "author": "BlueLamp <dev@bluelamp.app>",
11
+ "type": "module",
12
+ "main": "dist/index.js",
13
+ "types": "dist/index.d.ts",
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
21
+ "scripts": {
22
+ "build": "tsc",
23
+ "tsc": "tsc --noEmit",
24
+ "prepublishOnly": "npm run build",
25
+ "test": "npm run build && node --test tests/*.test.mjs"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^22.10.5",
29
+ "typescript": "^5.7.3"
30
+ },
31
+ "engines": {
32
+ "node": ">=18"
33
+ }
34
+ }