@interactive-inc/docs-client 0.0.7 → 0.0.9
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 +0 -228
- package/build/index.d.ts +4 -0
- package/build/index.js +28 -11
- package/package.json +1 -1
- package/debug/debug.ts +0 -108
package/README.md
CHANGED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
# @interactive-inc/docs-client
|
|
2
|
-
|
|
3
|
-
技術仕様書、製品資料など、Markdownで記述された資料をリポジトリで管理する際に、それらを効率的に読み書きするためのAPIを提供します。
|
|
4
|
-
|
|
5
|
-
```ts
|
|
6
|
-
import { DocClient, DocFileSystem, DocPathSystem } from "@interactive-inc/docs-client"
|
|
7
|
-
|
|
8
|
-
const docClient = new DocClient({
|
|
9
|
-
fileSystem: new DocFileSystem({
|
|
10
|
-
basePath: "/docs", // リポジトリ内のドキュメントルート
|
|
11
|
-
pathSystem: new DocPathSystem(),
|
|
12
|
-
}),
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
const ref = docClient
|
|
16
|
-
.directory("products/product-1/features")
|
|
17
|
-
.file("login.md")
|
|
18
|
-
|
|
19
|
-
const entity = await ref.read()
|
|
20
|
-
|
|
21
|
-
if (entity instanceof Error) throw entity
|
|
22
|
-
|
|
23
|
-
console.log(entity.content.title)
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## インストール
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
bun add @interactive-inc/docs
|
|
30
|
-
# または
|
|
31
|
-
npm install @interactive-inc/docs
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## 設計
|
|
35
|
-
|
|
36
|
-
このライブラリは、Markdownファイルを構造化されたディレクトリでの動作を想定しています。
|
|
37
|
-
|
|
38
|
-
以下は製品仕様書を管理する場合の一例です。ディレクトリ構造は自由に設計できます:
|
|
39
|
-
|
|
40
|
-
```
|
|
41
|
-
docs/ # ドキュメントルート(任意の名前)
|
|
42
|
-
├── products/ # 製品ドキュメント(例)
|
|
43
|
-
│ ├── product-a/
|
|
44
|
-
│ │ ├── index.md # 製品概要
|
|
45
|
-
│ │ ├── features/ # 機能仕様
|
|
46
|
-
│ │ │ ├── login.md
|
|
47
|
-
│ │ │ └── _/ # アーカイブ(非推奨・削除予定)
|
|
48
|
-
│ │ │ └── old-feature.md
|
|
49
|
-
│ │ ├── pages/ # 画面仕様
|
|
50
|
-
│ │ └── terms/ # 製品固有の用語
|
|
51
|
-
│ └── product-b/
|
|
52
|
-
├── terms/ # 共通用語集(例)
|
|
53
|
-
├── guidelines/ # 開発ガイドライン(例)
|
|
54
|
-
└── index.md # ルートドキュメント
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## 機能
|
|
58
|
-
|
|
59
|
-
### アーカイブシステム
|
|
60
|
-
|
|
61
|
-
ファイルを削除する代わりに、`_`ディレクトリに移動することで論理削除を表現できます。
|
|
62
|
-
|
|
63
|
-
- `features/login.md` → `features/_/login.md` (アーカイブ)
|
|
64
|
-
- アーカイブされたファイルも読み取り可能
|
|
65
|
-
- 必要に応じて復元可能
|
|
66
|
-
|
|
67
|
-
```ts
|
|
68
|
-
// ファイルをアーカイブする
|
|
69
|
-
const fileRef = docClient.directory("specs/v1").mdFile("deprecated-api.md")
|
|
70
|
-
await fileRef.archive()
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### メタデータ管理
|
|
74
|
-
|
|
75
|
-
各Markdownファイルの先頭にYAML形式でメタデータを記述:
|
|
76
|
-
|
|
77
|
-
```markdown
|
|
78
|
-
---
|
|
79
|
-
title: ログイン機能
|
|
80
|
-
milestone: 2025.01
|
|
81
|
-
features:
|
|
82
|
-
- authentication
|
|
83
|
-
- security
|
|
84
|
-
priority: high
|
|
85
|
-
is-done: false
|
|
86
|
-
---
|
|
87
|
-
|
|
88
|
-
# ログイン機能
|
|
89
|
-
|
|
90
|
-
説明...
|
|
91
|
-
|
|
92
|
-
本文...
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
このように操作できます。
|
|
96
|
-
|
|
97
|
-
```ts
|
|
98
|
-
// FrontMatterの読み取り
|
|
99
|
-
const fileRef = docClient.directory("features").mdFile("login.md")
|
|
100
|
-
|
|
101
|
-
const file = await fileRef.read()
|
|
102
|
-
|
|
103
|
-
if (file instanceof Error) throw file
|
|
104
|
-
|
|
105
|
-
// "ログイン機能"
|
|
106
|
-
console.log(file.content.frontMatter.title)
|
|
107
|
-
|
|
108
|
-
// ["authentication", "security"]
|
|
109
|
-
console.log(file.content.frontMatter.features)
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### ファイル間のリレーション
|
|
113
|
-
|
|
114
|
-
FrontMatterとスキーマを使用して、ドキュメント間の関連を定義できます。
|
|
115
|
-
|
|
116
|
-
#### スキーマの定義(index.md)
|
|
117
|
-
|
|
118
|
-
```markdown
|
|
119
|
-
---
|
|
120
|
-
title: 機能一覧
|
|
121
|
-
schema:
|
|
122
|
-
page:
|
|
123
|
-
type: relation
|
|
124
|
-
path: "../pages"
|
|
125
|
-
title: 関連ページ
|
|
126
|
-
required: false
|
|
127
|
-
tags:
|
|
128
|
-
type: multi-relation
|
|
129
|
-
path: "../tags"
|
|
130
|
-
title: タグ
|
|
131
|
-
required: false
|
|
132
|
-
---
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
#### リレーションの使用
|
|
136
|
-
|
|
137
|
-
features/login.md
|
|
138
|
-
|
|
139
|
-
```markdown
|
|
140
|
-
---
|
|
141
|
-
title: ログイン機能
|
|
142
|
-
page: login-page
|
|
143
|
-
tags:
|
|
144
|
-
- authentication
|
|
145
|
-
- security
|
|
146
|
-
---
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
#### 使い方
|
|
150
|
-
|
|
151
|
-
```ts
|
|
152
|
-
const featureRef = docClient.directory("features").mdFile("login.md")
|
|
153
|
-
|
|
154
|
-
const relatedTags = await featureRef.relations("tags")
|
|
155
|
-
|
|
156
|
-
for (const tagRef of relatedTags) {
|
|
157
|
-
const tagEntity = await tagRef.read()
|
|
158
|
-
if (tagEntity instanceof Error) continue
|
|
159
|
-
console.log(tagEntity.content.title)
|
|
160
|
-
}
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
## 使い方
|
|
164
|
-
|
|
165
|
-
### 初期設定
|
|
166
|
-
|
|
167
|
-
```ts
|
|
168
|
-
import { DocClient, DocFileSystem, DocPathSystem } from "@interactive-inc/docs-client"
|
|
169
|
-
|
|
170
|
-
const docClient = new DocClient({
|
|
171
|
-
fileSystem: new DocFileSystem({
|
|
172
|
-
basePath: "/path/to/your-repo/docs",
|
|
173
|
-
pathSystem: new DocPathSystem(),
|
|
174
|
-
}),
|
|
175
|
-
})
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
### ファイルの読み書き
|
|
179
|
-
|
|
180
|
-
```ts
|
|
181
|
-
// ファイル読み取り
|
|
182
|
-
const fileRef = docClient
|
|
183
|
-
.directory("specifications/api")
|
|
184
|
-
.mdFile("authentication.md")
|
|
185
|
-
|
|
186
|
-
const entity = await fileRef.read()
|
|
187
|
-
if (entity instanceof Error) throw entity
|
|
188
|
-
|
|
189
|
-
console.log(entity.content.body)
|
|
190
|
-
console.log(entity.content.frontMatter.value)
|
|
191
|
-
|
|
192
|
-
// ファイル作成・更新
|
|
193
|
-
await fileRef.writeContent(`---
|
|
194
|
-
title: 認証API仕様
|
|
195
|
-
version: 2.0.0
|
|
196
|
-
---
|
|
197
|
-
|
|
198
|
-
# 認証API仕様
|
|
199
|
-
|
|
200
|
-
POST /api/v2/auth/login
|
|
201
|
-
`)
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
### FrontMatterの操作
|
|
205
|
-
|
|
206
|
-
```ts
|
|
207
|
-
const entity = await fileRef.read()
|
|
208
|
-
if (entity instanceof Error) throw entity
|
|
209
|
-
|
|
210
|
-
// メタデータ更新
|
|
211
|
-
const newFrontMatter = new DocFrontMatterMdValue({
|
|
212
|
-
...entity.content.frontMatter.value,
|
|
213
|
-
milestone: "2025.02",
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
const newContent = entity.content.withFrontMatter(newFrontMatter)
|
|
217
|
-
await fileRef.writeContent(newContent.toText())
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
### アーカイブ操作
|
|
221
|
-
|
|
222
|
-
```ts
|
|
223
|
-
// ファイルをアーカイブ
|
|
224
|
-
const fileRef = docClient
|
|
225
|
-
.directory("specifications/api/v1")
|
|
226
|
-
.mdFile("legacy-endpoints.md")
|
|
227
|
-
await fileRef.archive()
|
|
228
|
-
```
|
package/build/index.d.ts
CHANGED
package/build/index.js
CHANGED
|
@@ -1348,9 +1348,9 @@ var DocSchemaFieldFactory = class {
|
|
|
1348
1348
|
const baseField = {
|
|
1349
1349
|
type: normalizedType,
|
|
1350
1350
|
required: fieldRequired ?? false,
|
|
1351
|
-
title: fieldTitle,
|
|
1352
|
-
description: fieldDescription,
|
|
1353
|
-
default: fieldDefault
|
|
1351
|
+
title: fieldTitle ?? null,
|
|
1352
|
+
description: fieldDescription ?? null,
|
|
1353
|
+
default: fieldDefault ?? null
|
|
1354
1354
|
};
|
|
1355
1355
|
return {
|
|
1356
1356
|
...baseField,
|
|
@@ -1364,9 +1364,9 @@ var DocSchemaFieldFactory = class {
|
|
|
1364
1364
|
return {
|
|
1365
1365
|
type: "text",
|
|
1366
1366
|
required: false,
|
|
1367
|
-
title:
|
|
1368
|
-
description:
|
|
1369
|
-
default:
|
|
1367
|
+
title: null,
|
|
1368
|
+
description: null,
|
|
1369
|
+
default: null
|
|
1370
1370
|
};
|
|
1371
1371
|
}
|
|
1372
1372
|
/**
|
|
@@ -2109,9 +2109,10 @@ import { parse as parse2, stringify as stringify3 } from "yaml";
|
|
|
2109
2109
|
|
|
2110
2110
|
// lib/values/doc-schema-value.ts
|
|
2111
2111
|
var DocSchemaValue = class _DocSchemaValue {
|
|
2112
|
+
value;
|
|
2112
2113
|
constructor(value) {
|
|
2113
|
-
this.value = value;
|
|
2114
|
-
zDocSchema.parse(value);
|
|
2114
|
+
this.value = _DocSchemaValue.normalizeSchema(value);
|
|
2115
|
+
zDocSchema.parse(this.value);
|
|
2115
2116
|
Object.freeze(this.value);
|
|
2116
2117
|
Object.freeze(this);
|
|
2117
2118
|
}
|
|
@@ -2130,7 +2131,7 @@ var DocSchemaValue = class _DocSchemaValue {
|
|
|
2130
2131
|
return null;
|
|
2131
2132
|
}
|
|
2132
2133
|
const factory = new DocSchemaFieldFactory();
|
|
2133
|
-
return factory.
|
|
2134
|
+
return factory.fromUnknown(name, fieldDef);
|
|
2134
2135
|
}
|
|
2135
2136
|
get fields() {
|
|
2136
2137
|
const factory = new DocSchemaFieldFactory();
|
|
@@ -2139,7 +2140,7 @@ var DocSchemaValue = class _DocSchemaValue {
|
|
|
2139
2140
|
if (!fieldValue) {
|
|
2140
2141
|
throw new Error(`Field ${name} not found in schema`);
|
|
2141
2142
|
}
|
|
2142
|
-
return factory.
|
|
2143
|
+
return factory.fromUnknown(name, fieldValue);
|
|
2143
2144
|
});
|
|
2144
2145
|
}
|
|
2145
2146
|
get relationFields() {
|
|
@@ -2351,6 +2352,21 @@ var DocSchemaValue = class _DocSchemaValue {
|
|
|
2351
2352
|
toJson() {
|
|
2352
2353
|
return this.value;
|
|
2353
2354
|
}
|
|
2355
|
+
/**
|
|
2356
|
+
* スキーマを正規化
|
|
2357
|
+
*/
|
|
2358
|
+
static normalizeSchema(schema) {
|
|
2359
|
+
const normalized = {};
|
|
2360
|
+
const factory = new DocSchemaFieldFactory();
|
|
2361
|
+
for (const [key, field] of Object.entries(schema)) {
|
|
2362
|
+
try {
|
|
2363
|
+
const normalizedField = factory.fromUnknown(key, field);
|
|
2364
|
+
normalized[key] = normalizedField.toJson();
|
|
2365
|
+
} catch {
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
return normalized;
|
|
2369
|
+
}
|
|
2354
2370
|
};
|
|
2355
2371
|
|
|
2356
2372
|
// lib/values/doc-front-matter-index-value.ts
|
|
@@ -4139,8 +4155,9 @@ var DocClient = class {
|
|
|
4139
4155
|
* Markdownファイル参照を取得
|
|
4140
4156
|
*/
|
|
4141
4157
|
mdFile(relativePath) {
|
|
4158
|
+
const normalizedPath = relativePath.endsWith(".md") ? relativePath : `${relativePath}.md`;
|
|
4142
4159
|
return new DocFileMdReference({
|
|
4143
|
-
path:
|
|
4160
|
+
path: normalizedPath,
|
|
4144
4161
|
fileSystem: this.fileSystem,
|
|
4145
4162
|
pathSystem: this.pathSystem
|
|
4146
4163
|
});
|
package/package.json
CHANGED
package/debug/debug.ts
DELETED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { DocClient } from "../lib/doc-client"
|
|
2
|
-
import { DocFileSystem } from "../lib/doc-file-system"
|
|
3
|
-
import { DocPathSystem } from "../lib/doc-path-system"
|
|
4
|
-
|
|
5
|
-
// DocClientの初期化
|
|
6
|
-
const basePath = "/Users/n/Documents/open-docs/docs" // docs ディレクトリをベースパスに
|
|
7
|
-
const pathSystem = new DocPathSystem()
|
|
8
|
-
const fileSystem = new DocFileSystem({
|
|
9
|
-
basePath,
|
|
10
|
-
pathSystem,
|
|
11
|
-
})
|
|
12
|
-
const docClient = new DocClient({
|
|
13
|
-
fileSystem,
|
|
14
|
-
pathSystem,
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
async function demonstrateRelations() {
|
|
18
|
-
console.log("=== DocClient リレーション機能のデモ ===\n")
|
|
19
|
-
|
|
20
|
-
// 1. ファイルを取得 (.mdファイルなのでmdFile()を使用)
|
|
21
|
-
const pageFile = docClient.mdFile("products/doc-browser/pages/home.md")
|
|
22
|
-
console.log("1. ファイルを取得:")
|
|
23
|
-
console.log(` パス: ${pageFile.path}`)
|
|
24
|
-
|
|
25
|
-
// 2. ファイルの内容を読み込む
|
|
26
|
-
const pageEntity = await pageFile.read()
|
|
27
|
-
if (pageEntity instanceof Error) {
|
|
28
|
-
console.error(" エラー:", pageEntity.message)
|
|
29
|
-
return
|
|
30
|
-
}
|
|
31
|
-
console.log(` タイトル: ${pageEntity.content.title}`)
|
|
32
|
-
console.log(` FrontMatter:`, pageEntity.content.frontMatter.value)
|
|
33
|
-
|
|
34
|
-
// 3. 単一のリレーションを取得(author)
|
|
35
|
-
console.log("\n2. 単一のリレーションを取得 (author):")
|
|
36
|
-
const authorRelation = await pageFile.relation("author")
|
|
37
|
-
if (authorRelation && !(authorRelation instanceof Error)) {
|
|
38
|
-
console.log(` リレーション先のパス: ${authorRelation.path}`)
|
|
39
|
-
|
|
40
|
-
// リレーション先のファイルを読み込む
|
|
41
|
-
const authorEntity = await authorRelation.read()
|
|
42
|
-
if (!(authorEntity instanceof Error)) {
|
|
43
|
-
console.log(` 著者名: ${authorEntity.content.title}`)
|
|
44
|
-
console.log(
|
|
45
|
-
` 内容の一部: ${authorEntity.content.body.substring(0, 50)}...`,
|
|
46
|
-
)
|
|
47
|
-
} else {
|
|
48
|
-
console.log(` 読み込みエラー: ${authorEntity.message}`)
|
|
49
|
-
}
|
|
50
|
-
} else if (authorRelation instanceof Error) {
|
|
51
|
-
console.log(` エラー: ${authorRelation.message}`)
|
|
52
|
-
} else {
|
|
53
|
-
console.log(" リレーションが見つかりません")
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// 4. 複数のリレーションを取得(features)
|
|
57
|
-
console.log("\n3. 複数のリレーションを取得 (features):")
|
|
58
|
-
const featureRelations = await pageFile.relations("features")
|
|
59
|
-
console.log(` 機能数: ${featureRelations.length}`)
|
|
60
|
-
|
|
61
|
-
for (const featureRef of featureRelations) {
|
|
62
|
-
console.log(` - パス: ${featureRef.path}`)
|
|
63
|
-
const featureEntity = await featureRef.read()
|
|
64
|
-
if (!(featureEntity instanceof Error)) {
|
|
65
|
-
console.log(` タイトル: ${featureEntity.content.title}`)
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// 4.5. 別の単一リレーションを取得(category)
|
|
70
|
-
console.log("\n4. 別の単一リレーションを取得 (category):")
|
|
71
|
-
const categoryRelation = await pageFile.relation("category")
|
|
72
|
-
if (categoryRelation && !(categoryRelation instanceof Error)) {
|
|
73
|
-
console.log(` リレーション先のパス: ${categoryRelation.path}`)
|
|
74
|
-
const categoryEntity = await categoryRelation.read()
|
|
75
|
-
if (!(categoryEntity instanceof Error)) {
|
|
76
|
-
console.log(` カテゴリー名: ${categoryEntity.content.title}`)
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// 5. ディレクトリのindex.mdからスキーマを確認
|
|
81
|
-
console.log("\n5. ディレクトリのindex.mdからスキーマを確認:")
|
|
82
|
-
const indexFile = await pageFile.getDirectoryIndex()
|
|
83
|
-
if (indexFile) {
|
|
84
|
-
const schema = indexFile.content.frontMatter.value.schema
|
|
85
|
-
console.log(" スキーマ定義:")
|
|
86
|
-
if (schema && typeof schema === "object") {
|
|
87
|
-
for (const [key, field] of Object.entries(schema)) {
|
|
88
|
-
if (typeof field === "object" && field !== null && "type" in field) {
|
|
89
|
-
console.log(` - ${key}: ${field.type}`)
|
|
90
|
-
if ("path" in field) {
|
|
91
|
-
console.log(` パス: ${field.path}`)
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// 6. ディレクトリ内のファイル一覧を取得
|
|
99
|
-
console.log("\n6. ディレクトリ内のファイル一覧:")
|
|
100
|
-
const pagesDir = docClient.directory("products/doc-browser/pages")
|
|
101
|
-
const files = await pagesDir.files()
|
|
102
|
-
for (const file of files) {
|
|
103
|
-
console.log(` - ${file.path}`)
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// 実行
|
|
108
|
-
demonstrateRelations().catch(console.error)
|