@downcity/city 0.2.17

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 (142) hide show
  1. package/README.md +182 -0
  2. package/bin/core/auth/authenticator.d.ts +79 -0
  3. package/bin/core/auth/authenticator.d.ts.map +1 -0
  4. package/bin/core/auth/authenticator.js +125 -0
  5. package/bin/core/auth/authenticator.js.map +1 -0
  6. package/bin/core/auth/token-signer.d.ts +27 -0
  7. package/bin/core/auth/token-signer.d.ts.map +1 -0
  8. package/bin/core/auth/token-signer.js +116 -0
  9. package/bin/core/auth/token-signer.js.map +1 -0
  10. package/bin/core/auth/types.d.ts +94 -0
  11. package/bin/core/auth/types.d.ts.map +1 -0
  12. package/bin/core/auth/types.js +7 -0
  13. package/bin/core/auth/types.js.map +1 -0
  14. package/bin/core/base/base-env-catalog.d.ts +13 -0
  15. package/bin/core/base/base-env-catalog.d.ts.map +1 -0
  16. package/bin/core/base/base-env-catalog.js +85 -0
  17. package/bin/core/base/base-env-catalog.js.map +1 -0
  18. package/bin/core/base/base-init.d.ts +48 -0
  19. package/bin/core/base/base-init.d.ts.map +1 -0
  20. package/bin/core/base/base-init.js +105 -0
  21. package/bin/core/base/base-init.js.map +1 -0
  22. package/bin/core/base/base-instruction.d.ts +11 -0
  23. package/bin/core/base/base-instruction.d.ts.map +1 -0
  24. package/bin/core/base/base-instruction.js +37 -0
  25. package/bin/core/base/base-instruction.js.map +1 -0
  26. package/bin/core/base/base-router.d.ts +41 -0
  27. package/bin/core/base/base-router.d.ts.map +1 -0
  28. package/bin/core/base/base-router.js +222 -0
  29. package/bin/core/base/base-router.js.map +1 -0
  30. package/bin/core/base/base-runtime.d.ts +13 -0
  31. package/bin/core/base/base-runtime.d.ts.map +1 -0
  32. package/bin/core/base/base-runtime.js +116 -0
  33. package/bin/core/base/base-runtime.js.map +1 -0
  34. package/bin/core/base/base.d.ts +82 -0
  35. package/bin/core/base/base.d.ts.map +1 -0
  36. package/bin/core/base/base.js +156 -0
  37. package/bin/core/base/base.js.map +1 -0
  38. package/bin/core/runtime.d.ts +120 -0
  39. package/bin/core/runtime.d.ts.map +1 -0
  40. package/bin/core/runtime.js +13 -0
  41. package/bin/core/runtime.js.map +1 -0
  42. package/bin/core/types.d.ts +60 -0
  43. package/bin/core/types.d.ts.map +1 -0
  44. package/bin/core/types.js +7 -0
  45. package/bin/core/types.js.map +1 -0
  46. package/bin/index.d.ts +33 -0
  47. package/bin/index.d.ts.map +1 -0
  48. package/bin/index.js +37 -0
  49. package/bin/index.js.map +1 -0
  50. package/bin/service/action.d.ts +44 -0
  51. package/bin/service/action.d.ts.map +1 -0
  52. package/bin/service/action.js +48 -0
  53. package/bin/service/action.js.map +1 -0
  54. package/bin/service/ai/ai-service.d.ts +56 -0
  55. package/bin/service/ai/ai-service.d.ts.map +1 -0
  56. package/bin/service/ai/ai-service.js +262 -0
  57. package/bin/service/ai/ai-service.js.map +1 -0
  58. package/bin/service/ai/openai-compatible-provider.d.ts +54 -0
  59. package/bin/service/ai/openai-compatible-provider.d.ts.map +1 -0
  60. package/bin/service/ai/openai-compatible-provider.js +175 -0
  61. package/bin/service/ai/openai-compatible-provider.js.map +1 -0
  62. package/bin/service/ai/provider.d.ts +43 -0
  63. package/bin/service/ai/provider.d.ts.map +1 -0
  64. package/bin/service/ai/provider.js +50 -0
  65. package/bin/service/ai/provider.js.map +1 -0
  66. package/bin/service/ai/types.d.ts +94 -0
  67. package/bin/service/ai/types.d.ts.map +1 -0
  68. package/bin/service/ai/types.js +7 -0
  69. package/bin/service/ai/types.js.map +1 -0
  70. package/bin/service/env/env-service.d.ts +12 -0
  71. package/bin/service/env/env-service.d.ts.map +1 -0
  72. package/bin/service/env/env-service.js +39 -0
  73. package/bin/service/env/env-service.js.map +1 -0
  74. package/bin/service/env/env-store.d.ts +15 -0
  75. package/bin/service/env/env-store.d.ts.map +1 -0
  76. package/bin/service/env/env-store.js +35 -0
  77. package/bin/service/env/env-store.js.map +1 -0
  78. package/bin/service/env/schema.d.ts +171 -0
  79. package/bin/service/env/schema.d.ts.map +1 -0
  80. package/bin/service/env/schema.js +52 -0
  81. package/bin/service/env/schema.js.map +1 -0
  82. package/bin/service/env/types.d.ts +79 -0
  83. package/bin/service/env/types.d.ts.map +1 -0
  84. package/bin/service/env/types.js +8 -0
  85. package/bin/service/env/types.js.map +1 -0
  86. package/bin/service/hook.d.ts +23 -0
  87. package/bin/service/hook.d.ts.map +1 -0
  88. package/bin/service/hook.js +49 -0
  89. package/bin/service/hook.js.map +1 -0
  90. package/bin/service/installable-service.d.ts +75 -0
  91. package/bin/service/installable-service.d.ts.map +1 -0
  92. package/bin/service/installable-service.js +89 -0
  93. package/bin/service/installable-service.js.map +1 -0
  94. package/bin/service/instruction.d.ts +106 -0
  95. package/bin/service/instruction.d.ts.map +1 -0
  96. package/bin/service/instruction.js +70 -0
  97. package/bin/service/instruction.js.map +1 -0
  98. package/bin/service/service.d.ts +140 -0
  99. package/bin/service/service.d.ts.map +1 -0
  100. package/bin/service/service.js +94 -0
  101. package/bin/service/service.js.map +1 -0
  102. package/bin/service/studios/schema.d.ts +207 -0
  103. package/bin/service/studios/schema.d.ts.map +1 -0
  104. package/bin/service/studios/schema.js +60 -0
  105. package/bin/service/studios/schema.js.map +1 -0
  106. package/bin/service/studios/studio-store.d.ts +17 -0
  107. package/bin/service/studios/studio-store.d.ts.map +1 -0
  108. package/bin/service/studios/studio-store.js +49 -0
  109. package/bin/service/studios/studio-store.js.map +1 -0
  110. package/bin/service/studios/studios-service.d.ts +15 -0
  111. package/bin/service/studios/studios-service.d.ts.map +1 -0
  112. package/bin/service/studios/studios-service.js +51 -0
  113. package/bin/service/studios/studios-service.js.map +1 -0
  114. package/bin/service/studios/types.d.ts +51 -0
  115. package/bin/service/studios/types.d.ts.map +1 -0
  116. package/bin/service/studios/types.js +7 -0
  117. package/bin/service/studios/types.js.map +1 -0
  118. package/bin/service/types.d.ts +11 -0
  119. package/bin/service/types.d.ts.map +1 -0
  120. package/bin/service/types.js +5 -0
  121. package/bin/service/types.js.map +1 -0
  122. package/bin/store/db.d.ts +61 -0
  123. package/bin/store/db.d.ts.map +1 -0
  124. package/bin/store/db.js +29 -0
  125. package/bin/store/db.js.map +1 -0
  126. package/bin/store/table-api.d.ts +42 -0
  127. package/bin/store/table-api.d.ts.map +1 -0
  128. package/bin/store/table-api.js +100 -0
  129. package/bin/store/table-api.js.map +1 -0
  130. package/bin/store/types.d.ts +14 -0
  131. package/bin/store/types.d.ts.map +1 -0
  132. package/bin/store/types.js +7 -0
  133. package/bin/store/types.js.map +1 -0
  134. package/bin/utils/helpers.d.ts +101 -0
  135. package/bin/utils/helpers.d.ts.map +1 -0
  136. package/bin/utils/helpers.js +192 -0
  137. package/bin/utils/helpers.js.map +1 -0
  138. package/bin/utils/validation.d.ts +18 -0
  139. package/bin/utils/validation.d.ts.map +1 -0
  140. package/bin/utils/validation.js +28 -0
  141. package/bin/utils/validation.js.map +1 -0
  142. package/package.json +55 -0
@@ -0,0 +1,85 @@
1
+ /**
2
+ * City env requirement 聚合模块。
3
+ *
4
+ * 负责把 service.env 与 AI 模型 env requirement 汇总成统一目录。
5
+ */
6
+ import { AIService } from "../../service/ai/ai-service.js";
7
+ /**
8
+ * 聚合当前 City 暴露的 env requirement。
9
+ */
10
+ export function collect_city_env_catalog(services, env_provider) {
11
+ const scopes = [];
12
+ for (const service of services) {
13
+ if ((service.env?.length ?? 0) === 0)
14
+ continue;
15
+ scopes.push({
16
+ id: service.id,
17
+ name: service.name,
18
+ env: service.env.map((item) => ({
19
+ key: item.key,
20
+ description: item.description,
21
+ required: item.required,
22
+ configured: Boolean(env_provider.get(item.key)),
23
+ value_preview: preview_env_value(env_provider.get(item.key)),
24
+ })),
25
+ });
26
+ }
27
+ const ai_scope = collect_ai_model_env_catalog(services, env_provider);
28
+ if (ai_scope)
29
+ scopes.push(ai_scope);
30
+ return scopes;
31
+ }
32
+ /**
33
+ * 聚合 AI 模型的 env requirement。
34
+ */
35
+ function collect_ai_model_env_catalog(services, env_provider) {
36
+ const aggregated = new Map();
37
+ for (const service of services) {
38
+ if (!(service instanceof AIService))
39
+ continue;
40
+ const models = AIService.listModels(service, {
41
+ env: () => undefined,
42
+ identity: "admin",
43
+ });
44
+ for (const model of models) {
45
+ for (const item of model.env_requirements ?? []) {
46
+ const current = aggregated.get(item.key);
47
+ if (current) {
48
+ current.models.push(model.name);
49
+ current.required = current.required || item.required;
50
+ continue;
51
+ }
52
+ aggregated.set(item.key, {
53
+ description: item.description,
54
+ required: item.required,
55
+ models: [model.name],
56
+ });
57
+ }
58
+ }
59
+ }
60
+ if (aggregated.size === 0)
61
+ return undefined;
62
+ const env = [...aggregated.entries()].map(([key, item]) => ({
63
+ key,
64
+ description: `${item.description} - used by ${item.models.join(", ")}`,
65
+ required: item.required,
66
+ configured: Boolean(env_provider.get(key)),
67
+ value_preview: preview_env_value(env_provider.get(key)),
68
+ }));
69
+ return {
70
+ id: "ai-models",
71
+ name: "AI Models",
72
+ env,
73
+ };
74
+ }
75
+ /**
76
+ * 生成 env 值预览。
77
+ */
78
+ function preview_env_value(value) {
79
+ if (!value)
80
+ return undefined;
81
+ if (value.length <= 8)
82
+ return value;
83
+ return `${value.slice(0, 6)}...${value.slice(-4)}`;
84
+ }
85
+ //# sourceMappingURL=base-env-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-env-catalog.js","sourceRoot":"","sources":["../../../src/core/base/base-env-catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * City 初始化模块。
3
+ *
4
+ * 负责组装表、执行建表、挂载 env store、初始化 authenticator,
5
+ * 并把 runtime 依赖注入到各个 service。
6
+ */
7
+ import { type CityTableApi } from "../../store/table-api.js";
8
+ import { StudioStore } from "../../service/studios/studio-store.js";
9
+ import { Authenticator } from "../auth/authenticator.js";
10
+ import type { Service } from "../../service/service.js";
11
+ import type { Runtime } from "../runtime.js";
12
+ import type { Database, DbClient } from "../../store/db.js";
13
+ /**
14
+ * City 初始化后的内部状态。
15
+ */
16
+ export interface CityInitState {
17
+ /** 初始化后的 database */
18
+ database: Database;
19
+ /** 初始化后的底层 client */
20
+ client: {
21
+ $client: DbClient;
22
+ };
23
+ /** 所有表 API 映射 */
24
+ table_map: Map<string, CityTableApi>;
25
+ /** studio store */
26
+ studio_store: StudioStore;
27
+ /** 鉴权器 */
28
+ authenticator: Authenticator;
29
+ }
30
+ /**
31
+ * 执行 City 初始化。
32
+ */
33
+ export declare function initialize_city(params: {
34
+ /** runtime 能力 */
35
+ runtime: Runtime;
36
+ /** 已注册服务 */
37
+ services: Service[];
38
+ /** City ready 回调 */
39
+ require_ready: () => Promise<{
40
+ studio: {
41
+ get(id: string): Promise<{
42
+ studio_id: string;
43
+ status: string;
44
+ } | undefined>;
45
+ };
46
+ }>;
47
+ }): Promise<CityInitState>;
48
+ //# sourceMappingURL=base-init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-init.d.ts","sourceRoot":"","sources":["../../../src/core/base/base-init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAqC,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAEhG,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAExD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,qBAAqB;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,qBAAqB;IACrB,MAAM,EAAE;QAAE,OAAO,EAAE,QAAQ,CAAA;KAAE,CAAC;IAC9B,iBAAiB;IACjB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACrC,mBAAmB;IACnB,YAAY,EAAE,WAAW,CAAC;IAC1B,UAAU;IACV,aAAa,EAAE,aAAa,CAAC;CAC9B;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAC5C,iBAAiB;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY;IACZ,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,oBAAoB;IACpB,aAAa,EAAE,MAAM,OAAO,CAAC;QAAE,MAAM,EAAE;YAAE,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;gBAAE,SAAS,EAAE,MAAM,CAAC;gBAAC,MAAM,EAAE,MAAM,CAAA;aAAE,GAAG,SAAS,CAAC,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;CAC3H,GAAG,OAAO,CAAC,aAAa,CAAC,CAuDzB"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * City 初始化模块。
3
+ *
4
+ * 负责组装表、执行建表、挂载 env store、初始化 authenticator,
5
+ * 并把 runtime 依赖注入到各个 service。
6
+ */
7
+ import { executeDDL } from "../../store/db.js";
8
+ import { TableApi, buildCreateUserTableSQL } from "../../store/table-api.js";
9
+ import { EnvStore } from "../../service/env/env-store.js";
10
+ import { StudioStore } from "../../service/studios/studio-store.js";
11
+ import { Authenticator } from "../auth/authenticator.js";
12
+ import { randomSecret } from "../../utils/helpers.js";
13
+ /**
14
+ * 执行 City 初始化。
15
+ */
16
+ export async function initialize_city(params) {
17
+ const { runtime, services, require_ready } = params;
18
+ const { database, client, env, builtinTables } = runtime;
19
+ const user_schema = collect_service_schemas(services);
20
+ const table_map = new Map();
21
+ table_map.set("studios", new TableApi(database, builtinTables.studios));
22
+ table_map.set("env", new TableApi(database, builtinTables.env));
23
+ for (const [name, table] of Object.entries(user_schema)) {
24
+ table_map.set(name, new TableApi(database, table));
25
+ }
26
+ const db_client = { $client: client };
27
+ for (const table of table_map.values()) {
28
+ const ddl = buildCreateUserTableSQL(table.schema);
29
+ if (ddl)
30
+ await executeDDL(db_client, ddl);
31
+ }
32
+ const env_table = table_map.get("env");
33
+ if (!env_table)
34
+ throw new Error("City env table is not initialized");
35
+ const env_store = new EnvStore(env_table);
36
+ await env.attachStore(env_store);
37
+ const studios_table = table_map.get("studios");
38
+ if (!studios_table)
39
+ throw new Error("City studios table is not initialized");
40
+ const studio_store = new StudioStore(studios_table);
41
+ const configured_base_url = env.get("DOWNCITY_CITY_BASE_URL")
42
+ ?? env.get("BETTER_AUTH_URL")
43
+ ?? runtime.baseURL
44
+ ?? "http://localhost";
45
+ await bootstrap_default_keys(env);
46
+ const authenticator = new Authenticator(env, require_ready);
47
+ for (const service of services) {
48
+ service._db = database;
49
+ service._client = db_client;
50
+ service._authenticator = authenticator;
51
+ service._env = env;
52
+ service._studioStore = studio_store;
53
+ service._raw = runtime.raw;
54
+ service._baseURL = configured_base_url ?? runtime.baseURL;
55
+ await service._onInit();
56
+ }
57
+ return {
58
+ database,
59
+ client: db_client,
60
+ table_map,
61
+ studio_store,
62
+ authenticator,
63
+ };
64
+ }
65
+ /**
66
+ * 收集所有 service 声明的业务表。
67
+ */
68
+ function collect_service_schemas(services) {
69
+ const collected = {};
70
+ for (const service of services) {
71
+ const tables = service.tables ?? service.schema;
72
+ if (!tables)
73
+ continue;
74
+ for (const [name, table] of Object.entries(tables)) {
75
+ const scoped_name = `${service.id}.${name}`;
76
+ if (collected[scoped_name]) {
77
+ throw new Error(`Duplicate schema table "${scoped_name}" from services: ${service.id}`);
78
+ }
79
+ collected[scoped_name] = table;
80
+ }
81
+ }
82
+ return collected;
83
+ }
84
+ /**
85
+ * 确保 City 系统级 env key 存在。
86
+ *
87
+ * 关键说明(中文)
88
+ * - 系统密钥也统一走 City env 表托管
89
+ * - 缺失时自动生成,避免宿主环境额外配置负担
90
+ */
91
+ async function bootstrap_default_keys(env) {
92
+ const admin_key = env.get("DOWNCITY_CITY_ADMIN_SECRET_KEY") || `admin_${randomSecret()}`;
93
+ if (!env.get("DOWNCITY_CITY_ADMIN_SECRET_KEY")) {
94
+ await env.upsert({ key: "DOWNCITY_CITY_ADMIN_SECRET_KEY", value: admin_key });
95
+ }
96
+ const token_key = env.get("DOWNCITY_CITY_TOKEN_SIGNING_KEY") || `sign_${randomSecret()}`;
97
+ if (!env.get("DOWNCITY_CITY_TOKEN_SIGNING_KEY")) {
98
+ await env.upsert({ key: "DOWNCITY_CITY_TOKEN_SIGNING_KEY", value: token_key });
99
+ }
100
+ const better_auth_secret = env.get("BETTER_AUTH_SECRET") || `better_auth_${randomSecret()}${randomSecret()}`;
101
+ if (!env.get("BETTER_AUTH_SECRET")) {
102
+ await env.upsert({ key: "BETTER_AUTH_SECRET", value: better_auth_secret });
103
+ }
104
+ }
105
+ //# sourceMappingURL=base-init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-init.js","sourceRoot":"","sources":["../../../src/core/base/base-init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * City instruction 聚合模块。
3
+ *
4
+ * 负责将所有 service 的 instruction 与 action 定义汇总成统一文档。
5
+ */
6
+ import type { Service } from "../../service/service.js";
7
+ /**
8
+ * 聚合 City 的 instruction 文档。
9
+ */
10
+ export declare function build_city_instruction(services: Service[]): Promise<string>;
11
+ //# sourceMappingURL=base-instruction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-instruction.d.ts","sourceRoot":"","sources":["../../../src/core/base/base-instruction.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAExD;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA6BjF"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * City instruction 聚合模块。
3
+ *
4
+ * 负责将所有 service 的 instruction 与 action 定义汇总成统一文档。
5
+ */
6
+ import { formatInstructionDocument, resolveInstruction, } from "../../service/instruction.js";
7
+ /**
8
+ * 聚合 City 的 instruction 文档。
9
+ */
10
+ export async function build_city_instruction(services) {
11
+ const sections = [];
12
+ for (const service of services) {
13
+ const actions = service._listInstructionActions();
14
+ const body = await resolveInstruction(service.instruction, {
15
+ id: service.id,
16
+ name: service.name,
17
+ env: service.env,
18
+ actions,
19
+ });
20
+ sections.push({
21
+ id: service.id,
22
+ name: service.name,
23
+ kind: "service",
24
+ actions,
25
+ env: service.env,
26
+ body,
27
+ });
28
+ }
29
+ return formatInstructionDocument({
30
+ base: {
31
+ builtin_services: ["env", "studios"],
32
+ loaded_modules: sections.map((item) => item.id),
33
+ },
34
+ sections,
35
+ });
36
+ }
37
+ //# sourceMappingURL=base-instruction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-instruction.js","sourceRoot":"","sources":["../../../src/core/base/base-instruction.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,yBAAyB,EACzB,kBAAkB,GAEnB,MAAM,8BAA8B,CAAC;AAGtC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,QAAmB;IAC9D,MAAM,QAAQ,GAAyB,EAAE,CAAC;IAE1C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC;QAClD,MAAM,IAAI,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,WAAW,EAAE;YACzD,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,OAAO;SACR,CAAC,CAAC;QAEH,QAAQ,CAAC,IAAI,CAAC;YACZ,EAAE,EAAE,OAAO,CAAC,EAAE;YACd,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,SAAS;YACf,OAAO;YACP,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,IAAI;SACL,CAAC,CAAC;IACL,CAAC;IAED,OAAO,yBAAyB,CAAC;QAC/B,IAAI,EAAE;YACJ,gBAAgB,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC;YACpC,cAAc,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;SAChD;QACD,QAAQ;KACT,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * City 路由构建模块。
3
+ *
4
+ * 负责把 service/action 暴露为 Hono 路由,并统一处理:
5
+ * - 请求身份解析
6
+ * - ctx 组装
7
+ * - hook 调度
8
+ * - 公共管理接口
9
+ */
10
+ import { Hono } from "hono";
11
+ import type { CityTableApi } from "../../store/table-api.js";
12
+ import type { Service } from "../../service/service.js";
13
+ import type { Authenticator } from "../auth/authenticator.js";
14
+ import type { Runtime } from "../runtime.js";
15
+ import type { RuntimeUser } from "../auth/types.js";
16
+ declare module "hono" {
17
+ interface ContextVariableMap {
18
+ identity?: {
19
+ kind: "guest" | "user" | "admin";
20
+ };
21
+ user?: RuntimeUser;
22
+ studio?: {
23
+ studio_id: string;
24
+ status: string;
25
+ };
26
+ }
27
+ }
28
+ /**
29
+ * 构建 City 对外路由。
30
+ */
31
+ export declare function build_city_router(params: {
32
+ /** runtime 能力 */
33
+ runtime: Runtime;
34
+ /** 已注册服务 */
35
+ services: Service[];
36
+ /** 鉴权器 */
37
+ authenticator: Authenticator;
38
+ /** 表映射 */
39
+ table_map: Map<string, CityTableApi>;
40
+ }): Hono;
41
+ //# sourceMappingURL=base-router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-router.d.ts","sourceRoot":"","sources":["../../../src/core/base/base-router.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAW,MAAM,0BAA0B,CAAC;AAGjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIpD,OAAO,QAAQ,MAAM,CAAC;IACpB,UAAU,kBAAkB;QAC1B,QAAQ,CAAC,EAAE;YAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAA;SAAE,CAAC;QAChD,IAAI,CAAC,EAAE,WAAW,CAAC;QACnB,MAAM,CAAC,EAAE;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;KAChD;CACF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,iBAAiB;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY;IACZ,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU;IACV,aAAa,EAAE,aAAa,CAAC;IAC7B,UAAU;IACV,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACtC,GAAG,IAAI,CA+IP"}
@@ -0,0 +1,222 @@
1
+ /**
2
+ * City 路由构建模块。
3
+ *
4
+ * 负责把 service/action 暴露为 Hono 路由,并统一处理:
5
+ * - 请求身份解析
6
+ * - ctx 组装
7
+ * - hook 调度
8
+ * - 公共管理接口
9
+ */
10
+ import { Hono } from "hono";
11
+ import { InstallableService } from "../../service/installable-service.js";
12
+ import { httpError } from "../../utils/helpers.js";
13
+ import { build_city_instruction } from "./base-instruction.js";
14
+ import { collect_city_env_catalog } from "./base-env-catalog.js";
15
+ /**
16
+ * 构建 City 对外路由。
17
+ */
18
+ export function build_city_router(params) {
19
+ const { runtime, services, authenticator, table_map } = params;
20
+ const app = new Hono();
21
+ app.get("/health", (c) => c.json({
22
+ ok: true,
23
+ name: "downcity",
24
+ checked_at: new Date().toISOString(),
25
+ services: services.map((service) => service.id),
26
+ service_list: services.map((service) => ({ id: service.id, name: service.name })),
27
+ }));
28
+ app.use("/v1/*", async (c, next) => {
29
+ // 关键说明(中文)
30
+ // City env 支持运行时动态更新,因此每次请求前先 refresh,
31
+ // 避免常驻进程读到旧的 provider key 或回调配置。
32
+ await runtime.env.refresh();
33
+ sync_request_origin(services, new URL(c.req.raw.url).origin);
34
+ const result = await authenticator.resolve(c.req.raw);
35
+ c.set("identity", { kind: result.level });
36
+ if (result.user)
37
+ c.set("user", result.user);
38
+ if (result.studio)
39
+ c.set("studio", result.studio);
40
+ await next();
41
+ });
42
+ app.get("/v1/services", (c) => c.json({
43
+ items: services.map((service) => ({
44
+ id: service.id,
45
+ name: service.name,
46
+ env: service.env ?? [],
47
+ })),
48
+ }));
49
+ app.get("/v1/env/catalog", async (c) => {
50
+ try {
51
+ authenticator.authorize({
52
+ level: c.get("identity")?.kind ?? "guest",
53
+ user: c.get("user"),
54
+ studio: c.get("studio"),
55
+ }, ["admin"]);
56
+ return c.json({ items: collect_city_env_catalog(services, runtime.env) });
57
+ }
58
+ catch (error) {
59
+ return build_error_response(error);
60
+ }
61
+ });
62
+ app.get("/v1/city/instruction", async (c) => {
63
+ try {
64
+ authenticator.authorize({
65
+ level: c.get("identity")?.kind ?? "guest",
66
+ user: c.get("user"),
67
+ studio: c.get("studio"),
68
+ }, ["admin"]);
69
+ return new Response(await build_city_instruction(services), {
70
+ status: 200,
71
+ headers: {
72
+ "content-type": "text/plain; charset=utf-8",
73
+ },
74
+ });
75
+ }
76
+ catch (error) {
77
+ return build_error_response(error);
78
+ }
79
+ });
80
+ for (const service of services) {
81
+ for (const def of service._listActionDefs()) {
82
+ const action = def.action;
83
+ const path = `/v1/${encodeURIComponent(service.id)}/${action.id}`;
84
+ const register = def.method === "GET" ? app.get.bind(app) : app.post.bind(app);
85
+ register(path, async (c) => {
86
+ let raw_body;
87
+ const input = def.method === "GET"
88
+ ? search_params_to_object(new URL(c.req.raw.url).searchParams)
89
+ : parse_request_input(raw_body = await c.req.text().catch(() => ""));
90
+ const db = {};
91
+ if (service.tables) {
92
+ for (const name of Object.keys(service.tables)) {
93
+ db[name] = table_map.get(`${service.id}.${name}`);
94
+ }
95
+ }
96
+ const ctx = {
97
+ input,
98
+ locals: {},
99
+ request: c.req.raw,
100
+ raw_body,
101
+ db,
102
+ identity: c.get("identity") ?? { kind: "guest" },
103
+ user: c.get("user"),
104
+ studio: c.get("studio"),
105
+ env: (key) => runtime.env.get(key),
106
+ service: { id: service.id, name: service.name },
107
+ action: { id: action.id },
108
+ started_at: new Date(),
109
+ };
110
+ try {
111
+ authenticator.authorize({
112
+ level: ctx.identity?.kind ?? "guest",
113
+ user: ctx.user,
114
+ studio: ctx.studio,
115
+ }, def.auth);
116
+ ensure_studio_identity_match(ctx);
117
+ for (const hook of global_service_hooks(services)) {
118
+ await hook.runBefore(ctx);
119
+ }
120
+ await action.hook.runBefore(ctx);
121
+ await service.hook.runBefore(ctx);
122
+ const output = await action.run(ctx);
123
+ ctx.output = output;
124
+ ctx.ended_at = new Date();
125
+ await service.hook.runAfter(ctx);
126
+ await action.hook.runAfter(ctx);
127
+ for (const hook of global_service_hooks(services)) {
128
+ await hook.runAfter(ctx);
129
+ }
130
+ if (output instanceof Response)
131
+ return output;
132
+ return c.json(output, 200);
133
+ }
134
+ catch (error) {
135
+ ctx.ended_at = new Date();
136
+ ctx.error = error instanceof Error ? error : new Error(String(error));
137
+ await service.hook.runOnError(ctx);
138
+ await action.hook.runOnError(ctx);
139
+ for (const hook of global_service_hooks(services)) {
140
+ await hook.runOnError(ctx);
141
+ }
142
+ return build_error_response(error);
143
+ }
144
+ });
145
+ }
146
+ }
147
+ return app;
148
+ }
149
+ /**
150
+ * 收集全局 hook。
151
+ */
152
+ function global_service_hooks(services) {
153
+ return services
154
+ .filter((service) => service instanceof InstallableService)
155
+ .map((service) => service.globalHook);
156
+ }
157
+ /**
158
+ * 同步当前请求 origin。
159
+ *
160
+ * 关键说明(中文)
161
+ * - OAuth callback、better-auth baseURL 依赖当前实际入口域名
162
+ * - 这里按请求 origin 实时覆盖,避免多域名场景下生成旧地址
163
+ */
164
+ function sync_request_origin(services, origin) {
165
+ for (const service of services) {
166
+ service._baseURL = origin;
167
+ if (service.auth?.options) {
168
+ service.auth.options.baseURL = origin;
169
+ }
170
+ }
171
+ }
172
+ /**
173
+ * 解析 POST 请求体。
174
+ */
175
+ function parse_request_input(raw_body) {
176
+ if (!raw_body)
177
+ return {};
178
+ try {
179
+ const parsed = JSON.parse(raw_body);
180
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed)
181
+ ? parsed
182
+ : {};
183
+ }
184
+ catch {
185
+ return {};
186
+ }
187
+ }
188
+ /**
189
+ * 将 querystring 转成普通对象。
190
+ */
191
+ function search_params_to_object(search_params) {
192
+ const result = {};
193
+ search_params.forEach((value, key) => {
194
+ result[key] = value;
195
+ });
196
+ return result;
197
+ }
198
+ /**
199
+ * 校验 input.studio_id 与 token 绑定产品一致。
200
+ */
201
+ function ensure_studio_identity_match(ctx) {
202
+ if (ctx.identity?.kind !== "user")
203
+ return;
204
+ const request_studio_id = typeof ctx.input.studio_id === "string"
205
+ ? ctx.input.studio_id.trim()
206
+ : "";
207
+ if (!request_studio_id)
208
+ return;
209
+ const token_studio_id = ctx.studio?.studio_id ?? "";
210
+ if (request_studio_id !== token_studio_id) {
211
+ throw httpError(403, "studio_id does not match the authenticated token");
212
+ }
213
+ }
214
+ /**
215
+ * 统一错误响应。
216
+ */
217
+ function build_error_response(error) {
218
+ const message = error instanceof Error ? error.message : String(error);
219
+ const status = error.statusCode ?? 500;
220
+ return Response.json({ error: { message, type: "server_error" } }, { status: status });
221
+ }
222
+ //# sourceMappingURL=base-router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-router.js","sourceRoot":"","sources":["../../../src/core/base/base-router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * City 组装模块。
3
+ *
4
+ * 负责把用户传入的 Drizzle db 适配成 City 内部 runtime 能力,
5
+ * 并提供默认的数据库 env provider。
6
+ */
7
+ import type { CityOptions } from "../types.js";
8
+ import type { Runtime } from "../runtime.js";
9
+ /**
10
+ * 从 CityOptions 创建 runtime。
11
+ */
12
+ export declare function create_runtime_from_db(options: CityOptions): Runtime;
13
+ //# sourceMappingURL=base-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-runtime.d.ts","sourceRoot":"","sources":["../../../src/core/base/base-runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,KAAK,EAA8B,OAAO,EAAE,MAAM,eAAe,CAAC;AAGzE;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAYpE"}