M0: 工作区骨架 + 五道门禁 + 环境自举
- pnpm workspaces / tsconfig 双工程(node · web)/ 路径别名(§11.1) - eslint flat(§11.3 + §12.5 可机检项)/ dependency-cruiser 基线八条 + JCAI 增补(§11.4) - tools/module-tiers.json + gen-depcruise-tiers.ts 生成 tier-order 逐层规则 - tools/api-report.mjs 契约快照只留契约面(ADR-005) - docker-compose(PG16)+ db/init 四 schema;种子数据五岗位五员工冻结为常量 - docs/debt.md · docs/adr/ADR-005 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "@sdk",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": { ".": "./src/index.ts" }
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* @sdk —— 活动开发面(编码规范 §8.2):基座六件接口 + defineActivity() + 本地开发宿主 + 回放夹具。
|
||||
* 活动包 ABI 见 ADR-004。
|
||||
*/
|
||||
export const SDK_VERSION = '0.0.0-m0';
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "@contracts",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": { ".": "./src/index.ts" }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* @contracts —— 前后端唯一共享点(编码规范 §8.1)。
|
||||
* 只有 zod schema、常量、品牌类型与推导类型,零实现。
|
||||
* 修改本包任何导出 = 契约变更(§12.4)。
|
||||
*/
|
||||
export const CONTRACTS_VERSION = '0.0.0-m0';
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "@sfeel",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": { ".": "./src/index.ts" }
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* @sfeel —— S-FEEL 子集(OS 03 定义域)的解析与求值,纯函数(编码规范 §8.3)。
|
||||
* 被 process / flow-engine / trigger 与前端 gov-process 共用:求值语义一份代码,前后端同源。
|
||||
*/
|
||||
export const SFEEL_VERSION = '0.0.0-m0';
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "@ui",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": { ".": "./src/index.ts" }
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* @ui —— 无业务语义展示组件(卡片原语 / 时间线 / 净化视图容器 ViewContainer)。
|
||||
*/
|
||||
export const UI_KIT_VERSION = '0.0.0-m0';
|
||||
@@ -0,0 +1,31 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { assertNever, groupBy, isDefined, sortedEntries } from '../src/index.ts';
|
||||
|
||||
describe('@utils', () => {
|
||||
it('isDefined 滤掉 null 与 undefined', () => {
|
||||
expect([1, null, 2, undefined].filter(isDefined)).toEqual([1, 2]);
|
||||
});
|
||||
|
||||
it('groupBy 按键分组', () => {
|
||||
const rows = [
|
||||
{ pn: 'A', type: 'A' as const },
|
||||
{ pn: 'B', type: 'B' as const },
|
||||
{ pn: 'C', type: 'A' as const },
|
||||
];
|
||||
expect(groupBy(rows, (r) => r.type)).toEqual({
|
||||
A: [rows[0], rows[2]],
|
||||
B: [rows[1]],
|
||||
});
|
||||
});
|
||||
|
||||
it('sortedEntries 稳定排序', () => {
|
||||
expect(sortedEntries({ b: 2, a: 1 })).toEqual([
|
||||
['a', 1],
|
||||
['b', 2],
|
||||
]);
|
||||
});
|
||||
|
||||
it('assertNever 抛错', () => {
|
||||
expect(() => assertNever('x' as never)).toThrow('未覆盖的分支');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "@utils",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": { ".": "./src/index.ts" }
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @utils —— 纯函数,零依赖(编码规范 §2 / §5.1:叶子包)。
|
||||
* 无业务语义;有业务语义的东西不属于这里。
|
||||
*/
|
||||
|
||||
/** 穷尽性检查:switch 漏分支时编译期报错 */
|
||||
export function assertNever(value: never, message = '未覆盖的分支'): never {
|
||||
throw new Error(`${message}: ${JSON.stringify(value)}`);
|
||||
}
|
||||
|
||||
/** 类型守卫:滤掉 null / undefined */
|
||||
export function isDefined<T>(value: T | null | undefined): value is T {
|
||||
return value !== null && value !== undefined;
|
||||
}
|
||||
|
||||
/** 按键分组 */
|
||||
export function groupBy<T, K extends string>(items: readonly T[], key: (item: T) => K): Record<K, T[]> {
|
||||
const out = {} as Record<K, T[]>;
|
||||
for (const item of items) {
|
||||
const k = key(item);
|
||||
(out[k] ??= []).push(item);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/** 稳定排序的键值对遍历(避免 Object.keys 顺序依赖) */
|
||||
export function sortedEntries<V>(record: Readonly<Record<string, V>>): Array<[string, V]> {
|
||||
return Object.entries(record).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
|
||||
}
|
||||
Reference in New Issue
Block a user