swallowkit 1.0.0-beta.12 → 1.0.0-beta.14
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.ja.md +35 -9
- package/README.md +35 -9
- package/dist/__tests__/fixtures.d.ts +8 -0
- package/dist/__tests__/fixtures.d.ts.map +1 -1
- package/dist/__tests__/fixtures.js +60 -0
- package/dist/__tests__/fixtures.js.map +1 -1
- package/dist/cli/commands/add-auth.d.ts +10 -0
- package/dist/cli/commands/add-auth.d.ts.map +1 -0
- package/dist/cli/commands/add-auth.js +365 -0
- package/dist/cli/commands/add-auth.js.map +1 -0
- package/dist/cli/commands/add-connector.d.ts +20 -0
- package/dist/cli/commands/add-connector.d.ts.map +1 -0
- package/dist/cli/commands/add-connector.js +161 -0
- package/dist/cli/commands/add-connector.js.map +1 -0
- package/dist/cli/commands/create-model.d.ts +1 -0
- package/dist/cli/commands/create-model.d.ts.map +1 -1
- package/dist/cli/commands/create-model.js +65 -1
- package/dist/cli/commands/create-model.js.map +1 -1
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +79 -3
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/commands/scaffold.d.ts.map +1 -1
- package/dist/cli/commands/scaffold.js +240 -14
- package/dist/cli/commands/scaffold.js.map +1 -1
- package/dist/cli/index.js +25 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/config.d.ts +7 -2
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +48 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/mock/connector-mock-server.d.ts +95 -0
- package/dist/core/mock/connector-mock-server.d.ts.map +1 -0
- package/dist/core/mock/connector-mock-server.js +480 -0
- package/dist/core/mock/connector-mock-server.js.map +1 -0
- package/dist/core/mock/zod-mock-generator.d.ts +14 -0
- package/dist/core/mock/zod-mock-generator.d.ts.map +1 -0
- package/dist/core/mock/zod-mock-generator.js +163 -0
- package/dist/core/mock/zod-mock-generator.js.map +1 -0
- package/dist/core/scaffold/auth-generator.d.ts +38 -0
- package/dist/core/scaffold/auth-generator.d.ts.map +1 -0
- package/dist/core/scaffold/auth-generator.js +1246 -0
- package/dist/core/scaffold/auth-generator.js.map +1 -0
- package/dist/core/scaffold/connector-functions-generator.d.ts +41 -0
- package/dist/core/scaffold/connector-functions-generator.d.ts.map +1 -0
- package/dist/core/scaffold/connector-functions-generator.js +1028 -0
- package/dist/core/scaffold/connector-functions-generator.js.map +1 -0
- package/dist/core/scaffold/functions-generator.d.ts +2 -1
- package/dist/core/scaffold/functions-generator.d.ts.map +1 -1
- package/dist/core/scaffold/functions-generator.js +21 -12
- package/dist/core/scaffold/functions-generator.js.map +1 -1
- package/dist/core/scaffold/model-parser.d.ts +12 -0
- package/dist/core/scaffold/model-parser.d.ts.map +1 -1
- package/dist/core/scaffold/model-parser.js +139 -0
- package/dist/core/scaffold/model-parser.js.map +1 -1
- package/dist/core/scaffold/nextjs-generator.d.ts +8 -0
- package/dist/core/scaffold/nextjs-generator.d.ts.map +1 -1
- package/dist/core/scaffold/nextjs-generator.js +133 -0
- package/dist/core/scaffold/nextjs-generator.js.map +1 -1
- package/dist/core/scaffold/ui-generator.d.ts +10 -4
- package/dist/core/scaffold/ui-generator.d.ts.map +1 -1
- package/dist/core/scaffold/ui-generator.js +120 -12
- package/dist/core/scaffold/ui-generator.js.map +1 -1
- package/dist/types/index.d.ts +61 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +3 -1
- package/src/__tests__/__snapshots__/ui-generator.test.ts.snap +9 -1
- package/src/__tests__/auth.test.ts +654 -0
- package/src/__tests__/config.test.ts +141 -0
- package/src/__tests__/connector-functions-generator.test.ts +288 -0
- package/src/__tests__/connector-mock-server.test.ts +401 -0
- package/src/__tests__/connector-model-bff.test.ts +162 -0
- package/src/__tests__/fixtures.ts +60 -0
- package/src/__tests__/zod-mock-generator.test.ts +132 -0
- package/src/cli/commands/add-auth.ts +413 -0
- package/src/cli/commands/add-connector.ts +157 -0
- package/src/cli/commands/create-model.ts +72 -2
- package/src/cli/commands/dev.ts +86 -5
- package/src/cli/commands/scaffold.ts +339 -19
- package/src/cli/index.ts +27 -0
- package/src/core/config.ts +53 -1
- package/src/core/mock/connector-mock-server.ts +555 -0
- package/src/core/mock/zod-mock-generator.ts +205 -0
- package/src/core/scaffold/auth-generator.ts +1286 -0
- package/src/core/scaffold/connector-functions-generator.ts +1130 -0
- package/src/core/scaffold/functions-generator.ts +23 -12
- package/src/core/scaffold/model-parser.ts +152 -0
- package/src/core/scaffold/nextjs-generator.ts +154 -0
- package/src/core/scaffold/ui-generator.ts +132 -12
- package/src/types/index.ts +89 -0
package/README.ja.md
CHANGED
|
@@ -28,6 +28,8 @@ Zod スキーマから自動的に CRUD 操作を生成する Scaffold 機能を
|
|
|
28
28
|
- **☁️ Azure 最適化** - Static Web Apps + Functions + Cosmos DB で最小コスト構成
|
|
29
29
|
- **🚀 簡単デプロイ** - Bicep IaC + CI/CD ワークフローを自動生成
|
|
30
30
|
- **🤖 AI フレンドリー** - 自動生成される指示ファイル(`AGENTS.md`、`CLAUDE.md`、`.github/copilot-instructions.md`)とレイヤー別ルールにより、GitHub Copilot・Claude Code・OpenAI Codex がプロジェクト規約に従ってコードを生成
|
|
31
|
+
- **🔌 外部データコネクタ** - MySQL・PostgreSQL・REST API などの外部データソースを Cosmos DB と並行して統合。同じ Zod 駆動の scaffold ワークフローで完全な型安全性を維持
|
|
32
|
+
- **🔐 認証・認可** - カスタム JWT 認証(外部 RDB ユーザーストア)とモデル単位のロールベースアクセス制御を組み込みサポート。将来の Static Web Apps 認証統合も計画中
|
|
31
33
|
- **🧩 [VS Code 拡張機能](https://marketplace.visualstudio.com/items?itemName=himanago.swallowkit-vscode)** - init/scaffold/dev の GUI ウィザード、モデルファイル右クリックでスキャフォールド、開発サーバーステータスバー、TypeScript スニペット
|
|
32
34
|
|
|
33
35
|
|
|
@@ -37,6 +39,8 @@ Zod スキーマから自動的に CRUD 操作を生成する Scaffold 機能を
|
|
|
37
39
|
|
|
38
40
|
- **[CLI リファレンス](https://himanago.github.io/swallowkit/ja/cli-reference)** - 全コマンドの詳細
|
|
39
41
|
- **[Scaffold ガイド](https://himanago.github.io/swallowkit/ja/scaffold-guide)** - CRUD コード生成
|
|
42
|
+
- **[Connector ガイド](https://himanago.github.io/swallowkit/ja/connector-guide)** - 外部データソース統合
|
|
43
|
+
- **[認証ガイド](https://himanago.github.io/swallowkit/ja/auth-guide)** - 認証とロールベースアクセス制御
|
|
40
44
|
- **[Zod スキーマ共有ガイド](https://himanago.github.io/swallowkit/ja/zod-schema-sharing-guide)** - スキーマ設計
|
|
41
45
|
- **[デプロイガイド](https://himanago.github.io/swallowkit/ja/deployment-guide)** - Azure へのデプロイ
|
|
42
46
|
|
|
@@ -162,6 +166,27 @@ const updated = await api.put<Todo>('/api/todos/123', { completed: true });
|
|
|
162
166
|
await api.delete('/api/todos/123');
|
|
163
167
|
```
|
|
164
168
|
|
|
169
|
+
### 6. 外部データソースの統合(オプション)
|
|
170
|
+
|
|
171
|
+
SwallowKit は **コネクタ** により、Cosmos DB と併用して外部 RDB データベースや REST API を統合できます。同じ Zod 駆動のワークフローをそのまま使えます:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# コネクタを登録
|
|
175
|
+
npx swallowkit add-connector mysql --type rdb --provider mysql --connection-env MYSQL_CONNECTION_STRING
|
|
176
|
+
|
|
177
|
+
# コネクタ対応モデルを作成
|
|
178
|
+
npx swallowkit create-model user --connector mysql
|
|
179
|
+
# shared/models/user.ts を編集(スキーマ + connectorConfig をカスタマイズ)
|
|
180
|
+
|
|
181
|
+
# scaffold がコネクタ固有の Functions コードを生成
|
|
182
|
+
npx swallowkit scaffold shared/models/user.ts
|
|
183
|
+
|
|
184
|
+
# 実際の MySQL がなくてもモックデータでローカル開発
|
|
185
|
+
npx swallowkit dev --mock-connectors
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
フロントエンドと BFF レイヤーはデータソースの違いを意識しません — `callFunction()` は Cosmos DB モデルでもコネクタモデルでも同一です。詳しくは **[Connector ガイド](https://himanago.github.io/swallowkit/ja/connector-guide)** を参照してください。
|
|
189
|
+
|
|
165
190
|
## 🏗️ アーキテクチャ
|
|
166
191
|
|
|
167
192
|
```
|
|
@@ -184,21 +209,22 @@ await api.delete('/api/todos/123');
|
|
|
184
209
|
│ - HTTP Triggers (CRUD) │
|
|
185
210
|
│ - Zod Validation (Re-check) │
|
|
186
211
|
│ - Business Logic │
|
|
187
|
-
│ -
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
│ Azure Cosmos
|
|
193
|
-
│
|
|
194
|
-
│
|
|
195
|
-
|
|
212
|
+
│ - Data Source Bindings │
|
|
213
|
+
└──────────┬───────────────┼───────────────┬──────────────────┘
|
|
214
|
+
│ │ │
|
|
215
|
+
▼ ▼ ▼
|
|
216
|
+
┌────────────────┐ ┌──────────────┐ ┌──────────────────┐
|
|
217
|
+
│ Azure Cosmos │ │ 外部 RDB │ │ 外部 SaaS API │
|
|
218
|
+
│ DB (既定) │ │ (MySQL, │ │ (REST) │
|
|
219
|
+
│ │ │ PostgreSQL) │ │ │
|
|
220
|
+
└────────────────┘ └──────────────┘ └──────────────────┘
|
|
196
221
|
```
|
|
197
222
|
|
|
198
223
|
**重要なパターン:**
|
|
199
224
|
- **BFF (Backend For Frontend)**: Next.js API Routes が Azure Functions へのプロキシ
|
|
200
225
|
- **共有スキーマ**: `shared/models/` の Zod スキーマを唯一のソースとして扱う
|
|
201
226
|
- **C#/Python 向け OpenAPI ブリッジ**: TypeScript 以外の Functions は `functions/generated/` の生成資産を利用
|
|
227
|
+
- **外部コネクタ**: MySQL・PostgreSQL・REST API — scaffold 生成の Functions で同じ BFF パターンを維持
|
|
202
228
|
- **契約安全性**: 共有 Zod または生成モデルで BFF とバックエンドの整合を保つ
|
|
203
229
|
- **マネージド ID**: サービス間の安全な接続(接続文字列不要)
|
|
204
230
|
|
package/README.md
CHANGED
|
@@ -30,6 +30,8 @@ Featuring Scaffold functionality to automatically generate CRUD operations from
|
|
|
30
30
|
- **☁️ Azure Optimized** - Minimal-cost architecture with Static Web Apps + Functions + Cosmos DB
|
|
31
31
|
- **🚀 Easy Deployment** - Auto-generated Bicep IaC + CI/CD workflows
|
|
32
32
|
- **🤖 AI-Friendly** - Auto-generated instruction files (`AGENTS.md`, `CLAUDE.md`, `.github/copilot-instructions.md`) and layer-specific rules help GitHub Copilot, Claude Code, and OpenAI Codex follow project conventions
|
|
33
|
+
- **🔌 External Data Connectors** - Integrate MySQL, PostgreSQL, REST APIs, and other external data sources alongside Cosmos DB — same Zod-driven scaffold workflow with full type safety
|
|
34
|
+
- **🔐 Authentication & Authorization** - Built-in support for custom JWT auth (with external RDB user stores) and role-based access control per model — with planned Static Web Apps auth integration
|
|
33
35
|
- **🧩 [VS Code Extension](https://marketplace.visualstudio.com/items?itemName=himanago.swallowkit-vscode)** - GUI wizard for init/scaffold/dev, right-click model scaffolding, dev server status bar, and TypeScript snippets
|
|
34
36
|
|
|
35
37
|
## 📚 Documentation
|
|
@@ -38,6 +40,8 @@ Visit the **[SwallowKit Documentation](https://himanago.github.io/swallowkit/)**
|
|
|
38
40
|
|
|
39
41
|
- **[CLI Reference](https://himanago.github.io/swallowkit/en/cli-reference)** - All commands in detail
|
|
40
42
|
- **[Scaffold Guide](https://himanago.github.io/swallowkit/en/scaffold-guide)** - CRUD code generation
|
|
43
|
+
- **[Connector Guide](https://himanago.github.io/swallowkit/en/connector-guide)** - External data source integration
|
|
44
|
+
- **[Authentication Guide](https://himanago.github.io/swallowkit/en/auth-guide)** - Authentication and role-based access control
|
|
41
45
|
- **[Zod Schema Sharing Guide](https://himanago.github.io/swallowkit/en/zod-schema-sharing-guide)** - Schema design
|
|
42
46
|
- **[Deployment Guide](https://himanago.github.io/swallowkit/en/deployment-guide)** - Deploy to Azure
|
|
43
47
|
|
|
@@ -219,6 +223,27 @@ const updated = await api.put<Todo>('/api/todos/123', { completed: true });
|
|
|
219
223
|
await api.delete('/api/todos/123');
|
|
220
224
|
```
|
|
221
225
|
|
|
226
|
+
### 6. Connect External Data Sources (Optional)
|
|
227
|
+
|
|
228
|
+
SwallowKit supports **connectors** for integrating external RDB databases and REST APIs alongside Cosmos DB, using the same Zod-driven workflow:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# Register a connector
|
|
232
|
+
npx swallowkit add-connector mysql --type rdb --provider mysql --connection-env MYSQL_CONNECTION_STRING
|
|
233
|
+
|
|
234
|
+
# Create a connector-aware model
|
|
235
|
+
npx swallowkit create-model user --connector mysql
|
|
236
|
+
# edit shared/models/user.ts (customize schema + connectorConfig)
|
|
237
|
+
|
|
238
|
+
# Scaffold generates connector-specific Functions code
|
|
239
|
+
npx swallowkit scaffold shared/models/user.ts
|
|
240
|
+
|
|
241
|
+
# Develop locally with mock data (no real MySQL needed)
|
|
242
|
+
npx swallowkit dev --mock-connectors
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
The frontend and BFF layer are completely transparent to data source differences — `callFunction()` works identically for Cosmos DB and connector models. See the **[Connector Guide](https://himanago.github.io/swallowkit/en/connector-guide)** for details.
|
|
246
|
+
|
|
222
247
|
## 🏗️ Architecture
|
|
223
248
|
|
|
224
249
|
```
|
|
@@ -241,21 +266,22 @@ await api.delete('/api/todos/123');
|
|
|
241
266
|
│ - HTTP Triggers (CRUD) │
|
|
242
267
|
│ - Zod Validation (Re-check) │
|
|
243
268
|
│ - Business Logic │
|
|
244
|
-
│ -
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
│ Azure Cosmos
|
|
250
|
-
│
|
|
251
|
-
│
|
|
252
|
-
|
|
269
|
+
│ - Data Source Bindings │
|
|
270
|
+
└──────────┬───────────────┼───────────────┬──────────────────┘
|
|
271
|
+
│ │ │
|
|
272
|
+
▼ ▼ ▼
|
|
273
|
+
┌────────────────┐ ┌──────────────┐ ┌──────────────────┐
|
|
274
|
+
│ Azure Cosmos │ │ External │ │ External SaaS │
|
|
275
|
+
│ DB (Default) │ │ RDB (MySQL │ │ APIs (REST) │
|
|
276
|
+
│ │ │ PostgreSQL) │ │ │
|
|
277
|
+
└────────────────┘ └──────────────┘ └──────────────────┘
|
|
253
278
|
```
|
|
254
279
|
|
|
255
280
|
**Key Patterns:**
|
|
256
281
|
- **BFF (Backend For Frontend)**: Next.js API Routes proxy to Azure Functions
|
|
257
282
|
- **Shared Schemas**: Zod schemas stay in `shared/models/` as the source of truth
|
|
258
283
|
- **OpenAPI Bridge for C#/Python**: Non-TypeScript Functions consume generated assets under `functions/generated/`
|
|
284
|
+
- **External Connectors**: MySQL, PostgreSQL, REST APIs — scaffold-generated Functions with the same BFF pattern
|
|
259
285
|
- **Contract Safety**: BFF and backend stay aligned through shared Zod or generated backend models
|
|
260
286
|
- **Managed Identity**: Secure service connections (no connection strings)
|
|
261
287
|
|
|
@@ -3,6 +3,14 @@ import { ModelInfo } from "../core/scaffold/model-parser";
|
|
|
3
3
|
* テスト用の基本的な ModelInfo フィクスチャ
|
|
4
4
|
*/
|
|
5
5
|
export declare function createBasicModelInfo(overrides?: Partial<ModelInfo>): ModelInfo;
|
|
6
|
+
/**
|
|
7
|
+
* RDB コネクタ (read-only) 付きの ModelInfo フィクスチャ
|
|
8
|
+
*/
|
|
9
|
+
export declare function createRdbConnectorModelInfo(overrides?: Partial<ModelInfo>): ModelInfo;
|
|
10
|
+
/**
|
|
11
|
+
* API コネクタ (read-write) 付きの ModelInfo フィクスチャ
|
|
12
|
+
*/
|
|
13
|
+
export declare function createApiConnectorModelInfo(overrides?: Partial<ModelInfo>): ModelInfo;
|
|
6
14
|
/**
|
|
7
15
|
* 外部キーを含む ModelInfo フィクスチャ
|
|
8
16
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/__tests__/fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE1D;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAoB9E;AAED;;GAEG;AACH,wBAAgB,6BAA6B,IAAI,SAAS,CAqBzD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,SAAS,CA0BnD"}
|
|
1
|
+
{"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/__tests__/fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE1D;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAoB9E;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAuBrF;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CA2BrF;AAED;;GAEG;AACH,wBAAgB,6BAA6B,IAAI,SAAS,CAqBzD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,SAAS,CA0BnD"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createBasicModelInfo = createBasicModelInfo;
|
|
4
|
+
exports.createRdbConnectorModelInfo = createRdbConnectorModelInfo;
|
|
5
|
+
exports.createApiConnectorModelInfo = createApiConnectorModelInfo;
|
|
4
6
|
exports.createModelInfoWithForeignKey = createModelInfoWithForeignKey;
|
|
5
7
|
exports.createModelInfoWithEnum = createModelInfoWithEnum;
|
|
6
8
|
/**
|
|
@@ -27,6 +29,64 @@ function createBasicModelInfo(overrides) {
|
|
|
27
29
|
...overrides,
|
|
28
30
|
};
|
|
29
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* RDB コネクタ (read-only) 付きの ModelInfo フィクスチャ
|
|
34
|
+
*/
|
|
35
|
+
function createRdbConnectorModelInfo(overrides) {
|
|
36
|
+
return createBasicModelInfo({
|
|
37
|
+
name: "User",
|
|
38
|
+
displayName: "User",
|
|
39
|
+
schemaName: "userSchema",
|
|
40
|
+
filePath: "/models/user.ts",
|
|
41
|
+
fields: [
|
|
42
|
+
{ name: "id", type: "string", isOptional: false, isArray: false },
|
|
43
|
+
{ name: "employeeCode", type: "string", isOptional: false, isArray: false },
|
|
44
|
+
{ name: "name", type: "string", isOptional: false, isArray: false },
|
|
45
|
+
{ name: "email", type: "string", isOptional: false, isArray: false },
|
|
46
|
+
{ name: "department", type: "string", isOptional: true, isArray: false },
|
|
47
|
+
{ name: "createdAt", type: "string", isOptional: true, isArray: false },
|
|
48
|
+
{ name: "updatedAt", type: "string", isOptional: true, isArray: false },
|
|
49
|
+
],
|
|
50
|
+
connectorConfig: {
|
|
51
|
+
connector: "mysql",
|
|
52
|
+
operations: ["getAll", "getById"],
|
|
53
|
+
table: "users",
|
|
54
|
+
idColumn: "id",
|
|
55
|
+
},
|
|
56
|
+
...overrides,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* API コネクタ (read-write) 付きの ModelInfo フィクスチャ
|
|
61
|
+
*/
|
|
62
|
+
function createApiConnectorModelInfo(overrides) {
|
|
63
|
+
return createBasicModelInfo({
|
|
64
|
+
name: "BacklogIssue",
|
|
65
|
+
displayName: "BacklogIssue",
|
|
66
|
+
schemaName: "backlogIssueSchema",
|
|
67
|
+
filePath: "/models/backlog-issue.ts",
|
|
68
|
+
fields: [
|
|
69
|
+
{ name: "id", type: "string", isOptional: false, isArray: false },
|
|
70
|
+
{ name: "projectId", type: "string", isOptional: false, isArray: false },
|
|
71
|
+
{ name: "issueKey", type: "string", isOptional: false, isArray: false },
|
|
72
|
+
{ name: "summary", type: "string", isOptional: false, isArray: false },
|
|
73
|
+
{ name: "description", type: "string", isOptional: true, isArray: false },
|
|
74
|
+
{ name: "createdAt", type: "string", isOptional: true, isArray: false },
|
|
75
|
+
{ name: "updatedAt", type: "string", isOptional: true, isArray: false },
|
|
76
|
+
],
|
|
77
|
+
connectorConfig: {
|
|
78
|
+
connector: "backlog",
|
|
79
|
+
operations: ["getAll", "getById", "create", "update"],
|
|
80
|
+
endpoints: {
|
|
81
|
+
getAll: "GET /issues",
|
|
82
|
+
getById: "GET /issues/{id}",
|
|
83
|
+
create: "POST /issues",
|
|
84
|
+
update: "PATCH /issues/{id}",
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
...overrides,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
30
90
|
/**
|
|
31
91
|
* 外部キーを含む ModelInfo フィクスチャ
|
|
32
92
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../src/__tests__/fixtures.ts"],"names":[],"mappings":";;AAKA,oDAoBC;AAKD,sEAqBC;AAKD,0DA0BC;
|
|
1
|
+
{"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../src/__tests__/fixtures.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-auth.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/add-auth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAwBH,UAAU,cAAc;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,cAAc,iBAgH3D"}
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* SwallowKit Add-Auth コマンド
|
|
4
|
+
* 認証認可基盤ファイルを生成する
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.addAuthCommand = addAuthCommand;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const config_1 = require("../../core/config");
|
|
44
|
+
const auth_generator_1 = require("../../core/scaffold/auth-generator");
|
|
45
|
+
const package_manager_1 = require("../../utils/package-manager");
|
|
46
|
+
async function addAuthCommand(options) {
|
|
47
|
+
(0, config_1.ensureSwallowKitProject)("add-auth");
|
|
48
|
+
console.log(" SwallowKit Add-Auth: Setting up authentication...\n");
|
|
49
|
+
const provider = (options.provider || "custom-jwt");
|
|
50
|
+
if (!["custom-jwt", "swa", "swa-custom", "none"].includes(provider)) {
|
|
51
|
+
console.error(` Unknown provider: ${provider}. Use: custom-jwt | swa | swa-custom | none`);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
const backendLanguage = (0, config_1.getBackendLanguage)();
|
|
55
|
+
const config = (0, config_1.getFullConfig)();
|
|
56
|
+
const cwd = process.cwd();
|
|
57
|
+
// Read project name from package.json
|
|
58
|
+
const pkgPath = path.join(cwd, "package.json");
|
|
59
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
60
|
+
const projectName = pkg.name || "app";
|
|
61
|
+
// Read shared package name
|
|
62
|
+
const sharedPkgPath = path.join(cwd, "shared", "package.json");
|
|
63
|
+
let sharedPackageName = `@${projectName}/shared`;
|
|
64
|
+
if (fs.existsSync(sharedPkgPath)) {
|
|
65
|
+
const sharedPkg = JSON.parse(fs.readFileSync(sharedPkgPath, "utf-8"));
|
|
66
|
+
sharedPackageName = sharedPkg.name || sharedPackageName;
|
|
67
|
+
}
|
|
68
|
+
// Default custom-jwt config
|
|
69
|
+
const customJwtConfig = config.auth?.customJwt || {
|
|
70
|
+
userConnector: "mysql",
|
|
71
|
+
userTable: "users",
|
|
72
|
+
loginIdColumn: "login_id",
|
|
73
|
+
passwordHashColumn: "password_hash",
|
|
74
|
+
rolesColumn: "roles",
|
|
75
|
+
jwtSecretEnv: "JWT_SECRET",
|
|
76
|
+
tokenExpiry: "24h",
|
|
77
|
+
};
|
|
78
|
+
// 1. Generate shared/models/auth.ts
|
|
79
|
+
console.log(" Generating auth models...");
|
|
80
|
+
const modelsDir = path.join(cwd, "shared", "models");
|
|
81
|
+
fs.mkdirSync(modelsDir, { recursive: true });
|
|
82
|
+
const authModelPath = path.join(modelsDir, "auth.ts");
|
|
83
|
+
fs.writeFileSync(authModelPath, (0, auth_generator_1.generateAuthModels)(), "utf-8");
|
|
84
|
+
console.log(` Created: shared/models/auth.ts`);
|
|
85
|
+
// Update shared/index.ts to re-export auth
|
|
86
|
+
updateSharedIndex(cwd);
|
|
87
|
+
// Resolve RDB provider for dependency installation
|
|
88
|
+
const connDef = (0, config_1.getConnectorDefinition)(customJwtConfig.userConnector);
|
|
89
|
+
const rdbProvider = connDef?.provider ?? "mysql";
|
|
90
|
+
// 2. Generate Functions auth code
|
|
91
|
+
console.log("\n Generating auth functions...");
|
|
92
|
+
generateFunctionsAuth(cwd, backendLanguage, sharedPackageName, customJwtConfig);
|
|
93
|
+
// 3. Generate BFF auth routes
|
|
94
|
+
console.log("\n Generating BFF auth routes...");
|
|
95
|
+
generateBFFAuth(cwd, projectName, sharedPackageName);
|
|
96
|
+
// 4. Generate middleware
|
|
97
|
+
console.log("\n Generating middleware...");
|
|
98
|
+
const middlewarePath = path.join(cwd, "middleware.ts");
|
|
99
|
+
fs.writeFileSync(middlewarePath, (0, auth_generator_1.generateMiddleware)(projectName), "utf-8");
|
|
100
|
+
console.log(` Created: middleware.ts`);
|
|
101
|
+
// 5. Generate login page
|
|
102
|
+
console.log("\n Generating login page...");
|
|
103
|
+
const loginDir = path.join(cwd, "app", "login");
|
|
104
|
+
fs.mkdirSync(loginDir, { recursive: true });
|
|
105
|
+
fs.writeFileSync(path.join(loginDir, "page.tsx"), (0, auth_generator_1.generateLoginPage)(), "utf-8");
|
|
106
|
+
console.log(` Created: app/login/page.tsx`);
|
|
107
|
+
// 6. Generate auth context
|
|
108
|
+
console.log("\n Generating auth context...");
|
|
109
|
+
const authLibDir = path.join(cwd, "lib", "auth");
|
|
110
|
+
fs.mkdirSync(authLibDir, { recursive: true });
|
|
111
|
+
fs.writeFileSync(path.join(authLibDir, "auth-context.tsx"), (0, auth_generator_1.generateAuthContext)(), "utf-8");
|
|
112
|
+
console.log(`✅ Created: lib/auth/auth-context.tsx`);
|
|
113
|
+
// 7. Update callFunction with auth support
|
|
114
|
+
console.log("\n Updating callFunction with auth support...");
|
|
115
|
+
const callFnPath = path.join(cwd, "lib", "api", "call-function.ts");
|
|
116
|
+
const callFnDir = path.dirname(callFnPath);
|
|
117
|
+
fs.mkdirSync(callFnDir, { recursive: true });
|
|
118
|
+
fs.writeFileSync(callFnPath, (0, auth_generator_1.generateBFFCallFunctionWithAuth)(), "utf-8");
|
|
119
|
+
console.log(` Updated: lib/api/call-function.ts`);
|
|
120
|
+
// 8. Update swallowkit.config.js
|
|
121
|
+
console.log("\n Updating configuration...");
|
|
122
|
+
updateConfigWithAuth(cwd, provider, customJwtConfig);
|
|
123
|
+
// 9. Update environment files
|
|
124
|
+
console.log("\n Updating environment files...");
|
|
125
|
+
updateEnvironmentFiles(cwd);
|
|
126
|
+
// 10. Install dependencies
|
|
127
|
+
console.log("\n Installing auth dependencies...");
|
|
128
|
+
await installAuthDependencies(cwd, backendLanguage, rdbProvider);
|
|
129
|
+
console.log("\n Authentication setup complete!");
|
|
130
|
+
console.log("\n Next steps:");
|
|
131
|
+
console.log(" 1. Review the generated files");
|
|
132
|
+
console.log(" 2. Set JWT_SECRET in functions/local.settings.json");
|
|
133
|
+
if (provider === "custom-jwt") {
|
|
134
|
+
console.log(" 3. Ensure your user database table matches the config");
|
|
135
|
+
console.log(" 4. Add authPolicy to your models for role-based access control:");
|
|
136
|
+
console.log(" export const authPolicy = { roles: ['admin'] };");
|
|
137
|
+
}
|
|
138
|
+
console.log(` 5. Run scaffold to regenerate functions with auth guards`);
|
|
139
|
+
}
|
|
140
|
+
function updateSharedIndex(cwd) {
|
|
141
|
+
const indexPath = path.join(cwd, "shared", "index.ts");
|
|
142
|
+
if (fs.existsSync(indexPath)) {
|
|
143
|
+
let content = fs.readFileSync(indexPath, "utf-8");
|
|
144
|
+
if (!content.includes("./models/auth")) {
|
|
145
|
+
content += `\nexport { LoginRequest, AuthUser, LoginResponse } from './models/auth';\n`;
|
|
146
|
+
fs.writeFileSync(indexPath, content, "utf-8");
|
|
147
|
+
console.log(` Updated: shared/index.ts`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
fs.writeFileSync(indexPath, `export { LoginRequest, AuthUser, LoginResponse } from './models/auth';\n`, "utf-8");
|
|
152
|
+
console.log(` Created: shared/index.ts`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function generateFunctionsAuth(cwd, backendLanguage, sharedPackageName, config) {
|
|
156
|
+
const functionsDir = path.join(cwd, "functions");
|
|
157
|
+
// Resolve the RDB provider from the connector definition
|
|
158
|
+
const connDef = (0, config_1.getConnectorDefinition)(config.userConnector);
|
|
159
|
+
const provider = connDef?.provider ?? "mysql";
|
|
160
|
+
if (backendLanguage === "typescript") {
|
|
161
|
+
// Auth functions
|
|
162
|
+
const srcDir = path.join(functionsDir, "src");
|
|
163
|
+
fs.mkdirSync(srcDir, { recursive: true });
|
|
164
|
+
fs.writeFileSync(path.join(srcDir, "auth.ts"), (0, auth_generator_1.generateAuthFunctionsTS)(sharedPackageName, config, provider), "utf-8");
|
|
165
|
+
console.log(` Created: functions/src/auth.ts`);
|
|
166
|
+
// JWT helper
|
|
167
|
+
const authDir = path.join(srcDir, "auth");
|
|
168
|
+
fs.mkdirSync(authDir, { recursive: true });
|
|
169
|
+
fs.writeFileSync(path.join(authDir, "jwt-helper.ts"), (0, auth_generator_1.generateJwtHelperTS)(), "utf-8");
|
|
170
|
+
console.log(` Created: functions/src/auth/jwt-helper.ts`);
|
|
171
|
+
}
|
|
172
|
+
else if (backendLanguage === "csharp") {
|
|
173
|
+
const authDir = path.join(functionsDir, "Auth");
|
|
174
|
+
fs.mkdirSync(authDir, { recursive: true });
|
|
175
|
+
fs.writeFileSync(path.join(authDir, "AuthFunctions.cs"), (0, auth_generator_1.generateAuthFunctionsCSharp)(config, provider), "utf-8");
|
|
176
|
+
console.log(` Created: functions/Auth/AuthFunctions.cs`);
|
|
177
|
+
fs.writeFileSync(path.join(authDir, "JwtHelper.cs"), (0, auth_generator_1.generateJwtHelperCSharp)(), "utf-8");
|
|
178
|
+
console.log(` Created: functions/Auth/JwtHelper.cs`);
|
|
179
|
+
}
|
|
180
|
+
else if (backendLanguage === "python") {
|
|
181
|
+
const blueprintsDir = path.join(functionsDir, "blueprints");
|
|
182
|
+
fs.mkdirSync(blueprintsDir, { recursive: true });
|
|
183
|
+
fs.writeFileSync(path.join(blueprintsDir, "auth.py"), (0, auth_generator_1.generateAuthFunctionsPython)(config, provider), "utf-8");
|
|
184
|
+
console.log(` Created: functions/blueprints/auth.py`);
|
|
185
|
+
const authDir = path.join(functionsDir, "auth");
|
|
186
|
+
fs.mkdirSync(authDir, { recursive: true });
|
|
187
|
+
fs.writeFileSync(path.join(authDir, "jwt_helper.py"), (0, auth_generator_1.generateJwtHelperPython)(), "utf-8");
|
|
188
|
+
console.log(` Created: functions/auth/jwt_helper.py`);
|
|
189
|
+
// __init__.py
|
|
190
|
+
fs.writeFileSync(path.join(authDir, "__init__.py"), "", "utf-8");
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function generateBFFAuth(cwd, projectName, sharedPackageName) {
|
|
194
|
+
const authApiDir = path.join(cwd, "app", "api", "auth");
|
|
195
|
+
// Login route
|
|
196
|
+
const loginDir = path.join(authApiDir, "login");
|
|
197
|
+
fs.mkdirSync(loginDir, { recursive: true });
|
|
198
|
+
fs.writeFileSync(path.join(loginDir, "route.ts"), (0, auth_generator_1.generateBFFAuthLoginRoute)(projectName, sharedPackageName), "utf-8");
|
|
199
|
+
console.log(` Created: app/api/auth/login/route.ts`);
|
|
200
|
+
// Logout route
|
|
201
|
+
const logoutDir = path.join(authApiDir, "logout");
|
|
202
|
+
fs.mkdirSync(logoutDir, { recursive: true });
|
|
203
|
+
fs.writeFileSync(path.join(logoutDir, "route.ts"), (0, auth_generator_1.generateBFFAuthLogoutRoute)(projectName), "utf-8");
|
|
204
|
+
console.log(` Created: app/api/auth/logout/route.ts`);
|
|
205
|
+
// Me route
|
|
206
|
+
const meDir = path.join(authApiDir, "me");
|
|
207
|
+
fs.mkdirSync(meDir, { recursive: true });
|
|
208
|
+
fs.writeFileSync(path.join(meDir, "route.ts"), (0, auth_generator_1.generateBFFAuthMeRoute)(sharedPackageName), "utf-8");
|
|
209
|
+
console.log(` Created: app/api/auth/me/route.ts`);
|
|
210
|
+
}
|
|
211
|
+
function updateConfigWithAuth(cwd, provider, config) {
|
|
212
|
+
const configPath = path.join(cwd, "swallowkit.config.js");
|
|
213
|
+
if (!fs.existsSync(configPath)) {
|
|
214
|
+
console.warn(" swallowkit.config.js not found. Please add auth config manually.");
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
218
|
+
if (content.includes("auth:") || content.includes("auth :")) {
|
|
219
|
+
console.log(" 'auth' section already exists in swallowkit.config.js");
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
// Find the last property before the closing of module.exports
|
|
223
|
+
const closingBraceIdx = content.lastIndexOf("}");
|
|
224
|
+
if (closingBraceIdx === -1) {
|
|
225
|
+
console.error(" Could not parse config file structure.");
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const beforeClosing = content.substring(0, closingBraceIdx).trimEnd();
|
|
229
|
+
const needsComma = !beforeClosing.endsWith(",") && !beforeClosing.endsWith("{");
|
|
230
|
+
const authBlock = `${needsComma ? "," : ""}
|
|
231
|
+
// 認証認可設定
|
|
232
|
+
auth: {
|
|
233
|
+
provider: '${provider}',
|
|
234
|
+
customJwt: {
|
|
235
|
+
userConnector: '${config.userConnector}',
|
|
236
|
+
userTable: '${config.userTable}',
|
|
237
|
+
loginIdColumn: '${config.loginIdColumn}',
|
|
238
|
+
passwordHashColumn: '${config.passwordHashColumn}',
|
|
239
|
+
rolesColumn: '${config.rolesColumn}',
|
|
240
|
+
jwtSecretEnv: '${config.jwtSecretEnv || "JWT_SECRET"}',
|
|
241
|
+
tokenExpiry: '${config.tokenExpiry || "24h"}',
|
|
242
|
+
},
|
|
243
|
+
authorization: {
|
|
244
|
+
defaultPolicy: 'authenticated',
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
`;
|
|
248
|
+
const newContent = content.substring(0, closingBraceIdx) + authBlock + content.substring(closingBraceIdx);
|
|
249
|
+
fs.writeFileSync(configPath, newContent, "utf-8");
|
|
250
|
+
console.log(` Updated: swallowkit.config.js`);
|
|
251
|
+
}
|
|
252
|
+
function updateEnvironmentFiles(cwd) {
|
|
253
|
+
// Update functions/local.settings.json
|
|
254
|
+
const localSettingsPath = path.join(cwd, "functions", "local.settings.json");
|
|
255
|
+
if (fs.existsSync(localSettingsPath)) {
|
|
256
|
+
const settings = JSON.parse(fs.readFileSync(localSettingsPath, "utf-8"));
|
|
257
|
+
if (!settings.Values)
|
|
258
|
+
settings.Values = {};
|
|
259
|
+
if (!settings.Values.JWT_SECRET) {
|
|
260
|
+
settings.Values.JWT_SECRET = "dev-jwt-secret-change-in-production-min-32-chars!!";
|
|
261
|
+
}
|
|
262
|
+
fs.writeFileSync(localSettingsPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
263
|
+
console.log(` Updated: functions/local.settings.json`);
|
|
264
|
+
}
|
|
265
|
+
// Update .env.example
|
|
266
|
+
const envExamplePath = path.join(cwd, ".env.example");
|
|
267
|
+
if (fs.existsSync(envExamplePath)) {
|
|
268
|
+
let content = fs.readFileSync(envExamplePath, "utf-8");
|
|
269
|
+
if (!content.includes("JWT_SECRET")) {
|
|
270
|
+
content += "\n# Authentication\nJWT_SECRET=your-jwt-secret-key-at-least-32-chars\n";
|
|
271
|
+
fs.writeFileSync(envExamplePath, content, "utf-8");
|
|
272
|
+
console.log(` Updated: .env.example`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
async function installAuthDependencies(cwd, backendLanguage, provider = "mysql") {
|
|
277
|
+
const pm = (0, package_manager_1.detectFromProject)();
|
|
278
|
+
const cmds = (0, package_manager_1.getCommands)(pm);
|
|
279
|
+
if (backendLanguage === "typescript") {
|
|
280
|
+
const funcPkgPath = path.join(cwd, "functions", "package.json");
|
|
281
|
+
if (fs.existsSync(funcPkgPath)) {
|
|
282
|
+
const funcPkg = JSON.parse(fs.readFileSync(funcPkgPath, "utf-8"));
|
|
283
|
+
if (!funcPkg.dependencies)
|
|
284
|
+
funcPkg.dependencies = {};
|
|
285
|
+
funcPkg.dependencies["jsonwebtoken"] = "^9.0.0";
|
|
286
|
+
funcPkg.dependencies["bcryptjs"] = "^2.4.3";
|
|
287
|
+
// RDB driver based on provider
|
|
288
|
+
if (provider === "mysql")
|
|
289
|
+
funcPkg.dependencies["mysql2"] = "^3.11.0";
|
|
290
|
+
else if (provider === "postgres")
|
|
291
|
+
funcPkg.dependencies["pg"] = "^8.13.0";
|
|
292
|
+
else
|
|
293
|
+
funcPkg.dependencies["mssql"] = "^11.0.0";
|
|
294
|
+
if (!funcPkg.devDependencies)
|
|
295
|
+
funcPkg.devDependencies = {};
|
|
296
|
+
funcPkg.devDependencies["@types/jsonwebtoken"] = "^9.0.0";
|
|
297
|
+
funcPkg.devDependencies["@types/bcryptjs"] = "^2.4.0";
|
|
298
|
+
if (provider === "postgres")
|
|
299
|
+
funcPkg.devDependencies["@types/pg"] = "^8.11.0";
|
|
300
|
+
fs.writeFileSync(funcPkgPath, JSON.stringify(funcPkg, null, 2), "utf-8");
|
|
301
|
+
console.log(` Updated: functions/package.json with auth dependencies (${provider})`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
else if (backendLanguage === "csharp") {
|
|
305
|
+
// Add NuGet package references to .csproj
|
|
306
|
+
const functionsDir = path.join(cwd, "functions");
|
|
307
|
+
const csprojFiles = fs.readdirSync(functionsDir).filter((f) => f.endsWith(".csproj"));
|
|
308
|
+
if (csprojFiles.length > 0) {
|
|
309
|
+
const csprojPath = path.join(functionsDir, csprojFiles[0]);
|
|
310
|
+
let csprojContent = fs.readFileSync(csprojPath, "utf-8");
|
|
311
|
+
const nugetPackages = [
|
|
312
|
+
{ name: "System.IdentityModel.Tokens.Jwt", version: "7.0.0" },
|
|
313
|
+
{ name: "Microsoft.IdentityModel.Tokens", version: "7.0.0" },
|
|
314
|
+
{ name: "BCrypt.Net-Next", version: "4.0.3" },
|
|
315
|
+
];
|
|
316
|
+
// RDB driver based on provider
|
|
317
|
+
if (provider === "mysql")
|
|
318
|
+
nugetPackages.push({ name: "MySqlConnector", version: "2.3.0" });
|
|
319
|
+
else if (provider === "postgres")
|
|
320
|
+
nugetPackages.push({ name: "Npgsql", version: "8.0.0" });
|
|
321
|
+
else
|
|
322
|
+
nugetPackages.push({ name: "Microsoft.Data.SqlClient", version: "5.2.0" });
|
|
323
|
+
for (const pkg of nugetPackages) {
|
|
324
|
+
if (!csprojContent.includes(`"${pkg.name}"`)) {
|
|
325
|
+
const insertPoint = csprojContent.lastIndexOf("</ItemGroup>");
|
|
326
|
+
if (insertPoint >= 0) {
|
|
327
|
+
csprojContent =
|
|
328
|
+
csprojContent.slice(0, insertPoint) +
|
|
329
|
+
` <PackageReference Include="${pkg.name}" Version="${pkg.version}" />\n ` +
|
|
330
|
+
csprojContent.slice(insertPoint);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
fs.writeFileSync(csprojPath, csprojContent, "utf-8");
|
|
335
|
+
console.log(` Updated: ${csprojFiles[0]} with auth NuGet packages (${provider})`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
else if (backendLanguage === "python") {
|
|
339
|
+
// Add Python dependencies to requirements.txt
|
|
340
|
+
const requirementsPath = path.join(cwd, "functions", "requirements.txt");
|
|
341
|
+
const baseDeps = ["PyJWT>=2.8.0", "bcrypt>=4.1.0"];
|
|
342
|
+
// RDB driver based on provider
|
|
343
|
+
if (provider === "mysql")
|
|
344
|
+
baseDeps.push("mysql-connector-python>=8.3.0");
|
|
345
|
+
else if (provider === "postgres")
|
|
346
|
+
baseDeps.push("psycopg2-binary>=2.9.0");
|
|
347
|
+
else
|
|
348
|
+
baseDeps.push("pymssql>=2.2.0");
|
|
349
|
+
if (fs.existsSync(requirementsPath)) {
|
|
350
|
+
let content = fs.readFileSync(requirementsPath, "utf-8");
|
|
351
|
+
for (const dep of baseDeps) {
|
|
352
|
+
const pkgName = dep.split(">=")[0].split("==")[0];
|
|
353
|
+
if (!content.includes(pkgName)) {
|
|
354
|
+
content += `${dep}\n`;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
fs.writeFileSync(requirementsPath, content, "utf-8");
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
fs.writeFileSync(requirementsPath, baseDeps.join("\n") + "\n", "utf-8");
|
|
361
|
+
}
|
|
362
|
+
console.log(` Updated: functions/requirements.txt with auth dependencies`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
//# sourceMappingURL=add-auth.js.map
|