firebase-dataconnect-bootstrap 1.1.0 → 1.2.1
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 +71 -32
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +131 -2
- package/dist/index.d.ts +6 -0
- package/dist/index.js +4 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +458 -34
- package/dist/prompt.d.ts +2 -0
- package/dist/prompt.js +276 -34
- package/dist/search-client.d.ts +40 -0
- package/dist/search-client.js +56 -0
- package/dist/types.d.ts +56 -0
- package/package.json +16 -3
package/README.md
CHANGED
|
@@ -1,31 +1,49 @@
|
|
|
1
1
|
# firebase-dataconnect-bootstrap
|
|
2
2
|
|
|
3
|
-
Firebase Data Connect
|
|
3
|
+
Firebase Data Connect と Cloud Functions のセットアップを自動化する CLI です。
|
|
4
|
+
初期作成だけでなく、再実行で設定変更(途中更新)もできます。
|
|
4
5
|
|
|
5
6
|
## できること
|
|
6
7
|
|
|
7
|
-
-
|
|
8
|
-
- `dataconnect/`
|
|
9
|
-
- `functions/`
|
|
10
|
-
- Firestore `onDocumentWritten`
|
|
11
|
-
-
|
|
8
|
+
- `.firebaserc` と `firebase.json` の生成/更新
|
|
9
|
+
- `dataconnect/` 初期ファイル生成
|
|
10
|
+
- `functions/` 未初期化時の最小構成作成
|
|
11
|
+
- Firestore `onDocumentWritten` の生成/更新
|
|
12
|
+
- ベクトル検索用 `onRequest` 関数の生成/更新
|
|
13
|
+
- 埋め込み実装差し替え用 `vectorSearchEmbedding` テンプレート生成
|
|
14
|
+
- 前回設定を `.firebase-dataconnect-bootstrap.json` に保存し、次回実行時に再利用
|
|
12
15
|
|
|
13
16
|
## 使い方
|
|
14
17
|
|
|
15
|
-
初回セットアップ:
|
|
16
|
-
|
|
17
18
|
```bash
|
|
18
|
-
|
|
19
|
-
npm run build
|
|
19
|
+
npx firebase-dataconnect-bootstrap
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
対話モードは日本語で質問が表示されます。
|
|
23
|
+
同じリポジトリで再実行すると、保存済み設定を初期値として設定変更できます。
|
|
24
|
+
既存設定がある場合は、対話中に「新しいコレクション設定を追加するか」を選べます。
|
|
25
|
+
|
|
26
|
+
## 追加コレクションを非対話で追加する例
|
|
23
27
|
|
|
24
28
|
```bash
|
|
25
|
-
npx firebase-dataconnect-bootstrap
|
|
29
|
+
npx firebase-dataconnect-bootstrap \
|
|
30
|
+
--yes \
|
|
31
|
+
--add-collection \
|
|
32
|
+
--target . \
|
|
33
|
+
--project your-firebase-project-id \
|
|
34
|
+
--document 'articles/{articleId}' \
|
|
35
|
+
--function onArticlesWritten \
|
|
36
|
+
--vector-search \
|
|
37
|
+
--vector-collection 'articles' \
|
|
38
|
+
--source-text-field 'body' \
|
|
39
|
+
--vector-field 'embedding' \
|
|
40
|
+
--search-fields 'title,body,updatedAt' \
|
|
41
|
+
--search-function 'searchArticlesByVector' \
|
|
42
|
+
--top-k 8 \
|
|
43
|
+
--no-install
|
|
26
44
|
```
|
|
27
45
|
|
|
28
|
-
|
|
46
|
+
## 非対話モード例
|
|
29
47
|
|
|
30
48
|
```bash
|
|
31
49
|
npx firebase-dataconnect-bootstrap \
|
|
@@ -37,30 +55,51 @@ npx firebase-dataconnect-bootstrap \
|
|
|
37
55
|
--location asia-northeast1 \
|
|
38
56
|
--document 'meetingSummaries/{summaryId}' \
|
|
39
57
|
--function onMeetingSummaryWritten \
|
|
58
|
+
--vector-search \
|
|
59
|
+
--vector-collection 'meetingSummaries' \
|
|
60
|
+
--source-text-field 'summary' \
|
|
61
|
+
--vector-field 'embedding' \
|
|
62
|
+
--search-fields 'title,summary,createdAt' \
|
|
63
|
+
--search-function 'searchByVector' \
|
|
64
|
+
--top-k 5 \
|
|
40
65
|
--install
|
|
41
66
|
```
|
|
42
67
|
|
|
43
|
-
##
|
|
68
|
+
## 主なオプション
|
|
69
|
+
|
|
70
|
+
- `--config <name>`: 設定保存ファイル名(既定: `.firebase-dataconnect-bootstrap.json`)
|
|
71
|
+
- `--add-collection`: 再実行時に既存設定へ新しいコレクション設定を追加
|
|
72
|
+
- `--vector-search` / `--no-vector-search`: ベクトル検索 scaffold の有効/無効
|
|
73
|
+
- `--vector-collection <path>`: 検索対象コレクション
|
|
74
|
+
- `--source-text-field <name>`: 埋め込み更新対象のテキストフィールド
|
|
75
|
+
- `--vector-field <name>`: ベクトル保存フィールド
|
|
76
|
+
- `--search-fields <csv>`: 検索結果として返すフィールド
|
|
77
|
+
- `--search-function <name>`: 生成する `onRequest` 関数名
|
|
78
|
+
- `--top-k <number>`: 検索時のデフォルト上位件数
|
|
44
79
|
|
|
45
|
-
|
|
46
|
-
- `--project <id>`: Firebase project id
|
|
47
|
-
- `--region <region>`: Functions region
|
|
48
|
-
- `--service <serviceId>`: Data Connect service id
|
|
49
|
-
- `--location <location>`: Data Connect location
|
|
50
|
-
- `--document <path>`: Firestore document path
|
|
51
|
-
- `--function <name>`: 関数の export 名
|
|
52
|
-
- `--install`: `functions` で `npm install` を実行
|
|
53
|
-
- `--no-install`: `npm install` をスキップ
|
|
54
|
-
- `--yes`: 対話なしで実行(`--project` は必須)
|
|
80
|
+
## 生成される主な関数(コレクションごと)
|
|
55
81
|
|
|
56
|
-
|
|
82
|
+
- `onDocumentWritten_<functionName>.*`
|
|
83
|
+
- `sourceTextField` の内容を `embedText` に渡し、`vectorField` へ保存
|
|
84
|
+
- `vectorSearchOnRequest_<searchFunctionName>.*`
|
|
85
|
+
- HTTP リクエストの `vector`(または `query`)でコサイン類似度検索
|
|
86
|
+
- `vectorSearchEmbedding_<functionName>.*`
|
|
87
|
+
- `embedText` を実装する差し替えポイント(デフォルトは `null` を返す)
|
|
57
88
|
|
|
58
|
-
|
|
59
|
-
2. パッケージ名が未使用か確認
|
|
60
|
-
3. `npm run build`
|
|
61
|
-
4. `npm publish --access public`
|
|
89
|
+
## npm モジュールとして検索クライアントを使う
|
|
62
90
|
|
|
63
|
-
|
|
91
|
+
```ts
|
|
92
|
+
import { createVectorSearchClient } from "firebase-dataconnect-bootstrap/search-client";
|
|
93
|
+
|
|
94
|
+
const client = createVectorSearchClient({
|
|
95
|
+
endpoint: "https://<region>-<project>.cloudfunctions.net/searchByVector"
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const result = await client.search({
|
|
99
|
+
query: "議事録の要点",
|
|
100
|
+
topK: 5
|
|
101
|
+
});
|
|
102
|
+
```
|
|
64
103
|
|
|
65
|
-
|
|
66
|
-
|
|
104
|
+
`query` を使う場合は、Functions 側 `vectorSearchEmbedding.*` の `embedText` 実装が必要です。
|
|
105
|
+
`vector` を直接渡す場合は `embedText` が未実装でも検索できます。
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runCli(argv?: string[]): Promise<void>;
|
package/dist/cli.js
CHANGED
|
@@ -14,8 +14,18 @@ Options:
|
|
|
14
14
|
--location <location> Data Connect location (default: same as region)
|
|
15
15
|
--document <path> Firestore document path (default: meetingSummaries/{summaryId})
|
|
16
16
|
--function <name> Function export name (default: onMeetingSummaryWritten)
|
|
17
|
+
--config <name> Saved config filename (default: .firebase-dataconnect-bootstrap.json)
|
|
18
|
+
--add-collection Add a new collection setting on re-run
|
|
17
19
|
--install Run npm install in functions directory
|
|
18
20
|
--no-install Skip npm install in functions directory
|
|
21
|
+
--vector-search Enable vector search scaffolding
|
|
22
|
+
--no-vector-search Disable vector search scaffolding
|
|
23
|
+
--vector-collection <path> Collection path used for vector search
|
|
24
|
+
--source-text-field <name> Source text field for embedding updates
|
|
25
|
+
--vector-field <name> Vector field name
|
|
26
|
+
--search-fields <csv> Response fields for search results (comma-separated)
|
|
27
|
+
--search-function <name> onRequest function export name for vector search
|
|
28
|
+
--top-k <number> Default topK value for vector search
|
|
19
29
|
--yes Use defaults and skip prompts where possible
|
|
20
30
|
-h, --help Show help
|
|
21
31
|
`;
|
|
@@ -29,6 +39,9 @@ function parseArgs(argv) {
|
|
|
29
39
|
documentPath: undefined,
|
|
30
40
|
functionName: undefined,
|
|
31
41
|
installDependencies: undefined,
|
|
42
|
+
configFileName: undefined,
|
|
43
|
+
vectorSearch: {},
|
|
44
|
+
addCollection: undefined,
|
|
32
45
|
yes: false,
|
|
33
46
|
help: false
|
|
34
47
|
};
|
|
@@ -50,6 +63,18 @@ function parseArgs(argv) {
|
|
|
50
63
|
args.installDependencies = false;
|
|
51
64
|
continue;
|
|
52
65
|
}
|
|
66
|
+
if (token === "--vector-search") {
|
|
67
|
+
args.vectorSearch = { ...(args.vectorSearch ?? {}), enabled: true };
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (token === "--no-vector-search") {
|
|
71
|
+
args.vectorSearch = { ...(args.vectorSearch ?? {}), enabled: false };
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (token === "--add-collection") {
|
|
75
|
+
args.addCollection = true;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
53
78
|
if (token.startsWith("--target=")) {
|
|
54
79
|
args.targetDir = token.slice("--target=".length);
|
|
55
80
|
continue;
|
|
@@ -78,12 +103,66 @@ function parseArgs(argv) {
|
|
|
78
103
|
args.functionName = token.slice("--function=".length);
|
|
79
104
|
continue;
|
|
80
105
|
}
|
|
106
|
+
if (token.startsWith("--config=")) {
|
|
107
|
+
args.configFileName = token.slice("--config=".length);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (token.startsWith("--vector-collection=")) {
|
|
111
|
+
args.vectorSearch = {
|
|
112
|
+
...(args.vectorSearch ?? {}),
|
|
113
|
+
collectionPath: token.slice("--vector-collection=".length)
|
|
114
|
+
};
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (token.startsWith("--source-text-field=")) {
|
|
118
|
+
args.vectorSearch = {
|
|
119
|
+
...(args.vectorSearch ?? {}),
|
|
120
|
+
sourceTextField: token.slice("--source-text-field=".length)
|
|
121
|
+
};
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (token.startsWith("--vector-field=")) {
|
|
125
|
+
args.vectorSearch = {
|
|
126
|
+
...(args.vectorSearch ?? {}),
|
|
127
|
+
vectorField: token.slice("--vector-field=".length)
|
|
128
|
+
};
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (token.startsWith("--search-fields=")) {
|
|
132
|
+
args.vectorSearch = {
|
|
133
|
+
...(args.vectorSearch ?? {}),
|
|
134
|
+
returnFields: token
|
|
135
|
+
.slice("--search-fields=".length)
|
|
136
|
+
.split(",")
|
|
137
|
+
.map((field) => field.trim())
|
|
138
|
+
.filter(Boolean)
|
|
139
|
+
};
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (token.startsWith("--search-function=")) {
|
|
143
|
+
args.vectorSearch = {
|
|
144
|
+
...(args.vectorSearch ?? {}),
|
|
145
|
+
functionName: token.slice("--search-function=".length)
|
|
146
|
+
};
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (token.startsWith("--top-k=")) {
|
|
150
|
+
const parsedTopK = Number.parseInt(token.slice("--top-k=".length), 10);
|
|
151
|
+
if (Number.isNaN(parsedTopK) || parsedTopK <= 0) {
|
|
152
|
+
throw new Error("--top-k must be a positive integer");
|
|
153
|
+
}
|
|
154
|
+
args.vectorSearch = { ...(args.vectorSearch ?? {}), defaultTopK: parsedTopK };
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
81
157
|
const nextValue = argv[i + 1];
|
|
82
|
-
const
|
|
158
|
+
const requireNextValue = () => {
|
|
83
159
|
if (!nextValue || nextValue.startsWith("-")) {
|
|
84
160
|
throw new Error(`Missing value for ${token}`);
|
|
85
161
|
}
|
|
86
|
-
|
|
162
|
+
return nextValue;
|
|
163
|
+
};
|
|
164
|
+
const useNext = (field) => {
|
|
165
|
+
args[field] = requireNextValue();
|
|
87
166
|
i += 1;
|
|
88
167
|
};
|
|
89
168
|
switch (token) {
|
|
@@ -108,6 +187,56 @@ function parseArgs(argv) {
|
|
|
108
187
|
case "--function":
|
|
109
188
|
useNext("functionName");
|
|
110
189
|
break;
|
|
190
|
+
case "--config":
|
|
191
|
+
useNext("configFileName");
|
|
192
|
+
break;
|
|
193
|
+
case "--vector-collection":
|
|
194
|
+
args.vectorSearch = {
|
|
195
|
+
...(args.vectorSearch ?? {}),
|
|
196
|
+
collectionPath: requireNextValue()
|
|
197
|
+
};
|
|
198
|
+
i += 1;
|
|
199
|
+
break;
|
|
200
|
+
case "--source-text-field":
|
|
201
|
+
args.vectorSearch = {
|
|
202
|
+
...(args.vectorSearch ?? {}),
|
|
203
|
+
sourceTextField: requireNextValue()
|
|
204
|
+
};
|
|
205
|
+
i += 1;
|
|
206
|
+
break;
|
|
207
|
+
case "--vector-field":
|
|
208
|
+
args.vectorSearch = {
|
|
209
|
+
...(args.vectorSearch ?? {}),
|
|
210
|
+
vectorField: requireNextValue()
|
|
211
|
+
};
|
|
212
|
+
i += 1;
|
|
213
|
+
break;
|
|
214
|
+
case "--search-fields":
|
|
215
|
+
args.vectorSearch = {
|
|
216
|
+
...(args.vectorSearch ?? {}),
|
|
217
|
+
returnFields: requireNextValue()
|
|
218
|
+
.split(",")
|
|
219
|
+
.map((field) => field.trim())
|
|
220
|
+
.filter(Boolean)
|
|
221
|
+
};
|
|
222
|
+
i += 1;
|
|
223
|
+
break;
|
|
224
|
+
case "--search-function":
|
|
225
|
+
args.vectorSearch = {
|
|
226
|
+
...(args.vectorSearch ?? {}),
|
|
227
|
+
functionName: requireNextValue()
|
|
228
|
+
};
|
|
229
|
+
i += 1;
|
|
230
|
+
break;
|
|
231
|
+
case "--top-k": {
|
|
232
|
+
const parsedTopK = Number.parseInt(requireNextValue(), 10);
|
|
233
|
+
if (Number.isNaN(parsedTopK) || parsedTopK <= 0) {
|
|
234
|
+
throw new Error("--top-k must be a positive integer");
|
|
235
|
+
}
|
|
236
|
+
args.vectorSearch = { ...(args.vectorSearch ?? {}), defaultTopK: parsedTopK };
|
|
237
|
+
i += 1;
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
111
240
|
default:
|
|
112
241
|
throw new Error(`Unknown option: ${token}`);
|
|
113
242
|
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { run } from "./main.js";
|
|
2
|
+
export { runCli } from "./cli.js";
|
|
3
|
+
export { collectConfig } from "./prompt.js";
|
|
4
|
+
export { createVectorSearchClient, searchByVector } from "./search-client.js";
|
|
5
|
+
export type { CliArgs, PersistedBootstrapConfig, RunResult, SetupConfig, SetupTargetConfig, VectorSearchConfig } from "./types.js";
|
|
6
|
+
export type { SearchByVectorInput, VectorSearchClientOptions, VectorSearchHit, VectorSearchResponse } from "./search-client.js";
|
package/dist/index.js
ADDED
package/dist/main.d.ts
ADDED