@tbox.cn/app-toolkit 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.d.ts +47 -16
- package/dist/index.js +9 -9
- package/package.json +2 -2
- package/src/assembly/resolve-key.ts +4 -2
- package/src/assembly/walk-manifests.ts +28 -12
- package/src/core/errors.ts +12 -2
- package/src/dto.ts +10 -5
- package/src/factory.ts +34 -20
- package/src/index.ts +2 -2
- package/src/integrations/predicate.ts +6 -3
- package/src/integrations/read.ts +11 -4
- package/src/integrations/write.ts +10 -5
- package/src/views/service-detail.ts +4 -3
- package/src/views/service-resolutions.ts +124 -28
- package/tests/dev-manifest-catalog.test.ts +39 -1
- package/tests/views.test.ts +266 -31
package/README.md
CHANGED
|
@@ -45,6 +45,6 @@ views/ 视图装配:modules / app / service-detail / service-resolutio
|
|
|
45
45
|
| ③ 发布形态门禁 | `pnpm --filter @tbox.cn/app-toolkit pack --check`(prepack 内建 build,tgz 内即 minified dist) | 打包完整性 |
|
|
46
46
|
| ④ 跨仓 file: tgz 联调 | agtcodingbox 联调(`file:` tgz 消费——真实宿主) | 消费面全链路 |
|
|
47
47
|
|
|
48
|
-
##
|
|
48
|
+
## 能力门控(v7:读求值轴降级 + 写/迁移面 503)
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
**读求值轴**(loadServiceResolutions / loadServiceResolution / include=serviceResolutions):contracts 不可用(未安装 / 无严格面 / 求值面缺席 / OWNERSHIP_BINDING_V6 标记缺席,三条件与 `contractsEvaluable`)→ **200 降级骨架**(`evaluation-unavailable` + N1 指引入 statusMessage + 静态可算字段 module/required/inheritance/instances 声明枚举;机制见 Agent Note evaluation-axis-degrade)。**写方法与迁移面**(write×4 / ensureMockBindings / writeIntegrationsConfig / evaluateIntegrationServices):contracts 不可用 → `AppToolkitError('CONTRACTS_NOT_RESOLVED', 503, contractsNotResolvedMessage 四分支)`。静态方法与 contracts 可用性解耦。门控断言单点 = 工厂边缘(写侧 policy at edge),机制层保持纯函数。
|
package/dist/index.d.ts
CHANGED
|
@@ -1004,7 +1004,8 @@ declare function invalidateContractsResolver(appDir?: string): void;
|
|
|
1004
1004
|
* **code 枚举单源 = 本文件头映射表(additive-only;api.md §5 表与本表同步)**:
|
|
1005
1005
|
* CREDENTIAL_FILE_MISSING #1 error effective credentialRef 引用凭据文件不在场
|
|
1006
1006
|
* CREDENTIAL_TYPE_MISMATCH #2 error 凭据文件 .type 与绑定 credentialType 不一致
|
|
1007
|
-
* SLOT_NOT_DECLARED #3 warning
|
|
1007
|
+
* SLOT_NOT_DECLARED #3 warning 服务槽无消费方声明(拼写/需求方未安装/旧槽位词汇;
|
|
1008
|
+
* v6.1 归属豁免——owned 服务不报)
|
|
1008
1009
|
* SLOT_NOT_CONFIGURED #4 warning 需求方缺口(服务槽未配置)
|
|
1009
1010
|
* INSTANCE_SUPPLY_UNMATCHED #5 error 绑定未命中已装供给(槽级/实例级覆盖)
|
|
1010
1011
|
* IMPL_WITHOUT_PROVIDER #5/#13 error impl-only(implementation 缺 provider 绑定组头)
|
|
@@ -1279,6 +1280,26 @@ interface WalkCatalog {
|
|
|
1279
1280
|
credentialSchema?: string;
|
|
1280
1281
|
}>;
|
|
1281
1282
|
}
|
|
1283
|
+
/** 词汇源条目(via 标记供 doctor 幻影槽判定——config 快照 vs 真源;walkManifests 消费忽略此字段) */
|
|
1284
|
+
interface DiscoveredSlotSource {
|
|
1285
|
+
dir: string;
|
|
1286
|
+
slots: string[];
|
|
1287
|
+
meta: Record<string, SlotMeta>;
|
|
1288
|
+
/** ⓪ config-override(应用级快照/override)|①② package(node_modules 真源)|③ local(候选自身副本) */
|
|
1289
|
+
via: 'config-override' | 'package' | 'local';
|
|
1290
|
+
}
|
|
1291
|
+
/** 契约包发现链(探测四跳——词汇源真实布局全覆盖,B0;跳⓪ v7 新增):
|
|
1292
|
+
* ⓪ <appDir>/config/service-slots.json(应用级 override 层——meta 首声明胜出 = 用户改名
|
|
1293
|
+
* per-service 覆盖;slots 并集 = 无依赖词汇引导快照。CLI seed-once 生成:仅 slots +
|
|
1294
|
+
* $comment 指纹,meta 恒空——真源 meta 恒可穿透,用户手写才生效);
|
|
1295
|
+
* ① <候选>/node_modules/@tbox.cn/<pkg>/service-slots.json(包根)
|
|
1296
|
+
* ② 同包 src/service-slots.json(发布包 src 附带 / 模板 shim 链接)
|
|
1297
|
+
* ③ 候选自身 {service-slots.json, src/service-slots.json}(local/codegen 全量副本——
|
|
1298
|
+
* mall 生成应用主形态,stage rewriteExportsToSrc 展开后永驻 packages/*,不依赖 install)
|
|
1299
|
+
* 词汇覆盖 = Set 并集(跳⓪ 不遮蔽真源新增);meta = 发现序首声明胜出(跳⓪ 最前 = 覆盖权)。
|
|
1300
|
+
* 同包双在场(异常态)root 优先。slots 与 meta 单次解析同产(目录枚举零缓存,F8;
|
|
1301
|
+
* FX-3:文件**内容**经 file-cache)。 */
|
|
1302
|
+
declare function discoverContractPackages(appDir: string, cache?: FileCache): DiscoveredSlotSource[];
|
|
1282
1303
|
/** walkManifests 主体(单次遍历四产物;目录枚举零缓存——每次调用执行) */
|
|
1283
1304
|
declare function walkManifests(appDir: string, cache?: FileCache): WalkManifestsResult;
|
|
1284
1305
|
interface DeclaredModuleInfo {
|
|
@@ -1417,9 +1438,10 @@ declare function pruneIntegrationBindings(appDir: string): Promise<PruneResult>;
|
|
|
1417
1438
|
*/
|
|
1418
1439
|
/** 模块双键解析:id 精确 → 展示名(descriptor.name ?? id)唯一命中 → 404。 */
|
|
1419
1440
|
declare function resolveModuleKey(walk: WalkManifestsResult, key: string): WalkModuleInfo;
|
|
1420
|
-
/** 服务双键解析 → 真实 service id:服务键集(词汇 ∪ demand ∪ 供给足迹 ∪ configuredKeys
|
|
1441
|
+
/** 服务双键解析 → 真实 service id:服务键集(词汇 ∪ demand ∪ 供给足迹 ∪ configuredKeys ∪ 归属)
|
|
1421
1442
|
* 精确命中 → 展示名(slotMeta.name ?? catalog.services[].name)唯一命中 → 404。
|
|
1422
|
-
* configuredKeys = 当前集成配置 services 节键集(调用方注入)。
|
|
1443
|
+
* configuredKeys = 当前集成配置 services 节键集(调用方注入)。
|
|
1444
|
+
* v6.1 += 归属键(walk.ownership——纯归属无词汇/demand/供给的 owns 合法,O6 对称)。 */
|
|
1423
1445
|
declare function resolveServiceKey(walk: WalkManifestsResult, configuredKeys: readonly string[], key: string): string;
|
|
1424
1446
|
|
|
1425
1447
|
/**
|
|
@@ -1730,11 +1752,14 @@ declare class AppToolkitError extends Error {
|
|
|
1730
1752
|
/** CONTRACTS_NOT_RESOLVED message(N1 构建指引——api.md 错误信封示例)。
|
|
1731
1753
|
* P-4:notes 优先——resolver 在全部不可解析路径均已 push 携带操作指引的 notes(导入失败/
|
|
1732
1754
|
* 产物缺失/未安装/<0.9 升级);现行 version===null 分支会把 notes 内细分指引吞成通用文案。
|
|
1733
|
-
*
|
|
1755
|
+
* 分支保留为兜底(防御性——正常路径 notes 恒非空)。
|
|
1756
|
+
* v7:+= ownershipBindingV6 分支(标记门第四分支单源化——写门控 assertContractsUsable 与
|
|
1757
|
+
* 读求值轴降级 statusMessage 共用同一文案;可选参向后兼容)。 */
|
|
1734
1758
|
declare function contractsNotResolvedMessage(contracts: {
|
|
1735
1759
|
version: string | null;
|
|
1736
1760
|
strictValidation: boolean;
|
|
1737
1761
|
notes: readonly string[];
|
|
1762
|
+
ownershipBindingV6?: boolean;
|
|
1738
1763
|
}): string;
|
|
1739
1764
|
|
|
1740
1765
|
/**
|
|
@@ -1748,8 +1773,11 @@ declare function contractsNotResolvedMessage(contracts: {
|
|
|
1748
1773
|
* title 键全量退役(与 manifest name→id/title→name 同一变更);`.title` 消费方
|
|
1749
1774
|
* (外部仓 import type / 运行时读)需同窗迁移。
|
|
1750
1775
|
*/
|
|
1751
|
-
/** contracts 求值五态原样(EffectiveServiceResolution.status
|
|
1752
|
-
|
|
1776
|
+
/** contracts 求值五态原样(EffectiveServiceResolution.status)+ 视图轴降级态
|
|
1777
|
+
* (evaluation-unavailable——toolkit 视图独有,非 contracts 求值产物:contracts 不可用
|
|
1778
|
+
* (未安装/无严格面/v6 标记缺席)时读求值轴不再 503,改投静态骨架 + 本态标记;
|
|
1779
|
+
* 消费方按非 ok 态渲染,statusMessage 携带 N1 分支指引) */
|
|
1780
|
+
type ServiceStatus = 'ok' | 'service-not-configured' | 'instance-not-found' | 'instance-disabled' | 'binding-unresolved' | 'evaluation-unavailable';
|
|
1753
1781
|
/** 四配置层(instance 为 map 字段层) */
|
|
1754
1782
|
type BindingLayer = 'app' | 'module' | 'service' | 'instance';
|
|
1755
1783
|
/** 纯模块清单(无 services——卡片展开走 /modules/:m);provider 家族包不在清单
|
|
@@ -1801,7 +1829,7 @@ interface ModuleDetailView {
|
|
|
1801
1829
|
configEditable: boolean;
|
|
1802
1830
|
/** 本模块 demand(declare.consumes;卡片展开 + 编辑器静态上下文自足) */
|
|
1803
1831
|
services: ServiceDemand[];
|
|
1804
|
-
/** v4.4 D31:include=serviceResolutions 内嵌(demand 服务过滤 ≡ 批量 ?service= 语义;<0.9/形态异常 → null——永不 503) */
|
|
1832
|
+
/** v4.4 D31:include=serviceResolutions 内嵌(v6.1 键集 = owned ∪ demand 服务过滤 ≡ 批量 ?service= 语义;<0.9/形态异常 → null——永不 503) */
|
|
1805
1833
|
serviceResolutions?: ServiceResolutionsView | null;
|
|
1806
1834
|
/** v4.4 D32:include=integrationSchemas 层级富化(零归属/未绑定 → null) */
|
|
1807
1835
|
integrationSchemas?: LayerIntegrationSchemas | null;
|
|
@@ -1899,7 +1927,7 @@ interface ServiceIntegrationSchemas {
|
|
|
1899
1927
|
interface ServiceResolutionsView {
|
|
1900
1928
|
/** P6 contracts echo(仅求值轴两端点携带) */
|
|
1901
1929
|
contracts: ContractsResolution;
|
|
1902
|
-
/** 键集 = 服务词汇 ∪
|
|
1930
|
+
/** 键集 = 服务词汇 ∪ 已配置 ∪ 归属(v6.1 += 归属——owned 服务恒可求值;模块/平台/孤儿全量) */
|
|
1903
1931
|
resolutions: Record<string, ServiceResolutionEntry>;
|
|
1904
1932
|
/** 谓词全量(doctor 同源;恒全量——subset 消费方客户端过滤) */
|
|
1905
1933
|
issues: IntegrationIssue[];
|
|
@@ -1916,7 +1944,8 @@ interface ServiceResolutionEntry {
|
|
|
1916
1944
|
layer?: BindingLayer;
|
|
1917
1945
|
/** provider 在场时在场:(provider, service) ∈ 供给关系 */
|
|
1918
1946
|
supplied?: boolean;
|
|
1919
|
-
/** owner 模块 install id
|
|
1947
|
+
/** owner 模块 install id(v6.1 = walk.ownership 归属单源——install id 轴,与模块清单 id 恒可 join;
|
|
1948
|
+
* 旧实现 demand owners[0] 为包名/@app 轴且漏 owned-not-consumed,已退役);平台服务/孤儿缺席 */
|
|
1920
1949
|
module?: string;
|
|
1921
1950
|
/** demand echo(OR 聚合);平台/孤儿恒 false;集成就绪判定单源(§7) */
|
|
1922
1951
|
required?: boolean;
|
|
@@ -2201,7 +2230,7 @@ declare function loadProviderServiceDetailView(snapshot: ViewSnapshot, provider:
|
|
|
2201
2230
|
|
|
2202
2231
|
/** P14 单源摘要函数:/service-resolutions map 值 ≡ /service-resolutions/:s 的 resolution 摘要基 */
|
|
2203
2232
|
declare function resolveServiceSummary(service: string, snapshot: ViewSnapshot): ServiceResolutionEntry;
|
|
2204
|
-
/** 批量求值(键集 =
|
|
2233
|
+
/** 批量求值(键集 = resolutionKeys 单源:词汇 ∪ 需求侧 ∪ 已配置 ∪ 归属;?service= 过滤语义——未知键缺席;issues 恒全量) */
|
|
2205
2234
|
declare function loadServiceResolutionsView(snapshot: ViewSnapshot, issues: IntegrationIssue[], filter?: string[]): ServiceResolutionsView;
|
|
2206
2235
|
/** 求值单体(完整结构 instances + inheritance + 过滤 issues;P14 extends 结构保证) */
|
|
2207
2236
|
declare function loadServiceResolutionDetail(service: string, snapshot: ViewSnapshot, allIssues: IntegrationIssue[]): ServiceResolutionDetail;
|
|
@@ -2301,11 +2330,13 @@ declare function loadCredentialTypesView(snapshot: ViewSnapshot, provider?: stri
|
|
|
2301
2330
|
* Read+Write = HTTP 直通面 additive 冻结(L1 端点↔方法 1:1,L3 命名镜像:Integration=节点级 /
|
|
2302
2331
|
* Config=文件级);Internals = CLI/doctor/桥消费(自由演进)。
|
|
2303
2332
|
*
|
|
2304
|
-
* **门控断言单点(policy at edge
|
|
2305
|
-
*
|
|
2306
|
-
*
|
|
2307
|
-
*
|
|
2308
|
-
*
|
|
2333
|
+
* **门控断言单点(policy at edge——v7 读求值轴退役后范围 = 写 + 迁移面)**:写(4)+
|
|
2334
|
+
* ensureMockBindings / writeIntegrationsConfig / evaluateIntegrationServices 入口
|
|
2335
|
+
* assertContractsUsable——strictValidation === false → 503 CONTRACTS_NOT_RESOLVED;静态方法不门控
|
|
2336
|
+
* (永不 503——铁律 #3);**读求值轴(loadServiceResolutions/loadServiceResolution 及 include 装配)
|
|
2337
|
+
* v7 起不再 503**——contracts 不可用 → 200 降级骨架(evaluation-unavailable,doctor 分级/D31 先例
|
|
2338
|
+
* 对齐;依据链与裁决见 Agent Note evaluation-axis-degrade);**include 装配为条件分支非门控**
|
|
2339
|
+
* (D31 null 分支退役——三条件门 + 内嵌轴同步降级,四面统一骨架);integrations/ views/ 机制层保持纯函数。
|
|
2309
2340
|
*
|
|
2310
2341
|
* 并发:进程内写串行(per-factory promise chain)+ 原子写 + 写后本实例缓存即刻失效(D26)。
|
|
2311
2342
|
* onApplied(D7):toolkit 判定「需要重启」(实际落盘且非 dryRun/no-diff)→ 调用一次 +
|
|
@@ -2403,4 +2434,4 @@ interface AppToolkitInternals {
|
|
|
2403
2434
|
type AppToolkit = AppToolkitRead & AppToolkitWrite & AppToolkitInternals;
|
|
2404
2435
|
declare function createAppToolkit(appDir: string, options?: AppToolkitOptions): AppToolkit;
|
|
2405
2436
|
|
|
2406
|
-
export { APP_INTEGRATION_NODE_KEYS, type AppIntegrationNode, type AppManifest, type AppManifestFull, type AppToolkit, AppToolkitError, type AppToolkitErrorCode, type AppToolkitInternals, type AppToolkitOptions, type AppToolkitRead, type AppToolkitWrite, type AppView, type AppliedCredential, type BindingLayer, type BridgeProviderCatalog, type CardContrib, type ContractsResolution, type CredentialBindingEcho, type CredentialEcho, type CredentialFile, type CredentialInput, type CredentialTypeEntry, type CredentialTypesView, type CredentialValues, type CredentialsView, type DeclarationIssue, type DeclaredModuleInfo, type EffectiveBinding, type EnvExpansionResult, type EvaluationExports, type FileCache, type InlineVendorDeclaration, type IntegrationFieldRegistryView, type IntegrationIssue, type IntegrationServiceIssue, type IntegrationServicePredicateInput, type LayerIntegrationSchemas, MODULE_INTEGRATION_NODE_KEYS, type MiniappContainerEntry, type MockBindingsResult, type ModuleBinding, type ModuleDeclaration, type ModuleDescriptor, type ModuleDetailView, type ModuleIntegrationNode, type ModuleMode, type ModuleOwnershipWritability, type ModuleResourceEcho, type ModuleResourcesEcho, type ModulesView, type NpmModuleEntry, type OrphanIssue, type ParseModuleResult, type PlannedCredential, type PredicateAssembly, type PredicateContracts, type PredicateIoInputs, type ProviderDetail, type ProviderEntry, type ProviderServiceDetail, type ProviderServiceSchemas, type ProviderServiceSchemasResult, type ProviderSlotContrib, type ProvidersView, type PruneResult, type ReadIntegrationsResult, type ResolvedContracts, type ResolvedInstance, type ResolvedModule, type ResourceNeedContrib, SAFE_NAME_PATTERN, type SaveResult, type ServiceConsumeContrib, type ServiceDemand, type ServiceDetail, type ServiceInstanceNode, type ServiceIntegrationNode, type ServiceIntegrationSchemas, type ServiceOwnContrib, type ServiceResolution, type ServiceResolutionDetail, type ServiceResolutionEntry, type ServiceResolutionsView, type ServiceStatus, type SlotMeta, type StemInput, type SupplyLookup, type ViewContext, type ViewSnapshot, type WalkCatalog, type WalkManifestsResult, type WalkModuleInfo, type WalkProviderEntry, type WriteCore, type WriteCoreOptions, type WriteOptions, assertValidModuleId, buildIntegrationFieldRegistry, buildOwnershipMap, buildPredicateAssembly, checkInstanceKeys, collectDeclaredModules, contractsNotResolvedMessage, createAppToolkit, createFileCache, createWriteCore, credentialArtifactExists, deepEqual, deriveStem, echoForRef, ensureDir, ensureMockBindings, evaluateAppIntegrationIssues, evaluateIntegrationServices, expandEnvVars, extractModuleIdFromSource, formProviderOf, invalidateContractsResolver, isControlledInlineProvider, isValidModuleId, loadAppIntegrationSchemas, loadAppView, loadCredentialTypesView, loadCredentialsView, loadModuleDetailView, loadModuleIntegrationSchemas, loadModulesView, loadProviderCatalog, loadProviderCatalogRaw, loadProviderDetailView, loadProviderServiceDetailView, loadProvidersView, loadServiceDetailView, loadServiceFieldRegistry, loadServiceIntegrationSchemas, loadServiceResolutionDetail, loadServiceResolutionsView, manifestPath, maskCredentialValues, moduleDependencySchema, moduleDescriptorSchema, moduleOwnershipWritable, pageContribSchema, parseModuleDescriptor, providerFootprint, providerSlotContribSchema, pruneIntegrationBindings, readAppManifest, readAppManifestFull, readCredentialFile, readIntegrationsConfig, readIntegrationsStrict, reconcileOrphanCredentials, refToEnvKey, removeNpmModule, resolveContractsForApp, resolveContractsForApp as resolveContractsForAppExport, resolveLayerIntegrationSchemas, resolveModuleBinding, resolveModuleKey, resolveServiceKey, resolveServiceSummary, resourceNeedContribSchema, serviceConsumeContribSchema, serviceOwnContribSchema, stemToFilePath, stemToRef, tabContribSchema, updateNpmModule, upsertMiniappContainer, upsertNpmModule, walkManifests, writeAppManifest, writeAtomic, writeCredentialFile };
|
|
2437
|
+
export { APP_INTEGRATION_NODE_KEYS, type AppIntegrationNode, type AppManifest, type AppManifestFull, type AppToolkit, AppToolkitError, type AppToolkitErrorCode, type AppToolkitInternals, type AppToolkitOptions, type AppToolkitRead, type AppToolkitWrite, type AppView, type AppliedCredential, type BindingLayer, type BridgeProviderCatalog, type CardContrib, type ContractsResolution, type CredentialBindingEcho, type CredentialEcho, type CredentialFile, type CredentialInput, type CredentialTypeEntry, type CredentialTypesView, type CredentialValues, type CredentialsView, type DeclarationIssue, type DeclaredModuleInfo, type DiscoveredSlotSource, type EffectiveBinding, type EnvExpansionResult, type EvaluationExports, type FileCache, type InlineVendorDeclaration, type IntegrationFieldRegistryView, type IntegrationIssue, type IntegrationServiceIssue, type IntegrationServicePredicateInput, type LayerIntegrationSchemas, MODULE_INTEGRATION_NODE_KEYS, type MiniappContainerEntry, type MockBindingsResult, type ModuleBinding, type ModuleDeclaration, type ModuleDescriptor, type ModuleDetailView, type ModuleIntegrationNode, type ModuleMode, type ModuleOwnershipWritability, type ModuleResourceEcho, type ModuleResourcesEcho, type ModulesView, type NpmModuleEntry, type OrphanIssue, type ParseModuleResult, type PlannedCredential, type PredicateAssembly, type PredicateContracts, type PredicateIoInputs, type ProviderDetail, type ProviderEntry, type ProviderServiceDetail, type ProviderServiceSchemas, type ProviderServiceSchemasResult, type ProviderSlotContrib, type ProvidersView, type PruneResult, type ReadIntegrationsResult, type ResolvedContracts, type ResolvedInstance, type ResolvedModule, type ResourceNeedContrib, SAFE_NAME_PATTERN, type SaveResult, type ServiceConsumeContrib, type ServiceDemand, type ServiceDetail, type ServiceInstanceNode, type ServiceIntegrationNode, type ServiceIntegrationSchemas, type ServiceOwnContrib, type ServiceResolution, type ServiceResolutionDetail, type ServiceResolutionEntry, type ServiceResolutionsView, type ServiceStatus, type SlotMeta, type StemInput, type SupplyLookup, type ViewContext, type ViewSnapshot, type WalkCatalog, type WalkManifestsResult, type WalkModuleInfo, type WalkProviderEntry, type WriteCore, type WriteCoreOptions, type WriteOptions, assertValidModuleId, buildIntegrationFieldRegistry, buildOwnershipMap, buildPredicateAssembly, checkInstanceKeys, collectDeclaredModules, contractsNotResolvedMessage, createAppToolkit, createFileCache, createWriteCore, credentialArtifactExists, deepEqual, deriveStem, discoverContractPackages, echoForRef, ensureDir, ensureMockBindings, evaluateAppIntegrationIssues, evaluateIntegrationServices, expandEnvVars, extractModuleIdFromSource, formProviderOf, invalidateContractsResolver, isControlledInlineProvider, isValidModuleId, loadAppIntegrationSchemas, loadAppView, loadCredentialTypesView, loadCredentialsView, loadModuleDetailView, loadModuleIntegrationSchemas, loadModulesView, loadProviderCatalog, loadProviderCatalogRaw, loadProviderDetailView, loadProviderServiceDetailView, loadProvidersView, loadServiceDetailView, loadServiceFieldRegistry, loadServiceIntegrationSchemas, loadServiceResolutionDetail, loadServiceResolutionsView, manifestPath, maskCredentialValues, moduleDependencySchema, moduleDescriptorSchema, moduleOwnershipWritable, pageContribSchema, parseModuleDescriptor, providerFootprint, providerSlotContribSchema, pruneIntegrationBindings, readAppManifest, readAppManifestFull, readCredentialFile, readIntegrationsConfig, readIntegrationsStrict, reconcileOrphanCredentials, refToEnvKey, removeNpmModule, resolveContractsForApp, resolveContractsForApp as resolveContractsForAppExport, resolveLayerIntegrationSchemas, resolveModuleBinding, resolveModuleKey, resolveServiceKey, resolveServiceSummary, resourceNeedContribSchema, serviceConsumeContribSchema, serviceOwnContribSchema, stemToFilePath, stemToRef, tabContribSchema, updateNpmModule, upsertMiniappContainer, upsertNpmModule, walkManifests, writeAppManifest, writeAtomic, writeCredentialFile };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import{a as
|
|
2
|
-
`,"utf8"),i}import{mkdirSync as
|
|
3
|
-
`,"utf8")}function De(e){let n=On(e);if(n===null)return null;let r=ve(e);try{let t=JSON.parse(An(r,"utf8"));return{...n,miniappContainers:Array.isArray(t?.miniappContainers)?t.miniappContainers:[]}}catch{return{...n,miniappContainers:[]}}}function Rt(e,n){let r=e.npmModules.filter(t=>t.id!==n.id);return{...e,npmModules:[...r,n]}}function It(e,n){return{...e,npmModules:e.npmModules.filter(r=>r.id!==n)}}function kt(e,n){let r=(e.miniappContainers??[]).filter(t=>t.id!==n.id);return{...e,miniappContainers:[...r,n]}}function bt(e,n,r){return{...e,npmModules:e.npmModules.map(t=>t.id===n?{...t,...r}:t)}}function Mn(e){return/^[a-z0-9]+(-[a-z0-9]+)*$/.test(e)&&!e.includes("..")}function Ct(e,n){if(!Mn(e))throw new Error(`非法模块 id "${e}"(来自 ${n}):仅允许小写字母/数字/中划线`)}function xn(e){try{let n=JSON.parse(e);if(!Array.isArray(n.slots))return null;let r=n.slots.filter(i=>typeof i=="string"),t={};if(n.meta&&typeof n.meta=="object"&&!Array.isArray(n.meta))for(let[i,s]of Object.entries(n.meta)){if(!s||typeof s!="object"||Array.isArray(s))continue;let{name:o,description:d}=s,p={};typeof o=="string"&&o.length>0&&(p.name=o),typeof d=="string"&&d.length>0&&(p.description=d),(p.name!==void 0||p.description!==void 0)&&(t[i]=p)}return{slots:r,meta:t}}catch{return null}}function ye(e,n){let r=t=>{try{let i=JSON.parse(t),s=oe(i);if(s.ok)return{kind:"strict",id:s.value.id,version:s.value.version,descriptor:s.value,declare:s.value.declare};if(s.legacy)return{kind:"legacy",detail:s.errors.join("; ")};if(i&&typeof i=="object"&&"declare"in i){let o=i;return{kind:"loose",...typeof o.id=="string"?{id:o.id}:{},declare:{providers:o.declare?.providers,consumes:o.declare?.consumes}}}return null}catch{return null}};if(n)return n.read(e,r)??null;if(!F(e))return null;try{return r(X(e,"utf8"))}catch{return null}}function At(e){let n=P(e,".tbox","app.json");if(!F(n))return[];try{let r=JSON.parse(X(n,"utf8"));return Array.isArray(r.npmModules)?r.npmModules.filter(t=>!!t&&typeof t=="object"&&typeof t.id=="string"&&typeof t.package=="string"):[]}catch{return[]}}function Et(e){let n=P(e,".tbox-dev.local"),r=P(n,"dev-manifest.json");if(!F(r))return[];try{let t=JSON.parse(X(r,"utf8")),i=[];for(let[s,o]of Object.entries(t.redirects??{}))typeof o!="string"||!s.startsWith("@tbox.cn/app-")||i.push({pkg:s,dir:P(n,o)});return i}catch{return[]}}function Ot(e,n){let r=[],t=[e];for(let o of["apps","packages"]){let d=P(e,o);if(F(d))try{for(let p of Fe(d,{withFileTypes:!0}))p.isDirectory()&&t.push(P(d,p.name))}catch{}}let i=new Set,s=(o,d)=>{let p=n?n.read(d,xn):xn(X(d,"utf8"));p!=null&&r.push({dir:o,slots:p.slots,meta:p.meta})};for(let o of t){let d=P(o,"node_modules","@tbox.cn");if(!F(d))continue;let p=[];try{p=Fe(d)}catch{continue}for(let c of p){let f=P(d,c);if(i.has(f))continue;i.add(f);let k=P(f,"service-slots.json"),w=P(f,"src","service-slots.json");F(k)?s(f,k):F(w)&&s(f,w)}}for(let o of t)for(let d of[P(o,"service-slots.json"),P(o,"src","service-slots.json")])F(d)&&s(o,d);return r}function V(e,n){let r=[],t={providers:{},services:{},credentialTypes:{}},i={},s=[],o={},d=new Set,p=(a,m,R,S)=>{for(let u of a){let v=t.providers[u.provider]??={},b=v[u.implementation];b?b.services.includes(u.service)||b.services.push(u.service):(v[u.implementation]={provider:u.provider,implementation:u.implementation,credentialType:u.credentialType,owner:m,...S?.name?{name:S.name}:{},...S?.description?{description:S.description}:{},...u.local?{local:!0}:{},...u.configSchema?{configSchema:u.configSchema}:{},...u.credentialSchema?{credentialSchema:u.credentialSchema}:{},services:[u.service]},t.credentialTypes[u.credentialType]??={owner:m,packageDir:R,...u.credentialSchema?{credentialSchema:u.credentialSchema}:{}});let l=`${u.provider}\0${u.service}`;i[l]||(i[l]={...u.configSchema?{configSchema:u.configSchema}:{},...u.credentialSchema?{credentialSchema:u.credentialSchema}:{},packageDir:R})}},c=a=>a.kind==="strict"?{name:a.descriptor.name,description:a.descriptor.description}:void 0,f=(a,m)=>{for(let R of a){let S=o[R];S===void 0?o[R]=m:S!==m&&s.push({severity:"error",code:"OWNERSHIP_CONFLICT",module:m,message:`服务 ${R} 归属冲突:${S} 与 ${m} 均声明 owns(先声明 ${S} 胜出)——修正 manifest declare.owns 互斥`})}},k=(a,m)=>{a.kind==="legacy"&&s.push({severity:"error",code:"OLD_MANIFEST_KEY",module:m,message:`${m}:${a.detail}`})},w=a=>a.kind==="strict"||a.kind==="loose"?a.declare:null,y=(a,m)=>{let R=a.optional!==!1,S=a.defaults??[],u=t.services[a.service];if(u){u.optional=u.optional&&R;let v=new Set(u.defaults.map(b=>`${b.provider}\0${b.implementation}`));for(let b of S){let l=`${b.provider}\0${b.implementation}`;v.has(l)||(u.defaults.push(b),v.add(l))}u.owners.includes(m)||u.owners.push(m);return}t.services[a.service]={optional:R,defaults:[...S],...a.name?{name:a.name}:{},...a.description?{description:a.description}:{},owners:[m]}};for(let a of At(e)){if(d.has(a.id))continue;let m=P(e,"packages",a.id),R=P(e,"node_modules",...a.package.split("/")),S=ye(P(m,"tbox.module.json"),n)??ye(P(R,"tbox.module.json"),n);if(S?.kind==="legacy"){k(S,a.id),d.add(a.id);continue}if(!S)continue;d.add(a.id);let u=F(P(m,"tbox.module.json"))?m:R,v=w(S);S.kind==="strict"&&r.push({id:a.id,dir:u,pkg:a.mode==="sdk"?a.package:`@app/${a.id}`,descriptor:S.descriptor});let b=v?.providers?.slots??[];b.length&&p(b,a.package,u,c(S));let l=v?.consumes??[];for(let E of l)y(E,a.package);let h=S.kind==="strict"?S.descriptor.declare.owns:[];h.length&&f(h.map(E=>E.service),a.id)}for(let{pkg:a,dir:m}of Et(e)){let R=ye(P(m,"tbox.module.json"),n);if(R?.kind==="legacy"){k(R,a);continue}if(!R?.id||d.has(R.id))continue;d.add(R.id);let S=w(R),u=S?.providers?.slots??[];u.length&&p(u,a,m,c(R));let v=S?.consumes??[];for(let l of v)y(l,a);let b=R.kind==="strict"?R.descriptor.declare.owns:[];b.length&&f(b.map(l=>l.service),R.id)}let A=P(e,"packages");if(F(A)){let a=[];try{a=Fe(A,{withFileTypes:!0}).filter(m=>m.isDirectory()).map(m=>m.name)}catch{}for(let m of a){if(d.has(m))continue;let R=P(A,m),S=ye(P(R,"tbox.module.json"),n);if(S?.kind==="legacy"){k(S,m),d.add(m);continue}if(!S)continue;let u=S.id??m;if(d.has(u))continue;d.add(u);let v=w(S);S.kind==="strict"&&r.push({id:u,dir:R,pkg:`@app/${u}`,descriptor:S.descriptor});let b=v?.providers?.slots??[];b.length&&p(b,`@app/${u}`,R,c(S));let l=v?.consumes??[];for(let E of l)y(E,`@app/${u}`);let h=S.kind==="strict"?S.descriptor.declare.owns:[];h.length&&f(h.map(E=>E.service),u)}}let O=new Set,g={};for(let a of Ot(e,n)){for(let m of a.slots)O.add(m);for(let[m,R]of Object.entries(a.meta))g[m]===void 0&&(g[m]=R)}return{modules:r,catalog:t,serviceSchemas:i,vocabulary:[...O].sort(),slotMeta:g,ownership:o,declarationIssues:s}}function jn(e,n,r){let t=P(e,"src",n,"index.ts");if(!F(t))return!1;try{let i=X(t,"utf8");return new RegExp(`export\\s+const\\s+${r}\\b`).test(i)}catch{return!1}}function Mt(e){let n=P(e,"src","server","index.ts");if(!F(n))return"";try{return X(n,"utf8")}catch{return""}}function Tn(e){return e.match(/declaration\s*:\s*\{[\s\S]*?moduleId\s*:\s*['"]([^'"]+)['"]/)?.[1]}function xt(e){let n=[],r=V(e),t=De(e),i=new Map;for(let s of t?.npmModules??[])i.set(s.id,s.mode);for(let s of r.modules){let o=i.get(s.id)??"local",d=jn(s.dir,"server","serverModule"),p=s.descriptor.declare;n.push({id:s.id,pkg:o==="sdk"?s.pkg:`@app/${s.id}`,mode:o,hasServerEntry:d,hasClientEntry:jn(s.dir,"client","clientModule"),hasCards:(p.cards?.length??0)>0,...d?{moduleId:Tn(Mt(s.dir))}:{}})}return n.sort((s,o)=>s.id.localeCompare(o.id))}function jt(e){return V(e).ownership}function L(e,n){let r=e?.modules?.[n]?.provider;if(typeof r=="string"&&r.length>0)return{provider:r,layer:"module"};let t=e?.provider;return typeof t=="string"&&t.length>0?{provider:t,layer:"app"}:{provider:null,layer:null}}function J(e,n){let r=(n.descriptor.declare.owns??[]).map(t=>t.service).sort();return r.length===0?{writable:!1,reason:"zero-ownership",ownedServices:[]}:{writable:!0,ownedServices:r}}function _e(e,n){return[...new Set(Object.values(e.providers[n]??{}).flatMap(r=>r.services))].sort()}function G(e){if(!e||typeof e!="object")return!1;let n=Object.keys(e),r=new Set(["provider","credentialType","configSchema"]);if(!n.every(i=>r.has(i)))return!1;let t=e;return typeof t.provider=="string"&&t.provider.length>0&&typeof t.credentialType=="string"&&t.credentialType.length>0&&(t.configSchema===void 0||typeof t.configSchema=="string")}function Nn(e,n,r){return e==="*"||r.has(e)?null:{severity:"error",code:"INSTANCE_KEY_NOT_REGISTERED",instance:e,message:`integrations: ${n} 键 ${e} 不在 malls 白名单内(${[...r].join(", ")})`}}function $e(e,n){let r=new Set(n),t=[],i=(s,o)=>{let d=Nn(s,o,r);d&&t.push(d)};for(let s of Object.keys(e.configByInstance??{}))i(s,"configByInstance");for(let s of Object.keys(e.credentialRefByInstance??{}))i(s,"credentialRefByInstance");for(let[s,o]of Object.entries(e.services??{}))for(let d of Object.keys(o.instances??{}))i(d,`services.${s}.instances`);return t}function ee(e){let n=[],r=e.contracts,{integrations:t,suppliedProviders:i,demandedServices:s,supplies:o,malls:d,credentialSchemaMissing:p,vendorConfigKeys:c,vendorGlobalConfigKeys:f,vendorConfigSchemaMissing:k,credentialFileMissing:w,credentialFileType:y,realmSwitchHints:A,moduleResourceNeeds:O,ownership:g,installedModuleIds:a}=e,m=d?new Set(d):void 0;for(let l of A??[])n.push({severity:"warning",code:"REALM_SWITCH_HINT",message:l});let R=new Set(Object.keys(i).map(l=>l.slice(0,l.indexOf("\0"))).filter(l=>l.length>0)),S=(l,h,E,C)=>{if(typeof E?.provider=="string"&&typeof E.implementation=="string"&&E.provider&&E.implementation)return i[ae(E.provider,E.implementation)]?.credentialType;if(typeof h.provider=="string"&&typeof h.implementation=="string")return i[ae(h.provider,h.implementation)]?.credentialType;let x=h.provider?.credentialType;if(typeof x=="string")return x;if(!o)return;let N=C??Object.keys(h.instances??{})[0]??"",j=r.resolveEffectiveService(t,l,N,o,g);if(!(j.status!=="ok"||typeof j.effective.provider!="string"))return i[ae(j.effective.provider,j.effective.implementation)]?.credentialType};if(w||y)for(let[l,h]of Object.entries(t.services))for(let[E,C]of Object.entries(h.instances??{})){if(C.enabled===!1)continue;let x=C.credentialRef??h.credentialRef??t.credentialRefByInstance?.[E]??t.credentialRef;if(typeof x!="string"||!x.startsWith("secret://"))continue;let N=x.slice(9);w?.[N]===!0&&n.push({severity:"error",code:"CREDENTIAL_FILE_MISSING",service:l,instance:E,message:`integrations: 凭据文件缺失 ${N}(${l}@${E} effective ref=${x};档内 config/credentials/ 无此文件)`});let j=y?.[N];if(j){let D=S(l,h,C,E);D&&j!==D&&n.push({severity:"error",code:"CREDENTIAL_TYPE_MISMATCH",service:l,instance:E,message:`integrations: 凭据文件 ${N}.json type=${j} 与绑定 credentialType ${D} 不一致(${l}@${E}——transport 创建期将按 type 选策略)`})}}let u=(l,h)=>{if(!m)return;let E=Nn(l,h,m);E&&n.push(E)};for(let[l]of Object.entries(t.configByInstance??{}))u(l,"configByInstance");for(let[l]of Object.entries(t.credentialRefByInstance??{}))u(l,"credentialRefByInstance");let v=Object.entries(t.services).filter(([,l])=>l.instances==null||l.instances["*"]!=null).map(([l])=>l);if(v.length>0){let l=Object.entries(t.services).filter(([,h])=>h.instances!=null&&h.instances["*"]==null).map(([h])=>h);l.length>0&&n.push({severity:"warning",code:"WILDCARD_ALIGNMENT",message:`integrations: 激活形态不对称(通配:${v.join(", ")};显式键集:${l.join(", ")})——动态 mallId 将在显式键集槽上 INSTANCE_NOT_FOUND(provider 业务限制表达位),确认是否齐步`})}let b=r.normalizeInstances({instances:t.instances,defaultInstanceId:t.defaultInstanceId});b.instances.length>=2&&b.defaultInstanceId===null&&n.push({severity:"warning",code:"MULTI_INSTANCE_NO_DEFAULT",message:`integrations: ${b.instances.length} 个部署实例(${b.instances.map(l=>l.id).join(", ")})均无 defaultInstanceId——无 scope 参数访问将落全局会话(默认商圈不注入)`});for(let[l,h]of Object.entries(t.services)){if(s[l]||n.push({severity:"warning",code:"SLOT_NOT_DECLARED",service:l,message:`integrations: 服务槽 ${l} 无消费方声明(拼写错误或需求方未安装)——若为拆分前旧槽位词汇(member.main/parking.main/promotion.read/shopping-guide.main),参照 cookbook·app-config 槽位迁移配方展开为新槽`}),typeof h.provider=="string"?typeof h.implementation=="string"&&!i[ae(h.provider,h.implementation)]&&n.push({severity:"error",code:"INSTANCE_SUPPLY_UNMATCHED",service:l,message:`integrations: provider ${h.provider}/${h.implementation} 未命中已装供给(${l} 槽级)——装对应 provider 包或改绑`}):h.provider!==void 0&&!G(h.provider)&&n.push({severity:"error",code:"INLINE_PROVIDER_INVALID",service:l,message:`integrations: 内联 provider 超受控形状(${l} 槽级;允许键 provider/credentialType/configSchema)`}),p){let C=S(l,h);C&&p[C]===!0&&n.push({severity:"error",code:"SCHEMA_FILE_MISSING",service:l,message:`integrations: credentialType ${C} 的 schema 引用不存在(${l};manifest 声明指向缺失文件)`})}typeof h.provider=="object"&&typeof h.implementation!="string"&&n.push({severity:"error",code:"IMPL_WITHOUT_PROVIDER",service:l,message:`integrations: 内联厂商声明必须同时提供 implementation(${l} 槽级)`});for(let[C,x]of Object.entries(h.instances??{})){u(C,`services.${l}.instances`);let N=x.provider!==void 0,j=x.implementation!==void 0;if(j&&!N&&n.push({severity:"error",code:"IMPL_WITHOUT_PROVIDER",service:l,instance:C,message:`integrations: 实例级 implementation 需伴随 provider(${l}@${C}——impl-only 禁止,provider 是绑定组头)`}),N&&j){let D=x.provider,W=x.implementation;typeof D=="string"&&typeof W=="string"?i[ae(D,W)]||n.push({severity:"error",code:"INSTANCE_SUPPLY_UNMATCHED",service:l,instance:C,message:`integrations: 实例级 provider 覆盖 ${D}/${W} 未命中已装供给(${l}@${C})`}):G(D)||n.push({severity:"error",code:"INLINE_PROVIDER_INVALID",service:l,instance:C,message:`integrations: 实例级内联 provider 超受控形状(${l}@${C})`})}}}for(let[l,h]of[["root",t.provider],...Object.entries(t.modules??{}).map(([E,C])=>[`modules.${E}`,C?.provider])])typeof h!="string"||h.length===0||R.has(h)||n.push({severity:"error",code:"VENDOR_NOT_INSTALLED",module:l.startsWith("modules.")?l.slice(8):void 0,message:`integrations: ${l} provider ${h} 未命中已装供给——装对应 provider 包或 provider use 改绑`});if(o)for(let[l,h]of Object.entries(t.services)){let E=h.instances?Object.keys(h.instances):[""];for(let C of E){let x=r.resolveEffectiveService(t,l,C,o,g);x.status==="binding-unresolved"&&n.push({severity:"error",code:"BINDING_UNRESOLVED",service:l,instance:C||void 0,message:`integrations: ${x.message}`})}}for(let[l,h]of Object.entries(t.services))h.implementation!==void 0&&h.provider===void 0&&n.push({severity:"error",code:"IMPL_WITHOUT_PROVIDER",service:l,message:`integrations: 槽级 implementation 需伴随 provider(${l}——impl-only 禁止,provider 是绑定组头)`});for(let[l,h]of Object.entries(t.modules??{})){if(!(h?.provider!==void 0||h?.config!==void 0))continue;let C=a?!a.has(l):!1,x=0;if(g)for(let j of Object.values(g))j===l&&(x+=1);if(C||!(g===void 0)&&x===0){let j=C?"未安装(键 = install id)":"未声明任何 owns(无模块级配置位)";n.push({severity:"error",code:"MODULE_CONFIG_DEAD",module:l,message:`integrations: modules.${l} 携带 provider/config 但模块${j}(MODULE_CONFIG_DEAD——模块级集成位作用于 declare.owns 服务,改 declare.owns 或删除该节点)`})}}if(c){let l=new Set,h=!1,E=C=>{typeof C!="string"||C.length===0||(c[C]&&l.add(C),!c[C]&&!k?.[C]&&(h=!0),k?.[C]&&(h=!0))};E(t.provider);for(let C of Object.values(t.modules??{}))E(C?.provider);for(let C of Object.values(t.services)){let x=C.provider;E(typeof C.provider=="string"?C.provider:x?.provider)}if(l.size>0&&!h){let C=new Set;for(let j of l)for(let D of c[j]??[])C.add(D);let x=new Set;for(let j of l)for(let D of f?.[j]??[])x.add(D);let N=(j,D,W,Z)=>{for(let[q]of Object.entries(j??{}))(W??C).has(q)?Z&&Z.size>0&&!Z.has(q)&&n.push({severity:"warning",code:"GLOBAL_FIELD_UNDECLARED",message:`integrations: ${D} 键 ${q} 过 schema 校验但未声明 x-tbox-global(不进应用/模块全局表单;已配置值照常生效——如需全局编辑请在 provider schema 标记)`}):n.push({severity:"error",code:"DOMAIN_CONFIG_INVALID",message:`integrations: ${D} 键 ${q} 不在引用厂商(${[...l].join("/")})任何槽 schema properties 内(死配置)`})};N(t.config,"root.config",void 0,x);for(let[j,D]of Object.entries(t.configByInstance??{}))N(D,`root.configByInstance[${j}]`,void 0,x);for(let[j,D]of Object.entries(t.modules??{})){if(!D?.config)continue;let W=L(t,j).provider??void 0;if(W===void 0){N(D.config,`modules.${j}.config`,void 0,x);continue}let Z=c[W];if(!Z||k?.[W])continue;let q=f?.[W];N(D.config,`modules.${j}.config`,new Set(Z),q)}}}for(let[l,h]of Object.entries(s)){let E=t.services[l];if(!E){n.push({severity:"warning",code:"SLOT_NOT_CONFIGURED",service:l,message:`integrations: 服务槽 ${l}(需求方 ${h.owners.join(", ")})未配置${h.optional?"(可选槽)":"(必需槽——模块将走降级链)"}`});continue}let C=Object.entries(E.instances??{}).filter(([,x])=>x.enabled===!1).map(([x])=>x);C.length>0&&n.push({severity:"warning",code:"INSTANCE_DISABLED",service:l,instance:C.join(", "),message:`integrations: ${l} 实例禁用(${C.join(", ")})`})}for(let[l,h]of Object.entries(t.modules??{})){let E=O?.[l];O&&!(l in O)&&n.push({severity:"warning",code:"RESOURCE_NOT_DECLARED",module:l,message:`integrations: modules.${l} 未命中已装模块(键 = install id——检查 .tbox/app.json entry.id / packages/ 目录名)`});for(let[C,x]of Object.entries(h?.resources??{})){let N=x?.type;(typeof N!="string"||!r.RESOURCE_TYPE_IDS.includes(N))&&n.push({severity:"error",code:"RESOURCE_TYPE_UNKNOWN",module:l,message:`integrations: modules.${l}.resources.${C} type 非法(${String(N)};词汇表 = ${r.RESOURCE_TYPE_IDS.join("/")})`}),E&&E.size>0&&!E.has(C)&&n.push({severity:"warning",code:"RESOURCE_NOT_DECLARED",module:l,message:`integrations: modules.${l}.resources.${C} 未被模块 manifest declare.resources 声明`})}}return n}function ae(e,n){return`${e}\0${n}`}import{existsSync as Le,readFileSync as Tt,readdirSync as Nt}from"fs";import{join as Se}from"path";function Vn(e){return e.replaceAll("-","_").toUpperCase()}function Pn(e){if(!Le(e))return null;try{let n=JSON.parse(Tt(e,"utf8"));return n&&typeof n=="object"?n:null}catch{return null}}function Pt(e){let n=new Set,r=e.properties;if(r&&typeof r=="object"&&!Array.isArray(r))for(let t of Object.keys(r))n.add(t);return n}function ce(e,n,r,t=process.env){let i={};for(let[u,v]of Object.entries(n.catalog.providers))for(let[b,l]of Object.entries(v))i[`${u}\0${b}`]={services:[...l.services],owner:l.owner,credentialType:l.credentialType};let s={};for(let[u,v]of Object.entries(n.catalog.services))s[u]={optional:v.optional,owners:[...v.owners]};let o={},d={},p={},c={},f={};for(let u of n.modules){f[u.id]=new Set((u.descriptor.declare.resources??[]).map(v=>v.id));for(let v of u.descriptor.declare.providers?.slots??[]){if(v.configSchema){let b=Pn(Se(u.dir,v.configSchema));if(b){let l=o[v.provider]??=new Set,h=d[v.provider]??=new Set;for(let C of Pt(b))l.add(C);let E=b.properties;if(E&&typeof E=="object"&&!Array.isArray(E))for(let[C,x]of Object.entries(E))x&&typeof x=="object"&&x["x-tbox-global"]===!0&&h.add(C)}else p[v.provider]=!0}v.credentialSchema&&!Le(Se(u.dir,v.credentialSchema))&&(c[v.credentialType]=!0)}}let k={},w=new Set,y=Se(e,"config","credentials");if(Le(y))for(let u of Nt(y)){if(!u.endsWith(".json"))continue;let v=u.slice(0,-5);w.add(v);let b=Pn(Se(y,u));b&&typeof b.type=="string"&&(k[v]=b.type)}let A=r,O=[],g=u=>{typeof u=="string"&&u.startsWith("secret://")&&O.push(u)};for(let u of Object.values(A.services??{}))if(u&&typeof u=="object"){g(u.credentialRef);for(let v of Object.values(u.instances??{}))v&&typeof v=="object"&&g(v.credentialRef)}for(let u of Object.values(A.credentialRefByInstance??{}))g(u);g(A.credentialRef);let a={};for(let u of O){let v=u.slice(9);t[Vn(v)]===void 0&&(w.has(v)||(a[v]=!0))}let m=[];for(let[u,v]of Object.entries(A.services??{})){let b=v&&typeof v=="object"&&typeof v.provider=="string"?v.provider:void 0;for(let[l,h]of Object.entries((v&&typeof v=="object"?v.instances:void 0)??{})){let E=h&&typeof h=="object"&&typeof h.provider=="string"?h.provider:void 0;b&&E&&E!==b&&m.push(`integrations: ${u}@${l} 实现覆盖跨厂商(${b} → ${E})——凭据域切换,确认该 mall 对应凭据在场`)}}let S=((Array.isArray(A.instances)?A.instances:void 0)??[]).map(u=>u&&typeof u=="object"&&typeof u.id=="string"?u.id:void 0).filter(u=>typeof u=="string");return{suppliedProviders:i,demandedServices:s,credentialFileMissing:a,credentialFileType:k,credentialSchemaMissing:c,vendorConfigKeys:o,vendorGlobalConfigKeys:d,vendorConfigSchemaMissing:p,realmSwitchHints:m,moduleResourceNeeds:f,...S.length>0?{malls:S}:{},ownership:n.ownership,installedModuleIds:new Set([...n.modules.map(u=>u.id),...new Set(Object.values(n.ownership))])}}import{existsSync as Hr,readFileSync as Yr}from"fs";import{join as qr,resolve as Qr}from"path";function We(e){return V(e).catalog}function we(e){let n=V(e).catalog,r={};for(let[s,o]of Object.entries(n.providers)){r[s]={};for(let[d,p]of Object.entries(o))r[s][d]={provider:p.provider,implementation:p.implementation,credentialType:p.credentialType,owner:p.owner,...p.local?{local:!0}:{},...p.configSchema?{configSchema:p.configSchema}:{},...p.credentialSchema?{credentialSchema:p.credentialSchema}:{},services:[...p.services]}}let t={};for(let[s,o]of Object.entries(n.services))t[s]={optional:o.optional,defaults:o.defaults.map(d=>({...d})),owners:[...o.owners]};let i={};for(let[s,o]of Object.entries(n.credentialTypes))i[s]={owner:o.owner,...o.credentialSchema?{credentialSchema:o.credentialSchema}:{}};return{providers:r,services:t,credentialTypes:i}}async function Be(e,n,r,t=process.env){let i=r.module,s=V(e),o=i.buildSupplyLookup(we(e)),d=ce(e,s,n,t);return ee({contracts:i,integrations:n,supplies:o,...d})}import{existsSync as Wt,rmSync as Bt}from"fs";import{join as Ut}from"path";import{existsSync as Vt,readFileSync as Dt}from"fs";import{join as Dn}from"path";var Ft=Dn("config","integrations.json");function B(e,n){let r=Dn(e,Ft),t=i=>JSON.parse(i);if(n)return n.read(r,t)??null;if(!Vt(r))return null;try{return t(Dt(r,"utf8"))}catch{return null}}async function Fn(e,n){let r=await T(e),t=B(e,n);if(t===null)return{config:null,strict:!1,contracts:r};if(r.strictValidation&&r.module.parseIntegrationsConfig)try{return{config:r.module.parseIntegrationsConfig(t),strict:!0,contracts:r}}catch(i){if(i instanceof Error&&Array.isArray(i.issues)){let s=i.issues.filter(o=>Array.isArray(o.path)).map(o=>o.path.map(String).join(".")).filter(o=>o.length>0);throw new M("VALIDATION_FAILED",400,"integrations.json 校验失败",s.length>0?s:void 0)}throw new M("VALIDATION_FAILED",400,i instanceof Error?i.message:String(i))}return{config:t,strict:!1,contracts:r}}function de(e,n,r){return e.includes(r)||n.includes(r)}import{readdirSync as _t,existsSync as he,readFileSync as $t}from"fs";import{join as Re}from"path";function _n(e,n,r){let t=[];if(n){let i=Q({provider:e});t.push({stem:i,ref:`secret://${i}`,input:n})}for(let[i,s]of Object.entries(r??{})){let o=Q({provider:e,instanceId:i});t.push({instanceId:i,stem:o,ref:`secret://${o}`,input:s})}return t}function $n(e,n,r,t,i){let s=[];if(t){let o=Q({provider:e,service:n});s.push({stem:o,ref:`secret://${o}`,input:t})}for(let[o,d]of Object.entries(i??{})){let p=Q({provider:e,instanceId:o,domain:r});s.push({instanceId:o,stem:p,ref:`secret://${p}`,input:d})}return s}function ze(e,n,r){return n.map(t=>({stem:t.stem,ref:t.ref,overwrote:r?he(Re(e,_(t.stem))):Ve(e,t.stem,t.input)}))}function Lt(e,n){return he(Re(e,_(n)))}function Ue(e,n){if(typeof e=="string"){e.startsWith("secret://")&&n.add(e.slice(9));return}if(Array.isArray(e)){for(let r of e)Ue(r,n);return}if(e&&typeof e=="object")for(let r of Object.values(e))Ue(r,n)}function ne(e){let n=Re(e,"config","credentials"),r=new Set,t=Re(e,"config","integrations.json");if(he(t))try{Ue(JSON.parse($t(t,"utf8")),r)}catch{}let i=[];if(!he(n))return i;let s=[];try{s=_t(n).filter(o=>o.endsWith(".json")).map(o=>o.slice(0,-5))}catch{return i}for(let o of s.sort()){if(r.has(o))continue;let d=se(e,o);i.push({severity:"warning",code:"ORPHANED_CREDENTIAL",message:`${_(o)} 不再被引用(凭据文件保留,可手动清理)`})}return i}function Ie(e){if(typeof e=="string")return e.length>0?e:void 0;if(e&&typeof e=="object"&&G(e)){let n=e.provider;return n.length>0?n:void 0}}async function zt(e){let n=Ut(e,"config","integrations.json"),r=B(e);if(r===null)return{removed:[],orphanCredentials:[],skipped:"not-configured"};let t=await T(e);if(!t.strictValidation)return{removed:[],orphanCredentials:[],skipped:"predicate-unavailable"};let i;try{let y=Ne(JSON.stringify(r),process.env);if(y.missing.length>0||y.text===void 0)return{removed:[],orphanCredentials:[],skipped:"predicate-unavailable"};i=JSON.parse(y.text)}catch{return{removed:[],orphanCredentials:[],skipped:"predicate-unavailable"}}let s;try{s=await Be(e,i,t,process.env)}catch{return{removed:[],orphanCredentials:[],skipped:"predicate-unavailable"}}let o=V(e),d=new Set(Object.keys(o.catalog.providers)),p=o.ownership,c=structuredClone(r);c.services??={};let f=[];for(let y of s)if(y.severity==="error"){if(y.code==="VENDOR_NOT_INSTALLED")if(y.module){let O=(c.modules??{})[y.module];O?.provider&&(f.push(`modules.${y.module}.provider=${String(O.provider)}`),delete O.provider,Object.keys(O).length===0&&delete c.modules[y.module])}else c.provider&&(f.push(`root.provider=${c.provider}`),delete c.provider);else if(y.code==="MODULE_CONFIG_DEAD"&&y.module){let A=c.modules??{};if(A[y.module]){let O=A[y.module],g=[O.provider!==void 0?"provider":void 0,O.config!==void 0?"config":void 0,O.resources!==void 0?"resources":void 0].filter(Boolean);f.push(`modules.${y.module}(${g.join("+")} 整节点)`),delete c.modules[y.module]}}else if(y.code==="BINDING_UNRESOLVED"&&y.service){let A=c.services[y.service];if(!A)continue;let O=p[y.service];if([y.instance?Ie(A.instances?.[y.instance]?.provider):void 0,Ie(A.provider),O!==void 0?Ie(c.modules?.[O]?.provider):void 0,Ie(c.provider)].filter(a=>typeof a=="string").some(a=>d.has(a)))continue;if(y.instance){let a=A.instances;if(!a||!(y.instance in a))continue;delete a[y.instance],f.push(`services.${y.service}.instances.${y.instance}`),Object.keys(a).length===0&&delete A.instances,Object.keys(A).length===0&&delete c.services[y.service]}else delete c.services[y.service],f.push(`services.${y.service}`)}}if(Object.keys(c.services).length===0&&delete c.services,f.length===0)return{removed:f,orphanCredentials:[]};let k=!c.provider&&Object.keys(c.services??{}).length===0&&Object.keys(c.config??{}).length===0&&Object.keys(c.configByInstance??{}).length===0&&!c.credentialRef&&Object.keys(c.credentialRefByInstance??{}).length===0&&(c.instances??[]).length===0&&c.defaultInstanceId==null&&Object.keys(c.modules??{}).length===0;if(!k&&(c.services??={},typeof t.module.parseIntegrationsConfig=="function"))try{t.module.parseIntegrationsConfig(c)}catch{return{removed:[],orphanCredentials:[],skipped:"validation-failed"}}let w=[];return k?Wt(n)&&Bt(n,{force:!0}):$(n,`${JSON.stringify(c,null,2)}
|
|
4
|
-
`),
|
|
5
|
-
`),t?.invalidate([
|
|
6
|
-
`),t?.invalidate([
|
|
7
|
-
`)}else{for(let
|
|
8
|
-
`)}return{generated:!0,reason:"generated",services:r.map(s=>s.service).sort()}}import{existsSync as Zt,readFileSync as qt}from"fs";import{join as Hn}from"path";function zn(e,n){let r=V(e.appDir,e.cache),t=B(e.appDir,e.cache);return{appDir:e.appDir,walk:r,catalog:r.catalog,integrations:t,contracts:n,...e.cache?{cache:e.cache}:{}}}function Kn(e){let n=new Set;for(let r of e.modules){for(let t of r.descriptor.declare.owns??[])n.add(t.service);for(let t of r.descriptor.declare.consumes??[])n.add(t.service);for(let t of r.descriptor.declare.providers?.slots??[])n.add(t.service)}return n}function Ee(e,n,r){let t=e.providers[n];return t?Object.values(t).some(i=>i.services.includes(r)):!1}function Jn(e,n){let r=[];for(let[t,i]of Object.entries(e.providers))Object.values(i).some(s=>s.services.includes(n))&&r.push(t);return r.sort()}function U(e,n){let r=e.slotMeta[n],t=e.catalog.services[n],i=r?.name??t?.name??n,s=r?.description??t?.description;return{name:i,...s!==void 0?{description:s}:{}}}var Qt=Hn("config","knowledge.json");function Xt(e,n,r){let i=r[n]?.resources;if(!i||typeof i!="object"||Array.isArray(i))return null;let s=Hn(e.appDir,Qt),o={};if(Zt(s))try{o=(e.cache?.read(s,c=>JSON.parse(c))??JSON.parse(qt(s,"utf8"))).knowledge_bases??{}}catch{o={}}let d={};for(let[p,c]of Object.entries(i)){if(!c||typeof c!="object"||Array.isArray(c))continue;let f=c,k=f.type==="knowledge"?"knowledge":String(f.type??"knowledge"),w=typeof f.datasetId=="string"&&f.datasetId!==""?f.datasetId:void 0,y=typeof f.ref=="string"&&f.ref!==""?f.ref:void 0,A=w??(y!==void 0&&typeof o[y]?.datasetId=="string"?o[y].datasetId:null),O={type:k,...w!==void 0?{datasetId:w}:{},...y!==void 0?{ref:y}:{},resolvedDatasetId:A,...typeof f.topK=="number"?{topK:f.topK}:{},...typeof f.scoreThreshold=="number"?{scoreThreshold:f.scoreThreshold}:{}};d[p]=O}return Object.keys(d).length>0?d:null}function Gn(e){return e.replace(/^@tbox\.cn\/app-/,"").replace(/^@[^/]+\//,"")}function er(e){return Gn(e.id).startsWith("provider-")||Gn(e.pkg).startsWith("provider-")}function He(e,n={}){return{modules:e.walk.modules.filter(t=>!er(t)).filter(t=>n.includeHidden===!0||t.descriptor.hidden!==!0).map(t=>({id:t.id,name:t.descriptor.name??t.descriptor.id,description:t.descriptor.description??"",...t.descriptor.hidden===!0?{hidden:!0}:{}})).sort((t,i)=>t.id.localeCompare(i.id))}}function Ye(e,n){let r=e.walk.modules.find(c=>c.id===n);if(!r)throw new M("MODULE_NOT_FOUND",404,`模块 ${n} 非已装模块`);let t=(r.descriptor.declare.consumes??[]).map(c=>{let f=U(e.walk,c.service);return{service:c.service,name:f.name,...f.description!==void 0?{description:f.description}:{},required:c.optional===!1}}),i=J(e.walk,r),s=e.integrations?.modules??{},o=s[n],d=o?{...typeof o.provider=="string"?{provider:o.provider}:{},...o.config&&typeof o.config=="object"&&!Array.isArray(o.config)?{config:o.config}:{}}:null,p=L(e.integrations,n);return{name:r.descriptor.name??r.descriptor.id,description:r.descriptor.description??"",...r.descriptor.hidden===!0?{hidden:!0}:{},ownedServices:i.ownedServices,integration:d,resources:Xt(e,n,s),binding:{provider:p.provider,layer:p.layer},configEditable:i.writable,services:t}}function Ze(e){let n=Kn(e.walk),r=e.walk.vocabulary.filter(s=>!n.has(s)).map(s=>{let o=U(e.walk,s);return{service:s,name:o.name,...o.description!==void 0?{description:o.description}:{},required:!1}}),t=e.integrations,i=null;if(t){let s={};for(let o of le)o in t&&(s[o]=t[o]);i=s}return{services:r,integration:i}}function qe(e,n){let r=e.integrations?.services??{},t=e.catalog.services[n];if(!de(e.walk.vocabulary,Object.keys(r),n))throw new M("SERVICE_NOT_FOUND",404,`服务 ${n} 不在服务词汇(已装契约包 ∪ 已配置)`);let i=r[n]??null,s=U(e.walk,n);return{service:n,name:s.name,...s.description!==void 0?{description:s.description}:{},required:t?!t.optional:!1,defaults:t?t.defaults.map(o=>({...o})):[],integration:i,suppliedBy:Jn(e.catalog,n)}}import{existsSync as qn,readFileSync as Qn,realpathSync as Yn}from"fs";import{isAbsolute as nr,join as tr,relative as rr,resolve as Zn,sep as ir}from"path";function Qe(e){let n=[];for(let[r,t]of Object.entries(e.catalog.providers)){let i=Object.values(t);i.length!==0&&n.push({provider:r,local:i.every(s=>s.local===!0),owner:i[0].owner,...i[0].name?{name:i[0].name}:{},...i[0].description?{description:i[0].description}:{}})}return{providers:n.sort((r,t)=>r.provider.localeCompare(t.provider))}}function Xe(e,n,r){let t=e.catalog.providers[n];if(!t)throw new M("PROVIDER_NOT_FOUND",404,`厂商 ${n} 不 ∈ catalog(内联声明厂商无包级档案——身份与表单经组合端点暴露)`);let i={};for(let o of Object.values(t))for(let d of o.services)(i[d]??={implementations:[]}).implementations.push({implementation:o.implementation,credentialType:o.credentialType});for(let[o,d]of Object.entries(i)){let p=U(e.walk,o);d.name=p.name,p.description!==void 0&&(d.description=p.description)}if(r?.has("integrationSchemas"))for(let[o,d]of Object.entries(i))d.integrationSchemas={configSchema:z(e,n,o)};let s=Object.values(t);return{provider:n,local:s.every(o=>o.local===!0),owner:s[0].owner,...s[0].name?{name:s[0].name}:{},...s[0].description?{description:s[0].description}:{},services:i}}function en(e,n,r){let t=e.catalog.providers[n],i=e.integrations?.services??{},s=[];if(t)for(let c of Object.values(t))c.services.includes(r)&&s.push({implementation:c.implementation,credentialType:c.credentialType});let o=i[r]?.provider,d=o&&typeof o=="object"&&o.provider===n?o:void 0;if(s.length===0&&!d)throw t?new M("SUPPLY_NOT_FOUND",404,`厂商 ${n} 未供给服务 ${r}(AI 帮我实现流:PUT 显式绑定后实施)`):new M("PROVIDER_NOT_FOUND",404,`厂商 ${n} 完全未知(不 ∈ catalog 且无任何内联声明)`);s.length===0&&d&&s.push({implementation:i[r]?.implementation??`${n}-inline@1`,credentialType:d.credentialType});let p=z(e,n,r,d?o?.configSchema:void 0);return{provider:n,service:r,implementations:s,integrationSchemas:{configSchema:p}}}function z(e,n,r,t){let i=e.walk.serviceSchemas[`${n}\0${r}`];return i?nn(e.appDir,i.packageDir,i.configSchema):typeof t=="string"?or(e.appDir,t):null}function nn(e,n,r){if(!r)return null;let t=tr(n,r);if(!qn(t))return null;try{return JSON.parse(Qn(t,"utf8"))}catch{return null}}function or(e,n){let r=Zn(e,"config","schemas"),t=Zn(e,n),i=rr(r,t);if(i===""||i.startsWith("..")||nr(i))throw new M("VALIDATION_FAILED",400,"configSchema 引用必须落在 config/schemas/ 内(禁路径逃逸)",["provider.configSchema"]);if(!qn(t))return null;let s,o;try{s=Yn(r),o=Yn(t)}catch{return null}if(o!==s&&!o.startsWith(s+ir))throw new M("VALIDATION_FAILED",400,"configSchema 引用经 symlink 逃逸出 config/schemas/(realpath 复核拒绝)",["provider.configSchema"]);try{return JSON.parse(Qn(t,"utf8"))}catch{return null}}function Xn(e){return{version:e.version,evaluation:e.evaluation,strictValidation:e.strictValidation,notes:[...e.notes]}}function et(e,n,r){let t=e.integrations,i=t?.services?.[n],s=i?.instances?.[r]??i?.instances?.["*"];if(s&&s.provider!==void 0)return"instance";if(i?.provider!==void 0)return"service";let o=e.walk.ownership[n];return o!==void 0&&L(e.integrations,o).layer==="module"?"module":typeof t?.provider=="string"&&t.provider.length>0?"app":null}function nt(e,n,r,t,i){let s=n.resolveEffectiveService(e.integrations,r,t,i);if(s.status==="ok"&&s.effective){let o=s.effective.provider,d=typeof o=="string"?o:String(o?.provider??"");return{status:"ok",provider:d,implementation:s.effective.implementation,effective:{provider:d,implementation:s.effective.implementation,...s.effective.config!==void 0?{config:{...s.effective.config}}:{},...s.effective.credentialRef!==void 0?{credentialRef:s.effective.credentialRef}:{},layer:et(e,r,t)??"app"}}}return s.status==="binding-unresolved"?{status:"binding-unresolved",statusMessage:s.message}:{status:s.status}}function tn(e){let n=e.contracts.module;if(!n.resolveEffectiveService||!n.normalizeInstances)throw new M("CONTRACTS_NOT_RESOLVED",503,"contracts 求值面缺席(契约包形态异常)——重新安装或升级应用 @tbox.cn/app-contracts 后重试");return n}function rn(e,n){let r=tn(n),{integrations:t,catalog:i}=n,s=r.buildSupplyLookup(i),o=t,p=r.normalizeInstances({instances:o?.instances,defaultInstanceId:o?.defaultInstanceId}).defaultInstanceId??"*",c=nt(n,r,e,p,s),f=et(n,e,p),k=n.integrations?.services?.[e]?.provider,w=c.provider??(typeof k=="string"?k:typeof k=="object"&&k?String(k.provider):void 0),y=new Set(Object.keys(n.catalog.providers)),A=w!==void 0&&y.has(w)?sr(n.catalog,w,e):void 0,O=i.services[e],g=O!==void 0?!O.optional:void 0,a=O?.owners[0];return{status:c.status,...c.statusMessage?{statusMessage:c.statusMessage}:{},...w!==void 0?{provider:w}:{},...w!==void 0&&f!==null?{layer:f}:{},...A!==void 0?{supplied:A}:{},...a!==void 0?{module:a}:{},...g!==void 0?{required:g}:{}}}function sr(e,n,r){return Ee(e,n,r)}function pe(e,n,r){let t=new Set([...e.walk.vocabulary,...Object.keys(e.catalog.services)]),i=e.integrations?.services??{};for(let o of Object.keys(i))t.add(o);let s={};for(let o of[...t].sort())r&&!r.includes(o)||(s[o]=rn(o,e));return{contracts:Xn(e.contracts),resolutions:s,issues:n}}function on(e,n,r){let t=tn(n),i=t.buildSupplyLookup(n.catalog),s=n.integrations,d=t.normalizeInstances({instances:s?.instances,defaultInstanceId:s?.defaultInstanceId}).instances.map(O=>O.id),p=n.integrations?.services?.[e],c=p?.instances?Object.keys(p.instances):void 0,f;d.length>0?(f=[...d],c?.includes("*")&&f.push("*")):c!==void 0&&c.length>0?f=c.includes("*")?["*"]:c:f=[];let k=f.map(O=>{let g=nt(n,t,e,O,i);return{instanceId:O,status:g.status,...g.statusMessage?{statusMessage:g.statusMessage}:{},...g.effective?{effective:g.effective}:{}}}),w=ar(n,e),A={...rn(e,n),instances:k,inheritance:w};return{contracts:Xn(n.contracts),resolution:A,issues:r.filter(O=>O.service===e)}}function ar(e,n){let r=e.integrations,t=r?.services?.[n],i=e.integrations,o=tn(e).normalizeInstances({instances:i?.instances,defaultInstanceId:i?.defaultInstanceId}).defaultInstanceId??"*",d=t?.instances?.[o]??t?.instances?.["*"],p=e.walk.ownership[n],c=p!==void 0?L(r,p):{provider:null,layer:null};return[{layer:"app",...r?.provider?{provider:r.provider}:{}},{layer:"module",...c.layer==="module"&&c.provider?{provider:c.provider}:{}},{layer:"service",...typeof t?.provider=="string"?{provider:t.provider}:{},...t?.implementation?{implementation:t.implementation}:{}},{layer:"instance",...d?.provider?{provider:d.provider}:{},...d?.implementation?{implementation:d.implementation}:{}}]}function sn(e,n,r){if(n===null)return null;let t={};for(let i of r)t[i]={configSchema:z(e,n,i)};return{provider:n,services:t}}function ie(e){return e===null||typeof e!="object"?JSON.stringify(e??null):Array.isArray(e)?`[${e.map(ie).join(",")}]`:`{${Object.keys(e).sort().map(r=>`${JSON.stringify(r)}:${ie(e[r])}`).join(",")}}`}var cr="\0no-enum";function dr(e){let n=e.enum;return Array.isArray(n)?`[${[...new Set(n.map(ie))].sort().join(",")}]`:cr}function lr(e){if(!e||typeof e!="object"||Array.isArray(e))return null;let n=e.type;return n===void 0?null:ie(n)}function ur(e){let n=e.map(t=>lr(t.subschema));if(n.some(t=>t===null)||new Set(n).size>1)return null;if(n[0]==='"object"'){let t=ie(e[0].subschema);return e.every(i=>ie(i.subschema)===t)?e[0].subschema:null}return new Set(e.map(t=>dr(t.subschema))).size===1?e[0].subschema:null}function Oe(e,n){let r=[],t=!0,i=new Map;for(let[o,d]of Object.entries(e.services)){let p=d.configSchema;if(p===null){r.push(o);continue}if(!p||typeof p!="object"||Array.isArray(p))continue;let c=p;c.additionalProperties===!1&&(t=!1);let f=c.properties;if(!f||typeof f!="object"||Array.isArray(f))continue;let k=Array.isArray(c.required)?c.required:[];for(let w of Object.keys(f)){let y=i.get(w)??[];y.push({service:o,subschema:f[w],required:k.includes(w)}),i.set(w,y)}}let s=[];for(let[o,d]of i)s.push({key:o,schema:ur(d),sources:d.map(({service:p,required:c})=>({service:p,required:c})),global:d.some(p=>!!p.subschema&&typeof p.subschema=="object"&&p.subschema["x-tbox-global"]===!0)});return{provider:e.provider,schemaless:r,unsupplied:[...n?.unsupplied??[]],additionalPropertiesAllowed:t,fields:s}}function an(e,n,r,t){let i=typeof t=="string"&&t.length>0?t:void 0;if(e==="app"){if(i!==void 0)return i;let d=n.integrations?.provider;return typeof d=="string"&&d.length>0?d:null}let s=n.walk.modules.find(d=>d.id===r);return!s||!J(n.walk,s).writable?null:i!==void 0?i:L(n.integrations,s.id).provider}var tt={integrationSchemas:null,integrationFieldRegistry:null};function rt(e){return{...e,fields:e.fields.filter(n=>n.global)}}function cn(e,n){let r=an("app",e,void 0,n);if(r===null)return tt;let t=sn(e,r,_e(e.catalog,r));return{integrationSchemas:t,integrationFieldRegistry:rt(Oe(t))}}function dn(e,n,r){let t=an("module",e,n,r),i=e.walk.modules.find(p=>p.id===n);if(t===null||!i)return tt;let s=(i.descriptor.declare.owns??[]).map(p=>p.service),o=p=>Ee(e.catalog,t,p),d=sn(e,t,s.filter(o));return{integrationSchemas:d,integrationFieldRegistry:rt(Oe(d,{unsupplied:[...new Set(s.filter(p=>!o(p)))]}))}}function pr(e){return cn(e).integrationSchemas}function fr(e,n){return dn(e,n).integrationSchemas}function gr(e,n){let r=e.walk.ownership[n];if(r!==void 0)return L(e.integrations,r).provider;let t=e.integrations?.provider;return typeof t=="string"&&t.length>0?t:null}function Me(e,n,r){let t=typeof r=="string"&&r.length>0?r:void 0;if(t!==void 0)return{provider:t,configSchema:z(e,t,n)};let i=e.integrations?.services?.[n]?.provider;if(i===void 0||i===""){let s=gr(e,n);return s===null?null:{provider:s,configSchema:z(e,s,n)}}if(typeof i=="string")return{provider:i,configSchema:z(e,i,n)};if(G(i)){let s=i;return{provider:s.provider,configSchema:z(e,s.provider,n,s.configSchema)}}return null}function ln(e,n,r){let t=Me(e,n,r);if(t===null)return null;let i={provider:t.provider,services:{[n]:{configSchema:t.configSchema}}};return Oe(i)}function fe(e,n){if(n===void 0||!n.startsWith("secret://"))return;let r=n.slice(9),t=se(e,r);if(t)return{type:t.type,ref:n,file:_(r),masked:ge(t.values)}}function un(e){let n=e.integrations,r={credential:fe(e.appDir,typeof n?.credentialRef=="string"?n.credentialRef:void 0)??null,byInstance:{}};for(let{id:i}of n?.instances??[]){let s=n?.credentialRefByInstance?.[i];s!==void 0&&(r.byInstance[i]=fe(e.appDir,s)??null)}let t={};for(let[i,s]of Object.entries(n?.services??{})){let o={credential:fe(e.appDir,s.credentialRef)??null,byInstance:{}};for(let[d,p]of Object.entries(s.instances??{}))o.byInstance[d]=fe(e.appDir,p.credentialRef)??null;t[i]=o}return{app:r,services:t}}function pn(e,n){return{types:(n===void 0?Object.keys(e.catalog.credentialTypes):[...new Set(Object.values(e.catalog.providers[n]??{}).map(t=>t.credentialType))]).sort().map(t=>{let i=e.catalog.credentialTypes[t];return{credentialType:t,owner:i?.owner??"",credentialSchema:i?nn(e.appDir,i.packageDir,i.credentialSchema):null}})}}import mr from"path";var vr={app:["serviceResolutions","integrationSchemas","integrationFieldRegistry"],module:["serviceResolutions","integrationSchemas","integrationFieldRegistry"],provider:["integrationSchemas"],service:["integrationSchemas","integrationFieldRegistry"]};function xe(e,n){if(!n||n.length===0)return new Set;let r=vr[e],t=[...new Set(n)].filter(i=>!r.includes(i));if(t.length>0)throw new M("VALIDATION_FAILED",400,`include 含未知或不适用于本端点的键:${t.join("、")}(白名单:${r.join("、")})`,["include"]);return new Set(n)}var it=["integrationSchemas","integrationFieldRegistry"];function fn(e,n,r){if(!(typeof n!="string"||n.length===0)&&!it.some(t=>r.has(t)))throw new M("VALIDATION_FAILED",400,`参数 ${e} 需与表单 include 键(${it.join("、")})同现——轴参仅重定向表单层双投影`,[e])}function yr(e,n={}){let r=je(),t=Promise.resolve(),i={appDir:e,cache:r};function s(g){if(!g.strictValidation)throw new M("CONTRACTS_NOT_RESOLVED",503,Pe(g));if(!g.ownershipBindingV6)throw new M("CONTRACTS_NOT_RESOLVED",503,`contracts ${g.version??"(版本未知)"} 不支持 v6 modules 绑定形状(OWNERSHIP_BINDING_V6 标记缺席)——升级应用 @tbox.cn/app-contracts 依赖后可用`)}function o(g){return zn(i,g)}function d(g){let a=g.integrations?.services;return a&&typeof a=="object"?Object.keys(a):[]}async function p(){let g=await T(e),a=o(g),m=a.integrations;if(m===null)return[];let R={resolveEffectiveService:c(g.module.resolveEffectiveService,"resolveEffectiveService"),buildSupplyLookup:c(g.module.buildSupplyLookup,"buildSupplyLookup"),normalizeInstances:c(g.module.normalizeInstances,"normalizeInstances"),RESOURCE_TYPE_IDS:g.module.RESOURCE_TYPE_IDS??[]},S=ce(e,a.walk,m,process.env);return ee({contracts:R,integrations:m,supplies:R.buildSupplyLookup(a.catalog),...S})}function c(g,a){if(typeof g!="function")throw new M("CONTRACTS_NOT_RESOLVED",503,`contracts 求值面 ${a} 缺席(形态异常)`);return g}function f(g){let a=t.then(g,g);return t=a.catch(()=>{}),a}let k={async loadModules(g){let a=await T(e);return He(o(a),g)},async loadModule(g,a){let m=xe("module",a?.include);fn("moduleProvider",a?.moduleProvider,m);let R=await T(e),S=o(R),u=ke(S.walk,g),v=Ye(S,u.id);if(m.has("serviceResolutions")&&(v.serviceResolutions=R.evaluation&&R.strictValidation?await p().then(b=>pe(S,b,v.services.map(l=>l.service))):null),m.has("integrationSchemas")||m.has("integrationFieldRegistry")){let b=dn(S,u.id,a?.moduleProvider);m.has("integrationSchemas")&&(v.integrationSchemas=b.integrationSchemas),m.has("integrationFieldRegistry")&&(v.integrationFieldRegistry=b.integrationFieldRegistry)}return v},async loadApp(g){let a=xe("app",g?.include);fn("appProvider",g?.appProvider,a);let m=await T(e),R=o(m),S=Ze(R);if(a.has("serviceResolutions")&&(S.serviceResolutions=m.evaluation&&m.strictValidation?await p().then(u=>pe(R,u)):null),a.has("integrationSchemas")||a.has("integrationFieldRegistry")){let u=cn(R,g?.appProvider);a.has("integrationSchemas")&&(S.integrationSchemas=u.integrationSchemas),a.has("integrationFieldRegistry")&&(S.integrationFieldRegistry=u.integrationFieldRegistry)}return S},async loadService(g,a){let m=xe("service",a?.include);fn("serviceProvider",a?.serviceProvider,m);let R=await T(e),S=o(R),u=H(S.walk,d(S),g),v=qe(S,u);return m.has("integrationSchemas")&&(v.integrationSchemas=Me(S,u,a?.serviceProvider)),m.has("integrationFieldRegistry")&&(v.integrationFieldRegistry=ln(S,u,a?.serviceProvider)),v},async loadServiceResolutions(g){let a=await T(e);s(a);let m=await p();return pe(o(a),m,g)},async loadServiceResolution(g){let a=await T(e);s(a);let m=o(a),R=H(m.walk,d(m),g),S=await p();return on(R,m,S)},async loadProviders(){let g=await T(e);return Qe(o(g))},async loadProvider(g,a){let m=xe("provider",a?.include),R=await T(e);return Xe(o(R),g,m)},async loadProviderService(g,a){let m=await T(e),R=o(m),S=H(R.walk,d(R),a);return en(R,g,S)},async loadCredentials(){let g=await T(e);return un(o(g))},async loadCredentialTypes(g){let a=await T(e);return pn(o(a),g)}},w=Je(e,{onApplied:n.onApplied,cache:r}),y={async writeAppIntegration(g,a){await w.warmup();let m=await T(e);return s(m),f(()=>w.applyApp(g,a))},async writeModuleIntegration(g,a,m){await w.warmup();let R=await T(e);return s(R),f(()=>{let S=ke(o(R).walk,g);return w.applyModule(S.id,a,m)})},async writeServiceIntegration(g,a,m){await w.warmup();let R=await T(e);return s(R),f(()=>{let S=o(R),u=H(S.walk,d(S),g);return w.applyService(u,a,m)})},async deleteServiceIntegration(g){await w.warmup();let a=await T(e);return s(a),f(()=>{let m=o(a),R=H(m.walk,d(m),g);return w.deleteService(R)})}},A={invalidate(){r.invalidate(),Te(e)},async resolveContracts(){return T(e)},walkManifests(){return O(e)},parseModuleDescriptor(g){return oe(g)},loadProviderCatalogRaw(){return We(e)},async readIntegrationsConfig(){return B(e,r)},async writeIntegrationsConfig(g){await w.warmup();let a=await T(e);return s(a),f(()=>Sr(e,g,r))},async ensureMockBindings(){await w.warmup();let g=await T(e);return s(g),f(()=>Ge(e))},async evaluateIntegrationServices(g){await w.warmup();let a=await T(e);s(a);let m={resolveEffectiveService:c(a.module.resolveEffectiveService,"resolveEffectiveService"),buildSupplyLookup:c(a.module.buildSupplyLookup,"buildSupplyLookup"),normalizeInstances:c(a.module.normalizeInstances,"normalizeInstances"),RESOURCE_TYPE_IDS:a.module.RESOURCE_TYPE_IDS??[]};return ee({...g,contracts:m})}};function O(g){return V(g,r)}return{...k,...y,...A}}function Sr(e,n,r){let t=mr.join(e,"config","integrations.json");$(t,`${JSON.stringify(n,null,2)}
|
|
9
|
-
`),r.invalidate([t])}export{
|
|
1
|
+
import{a as Ve,b as T,c as De}from"./chunk-WUULQDOV.js";import{z as k}from"zod";var z=/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/,ft=k.object({cardType:k.string(),schemaVersion:k.number().optional()}),vn=k.object({route:k.string(),component:k.string()}),yn=k.object({route:k.string(),label:k.string().optional(),icon:k.string().optional(),order:k.number().optional()}),Sn=k.object({id:k.string(),range:k.string().optional(),required:k.boolean().default(!0)}),wn=k.object({service:k.string(),provider:k.string().regex(z,"provider 名含非法字符(需 /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/)"),implementation:k.string(),credentialType:k.string(),local:k.boolean().optional(),configSchema:k.string().optional(),credentialSchema:k.string().optional()}),hn=k.object({service:k.string(),optional:k.boolean().default(!0),defaults:k.array(k.object({provider:k.string().regex(z,"provider 名含非法字符(需 /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/)"),implementation:k.string()})).default([]),name:k.string().optional(),description:k.string().optional()}),Rn=k.object({service:k.string()}).strict(),In=k.object({id:k.string(),type:k.string()}),kn=k.object({schemaVersion:k.number().default(1),id:k.string(),name:k.string().optional(),description:k.string().optional(),hidden:k.boolean().optional(),version:k.string().default("0.0.0"),kind:k.enum(["platform","business","third-party"]).default("business"),risk:k.object({level:k.enum(["high","medium","low"]).default("low"),writeBoundary:k.enum(["sdk-enforced","source"]).default("source")}).default({}),distribution:k.object({defaultMode:k.enum(["hybrid","sdk","codegen","local"]).default("codegen")}).default({}),declare:k.object({handlers:k.array(k.string()).default([]),tools:k.array(k.string()).default([]),cards:k.array(ft).default([]),routes:k.array(k.string()).default([]),pages:k.array(vn).default([]),tabs:k.array(yn).default([]),providers:k.object({slots:k.array(wn).default([])}).default({}),owns:k.array(Rn).default([]),consumes:k.array(hn).default([]),resources:k.array(In).default([])}).default({}),dependencies:k.object({modules:k.array(Sn).default([])}).default({}),env:k.array(k.string()).default([])}).strict();function gt(e){if(!e||typeof e!="object"||Array.isArray(e))return[];let n=[],r=e;"contributes"in r&&n.push("(root): manifest 旧键 `contributes` 已更名 `declare`(v6 声明面)——codegen 副本经 `module update --source` 重新生成 / sdk 模式升级模块包 / 手改两键");let t=r.declare;t&&typeof t=="object"&&!Array.isArray(t)&&"services"in t&&n.push("declare: manifest 旧键 `declare.services` 已更名 `declare.consumes`(消费关系定向化)——同上三路径升级"),!("id"in r)&&"name"in r&&n.push("(root): manifest 标识键 `name` 已更名 `id`(v7 词汇统一)——codegen 副本经 `module update --source` 重新生成 / sdk 模式升级模块包 / 手改两键");let i=t&&typeof t=="object"&&!Array.isArray(t)?t:void 0,o=Array.isArray(i?.consumes)&&i.consumes.some(s=>s!==null&&typeof s=="object"&&"title"in s);return("title"in r||o)&&n.push("(root): manifest 展示名键 `title` 已更名 `name`(v7 词汇统一;declare.consumes[].title 同步改 name)——同上三路径升级"),n}function se(e){let n=gt(e);if(n.length>0)return{ok:!1,errors:n,legacy:!0};let r=kn.safeParse(e);return r.success?{ok:!0,value:r.data}:{ok:!1,errors:r.error.issues.map(t=>`${t.path.join(".")||"(root)"}: ${t.message}`)}}var mt=/\$\$?\{([A-Z][A-Z0-9_]*)(?::-([^}]*))?\}/g;function bn(e){return JSON.stringify(e).slice(1,-1)}function Fe(e,n=process.env){let r=[],t=e.replace(mt,(i,o,s)=>{if(i.startsWith("$$"))return i.slice(1);let l=n[o];return l!==void 0?bn(l):s!==void 0?bn(s):(r.push(o),i)});return r.length>0?{missing:r}:{text:t,missing:[]}}import{mkdirSync as vt,existsSync as Cn,readFileSync as yt,writeFileSync as St}from"fs";import{dirname as wt,join as An}from"path";function ve(e){let n={};for(let[r,t]of Object.entries(e)){if(typeof t!="string"){n[r]=null;continue}n[r]=t.length<=4?"****":`${t.slice(0,2)}****`}return n}var x=class extends Error{code;httpStatus;fields;constructor(n,r,t,i){super(t),this.name="AppToolkitError",this.code=n,this.httpStatus=r,this.fields=i}};function J(e){return e.notes.length>0?e.notes[0]:e.version===null?"contracts 不可解析(未安装)——检查应用依赖安装后重试":e.strictValidation?e.ownershipBindingV6===!1?`contracts ${e.version??"(版本未知)"} 不支持 v6 modules 绑定形状(OWNERSHIP_BINDING_V6 标记缺席)——升级应用 @tbox.cn/app-contracts 依赖后可用`:"contracts workspace 源码态未构建——执行 pnpm --filter @tbox.cn/app-contracts build 后重试":`contracts ${e.version} 无严格校验面(需 ≥0.9.0)——升级应用 @tbox.cn/app-contracts 依赖后可用`}function ye(e,n){if(n!==void 0&&(n.includes("/")||n.includes("\\")||n.includes("..")))throw new x("VALIDATION_FAILED",400,`凭据 stem 派生输入含路径敌对字符(${e})——拒绝派生`)}function X(e){if(ye("provider",e.provider),ye("service",e.service),ye("instanceId",e.instanceId),ye("domain",e.domain),e.instanceId!==void 0){let n=e.domain??e.service??"global";return`${e.provider}-${e.instanceId}-${n}`}return e.service!==void 0?`${e.provider}-${e.service}`:`${e.provider}-global`}function ht(e){return`secret://${e}`}function _(e){return`config/credentials/${e}.json`}function ae(e,n){let r=An(e,_(n));if(!Cn(r))return null;try{let t=JSON.parse(yt(r,"utf8"));if(typeof t.type!="string")return null;let{type:i,...o}=t,s={};for(let[l,p]of Object.entries(o))typeof p=="string"&&(s[l]=p);return{type:i,values:s}}catch{return null}}function _e(e,n,r){let t=An(e,_(n)),i=Cn(t);return vt(wt(t),{recursive:!0}),St(t,`${JSON.stringify({type:r.type,...r.values},null,2)}
|
|
2
|
+
`,"utf8"),i}import{mkdirSync as Rt,renameSync as It,writeFileSync as kt}from"fs";import{dirname as bt}from"path";function $(e,n){En(bt(e));let r=`${e}.tmp-${process.pid}-${Date.now()}`;kt(r,n,"utf8"),It(r,e)}function En(e){Rt(e,{recursive:!0})}import{existsSync as F,readdirSync as Le,readFileSync as ee}from"fs";import{join as V}from"path";import{existsSync as Ct,readFileSync as On,mkdirSync as At,writeFileSync as Et}from"fs";import xn from"path";function Se(e){return xn.join(e,".tbox","app.json")}function Mn(e){let n=Se(e);if(!Ct(n))return null;try{let r=JSON.parse(On(n,"utf8")),t=r?.templateVersion;return typeof t!="string"||t.trim().length===0?null:{templateVersion:t.trim(),npmModules:Array.isArray(r?.npmModules)?r.npmModules:[]}}catch{return null}}function Ot(e,n){let r=Se(e);At(xn.dirname(r),{recursive:!0}),Et(r,`${JSON.stringify(n,null,2)}
|
|
3
|
+
`,"utf8")}function $e(e){let n=Mn(e);if(n===null)return null;let r=Se(e);try{let t=JSON.parse(On(r,"utf8"));return{...n,miniappContainers:Array.isArray(t?.miniappContainers)?t.miniappContainers:[]}}catch{return{...n,miniappContainers:[]}}}function xt(e,n){let r=e.npmModules.filter(t=>t.id!==n.id);return{...e,npmModules:[...r,n]}}function Mt(e,n){return{...e,npmModules:e.npmModules.filter(r=>r.id!==n)}}function jt(e,n){let r=(e.miniappContainers??[]).filter(t=>t.id!==n.id);return{...e,miniappContainers:[...r,n]}}function Tt(e,n,r){return{...e,npmModules:e.npmModules.map(t=>t.id===n?{...t,...r}:t)}}function jn(e){return/^[a-z0-9]+(-[a-z0-9]+)*$/.test(e)&&!e.includes("..")}function Nt(e,n){if(!jn(e))throw new Error(`非法模块 id "${e}"(来自 ${n}):仅允许小写字母/数字/中划线`)}function Tn(e){try{let n=JSON.parse(e);if(!Array.isArray(n.slots))return null;let r=n.slots.filter(i=>typeof i=="string"),t={};if(n.meta&&typeof n.meta=="object"&&!Array.isArray(n.meta))for(let[i,o]of Object.entries(n.meta)){if(!o||typeof o!="object"||Array.isArray(o))continue;let{name:s,description:l}=o,p={};typeof s=="string"&&s.length>0&&(p.name=s),typeof l=="string"&&l.length>0&&(p.description=l),(p.name!==void 0||p.description!==void 0)&&(t[i]=p)}return{slots:r,meta:t}}catch{return null}}function we(e,n){let r=t=>{try{let i=JSON.parse(t),o=se(i);if(o.ok)return{kind:"strict",id:o.value.id,version:o.value.version,descriptor:o.value,declare:o.value.declare};if(o.legacy)return{kind:"legacy",detail:o.errors.join("; ")};if(i&&typeof i=="object"&&"declare"in i){let s=i;return{kind:"loose",...typeof s.id=="string"?{id:s.id}:{},declare:{providers:s.declare?.providers,consumes:s.declare?.consumes}}}return null}catch{return null}};if(n)return n.read(e,r)??null;if(!F(e))return null;try{return r(ee(e,"utf8"))}catch{return null}}function Pt(e){let n=V(e,".tbox","app.json");if(!F(n))return[];try{let r=JSON.parse(ee(n,"utf8"));return Array.isArray(r.npmModules)?r.npmModules.filter(t=>!!t&&typeof t=="object"&&typeof t.id=="string"&&typeof t.package=="string"):[]}catch{return[]}}function Vt(e){let n=V(e,".tbox-dev.local"),r=V(n,"dev-manifest.json");if(!F(r))return[];try{let t=JSON.parse(ee(r,"utf8")),i=[];for(let[o,s]of Object.entries(t.redirects??{}))typeof s!="string"||!o.startsWith("@tbox.cn/app-")||i.push({pkg:o,dir:V(n,s)});return i}catch{return[]}}function Pn(e,n){let r=[],t=[e];for(let l of["apps","packages"]){let p=V(e,l);if(F(p))try{for(let c of Le(p,{withFileTypes:!0}))c.isDirectory()&&t.push(V(p,c.name))}catch{}}let i=new Set,o=(l,p,c)=>{let m=n?n.read(p,Tn):Tn(ee(p,"utf8"));m!=null&&r.push({dir:l,slots:m.slots,meta:m.meta,via:c})},s=V(e,"config","service-slots.json");F(s)&&o(e,s,"config-override");for(let l of t){let p=V(l,"node_modules","@tbox.cn");if(!F(p))continue;let c=[];try{c=Le(p)}catch{continue}for(let m of c){let I=V(p,m);if(i.has(I))continue;i.add(I);let h=V(I,"service-slots.json"),v=V(I,"src","service-slots.json");F(h)?o(I,h,"package"):F(v)&&o(I,v,"package")}}for(let l of t)for(let p of[V(l,"service-slots.json"),V(l,"src","service-slots.json")])F(p)&&o(l,p,"local");return r}function D(e,n){let r=[],t={providers:{},services:{},credentialTypes:{}},i={},o=[],s={},l=new Set,p=(a,g,w,S)=>{for(let u of a){let y=t.providers[u.provider]??={},b=y[u.implementation];b?b.services.includes(u.service)||b.services.push(u.service):(y[u.implementation]={provider:u.provider,implementation:u.implementation,credentialType:u.credentialType,owner:g,...S?.name?{name:S.name}:{},...S?.description?{description:S.description}:{},...u.local?{local:!0}:{},...u.configSchema?{configSchema:u.configSchema}:{},...u.credentialSchema?{credentialSchema:u.credentialSchema}:{},services:[u.service]},t.credentialTypes[u.credentialType]??={owner:g,packageDir:w,...u.credentialSchema?{credentialSchema:u.credentialSchema}:{}});let d=`${u.provider}\0${u.service}`;i[d]||(i[d]={...u.configSchema?{configSchema:u.configSchema}:{},...u.credentialSchema?{credentialSchema:u.credentialSchema}:{},packageDir:w})}},c=a=>a.kind==="strict"?{name:a.descriptor.name,description:a.descriptor.description}:void 0,m=(a,g)=>{for(let w of a){let S=s[w];S===void 0?s[w]=g:S!==g&&o.push({severity:"error",code:"OWNERSHIP_CONFLICT",module:g,message:`服务 ${w} 归属冲突:${S} 与 ${g} 均声明 owns(先声明 ${S} 胜出)——修正 manifest declare.owns 互斥`})}},I=(a,g)=>{a.kind==="legacy"&&o.push({severity:"error",code:"OLD_MANIFEST_KEY",module:g,message:`${g}:${a.detail}`})},h=a=>a.kind==="strict"||a.kind==="loose"?a.declare:null,v=(a,g)=>{let w=a.optional!==!1,S=a.defaults??[],u=t.services[a.service];if(u){u.optional=u.optional&&w;let y=new Set(u.defaults.map(b=>`${b.provider}\0${b.implementation}`));for(let b of S){let d=`${b.provider}\0${b.implementation}`;y.has(d)||(u.defaults.push(b),y.add(d))}u.owners.includes(g)||u.owners.push(g);return}t.services[a.service]={optional:w,defaults:[...S],...a.name?{name:a.name}:{},...a.description?{description:a.description}:{},owners:[g]}};for(let a of Pt(e)){if(l.has(a.id))continue;let g=V(e,"packages",a.id),w=V(e,"node_modules",...a.package.split("/")),S=we(V(g,"tbox.module.json"),n)??we(V(w,"tbox.module.json"),n);if(S?.kind==="legacy"){I(S,a.id),l.add(a.id);continue}if(!S)continue;l.add(a.id);let u=F(V(g,"tbox.module.json"))?g:w,y=h(S);S.kind==="strict"&&r.push({id:a.id,dir:u,pkg:a.mode==="sdk"?a.package:`@app/${a.id}`,descriptor:S.descriptor});let b=y?.providers?.slots??[];b.length&&p(b,a.package,u,c(S));let d=y?.consumes??[];for(let E of d)v(E,a.package);let R=S.kind==="strict"?S.descriptor.declare.owns:[];R.length&&m(R.map(E=>E.service),a.id)}for(let{pkg:a,dir:g}of Vt(e)){let w=we(V(g,"tbox.module.json"),n);if(w?.kind==="legacy"){I(w,a);continue}if(!w?.id||l.has(w.id))continue;l.add(w.id);let S=h(w),u=S?.providers?.slots??[];u.length&&p(u,a,g,c(w));let y=S?.consumes??[];for(let d of y)v(d,a);let b=w.kind==="strict"?w.descriptor.declare.owns:[];b.length&&m(b.map(d=>d.service),w.id)}let A=V(e,"packages");if(F(A)){let a=[];try{a=Le(A,{withFileTypes:!0}).filter(g=>g.isDirectory()).map(g=>g.name)}catch{}for(let g of a){if(l.has(g))continue;let w=V(A,g),S=we(V(w,"tbox.module.json"),n);if(S?.kind==="legacy"){I(S,g),l.add(g);continue}if(!S)continue;let u=S.id??g;if(l.has(u))continue;l.add(u);let y=h(S);S.kind==="strict"&&r.push({id:u,dir:w,pkg:`@app/${u}`,descriptor:S.descriptor});let b=y?.providers?.slots??[];b.length&&p(b,`@app/${u}`,w,c(S));let d=y?.consumes??[];for(let E of d)v(E,`@app/${u}`);let R=S.kind==="strict"?S.descriptor.declare.owns:[];R.length&&m(R.map(E=>E.service),u)}}let O=new Set,f={};for(let a of Pn(e,n)){for(let g of a.slots)O.add(g);for(let[g,w]of Object.entries(a.meta))f[g]===void 0&&(f[g]=w)}return{modules:r,catalog:t,serviceSchemas:i,vocabulary:[...O].sort(),slotMeta:f,ownership:s,declarationIssues:o}}function Nn(e,n,r){let t=V(e,"src",n,"index.ts");if(!F(t))return!1;try{let i=ee(t,"utf8");return new RegExp(`export\\s+const\\s+${r}\\b`).test(i)}catch{return!1}}function Dt(e){let n=V(e,"src","server","index.ts");if(!F(n))return"";try{return ee(n,"utf8")}catch{return""}}function Vn(e){return e.match(/declaration\s*:\s*\{[\s\S]*?moduleId\s*:\s*['"]([^'"]+)['"]/)?.[1]}function Ft(e){let n=[],r=D(e),t=$e(e),i=new Map;for(let o of t?.npmModules??[])i.set(o.id,o.mode);for(let o of r.modules){let s=i.get(o.id)??"local",l=Nn(o.dir,"server","serverModule"),p=o.descriptor.declare;n.push({id:o.id,pkg:s==="sdk"?o.pkg:`@app/${o.id}`,mode:s,hasServerEntry:l,hasClientEntry:Nn(o.dir,"client","clientModule"),hasCards:(p.cards?.length??0)>0,...l?{moduleId:Vn(Dt(o.dir))}:{}})}return n.sort((o,s)=>o.id.localeCompare(s.id))}function _t(e){return D(e).ownership}function L(e,n){let r=e?.modules?.[n]?.provider;if(typeof r=="string"&&r.length>0)return{provider:r,layer:"module"};let t=e?.provider;return typeof t=="string"&&t.length>0?{provider:t,layer:"app"}:{provider:null,layer:null}}function G(e,n){let r=(n.descriptor.declare.owns??[]).map(t=>t.service).sort();return r.length===0?{writable:!1,reason:"zero-ownership",ownedServices:[]}:{writable:!0,ownedServices:r}}function We(e,n){return[...new Set(Object.values(e.providers[n]??{}).flatMap(r=>r.services))].sort()}function H(e){if(!e||typeof e!="object")return!1;let n=Object.keys(e),r=new Set(["provider","credentialType","configSchema"]);if(!n.every(i=>r.has(i)))return!1;let t=e;return typeof t.provider=="string"&&t.provider.length>0&&typeof t.credentialType=="string"&&t.credentialType.length>0&&(t.configSchema===void 0||typeof t.configSchema=="string")}function Dn(e,n,r){return e==="*"||r.has(e)?null:{severity:"error",code:"INSTANCE_KEY_NOT_REGISTERED",instance:e,message:`integrations: ${n} 键 ${e} 不在 malls 白名单内(${[...r].join(", ")})`}}function Be(e,n){let r=new Set(n),t=[],i=(o,s)=>{let l=Dn(o,s,r);l&&t.push(l)};for(let o of Object.keys(e.configByInstance??{}))i(o,"configByInstance");for(let o of Object.keys(e.credentialRefByInstance??{}))i(o,"credentialRefByInstance");for(let[o,s]of Object.entries(e.services??{}))for(let l of Object.keys(s.instances??{}))i(l,`services.${o}.instances`);return t}function ne(e){let n=[],r=e.contracts,{integrations:t,suppliedProviders:i,demandedServices:o,supplies:s,malls:l,credentialSchemaMissing:p,vendorConfigKeys:c,vendorGlobalConfigKeys:m,vendorConfigSchemaMissing:I,credentialFileMissing:h,credentialFileType:v,realmSwitchHints:A,moduleResourceNeeds:O,ownership:f,installedModuleIds:a}=e,g=l?new Set(l):void 0;for(let d of A??[])n.push({severity:"warning",code:"REALM_SWITCH_HINT",message:d});let w=new Set(Object.keys(i).map(d=>d.slice(0,d.indexOf("\0"))).filter(d=>d.length>0)),S=(d,R,E,C)=>{if(typeof E?.provider=="string"&&typeof E.implementation=="string"&&E.provider&&E.implementation)return i[ce(E.provider,E.implementation)]?.credentialType;if(typeof R.provider=="string"&&typeof R.implementation=="string")return i[ce(R.provider,R.implementation)]?.credentialType;let M=R.provider?.credentialType;if(typeof M=="string")return M;if(!s)return;let N=C??Object.keys(R.instances??{})[0]??"",j=r.resolveEffectiveService(t,d,N,s,f);if(!(j.status!=="ok"||typeof j.effective.provider!="string"))return i[ce(j.effective.provider,j.effective.implementation)]?.credentialType};if(h||v)for(let[d,R]of Object.entries(t.services))for(let[E,C]of Object.entries(R.instances??{})){if(C.enabled===!1)continue;let M=C.credentialRef??R.credentialRef??t.credentialRefByInstance?.[E]??t.credentialRef;if(typeof M!="string"||!M.startsWith("secret://"))continue;let N=M.slice(9);h?.[N]===!0&&n.push({severity:"error",code:"CREDENTIAL_FILE_MISSING",service:d,instance:E,message:`integrations: 凭据文件缺失 ${N}(${d}@${E} effective ref=${M};档内 config/credentials/ 无此文件)`});let j=v?.[N];if(j){let P=S(d,R,C,E);P&&j!==P&&n.push({severity:"error",code:"CREDENTIAL_TYPE_MISMATCH",service:d,instance:E,message:`integrations: 凭据文件 ${N}.json type=${j} 与绑定 credentialType ${P} 不一致(${d}@${E}——transport 创建期将按 type 选策略)`})}}let u=(d,R)=>{if(!g)return;let E=Dn(d,R,g);E&&n.push(E)};for(let[d]of Object.entries(t.configByInstance??{}))u(d,"configByInstance");for(let[d]of Object.entries(t.credentialRefByInstance??{}))u(d,"credentialRefByInstance");let y=Object.entries(t.services).filter(([,d])=>d.instances==null||d.instances["*"]!=null).map(([d])=>d);if(y.length>0){let d=Object.entries(t.services).filter(([,R])=>R.instances!=null&&R.instances["*"]==null).map(([R])=>R);d.length>0&&n.push({severity:"warning",code:"WILDCARD_ALIGNMENT",message:`integrations: 激活形态不对称(通配:${y.join(", ")};显式键集:${d.join(", ")})——动态 mallId 将在显式键集槽上 INSTANCE_NOT_FOUND(provider 业务限制表达位),确认是否齐步`})}let b=r.normalizeInstances({instances:t.instances,defaultInstanceId:t.defaultInstanceId});b.instances.length>=2&&b.defaultInstanceId===null&&n.push({severity:"warning",code:"MULTI_INSTANCE_NO_DEFAULT",message:`integrations: ${b.instances.length} 个部署实例(${b.instances.map(d=>d.id).join(", ")})均无 defaultInstanceId——无 scope 参数访问将落全局会话(默认商圈不注入)`});for(let[d,R]of Object.entries(t.services)){if(!o[d]&&f?.[d]===void 0&&n.push({severity:"warning",code:"SLOT_NOT_DECLARED",service:d,message:`integrations: 服务槽 ${d} 无消费方声明(拼写错误或需求方未安装)——若为拆分前旧槽位词汇(member.main/parking.main/promotion.read/shopping-guide.main),参照 cookbook·app-config 槽位迁移配方展开为新槽`}),typeof R.provider=="string"?typeof R.implementation=="string"&&!i[ce(R.provider,R.implementation)]&&n.push({severity:"error",code:"INSTANCE_SUPPLY_UNMATCHED",service:d,message:`integrations: provider ${R.provider}/${R.implementation} 未命中已装供给(${d} 槽级)——装对应 provider 包或改绑`}):R.provider!==void 0&&!H(R.provider)&&n.push({severity:"error",code:"INLINE_PROVIDER_INVALID",service:d,message:`integrations: 内联 provider 超受控形状(${d} 槽级;允许键 provider/credentialType/configSchema)`}),p){let C=S(d,R);C&&p[C]===!0&&n.push({severity:"error",code:"SCHEMA_FILE_MISSING",service:d,message:`integrations: credentialType ${C} 的 schema 引用不存在(${d};manifest 声明指向缺失文件)`})}typeof R.provider=="object"&&typeof R.implementation!="string"&&n.push({severity:"error",code:"IMPL_WITHOUT_PROVIDER",service:d,message:`integrations: 内联厂商声明必须同时提供 implementation(${d} 槽级)`});for(let[C,M]of Object.entries(R.instances??{})){u(C,`services.${d}.instances`);let N=M.provider!==void 0,j=M.implementation!==void 0;if(j&&!N&&n.push({severity:"error",code:"IMPL_WITHOUT_PROVIDER",service:d,instance:C,message:`integrations: 实例级 implementation 需伴随 provider(${d}@${C}——impl-only 禁止,provider 是绑定组头)`}),N&&j){let P=M.provider,W=M.implementation;typeof P=="string"&&typeof W=="string"?i[ce(P,W)]||n.push({severity:"error",code:"INSTANCE_SUPPLY_UNMATCHED",service:d,instance:C,message:`integrations: 实例级 provider 覆盖 ${P}/${W} 未命中已装供给(${d}@${C})`}):H(P)||n.push({severity:"error",code:"INLINE_PROVIDER_INVALID",service:d,instance:C,message:`integrations: 实例级内联 provider 超受控形状(${d}@${C})`})}}}for(let[d,R]of[["root",t.provider],...Object.entries(t.modules??{}).map(([E,C])=>[`modules.${E}`,C?.provider])])typeof R!="string"||R.length===0||w.has(R)||n.push({severity:"error",code:"VENDOR_NOT_INSTALLED",module:d.startsWith("modules.")?d.slice(8):void 0,message:`integrations: ${d} provider ${R} 未命中已装供给——装对应 provider 包或 provider use 改绑`});if(s)for(let[d,R]of Object.entries(t.services)){let E=R.instances?Object.keys(R.instances):[""];for(let C of E){let M=r.resolveEffectiveService(t,d,C,s,f);M.status==="binding-unresolved"&&n.push({severity:"error",code:"BINDING_UNRESOLVED",service:d,instance:C||void 0,message:`integrations: ${M.message}`})}}for(let[d,R]of Object.entries(t.services))R.implementation!==void 0&&R.provider===void 0&&n.push({severity:"error",code:"IMPL_WITHOUT_PROVIDER",service:d,message:`integrations: 槽级 implementation 需伴随 provider(${d}——impl-only 禁止,provider 是绑定组头)`});for(let[d,R]of Object.entries(t.modules??{})){if(!(R?.provider!==void 0||R?.config!==void 0))continue;let C=a?!a.has(d):!1,M=0;if(f)for(let j of Object.values(f))j===d&&(M+=1);if(C||!(f===void 0)&&M===0){let j=C?"未安装(键 = install id)":"未声明任何 owns(无模块级配置位)";n.push({severity:"error",code:"MODULE_CONFIG_DEAD",module:d,message:`integrations: modules.${d} 携带 provider/config 但模块${j}(MODULE_CONFIG_DEAD——模块级集成位作用于 declare.owns 服务,改 declare.owns 或删除该节点)`})}}if(c){let d=new Set,R=!1,E=C=>{typeof C!="string"||C.length===0||(c[C]&&d.add(C),!c[C]&&!I?.[C]&&(R=!0),I?.[C]&&(R=!0))};E(t.provider);for(let C of Object.values(t.modules??{}))E(C?.provider);for(let C of Object.values(t.services)){let M=C.provider;E(typeof C.provider=="string"?C.provider:M?.provider)}if(d.size>0&&!R){let C=new Set;for(let j of d)for(let P of c[j]??[])C.add(P);let M=new Set;for(let j of d)for(let P of m?.[j]??[])M.add(P);let N=(j,P,W,Z)=>{for(let[Q]of Object.entries(j??{}))(W??C).has(Q)?Z&&Z.size>0&&!Z.has(Q)&&n.push({severity:"warning",code:"GLOBAL_FIELD_UNDECLARED",message:`integrations: ${P} 键 ${Q} 过 schema 校验但未声明 x-tbox-global(不进应用/模块全局表单;已配置值照常生效——如需全局编辑请在 provider schema 标记)`}):n.push({severity:"error",code:"DOMAIN_CONFIG_INVALID",message:`integrations: ${P} 键 ${Q} 不在引用厂商(${[...d].join("/")})任何槽 schema properties 内(死配置)`})};N(t.config,"root.config",void 0,M);for(let[j,P]of Object.entries(t.configByInstance??{}))N(P,`root.configByInstance[${j}]`,void 0,M);for(let[j,P]of Object.entries(t.modules??{})){if(!P?.config)continue;let W=L(t,j).provider??void 0;if(W===void 0){N(P.config,`modules.${j}.config`,void 0,M);continue}let Z=c[W];if(!Z||I?.[W])continue;let Q=m?.[W];N(P.config,`modules.${j}.config`,new Set(Z),Q)}}}for(let[d,R]of Object.entries(o)){let E=t.services[d];if(!E){n.push({severity:"warning",code:"SLOT_NOT_CONFIGURED",service:d,message:`integrations: 服务槽 ${d}(需求方 ${R.owners.join(", ")})未配置${R.optional?"(可选槽)":"(必需槽——模块将走降级链)"}`});continue}let C=Object.entries(E.instances??{}).filter(([,M])=>M.enabled===!1).map(([M])=>M);C.length>0&&n.push({severity:"warning",code:"INSTANCE_DISABLED",service:d,instance:C.join(", "),message:`integrations: ${d} 实例禁用(${C.join(", ")})`})}for(let[d,R]of Object.entries(t.modules??{})){let E=O?.[d];O&&!(d in O)&&n.push({severity:"warning",code:"RESOURCE_NOT_DECLARED",module:d,message:`integrations: modules.${d} 未命中已装模块(键 = install id——检查 .tbox/app.json entry.id / packages/ 目录名)`});for(let[C,M]of Object.entries(R?.resources??{})){let N=M?.type;(typeof N!="string"||!r.RESOURCE_TYPE_IDS.includes(N))&&n.push({severity:"error",code:"RESOURCE_TYPE_UNKNOWN",module:d,message:`integrations: modules.${d}.resources.${C} type 非法(${String(N)};词汇表 = ${r.RESOURCE_TYPE_IDS.join("/")})`}),E&&E.size>0&&!E.has(C)&&n.push({severity:"warning",code:"RESOURCE_NOT_DECLARED",module:d,message:`integrations: modules.${d}.resources.${C} 未被模块 manifest declare.resources 声明`})}}return n}function ce(e,n){return`${e}\0${n}`}import{existsSync as Ue,readFileSync as $t,readdirSync as Lt}from"fs";import{join as he}from"path";function _n(e){return e.replaceAll("-","_").toUpperCase()}function Fn(e){if(!Ue(e))return null;try{let n=JSON.parse($t(e,"utf8"));return n&&typeof n=="object"?n:null}catch{return null}}function Wt(e){let n=new Set,r=e.properties;if(r&&typeof r=="object"&&!Array.isArray(r))for(let t of Object.keys(r))n.add(t);return n}function de(e,n,r,t=process.env){let i={};for(let[u,y]of Object.entries(n.catalog.providers))for(let[b,d]of Object.entries(y))i[`${u}\0${b}`]={services:[...d.services],owner:d.owner,credentialType:d.credentialType};let o={};for(let[u,y]of Object.entries(n.catalog.services))o[u]={optional:y.optional,owners:[...y.owners]};let s={},l={},p={},c={},m={};for(let u of n.modules){m[u.id]=new Set((u.descriptor.declare.resources??[]).map(y=>y.id));for(let y of u.descriptor.declare.providers?.slots??[]){if(y.configSchema){let b=Fn(he(u.dir,y.configSchema));if(b){let d=s[y.provider]??=new Set,R=l[y.provider]??=new Set;for(let C of Wt(b))d.add(C);let E=b.properties;if(E&&typeof E=="object"&&!Array.isArray(E))for(let[C,M]of Object.entries(E))M&&typeof M=="object"&&M["x-tbox-global"]===!0&&R.add(C)}else p[y.provider]=!0}y.credentialSchema&&!Ue(he(u.dir,y.credentialSchema))&&(c[y.credentialType]=!0)}}let I={},h=new Set,v=he(e,"config","credentials");if(Ue(v))for(let u of Lt(v)){if(!u.endsWith(".json"))continue;let y=u.slice(0,-5);h.add(y);let b=Fn(he(v,u));b&&typeof b.type=="string"&&(I[y]=b.type)}let A=r,O=[],f=u=>{typeof u=="string"&&u.startsWith("secret://")&&O.push(u)};for(let u of Object.values(A.services??{}))if(u&&typeof u=="object"){f(u.credentialRef);for(let y of Object.values(u.instances??{}))y&&typeof y=="object"&&f(y.credentialRef)}for(let u of Object.values(A.credentialRefByInstance??{}))f(u);f(A.credentialRef);let a={};for(let u of O){let y=u.slice(9);t[_n(y)]===void 0&&(h.has(y)||(a[y]=!0))}let g=[];for(let[u,y]of Object.entries(A.services??{})){let b=y&&typeof y=="object"&&typeof y.provider=="string"?y.provider:void 0;for(let[d,R]of Object.entries((y&&typeof y=="object"?y.instances:void 0)??{})){let E=R&&typeof R=="object"&&typeof R.provider=="string"?R.provider:void 0;b&&E&&E!==b&&g.push(`integrations: ${u}@${d} 实现覆盖跨厂商(${b} → ${E})——凭据域切换,确认该 mall 对应凭据在场`)}}let S=((Array.isArray(A.instances)?A.instances:void 0)??[]).map(u=>u&&typeof u=="object"&&typeof u.id=="string"?u.id:void 0).filter(u=>typeof u=="string");return{suppliedProviders:i,demandedServices:o,credentialFileMissing:a,credentialFileType:I,credentialSchemaMissing:c,vendorConfigKeys:s,vendorGlobalConfigKeys:l,vendorConfigSchemaMissing:p,realmSwitchHints:g,moduleResourceNeeds:m,...S.length>0?{malls:S}:{},ownership:n.ownership,installedModuleIds:new Set([...n.modules.map(u=>u.id),...new Set(Object.values(n.ownership))])}}import{existsSync as ti,readFileSync as ri}from"fs";import{join as oi,resolve as si}from"path";function Ke(e){return D(e).catalog}function Re(e){let n=D(e).catalog,r={};for(let[o,s]of Object.entries(n.providers)){r[o]={};for(let[l,p]of Object.entries(s))r[o][l]={provider:p.provider,implementation:p.implementation,credentialType:p.credentialType,owner:p.owner,...p.local?{local:!0}:{},...p.configSchema?{configSchema:p.configSchema}:{},...p.credentialSchema?{credentialSchema:p.credentialSchema}:{},services:[...p.services]}}let t={};for(let[o,s]of Object.entries(n.services))t[o]={optional:s.optional,defaults:s.defaults.map(l=>({...l})),owners:[...s.owners]};let i={};for(let[o,s]of Object.entries(n.credentialTypes))i[o]={owner:s.owner,...s.credentialSchema?{credentialSchema:s.credentialSchema}:{}};return{providers:r,services:t,credentialTypes:i}}async function ze(e,n,r,t=process.env){let i=r.module,o=D(e),s=i.buildSupplyLookup(Re(e)),l=de(e,o,n,t);return ne({contracts:i,integrations:n,supplies:s,...l})}import{existsSync as Ht,rmSync as Yt}from"fs";import{join as qt}from"path";import{existsSync as Bt,readFileSync as Ut}from"fs";import{join as $n}from"path";var Kt=$n("config","integrations.json");function B(e,n){let r=$n(e,Kt),t=i=>JSON.parse(i);if(n)return n.read(r,t)??null;if(!Bt(r))return null;try{return t(Ut(r,"utf8"))}catch{return null}}async function Ln(e,n){let r=await T(e),t=B(e,n);if(t===null)return{config:null,strict:!1,contracts:r};if(r.strictValidation&&r.module.parseIntegrationsConfig)try{return{config:r.module.parseIntegrationsConfig(t),strict:!0,contracts:r}}catch(i){if(i instanceof Error&&Array.isArray(i.issues)){let o=i.issues.filter(s=>Array.isArray(s.path)).map(s=>s.path.map(String).join(".")).filter(s=>s.length>0);throw new x("VALIDATION_FAILED",400,"integrations.json 校验失败",o.length>0?o:void 0)}throw new x("VALIDATION_FAILED",400,i instanceof Error?i.message:String(i))}return{config:t,strict:!1,contracts:r}}function le(e,n,r,t){return e.includes(r)||n.includes(r)||t.includes(r)}import{readdirSync as zt,existsSync as Ie,readFileSync as Jt}from"fs";import{join as ke}from"path";function Wn(e,n,r){let t=[];if(n){let i=X({provider:e});t.push({stem:i,ref:`secret://${i}`,input:n})}for(let[i,o]of Object.entries(r??{})){let s=X({provider:e,instanceId:i});t.push({instanceId:i,stem:s,ref:`secret://${s}`,input:o})}return t}function Bn(e,n,r,t,i){let o=[];if(t){let s=X({provider:e,service:n});o.push({stem:s,ref:`secret://${s}`,input:t})}for(let[s,l]of Object.entries(i??{})){let p=X({provider:e,instanceId:s,domain:r});o.push({instanceId:s,stem:p,ref:`secret://${p}`,input:l})}return o}function Ge(e,n,r){return n.map(t=>({stem:t.stem,ref:t.ref,overwrote:r?Ie(ke(e,_(t.stem))):_e(e,t.stem,t.input)}))}function Gt(e,n){return Ie(ke(e,_(n)))}function Je(e,n){if(typeof e=="string"){e.startsWith("secret://")&&n.add(e.slice(9));return}if(Array.isArray(e)){for(let r of e)Je(r,n);return}if(e&&typeof e=="object")for(let r of Object.values(e))Je(r,n)}function te(e){let n=ke(e,"config","credentials"),r=new Set,t=ke(e,"config","integrations.json");if(Ie(t))try{Je(JSON.parse(Jt(t,"utf8")),r)}catch{}let i=[];if(!Ie(n))return i;let o=[];try{o=zt(n).filter(s=>s.endsWith(".json")).map(s=>s.slice(0,-5))}catch{return i}for(let s of o.sort()){if(r.has(s))continue;let l=ae(e,s);i.push({severity:"warning",code:"ORPHANED_CREDENTIAL",message:`${_(s)} 不再被引用(凭据文件保留,可手动清理)`})}return i}function be(e){if(typeof e=="string")return e.length>0?e:void 0;if(e&&typeof e=="object"&&H(e)){let n=e.provider;return n.length>0?n:void 0}}async function Zt(e){let n=qt(e,"config","integrations.json"),r=B(e);if(r===null)return{removed:[],orphanCredentials:[],skipped:"not-configured"};let t=await T(e);if(!t.strictValidation)return{removed:[],orphanCredentials:[],skipped:"predicate-unavailable"};let i;try{let v=Fe(JSON.stringify(r),process.env);if(v.missing.length>0||v.text===void 0)return{removed:[],orphanCredentials:[],skipped:"predicate-unavailable"};i=JSON.parse(v.text)}catch{return{removed:[],orphanCredentials:[],skipped:"predicate-unavailable"}}let o;try{o=await ze(e,i,t,process.env)}catch{return{removed:[],orphanCredentials:[],skipped:"predicate-unavailable"}}let s=D(e),l=new Set(Object.keys(s.catalog.providers)),p=s.ownership,c=structuredClone(r);c.services??={};let m=[];for(let v of o)if(v.severity==="error"){if(v.code==="VENDOR_NOT_INSTALLED")if(v.module){let O=(c.modules??{})[v.module];O?.provider&&(m.push(`modules.${v.module}.provider=${String(O.provider)}`),delete O.provider,Object.keys(O).length===0&&delete c.modules[v.module])}else c.provider&&(m.push(`root.provider=${c.provider}`),delete c.provider);else if(v.code==="MODULE_CONFIG_DEAD"&&v.module){let A=c.modules??{};if(A[v.module]){let O=A[v.module],f=[O.provider!==void 0?"provider":void 0,O.config!==void 0?"config":void 0,O.resources!==void 0?"resources":void 0].filter(Boolean);m.push(`modules.${v.module}(${f.join("+")} 整节点)`),delete c.modules[v.module]}}else if(v.code==="BINDING_UNRESOLVED"&&v.service){let A=c.services[v.service];if(!A)continue;let O=p[v.service];if([v.instance?be(A.instances?.[v.instance]?.provider):void 0,be(A.provider),O!==void 0?be(c.modules?.[O]?.provider):void 0,be(c.provider)].filter(a=>typeof a=="string").some(a=>l.has(a)))continue;if(v.instance){let a=A.instances;if(!a||!(v.instance in a))continue;delete a[v.instance],m.push(`services.${v.service}.instances.${v.instance}`),Object.keys(a).length===0&&delete A.instances,Object.keys(A).length===0&&delete c.services[v.service]}else delete c.services[v.service],m.push(`services.${v.service}`)}}if(Object.keys(c.services).length===0&&delete c.services,m.length===0)return{removed:m,orphanCredentials:[]};let I=!c.provider&&Object.keys(c.services??{}).length===0&&Object.keys(c.config??{}).length===0&&Object.keys(c.configByInstance??{}).length===0&&!c.credentialRef&&Object.keys(c.credentialRefByInstance??{}).length===0&&(c.instances??[]).length===0&&c.defaultInstanceId==null&&Object.keys(c.modules??{}).length===0;if(!I&&(c.services??={},typeof t.module.parseIntegrationsConfig=="function"))try{t.module.parseIntegrationsConfig(c)}catch{return{removed:[],orphanCredentials:[],skipped:"validation-failed"}}let h=[];return I?Ht(n)&&Yt(n,{force:!0}):$(n,`${JSON.stringify(c,null,2)}
|
|
4
|
+
`),h=te(e).map(v=>v.message),{removed:m,orphanCredentials:h}}function Ce(e,n){let r=e.modules.find(i=>i.id===n);if(r)return r;let t=e.modules.filter(i=>(i.descriptor.name??i.descriptor.id)===n);if(t.length===1)return t[0];throw t.length>1?new x("MODULE_NOT_FOUND",404,`模块展示名「${n}」命中多个模块:${t.map(i=>`${i.descriptor.name}(id=${i.id})`).join(" / ")}——请改用模块 id 寻址`):new x("MODULE_NOT_FOUND",404,`模块 ${n} 非已装模块(id / 展示名均未命中)`)}function Y(e,n,r){let t=new Set;for(let s of Object.values(e.catalog.providers))for(let l of Object.values(s))for(let p of l.services)t.add(p);if(e.vocabulary.includes(r)||Object.hasOwn(e.catalog.services,r)||t.has(r)||n.includes(r)||Object.hasOwn(e.ownership,r))return r;let i=[],o=s=>{i.includes(s)||i.push(s)};for(let s of e.vocabulary)(e.slotMeta[s]?.name??e.catalog.services[s]?.name)===r&&o(s);for(let[s,l]of Object.entries(e.catalog.services))l.name===r&&o(s);if(i.length===1)return i[0];throw i.length>1?new x("SERVICE_NOT_FOUND",404,`服务展示名「${r}」命中多个服务:${i.join(" / ")}——请改用服务 id 寻址`):new x("SERVICE_NOT_FOUND",404,`服务 ${r} 不在服务词汇(已装契约包 ∪ 已配置)`)}import{existsSync as zn,readFileSync as Jn}from"fs";import{join as re,resolve as Qt}from"path";import Xt from"ajv";var ue=["provider","config","configByInstance","credentialRef","credentialRefByInstance","instances","defaultInstanceId"],pe=["provider","config"];var q=re("config","integrations.json");function ie(e,n){if(e===n)return!0;if(Array.isArray(e)&&Array.isArray(n))return e.length!==n.length?!1:e.every((r,t)=>ie(r,n[t]));if(e&&n&&typeof e=="object"&&typeof n=="object"){let r=Object.keys(e),t=Object.keys(n);return r.length!==t.length?!1:r.every(i=>ie(e[i],n[i]))}return!1}function Oe(e,n){if(typeof e!="string"&&e&&typeof e=="object")for(let[r,t]of Object.entries(e)){if((r==="provider"||r==="instanceId")&&typeof t=="string"&&!z.test(t))throw new x("VALIDATION_FAILED",400,`${r} 名含非法字符(需 /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/)`,[`${n}.${r}`]);Oe(t,`${n}.${r}`)}}function Ae(e,n,r){if(!(!e||typeof e!="object"||Array.isArray(e))){for(let t of Object.keys(e))if(!(r&&(t==="*"||t==="**"))&&!z.test(t))throw new x("VALIDATION_FAILED",400,`${n} 键 ${t} 含非法字符(需 /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/)——进凭据 stem 派生,防路径逃逸`,[n])}}function Un(e,n,r){if(r==="root"){let t=e.instances;Array.isArray(t)&&t.forEach((i,o)=>{let s=i&&typeof i=="object"?i.id:void 0;if(typeof s=="string"&&!z.test(s))throw new x("VALIDATION_FAILED",400,`instances[${o}].id 含非法字符(需 /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/)`,[`root.instances[${o}].id`])}),Ae(e.configByInstance,"root.configByInstance",!1),Ae(e.credentialRefByInstance,"root.credentialRefByInstance",!1)}else Ae(e.instances,"services.instances",!0);Ae(n.credentialsByInstance,"credentialsByInstance",!1)}function Ee(e,n){let r=re(e,q),t=i=>JSON.parse(i);if(n)return n.read(r,t)??null;if(!zn(r))return null;try{return t(Jn(r,"utf8"))}catch{return null}}function He(e){let n=(e.instances??[]).map(r=>r.id);return n.length===0?[]:Be(e,n)}function er(e,n,r,t){let{catalog:i}=D(e,t),o=i.providers[n];if(!o)return;let s=new Set;for(let l of Object.values(o))(r===void 0||l.services.includes(r))&&s.add(l.credentialType);return s.size===1?[...s][0]:void 0}function Kn(e,n,r,t,i,o){if(typeof t.type!="string"||t.type.length===0)throw new x("VALIDATION_FAILED",400,"凭据 type 缺失或为空字符串",["credentials.type"]);let s=i??er(e,n,r,o);if(s!==void 0&&s!=="-"&&t.type!==s)throw new x("VALIDATION_FAILED",400,`凭据 type=${t.type} 与绑定 credentialType ${s} 不一致`,["credentials.type"]);if(r===void 0)return;let{serviceSchemas:l}=D(e,o),p=l[`${n}\0${r}`];if(!p?.credentialSchema)return;let c=Qt(p.packageDir,p.credentialSchema);if(zn(c))try{let I=new Xt({allErrors:!0}).compile(JSON.parse(Jn(c,"utf8")));if(!I({type:t.type,...t.values})){let h=(I.errors??[]).map(v=>`credentials.values.${String(v.instancePath||v.params?.missingProperty||"").replace(/^\//,"")}`);throw new x("VALIDATION_FAILED",400,"凭据字段校验失败(ajv 字段级)",h)}}catch(m){if(m instanceof x)throw m}}function Ye(e,n={}){let{onApplied:r,cache:t}=n;function i(c,m,I,h){let v=c!==null,A=m.length>0,O=!h&&v,f=!h&&A;O&&($(re(e,q),`${JSON.stringify(c,null,2)}
|
|
5
|
+
`),t?.invalidate([re(e,q)]));let a=O||f;a&&I.push(...te(e));let g=a&&r!==void 0;g&&r?.();let w=[];return v&&w.push(q),A&&w.push(...m.map(S=>_(S.stem))),{written:a,restartScheduled:g,files:w,credentials:m,issues:I}}let o;async function s(){o=await T(e)}function l(c,m){return c.filter(I=>Array.isArray(I.path)).map(I=>{let h=I.path.map(String).join(".");return m!==""&&h.startsWith(m)&&h.length>m.length?h.slice(m.length):h}).filter(I=>I.length>0)}function p(c,m,I){let h=o;if(!h||!h.strictValidation||!h.module.parseIntegrationsConfig)throw new x("CONTRACTS_NOT_RESOLVED",503,"contracts 严格校验面不可用(需 ≥0.9)——写路径门控失败(工厂边缘断言应先行拦截)");try{h.module.parseIntegrationsConfig(c)}catch(v){throw v instanceof Error&&Array.isArray(v.issues)?new x("VALIDATION_FAILED",400,"节点 schema 校验失败",l(v.issues,I)):new x("VALIDATION_FAILED",400,v instanceof Error?v.message:String(v))}}return{warmup:s,applyApp(c,m={}){Oe(c,"root"),Un(c,m,"root");let I=[],h=Ee(e,t),v=h??{services:{}};h===null&&I.push({severity:"warning",code:"SKELETON_MATERIALIZED",message:"config/integrations.json 缺席——已物化骨架(写时自动初始化;R13 语义翻转提示)"});let A={...v};for(let y of ue)y in c||delete A[y];for(let[y,b]of Object.entries(c))A[y]=b;let O=typeof A.provider=="string"?A.provider:"app",f=Wn(O,m.credentials,m.credentialsByInstance);for(let y of f)Kn(e,O,void 0,y.input,void 0,t);let a=f.find(y=>y.instanceId===void 0);if(m.credentials&&a&&(A.credentialRef=a.ref),m.credentialsByInstance){let y={...A.credentialRefByInstance??{}};for(let b of f)b.instanceId!==void 0&&(y[b.instanceId]=b.ref);A.credentialRefByInstance=y}let g=m.credentials!==void 0||m.credentialsByInstance!==void 0,w=ie(h,A);if(w&&!g)return{written:!1,restartScheduled:!1,files:[],credentials:[],issues:I};p(A,I,"");let S=m.dryRun===!0,u=Ge(e,f,S);return I.push(...He(A)),i(w?null:A,u,I,m.dryRun)},applyModule(c,m,I={}){Oe(m,"root");let{modules:h,catalog:v,ownership:A}=D(e,t),O=h.find(d=>d.id===c);if(!O)throw new x("MODULE_NOT_FOUND",404,`模块 ${c} 非已装模块`);if(!G({modules:h,catalog:v,ownership:A},O).writable)throw new x("VALIDATION_FAILED",400,`模块 ${c} 未声明任何 declare.owns——无模块级配置位(模块级 provider/config 作用于归属服务)`);let a=[],g=Ee(e,t);if(g===null&&Object.keys(m).length===0)return{written:!1,restartScheduled:!1,files:[],credentials:[],issues:a};g===null&&a.push({severity:"warning",code:"SKELETON_MATERIALIZED",message:"config/integrations.json 缺席——已物化骨架(写时自动初始化;R13 语义翻转提示)"});let w=g??{services:{}},S={...w.modules??{}},u={...S[c]??{}};for(let d of Object.keys(m))if(!pe.includes(d))throw new x("VALIDATION_FAILED",400,`模块集成位仅接受 ${pe.join("/")} 键(收到 ${d})`,[d]);let y={...u};for(let d of pe){let R=m[d];R==null||R===""||typeof R=="object"&&!Array.isArray(R)&&Object.keys(R).length===0?delete y[d]:y[d]=R}Object.keys(y).length===0?delete S[c]:S[c]=y;let b={...w,modules:S};return ie(g,b)?{written:!1,restartScheduled:!1,files:[],credentials:[],issues:a}:(p(b,a,`modules.${c}.`),a.push(...He(b)),i(b,[],a,I.dryRun))},applyService(c,m,I={}){Oe(m,"root"),Un(m,I,"slot");let h=[],v=Ee(e,t),A=D(e,t);if(!le(A.vocabulary,Object.keys(v?.services??{}),c,Object.keys(A.ownership)))throw new x("SERVICE_NOT_FOUND",404,`服务 ${c} 不在服务词汇(已装契约包 ∪ 已配置 ∪ 归属)`);v===null&&h.push({severity:"warning",code:"SKELETON_MATERIALIZED",message:"config/integrations.json 缺席——已物化骨架(写时自动初始化;R13 语义翻转提示)"});let O=v??{services:{}},f={...O.services??{}},a={...O,services:f};f[c]={...m};let g=m.provider,w=g!==null&&typeof g=="object"?g:void 0,S=typeof g=="string"?g:typeof w?.provider=="string"?w.provider:"app",u=c.includes(".")?c.slice(0,c.indexOf(".")):c,y=Bn(S,c,u,I.credentials,I.credentialsByInstance);for(let N of y)Kn(e,S,c,N.input,typeof w?.credentialType=="string"?w.credentialType:void 0,t);let b=f[c],d=y.find(N=>N.instanceId===void 0);if(I.credentials&&d&&(b.credentialRef=d.ref),I.credentialsByInstance){let N={...b.instances??{}};for(let j of y){if(j.instanceId===void 0)continue;let P={...N[j.instanceId]??{}};P.credentialRef=j.ref,N[j.instanceId]=P}b.instances=N}let R=I.credentials!==void 0||I.credentialsByInstance!==void 0,E=ie(v,a);if(E&&!R)return{written:!1,restartScheduled:!1,files:[],credentials:[],issues:h};p(a,h,`services.${c}.`);let C=I.dryRun===!0,M=Ge(e,y,C);return h.push(...He(a)),i(E?null:a,M,h,I.dryRun)},deleteService(c){let m=[],I=Ee(e,t),h=D(e,t);if(!le(h.vocabulary,Object.keys(I?.services??{}),c,Object.keys(h.ownership)))throw new x("SERVICE_NOT_FOUND",404,`服务 ${c} 不在服务词汇(已装契约包 ∪ 已配置 ∪ 归属)`);let v={...I?.services??{}};if(!(c in v))return{written:!1,restartScheduled:!1,files:[],credentials:[],issues:m};delete v[c];let A={...I??{services:{}},services:v};$(re(e,q),`${JSON.stringify(A,null,2)}
|
|
6
|
+
`),t?.invalidate([re(e,q)]),m.push(...te(e));let O=r!==void 0;return O&&r?.(),{written:!0,restartScheduled:O,files:[q],credentials:[],issues:m}}}}import{existsSync as nr}from"fs";import{join as tr}from"path";function qe(e){let n=tr(e,"config","integrations.json");if(nr(n))return{generated:!1,reason:"in-place",services:[]};let r=[];for(let o of D(e).modules)for(let s of o.descriptor.declare.providers?.slots??[])s.local===!0&&r.push({service:s.service,provider:s.provider,implementation:s.implementation});if(r.length===0)return{generated:!1,reason:"no-local-slots",services:[]};let t={},i=new Set(r.map(o=>o.provider));if(i.size===1){let[o]=i;for(let s of r)t[s.service]={};$(n,`${JSON.stringify({provider:o,services:t},null,2)}
|
|
7
|
+
`)}else{for(let o of r)t[o.service]={provider:o.provider,implementation:o.implementation};$(n,`${JSON.stringify({services:t},null,2)}
|
|
8
|
+
`)}return{generated:!0,reason:"generated",services:r.map(o=>o.service).sort()}}import{existsSync as rr,readFileSync as ir}from"fs";import{join as Zn}from"path";function Gn(e,n){let r=D(e.appDir,e.cache),t=B(e.appDir,e.cache);return{appDir:e.appDir,walk:r,catalog:r.catalog,integrations:t,contracts:n,...e.cache?{cache:e.cache}:{}}}function Hn(e){let n=new Set;for(let r of e.modules){for(let t of r.descriptor.declare.owns??[])n.add(t.service);for(let t of r.descriptor.declare.consumes??[])n.add(t.service);for(let t of r.descriptor.declare.providers?.slots??[])n.add(t.service)}return n}function xe(e,n,r){let t=e.providers[n];return t?Object.values(t).some(i=>i.services.includes(r)):!1}function Yn(e,n){let r=[];for(let[t,i]of Object.entries(e.providers))Object.values(i).some(o=>o.services.includes(n))&&r.push(t);return r.sort()}function U(e,n){let r=e.slotMeta[n],t=e.catalog.services[n],i=r?.name??t?.name??n,o=r?.description??t?.description;return{name:i,...o!==void 0?{description:o}:{}}}var or=Zn("config","knowledge.json");function sr(e,n,r){let i=r[n]?.resources;if(!i||typeof i!="object"||Array.isArray(i))return null;let o=Zn(e.appDir,or),s={};if(rr(o))try{s=(e.cache?.read(o,c=>JSON.parse(c))??JSON.parse(ir(o,"utf8"))).knowledge_bases??{}}catch{s={}}let l={};for(let[p,c]of Object.entries(i)){if(!c||typeof c!="object"||Array.isArray(c))continue;let m=c,I=m.type==="knowledge"?"knowledge":String(m.type??"knowledge"),h=typeof m.datasetId=="string"&&m.datasetId!==""?m.datasetId:void 0,v=typeof m.ref=="string"&&m.ref!==""?m.ref:void 0,A=h??(v!==void 0&&typeof s[v]?.datasetId=="string"?s[v].datasetId:null),O={type:I,...h!==void 0?{datasetId:h}:{},...v!==void 0?{ref:v}:{},resolvedDatasetId:A,...typeof m.topK=="number"?{topK:m.topK}:{},...typeof m.scoreThreshold=="number"?{scoreThreshold:m.scoreThreshold}:{}};l[p]=O}return Object.keys(l).length>0?l:null}function qn(e){return e.replace(/^@tbox\.cn\/app-/,"").replace(/^@[^/]+\//,"")}function ar(e){return qn(e.id).startsWith("provider-")||qn(e.pkg).startsWith("provider-")}function Ze(e,n={}){return{modules:e.walk.modules.filter(t=>!ar(t)).filter(t=>n.includeHidden===!0||t.descriptor.hidden!==!0).map(t=>({id:t.id,name:t.descriptor.name??t.descriptor.id,description:t.descriptor.description??"",...t.descriptor.hidden===!0?{hidden:!0}:{}})).sort((t,i)=>t.id.localeCompare(i.id))}}function Qe(e,n){let r=e.walk.modules.find(c=>c.id===n);if(!r)throw new x("MODULE_NOT_FOUND",404,`模块 ${n} 非已装模块`);let t=(r.descriptor.declare.consumes??[]).map(c=>{let m=U(e.walk,c.service);return{service:c.service,name:m.name,...m.description!==void 0?{description:m.description}:{},required:c.optional===!1}}),i=G(e.walk,r),o=e.integrations?.modules??{},s=o[n],l=s?{...typeof s.provider=="string"?{provider:s.provider}:{},...s.config&&typeof s.config=="object"&&!Array.isArray(s.config)?{config:s.config}:{}}:null,p=L(e.integrations,n);return{name:r.descriptor.name??r.descriptor.id,description:r.descriptor.description??"",...r.descriptor.hidden===!0?{hidden:!0}:{},ownedServices:i.ownedServices,integration:l,resources:sr(e,n,o),binding:{provider:p.provider,layer:p.layer},configEditable:i.writable,services:t}}function Xe(e){let n=Hn(e.walk),r=e.walk.vocabulary.filter(o=>!n.has(o)).map(o=>{let s=U(e.walk,o);return{service:o,name:s.name,...s.description!==void 0?{description:s.description}:{},required:!1}}),t=e.integrations,i=null;if(t){let o={};for(let s of ue)s in t&&(o[s]=t[s]);i=o}return{services:r,integration:i}}function en(e,n){let r=e.integrations?.services??{},t=e.catalog.services[n];if(!le(e.walk.vocabulary,Object.keys(r),n,Object.keys(e.walk.ownership)))throw new x("SERVICE_NOT_FOUND",404,`服务 ${n} 不在服务词汇(已装契约包 ∪ 已配置 ∪ 归属)`);let i=r[n]??null,o=U(e.walk,n);return{service:n,name:o.name,...o.description!==void 0?{description:o.description}:{},required:t?!t.optional:!1,defaults:t?t.defaults.map(s=>({...s})):[],integration:i,suppliedBy:Yn(e.catalog,n)}}import{existsSync as et,readFileSync as nt,realpathSync as Qn}from"fs";import{isAbsolute as cr,join as dr,relative as lr,resolve as Xn,sep as ur}from"path";function nn(e){let n=[];for(let[r,t]of Object.entries(e.catalog.providers)){let i=Object.values(t);i.length!==0&&n.push({provider:r,local:i.every(o=>o.local===!0),owner:i[0].owner,...i[0].name?{name:i[0].name}:{},...i[0].description?{description:i[0].description}:{}})}return{providers:n.sort((r,t)=>r.provider.localeCompare(t.provider))}}function tn(e,n,r){let t=e.catalog.providers[n];if(!t)throw new x("PROVIDER_NOT_FOUND",404,`厂商 ${n} 不 ∈ catalog(内联声明厂商无包级档案——身份与表单经组合端点暴露)`);let i={};for(let s of Object.values(t))for(let l of s.services)(i[l]??={implementations:[]}).implementations.push({implementation:s.implementation,credentialType:s.credentialType});for(let[s,l]of Object.entries(i)){let p=U(e.walk,s);l.name=p.name,p.description!==void 0&&(l.description=p.description)}if(r?.has("integrationSchemas"))for(let[s,l]of Object.entries(i))l.integrationSchemas={configSchema:K(e,n,s)};let o=Object.values(t);return{provider:n,local:o.every(s=>s.local===!0),owner:o[0].owner,...o[0].name?{name:o[0].name}:{},...o[0].description?{description:o[0].description}:{},services:i}}function rn(e,n,r){let t=e.catalog.providers[n],i=e.integrations?.services??{},o=[];if(t)for(let c of Object.values(t))c.services.includes(r)&&o.push({implementation:c.implementation,credentialType:c.credentialType});let s=i[r]?.provider,l=s&&typeof s=="object"&&s.provider===n?s:void 0;if(o.length===0&&!l)throw t?new x("SUPPLY_NOT_FOUND",404,`厂商 ${n} 未供给服务 ${r}(AI 帮我实现流:PUT 显式绑定后实施)`):new x("PROVIDER_NOT_FOUND",404,`厂商 ${n} 完全未知(不 ∈ catalog 且无任何内联声明)`);o.length===0&&l&&o.push({implementation:i[r]?.implementation??`${n}-inline@1`,credentialType:l.credentialType});let p=K(e,n,r,l?s?.configSchema:void 0);return{provider:n,service:r,implementations:o,integrationSchemas:{configSchema:p}}}function K(e,n,r,t){let i=e.walk.serviceSchemas[`${n}\0${r}`];return i?on(e.appDir,i.packageDir,i.configSchema):typeof t=="string"?pr(e.appDir,t):null}function on(e,n,r){if(!r)return null;let t=dr(n,r);if(!et(t))return null;try{return JSON.parse(nt(t,"utf8"))}catch{return null}}function pr(e,n){let r=Xn(e,"config","schemas"),t=Xn(e,n),i=lr(r,t);if(i===""||i.startsWith("..")||cr(i))throw new x("VALIDATION_FAILED",400,"configSchema 引用必须落在 config/schemas/ 内(禁路径逃逸)",["provider.configSchema"]);if(!et(t))return null;let o,s;try{o=Qn(r),s=Qn(t)}catch{return null}if(s!==o&&!s.startsWith(o+ur))throw new x("VALIDATION_FAILED",400,"configSchema 引用经 symlink 逃逸出 config/schemas/(realpath 复核拒绝)",["provider.configSchema"]);try{return JSON.parse(nt(t,"utf8"))}catch{return null}}function Me(e){return{version:e.version,evaluation:e.evaluation,strictValidation:e.strictValidation,notes:[...e.notes]}}function tt(e,n,r){let t=e.integrations,i=t?.services?.[n],o=i?.instances?.[r]??i?.instances?.["*"];if(o&&o.provider!==void 0)return"instance";if(i?.provider!==void 0)return"service";let s=e.walk.ownership[n];return s!==void 0&&L(e.integrations,s).layer==="module"?"module":typeof t?.provider=="string"&&t.provider.length>0?"app":null}function rt(e,n,r,t,i){let o=n.resolveEffectiveService(e.integrations,r,t,i,e.walk.ownership);if(o.status==="ok"&&o.effective){let s=o.effective.provider,l=typeof s=="string"?s:String(s?.provider??"");return{status:"ok",provider:l,implementation:o.effective.implementation,effective:{provider:l,implementation:o.effective.implementation,...o.effective.config!==void 0?{config:{...o.effective.config}}:{},...o.effective.credentialRef!==void 0?{credentialRef:o.effective.credentialRef}:{},layer:tt(e,r,t)??"app"}}}return o.status==="binding-unresolved"?{status:"binding-unresolved",statusMessage:o.message}:{status:o.status}}function it(e){let n=e.contracts.module;if(!n.resolveEffectiveService||!n.normalizeInstances)throw new x("CONTRACTS_NOT_RESOLVED",503,"contracts 求值面缺席(契约包形态异常)——重新安装或升级应用 @tbox.cn/app-contracts 后重试");return n}function sn(e,n){let r=it(n),{integrations:t,catalog:i}=n,o=r.buildSupplyLookup(i),s=t,p=r.normalizeInstances({instances:s?.instances,defaultInstanceId:s?.defaultInstanceId}).defaultInstanceId??"*",c=rt(n,r,e,p,o),m=tt(n,e,p),I=n.integrations?.services?.[e]?.provider,h=c.provider??(typeof I=="string"?I:typeof I=="object"&&I?String(I.provider):void 0),v=new Set(Object.keys(n.catalog.providers)),A=h!==void 0&&v.has(h)?fr(n.catalog,h,e):void 0,O=i.services[e],f=O!==void 0?!O.optional:void 0,a=n.walk.ownership[e];return{status:c.status,...c.statusMessage?{statusMessage:c.statusMessage}:{},...h!==void 0?{provider:h}:{},...h!==void 0&&m!==null?{layer:m}:{},...A!==void 0?{supplied:A}:{},...a!==void 0?{module:a}:{},...f!==void 0?{required:f}:{}}}function fr(e,n,r){return xe(e,n,r)}function ot(e){let n=new Set([...e.walk.vocabulary,...Object.keys(e.catalog.services),...Object.keys(e.walk.ownership)]),r=e.integrations?.services??{};for(let t of Object.keys(r))n.add(t);return[...n].sort()}function fe(e,n,r){let t={};for(let i of ot(e))r&&!r.includes(i)||(t[i]=sn(i,e));return{contracts:Me(e.contracts),resolutions:t,issues:n}}function an(e,n,r){let t=it(n),i=t.buildSupplyLookup(n.catalog),o=n.integrations,s=t.normalizeInstances({instances:o?.instances,defaultInstanceId:o?.defaultInstanceId}),l=s.instances.map(O=>O.id),p=n.integrations?.services?.[e],c=p?.instances?Object.keys(p.instances):void 0,I=st(c,l).map(O=>{let f=rt(n,t,e,O,i);return{instanceId:O,status:f.status,...f.statusMessage?{statusMessage:f.statusMessage}:{},...f.effective?{effective:f.effective}:{}}}),h=at(n,e,s.defaultInstanceId??"*"),A={...sn(e,n),instances:I,inheritance:h};return{contracts:Me(n.contracts),resolution:A,issues:r.filter(O=>O.service===e)}}function st(e,n){if(n.length>0){let r=[...n];return e?.includes("*")&&r.push("*"),r}return e!==void 0&&e.length>0?e.includes("*")?["*"]:e:[]}function at(e,n,r){let t=e.integrations,i=t?.services?.[n],o=i?.instances?.[r]??i?.instances?.["*"],s=e.walk.ownership[n],l=s!==void 0?L(t,s):{provider:null,layer:null};return[{layer:"app",...t?.provider?{provider:t.provider}:{}},{layer:"module",...l.layer==="module"&&l.provider?{provider:l.provider}:{}},{layer:"service",...typeof i?.provider=="string"?{provider:i.provider}:{},...i?.implementation?{implementation:i.implementation}:{}},{layer:"instance",...o?.provider?{provider:o.provider}:{},...o?.implementation?{implementation:o.implementation}:{}}]}function ge(e){return e.evaluation&&e.strictValidation&&e.ownershipBindingV6}function ct(e,n,r){let t=e.catalog.services[n],i=e.walk.ownership[n];return{status:"evaluation-unavailable",statusMessage:r,...i!==void 0?{module:i}:{},...t!==void 0?{required:!t.optional}:{}}}function je(e,n,r){let t=J(n),i={};for(let o of ot(e))r&&!r.includes(o)||(i[o]=ct(e,o,t));return{contracts:Me(n),resolutions:i,issues:[]}}function dt(e,n,r){let t=J(r),i={...ct(n,e,t),instances:gr(n,e),inheritance:at(n,e,mr(n))};return{contracts:Me(r),resolution:i,issues:[]}}function gr(e,n){let r=e.integrations?.services?.[n],t=e.integrations,i=Array.isArray(t?.instances)?t.instances.map(s=>s&&typeof s=="object"?s.id:void 0).filter(s=>typeof s=="string"):[],o=r?.instances?Object.keys(r.instances):void 0;return st(o,i).map(s=>({instanceId:s,status:"evaluation-unavailable"}))}function mr(e){let n=e.integrations;return typeof n?.defaultInstanceId=="string"&&n.defaultInstanceId.length>0?n.defaultInstanceId:"*"}function cn(e,n,r){if(n===null)return null;let t={};for(let i of r)t[i]={configSchema:K(e,n,i)};return{provider:n,services:t}}function oe(e){return e===null||typeof e!="object"?JSON.stringify(e??null):Array.isArray(e)?`[${e.map(oe).join(",")}]`:`{${Object.keys(e).sort().map(r=>`${JSON.stringify(r)}:${oe(e[r])}`).join(",")}}`}var vr="\0no-enum";function yr(e){let n=e.enum;return Array.isArray(n)?`[${[...new Set(n.map(oe))].sort().join(",")}]`:vr}function Sr(e){if(!e||typeof e!="object"||Array.isArray(e))return null;let n=e.type;return n===void 0?null:oe(n)}function wr(e){let n=e.map(t=>Sr(t.subschema));if(n.some(t=>t===null)||new Set(n).size>1)return null;if(n[0]==='"object"'){let t=oe(e[0].subschema);return e.every(i=>oe(i.subschema)===t)?e[0].subschema:null}return new Set(e.map(t=>yr(t.subschema))).size===1?e[0].subschema:null}function Te(e,n){let r=[],t=!0,i=new Map;for(let[s,l]of Object.entries(e.services)){let p=l.configSchema;if(p===null){r.push(s);continue}if(!p||typeof p!="object"||Array.isArray(p))continue;let c=p;c.additionalProperties===!1&&(t=!1);let m=c.properties;if(!m||typeof m!="object"||Array.isArray(m))continue;let I=Array.isArray(c.required)?c.required:[];for(let h of Object.keys(m)){let v=i.get(h)??[];v.push({service:s,subschema:m[h],required:I.includes(h)}),i.set(h,v)}}let o=[];for(let[s,l]of i)o.push({key:s,schema:wr(l),sources:l.map(({service:p,required:c})=>({service:p,required:c})),global:l.some(p=>!!p.subschema&&typeof p.subschema=="object"&&p.subschema["x-tbox-global"]===!0)});return{provider:e.provider,schemaless:r,unsupplied:[...n?.unsupplied??[]],additionalPropertiesAllowed:t,fields:o}}function dn(e,n,r,t){let i=typeof t=="string"&&t.length>0?t:void 0;if(e==="app"){if(i!==void 0)return i;let l=n.integrations?.provider;return typeof l=="string"&&l.length>0?l:null}let o=n.walk.modules.find(l=>l.id===r);return!o||!G(n.walk,o).writable?null:i!==void 0?i:L(n.integrations,o.id).provider}var lt={integrationSchemas:null,integrationFieldRegistry:null};function ut(e){return{...e,fields:e.fields.filter(n=>n.global)}}function ln(e,n){let r=dn("app",e,void 0,n);if(r===null)return lt;let t=cn(e,r,We(e.catalog,r));return{integrationSchemas:t,integrationFieldRegistry:ut(Te(t))}}function un(e,n,r){let t=dn("module",e,n,r),i=e.walk.modules.find(p=>p.id===n);if(t===null||!i)return lt;let o=(i.descriptor.declare.owns??[]).map(p=>p.service),s=p=>xe(e.catalog,t,p),l=cn(e,t,o.filter(s));return{integrationSchemas:l,integrationFieldRegistry:ut(Te(l,{unsupplied:[...new Set(o.filter(p=>!s(p)))]}))}}function hr(e){return ln(e).integrationSchemas}function Rr(e,n){return un(e,n).integrationSchemas}function Ir(e,n){let r=e.walk.ownership[n];if(r!==void 0)return L(e.integrations,r).provider;let t=e.integrations?.provider;return typeof t=="string"&&t.length>0?t:null}function Ne(e,n,r){let t=typeof r=="string"&&r.length>0?r:void 0;if(t!==void 0)return{provider:t,configSchema:K(e,t,n)};let i=e.integrations?.services?.[n]?.provider;if(i===void 0||i===""){let o=Ir(e,n);return o===null?null:{provider:o,configSchema:K(e,o,n)}}if(typeof i=="string")return{provider:i,configSchema:K(e,i,n)};if(H(i)){let o=i;return{provider:o.provider,configSchema:K(e,o.provider,n,o.configSchema)}}return null}function pn(e,n,r){let t=Ne(e,n,r);if(t===null)return null;let i={provider:t.provider,services:{[n]:{configSchema:t.configSchema}}};return Te(i)}function me(e,n){if(n===void 0||!n.startsWith("secret://"))return;let r=n.slice(9),t=ae(e,r);if(t)return{type:t.type,ref:n,file:_(r),masked:ve(t.values)}}function fn(e){let n=e.integrations,r={credential:me(e.appDir,typeof n?.credentialRef=="string"?n.credentialRef:void 0)??null,byInstance:{}};for(let{id:i}of n?.instances??[]){let o=n?.credentialRefByInstance?.[i];o!==void 0&&(r.byInstance[i]=me(e.appDir,o)??null)}let t={};for(let[i,o]of Object.entries(n?.services??{})){let s={credential:me(e.appDir,o.credentialRef)??null,byInstance:{}};for(let[l,p]of Object.entries(o.instances??{}))s.byInstance[l]=me(e.appDir,p.credentialRef)??null;t[i]=s}return{app:r,services:t}}function gn(e,n){return{types:(n===void 0?Object.keys(e.catalog.credentialTypes):[...new Set(Object.values(e.catalog.providers[n]??{}).map(t=>t.credentialType))]).sort().map(t=>{let i=e.catalog.credentialTypes[t];return{credentialType:t,owner:i?.owner??"",credentialSchema:i?on(e.appDir,i.packageDir,i.credentialSchema):null}})}}import kr from"path";var br={app:["serviceResolutions","integrationSchemas","integrationFieldRegistry"],module:["serviceResolutions","integrationSchemas","integrationFieldRegistry"],provider:["integrationSchemas"],service:["integrationSchemas","integrationFieldRegistry"]};function Pe(e,n){if(!n||n.length===0)return new Set;let r=br[e],t=[...new Set(n)].filter(i=>!r.includes(i));if(t.length>0)throw new x("VALIDATION_FAILED",400,`include 含未知或不适用于本端点的键:${t.join("、")}(白名单:${r.join("、")})`,["include"]);return new Set(n)}var pt=["integrationSchemas","integrationFieldRegistry"];function mn(e,n,r){if(!(typeof n!="string"||n.length===0)&&!pt.some(t=>r.has(t)))throw new x("VALIDATION_FAILED",400,`参数 ${e} 需与表单 include 键(${pt.join("、")})同现——轴参仅重定向表单层双投影`,[e])}function Cr(e,n={}){let r=Ve(),t=Promise.resolve(),i={appDir:e,cache:r};function o(f){if(!f.strictValidation)throw new x("CONTRACTS_NOT_RESOLVED",503,J(f));if(!f.ownershipBindingV6)throw new x("CONTRACTS_NOT_RESOLVED",503,J(f))}function s(f){return Gn(i,f)}function l(f){let a=f.integrations?.services;return a&&typeof a=="object"?Object.keys(a):[]}async function p(){let f=await T(e),a=s(f),g=a.integrations;if(g===null)return[];let w={resolveEffectiveService:c(f.module.resolveEffectiveService,"resolveEffectiveService"),buildSupplyLookup:c(f.module.buildSupplyLookup,"buildSupplyLookup"),normalizeInstances:c(f.module.normalizeInstances,"normalizeInstances"),RESOURCE_TYPE_IDS:f.module.RESOURCE_TYPE_IDS??[]},S=de(e,a.walk,g,process.env);return ne({contracts:w,integrations:g,supplies:w.buildSupplyLookup(a.catalog),...S})}function c(f,a){if(typeof f!="function")throw new x("CONTRACTS_NOT_RESOLVED",503,`contracts 求值面 ${a} 缺席(形态异常)`);return f}function m(f){let a=t.then(f,f);return t=a.catch(()=>{}),a}let I={async loadModules(f){let a=await T(e);return Ze(s(a),f)},async loadModule(f,a){let g=Pe("module",a?.include);mn("moduleProvider",a?.moduleProvider,g);let w=await T(e),S=s(w),u=Ce(S.walk,f),y=Qe(S,u.id);if(g.has("serviceResolutions")){let b=[...new Set([...y.ownedServices,...y.services.map(d=>d.service)])];y.serviceResolutions=ge(w)?await p().then(d=>fe(S,d,b)):je(S,w,b)}if(g.has("integrationSchemas")||g.has("integrationFieldRegistry")){let b=un(S,u.id,a?.moduleProvider);g.has("integrationSchemas")&&(y.integrationSchemas=b.integrationSchemas),g.has("integrationFieldRegistry")&&(y.integrationFieldRegistry=b.integrationFieldRegistry)}return y},async loadApp(f){let a=Pe("app",f?.include);mn("appProvider",f?.appProvider,a);let g=await T(e),w=s(g),S=Xe(w);if(a.has("serviceResolutions")&&(S.serviceResolutions=ge(g)?await p().then(u=>fe(w,u)):je(w,g)),a.has("integrationSchemas")||a.has("integrationFieldRegistry")){let u=ln(w,f?.appProvider);a.has("integrationSchemas")&&(S.integrationSchemas=u.integrationSchemas),a.has("integrationFieldRegistry")&&(S.integrationFieldRegistry=u.integrationFieldRegistry)}return S},async loadService(f,a){let g=Pe("service",a?.include);mn("serviceProvider",a?.serviceProvider,g);let w=await T(e),S=s(w),u=Y(S.walk,l(S),f),y=en(S,u);return g.has("integrationSchemas")&&(y.integrationSchemas=Ne(S,u,a?.serviceProvider)),g.has("integrationFieldRegistry")&&(y.integrationFieldRegistry=pn(S,u,a?.serviceProvider)),y},async loadServiceResolutions(f){let a=await T(e),g=s(a);if(!ge(a))return je(g,a,f);let w=await p();return fe(g,w,f)},async loadServiceResolution(f){let a=await T(e),g=s(a),w=Y(g.walk,l(g),f);if(!ge(a))return dt(w,g,a);let S=await p();return an(w,g,S)},async loadProviders(){let f=await T(e);return nn(s(f))},async loadProvider(f,a){let g=Pe("provider",a?.include),w=await T(e);return tn(s(w),f,g)},async loadProviderService(f,a){let g=await T(e),w=s(g),S=Y(w.walk,l(w),a);return rn(w,f,S)},async loadCredentials(){let f=await T(e);return fn(s(f))},async loadCredentialTypes(f){let a=await T(e);return gn(s(a),f)}},h=Ye(e,{onApplied:n.onApplied,cache:r}),v={async writeAppIntegration(f,a){await h.warmup();let g=await T(e);return o(g),m(()=>h.applyApp(f,a))},async writeModuleIntegration(f,a,g){await h.warmup();let w=await T(e);return o(w),m(()=>{let S=Ce(s(w).walk,f);return h.applyModule(S.id,a,g)})},async writeServiceIntegration(f,a,g){await h.warmup();let w=await T(e);return o(w),m(()=>{let S=s(w),u=Y(S.walk,l(S),f);return h.applyService(u,a,g)})},async deleteServiceIntegration(f){await h.warmup();let a=await T(e);return o(a),m(()=>{let g=s(a),w=Y(g.walk,l(g),f);return h.deleteService(w)})}},A={invalidate(){r.invalidate(),De(e)},async resolveContracts(){return T(e)},walkManifests(){return O(e)},parseModuleDescriptor(f){return se(f)},loadProviderCatalogRaw(){return Ke(e)},async readIntegrationsConfig(){return B(e,r)},async writeIntegrationsConfig(f){await h.warmup();let a=await T(e);return o(a),m(()=>Ar(e,f,r))},async ensureMockBindings(){await h.warmup();let f=await T(e);return o(f),m(()=>qe(e))},async evaluateIntegrationServices(f){await h.warmup();let a=await T(e);o(a);let g={resolveEffectiveService:c(a.module.resolveEffectiveService,"resolveEffectiveService"),buildSupplyLookup:c(a.module.buildSupplyLookup,"buildSupplyLookup"),normalizeInstances:c(a.module.normalizeInstances,"normalizeInstances"),RESOURCE_TYPE_IDS:a.module.RESOURCE_TYPE_IDS??[]};return ne({...f,contracts:g})}};function O(f){return D(f,r)}return{...I,...v,...A}}function Ar(e,n,r){let t=kr.join(e,"config","integrations.json");$(t,`${JSON.stringify(n,null,2)}
|
|
9
|
+
`),r.invalidate([t])}export{ue as APP_INTEGRATION_NODE_KEYS,x as AppToolkitError,pe as MODULE_INTEGRATION_NODE_KEYS,z as SAFE_NAME_PATTERN,Nt as assertValidModuleId,Te as buildIntegrationFieldRegistry,_t as buildOwnershipMap,de as buildPredicateAssembly,Be as checkInstanceKeys,Ft as collectDeclaredModules,J as contractsNotResolvedMessage,Cr as createAppToolkit,Ve as createFileCache,Ye as createWriteCore,Gt as credentialArtifactExists,ie as deepEqual,X as deriveStem,Pn as discoverContractPackages,me as echoForRef,En as ensureDir,qe as ensureMockBindings,ze as evaluateAppIntegrationIssues,ne as evaluateIntegrationServices,Fe as expandEnvVars,Vn as extractModuleIdFromSource,dn as formProviderOf,De as invalidateContractsResolver,H as isControlledInlineProvider,jn as isValidModuleId,hr as loadAppIntegrationSchemas,Xe as loadAppView,gn as loadCredentialTypesView,fn as loadCredentialsView,Qe as loadModuleDetailView,Rr as loadModuleIntegrationSchemas,Ze as loadModulesView,Re as loadProviderCatalog,Ke as loadProviderCatalogRaw,tn as loadProviderDetailView,rn as loadProviderServiceDetailView,nn as loadProvidersView,en as loadServiceDetailView,pn as loadServiceFieldRegistry,Ne as loadServiceIntegrationSchemas,an as loadServiceResolutionDetail,fe as loadServiceResolutionsView,Se as manifestPath,ve as maskCredentialValues,Sn as moduleDependencySchema,kn as moduleDescriptorSchema,G as moduleOwnershipWritable,vn as pageContribSchema,se as parseModuleDescriptor,We as providerFootprint,wn as providerSlotContribSchema,Zt as pruneIntegrationBindings,Mn as readAppManifest,$e as readAppManifestFull,ae as readCredentialFile,B as readIntegrationsConfig,Ln as readIntegrationsStrict,te as reconcileOrphanCredentials,_n as refToEnvKey,Mt as removeNpmModule,T as resolveContractsForApp,T as resolveContractsForAppExport,cn as resolveLayerIntegrationSchemas,L as resolveModuleBinding,Ce as resolveModuleKey,Y as resolveServiceKey,sn as resolveServiceSummary,In as resourceNeedContribSchema,hn as serviceConsumeContribSchema,Rn as serviceOwnContribSchema,_ as stemToFilePath,ht as stemToRef,yn as tabContribSchema,Tt as updateNpmModule,jt as upsertMiniappContainer,xt as upsertNpmModule,D as walkManifests,Ot as writeAppManifest,$ as writeAtomic,_e as writeCredentialFile};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tbox.cn/app-toolkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "tbox 应用工具面(运行面/工具面对仗:app-sdk 给运行的应用用,app-toolkit 给操作应用的工具用)——模块解析、集成配置求值/校验/写入内核,contracts 经应用侧动态解析(沙箱与目标应用版本解耦)。",
|
|
6
6
|
"exports": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"zod": "3.25.76"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@tbox.cn/app-contracts": "0.12.
|
|
21
|
+
"@tbox.cn/app-contracts": "0.12.1",
|
|
22
22
|
"typescript": "5.9.3",
|
|
23
23
|
"tsup": "8.5.1",
|
|
24
24
|
"vitest": "4.1.10",
|