@tbox.cn/app-toolkit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +50 -0
- package/dist/chunk-VV3ERZXS.js +1 -0
- package/dist/contracts-resolver-QM4FBQQV.js +1 -0
- package/dist/index.d.ts +1909 -0
- package/dist/index.js +8 -0
- package/package.json +47 -0
- package/src/assembly/app-manifest.ts +132 -0
- package/src/assembly/provider-catalog.ts +167 -0
- package/src/assembly/walk-manifests.ts +461 -0
- package/src/core/contracts-expected.ts +31 -0
- package/src/core/contracts-resolver.ts +274 -0
- package/src/core/credential-format.ts +98 -0
- package/src/core/credential-mask.ts +19 -0
- package/src/core/env-expansion.ts +51 -0
- package/src/core/errors.ts +46 -0
- package/src/core/file-cache.ts +65 -0
- package/src/core/fskit.ts +21 -0
- package/src/core/module-schema.ts +139 -0
- package/src/dto.ts +298 -0
- package/src/factory.ts +297 -0
- package/src/index.ts +137 -0
- package/src/integrations/credentials.ts +153 -0
- package/src/integrations/mock-bindings.ts +55 -0
- package/src/integrations/predicate-io.ts +199 -0
- package/src/integrations/predicate.ts +598 -0
- package/src/integrations/read.ts +53 -0
- package/src/integrations/write.ts +448 -0
- package/src/views/app.ts +28 -0
- package/src/views/context.ts +70 -0
- package/src/views/modules.ts +48 -0
- package/src/views/providers.ts +165 -0
- package/src/views/service-detail.ts +32 -0
- package/src/views/service-resolutions.ts +323 -0
- package/tests/contracts-resolver.test.ts +203 -0
- package/tests/demo-app.ts +146 -0
- package/tests/dev-manifest-catalog.test.ts +114 -0
- package/tests/error-name-safety.test.ts +26 -0
- package/tests/file-cache.test.ts +242 -0
- package/tests/import-layers.test.ts +111 -0
- package/tests/module-schema.test.ts +84 -0
- package/tests/naming-alignment.test.ts +50 -0
- package/tests/views.test.ts +427 -0
- package/tests/write-core.test.ts +188 -0
- package/tsconfig.json +11 -0
- package/tsup.config.ts +29 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 tbox.cn
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# @tbox.cn/app-toolkit
|
|
2
|
+
|
|
3
|
+
tbox 应用**工具面**包(与 `@tbox.cn/app-sdk` 运行面/工具面对仗:sdk 给运行的应用用,toolkit 给操作应用的工具用——22 个工厂方法全部以 appDir 为首参)。
|
|
4
|
+
|
|
5
|
+
模块解析、集成配置求值/校验/写入内核。**contracts 求值与校验语义由应用自己的 `@tbox.cn/app-contracts` 版本动态驱动**(`core/contracts-resolver`)——沙箱镜像内 toolkit 与目标应用版本节奏解耦,呈现给用户的求值结果与写出的文件恒由应用自身 contracts 求值/校验。
|
|
6
|
+
|
|
7
|
+
## 分层(四层线性链,import 只准向下;`tests/import-layers.test.ts` 包内自测锁)
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
core/ 零领域依赖:descriptor zod、env 展开(纯数据)、凭据格式、fskit 原子写、file-cache、contracts 动态解析器、期望面锁
|
|
11
|
+
assembly/ 目录知识:walkManifests 单次遍历四产物、provider catalog、per-service schema 表
|
|
12
|
+
integrations/ 领域:谓词单源(doctor 同源)、写核心(PUT 节点全量替换)、mock 绑定、凭据双工件
|
|
13
|
+
views/ 视图装配:modules / app / service-detail / service-resolutions / providers 五投影 + 工厂
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
禁 import `@tbox.cn/app-sdk`(叶包);反向 app-sdk → toolkit 仅一条**永久生态兼容 re-export 桥**(`loadProviderCatalog` + `expandEnvVars`——存量克隆应用模板导入零改动,桥源形态冻结)。
|
|
17
|
+
|
|
18
|
+
## Freshness Contract(公开契约)
|
|
19
|
+
|
|
20
|
+
> **每个公开方法调用,反映调用开始前已完成的全部文件系统状态变更——无需调用方显式失效。**
|
|
21
|
+
> 新鲜度承诺单位是**方法调用**,不是实例(长生命周期进程级单例安全的前提)。
|
|
22
|
+
|
|
23
|
+
| 状态类别 | 机制 | 成本 |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| 目录结构(packages/ 增删、node_modules 候选、契约包发现) | **枚举零缓存**(每次 readdir) | ~20-40 stat/请求 |
|
|
26
|
+
| 清单输入(`.tbox/app.json`、dev-manifest、模块 manifest) | 枚举零缓存(小文件直读) | 同上 |
|
|
27
|
+
| 文件内容(integrations.json、credentials/*、schemas/*、service-slots.json、contracts package.json) | **stat 指纹**(mtimeMs+size;外部写下一笔自愈) | 命中后 1 stat/文件 |
|
|
28
|
+
| contracts 模块(动态 import 产物) | **版本轻探测**(候选路径经 symlink 读 version;变更重走候选链 + 重 import) | 1 stat/请求 |
|
|
29
|
+
| 本进程写入 | **写后本实例即刻失效**(read-your-writes,不依赖 mtime 粒度) | 0 |
|
|
30
|
+
|
|
31
|
+
边界:① 无快照隔离——请求进行中的变更可能产生部分视图,下一笔收敛(写路径写时重新枚举 + 校验,无 stale-clobber);② 同 stat 指纹的外部覆写不可觉察(现实中不发生;本进程写有显式失效兜底);③ workspace 源码态 contracts 原地改 dist 不 bump version → 不重 import(与应用自身装载行为一致)。验收面 = `tests/file-cache.test.ts` W1-W7 矩阵。
|
|
32
|
+
|
|
33
|
+
## 打包纪律三件套(tsup.config.ts 同文)
|
|
34
|
+
|
|
35
|
+
1. **禁 `createRequire(import.meta.url)`**——contracts 发布面 exports 仅 types+import 双条件,require 必抛 `ERR_PACKAGE_PATH_NOT_EXPORTED`;
|
|
36
|
+
2. **动态 import 路径禁字面量包名折叠**——resolver 探测命中文件运行时计算(agtcodingbox esbuild `packages:"external"` 已核实 toolkit 不进 bundle);
|
|
37
|
+
3. **minify 两键 + 导出 Error 类 `this.name` 字符串字面量约定**——`minify: true` + `charset utf8`(沿 commit 72383576 配方;真源 process note `2026-09-11-publish-dist-minify`);Error 子类构造器必须 `this.name = 'XxxError'` 字面量赋值(禁 binding 形态——mangle 后静默漂移),`tests/error-name-safety.test.ts` src 态守卫。
|
|
38
|
+
|
|
39
|
+
## 验证分层①-④(发布形态全链路)
|
|
40
|
+
|
|
41
|
+
| 层 | 载体 | 覆盖 |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| ① src 态守卫 | `tests/error-name-safety.test.ts` + 全测试矩阵(随 `pnpm -r test` 进根 verify 链) | 导出面/字面量约定/行为矩阵 |
|
|
44
|
+
| ② minified dist 冒烟 | `pnpm --filter @tbox.cn/app-toolkit smoke:dist`(`scripts/smoke-dist.mjs`——纯 node:22 方法 typeof + AppToolkitError.name + resolver 命中 + file-cache 快测) | dist 产物直调(mangle 后) |
|
|
45
|
+
| ③ 发布形态门禁 | `pnpm --filter @tbox.cn/app-toolkit pack --check`(prepack 内建 build,tgz 内即 minified dist) | 打包完整性 |
|
|
46
|
+
| ④ 跨仓 file: tgz 联调 | agtcodingbox 联调(`file:` tgz 消费——真实宿主) | 消费面全链路 |
|
|
47
|
+
|
|
48
|
+
## 能力门控(读写严格 ≥0.9 单门禁)
|
|
49
|
+
|
|
50
|
+
求值端点与写方法要求应用 contracts 具备严格校验面(`strictValidation`,≥0.9)——`AppToolkitError('CONTRACTS_NOT_RESOLVED', 503, message 三分支)`;静态方法与 contracts 可用性解耦。门控断言单点 = 工厂边缘(policy at edge),机制层保持纯函数。
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{existsSync as l,readdirSync as F,realpathSync as m}from"fs";import{join as c}from"path";import{pathToFileURL as w}from"url";import{existsSync as T,readFileSync as k,statSync as x}from"fs";function p(){let e=new Map,n=0;function r(t){if(!T(t))return null;let i=x(t);return`${i.mtimeMs}:${i.size}`}return{read(t,i){let o=r(t);if(o===null){e.delete(t);return}let s=e.get(t);if(s&&s.fingerprint===o)return s.value;n+=1;let a=i(k(t,"utf8"));return e.set(t,{fingerprint:o,value:a}),a},invalidate(t){if(t===void 0){e.clear();return}for(let i of t)e.delete(i)},get parseCount(){return n}}}var g=["resolveEffectiveService","buildSupplyLookup","moduleDomainOf","normalizeInstances","RESOURCE_TYPE_IDS"],M="parseIntegrationsConfig",v={version:null,evaluation:!1,strictValidation:!1,module:{},notes:[]};function C(e){let n=[e];for(let r of["apps","packages"]){let t=c(e,r);if(!l(t))continue;let i=F(t,{withFileTypes:!0}).filter(o=>o.isDirectory()).map(o=>o.name);r==="apps"?i.sort((o,s)=>o==="server"?-1:s==="server"?1:o.localeCompare(s)):i.sort((o,s)=>o.localeCompare(s));for(let o of i)n.push(c(t,o))}return n}var d=new Map,h=p();function y(e){return h.read(e,n=>{let r=JSON.parse(n);return typeof r.version=="string"?r.version:null})??null}function b(e){if(!l(e))return"gone";let n;try{n=m(e)}catch{n=e}return l(c(n,"dist","runtime.js"))?"dist":l(c(n,"src","runtime.ts"))?"src":"none"}function R(e){let n=c(e,"package.json");return{pkgPath:n,candidateDir:e,version:y(n),artifact:b(e)}}function E(e){for(let n of C(e)){let r=c(n,"node_modules","@tbox.cn","app-contracts"),t=c(r,"package.json");if(l(t))return{pkgPath:t,candidateDir:r,version:y(t),artifact:b(r)}}return null}function u(e){return e===null?"none":`${e.pkgPath}|${e.version??"null"}|${e.artifact}`}function $(e,n){let r=E(e);if(u(r)!==u(n.first))return!1;if(n.resolved===null)return!0;let t=r!==null&&r.candidateDir===n.resolved.candidateDir?r:R(n.resolved.candidateDir);return u(t)===u(n.resolved)}async function O(e,n){if(!l(e))return null;let r;try{r=m(e)}catch{return null}let i=[c(r,"dist","runtime.js"),c(r,"src","runtime.ts")].find(s=>l(s)),o=h.read(c(e,"package.json"),s=>{let a=JSON.parse(s);return typeof a.version=="string"?a.version:null})??null;if(i===void 0)return n.push(`contracts ${o??"(版本未知)"} 探测命中但无构建产物(dist/runtime.js 缺失)——workspace 源码态未构建:执行 pnpm --filter @tbox.cn/app-contracts build 后重试`),null;try{let s=o!==null?`?v=${encodeURIComponent(o)}`:"",a=await import(w(i).href+s),f=g.every(S=>a[S]!==void 0),P=a[M]!==void 0;return{version:o,evaluation:f,strictValidation:P,module:a,notes:f?[]:[`${i} 命中但求值面具名导出缺席(${g.join("/")})——契约包形态异常`]}}catch(s){return n.push(`contracts ${o??"(版本未知)"} 构建产物导入失败(${s instanceof Error?s.message:String(s)})——workspace 源码态未构建或产物损坏:执行 pnpm --filter @tbox.cn/app-contracts build 后重试`),null}}function U(e){let n=d.get(e);if(n&&$(e,n))return n.promise;let r=E(e),t={promise:Promise.resolve({...v}),first:r,resolved:r};return t.promise=(async()=>{let i=[];for(let o of C(e)){let s=c(o,"node_modules","@tbox.cn","app-contracts"),a=await O(s,i);if(a)return a.version!==null&&!a.strictValidation&&a.notes.push(`contracts ${a.version} 无严格校验面(需 ≥0.9)——升级应用 @tbox.cn/app-contracts 依赖后可用`),t.resolved=R(s),a}return t.resolved=null,i.length===0&&i.push("contracts 不可解析(未安装)——检查应用依赖安装后重试"),{...v,notes:i}})(),d.set(e,t),t.promise}function L(e){e===void 0?d.clear():d.delete(e)}export{p as a,U as b,L as c};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{b as a,c as b}from"./chunk-VV3ERZXS.js";export{b as invalidateContractsResolver,a as resolveContractsForApp};
|