@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 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
@@ -800,6 +800,10 @@ declare class DocSchemaValue {
800
800
  */
801
801
  private isNullOrUndefined;
802
802
  toJson(): DocSchemaRecord;
803
+ /**
804
+ * スキーマを正規化
805
+ */
806
+ private static normalizeSchema;
803
807
  }
804
808
 
805
809
  /**
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.fromSchemaEntry(name, fieldDef);
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.fromSchemaEntry(name, fieldValue);
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: relativePath,
4160
+ path: normalizedPath,
4144
4161
  fileSystem: this.fileSystem,
4145
4162
  pathSystem: this.pathSystem
4146
4163
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interactive-inc/docs-client",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "check": "tsgo --noEmit",
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)