@vegamo/loom 0.1.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.
Files changed (196) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +465 -0
  3. package/dist/agents/core/agent.d.ts +65 -0
  4. package/dist/agents/core/agent.d.ts.map +1 -0
  5. package/dist/agents/core/agent.js +277 -0
  6. package/dist/agents/core/agent.js.map +1 -0
  7. package/dist/agents/core/prompt.d.ts +11 -0
  8. package/dist/agents/core/prompt.d.ts.map +1 -0
  9. package/dist/agents/core/prompt.js +117 -0
  10. package/dist/agents/core/prompt.js.map +1 -0
  11. package/dist/agents/core/types.d.ts +49 -0
  12. package/dist/agents/core/types.d.ts.map +1 -0
  13. package/dist/agents/core/types.js +5 -0
  14. package/dist/agents/core/types.js.map +1 -0
  15. package/dist/agents/memory/memory.d.ts +62 -0
  16. package/dist/agents/memory/memory.d.ts.map +1 -0
  17. package/dist/agents/memory/memory.js +113 -0
  18. package/dist/agents/memory/memory.js.map +1 -0
  19. package/dist/agents/memory/types.d.ts +15 -0
  20. package/dist/agents/memory/types.d.ts.map +1 -0
  21. package/dist/agents/memory/types.js +5 -0
  22. package/dist/agents/memory/types.js.map +1 -0
  23. package/dist/index.d.ts +13 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +104 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/llm/client.d.ts +49 -0
  28. package/dist/llm/client.d.ts.map +1 -0
  29. package/dist/llm/client.js +256 -0
  30. package/dist/llm/client.js.map +1 -0
  31. package/dist/llm/config.d.ts +13 -0
  32. package/dist/llm/config.d.ts.map +1 -0
  33. package/dist/llm/config.js +50 -0
  34. package/dist/llm/config.js.map +1 -0
  35. package/dist/llm/types.d.ts +74 -0
  36. package/dist/llm/types.d.ts.map +1 -0
  37. package/dist/llm/types.js +17 -0
  38. package/dist/llm/types.js.map +1 -0
  39. package/dist/mocks/generator.d.ts +10 -0
  40. package/dist/mocks/generator.d.ts.map +1 -0
  41. package/dist/mocks/generator.js +19 -0
  42. package/dist/mocks/generator.js.map +1 -0
  43. package/dist/mocks/router.d.ts +13 -0
  44. package/dist/mocks/router.d.ts.map +1 -0
  45. package/dist/mocks/router.js +44 -0
  46. package/dist/mocks/router.js.map +1 -0
  47. package/dist/mocks/server.d.ts +21 -0
  48. package/dist/mocks/server.d.ts.map +1 -0
  49. package/dist/mocks/server.js +36 -0
  50. package/dist/mocks/server.js.map +1 -0
  51. package/dist/serve.d.ts +17 -0
  52. package/dist/serve.d.ts.map +1 -0
  53. package/dist/serve.js +56 -0
  54. package/dist/serve.js.map +1 -0
  55. package/dist/shared/config-wizard.d.ts +7 -0
  56. package/dist/shared/config-wizard.d.ts.map +1 -0
  57. package/dist/shared/config-wizard.js +84 -0
  58. package/dist/shared/config-wizard.js.map +1 -0
  59. package/dist/shared/config.d.ts +32 -0
  60. package/dist/shared/config.d.ts.map +1 -0
  61. package/dist/shared/config.js +77 -0
  62. package/dist/shared/config.js.map +1 -0
  63. package/dist/shared/entity-utils.d.ts +30 -0
  64. package/dist/shared/entity-utils.d.ts.map +1 -0
  65. package/dist/shared/entity-utils.js +207 -0
  66. package/dist/shared/entity-utils.js.map +1 -0
  67. package/dist/shared/logger.d.ts +13 -0
  68. package/dist/shared/logger.d.ts.map +1 -0
  69. package/dist/shared/logger.js +45 -0
  70. package/dist/shared/logger.js.map +1 -0
  71. package/dist/shared/manifest-utils.d.ts +9 -0
  72. package/dist/shared/manifest-utils.d.ts.map +1 -0
  73. package/dist/shared/manifest-utils.js +110 -0
  74. package/dist/shared/manifest-utils.js.map +1 -0
  75. package/dist/shared/schema-entity-resolver.d.ts +15 -0
  76. package/dist/shared/schema-entity-resolver.d.ts.map +1 -0
  77. package/dist/shared/schema-entity-resolver.js +134 -0
  78. package/dist/shared/schema-entity-resolver.js.map +1 -0
  79. package/dist/shared/schema-utils.d.ts +21 -0
  80. package/dist/shared/schema-utils.d.ts.map +1 -0
  81. package/dist/shared/schema-utils.js +56 -0
  82. package/dist/shared/schema-utils.js.map +1 -0
  83. package/dist/shared/types.d.ts +130 -0
  84. package/dist/shared/types.d.ts.map +1 -0
  85. package/dist/shared/types.js +5 -0
  86. package/dist/shared/types.js.map +1 -0
  87. package/dist/tools/entity-file-ops.d.ts +10 -0
  88. package/dist/tools/entity-file-ops.d.ts.map +1 -0
  89. package/dist/tools/entity-file-ops.js +183 -0
  90. package/dist/tools/entity-file-ops.js.map +1 -0
  91. package/dist/tools/entity-workflow.d.ts +10 -0
  92. package/dist/tools/entity-workflow.d.ts.map +1 -0
  93. package/dist/tools/entity-workflow.js +447 -0
  94. package/dist/tools/entity-workflow.js.map +1 -0
  95. package/dist/tools/file-ops.d.ts +9 -0
  96. package/dist/tools/file-ops.d.ts.map +1 -0
  97. package/dist/tools/file-ops.js +83 -0
  98. package/dist/tools/file-ops.js.map +1 -0
  99. package/dist/tools/registry.d.ts +31 -0
  100. package/dist/tools/registry.d.ts.map +1 -0
  101. package/dist/tools/registry.js +58 -0
  102. package/dist/tools/registry.js.map +1 -0
  103. package/dist/tools/schema-gen.d.ts +8 -0
  104. package/dist/tools/schema-gen.d.ts.map +1 -0
  105. package/dist/tools/schema-gen.js +82 -0
  106. package/dist/tools/schema-gen.js.map +1 -0
  107. package/dist/tools/schema-validate.d.ts +8 -0
  108. package/dist/tools/schema-validate.d.ts.map +1 -0
  109. package/dist/tools/schema-validate.js +79 -0
  110. package/dist/tools/schema-validate.js.map +1 -0
  111. package/dist/tools/types.d.ts +29 -0
  112. package/dist/tools/types.d.ts.map +1 -0
  113. package/dist/tools/types.js +5 -0
  114. package/dist/tools/types.js.map +1 -0
  115. package/dist/tui/app.d.ts +13 -0
  116. package/dist/tui/app.d.ts.map +1 -0
  117. package/dist/tui/app.js +357 -0
  118. package/dist/tui/app.js.map +1 -0
  119. package/dist/tui/components/Chat.d.ts +14 -0
  120. package/dist/tui/components/Chat.d.ts.map +1 -0
  121. package/dist/tui/components/Chat.js +24 -0
  122. package/dist/tui/components/Chat.js.map +1 -0
  123. package/dist/tui/components/Header.d.ts +14 -0
  124. package/dist/tui/components/Header.d.ts.map +1 -0
  125. package/dist/tui/components/Header.js +6 -0
  126. package/dist/tui/components/Header.js.map +1 -0
  127. package/dist/tui/components/Input.d.ts +15 -0
  128. package/dist/tui/components/Input.d.ts.map +1 -0
  129. package/dist/tui/components/Input.js +74 -0
  130. package/dist/tui/components/Input.js.map +1 -0
  131. package/dist/tui/components/SchemaPreview.d.ts +13 -0
  132. package/dist/tui/components/SchemaPreview.d.ts.map +1 -0
  133. package/dist/tui/components/SchemaPreview.js +9 -0
  134. package/dist/tui/components/SchemaPreview.js.map +1 -0
  135. package/dist/tui/components/StatusBar.d.ts +15 -0
  136. package/dist/tui/components/StatusBar.d.ts.map +1 -0
  137. package/dist/tui/components/StatusBar.js +7 -0
  138. package/dist/tui/components/StatusBar.js.map +1 -0
  139. package/dist/tui/hooks/useAgent.d.ts +41 -0
  140. package/dist/tui/hooks/useAgent.d.ts.map +1 -0
  141. package/dist/tui/hooks/useAgent.js +180 -0
  142. package/dist/tui/hooks/useAgent.js.map +1 -0
  143. package/dist/view/frontend/components/App.d.ts +4 -0
  144. package/dist/view/frontend/components/App.d.ts.map +1 -0
  145. package/dist/view/frontend/components/App.js +35 -0
  146. package/dist/view/frontend/components/App.js.map +1 -0
  147. package/dist/view/frontend/components/EndpointDetailPage.d.ts +4 -0
  148. package/dist/view/frontend/components/EndpointDetailPage.d.ts.map +1 -0
  149. package/dist/view/frontend/components/EndpointDetailPage.js +103 -0
  150. package/dist/view/frontend/components/EndpointDetailPage.js.map +1 -0
  151. package/dist/view/frontend/components/HomePage.d.ts +4 -0
  152. package/dist/view/frontend/components/HomePage.d.ts.map +1 -0
  153. package/dist/view/frontend/components/HomePage.js +6 -0
  154. package/dist/view/frontend/components/HomePage.js.map +1 -0
  155. package/dist/view/frontend/components/ModuleDetailPage.d.ts +4 -0
  156. package/dist/view/frontend/components/ModuleDetailPage.d.ts.map +1 -0
  157. package/dist/view/frontend/components/ModuleDetailPage.js +64 -0
  158. package/dist/view/frontend/components/ModuleDetailPage.js.map +1 -0
  159. package/dist/view/frontend/components/ModulesPage.d.ts +4 -0
  160. package/dist/view/frontend/components/ModulesPage.d.ts.map +1 -0
  161. package/dist/view/frontend/components/ModulesPage.js +40 -0
  162. package/dist/view/frontend/components/ModulesPage.js.map +1 -0
  163. package/dist/view/frontend/index.d.ts +2 -0
  164. package/dist/view/frontend/index.d.ts.map +1 -0
  165. package/dist/view/frontend/index.js +15 -0
  166. package/dist/view/frontend/index.js.map +1 -0
  167. package/dist/view/frontend/types.d.ts +35 -0
  168. package/dist/view/frontend/types.d.ts.map +1 -0
  169. package/dist/view/frontend/types.js +2 -0
  170. package/dist/view/frontend/types.js.map +1 -0
  171. package/dist/view/frontend/utils/api.d.ts +5 -0
  172. package/dist/view/frontend/utils/api.d.ts.map +1 -0
  173. package/dist/view/frontend/utils/api.js +28 -0
  174. package/dist/view/frontend/utils/api.js.map +1 -0
  175. package/dist/view/public/bundle.js +104633 -0
  176. package/dist/view/public/bundle.js.map +7 -0
  177. package/dist/view/public/index.html +50 -0
  178. package/dist/view/routes/docs.d.ts +13 -0
  179. package/dist/view/routes/docs.d.ts.map +1 -0
  180. package/dist/view/routes/docs.js +53 -0
  181. package/dist/view/routes/docs.js.map +1 -0
  182. package/dist/view/routes/entities.d.ts +11 -0
  183. package/dist/view/routes/entities.d.ts.map +1 -0
  184. package/dist/view/routes/entities.js +39 -0
  185. package/dist/view/routes/entities.js.map +1 -0
  186. package/dist/view/routes/schema.d.ts +11 -0
  187. package/dist/view/routes/schema.d.ts.map +1 -0
  188. package/dist/view/routes/schema.js +43 -0
  189. package/dist/view/routes/schema.js.map +1 -0
  190. package/dist/view/server.d.ts +20 -0
  191. package/dist/view/server.d.ts.map +1 -0
  192. package/dist/view/server.js +54 -0
  193. package/dist/view/server.js.map +1 -0
  194. package/docgen.config.json +19 -0
  195. package/docgen.config.json.example +19 -0
  196. package/package.json +79 -0
@@ -0,0 +1,17 @@
1
+ /**
2
+ * LLM 相关类型定义
3
+ */
4
+ /** LLM 自定义错误 */
5
+ export class LLMError extends Error {
6
+ code;
7
+ retryable;
8
+ statusCode;
9
+ constructor(message, code, opts) {
10
+ super(message);
11
+ this.name = 'LLMError';
12
+ this.code = code;
13
+ this.retryable = opts?.retryable ?? false;
14
+ this.statusCode = opts?.statusCode;
15
+ }
16
+ }
17
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/llm/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiGH,gBAAgB;AAChB,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjC,IAAI,CAAe;IACnB,SAAS,CAAU;IACnB,UAAU,CAAU;IAEpB,YAAY,OAAe,EAAE,IAAkB,EAAE,IAAmD;QAClG,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,SAAS,GAAG,IAAI,EAAE,SAAS,IAAI,KAAK,CAAC;QAC1C,IAAI,CAAC,UAAU,GAAG,IAAI,EAAE,UAAU,CAAC;IACrC,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Mock 数据生成器
3
+ *
4
+ * 根据 JSON Schema 定义生成符合约束的假数据
5
+ */
6
+ /**
7
+ * 根据 JSON Schema 生成 mock 数据
8
+ */
9
+ export declare function generateMockData(schema: Record<string, unknown>): unknown;
10
+ //# sourceMappingURL=generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/mocks/generator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAOzE"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Mock 数据生成器
3
+ *
4
+ * 根据 JSON Schema 定义生成符合约束的假数据
5
+ */
6
+ import { mock } from 'mock-json-schema';
7
+ /**
8
+ * 根据 JSON Schema 生成 mock 数据
9
+ */
10
+ export function generateMockData(schema) {
11
+ try {
12
+ return mock(schema);
13
+ }
14
+ catch {
15
+ // 如果生成失败,返回空对象
16
+ return {};
17
+ }
18
+ }
19
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/mocks/generator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAA+B;IAC9D,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;QACf,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Mock 动态路由注册
3
+ *
4
+ * 读取 docs 目录下的 schema 文件,为每个 endpoint 注册对应的 mock 路由
5
+ */
6
+ import type { FastifyInstance } from 'fastify';
7
+ /**
8
+ * 根据 docs 目录中的 schema 文件注册所有 mock 路由
9
+ *
10
+ * @param prefix 路由前缀 (独立 mock 服务为 '', serve 模式为 '/mock')
11
+ */
12
+ export declare function registerMockRoutes(fastify: FastifyInstance, docsDir: string, prefix?: string): Promise<number>;
13
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/mocks/router.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAa/C;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAW,GAClB,OAAO,CAAC,MAAM,CAAC,CAmCjB"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Mock 动态路由注册
3
+ *
4
+ * 读取 docs 目录下的 schema 文件,为每个 endpoint 注册对应的 mock 路由
5
+ */
6
+ import { listSchemaFiles, readSchemaFile } from '../shared/schema-utils.js';
7
+ import { generateMockData } from './generator.js';
8
+ import { logger } from '../shared/logger.js';
9
+ /**
10
+ * 将 schema 中的路径参数格式转换为 Fastify 格式
11
+ * /api/users/:id → /api/users/:id (Fastify 已原生支持)
12
+ */
13
+ function normalizePath(schemaPath, prefix) {
14
+ return prefix + schemaPath;
15
+ }
16
+ /**
17
+ * 根据 docs 目录中的 schema 文件注册所有 mock 路由
18
+ *
19
+ * @param prefix 路由前缀 (独立 mock 服务为 '', serve 模式为 '/mock')
20
+ */
21
+ export async function registerMockRoutes(fastify, docsDir, prefix = '') {
22
+ const files = listSchemaFiles(docsDir);
23
+ let routeCount = 0;
24
+ for (const fileMeta of files) {
25
+ const doc = readSchemaFile(fileMeta.filepath);
26
+ for (const endpoint of doc.endpoints) {
27
+ const fullPath = normalizePath(endpoint.path, prefix);
28
+ const method = endpoint.method.toLowerCase();
29
+ fastify[method](fullPath, async () => {
30
+ // 取第一个成功响应的 schema 来生成数据
31
+ const successStatus = Object.keys(endpoint.response).find((s) => s.startsWith('2')) || '200';
32
+ const responseSchema = endpoint.response[successStatus];
33
+ if (responseSchema) {
34
+ return generateMockData(responseSchema);
35
+ }
36
+ return { message: 'ok' };
37
+ });
38
+ routeCount++;
39
+ logger.debug(`Mock route: ${endpoint.method} ${fullPath}`);
40
+ }
41
+ }
42
+ return routeCount;
43
+ }
44
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/mocks/router.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C;;;GAGG;AACH,SAAS,aAAa,CAAC,UAAkB,EAAE,MAAc;IACvD,OAAO,MAAM,GAAG,UAAU,CAAC;AAC7B,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAwB,EACxB,OAAe,EACf,SAAiB,EAAE;IAEnB,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAE9C,KAAK,MAAM,QAAQ,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;YACrC,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACtD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,WAAW,EAK/B,CAAC;YAEZ,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;gBACnC,yBAAyB;gBACzB,MAAM,aAAa,GACjB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC;gBACzE,MAAM,cAAc,GAAG,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;gBAExD,IAAI,cAAc,EAAE,CAAC;oBACnB,OAAO,gBAAgB,CAAC,cAAc,CAAC,CAAC;gBAC1C,CAAC;gBAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC3B,CAAC,CAAC,CAAC;YAEH,UAAU,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,eAAe,QAAQ,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Mock Server — Fastify 服务
3
+ *
4
+ * 根据 JSON Schema 文档提供 mock API 响应
5
+ */
6
+ import type { FastifyInstance } from 'fastify';
7
+ export interface MockServerOptions {
8
+ port: number;
9
+ host?: string;
10
+ docsDir: string;
11
+ silent?: boolean;
12
+ }
13
+ export interface MockServerHandle {
14
+ app: FastifyInstance;
15
+ host: string;
16
+ port: number;
17
+ routeCount: number;
18
+ close: () => Promise<void>;
19
+ }
20
+ export declare function startMockServer(options: MockServerOptions): Promise<MockServerHandle>;
21
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mocks/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAK/C,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,eAAe,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA+B3F"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Mock Server — Fastify 服务
3
+ *
4
+ * 根据 JSON Schema 文档提供 mock API 响应
5
+ */
6
+ import Fastify from 'fastify';
7
+ import fastifyCors from '@fastify/cors';
8
+ import { registerMockRoutes } from './router.js';
9
+ import { logger } from '../shared/logger.js';
10
+ export async function startMockServer(options) {
11
+ const { port, host = '0.0.0.0', docsDir, silent = false } = options;
12
+ const app = Fastify({ logger: false });
13
+ // CORS
14
+ await app.register(fastifyCors, { origin: true });
15
+ // 注册 mock 路由 (无前缀,独立服务)
16
+ const routeCount = await registerMockRoutes(app, docsDir);
17
+ if (!silent && routeCount === 0) {
18
+ logger.warn('No schema files found. Mock server has no routes.');
19
+ logger.info('Use "loom chat" to generate schema files first.');
20
+ }
21
+ await app.listen({ port, host });
22
+ if (!silent) {
23
+ logger.success(`Mock Server running at http://localhost:${port}`);
24
+ logger.info(`${routeCount} mock routes registered from: ${docsDir}`);
25
+ }
26
+ return {
27
+ app,
28
+ host,
29
+ port,
30
+ routeCount,
31
+ close: async () => {
32
+ await app.close();
33
+ },
34
+ };
35
+ }
36
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mocks/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAiB7C,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAA0B;IAC9D,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAEpE,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAEvC,OAAO;IACP,MAAM,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAElD,wBAAwB;IACxB,MAAM,UAAU,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAE1D,IAAI,CAAC,MAAM,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;QACjE,MAAM,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,CAAC,OAAO,CAAC,2CAA2C,IAAI,EAAE,CAAC,CAAC;QAClE,MAAM,CAAC,IAAI,CAAC,GAAG,UAAU,iCAAiC,OAAO,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,OAAO;QACL,GAAG;QACH,IAAI;QACJ,IAAI;QACJ,UAAU;QACV,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Serve — 合并的 Web Viewer + Mock Server
3
+ *
4
+ * loom serve 命令启动的服务,同一个端口提供:
5
+ * - / → Web Viewer 前端页面
6
+ * - /api/docs → 文档 API
7
+ * - /api/schemas→ Schema API
8
+ * - /api/entities → Entity API
9
+ * - /mock/* → Mock 服务
10
+ */
11
+ export interface ServeOptions {
12
+ port: number;
13
+ host?: string;
14
+ docsDir: string;
15
+ }
16
+ export declare function startServe(options: ServeOptions): Promise<void>;
17
+ //# sourceMappingURL=serve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAeH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA0CrE"}
package/dist/serve.js ADDED
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Serve — 合并的 Web Viewer + Mock Server
3
+ *
4
+ * loom serve 命令启动的服务,同一个端口提供:
5
+ * - / → Web Viewer 前端页面
6
+ * - /api/docs → 文档 API
7
+ * - /api/schemas→ Schema API
8
+ * - /api/entities → Entity API
9
+ * - /mock/* → Mock 服务
10
+ */
11
+ import Fastify from 'fastify';
12
+ import fastifyStatic from '@fastify/static';
13
+ import fastifyCors from '@fastify/cors';
14
+ import path from 'node:path';
15
+ import { fileURLToPath } from 'node:url';
16
+ import { schemaRoutes } from './view/routes/schema.js';
17
+ import { docsRoutes } from './view/routes/docs.js';
18
+ import { entityRoutes } from './view/routes/entities.js';
19
+ import { registerMockRoutes } from './mocks/router.js';
20
+ import { logger } from './shared/logger.js';
21
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
22
+ export async function startServe(options) {
23
+ const { port, host = '0.0.0.0', docsDir } = options;
24
+ const app = Fastify({ logger: false });
25
+ // CORS
26
+ await app.register(fastifyCors, { origin: true });
27
+ // 静态文件 (前端页面)
28
+ await app.register(fastifyStatic, {
29
+ root: path.join(__dirname, 'view', 'public'),
30
+ prefix: '/',
31
+ });
32
+ // Web Viewer API 路由
33
+ await app.register(schemaRoutes, { docsDir });
34
+ await app.register(docsRoutes, { docsDir });
35
+ await app.register(entityRoutes, { docsDir });
36
+ // Mock 路由 (带 /mock 前缀)
37
+ const routeCount = await registerMockRoutes(app, docsDir, '/mock');
38
+ // SPA fallback: BrowserRouter 刷新子路径时统一回退到 index.html
39
+ app.setNotFoundHandler((request, reply) => {
40
+ const requestPath = request.url.split('?')[0] || '/';
41
+ const isApiPath = requestPath === '/api' || requestPath.startsWith('/api/');
42
+ const isMockPath = requestPath === '/mock' || requestPath.startsWith('/mock/');
43
+ const isNavigationRequest = request.method === 'GET' || request.method === 'HEAD';
44
+ if (isNavigationRequest && !isApiPath && !isMockPath) {
45
+ return reply.type('text/html').sendFile('index.html');
46
+ }
47
+ return reply.code(404).send({ message: 'Not Found' });
48
+ });
49
+ await app.listen({ port, host });
50
+ logger.success(`Loom Server running at http://localhost:${port}`);
51
+ logger.info(` Web Viewer: http://localhost:${port}/`);
52
+ logger.info(` Mock Server: http://localhost:${port}/mock/...`);
53
+ logger.info(` ${routeCount} mock routes registered`);
54
+ logger.info(` Serving docs from: ${docsDir}`);
55
+ }
56
+ //# sourceMappingURL=serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { LoomConfig } from './types.js';
2
+ /**
3
+ * Ensure chat command has a usable config file.
4
+ * Missing/invalid API key triggers an interactive setup wizard.
5
+ */
6
+ export declare function ensureChatConfig(projectDir?: string): Promise<LoomConfig>;
7
+ //# sourceMappingURL=config-wizard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-wizard.d.ts","sourceRoot":"","sources":["../../src/shared/config-wizard.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAgF7C;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAoB/E"}
@@ -0,0 +1,84 @@
1
+ import { createInterface } from 'node:readline/promises';
2
+ import { stdin as input, stdout as output } from 'node:process';
3
+ import path from 'node:path';
4
+ import { DEFAULT_CONFIG, getConfigPath, loadConfig, readRawConfig, writeConfig, } from './config.js';
5
+ import { logger } from './logger.js';
6
+ function isPlaceholderValue(value) {
7
+ if (!value)
8
+ return false;
9
+ return /^\$\{[^}]+\}$/.test(value.trim());
10
+ }
11
+ async function promptWithDefault(rl, label, defaultValue) {
12
+ const answer = (await rl.question(`${label} (${defaultValue}): `)).trim();
13
+ return answer || defaultValue;
14
+ }
15
+ async function promptRequired(rl, label) {
16
+ while (true) {
17
+ const answer = (await rl.question(`${label}: `)).trim();
18
+ if (answer)
19
+ return answer;
20
+ logger.warn('This field is required.');
21
+ }
22
+ }
23
+ function shouldRunWizard(config, rawConfig) {
24
+ if (rawConfig === null)
25
+ return true;
26
+ if (!config.llm.apiKey)
27
+ return true;
28
+ if (isPlaceholderValue(config.llm.apiKey))
29
+ return true;
30
+ return false;
31
+ }
32
+ async function runWizard(projectDir, baseConfig) {
33
+ if (!input.isTTY || !output.isTTY) {
34
+ throw new Error('Missing required config for chat and no interactive terminal available. ' +
35
+ `Please create ${path.basename(getConfigPath(projectDir))} with llm.apiKey.`);
36
+ }
37
+ const rl = createInterface({ input, output });
38
+ logger.info('Let us set up loom.config.json for chat.');
39
+ logger.info('Press Enter to accept a default value.');
40
+ try {
41
+ const provider = await promptWithDefault(rl, 'LLM provider', 'deepseek');
42
+ const model = await promptWithDefault(rl, 'Model', 'deepseek-chat');
43
+ const baseURL = await promptWithDefault(rl, 'Base URL', 'https://api.deepseek.com/v1');
44
+ const apiKey = await promptRequired(rl, 'API Key');
45
+ const finalConfig = {
46
+ ...baseConfig,
47
+ llm: {
48
+ ...baseConfig.llm,
49
+ provider,
50
+ model,
51
+ baseURL,
52
+ apiKey,
53
+ },
54
+ };
55
+ writeConfig(projectDir, finalConfig);
56
+ logger.success(`Saved config to ${getConfigPath(projectDir)}`);
57
+ return finalConfig;
58
+ }
59
+ finally {
60
+ rl.close();
61
+ }
62
+ }
63
+ /**
64
+ * Ensure chat command has a usable config file.
65
+ * Missing/invalid API key triggers an interactive setup wizard.
66
+ */
67
+ export async function ensureChatConfig(projectDir) {
68
+ let rawConfig;
69
+ let parseError = false;
70
+ try {
71
+ rawConfig = readRawConfig(projectDir);
72
+ }
73
+ catch (err) {
74
+ logger.warn(`Failed to parse ${path.basename(getConfigPath(projectDir))}: ${err instanceof Error ? err.message : String(err)}`);
75
+ rawConfig = null;
76
+ parseError = true;
77
+ }
78
+ const config = parseError ? DEFAULT_CONFIG : loadConfig(projectDir);
79
+ if (!shouldRunWizard(config, rawConfig)) {
80
+ return config;
81
+ }
82
+ return runWizard(projectDir, config);
83
+ }
84
+ //# sourceMappingURL=config-wizard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-wizard.js","sourceRoot":"","sources":["../../src/shared/config-wizard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * 全局配置加载
3
+ *
4
+ * 优先级: CLI 参数 > loom.config.json > 默认值
5
+ */
6
+ import type { LoomConfig } from './types.js';
7
+ /** 默认配置 */
8
+ export declare const DEFAULT_CONFIG: LoomConfig;
9
+ /** 配置文件名 */
10
+ export declare const CONFIG_FILENAME = "loom.config.json";
11
+ export declare function getConfigPath(projectDir?: string): string;
12
+ /**
13
+ * 读取配置文件 (仅文件内容,不做默认值合并)
14
+ *
15
+ * @returns null 表示文件不存在
16
+ * @throws JSON 解析异常
17
+ */
18
+ export declare function readRawConfig(projectDir?: string): Partial<LoomConfig> | null;
19
+ /**
20
+ * 将配置写回 loom.config.json
21
+ */
22
+ export declare function writeConfig(projectDir: string | undefined, config: LoomConfig): void;
23
+ /**
24
+ * 从目标项目目录加载配置
25
+ * @param projectDir 目标项目根目录 (默认 process.cwd())
26
+ */
27
+ export declare function loadConfig(projectDir?: string): LoomConfig;
28
+ /**
29
+ * 获取 schema 文件输出的绝对路径
30
+ */
31
+ export declare function getOutDir(config: LoomConfig, projectDir?: string): string;
32
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,WAAW;AACX,eAAO,MAAM,cAAc,EAAE,UAa5B,CAAC;AAEF,YAAY;AACZ,eAAO,MAAM,eAAe,qBAAqB,CAAC;AAElD,wBAAgB,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,CAQ7E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAGpF;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,UAAU,CAK1D;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAGzE"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * 全局配置加载
3
+ *
4
+ * 优先级: CLI 参数 > loom.config.json > 默认值
5
+ */
6
+ import path from 'node:path';
7
+ import fs from 'node:fs';
8
+ /** 默认配置 */
9
+ export const DEFAULT_CONFIG = {
10
+ outDir: 'docs',
11
+ llm: {
12
+ provider: 'deepseek',
13
+ model: 'deepseek-chat',
14
+ baseURL: 'https://api.deepseek.com/v1',
15
+ },
16
+ serve: {
17
+ port: 3000,
18
+ },
19
+ mock: {
20
+ port: 3001,
21
+ },
22
+ };
23
+ /** 配置文件名 */
24
+ export const CONFIG_FILENAME = 'loom.config.json';
25
+ export function getConfigPath(projectDir) {
26
+ const dir = projectDir || process.cwd();
27
+ return path.resolve(dir, CONFIG_FILENAME);
28
+ }
29
+ /**
30
+ * 读取配置文件 (仅文件内容,不做默认值合并)
31
+ *
32
+ * @returns null 表示文件不存在
33
+ * @throws JSON 解析异常
34
+ */
35
+ export function readRawConfig(projectDir) {
36
+ const configPath = getConfigPath(projectDir);
37
+ if (!fs.existsSync(configPath)) {
38
+ return null;
39
+ }
40
+ const raw = fs.readFileSync(configPath, 'utf-8');
41
+ return JSON.parse(raw);
42
+ }
43
+ /**
44
+ * 将配置写回 loom.config.json
45
+ */
46
+ export function writeConfig(projectDir, config) {
47
+ const configPath = getConfigPath(projectDir);
48
+ fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`, 'utf-8');
49
+ }
50
+ /**
51
+ * 从目标项目目录加载配置
52
+ * @param projectDir 目标项目根目录 (默认 process.cwd())
53
+ */
54
+ export function loadConfig(projectDir) {
55
+ const fileConfig = readRawConfig(projectDir) ?? {};
56
+ // 深度合并: 默认值 + 文件配置
57
+ return mergeConfig(DEFAULT_CONFIG, fileConfig);
58
+ }
59
+ /**
60
+ * 获取 schema 文件输出的绝对路径
61
+ */
62
+ export function getOutDir(config, projectDir) {
63
+ const dir = projectDir || process.cwd();
64
+ return path.resolve(dir, config.outDir);
65
+ }
66
+ /**
67
+ * 深度合并配置
68
+ */
69
+ function mergeConfig(defaults, overrides) {
70
+ return {
71
+ outDir: overrides.outDir ?? defaults.outDir,
72
+ llm: { ...defaults.llm, ...overrides.llm },
73
+ serve: { ...defaults.serve, ...overrides.serve },
74
+ mock: { ...defaults.mock, ...overrides.mock },
75
+ };
76
+ }
77
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAGzB,WAAW;AACX,MAAM,CAAC,MAAM,cAAc,GAAe;IACxC,MAAM,EAAE,MAAM;IACd,GAAG,EAAE;QACH,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,eAAe;QACtB,OAAO,EAAE,6BAA6B;KACvC;IACD,KAAK,EAAE;QACL,IAAI,EAAE,IAAI;KACX;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,IAAI;KACX;CACF,CAAC;AAEF,YAAY;AACZ,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,CAAC;AAElD,MAAM,UAAU,aAAa,CAAC,UAAmB;IAC/C,MAAM,GAAG,GAAG,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACxC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,UAAmB;IAC/C,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IAC7C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACjD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAwB,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,UAA8B,EAAE,MAAkB;IAC5E,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IAC7C,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAChF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,UAAmB;IAC5C,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IAEnD,mBAAmB;IACnB,OAAO,WAAW,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,MAAkB,EAAE,UAAmB;IAC/D,MAAM,GAAG,GAAG,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACxC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAClB,QAAoB,EACpB,SAA8B;IAE9B,OAAO;QACL,MAAM,EAAE,SAAS,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM;QAC3C,GAAG,EAAE,EAAE,GAAG,QAAQ,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,EAAE;QAC1C,KAAK,EAAE,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE,GAAG,SAAS,CAAC,KAAK,EAAE;QAChD,IAAI,EAAE,EAAE,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,SAAS,CAAC,IAAI,EAAE;KAC9C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * 实体文件与实体引用工具
3
+ */
4
+ import type { EntityDocument, EntityFileMeta, EntityRefConfig } from './types.js';
5
+ export declare const ENTITY_DIRNAME = "entities";
6
+ export declare const ENTITY_FILENAME_SUFFIX = ".entity.schema.json";
7
+ export declare function getEntitiesDir(outDir: string): string;
8
+ export declare function toEntityFilename(entityName: string): string;
9
+ export declare function isValidEntityDocument(obj: unknown): obj is EntityDocument;
10
+ export declare function listEntityFiles(outDir: string): EntityFileMeta[];
11
+ export declare function readEntityFile(outDir: string, filename: string): EntityDocument;
12
+ export declare function writeEntityFile(outDir: string, filename: string, doc: EntityDocument): void;
13
+ /**
14
+ * 根据实体名或文件名解析到真实文件名
15
+ */
16
+ export declare function resolveEntityFilename(outDir: string, nameOrFilename: string): string | null;
17
+ /**
18
+ * 解析 x-entity-ref:
19
+ * - "User"
20
+ * - { "entity": "User", "pick": ["id", "name"] }
21
+ */
22
+ export declare function parseEntityRefConfig(raw: unknown): EntityRefConfig | null;
23
+ /**
24
+ * 根据实体和 ref 配置,生成引用后的 schema 片段
25
+ */
26
+ export declare function resolveEntitySchemaByRef(entity: EntityDocument, ref: EntityRefConfig): {
27
+ schema: Record<string, unknown>;
28
+ fields: string[];
29
+ };
30
+ //# sourceMappingURL=entity-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-utils.d.ts","sourceRoot":"","sources":["../../src/shared/entity-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElF,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,sBAAsB,wBAAwB,CAAC;AAe5D,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAM3D;AAOD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,cAAc,CAYzE;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,EAAE,CA6BhE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,CAG/E;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CAO3F;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsB3F;AAYD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAwCzE;AAgBD;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE,eAAe,GACnB;IAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAkDvD"}