@simplysm/sd-claude 14.0.82 → 14.0.83

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.
Files changed (87) hide show
  1. package/claude/references/sd-requirement-source-handling.md +20 -20
  2. package/claude/references/sd-simplysm14/README.md +13 -13
  3. package/claude/references/sd-simplysm14/manuals/client-component.md +92 -92
  4. package/claude/references/sd-simplysm14/manuals/client-crud.md +11 -11
  5. package/claude/references/sd-simplysm14/manuals/client-demo.md +28 -28
  6. package/claude/references/sd-simplysm14/manuals/client-rules.md +1 -1
  7. package/claude/references/sd-simplysm14/manuals/client-setup.md +21 -21
  8. package/claude/references/sd-simplysm14/manuals/client-tab.md +3 -3
  9. package/claude/references/sd-simplysm14/manuals/logging.md +15 -15
  10. package/claude/references/sd-simplysm14/manuals/orm-union.md +6 -6
  11. package/claude/references/sd-simplysm14/manuals/orm.md +19 -19
  12. package/claude/references/sd-simplysm14/manuals/test.md +33 -33
  13. package/claude/rules/sd-base-rules.md +44 -43
  14. package/claude/rules/sd-design-rules.md +18 -18
  15. package/claude/skills/sd-commit/SKILL.md +10 -10
  16. package/claude/skills/sd-config/SKILL.md +2 -2
  17. package/claude/skills/sd-demo/SKILL.md +45 -45
  18. package/claude/skills/sd-dev/SKILL.md +15 -15
  19. package/claude/skills/sd-docs/SKILL.md +7 -7
  20. package/claude/skills/sd-docs/references/subagent-prompt.md +33 -33
  21. package/claude/skills/sd-impl/SKILL.md +60 -60
  22. package/claude/skills/sd-review/SKILL.md +9 -9
  23. package/claude/skills/sd-skill/SKILL.md +74 -74
  24. package/claude/skills/sd-skill/evals/fixtures/existing-skill/.claude/skills/todo-format/SKILL.md +1 -1
  25. package/claude/skills/sd-spec/SKILL.md +355 -319
  26. package/claude/skills/sd-spec/references/example-spec.md +104 -104
  27. package/claude/skills/sd-unpack/SKILL.md +34 -34
  28. package/claude/skills/sd-use/SKILL.md +4 -4
  29. package/package.json +1 -1
  30. package/claude/references/sd-simplysm14/apis/angular/README.md +0 -37
  31. package/claude/references/sd-simplysm14/apis/angular/app-structure.md +0 -92
  32. package/claude/references/sd-simplysm14/apis/angular/buttons.md +0 -88
  33. package/claude/references/sd-simplysm14/apis/angular/crud.md +0 -100
  34. package/claude/references/sd-simplysm14/apis/angular/forms.md +0 -200
  35. package/claude/references/sd-simplysm14/apis/angular/infrastructure.md +0 -231
  36. package/claude/references/sd-simplysm14/apis/angular/kanban.md +0 -80
  37. package/claude/references/sd-simplysm14/apis/angular/layout.md +0 -92
  38. package/claude/references/sd-simplysm14/apis/angular/modal.md +0 -115
  39. package/claude/references/sd-simplysm14/apis/angular/routing.md +0 -107
  40. package/claude/references/sd-simplysm14/apis/angular/select-dropdown.md +0 -35
  41. package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +0 -82
  42. package/claude/references/sd-simplysm14/apis/angular/shared-data.md +0 -134
  43. package/claude/references/sd-simplysm14/apis/angular/sheet.md +0 -127
  44. package/claude/references/sd-simplysm14/apis/angular/toast.md +0 -97
  45. package/claude/references/sd-simplysm14/apis/angular/visual.md +0 -167
  46. package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +0 -79
  47. package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +0 -83
  48. package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +0 -91
  49. package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +0 -49
  50. package/claude/references/sd-simplysm14/apis/core-browser/README.md +0 -143
  51. package/claude/references/sd-simplysm14/apis/core-common/README.md +0 -58
  52. package/claude/references/sd-simplysm14/apis/core-common/extensions.md +0 -88
  53. package/claude/references/sd-simplysm14/apis/core-common/features.md +0 -51
  54. package/claude/references/sd-simplysm14/apis/core-common/types.md +0 -88
  55. package/claude/references/sd-simplysm14/apis/core-common/utils.md +0 -189
  56. package/claude/references/sd-simplysm14/apis/core-node/README.md +0 -12
  57. package/claude/references/sd-simplysm14/apis/core-node/consola.md +0 -59
  58. package/claude/references/sd-simplysm14/apis/core-node/cpx.md +0 -44
  59. package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +0 -42
  60. package/claude/references/sd-simplysm14/apis/core-node/fsx.md +0 -53
  61. package/claude/references/sd-simplysm14/apis/core-node/pathx.md +0 -24
  62. package/claude/references/sd-simplysm14/apis/core-node/worker.md +0 -65
  63. package/claude/references/sd-simplysm14/apis/excel/README.md +0 -193
  64. package/claude/references/sd-simplysm14/apis/lint/README.md +0 -94
  65. package/claude/references/sd-simplysm14/apis/orm-common/README.md +0 -58
  66. package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +0 -77
  67. package/claude/references/sd-simplysm14/apis/orm-common/executable.md +0 -20
  68. package/claude/references/sd-simplysm14/apis/orm-common/expr.md +0 -92
  69. package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +0 -98
  70. package/claude/references/sd-simplysm14/apis/orm-common/schema-builders.md +0 -128
  71. package/claude/references/sd-simplysm14/apis/orm-node/README.md +0 -69
  72. package/claude/references/sd-simplysm14/apis/sd-claude/README.md +0 -32
  73. package/claude/references/sd-simplysm14/apis/sd-cli/README.md +0 -80
  74. package/claude/references/sd-simplysm14/apis/sd-cli/sd-config.md +0 -155
  75. package/claude/references/sd-simplysm14/apis/service-client/README.md +0 -131
  76. package/claude/references/sd-simplysm14/apis/service-common/README.md +0 -29
  77. package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +0 -63
  78. package/claude/references/sd-simplysm14/apis/service-common/messages.md +0 -56
  79. package/claude/references/sd-simplysm14/apis/service-common/protocol.md +0 -64
  80. package/claude/references/sd-simplysm14/apis/service-common/service-types.md +0 -43
  81. package/claude/references/sd-simplysm14/apis/service-server/README.md +0 -13
  82. package/claude/references/sd-simplysm14/apis/service-server/auth.md +0 -39
  83. package/claude/references/sd-simplysm14/apis/service-server/builtin-services.md +0 -71
  84. package/claude/references/sd-simplysm14/apis/service-server/define-service.md +0 -55
  85. package/claude/references/sd-simplysm14/apis/service-server/internals.md +0 -82
  86. package/claude/references/sd-simplysm14/apis/service-server/server.md +0 -57
  87. package/claude/references/sd-simplysm14/apis/storage/README.md +0 -71
@@ -1,80 +0,0 @@
1
- # @simplysm/sd-cli
2
-
3
- 워크스페이스 빌드/배포 오케스트레이터. 소비 표면은 두 갈래다 — `pnpm sd-cli <cmd>` 서브커맨드와 `sd.config.ts` 작성용 타입. 라이브러리 export 로는 Vitest Angular 플러그인과 외부 도구가 재사용할 `SdTsCompiler` 도 노출한다.
4
-
5
- ## 사용 트리거 인덱스
6
-
7
- ### 서브커맨드 (`pnpm sd-cli <cmd>`)
8
-
9
- - **`check`** — 타입체크와 lint 를 병렬 실행. 일반 검증 명령으로 가장 자주 호출됨.
10
- - **`watch`** — 워크스페이스 전체 또는 일부 패키지를 watch 모드로 증분 빌드.
11
- - **`dev`** — server 패키지를 dev 모드로 실행 (`tsx` 핫리로드 + client 패키지의 dev http 서버 동반 기동).
12
- - **`device`** — client 패키지를 안드로이드 디바이스 또는 Electron 데스크톱에서 실행. dev 서버가 떠 있어야 함.
13
- - **`build`** — 프로덕션 빌드. `sd.config.ts` 의 `packages` 전 항목 또는 `-t` 지정 항목.
14
- - **`publish`** — 빌드 후 `publish` 설정을 따라 배포 (npm / 로컬 디렉토리 / FTP·SFTP). `--no-build` 로 기존 산출물만 배포.
15
- - **`replace-deps`** — `sd.config.ts.replaceDeps` 에 따라 `node_modules` 패키지를 로컬 소스로 심링크 교체.
16
- - **`init`** — 인터랙티브 프롬프트로 SI 워크스페이스 골격 생성.
17
-
18
- 공통 옵션:
19
- - `-t / --target <pkg>` (반복 가능) — 대상 패키지. `sd.config.ts.packages` 키 (= `@simplysm/` 접두사 **제외**한 짧은 이름). 미지정 시 전체. `check`/`watch`/`dev`/`build`/`publish` 에서 지원. `device` 는 단수(`-t <pkg>` 1회). `replace-deps`/`init` 미지원.
20
- - `-o / --opt <val>` (반복 가능) — `sd.config.ts` 함수의 `params.opt[]` 로 전달. `check` 와 `init` 제외 전 커맨드에서 지원.
21
- - `--debug` — 디버그 로그 출력 (모든 커맨드).
22
- - `--help / -h` — 단독 호출 시 모든 서브커맨드 종합 도움말.
23
-
24
- 커맨드별 고유 옵션:
25
- - `check`: `--type typecheck|lint` (반복 가능, 기본 둘 다), `--fix` (lint 자동 수정).
26
- - `device`: `--target <pkg>` (단수, 미지정 시 유일 client 자동 선택), `--url <devServerUrl>` (미지정 시 `sd.config.ts` 의 server 설정에서 자동 도출).
27
- - `publish`: `--no-build` (빌드 생략), `--dry-run` (실제 배포 없이 시뮬레이션).
28
-
29
- 진실 근거: `packages/sd-cli/src/sd-cli-entry.ts` (yargs 등록부), `packages/sd-cli/src/commands/<cmd>.ts`.
30
-
31
- ### 설정 타입 (`sd.config.ts`)
32
-
33
- - **`SdConfigFn` / `SdConfig` / `SdConfigParams`** — `sd.config.ts` 의 default export 함수와 그 반환 타입. 자세히: [sd-config.md](./sd-config.md)
34
- - **`SdBuildPackageConfig` / `SdClientPackageConfig` / `SdServerPackageConfig` / `SdScriptsPackageConfig`** — `SdConfig.packages` 의 값 타입. 각각 라이브러리 / Frontend 앱 / Fastify 서버 / 유틸 패키지에 대응. 자세히: [sd-config.md](./sd-config.md)
35
- - **`SdPublishConfig` / `SdPostPublishScriptConfig`** — 패키지의 `publish` 와 전역 `postPublish` 항목 타입. 자세히: [sd-config.md](./sd-config.md)
36
- - **`SdCapacitorConfig` / `SdElectronConfig` / `SdPwaConfig` / `SdBrowserSupportConfig`** — client 패키지의 모바일·데스크톱·PWA·브라우저 지원 옵션. 자세히: [sd-config.md](./sd-config.md)
37
-
38
- ### 라이브러리 export
39
-
40
- - **`sdAngularPlugin(options)`** — Vitest 의 `vite.config` / `vitest.config` 에서 Angular 패키지 AOT 컴파일이 필요할 때 plugin 으로 추가.
41
- - **`SdTsCompiler` (+ `ISdTsCompilerOptions`, `ISdTsCompilerResult`)** — Angular/Non-Angular TS 패키지를 증분 컴파일·진단·lint·SCSS 통합 처리하는 엔진. `sd-cli` 내부와 `sdAngularPlugin` 이 사용. 외부에서 동일한 엔진을 재사용할 때만 직접 import.
42
-
43
- ## sdAngularPlugin
44
-
45
- ```typescript
46
- import { sdAngularPlugin, type SdAngularPluginOptions } from "@simplysm/sd-cli";
47
-
48
- // vitest.config.ts
49
- plugins: [sdAngularPlugin({ pkg: "angular" })]
50
- ```
51
-
52
- `pkg` 는 `sd.config.ts.packages` 키 (= `packages/<pkg>/` 디렉토리명). 패키지의 `.ts` 를 AOT 컴파일해 `transform` 훅에서 JS 로 치환한다. `tsconfig.json` 의 `angularCompilerOptions` 유무로 Angular 모드를 자동 감지. Vitest watch 의 `watchChange` 를 받아 증분 재컴파일. 첫 `buildStart` 전에 `config()` 호출 필수 (Vitest 가 자동 호출).
53
-
54
- ## SdTsCompiler
55
-
56
- ```typescript
57
- import { SdTsCompiler } from "@simplysm/sd-cli";
58
-
59
- const compiler = new SdTsCompiler({
60
- pkgDir: "/abs/path/to/packages/foo",
61
- cwd: "/abs/path/to/workspace",
62
- output: { js: true, dts: false }, // 출력 제어 — 둘 다 false 면 typecheck only
63
- includeTests: false, // true 면 tests/ 도 rootNames 에 포함
64
- lint: false,
65
- globalScss: false,
66
- });
67
- const result = await compiler.compileAsync(/* modifiedFiles? */);
68
- // result.diagnostics, result.errorCount, result.emitResults (Angular), ...
69
- ```
70
-
71
- 특징:
72
- - 인스턴스를 재사용해 호출 간 incremental 빌드 (`tsBuildInfoFile` 은 `<pkgDir>/.cache/` 하위).
73
- - `compileAsync(modifiedFiles)` 의 modifiedFiles 는 watch 모드의 변경 파일. 미전달 시 전체 affected 탐색.
74
- - Angular 패키지(`tsconfig.angularCompilerOptions`)는 자동으로 NgtscProgram 사용. 결과의 `emitResults: { filename, contents, sourceFileName }[]` 를 호출자가 디스크/번들러에 전달. Non-Angular 은 `host.writeFile` 로 디스크에 직접 emit (결과의 `emitResults` undefined).
75
- - `compilerOptionsTransformer` 로 target/module/outDir 등을 후처리 override 가능.
76
- - `transformStylesheet`, `externalStylesheets`, `sourceFileCache` 는 Angular 클라이언트 빌드 통합용 (esbuild 플러그인이 사용).
77
- - 단계별 try/catch 로 부분 복구 — 한 단계 실패해도 다른 진단/emit 결과는 유지.
78
- - 결과의 `affectedFiles` 가 `undefined` 면 전역 변경 (전체 리빌드 신호).
79
-
80
- 전체 옵션·결과 필드 정의는 `packages/sd-cli/src/ts-compiler/sd-ts-compiler-options.ts`, `sd-ts-compiler-result.ts` 참조.
@@ -1,155 +0,0 @@
1
- # @simplysm/sd-cli — sd-config
2
-
3
- `sd.config.ts` 작성용 타입 모음. 진실 근거: `packages/sd-cli/src/sd-config.types.ts`.
4
-
5
- ## 진입 타입
6
-
7
- ```typescript
8
- import type { SdConfig, SdConfigFn, SdConfigParams } from "@simplysm/sd-cli";
9
-
10
- const config: SdConfigFn = (params) => ({
11
- packages: {
12
- "core-common": { target: "neutral" },
13
- "core-node": { target: "node" },
14
- },
15
- });
16
- export default config;
17
- ```
18
-
19
- - `SdConfigFn = (params: SdConfigParams) => SdConfig | Promise<SdConfig>`
20
- - `SdConfigParams = { cwd: string; dev: boolean; opt: string[] }` — `opt` 는 CLI `-o` 플래그.
21
- - `SdConfig = { packages: Record<string, SdPackageConfig | undefined>; replaceDeps?: Record<string, string>; postPublish?: SdPostPublishScriptConfig[] }`
22
- - `packages` 키 = `packages/` 하위 디렉토리명.
23
- - `replaceDeps`: node_modules 의 패키지를 로컬 소스로 심링크 교체. 예: `{ "@simplysm/*": "../simplysm/packages/*" }` (key 의 `*` 가 value 의 `*` 로 치환).
24
-
25
- ## 패키지 설정
26
-
27
- `SdPackageConfig = SdBuildPackageConfig | SdClientPackageConfig | SdServerPackageConfig | SdScriptsPackageConfig`.
28
-
29
- ### SdBuildPackageConfig (라이브러리: node/browser/neutral)
30
-
31
- ```typescript
32
- {
33
- target: "node" | "browser" | "neutral"; // BuildTarget
34
- publish?: SdPublishConfig;
35
- copySrc?: string[]; // src/ 기준 glob → dist/ 로 복사
36
- watch?: SdWatchHookConfig; // watch 모드 훅
37
- }
38
- ```
39
-
40
- ### SdClientPackageConfig (Frontend 앱)
41
-
42
- ```typescript
43
- {
44
- target: "client";
45
- server: string | number; // 연결 서버 패키지명, 또는 포트
46
- env?: Record<string, string>; // esbuild define 으로 process.env 치환
47
- publish?: SdPublishConfig;
48
- capacitor?: SdCapacitorConfig;
49
- electron?: SdElectronConfig;
50
- configs?: Record<string, unknown>; // 런타임 설정 → dist/.config.json
51
- exclude?: string[]; // Capacitor/Electron package.json 에 추가
52
- browserSupport?: SdBrowserSupportConfig;
53
- pwa?: false | SdPwaConfig; // 미지정 시 기본값으로 활성
54
- }
55
- ```
56
-
57
- ### SdServerPackageConfig (Fastify 서버)
58
-
59
- ```typescript
60
- {
61
- target: "server";
62
- env?: Record<string, string>; // esbuild banner 로 process.env.KEY 상수 치환
63
- publish?: SdPublishConfig;
64
- configs?: Record<string, unknown>; // 런타임 설정 → dist/.config.json
65
- externals?: string[]; // esbuild external (binding.gyp 자동 감지에 추가)
66
- pm2?: { name?: string; ignoreWatchPaths?: string[] }; // 지정 시 dist/pm2.config.cjs 생성
67
- packageManager?: "volta" | "mise"; // mise.toml / volta 설정 생성에 영향
68
- }
69
- ```
70
-
71
- ### SdScriptsPackageConfig (유틸·임의 명령 실행)
72
-
73
- ```typescript
74
- {
75
- target: "scripts";
76
- publish?: SdPublishConfig;
77
- watch?: SdWatchHookConfig; // 미지정이면 watch/typecheck 에서 제외
78
- }
79
- ```
80
-
81
- `SdWatchHookConfig`: `{ target: string[]; cmd: string; args?: string[] }`. `target` 은 패키지 디렉토리 기준 glob. 매칭 변경 시 `cmd args` 실행.
82
-
83
- ## 배포 설정
84
-
85
- `SdPublishConfig`:
86
- - `{ type: "npm" }` — npm 레지스트리.
87
- - `{ type: "local-directory"; path: string }` — 로컬 복사. `path` 에 `%VER%`, `%PROJECT%` 치환.
88
- - `{ type: "ftp" | "ftps" | "sftp"; host; port?; path?; user?; password? }`.
89
-
90
- `postPublish` 항목 `SdPostPublishScriptConfig`: `{ type: "script"; cmd: string; args: string[] }`. `args` 의 `%VER%`, `%PROJECT%` 치환.
91
-
92
- ## 클라이언트 부속 옵션
93
-
94
- ### SdCapacitorConfig
95
-
96
- ```typescript
97
- {
98
- appId: string; // 예 "com.example.app"
99
- appName: string;
100
- plugins?: Record<string, Record<string, unknown> | true>;
101
- icon?: string; // 패키지 기준 상대 경로
102
- debug?: boolean;
103
- platform?: { android?: SdCapacitorAndroidConfig };
104
- }
105
- ```
106
-
107
- `SdCapacitorAndroidConfig`: `config`(AndroidManifest application 속성), `bundle`(true=AAB, false=APK), `intentFilters`, `sign: SdCapacitorSignConfig`, `sdkVersion`, `permissions: SdCapacitorPermission[]`.
108
-
109
- - `SdCapacitorSignConfig`: `keystore, storePassword, alias, password, keystoreType?` (기본 `"jks"`).
110
- - `SdCapacitorPermission`: `{ name; maxSdkVersion?; ignore? }`.
111
- - `SdCapacitorIntentFilter`: `{ action?; category? }`.
112
-
113
- ### SdElectronConfig
114
-
115
- ```typescript
116
- {
117
- appId: string;
118
- portable?: boolean; // true=포터블 exe, 미지정/false=NSIS 설치본
119
- installerIcon?: string; // .ico, 패키지 기준 상대 경로
120
- reinstallDependencies?: string[]; // 네이티브 모듈 등
121
- postInstallScript?: string;
122
- nsisOptions?: Record<string, unknown>;
123
- env?: Record<string, string>; // electron-main.ts 의 process.env
124
- }
125
- ```
126
-
127
- ### SdPwaConfig
128
-
129
- ```typescript
130
- {
131
- manifest?: {
132
- name?; short_name?;
133
- display?: "standalone" | "fullscreen" | "minimal-ui" | "browser";
134
- theme_color?; background_color?;
135
- icons?: Array<{ src: string; sizes: string; type?: string }>;
136
- };
137
- }
138
- ```
139
-
140
- `pwa: false` 로 비활성. 미지정 시 기본값으로 활성.
141
-
142
- ### SdBrowserSupportConfig
143
-
144
- ```typescript
145
- {
146
- browserslist?: string | string[]; // 예 "last 2 Chrome versions"
147
- postCss?: { plugins: [string, (object | string)?][] };
148
- legacyModule?: boolean; // 코드 분할 비활성 + import.meta 치환
149
- }
150
- ```
151
-
152
- ## 부수 타입
153
-
154
- - `BuildTarget = "node" | "browser" | "neutral"` — `SdBuildPackageConfig.target`.
155
- - `NpmConfig` — `package.json` 구조 헬퍼 (`name`, `version`, `dependencies`, `devDependencies`, `peerDependencies`, `volta?`).
@@ -1,131 +0,0 @@
1
- # @simplysm/service-client
2
-
3
- `@simplysm/service-server` 와 WebSocket(`/ws`) 으로 통신하는 클라이언트. RPC 호출·서버 push 이벤트 구독·파일 업/다운로드·원격 ORM 트랜잭션 실행을 단일 `ServiceClient` 에서 제공한다 (Node/브라우저 공용).
4
-
5
- ## 사용 트리거 인덱스
6
-
7
- - **createServiceClient / ServiceClient / ServiceConnectionOptions** — 서버 접속 클라이언트를 생성하고 `connect()` / `close()` 로 연결 수명을 관리할 때.
8
- - **getService / send / ServiceProxy** — 서버 등록 서비스의 메서드를 타입 안전 RPC 로 호출할 때 (Proxy 호출 또는 저수준 `send`).
9
- - **auth** — 서버 인증 토큰을 등록하고 재연결 시 자동 재인증 + 파일 업로드 인증을 활성화할 때.
10
- - **getEvent / addListener / removeListener / emitEvent / ClientEventProxy** — 서버 push 이벤트를 구독·해지하거나 다른 클라이언트에게 발행할 때.
11
- - **uploadFile / downloadFileBuffer** — 서버에 multipart 파일을 올리거나 정적 경로에서 바이트(`Uint8Array`)로 받을 때.
12
- - **createOrmClientConnector / OrmClientConnector / OrmConnectOptions** — 서버 `"Orm"` 서비스를 통해 `DbContext` 트랜잭션을 원격 실행할 때.
13
- - **OrmClientDbContextExecutor** — `DbContext` 를 직접 구성해야 할 때만. 보통 `OrmClientConnector` 가 내부에서 사용함.
14
- - **ServiceClient 인스턴스 이벤트 (`state` / `request-progress` / `response-progress` / `server-progress`)** — 연결 상태 변화와 전송/응답/서버 진행률을 인스턴스 레벨에서 구독할 때.
15
- - **BlobInput / FileCollection / BrowserWorker / isBrowserWorkerSupported / isNodeWorkerSupported / isWorkerSupported** — Node/브라우저 공용 코드에서 DOM 의존 타입을 대체하거나 Worker 오프로딩 가용성을 확인할 때.
16
-
17
- ## 연결 / 생성
18
-
19
- ```ts
20
- createServiceClient(name: string, options: ServiceConnectionOptions): ServiceClient
21
- interface ServiceConnectionOptions { port: number; host: string; ssl?: boolean; maxReconnectCount?: number; }
22
- client.connect(): Promise<void>
23
- client.close(): Promise<void> // protocol wrapper 의 worker·resolver 자원도 dispose
24
- client.connected: boolean
25
- client.hostUrl: string // `${ssl?https:http}://host:port`
26
- ```
27
-
28
- - WebSocket URL: `${ws|wss}://host:port/ws?ver=2&clientId=<uuid>&clientName=<name>`.
29
- - `maxReconnectCount` 기본 10. `0` 이면 재연결 비활성.
30
- - 5s 마다 ping(`0x01`), 30s 무응답 시 강제 재연결. 재연결 성공 시 인증 토큰과 이벤트 리스너가 자동 복구된다.
31
- - Node 환경에서 글로벌 `WebSocket` 이 없으면 `ws` 패키지로 polyfill (모듈 로드 시 1회).
32
-
33
- ## RPC 호출
34
-
35
- ```ts
36
- client.getService<TService>(serviceName: string): ServiceProxy<TService>
37
- client.send(serviceName, methodName, params: unknown[], progress?: ServiceProgress): Promise<unknown>
38
- type ServiceProxy<T> = { [K in keyof T]: T[K] extends (...a: infer P) => infer R ? (...a: P) => Promise<Awaited<R>> : never }
39
- interface ServiceProgress { request?(s: ServiceProgressState): void; response?(s): void; server?(s): void }
40
- interface ServiceProgressState { uuid: string; totalSize: number; completedSize: number }
41
- ```
42
-
43
- - `getService` 는 Proxy. 임의 메서드명 호출 가능하며 타입 보장은 `TService` 로만.
44
- - 와이어 메시지 이름은 `"<serviceName>.<methodName>"`.
45
- - 인코드/디코드의 Worker 오프로딩 임계값:
46
- - **인코드**: body 가 `Uint8Array`, 30KB 초과 문자열, 길이 100 초과 배열, 또는 첫 원소가 `Uint8Array` 인 배열일 때 Worker.
47
- - **디코드**: 수신 바이트 30KB 초과 시 Worker.
48
- - Worker 미지원/초기화 실패 환경은 메인 스레드 fallback.
49
- - 소켓 끊김·재연결 시 대기 중인 모든 요청은 `"요청 취소됨: 소켓 연결이 끊어졌습니다"` 로 reject.
50
-
51
- ## 인증
52
-
53
- ```ts
54
- client.auth(token: string): Promise<void>
55
- ```
56
-
57
- - 서버에 `auth` 메시지를 보내고 토큰을 내부 저장. 재연결 시 동일 토큰으로 자동 재인증.
58
- - `uploadFile` 은 토큰이 없으면 즉시 throw.
59
-
60
- ## 이벤트 (서버 push)
61
-
62
- ```ts
63
- client.getEvent<TEventDef>(eventName: string): ClientEventProxy<TEventDef>
64
- client.addListener<TEventDef>(eventName, info: TEventDef["$info"], cb): Promise<string> // listener key
65
- client.removeListener(key: string): Promise<void>
66
- client.emitEvent<TEventDef>(eventName, infoSelector: (info) => boolean, data): Promise<void>
67
- interface ClientEventProxy<T> { addListener(info, cb): Promise<string>; removeListener(key): Promise<void>; emit(infoSelector, data): Promise<void> }
68
- ```
69
-
70
- - `addListener` 는 `connected` 상태에서만 호출 가능 (그 외 throw). 로컬 맵에 보관해 재연결 시 자동 재구독.
71
- - `emitEvent` 는 서버에 `evt:gets` 로 후보 목록을 받아 `infoSelector` 통과분에만 `evt:emit` 호출. 대상 0건이면 emit 생략.
72
- - 핸들러 내부 에러는 로깅만, 다른 핸들러 호출은 계속.
73
- - `removeListener` 는 서버 전송 실패를 무시함 (서버가 연결 끊김 시 자동 정리하므로).
74
-
75
- ## 파일 업/다운로드
76
-
77
- ```ts
78
- client.uploadFile(files: File[] | FileCollection | { name: string; data: BlobInput }[]): Promise<ServiceUploadResult[]>
79
- client.downloadFileBuffer(relPath: string): Promise<Uint8Array>
80
- type BlobInput = Blob | Uint8Array<ArrayBuffer> | ArrayBuffer | string
81
- interface FileCollection { readonly length; item(i); [i]; [Symbol.iterator]() } // 브라우저 FileList 와 구조적 호환
82
- ```
83
-
84
- - 업로드: `POST {hostUrl}/upload` (multipart). 헤더 `x-sd-client-name`, `Authorization: Bearer <token>`. 인증 필수.
85
- - 다운로드: `GET {hostUrl}/{relPath}` 응답 본문을 `Uint8Array` 로 반환. `relPath` 가 `/` 로 시작하지 않으면 자동 prepend.
86
- - 브라우저 전용 `File`/`FileList` 대신 `BlobInput`/`FileCollection` 으로 Node 환경도 지원.
87
-
88
- ## ORM 클라이언트
89
-
90
- ```ts
91
- createOrmClientConnector(client: ServiceClient): OrmClientConnector
92
- interface OrmConnectOptions<T extends DbContext> {
93
- DbClass: new (executor: DbContextExecutor, opt: { database: string; schema?: string }) => T;
94
- connOpt: DbConnOptions & { configName: string };
95
- dbContextOpt?: { database: string; schema: string }; // 지정 시 둘 다 필수
96
- }
97
- connector.connect(config, async db => ...) // 트랜잭션 래핑
98
- connector.connectWithoutTransaction(config, async db => ...)
99
- ```
100
-
101
- - 서버 `"Orm"` 서비스에 RPC 를 걸어 `getInfo` → `connect` → `executeDefs` / `executeParametrized` / `bulkInsert` / `begin·commit·rollbackTransaction` / `close` 를 위임.
102
- - `dbContextOpt` 생략 시 서버가 알려준 `database` / `schema` 사용. 최종 `database` 가 빈 값이면 throw.
103
- - 외래키 참조 위반 메시지(`a parent row: a foreign key constraint` / `conflicted with the REFERENCE`)는 "경고! 연관된 작업으로 인해 작업이 거부되었습니다. 후속 작업을 확인해 주세요." 로 변환되어 throw (원본은 `cause`).
104
- - `OrmClientDbContextExecutor` 는 `DbContextExecutor` 구현체. 보통 connector 가 내부 생성하며 직접 인스턴스화는 커스텀 `DbContext` 구성 시에만.
105
-
106
- ## 인스턴스 이벤트 (상태/진행률)
107
-
108
- ```ts
109
- client.on("state", (s: "connected" | "closed" | "reconnecting") => ...)
110
- client.on("request-progress", (s: ServiceProgressState) => ...) // 클라 → 서버 전송 청크 진행
111
- client.on("response-progress", (s: ServiceProgressState) => ...) // 서버 → 클라 응답 청크 진행
112
- client.on("server-progress", (s: ServiceProgressState) => ...) // 서버가 명시적으로 보내는 진행률
113
- ```
114
-
115
- - `request-progress` 는 인코드 결과 chunk 가 2개 이상일 때만 0% 초기값 발행. 단일 청크면 발행 없음.
116
- - `response-progress` 는 분할 수신 중에는 서버 progress 메시지, 응답 완료 시 100% 보정값으로 발행.
117
- - `send` 호출에 전달한 `progress` 콜백은 인스턴스 이벤트와 함께 호출됨.
118
-
119
- ## 환경 호환 유틸
120
-
121
- ```ts
122
- import { BlobInput, FileCollection, BrowserWorker,
123
- isBrowserWorkerSupported, isNodeWorkerSupported, isWorkerSupported }
124
- from "@simplysm/service-client";
125
- ```
126
-
127
- - `BrowserWorker` — DOM `Worker` 의 최소 구조 호환 인터페이스. Node 환경 typecheck 통과용.
128
- - `isBrowserWorkerSupported()` — `"Worker" in globalThis`.
129
- - `isNodeWorkerSupported()` — `process.versions.node` 존재 여부.
130
- - `isWorkerSupported()` — 위 둘 중 하나.
131
- - 보통 직접 호출할 필요 없음 (`ServiceClient` 내부에서 분기). 환경 분기 로직을 사용자 코드에서 직접 짤 때만 사용.
@@ -1,29 +0,0 @@
1
- # @simplysm/service-common
2
-
3
- 서버/클라이언트가 공유하는 서비스 프로토콜·메시지 타입·서비스 인터페이스·앱 구조 정의·이벤트 정의 유틸.
4
-
5
- ## 사용 트리거 인덱스
6
-
7
- - **`createServiceProtocol` / `ServiceProtocol` / `ServiceMessageDecodeResult` / `PROTOCOL_CONFIG`** — 서버/클라이언트 transport 의 바이너리 V2 프로토콜(헤더 28B + JSON, 3MB↑ 자동 청킹, 100MB 한계) 인/디코더 생성. 자세히: [protocol.md](./protocol.md)
8
- - **메시지 타입 (`ServiceMessage` / `ServiceClientMessage` / `ServiceServerMessage` / `ServiceServerRawMessage` 및 9 종의 개별 메시지)** — 프로토콜 위에 실리는 메시지 식별·타입 가드·핸들러 분기. 자세히: [messages.md](./messages.md)
9
- - **서비스 인터페이스 (`OrmService` / `AutoUpdateService` / `AppStructureService` / `DbConnOptions`)** — 서버 구현·클라이언트 호출 양쪽이 공유하는 빌트인 서비스의 시그니처. 자세히: [service-types.md](./service-types.md)
10
- - **앱 구조 (`AppStructureItem` / `AppStructureGroupItem` / `AppStructureLeafItem` / `AppStructureSubPermission` / `FlatPermission` + `isUsableModules` / `isUsableModulesChain` / `getFlatPermissions`)** — 메뉴/권한 트리 정의와 모듈 기반 가용성 평가·평탄화. 자세히: [app-structure.md](./app-structure.md)
11
- - **`defineEvent` / `ServiceEventDef`** — 서버 발신·클라이언트 구독에서 `info`/`data` 타입을 공유하기 위한 이벤트 정의.
12
- - **`ServiceUploadResult`** — 파일 업로드 결과(저장 경로·원본명·바이트 크기).
13
-
14
- ## defineEvent / ServiceEventDef
15
-
16
- ```ts
17
- function defineEvent<TInfo, TData>(eventName: string): ServiceEventDef<TInfo, TData>
18
- interface ServiceEventDef<TInfo, TData> { eventName: string; readonly $info: TInfo; readonly $data: TData; }
19
- ```
20
-
21
- `$info`/`$data` 는 런타임 미사용, 타입 추출 전용 마커. 서버는 `defineEvent` 로 정의·export 하고, 클라이언트는 `import type` 으로 가져와 `addListener<typeof Evt>(...)` / `emitEvent<typeof Evt>(...)` 에 전달해 `info` 필터·`data` 페이로드를 정적으로 검증한다.
22
-
23
- ## ServiceUploadResult
24
-
25
- ```ts
26
- interface ServiceUploadResult { path: string; filename: string; size: number; }
27
- ```
28
-
29
- 서버 업로드 핸들러가 클라이언트로 반환하는 결과. `path` 는 서버 내부 저장 경로다.
@@ -1,63 +0,0 @@
1
- # @simplysm/service-common — app-structure
2
-
3
- 메뉴/권한 트리 정의 타입과 모듈(라이선스/플랜 등) 기반 가용성 평가·평탄화 함수.
4
-
5
- ## 타입
6
-
7
- ```ts
8
- type AppStructureItem<TModule = unknown> =
9
- | AppStructureGroupItem<TModule>
10
- | AppStructureLeafItem<TModule>;
11
-
12
- interface AppStructureGroupItem<TModule> {
13
- code: string; title: string;
14
- modules?: TModule[]; requiredModules?: TModule[];
15
- icon?: string;
16
- children: AppStructureItem<TModule>[];
17
- }
18
-
19
- interface AppStructureLeafItem<TModule> {
20
- code: string; title: string;
21
- modules?: TModule[]; requiredModules?: TModule[];
22
- perms?: ("use" | "edit")[];
23
- subPerms?: AppStructureSubPermission<TModule>[];
24
- icon?: string; url?: string;
25
- isNotMenu?: boolean;
26
- }
27
-
28
- interface AppStructureSubPermission<TModule> {
29
- code: string; title: string;
30
- modules?: TModule[]; requiredModules?: TModule[];
31
- perms: ("use" | "edit")[];
32
- }
33
-
34
- interface FlatPermission<TModule = unknown> {
35
- titleChain: string[];
36
- codeChain: string[]; // [...상위 code, perm] 또는 [...상위 code, subPerm.code, perm]
37
- modulesChain: TModule[][];
38
- }
39
- ```
40
-
41
- Group/Leaf 는 `children` 존재로 구분(`"children" in item`).
42
-
43
- ## isUsableModules(modules, requiredModules, usableModules) → boolean
44
-
45
- - `requiredModules` (AND): 모두 `usableModules` 에 포함되어야 함. 없거나 빈 배열이면 통과.
46
- - `modules` (OR): 비었거나 그 중 하나라도 `usableModules` 에 있으면 통과.
47
-
48
- ## isUsableModulesChain(modulesChain, requiredModulesChain, usableModules) → boolean
49
-
50
- 체인 각 레벨에 대해 `modules` OR 와 `requiredModules` AND 모두 만족해야 통과. 트리 깊이별 누적 조건 평가용.
51
-
52
- ## getFlatPermissions(items, usableModules) → FlatPermission[]
53
-
54
- 트리를 BFS 로 순회하며 각 leaf 의 `perms` / `subPerms` 를 평탄화한다.
55
-
56
- - 진행 중 노드 단위로 `isUsableModulesChain` 체크 — 실패 시 하위 폐기.
57
- - `subPerms` 도 자체 `modules`/`requiredModules` 로 추가 필터.
58
- - 결과 `codeChain` 마지막에 권한값(`"use"|"edit"`)이 붙는다.
59
-
60
- ```ts
61
- const perms = getFlatPermissions(items, ["BASIC", "PRO"]);
62
- // [{ titleChain: ["주문","주문등록"], codeChain: ["order","register","use"], modulesChain: [["PRO"]] }, ...]
63
- ```
@@ -1,56 +0,0 @@
1
- # @simplysm/service-common — messages
2
-
3
- `ServiceProtocol` 위에 실리는 메시지 식별자(`name`) 별 바디 스키마. 모든 인터페이스는 `name` discriminator 로 좁힌다.
4
-
5
- ## 유니언
6
-
7
- ```ts
8
- type ServiceMessage =
9
- | ServiceRequestMessage | ServiceAuthMessage
10
- | ServiceProgressMessage | ServiceResponseMessage | ServiceErrorMessage
11
- | ServiceAddEventListenerMessage | ServiceRemoveEventListenerMessage
12
- | ServiceGetEventListenerInfosMessage
13
- | ServiceEmitEventMessage | ServiceEventMessage;
14
-
15
- type ServiceClientMessage = // 클라이언트 → 서버
16
- | ServiceRequestMessage | ServiceAuthMessage
17
- | ServiceAddEventListenerMessage | ServiceRemoveEventListenerMessage
18
- | ServiceGetEventListenerInfosMessage | ServiceEmitEventMessage;
19
-
20
- type ServiceServerMessage = // 서버 → 클라이언트 (디스패치 대상)
21
- | ServiceResponseMessage | ServiceErrorMessage | ServiceEventMessage;
22
-
23
- type ServiceServerRawMessage = // 서버 → 클라이언트 (progress 포함 전체)
24
- | ServiceProgressMessage | ServiceServerMessage;
25
- ```
26
-
27
- ## 시스템
28
-
29
- - `ServiceProgressMessage` — `name: "progress"`, `body: { totalSize, completedSize }`. 서버가 청크 수신 진행률 알림.
30
- - `ServiceErrorMessage` — `name: "error"`, `body: { name, message, code, stack?, detail?, cause? }`. 처리 중 에러 알림.
31
- - `ServiceAuthMessage` — `name: "auth"`, `body: string` (토큰). 클라이언트 인증.
32
-
33
- ## 서비스 메서드
34
-
35
- - `ServiceRequestMessage` — `` name: `${string}.${string}` `` (예: `"User.findOne"`), `body: unknown[]` (매개변수 배열).
36
- - `ServiceResponseMessage` — `name: "response"`, `body?: unknown` (반환값).
37
-
38
- ## 이벤트
39
-
40
- - `ServiceAddEventListenerMessage` — `name: "evt:add"`, `body: { key, name, info }`. `key` 는 uuid (remove 키).
41
- - `ServiceRemoveEventListenerMessage` — `name: "evt:remove"`, `body: { key }`.
42
- - `ServiceGetEventListenerInfosMessage` — `name: "evt:gets"`, `body: { name }`. 동일 이벤트 구독자들의 `info` 목록 요청.
43
- - `ServiceEmitEventMessage` — `name: "evt:emit"`, `body: { keys, data }`. 클라이언트 발생.
44
- - `ServiceEventMessage` — `name: "evt:on"`, `body: { keys, data }`. 서버 알림.
45
-
46
- ## 사용
47
-
48
- ```ts
49
- function dispatch(msg: ServiceServerMessage) {
50
- switch (msg.name) {
51
- case "response": return resolveCall(msg.body);
52
- case "error": return rejectCall(msg.body);
53
- case "evt:on": return notifyListeners(msg.body.keys, msg.body.data);
54
- }
55
- }
56
- ```
@@ -1,64 +0,0 @@
1
- # @simplysm/service-common — protocol
2
-
3
- 서비스 transport(웹소켓 등) 위에 얹는 바이너리 메시지 프로토콜(V2). 메시지를 청크로 자르고/재조립하며, 청크 누적의 GC 까지 캡슐화한다.
4
-
5
- ## PROTOCOL_CONFIG
6
-
7
- ```ts
8
- const PROTOCOL_CONFIG = {
9
- MAX_TOTAL_SIZE: 100 * 1024 * 1024, // 100MB 한계 (인/디코딩 양쪽에서 검사)
10
- SPLIT_MESSAGE_SIZE: 3 * 1024 * 1024, // 이 크기 초과 시 청크 분할
11
- CHUNK_SIZE: 300 * 1024, // 청크 본문 크기
12
- GC_INTERVAL: 10 * 1000, // 청크 누적기 GC 주기
13
- EXPIRE_TIME: 60 * 1000, // 미완성 메시지 만료
14
- } as const;
15
- ```
16
-
17
- `as const`. 임계값 조정 필요 시 이 상수를 참조한다.
18
-
19
- ## ServiceProtocol
20
-
21
- ```ts
22
- interface ServiceProtocol {
23
- encode(uuid: string, message: ServiceMessage): { chunks: Bytes[]; totalSize: number };
24
- decode<T extends ServiceMessage>(bytes: Bytes): ServiceMessageDecodeResult<T>;
25
- dispose(): void;
26
- }
27
- ```
28
-
29
- - 청크 헤더 28B: UUID 16B + TotalSize 8B(uint64, 상위 4B 는 0) + Index 4B(uint32), Big Endian.
30
- - 본문: `json.stringify([name, body?])` UTF-8.
31
- - `dispose()` 는 내부 `LazyGcMap` 의 GC 타이머를 해제. 인스턴스 종료 시 반드시 호출.
32
-
33
- ## ServiceMessageDecodeResult
34
-
35
- ```ts
36
- type ServiceMessageDecodeResult<T extends ServiceMessage> =
37
- | { type: "complete"; uuid: string; message: T }
38
- | { type: "progress"; uuid: string; totalSize: number; completedSize: number };
39
- ```
40
-
41
- - `complete`: 모든 청크 수신·재조립 완료. 메시지 디스패치 가능.
42
- - `progress`: 청크 일부만 도착. 진행률 표시·`progress` 알림 송신에 사용.
43
-
44
- ## createServiceProtocol()
45
-
46
- `ServiceProtocol` 인스턴스를 생성한다. 서버·클라이언트 각자 1 개씩 보유하는 것이 일반적.
47
-
48
- ```ts
49
- const proto = createServiceProtocol();
50
- const { chunks } = proto.encode(uuid, { name: "User.findOne", body: [{ id: 1 }] });
51
- for (const c of chunks) socket.send(c);
52
-
53
- const res = proto.decode<ServiceServerMessage>(receivedBytes);
54
- if (res.type === "complete") handle(res.message);
55
- ```
56
-
57
- 예외:
58
-
59
- - `MAX_TOTAL_SIZE` 초과: `ArgumentError("메시지 크기가 제한을 초과했습니다.")`.
60
- - 헤더(<28B) 미달: `ArgumentError("버퍼 크기가 헤더 크기보다 작습니다.")`.
61
- - 본문 JSON 파싱 실패: `ArgumentError("메시지 디코딩에 실패했습니다.", { uuid, cause })`.
62
- - 무결성 위반(누적 크기 > totalSize): `ArgumentError("프로토콜 무결성 위반: ...")`.
63
-
64
- 중복 청크는 인덱스가 이미 채워진 경우 무시(방어). 만료(`EXPIRE_TIME`) 시 누적 항목은 GC 가 폐기.
@@ -1,43 +0,0 @@
1
- # @simplysm/service-common — service-types
2
-
3
- 서버 구현·클라이언트 호출이 공유하는 빌트인 서비스 인터페이스. 서버는 인터페이스를 구현, 클라이언트는 동일 시그니처로 RPC 호출한다.
4
-
5
- ## OrmService
6
-
7
- ```ts
8
- interface OrmService {
9
- getInfo(opt: DbConnOptions & { configName: string }): Promise<{ dialect: Dialect; database?: string; schema?: string }>;
10
- connect(opt: DbConnOptions & { configName: string }): Promise<number>; // connId
11
- close(connId: number): Promise<void>;
12
- beginTransaction(connId: number, isolationLevel?: IsolationLevel): Promise<void>;
13
- commitTransaction(connId: number): Promise<void>;
14
- rollbackTransaction(connId: number): Promise<void>;
15
- executeParametrized(connId: number, query: string, params?: unknown[]): Promise<unknown[][]>;
16
- executeDefs(connId: number, defs: QueryDef[], options?: (ResultMeta | undefined)[]): Promise<unknown[][]>;
17
- bulkInsert(connId: number, tableName: string, columnDefs: Record<string, ColumnMeta>, records: Record<string, unknown>[]): Promise<void>;
18
- }
19
-
20
- type DbConnOptions = { configName?: string; config?: Record<string, unknown> };
21
- ```
22
-
23
- MySQL / MSSQL / PostgreSQL 공통 추상. `connId` 단위로 트랜잭션·세션 식별. `Dialect`·`IsolationLevel`·`QueryDef`·`ColumnMeta`·`ResultMeta` 는 `@simplysm/orm-common` 정의.
24
-
25
- ## AutoUpdateService
26
-
27
- ```ts
28
- interface AutoUpdateService {
29
- getLastVersion(platform: string): Promise<{ version: string; downloadPath: string } | undefined>;
30
- }
31
- ```
32
-
33
- `platform` 예: `"win32" | "darwin" | "linux"`. 등록된 버전 없으면 `undefined`.
34
-
35
- ## AppStructureService
36
-
37
- ```ts
38
- interface AppStructureService {
39
- getItems(): Record<string, AppStructureItem[]>;
40
- }
41
- ```
42
-
43
- 키는 클라이언트명, 값은 해당 클라이언트의 앱 구조 트리. `AppStructureItem` 은 [app-structure.md](./app-structure.md) 참조.
@@ -1,13 +0,0 @@
1
- # @simplysm/service-server
2
-
3
- Fastify + WebSocket 기반 서비스 서버. 클라이언트(`@simplysm/service-client`)와 짝으로 RPC·이벤트 푸시·파일 업로드·정적 서빙·JWT 인증을 단일 포트로 제공한다.
4
-
5
- ## 사용 트리거 인덱스
6
-
7
- | 트리거 | 자료 |
8
- | --- | --- |
9
- | 서버 인스턴스 생성·기동·종료, 이벤트 emit, JWT 토큰 발급/검증, `ServiceServerOptions`(`rootPath`/`port`/`ssl`/`auth`/`services`/`legacyV1Handlers`) | [server.md](./server.md) |
10
- | 사용자 서비스 정의(`defineService`), `ServiceContext`, `ServiceMethods` 타입 추출, `createServiceContext`, `getServiceAuthPermissions` | [define-service.md](./define-service.md) |
11
- | 인증 래퍼 `auth()` (서비스/메서드 레벨, 역할 제한), `AuthTokenPayload`, `signJwt`/`verifyJwt`/`decodeJwt` | [auth.md](./auth.md) |
12
- | 빌트인 서비스: `OrmService`, `AutoUpdateService`, `AppStructureService`, V1 레거시 자동 업데이트 핸들러 | [builtin-services.md](./builtin-services.md) |
13
- | 내부 전송 계층(`/api/:service/:method`·`/upload`·정적 서빙, WebSocket 핸들러, 프로토콜 래퍼/워커, `ServiceSocket`, `getConfig`) — 직접 사용 시 | [internals.md](./internals.md) |