@simplysm/sd-claude 14.0.85 → 14.0.86
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/claude/references/sd-simplysm14/README.md +7 -1
- package/claude/references/sd-simplysm14/manuals/client-app-structure.md +140 -0
- package/claude/references/sd-simplysm14/manuals/client-component.md +6 -5
- package/claude/references/sd-simplysm14/manuals/client-orm.md +62 -0
- package/claude/references/sd-simplysm14/manuals/client-service.md +96 -0
- package/claude/references/sd-simplysm14/manuals/client-shared-data.md +146 -0
- package/claude/references/sd-simplysm14/manuals/client-system-log.md +96 -0
- package/claude/references/sd-simplysm14/manuals/data-log.md +209 -0
- package/claude/references/sd-simplysm14/manuals/event.md +135 -0
- package/claude/sd-system-prompt.md +29 -15
- package/claude/skills/sd-impl/SKILL.md +15 -10
- package/claude/skills/sd-impl/evals/fixtures/case-a-new-screen/.specs/260513120000_warehouse/spec.md +1 -1
- package/claude/skills/sd-impl/evals/fixtures/case-b-update-with-demo/.specs/260513120000_warehouse/spec.md +1 -1
- package/claude/skills/sd-impl/evals/fixtures/case-c-new-cross/.specs/260513120000_warehouse/spec.md +2 -2
- package/claude/skills/sd-impl/evals/fixtures/case-d-spec-modify/.specs/260513120000_warehouse/spec.md +1 -1
- package/claude/skills/sd-impl/evals/golden.jsonl +1 -1
- package/claude/skills/sd-manual/SKILL.md +51 -0
- package/claude/skills/sd-manual/evals/fixtures/new-manual/src/notification.ts +25 -0
- package/claude/skills/sd-manual/evals/fixtures/update-manual/.claude/references/sd-simplysm14/manuals/notification.md +14 -0
- package/claude/skills/sd-manual/evals/fixtures/update-manual/src/notification.ts +37 -0
- package/claude/skills/sd-manual/evals/golden.jsonl +2 -0
- package/claude/skills/sd-review/SKILL.md +1 -1
- package/claude/skills/sd-spec/SKILL.md +61 -63
- package/claude/skills/sd-spec/evals/fixtures/case-a-split//355/232/214/354/235/230/353/241/235.md +20 -0
- package/claude/skills/sd-spec/evals/fixtures/case-b-detail/.specs/260513120000_warehouse/spec.md +95 -0
- package/claude/skills/sd-spec/evals/golden.jsonl +2 -0
- package/claude/skills/sd-spec/references/example-spec.md +14 -47
- package/package.json +1 -1
- package/claude/references/sd-simplysm14/manuals/client-setup.md +0 -154
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
# 클라이언트 환경 셋업 매뉴얼
|
|
2
|
-
|
|
3
|
-
화면 작성 시점에는 거의 건드리지 않음. 새 앱 부트스트랩 시 또는 새 서비스/마스터 데이터를 추가할 때만 참조.
|
|
4
|
-
|
|
5
|
-
## AppServiceProvider
|
|
6
|
-
|
|
7
|
-
`@simplysm/service-client` 위에 앱이 만드는 root provider. 서비스·이벤트 프록시와 ORM(Object-Relational Mapping) 커넥터를 lazy 캐싱으로 노출.
|
|
8
|
-
|
|
9
|
-
```ts
|
|
10
|
-
@Injectable({ providedIn: "root" })
|
|
11
|
-
export class AppServiceProvider {
|
|
12
|
-
private readonly _sdServiceClientFactory = inject(SdServiceClientFactoryProvider);
|
|
13
|
-
|
|
14
|
-
private _orm?: OrmClientConnector;
|
|
15
|
-
private _user?: ServiceProxy<UserServiceType>;
|
|
16
|
-
private _authInfoEvent?: ClientEventProxy<typeof AuthInfoEvent>;
|
|
17
|
-
// ...
|
|
18
|
-
|
|
19
|
-
get client() {
|
|
20
|
-
return this._sdServiceClientFactory.get("MAIN");
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
get orm(): OrmClientConnector {
|
|
24
|
-
return (this._orm ??= createOrmClientConnector(this.client));
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
get user(): ServiceProxy<UserServiceType> {
|
|
28
|
-
return (this._user ??= this.client.getService<UserServiceType>("User"));
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
get authInfoEvent(): ClientEventProxy<typeof AuthInfoEvent> {
|
|
32
|
-
return (this._authInfoEvent ??= this.client.getEvent<typeof AuthInfoEvent>("AuthInfo"));
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async connectAsync() {
|
|
36
|
-
await this._sdServiceClientFactory.connectAsync("MAIN");
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
**약속**:
|
|
42
|
-
|
|
43
|
-
- `@Injectable({ providedIn: "root" })`.
|
|
44
|
-
- 서비스·이벤트는 `private _xxx?` 캐시 필드 + getter 로 노출. lazy 초기화는 `??=` 패턴 사용.
|
|
45
|
-
- 서비스: `client.getService<XxxServiceType>("XxxName")` 호출. 이벤트: `client.getEvent<typeof XxxEvent>("XxxName")` 호출.
|
|
46
|
-
- ORM 커넥터: `createOrmClientConnector(this.client)` 결과를 `orm` getter 로 노출.
|
|
47
|
-
- `connectAsync()` — 앱 부트스트랩 시점에 서버 연결 수행.
|
|
48
|
-
|
|
49
|
-
## AppOrmProvider
|
|
50
|
-
|
|
51
|
-
`AppServiceProvider.orm` 위에 앱별 DB(데이터베이스) 설정(DbContext·데이터베이스명·스키마명)을 고정해 둔 root provider.
|
|
52
|
-
|
|
53
|
-
```ts
|
|
54
|
-
@Injectable({ providedIn: "root" })
|
|
55
|
-
export class AppOrmProvider {
|
|
56
|
-
private readonly _appService = inject(AppServiceProvider);
|
|
57
|
-
|
|
58
|
-
connectAsync<R>(callback: (db: MainDbContext) => Promise<R>): Promise<R> {
|
|
59
|
-
return this._appService.orm.connect(
|
|
60
|
-
{
|
|
61
|
-
DbClass: MainDbContext,
|
|
62
|
-
connOpt: { configName: "MAIN" },
|
|
63
|
-
dbContextOpt: { database: "...", schema: "dbo" },
|
|
64
|
-
},
|
|
65
|
-
callback,
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
connectWithoutTransAsync<R>(callback: (db: MainDbContext) => Promise<R>): Promise<R> {
|
|
70
|
-
return this._appService.orm.connectWithoutTransaction(
|
|
71
|
-
{ /* 같은 옵션 */ },
|
|
72
|
-
callback,
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
**약속**:
|
|
79
|
-
|
|
80
|
-
- `@Injectable({ providedIn: "root" })`.
|
|
81
|
-
- DbContext 는 앱별로 정의 (예: `@adtek/db-main` 의 `MainDbContext`).
|
|
82
|
-
- 기본 메서드는 `connectAsync` (트랜잭션 포함). `connectWithoutTransAsync` 는 initialize 등 트랜잭션 안에서 동작하지 않는 작업 전용 헬퍼.
|
|
83
|
-
- 콜백의 반환값이 그대로 메서드의 반환값이 됨.
|
|
84
|
-
|
|
85
|
-
## AppSharedDataProvider
|
|
86
|
-
|
|
87
|
-
`@simplysm/angular` 의 `SdSharedDataProvider` 를 상속하여 화면에서 자주 참조하는 마스터 데이터(고객사·품목·로케이션 등)를 등록한 root provider.
|
|
88
|
-
|
|
89
|
-
```ts
|
|
90
|
-
export function useSharedSignal<K extends keyof TAppSharedData>(
|
|
91
|
-
name: K,
|
|
92
|
-
): SharedDataHandle<TAppSharedData[K]> {
|
|
93
|
-
const appSharedData = inject(AppSharedDataProvider);
|
|
94
|
-
return appSharedData.getHandle(name);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
@Injectable({ providedIn: "root" })
|
|
98
|
-
export class AppSharedDataProvider extends SdSharedDataProvider<TAppSharedData> {
|
|
99
|
-
private readonly _appOrm = inject(AppOrmProvider);
|
|
100
|
-
|
|
101
|
-
override initialize() {
|
|
102
|
-
this.register("고객사", {
|
|
103
|
-
serviceKey: "MAIN",
|
|
104
|
-
getter: async (changeKeys) => {
|
|
105
|
-
return this._appOrm.connectAsync(async (db) => {
|
|
106
|
-
let qr = db.customer().select((item) => ({
|
|
107
|
-
id: item.id,
|
|
108
|
-
code: item.code,
|
|
109
|
-
name: item.name,
|
|
110
|
-
isDeleted: item.isDeleted,
|
|
111
|
-
|
|
112
|
-
__valueKey: item.id,
|
|
113
|
-
__searchText: expr.concat(item.code, "|_|", item.name),
|
|
114
|
-
__isHidden: item.isDeleted,
|
|
115
|
-
}));
|
|
116
|
-
|
|
117
|
-
if (changeKeys) {
|
|
118
|
-
qr = qr.where((item) => [expr.in(item.id, changeKeys as number[])]);
|
|
119
|
-
}
|
|
120
|
-
return qr.execute();
|
|
121
|
-
});
|
|
122
|
-
},
|
|
123
|
-
orderBy: (item) => item.code,
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// ... 다른 마스터 데이터 등록 ...
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export type TAppSharedData = {
|
|
131
|
-
고객사: ISharedCustomer;
|
|
132
|
-
// ...
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
export interface ISharedCustomer extends SharedDataBase<number> {
|
|
136
|
-
id: number;
|
|
137
|
-
code: string;
|
|
138
|
-
name: string;
|
|
139
|
-
isDeleted: boolean;
|
|
140
|
-
}
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
**약속**:
|
|
144
|
-
|
|
145
|
-
- `@Injectable({ providedIn: "root" })` 사용, `SdSharedDataProvider<TAppSharedData>` 를 상속.
|
|
146
|
-
- 등록은 `override initialize()` 안에서 `this.register(name, opts)` 호출로 수행.
|
|
147
|
-
- 각 항목의 인터페이스는 `SharedDataBase<TKey>` 를 상속.
|
|
148
|
-
- getter 의 select 결과에 다음 매직 필드를 포함:
|
|
149
|
-
- `__valueKey` — 항목의 키.
|
|
150
|
-
- `__searchText` — 검색용 텍스트.
|
|
151
|
-
- `__isHidden` — 숨김 여부 (예: `isDeleted` 값으로 지정).
|
|
152
|
-
- `getter(changeKeys)` 의 `changeKeys` 인자가 주어지면 해당 키들만 다시 조회 (incremental refresh).
|
|
153
|
-
- `orderBy` 는 정렬 키를 반환하는 함수 (예: `(item) => item.code`).
|
|
154
|
-
- `useSharedSignal<K>(name)` 헬퍼 함수를 함께 export — 컴포넌트는 inject 없이 이름만으로 접근 가능.
|