swallowkit 1.0.0-beta.3 → 1.0.0-beta.30
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/LICENSE +21 -21
- package/README.ja.md +321 -215
- package/README.md +388 -216
- package/dist/__tests__/fixtures.d.ts +22 -0
- package/dist/__tests__/fixtures.d.ts.map +1 -0
- package/dist/__tests__/fixtures.js +146 -0
- package/dist/__tests__/fixtures.js.map +1 -0
- 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 +444 -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 +163 -0
- package/dist/cli/commands/add-connector.js.map +1 -0
- package/dist/cli/commands/create-model.d.ts +1 -4
- package/dist/cli/commands/create-model.d.ts.map +1 -1
- package/dist/cli/commands/create-model.js +21 -82
- package/dist/cli/commands/create-model.js.map +1 -1
- package/dist/cli/commands/dev-seeds.d.ts +57 -0
- package/dist/cli/commands/dev-seeds.d.ts.map +1 -0
- package/dist/cli/commands/dev-seeds.js +470 -0
- package/dist/cli/commands/dev-seeds.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +33 -0
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +628 -146
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +3 -1
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +15 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +2693 -1706
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/scaffold.d.ts.map +1 -1
- package/dist/cli/commands/scaffold.js +448 -129
- package/dist/cli/commands/scaffold.js.map +1 -1
- package/dist/cli/index.d.ts +5 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +200 -42
- package/dist/cli/index.js.map +1 -1
- package/dist/core/config.d.ts +8 -2
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +94 -5
- package/dist/core/config.js.map +1 -1
- package/dist/core/mock/connector-mock-server.d.ts +101 -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/operations/create-model.d.ts +15 -0
- package/dist/core/operations/create-model.d.ts.map +1 -0
- package/dist/core/operations/create-model.js +171 -0
- package/dist/core/operations/create-model.js.map +1 -0
- package/dist/core/operations/runtime.d.ts +32 -0
- package/dist/core/operations/runtime.d.ts.map +1 -0
- package/dist/core/operations/runtime.js +225 -0
- package/dist/core/operations/runtime.js.map +1 -0
- package/dist/core/operations/scaffold-machine.d.ts +16 -0
- package/dist/core/operations/scaffold-machine.d.ts.map +1 -0
- package/dist/core/operations/scaffold-machine.js +63 -0
- package/dist/core/operations/scaffold-machine.js.map +1 -0
- package/dist/core/project/manifest.d.ts +92 -0
- package/dist/core/project/manifest.d.ts.map +1 -0
- package/dist/core/project/manifest.js +321 -0
- package/dist/core/project/manifest.js.map +1 -0
- package/dist/core/project/validation.d.ts +20 -0
- package/dist/core/project/validation.d.ts.map +1 -0
- package/dist/core/project/validation.js +209 -0
- package/dist/core/project/validation.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 +1244 -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 +1027 -0
- package/dist/core/scaffold/connector-functions-generator.js.map +1 -0
- package/dist/core/scaffold/functions-generator.d.ts +7 -1
- package/dist/core/scaffold/functions-generator.d.ts.map +1 -1
- package/dist/core/scaffold/functions-generator.js +920 -213
- package/dist/core/scaffold/functions-generator.js.map +1 -1
- package/dist/core/scaffold/model-parser.d.ts +20 -1
- package/dist/core/scaffold/model-parser.d.ts.map +1 -1
- package/dist/core/scaffold/model-parser.js +328 -135
- package/dist/core/scaffold/model-parser.js.map +1 -1
- package/dist/core/scaffold/native-schema-generator.d.ts +13 -0
- package/dist/core/scaffold/native-schema-generator.d.ts.map +1 -0
- package/dist/core/scaffold/native-schema-generator.js +677 -0
- package/dist/core/scaffold/native-schema-generator.js.map +1 -0
- 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 +314 -182
- package/dist/core/scaffold/nextjs-generator.js.map +1 -1
- package/dist/core/scaffold/openapi-generator.d.ts +3 -0
- package/dist/core/scaffold/openapi-generator.d.ts.map +1 -0
- package/dist/core/scaffold/openapi-generator.js +190 -0
- package/dist/core/scaffold/openapi-generator.js.map +1 -0
- 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 +768 -663
- package/dist/core/scaffold/ui-generator.js.map +1 -1
- package/dist/database/base-model.d.ts +3 -3
- package/dist/database/base-model.js +3 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/machine/contracts.d.ts +16 -0
- package/dist/machine/contracts.d.ts.map +1 -0
- package/dist/machine/contracts.js +3 -0
- package/dist/machine/contracts.js.map +1 -0
- package/dist/machine/errors.d.ts +11 -0
- package/dist/machine/errors.d.ts.map +1 -0
- package/dist/machine/errors.js +34 -0
- package/dist/machine/errors.js.map +1 -0
- package/dist/machine/index.d.ts +3 -0
- package/dist/machine/index.d.ts.map +1 -0
- package/dist/machine/index.js +156 -0
- package/dist/machine/index.js.map +1 -0
- package/dist/mcp/index.d.ts +25 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +184 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/types/index.d.ts +65 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/package-manager.d.ts +109 -0
- package/dist/utils/package-manager.d.ts.map +1 -0
- package/dist/utils/package-manager.js +215 -0
- package/dist/utils/package-manager.js.map +1 -0
- package/dist/utils/python-uv.d.ts +21 -0
- package/dist/utils/python-uv.d.ts.map +1 -0
- package/dist/utils/python-uv.js +111 -0
- package/dist/utils/python-uv.js.map +1 -0
- package/package.json +85 -73
- package/src/__tests__/__snapshots__/functions-generator.test.ts.snap +1139 -0
- package/src/__tests__/__snapshots__/nextjs-generator.test.ts.snap +194 -0
- package/src/__tests__/__snapshots__/ui-generator.test.ts.snap +532 -0
- package/src/__tests__/auth.test.ts +654 -0
- package/src/__tests__/config.test.ts +274 -0
- package/src/__tests__/connector-functions-generator.test.ts +288 -0
- package/src/__tests__/connector-mock-server.test.ts +439 -0
- package/src/__tests__/connector-model-bff.test.ts +162 -0
- package/src/__tests__/dev-seeds.test.ts +173 -0
- package/src/__tests__/dev.test.ts +252 -0
- package/src/__tests__/fixtures.ts +144 -0
- package/src/__tests__/functions-generator.test.ts +237 -0
- package/src/__tests__/init.test.ts +109 -0
- package/src/__tests__/machine.test.ts +251 -0
- package/src/__tests__/mcp.test.ts +117 -0
- package/src/__tests__/model-parser.test.ts +52 -0
- package/src/__tests__/nextjs-generator.test.ts +97 -0
- package/src/__tests__/openapi-generator.test.ts +43 -0
- package/src/__tests__/package-manager.test.ts +189 -0
- package/src/__tests__/python-uv.test.ts +48 -0
- package/src/__tests__/scaffold.test.ts +67 -0
- package/src/__tests__/string-utils.test.ts +75 -0
- package/src/__tests__/ui-generator.test.ts +144 -0
- package/src/__tests__/zod-mock-generator.test.ts +132 -0
- package/src/cli/commands/add-auth.ts +500 -0
- package/src/cli/commands/add-connector.ts +158 -0
- package/src/cli/commands/create-model.ts +62 -0
- package/src/cli/commands/dev-seeds.ts +614 -0
- package/src/cli/commands/dev.ts +1134 -0
- package/src/cli/commands/index.ts +9 -0
- package/src/cli/commands/init.ts +3477 -0
- package/src/cli/commands/provision.ts +193 -0
- package/src/cli/commands/scaffold.ts +1001 -0
- package/src/cli/index.ts +196 -0
- package/src/core/config.ts +312 -0
- package/src/core/mock/connector-mock-server.ts +555 -0
- package/src/core/mock/zod-mock-generator.ts +205 -0
- package/src/core/operations/create-model.ts +174 -0
- package/src/core/operations/runtime.ts +235 -0
- package/src/core/operations/scaffold-machine.ts +91 -0
- package/src/core/project/manifest.ts +402 -0
- package/src/core/project/validation.ts +229 -0
- package/src/core/scaffold/auth-generator.ts +1284 -0
- package/src/core/scaffold/connector-functions-generator.ts +1128 -0
- package/src/core/scaffold/functions-generator.ts +970 -0
- package/src/core/scaffold/model-parser.ts +841 -0
- package/src/core/scaffold/native-schema-generator.ts +798 -0
- package/src/core/scaffold/nextjs-generator.ts +370 -0
- package/src/core/scaffold/openapi-generator.ts +212 -0
- package/src/core/scaffold/ui-generator.ts +1061 -0
- package/src/database/base-model.ts +184 -0
- package/src/database/client.ts +140 -0
- package/src/database/repository.ts +104 -0
- package/src/database/runtime-check.ts +25 -0
- package/src/index.ts +27 -0
- package/src/machine/contracts.ts +17 -0
- package/src/machine/errors.ts +34 -0
- package/src/machine/index.ts +173 -0
- package/src/mcp/index.ts +185 -0
- package/src/types/index.ts +134 -0
- package/src/utils/package-manager.ts +229 -0
- package/src/utils/python-uv.ts +96 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"functions-generator.js","sourceRoot":"","sources":["../../../src/core/scaffold/functions-generator.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;
|
|
1
|
+
{"version":3,"file":"functions-generator.js","sourceRoot":"","sources":["../../../src/core/scaffold/functions-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Zod モデルファイルを解析して、スキーマ情報を抽出する
|
|
3
3
|
*/
|
|
4
|
+
import { ModelConnectorConfig, ModelAuthPolicy } from "../../types";
|
|
4
5
|
export interface ModelInfo {
|
|
5
6
|
name: string;
|
|
6
7
|
displayName: string;
|
|
@@ -11,6 +12,9 @@ export interface ModelInfo {
|
|
|
11
12
|
hasCreatedAt: boolean;
|
|
12
13
|
hasUpdatedAt: boolean;
|
|
13
14
|
nestedSchemaRefs: NestedSchemaRef[];
|
|
15
|
+
connectorConfig?: ModelConnectorConfig;
|
|
16
|
+
authPolicy?: ModelAuthPolicy;
|
|
17
|
+
partitionKey: string;
|
|
14
18
|
}
|
|
15
19
|
export interface FieldInfo {
|
|
16
20
|
name: string;
|
|
@@ -49,13 +53,28 @@ export declare function toPascalCase(str: string): string;
|
|
|
49
53
|
* 文字列を camelCase に変換
|
|
50
54
|
*/
|
|
51
55
|
export declare function toCamelCase(str: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* モデルファイルから connectorConfig エクスポートを静的解析で抽出する
|
|
58
|
+
*/
|
|
59
|
+
export declare function parseConnectorConfig(content: string): ModelConnectorConfig | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* authPolicy をモデルファイルから抽出
|
|
62
|
+
* パターン: export const authPolicy = { roles: [...], read: [...], write: [...] }
|
|
63
|
+
*/
|
|
64
|
+
export declare function parseAuthPolicy(content: string): ModelAuthPolicy | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* パーティションキーを抽出する
|
|
67
|
+
* export const partitionKey = '/tenantId' のようなエクスポートを検出
|
|
68
|
+
* 未指定の場合はデフォルト '/id' を返す
|
|
69
|
+
*/
|
|
70
|
+
export declare function parsePartitionKey(content: string): string;
|
|
52
71
|
/**
|
|
53
72
|
* 文字列を kebab-case に変換
|
|
54
73
|
*/
|
|
55
74
|
export declare function toKebabCase(str: string): string;
|
|
56
75
|
/**
|
|
57
76
|
* models ディレクトリから全てのモデル情報を取得
|
|
58
|
-
* @param modelsDir モデルディレクトリのパス(デフォルト: "
|
|
77
|
+
* @param modelsDir モデルディレクトリのパス(デフォルト: "shared/models")
|
|
59
78
|
* @returns モデル情報の配列
|
|
60
79
|
*/
|
|
61
80
|
export declare function getAllModels(modelsDir?: string): Promise<ModelInfo[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-parser.d.ts","sourceRoot":"","sources":["../../../src/core/scaffold/model-parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,EAAE,eAAe,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"model-parser.d.ts","sourceRoot":"","sources":["../../../src/core/scaffold/model-parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEpE,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,eAAe,CAAC,EAAE,oBAAoB,CAAC;IACvC,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAgF1E;AAmfD;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKhD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG/C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CA2FtF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAsC5E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI/C;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,SAAS,GAAE,MAAwB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAwB5F"}
|
|
@@ -39,9 +39,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
39
39
|
exports.parseModelFile = parseModelFile;
|
|
40
40
|
exports.toPascalCase = toPascalCase;
|
|
41
41
|
exports.toCamelCase = toCamelCase;
|
|
42
|
+
exports.parseConnectorConfig = parseConnectorConfig;
|
|
43
|
+
exports.parseAuthPolicy = parseAuthPolicy;
|
|
44
|
+
exports.parsePartitionKey = parsePartitionKey;
|
|
42
45
|
exports.toKebabCase = toKebabCase;
|
|
43
46
|
exports.getAllModels = getAllModels;
|
|
44
47
|
const fs = __importStar(require("fs"));
|
|
48
|
+
const child_process_1 = require("child_process");
|
|
45
49
|
const path = __importStar(require("path"));
|
|
46
50
|
/**
|
|
47
51
|
* モデルファイルを解析して ModelInfo を返す
|
|
@@ -55,11 +59,15 @@ async function parseModelFile(modelPath) {
|
|
|
55
59
|
// モデル名を推定(ファイル名を PascalCase に変換)
|
|
56
60
|
const modelName = toPascalCase(fileName);
|
|
57
61
|
// スキーマ変数名を抽出
|
|
62
|
+
// コメント内のコードパターンを誤認識しないよう、先にコメントを除去してから正規表現を適用する
|
|
58
63
|
// パターン1: export const todoSchema = z.object({ ... }) (camelCase + Schema接尾辞)
|
|
59
64
|
// パターン2: export const Todo = z.object({ ... }) (Zod公式パターン)
|
|
60
|
-
|
|
65
|
+
const contentWithoutComments = content
|
|
66
|
+
.replace(/\/\*[\s\S]*?\*\//g, '') // ブロックコメントを除去
|
|
67
|
+
.replace(/\/\/.*/g, ''); // 行コメントを除去
|
|
68
|
+
let schemaMatch = contentWithoutComments.match(/export\s+const\s+(\w+Schema)\s*=/);
|
|
61
69
|
if (!schemaMatch) {
|
|
62
|
-
schemaMatch =
|
|
70
|
+
schemaMatch = contentWithoutComments.match(/export\s+const\s+(\w+)\s*=\s*z\.object\s*\(/);
|
|
63
71
|
}
|
|
64
72
|
if (!schemaMatch) {
|
|
65
73
|
throw new Error(`Could not find exported schema in ${modelPath}. Expected patterns:\n - export const xxxSchema = z.object({ ... })\n - export const Xxx = z.object({ ... })`);
|
|
@@ -68,6 +76,12 @@ async function parseModelFile(modelPath) {
|
|
|
68
76
|
// displayName を抽出(例: export const displayName = 'Task')
|
|
69
77
|
const displayNameMatch = content.match(/export\s+const\s+displayName\s*=\s*['"]([^'"]+)['"]/);
|
|
70
78
|
const displayName = displayNameMatch ? displayNameMatch[1] : modelName;
|
|
79
|
+
// connectorConfig を抽出(外部データソース用メタデータ)
|
|
80
|
+
const connectorConfig = parseConnectorConfig(content);
|
|
81
|
+
// authPolicy を抽出(ロールベースアクセス制御用メタデータ)
|
|
82
|
+
const authPolicy = parseAuthPolicy(content);
|
|
83
|
+
// partitionKey を抽出(Cosmos DB パーティションキー)
|
|
84
|
+
const partitionKey = parsePartitionKey(content);
|
|
71
85
|
// ネストしたスキーマ参照を検出
|
|
72
86
|
const nestedSchemaRefs = detectNestedSchemaRefs(modelPath, content, schemaName);
|
|
73
87
|
// フィールド情報を抽出(動的インポートを使用)
|
|
@@ -78,6 +92,16 @@ async function parseModelFile(modelPath) {
|
|
|
78
92
|
const hasId = fields.some(f => f.name === "id");
|
|
79
93
|
const hasCreatedAt = fields.some(f => f.name === "createdAt");
|
|
80
94
|
const hasUpdatedAt = fields.some(f => f.name === "updatedAt");
|
|
95
|
+
// パーティションキーのバリデーション
|
|
96
|
+
if (partitionKey !== '/id') {
|
|
97
|
+
if (!partitionKey.startsWith('/')) {
|
|
98
|
+
console.warn(`⚠️ [${modelName}] partitionKey should start with '/': got '${partitionKey}'`);
|
|
99
|
+
}
|
|
100
|
+
const pkField = partitionKey.startsWith('/') ? partitionKey.slice(1) : partitionKey;
|
|
101
|
+
if (fields.length > 0 && !fields.some(f => f.name === pkField)) {
|
|
102
|
+
console.warn(`⚠️ [${modelName}] partitionKey field '${pkField}' not found in schema fields`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
81
105
|
return {
|
|
82
106
|
name: modelName,
|
|
83
107
|
displayName,
|
|
@@ -88,6 +112,9 @@ async function parseModelFile(modelPath) {
|
|
|
88
112
|
hasCreatedAt,
|
|
89
113
|
hasUpdatedAt,
|
|
90
114
|
nestedSchemaRefs,
|
|
115
|
+
partitionKey,
|
|
116
|
+
...(connectorConfig ? { connectorConfig } : {}),
|
|
117
|
+
...(authPolicy ? { authPolicy } : {}),
|
|
91
118
|
};
|
|
92
119
|
}
|
|
93
120
|
/**
|
|
@@ -257,53 +284,77 @@ function mergeNestedSchemaInfo(fields, nestedRefs) {
|
|
|
257
284
|
}
|
|
258
285
|
}
|
|
259
286
|
}
|
|
287
|
+
/**
|
|
288
|
+
* ローカル依存ファイルを再帰的にインライン化する(動的インポート用一時スクリプト生成用)。
|
|
289
|
+
* seen によって循環依存を防ぐ。
|
|
290
|
+
* importedNames が指定された場合はその名前の const だけを残し、他を除去する。
|
|
291
|
+
*/
|
|
292
|
+
function inlineLocalDeps(filePath, importedNames, seen) {
|
|
293
|
+
const resolvedPath = path.resolve(filePath);
|
|
294
|
+
if (seen.has(resolvedPath))
|
|
295
|
+
return '';
|
|
296
|
+
seen.add(resolvedPath);
|
|
297
|
+
if (!fs.existsSync(resolvedPath))
|
|
298
|
+
return '';
|
|
299
|
+
let content = fs.readFileSync(resolvedPath, 'utf8');
|
|
300
|
+
const fileDir = path.dirname(resolvedPath);
|
|
301
|
+
const transitiveParts = [];
|
|
302
|
+
// ローカル(相対)インポートを再帰的にインライン化
|
|
303
|
+
content = content.replace(/import\s*\{([^}]+)\}\s*from\s*['"](\.[^'"]+)['"]\s*;?/g, (_match, _imports, importPath) => {
|
|
304
|
+
let depPath = path.resolve(fileDir, importPath);
|
|
305
|
+
if (!depPath.endsWith('.ts') && !depPath.endsWith('.js'))
|
|
306
|
+
depPath += '.ts';
|
|
307
|
+
const inlined = inlineLocalDeps(depPath, null, seen);
|
|
308
|
+
if (inlined)
|
|
309
|
+
transitiveParts.push(inlined);
|
|
310
|
+
return '';
|
|
311
|
+
});
|
|
312
|
+
// 外部パッケージのインポートを除去
|
|
313
|
+
content = content.replace(/import\s+.*?\s+from\s+['"](?!\.).*?['"];?\s*/g, '');
|
|
314
|
+
// export キーワードを除去
|
|
315
|
+
content = content.replace(/export\s+(const|type|interface|class|function)\s+/g, '$1 ');
|
|
316
|
+
// 型宣言を除去(ランタイムでは不要)
|
|
317
|
+
content = content.replace(/^type\s+\w+\s*=\s*[^;]+;/gm, '');
|
|
318
|
+
content = content.replace(/^interface\s+\w+\s*\{[\s\S]*?\}/gm, '');
|
|
319
|
+
// コメントを除去
|
|
320
|
+
content = content.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
321
|
+
content = content.replace(/\/\/.*/g, '');
|
|
322
|
+
// 直接インポートされていない const 宣言を除去(displayName 等の重複を防ぐ)
|
|
323
|
+
if (importedNames) {
|
|
324
|
+
content = content.replace(/^const\s+(\w+)\s*=\s*[^;]+;/gm, (constMatch, varName) => {
|
|
325
|
+
return importedNames.has(varName) ? constMatch : '';
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
return [...transitiveParts, content.trim()].filter(Boolean).join('\n\n');
|
|
329
|
+
}
|
|
330
|
+
function resolveBundledTsxCliPath() {
|
|
331
|
+
return require.resolve("tsx/cli");
|
|
332
|
+
}
|
|
260
333
|
/**
|
|
261
334
|
* Zodスキーマから動的にフィールド情報を抽出
|
|
262
335
|
*/
|
|
263
336
|
async function extractFieldsFromSchema(modelPath, schemaName) {
|
|
264
337
|
const fields = [];
|
|
265
338
|
try {
|
|
266
|
-
// child_processでtsxを実行
|
|
267
|
-
const { execSync } = require('child_process');
|
|
268
|
-
const { tmpdir } = require('os');
|
|
269
|
-
const { join } = require('path');
|
|
270
|
-
const { writeFileSync, unlinkSync, readFileSync } = require('fs');
|
|
271
339
|
// モデルファイルの内容を読み込む
|
|
272
|
-
let modelContent = readFileSync(modelPath, 'utf8');
|
|
340
|
+
let modelContent = fs.readFileSync(modelPath, 'utf8');
|
|
273
341
|
const modelDir = path.dirname(path.resolve(modelPath));
|
|
274
|
-
//
|
|
342
|
+
// ローカル相対インポートを再帰的にインライン化して保持
|
|
275
343
|
// パターン: import { categorySchema } from './category'
|
|
344
|
+
const seenPaths = new Set([path.resolve(modelPath)]);
|
|
276
345
|
const localImports = [];
|
|
277
346
|
modelContent = modelContent.replace(/import\s*\{([^}]+)\}\s*from\s*['"](\.[^'"]+)['"]\s*;?/g, (_match, imports, importPath) => {
|
|
278
347
|
// インポートされた変数名を取得
|
|
279
|
-
const importedNames = imports.split(',').map(s =>
|
|
280
|
-
const trimmed = s.trim();
|
|
281
|
-
// 'as' エイリアスに対応
|
|
282
|
-
return trimmed.split(/\s+as\s+/).pop().trim();
|
|
283
|
-
}).filter(s => s.length > 0);
|
|
348
|
+
const importedNames = new Set(imports.split(',').map(s => s.trim().split(/\s+as\s+/).pop().trim()).filter(s => s.length > 0));
|
|
284
349
|
// 相対パスを絶対パスに解決
|
|
285
350
|
let resolvedPath = path.resolve(modelDir, importPath);
|
|
286
351
|
if (!resolvedPath.endsWith('.ts') && !resolvedPath.endsWith('.js')) {
|
|
287
352
|
resolvedPath += '.ts';
|
|
288
353
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
refContent = refContent.replace(/import\s+.*?\s+from\s+['"](?!\.).*?['"];?\s*/g, '');
|
|
294
|
-
refContent = refContent.replace(/import\s+.*?\s+from\s+['"]\..*?['"];?\s*/g, '');
|
|
295
|
-
refContent = refContent.replace(/export\s+(const|type|interface|class|function)\s+/g, '$1 ');
|
|
296
|
-
refContent = refContent.replace(/^type\s+\w+\s*=\s*[^;]+;/gm, '');
|
|
297
|
-
refContent = refContent.replace(/^interface\s+\w+\s*\{[\s\S]*?\}/gm, '');
|
|
298
|
-
refContent = refContent.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
299
|
-
refContent = refContent.replace(/\/\/.*/g, '');
|
|
300
|
-
// インポートされていない const 宣言を除去(displayName 等の重複を防ぐ)
|
|
301
|
-
const importedNameSet = new Set(importedNames);
|
|
302
|
-
refContent = refContent.replace(/^const\s+(\w+)\s*=\s*[^;]+;/gm, (constMatch, varName) => {
|
|
303
|
-
return importedNameSet.has(varName) ? constMatch : '';
|
|
304
|
-
});
|
|
305
|
-
localImports.push(refContent.trim());
|
|
306
|
-
}
|
|
354
|
+
// 推移的なローカル依存を含めて再帰的にインライン化
|
|
355
|
+
const inlined = inlineLocalDeps(resolvedPath, importedNames, seenPaths);
|
|
356
|
+
if (inlined)
|
|
357
|
+
localImports.push(inlined);
|
|
307
358
|
return ''; // 元のインポート文は除去
|
|
308
359
|
});
|
|
309
360
|
// zod 以外のパッケージインポートを除去
|
|
@@ -316,6 +367,8 @@ async function extractFieldsFromSchema(modelPath, schemaName) {
|
|
|
316
367
|
// コメントを削除
|
|
317
368
|
modelContent = modelContent.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
318
369
|
modelContent = modelContent.replace(/\/\/.*/g, '');
|
|
370
|
+
// TypeScript の `as const` アサーションを削除(.mjs では構文エラーになる)
|
|
371
|
+
modelContent = modelContent.replace(/\s+as\s+const\b/g, '');
|
|
319
372
|
// インライン化したローカルインポートを先頭に追加
|
|
320
373
|
const inlinedDeps = localImports.length > 0 ? localImports.join('\n\n') + '\n\n' : '';
|
|
321
374
|
// プロジェクトルートを探す(package.jsonがある場所)
|
|
@@ -328,109 +381,109 @@ async function extractFieldsFromSchema(modelPath, schemaName) {
|
|
|
328
381
|
}
|
|
329
382
|
// プロジェクトルート内に一時スクリプトファイルを作成
|
|
330
383
|
const tempScript = path.join(projectRoot, `.swallowkit-parser-${Date.now()}.mjs`);
|
|
331
|
-
const scriptCode = `
|
|
332
|
-
import { z } from 'zod/v4';
|
|
333
|
-
|
|
334
|
-
// インライン化した依存スキーマ
|
|
335
|
-
${inlinedDeps}
|
|
336
|
-
// モデルファイルの内容を評価
|
|
337
|
-
${modelContent}
|
|
338
|
-
|
|
339
|
-
const schema = ${schemaName};
|
|
340
|
-
|
|
341
|
-
// Zod v3とv4の両方に対応
|
|
342
|
-
const isObject = (schema && schema._def &&
|
|
343
|
-
(schema._def.typeName === 'ZodObject' || schema.constructor?.name === 'ZodObject' || typeof schema._def.shape === 'function'));
|
|
344
|
-
|
|
345
|
-
if (isObject) {
|
|
346
|
-
const shape = typeof schema._def.shape === 'function' ? schema._def.shape() : schema._def.shape;
|
|
347
|
-
const fields = Object.keys(shape).map(key => {
|
|
348
|
-
const field = shape[key];
|
|
349
|
-
let type = 'string';
|
|
350
|
-
let isOptional = false;
|
|
351
|
-
let isArray = false;
|
|
352
|
-
let enumValues = undefined;
|
|
353
|
-
|
|
354
|
-
// ZodOptional, ZodDefault, ZodEffects を unwrap
|
|
355
|
-
let fieldDef = field;
|
|
356
|
-
const getTypeName = (def) => def?._def?.typeName || def?.constructor?.name || '';
|
|
357
|
-
|
|
358
|
-
// 繰り返し unwrap(複数のラッパーがある場合に対応)
|
|
359
|
-
let unwrapped = false;
|
|
360
|
-
do {
|
|
361
|
-
unwrapped = false;
|
|
362
|
-
const typeName = getTypeName(fieldDef);
|
|
363
|
-
|
|
364
|
-
if (typeName === 'ZodOptional') {
|
|
365
|
-
isOptional = true;
|
|
366
|
-
fieldDef = fieldDef._def.innerType;
|
|
367
|
-
unwrapped = true;
|
|
368
|
-
} else if (typeName === 'ZodDefault') {
|
|
369
|
-
// .default() は optional と同様に扱う
|
|
370
|
-
isOptional = true;
|
|
371
|
-
fieldDef = fieldDef._def.innerType;
|
|
372
|
-
unwrapped = true;
|
|
373
|
-
} else if (typeName === 'ZodEffects') {
|
|
374
|
-
// .min(), .max(), .regex() などの Effects を unwrap
|
|
375
|
-
fieldDef = fieldDef._def.schema;
|
|
376
|
-
unwrapped = true;
|
|
377
|
-
}
|
|
378
|
-
} while (unwrapped);
|
|
379
|
-
|
|
380
|
-
// ZodArray をチェック
|
|
381
|
-
if (getTypeName(fieldDef) === 'ZodArray') {
|
|
382
|
-
isArray = true;
|
|
383
|
-
fieldDef = fieldDef._def.type || fieldDef._def.element;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
// 基本型を判定
|
|
387
|
-
const typeName = getTypeName(fieldDef);
|
|
388
|
-
if (typeName === 'ZodString') type = 'string';
|
|
389
|
-
else if (typeName === 'ZodNumber') type = 'number';
|
|
390
|
-
else if (typeName === 'ZodBoolean') type = 'boolean';
|
|
391
|
-
else if (typeName === 'ZodDate') type = 'date';
|
|
392
|
-
else if (typeName === 'ZodObject') type = 'object';
|
|
393
|
-
else if (typeName === 'ZodEnum' || typeName === 'ZodNativeEnum') {
|
|
394
|
-
type = 'string';
|
|
395
|
-
// enum の選択肢を取得(複数のZodバージョンに対応)
|
|
396
|
-
if (fieldDef.options) {
|
|
397
|
-
// Zod v3.23+ では options プロパティを使用
|
|
398
|
-
enumValues = Array.isArray(fieldDef.options)
|
|
399
|
-
? fieldDef.options
|
|
400
|
-
: Object.values(fieldDef.options);
|
|
401
|
-
} else if (fieldDef._def.values) {
|
|
402
|
-
// 古いバージョンでは _def.values を使用
|
|
403
|
-
enumValues = Array.isArray(fieldDef._def.values)
|
|
404
|
-
? fieldDef._def.values
|
|
405
|
-
: Object.values(fieldDef._def.values);
|
|
406
|
-
} else if (fieldDef._def.entries) {
|
|
407
|
-
// さらに古いバージョンでは _def.entries を使用
|
|
408
|
-
enumValues = Array.isArray(fieldDef._def.entries)
|
|
409
|
-
? fieldDef._def.entries
|
|
410
|
-
: Object.values(fieldDef._def.entries);
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
// 外部キー検出: フィールド名が <ModelName>Id のパターンの場合
|
|
415
|
-
let isForeignKey = false;
|
|
416
|
-
let referencedModel = undefined;
|
|
417
|
-
if (key.endsWith('Id') && key.length > 2 && type === 'string') {
|
|
418
|
-
// categoryId -> Category, userId -> User など
|
|
419
|
-
const modelName = key.slice(0, -2); // "Id" を除去
|
|
420
|
-
referencedModel = modelName.charAt(0).toUpperCase() + modelName.slice(1); // 先頭を大文字に
|
|
421
|
-
isForeignKey = true;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
return { name: key, type, isOptional, isArray, enumValues, isForeignKey, referencedModel };
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
console.log(JSON.stringify(fields));
|
|
428
|
-
}
|
|
384
|
+
const scriptCode = `
|
|
385
|
+
import { z } from 'zod/v4';
|
|
386
|
+
|
|
387
|
+
// インライン化した依存スキーマ
|
|
388
|
+
${inlinedDeps}
|
|
389
|
+
// モデルファイルの内容を評価
|
|
390
|
+
${modelContent}
|
|
391
|
+
|
|
392
|
+
const schema = ${schemaName};
|
|
393
|
+
|
|
394
|
+
// Zod v3とv4の両方に対応
|
|
395
|
+
const isObject = (schema && schema._def &&
|
|
396
|
+
(schema._def.typeName === 'ZodObject' || schema.constructor?.name === 'ZodObject' || typeof schema._def.shape === 'function'));
|
|
397
|
+
|
|
398
|
+
if (isObject) {
|
|
399
|
+
const shape = typeof schema._def.shape === 'function' ? schema._def.shape() : schema._def.shape;
|
|
400
|
+
const fields = Object.keys(shape).map(key => {
|
|
401
|
+
const field = shape[key];
|
|
402
|
+
let type = 'string';
|
|
403
|
+
let isOptional = false;
|
|
404
|
+
let isArray = false;
|
|
405
|
+
let enumValues = undefined;
|
|
406
|
+
|
|
407
|
+
// ZodOptional, ZodDefault, ZodEffects を unwrap
|
|
408
|
+
let fieldDef = field;
|
|
409
|
+
const getTypeName = (def) => def?._def?.typeName || def?.constructor?.name || '';
|
|
410
|
+
|
|
411
|
+
// 繰り返し unwrap(複数のラッパーがある場合に対応)
|
|
412
|
+
let unwrapped = false;
|
|
413
|
+
do {
|
|
414
|
+
unwrapped = false;
|
|
415
|
+
const typeName = getTypeName(fieldDef);
|
|
416
|
+
|
|
417
|
+
if (typeName === 'ZodOptional') {
|
|
418
|
+
isOptional = true;
|
|
419
|
+
fieldDef = fieldDef._def.innerType;
|
|
420
|
+
unwrapped = true;
|
|
421
|
+
} else if (typeName === 'ZodDefault') {
|
|
422
|
+
// .default() は optional と同様に扱う
|
|
423
|
+
isOptional = true;
|
|
424
|
+
fieldDef = fieldDef._def.innerType;
|
|
425
|
+
unwrapped = true;
|
|
426
|
+
} else if (typeName === 'ZodEffects') {
|
|
427
|
+
// .min(), .max(), .regex() などの Effects を unwrap
|
|
428
|
+
fieldDef = fieldDef._def.schema;
|
|
429
|
+
unwrapped = true;
|
|
430
|
+
}
|
|
431
|
+
} while (unwrapped);
|
|
432
|
+
|
|
433
|
+
// ZodArray をチェック
|
|
434
|
+
if (getTypeName(fieldDef) === 'ZodArray') {
|
|
435
|
+
isArray = true;
|
|
436
|
+
fieldDef = fieldDef._def.type || fieldDef._def.element;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// 基本型を判定
|
|
440
|
+
const typeName = getTypeName(fieldDef);
|
|
441
|
+
if (typeName === 'ZodString') type = 'string';
|
|
442
|
+
else if (typeName === 'ZodNumber') type = 'number';
|
|
443
|
+
else if (typeName === 'ZodBoolean') type = 'boolean';
|
|
444
|
+
else if (typeName === 'ZodDate') type = 'date';
|
|
445
|
+
else if (typeName === 'ZodObject') type = 'object';
|
|
446
|
+
else if (typeName === 'ZodEnum' || typeName === 'ZodNativeEnum') {
|
|
447
|
+
type = 'string';
|
|
448
|
+
// enum の選択肢を取得(複数のZodバージョンに対応)
|
|
449
|
+
if (fieldDef.options) {
|
|
450
|
+
// Zod v3.23+ では options プロパティを使用
|
|
451
|
+
enumValues = Array.isArray(fieldDef.options)
|
|
452
|
+
? fieldDef.options
|
|
453
|
+
: Object.values(fieldDef.options);
|
|
454
|
+
} else if (fieldDef._def.values) {
|
|
455
|
+
// 古いバージョンでは _def.values を使用
|
|
456
|
+
enumValues = Array.isArray(fieldDef._def.values)
|
|
457
|
+
? fieldDef._def.values
|
|
458
|
+
: Object.values(fieldDef._def.values);
|
|
459
|
+
} else if (fieldDef._def.entries) {
|
|
460
|
+
// さらに古いバージョンでは _def.entries を使用
|
|
461
|
+
enumValues = Array.isArray(fieldDef._def.entries)
|
|
462
|
+
? fieldDef._def.entries
|
|
463
|
+
: Object.values(fieldDef._def.entries);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// 外部キー検出: フィールド名が <ModelName>Id のパターンの場合
|
|
468
|
+
let isForeignKey = false;
|
|
469
|
+
let referencedModel = undefined;
|
|
470
|
+
if (key.endsWith('Id') && key.length > 2 && type === 'string') {
|
|
471
|
+
// categoryId -> Category, userId -> User など
|
|
472
|
+
const modelName = key.slice(0, -2); // "Id" を除去
|
|
473
|
+
referencedModel = modelName.charAt(0).toUpperCase() + modelName.slice(1); // 先頭を大文字に
|
|
474
|
+
isForeignKey = true;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return { name: key, type, isOptional, isArray, enumValues, isForeignKey, referencedModel };
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
console.log(JSON.stringify(fields));
|
|
481
|
+
}
|
|
429
482
|
`;
|
|
430
|
-
writeFileSync(tempScript, scriptCode, 'utf8');
|
|
483
|
+
fs.writeFileSync(tempScript, scriptCode, 'utf8');
|
|
431
484
|
try {
|
|
432
|
-
|
|
433
|
-
const result =
|
|
485
|
+
const tsxCliPath = resolveBundledTsxCliPath();
|
|
486
|
+
const result = (0, child_process_1.execFileSync)(process.execPath, [tsxCliPath, tempScript], {
|
|
434
487
|
encoding: 'utf8',
|
|
435
488
|
cwd: projectRoot,
|
|
436
489
|
});
|
|
@@ -443,7 +496,7 @@ if (isObject) {
|
|
|
443
496
|
finally {
|
|
444
497
|
// 一時ファイルを削除
|
|
445
498
|
try {
|
|
446
|
-
unlinkSync(tempScript);
|
|
499
|
+
fs.unlinkSync(tempScript);
|
|
447
500
|
}
|
|
448
501
|
catch (e) {
|
|
449
502
|
// ファイル削除失敗は無視
|
|
@@ -520,6 +573,146 @@ function toCamelCase(str) {
|
|
|
520
573
|
const pascal = toPascalCase(str);
|
|
521
574
|
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
522
575
|
}
|
|
576
|
+
/**
|
|
577
|
+
* モデルファイルから connectorConfig エクスポートを静的解析で抽出する
|
|
578
|
+
*/
|
|
579
|
+
function parseConnectorConfig(content) {
|
|
580
|
+
// export const connectorConfig = { ... } を検出
|
|
581
|
+
const connectorMatch = content.match(/export\s+const\s+connectorConfig\s*=\s*\{/);
|
|
582
|
+
if (!connectorMatch) {
|
|
583
|
+
return undefined;
|
|
584
|
+
}
|
|
585
|
+
// connectorConfig オブジェクトの内容を抽出
|
|
586
|
+
const startIdx = content.indexOf('{', connectorMatch.index);
|
|
587
|
+
let braceCount = 1;
|
|
588
|
+
let endIdx = startIdx + 1;
|
|
589
|
+
while (braceCount > 0 && endIdx < content.length) {
|
|
590
|
+
if (content[endIdx] === '{')
|
|
591
|
+
braceCount++;
|
|
592
|
+
if (content[endIdx] === '}')
|
|
593
|
+
braceCount--;
|
|
594
|
+
endIdx++;
|
|
595
|
+
}
|
|
596
|
+
const objectStr = content.substring(startIdx, endIdx);
|
|
597
|
+
// connector 名を抽出
|
|
598
|
+
const connectorNameMatch = objectStr.match(/connector\s*:\s*['"]([^'"]+)['"]/);
|
|
599
|
+
if (!connectorNameMatch) {
|
|
600
|
+
return undefined;
|
|
601
|
+
}
|
|
602
|
+
const connector = connectorNameMatch[1];
|
|
603
|
+
// operations を抽出
|
|
604
|
+
const opsMatch = objectStr.match(/operations\s*:\s*\[([^\]]*)\]/);
|
|
605
|
+
const operations = [];
|
|
606
|
+
if (opsMatch) {
|
|
607
|
+
const opsStr = opsMatch[1];
|
|
608
|
+
const opEntries = opsStr.match(/['"]([^'"]+)['"]/g);
|
|
609
|
+
if (opEntries) {
|
|
610
|
+
for (const entry of opEntries) {
|
|
611
|
+
operations.push(entry.replace(/['"]/g, ''));
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
// table を抽出(RDB 固有)
|
|
616
|
+
const tableMatch = objectStr.match(/table\s*:\s*['"]([^'"]+)['"]/);
|
|
617
|
+
// idColumn を抽出(RDB 固有)
|
|
618
|
+
const idColumnMatch = objectStr.match(/idColumn\s*:\s*['"]([^'"]+)['"]/);
|
|
619
|
+
// endpoints を抽出(API 固有)— endpoint値に {id} 等のプレースホルダが含まれるためbrace-countingで抽出
|
|
620
|
+
let endpoints;
|
|
621
|
+
const endpointsStart = objectStr.match(/endpoints\s*:\s*\{/);
|
|
622
|
+
if (endpointsStart) {
|
|
623
|
+
const epStartIdx = objectStr.indexOf('{', endpointsStart.index);
|
|
624
|
+
let epBraceCount = 1;
|
|
625
|
+
let epEndIdx = epStartIdx + 1;
|
|
626
|
+
while (epBraceCount > 0 && epEndIdx < objectStr.length) {
|
|
627
|
+
const ch = objectStr[epEndIdx];
|
|
628
|
+
// 文字列内の波括弧をスキップ
|
|
629
|
+
if (ch === "'" || ch === '"') {
|
|
630
|
+
epEndIdx++;
|
|
631
|
+
while (epEndIdx < objectStr.length && objectStr[epEndIdx] !== ch) {
|
|
632
|
+
epEndIdx++;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
else if (ch === '{') {
|
|
636
|
+
epBraceCount++;
|
|
637
|
+
}
|
|
638
|
+
else if (ch === '}') {
|
|
639
|
+
epBraceCount--;
|
|
640
|
+
}
|
|
641
|
+
epEndIdx++;
|
|
642
|
+
}
|
|
643
|
+
const epStr = objectStr.substring(epStartIdx + 1, epEndIdx - 1);
|
|
644
|
+
endpoints = {};
|
|
645
|
+
const endpointEntries = epStr.matchAll(/(\w+)\s*:\s*['"]([^'"]+)['"]/g);
|
|
646
|
+
for (const entry of endpointEntries) {
|
|
647
|
+
endpoints[entry[1]] = entry[2];
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
if (tableMatch) {
|
|
651
|
+
// RDB コネクタ
|
|
652
|
+
return {
|
|
653
|
+
connector,
|
|
654
|
+
operations: operations,
|
|
655
|
+
table: tableMatch[1],
|
|
656
|
+
...(idColumnMatch ? { idColumn: idColumnMatch[1] } : {}),
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
// API コネクタ
|
|
660
|
+
return {
|
|
661
|
+
connector,
|
|
662
|
+
operations: operations,
|
|
663
|
+
...(endpoints ? { endpoints } : {}),
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* authPolicy をモデルファイルから抽出
|
|
668
|
+
* パターン: export const authPolicy = { roles: [...], read: [...], write: [...] }
|
|
669
|
+
*/
|
|
670
|
+
function parseAuthPolicy(content) {
|
|
671
|
+
const policyMatch = content.match(/export\s+const\s+authPolicy\s*=\s*\{/);
|
|
672
|
+
if (!policyMatch) {
|
|
673
|
+
return undefined;
|
|
674
|
+
}
|
|
675
|
+
const startIdx = content.indexOf('{', policyMatch.index);
|
|
676
|
+
let braceCount = 1;
|
|
677
|
+
let endIdx = startIdx + 1;
|
|
678
|
+
while (braceCount > 0 && endIdx < content.length) {
|
|
679
|
+
if (content[endIdx] === '{')
|
|
680
|
+
braceCount++;
|
|
681
|
+
if (content[endIdx] === '}')
|
|
682
|
+
braceCount--;
|
|
683
|
+
endIdx++;
|
|
684
|
+
}
|
|
685
|
+
const objectStr = content.substring(startIdx, endIdx);
|
|
686
|
+
const extractRoles = (key) => {
|
|
687
|
+
const match = objectStr.match(new RegExp(`${key}\\s*:\\s*\\[([^\\]]*)\\]`));
|
|
688
|
+
if (!match)
|
|
689
|
+
return undefined;
|
|
690
|
+
const entries = match[1].match(/['"]([^'"]+)['"]/g);
|
|
691
|
+
if (!entries)
|
|
692
|
+
return [];
|
|
693
|
+
return entries.map(e => e.replace(/['"]/g, ''));
|
|
694
|
+
};
|
|
695
|
+
const roles = extractRoles('roles');
|
|
696
|
+
const read = extractRoles('read');
|
|
697
|
+
const write = extractRoles('write');
|
|
698
|
+
if (!roles && !read && !write) {
|
|
699
|
+
return undefined;
|
|
700
|
+
}
|
|
701
|
+
return {
|
|
702
|
+
...(roles ? { roles } : {}),
|
|
703
|
+
...(read ? { read } : {}),
|
|
704
|
+
...(write ? { write } : {}),
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* パーティションキーを抽出する
|
|
709
|
+
* export const partitionKey = '/tenantId' のようなエクスポートを検出
|
|
710
|
+
* 未指定の場合はデフォルト '/id' を返す
|
|
711
|
+
*/
|
|
712
|
+
function parsePartitionKey(content) {
|
|
713
|
+
const match = content.match(/export\s+const\s+partitionKey\s*=\s*['"]([^'"]+)['"]/);
|
|
714
|
+
return match ? match[1] : '/id';
|
|
715
|
+
}
|
|
523
716
|
/**
|
|
524
717
|
* 文字列を kebab-case に変換
|
|
525
718
|
*/
|
|
@@ -530,7 +723,7 @@ function toKebabCase(str) {
|
|
|
530
723
|
}
|
|
531
724
|
/**
|
|
532
725
|
* models ディレクトリから全てのモデル情報を取得
|
|
533
|
-
* @param modelsDir モデルディレクトリのパス(デフォルト: "
|
|
726
|
+
* @param modelsDir モデルディレクトリのパス(デフォルト: "shared/models")
|
|
534
727
|
* @returns モデル情報の配列
|
|
535
728
|
*/
|
|
536
729
|
async function getAllModels(modelsDir = "shared/models") {
|