labull-framework 0.1.35 → 1.0.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/README.md +42 -2
- package/dist/magic-block.js +2049 -1710
- package/dist/style.css +1 -1
- package/dist/theme.js +1 -4
- package/dist/types/magic-block-declared.d.ts +29 -2
- package/dist/types/magic-block-instances.d.ts +1 -1
- package/dist/types/magic-block-localfs.d.ts +2 -2
- package/dist/types/magic-block-manifest.d.ts +39 -8
- package/dist/types/magic-block-real.d.ts +2 -2
- package/dist/types/theme.d.ts +0 -1
- package/package.json +1 -1
package/dist/theme.js
CHANGED
|
@@ -31,7 +31,7 @@ export interface DeclaredEntry {
|
|
|
31
31
|
* 🔴 先认 `meta.blockUuid`:uuid 是**身份**,把它写在 `meta` 上就与"传给组件的参数"这件事分开了
|
|
32
32
|
* (`props` 那里放的是渲染参数,可能被 `props: 'uuid'` / `props: true` 这类写法占掉)。
|
|
33
33
|
* 🔴 再退回 `props.default.uuid`:这是本仓库现在的写法(`props: { uuid }`),
|
|
34
|
-
* **不许**顺手取消掉 ——
|
|
34
|
+
* **不许**顺手取消掉 —— 老应用照旧要认得出来,认不出等于管理台把它们当成"没有块"。
|
|
35
35
|
* ⚠️ **不认 `props` 是字符串 / 布尔**那两种:它们分别是"从路由参数里取那个字段"与"把 query 当 props",
|
|
36
36
|
* 都不是一个写死的 uuid(去解它就得解析路由参数,等于凭空发明一条判据)。
|
|
37
37
|
*/
|
|
@@ -41,7 +41,7 @@ export declare function declaredUuidOf(route: DeclaredRoute | null | undefined):
|
|
|
41
41
|
*
|
|
42
42
|
* 🔴 只认"挂的是**块页**"那些路由(`page` 由调用方传进来 = `MagicBlockPage`):
|
|
43
43
|
* 与 `pagesOf()` 生成 `pages.lock.ts` 用的是同一条判据(`components.default` 是不是块页),
|
|
44
|
-
* 两处若各写一套,"
|
|
44
|
+
* 两处若各写一套,"枚举里有这一页、管理台说它不是块"这种自相矛盾迟早出现。
|
|
45
45
|
* ⚠️ 带参数的路由(`/orders/:id`)与通配路由**照样算**:它声明的是**同一个块**
|
|
46
46
|
* (`props: { uuid }` 对它们一样成立),排掉反而会漏掉"这个块只在实例页上挂着"的应用。
|
|
47
47
|
*/
|
|
@@ -90,3 +90,30 @@ export interface BlockPlacementProblem {
|
|
|
90
90
|
* 闸门误报一次,人就会把整个闸门绕过去(`tools/block-guard.mjs` 里是同一句话)。
|
|
91
91
|
*/
|
|
92
92
|
export declare function blockPlacementProblems(chain: DeclaredRoute[] | null | undefined, page?: unknown): BlockPlacementProblem[];
|
|
93
|
+
/** 一条"声明的跨块路由"的问题(`code` 是机器判据:用例按它断言 —— 报文改一个标点不该让用例红)。 */
|
|
94
|
+
export interface DeclaredRouteProblem {
|
|
95
|
+
/** `no-page` = 声明的那条地址在路由表里找不到(那个页面改名 / 搬走了) */
|
|
96
|
+
code: 'no-page';
|
|
97
|
+
/** 声明的那条地址(原样,便于人对着改)。 */
|
|
98
|
+
path: string;
|
|
99
|
+
/** 给人看的一句话:错在哪儿 + 该往哪儿写。 */
|
|
100
|
+
message: string;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* 两条地址是不是**同一条路由**(段数一样,占位位当通配)。
|
|
104
|
+
*
|
|
105
|
+
* 🔴 这是"声明 → 现实"那一半的唯一判据:块声明 `/expense/applications/{id}`、
|
|
106
|
+
* 路由表里写着 `/expense/applications/:id` ⇒ **算对上**(逐字比会判错)。
|
|
107
|
+
*/
|
|
108
|
+
export declare function sameRouteShape(declared: string, actual: string): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* 「块声明的跨块路由,这个应用里真有那些页面吗」。
|
|
111
|
+
*
|
|
112
|
+
* :param declared: 块清单里 `requires.routes` 那一串(后端从清单读出来下发的)。
|
|
113
|
+
* :param routes: 宿主的路由表(`router.getRoutes()`)。
|
|
114
|
+
* :returns: 逐条问题(空数组 = 都对得上,或者压根没声明 —— 没声明不是错)。
|
|
115
|
+
*
|
|
116
|
+
* 🔴 拿不到路由表(`undefined` / 空表)时回**空清单**:不知道的事不许编成一条问题
|
|
117
|
+
* (闸门误报一次,人就会把整个闸门绕过去)。
|
|
118
|
+
*/
|
|
119
|
+
export declare function requiresRouteProblems(declared: string[] | null | undefined, routes: DeclaredRoute[] | null | undefined): DeclaredRouteProblem[];
|
|
@@ -20,7 +20,7 @@ export declare function mountedAt(uuid: string): string[];
|
|
|
20
20
|
*
|
|
21
21
|
* 🔴 与 `whereElse()` 是两件事、两套取舍,别混着用:
|
|
22
22
|
* · `whereElse()`(块自己那一圈被点)—— 优先去**别的**标签("这个块还挂在别处");
|
|
23
|
-
* · `locateTarget()
|
|
23
|
+
* · `locateTarget()`(管理台里点那一行)—— 本条标签就有就**留在本标签**(就在眼皮底下,
|
|
24
24
|
* 把人传送走只会让人找不到刚点的那一块),本标签没有才去第一条挂着它的标签。
|
|
25
25
|
* 🔴 `pick` 是调用方给的"哪条标签能当目标":**实例页(`/orders/42?orderId=7` 这种带参数的)
|
|
26
26
|
* 不该被自动选中** —— 那是"某一单",不是"这个块在哪一页"(判据见 `@labull/ui` 的
|
|
@@ -127,7 +127,7 @@ export declare function contentDigest(text: string): string;
|
|
|
127
127
|
/**
|
|
128
128
|
* 把一整个开发包写进用户选的目录(`{相对路径: 正文}`)。
|
|
129
129
|
*
|
|
130
|
-
* 🔴 **清空是"问过才做"
|
|
130
|
+
* 🔴 **清空是"问过才做"的动作**:导出前会先看目录里有什么、由管理台问一句(清空 / 只覆盖 / 取消)。
|
|
131
131
|
* 这个函数自己**不删任何东西**(`clearChildren()` 才是删那一步),它只管写。
|
|
132
132
|
* 🔴 **并发写 + 目录句柄缓存**:原来是一个文件一个文件地等、每个文件都从根重新走一遍目录,
|
|
133
133
|
* 几十个文件(含 540 KB 的主题那份)要串行好几趟目录树。
|
|
@@ -167,7 +167,7 @@ export declare function inspectDirectory(dir: LocalDir, rules: ScanRules): Promi
|
|
|
167
167
|
*
|
|
168
168
|
* 🔴 判据只有一条:**只删 `dir` 的子项**。用 `handle.removeEntry(name, { recursive: true })` 按名字删,
|
|
169
169
|
* 路径**拼不出来**(不是"拼一个路径再删")—— 这样"删到别处去"在实现上就不可能发生。
|
|
170
|
-
* 🔴 删除是**不可逆**的,所以它只能由用户在确认框里点过"清空并导出"
|
|
170
|
+
* 🔴 删除是**不可逆**的,所以它只能由用户在确认框里点过"清空并导出"之后走到这里(见管理台)。
|
|
171
171
|
* 🔴 **并发删**(一次 8 个):20 个块的开发目录就是 20 多个顶层项,一个个等太慢。
|
|
172
172
|
* ⚠️ 删完再铺:并发写的时候如果和删除同时跑,`getDirectoryHandle(create: true)` 可能建出马上又被删掉的目录。
|
|
173
173
|
* ⚠️ 一个删不掉就照原样抛(**与串行一样**):已经删掉的那些留在那儿,"删了几项"由调用方自己看到。
|
|
@@ -2,15 +2,27 @@
|
|
|
2
2
|
export declare const BLOCK_ENTRY = "index.open.html";
|
|
3
3
|
/** 块包清单(必备件)。与后端 `sdk.BLOCK_MANIFEST` 逐字一致。 */
|
|
4
4
|
export declare const BLOCK_MANIFEST = "magic-block.open.yaml";
|
|
5
|
-
/**
|
|
6
|
-
export declare const
|
|
7
|
-
|
|
5
|
+
/** 块包内那两份"作者改的"文件(`.open.`)。与后端 `sdk.OPEN_FILES` 逐字一致。 */
|
|
6
|
+
export declare const README_OPEN = "README.open.md";
|
|
7
|
+
export declare const REQUIRES_OPEN = "requires.open.yaml";
|
|
8
|
+
/** 清单认得的键(顺序就是文档里的顺序)。🔴 `requires` 是**可选**的第五个键。 */
|
|
9
|
+
export declare const MANIFEST_KEYS: readonly ["id", "module", "name", "brief", "requires"];
|
|
10
|
+
/** 必须写全的那四个键(= `MANIFEST_KEYS` 去掉可选的 `requires`)。
|
|
8
11
|
*
|
|
9
|
-
* 🔴 为什么 `
|
|
10
|
-
*
|
|
12
|
+
* 🔴 为什么 `requires` **不进必填这一档**:存量块的清单里一个都没有 —— 判"缺少 requires"
|
|
13
|
+
* 等于让库里每一个块在保存 / 体检时集体判不合格(这是**加一个字段**,不是**换一份契约**)。
|
|
11
14
|
* 🔴 认得的键与必填的键**必须分开两处**:合成一处的话,报文会把可选键说成必填。
|
|
12
15
|
* 与后端 `validate.MANIFEST_REQUIRED` 逐字对齐。 */
|
|
13
16
|
export declare const MANIFEST_REQUIRED: readonly ["id", "module", "name", "brief"];
|
|
17
|
+
/** **搬家走了**的那个老键:`detail` 的正文现在住在块包内的 `README.open.md`。
|
|
18
|
+
*
|
|
19
|
+
* 🔴 判据是**提示、不是硬错**:老块的清单里可能还留着它 —— 报成硬错会让那些块直接存不回去。
|
|
20
|
+
* 与后端 `validate.MANIFEST_MOVED` 逐字一致(差分比对盯着两边)。 */
|
|
21
|
+
export declare const MANIFEST_MOVED: readonly ["detail"];
|
|
22
|
+
/** `requires` 认得的七个键(顺序就是文档与渲染的顺序)。与后端 `sdk.REQUIRES_KEYS` 逐字一致。 */
|
|
23
|
+
export declare const REQUIRES_KEYS: readonly ["models", "surface", "packages", "settings", "config", "routes", "opaque"];
|
|
24
|
+
/** `requires` 里唯一一个"值是一张映射"的键(`模型完整路径` → `[方法名, …]`)。 */
|
|
25
|
+
export declare const REQUIRES_SURFACE = "surface";
|
|
14
26
|
export type ManifestKey = (typeof MANIFEST_KEYS)[number];
|
|
15
27
|
/** 可读名的字符上限(与后端 `NAME_MAX` 同一份)。 */
|
|
16
28
|
export declare const NAME_MAX = 40;
|
|
@@ -19,7 +31,24 @@ export declare function isExcluded(name: string): boolean;
|
|
|
19
31
|
/** 清单里 `name` 的形状(🔴 这里**不能只判长度**:`' '` 长度合法但它是空的)。 */
|
|
20
32
|
export declare function validName(value: string): boolean;
|
|
21
33
|
/** 清单解析出来的字段(缺的 / 空的**不会**出现在这里)。 */
|
|
22
|
-
export type Manifest = Partial<Record<ManifestKey, string
|
|
34
|
+
export type Manifest = Partial<Record<Exclude<ManifestKey, 'requires'>, string>> & {
|
|
35
|
+
/** 依赖声明(可选键,结构:七个键 → 一串字符串;`surface` 再深一层)。 */
|
|
36
|
+
requires?: Requires;
|
|
37
|
+
/** **搬家走了**的老键:老块的清单里可能还留着它(迁移期),收下它、**不报错**。
|
|
38
|
+
* 🔴 收下它是**有意的迁移**(不是还在用的键):正文由后端 `normalize_package()` 搬进
|
|
39
|
+
* 块包内那份 `README.open.md` —— 报成硬错会让那些块直接存不回去。 */
|
|
40
|
+
detail?: string;
|
|
41
|
+
};
|
|
42
|
+
/** 依赖声明(`requires`)的规范化结构。与后端 `validate._parse_requires()` 读出来的**同一份形状**。 */
|
|
43
|
+
export interface Requires {
|
|
44
|
+
models?: string[];
|
|
45
|
+
surface?: Record<string, string[]>;
|
|
46
|
+
packages?: string[];
|
|
47
|
+
settings?: string[];
|
|
48
|
+
config?: string[];
|
|
49
|
+
routes?: string[];
|
|
50
|
+
opaque?: string[];
|
|
51
|
+
}
|
|
23
52
|
/** 一个块包的校验结果。`files` 是提交时**原样回给后端**的那一份,这里只读不写。 */
|
|
24
53
|
export interface BlockValidation {
|
|
25
54
|
/** 清单里读出来的键(没读全就是空对象)。 */
|
|
@@ -30,10 +59,12 @@ export interface BlockValidation {
|
|
|
30
59
|
/**
|
|
31
60
|
* 解析清单正文:`[认得的字段, 逐条问题]`(与后端 `parse_manifest` 同一套判据、同一套报文)。
|
|
32
61
|
*
|
|
33
|
-
* 🔴 不认识的写法(列表 /
|
|
62
|
+
* 🔴 不认识的写法(列表 / 没有冒号 / 不认识的键 / 重复键)**各报一条**,绝不静默忽略 ——
|
|
34
63
|
* 静默的后果是"前端放行、后端拒绝",用户看到的是两套说法。
|
|
64
|
+
* 🔴 **唯一的两处例外都很窄**:`requires`(清单里唯一的结构,见 `parseRequires`)与
|
|
65
|
+
* `detail`(搬去 `README.open.md` 的老键:收下它、**不报错**)。
|
|
35
66
|
*/
|
|
36
|
-
export declare function parseManifest(text: string): [Manifest, string[]];
|
|
67
|
+
export declare function parseManifest(text: string, strict?: boolean): [Manifest, string[]];
|
|
37
68
|
/** 包内文件名合法吗(形状 + 不许 `..` 段)。 */
|
|
38
69
|
export declare function validFileName(name: string): boolean;
|
|
39
70
|
/**
|
|
@@ -4,6 +4,6 @@ export { default as MagicBlockConsole } from './magic-block-MagicBlockConsole.vu
|
|
|
4
4
|
export { loadBlockRender, onBlockRenderRefresh, refreshBlockRender, type BlockRender } from './magic-block-render';
|
|
5
5
|
export { BLOCK_BACKEND_FILE, BLOCK_ENTRY, buildPreview } from './magic-block-preview';
|
|
6
6
|
export { CLIENT_SOURCE, installBridge, type BridgeDeps } from './magic-block-bridge';
|
|
7
|
-
export { BLOCK_MANIFEST, MANIFEST_KEYS, MANIFEST_REQUIRED, NAME_MAX, checkSelection, parseManifest, validFileName, validName, validateBlock, type BlockValidation, type Manifest, type ManifestKey, type SelectionCheck, } from './magic-block-manifest';
|
|
7
|
+
export { BLOCK_MANIFEST, MANIFEST_KEYS, MANIFEST_REQUIRED, MANIFEST_MOVED, NAME_MAX, README_OPEN, REQUIRES_KEYS, REQUIRES_OPEN, checkSelection, parseManifest, validFileName, validName, validateBlock, type BlockValidation, type Manifest, type ManifestKey, type Requires, type SelectionCheck, } from './magic-block-manifest';
|
|
8
8
|
export { API_BASE, setApiBase } from './auth-real';
|
|
9
|
-
export { BLOCK_PAGE_MARK, blockPlacementProblems, declaredMissing, declaredUuidOf, declaredUuidsOf, isBlockPage, type BlockPlacementProblem, type DeclaredEntry, type DeclaredRoute, } from './magic-block-declared';
|
|
9
|
+
export { BLOCK_PAGE_MARK, blockPlacementProblems, declaredMissing, declaredUuidOf, declaredUuidsOf, isBlockPage, requiresRouteProblems, sameRouteShape, type BlockPlacementProblem, type DeclaredEntry, type DeclaredRoute, type DeclaredRouteProblem, } from './magic-block-declared';
|
package/dist/types/theme.d.ts
CHANGED