@simplysm/sd-claude 14.0.91 → 14.0.92
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 -6
- package/claude/references/sd-simplysm14/apis/angular/README.md +59 -39
- package/claude/references/sd-simplysm14/apis/angular/controls.md +119 -186
- package/claude/references/sd-simplysm14/apis/angular/crud.md +70 -31
- package/claude/references/sd-simplysm14/apis/angular/directives.md +55 -57
- package/claude/references/sd-simplysm14/apis/angular/features.md +86 -105
- package/claude/references/sd-simplysm14/apis/angular/infra.md +48 -57
- package/claude/references/sd-simplysm14/apis/angular/layout.md +37 -47
- package/claude/references/sd-simplysm14/apis/angular/overlay.md +82 -74
- package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +61 -50
- package/claude/references/sd-simplysm14/apis/angular/shared-data.md +74 -57
- package/claude/references/sd-simplysm14/apis/angular/sheet.md +63 -72
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +23 -18
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +21 -19
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +23 -18
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +72 -32
- package/claude/references/sd-simplysm14/apis/core-browser/README.md +18 -18
- package/claude/references/sd-simplysm14/apis/core-browser/dom-element.md +29 -29
- package/claude/references/sd-simplysm14/apis/core-browser/indexed-db.md +41 -41
- package/claude/references/sd-simplysm14/apis/core-common/README.md +97 -90
- package/claude/references/sd-simplysm14/apis/core-common/async-runtime.md +75 -51
- package/claude/references/sd-simplysm14/apis/core-common/collection-ext.md +81 -0
- package/claude/references/sd-simplysm14/apis/core-common/errors.md +27 -29
- package/claude/references/sd-simplysm14/apis/core-common/obj.md +44 -45
- package/claude/references/sd-simplysm14/apis/core-common/serialization.md +34 -33
- package/claude/references/sd-simplysm14/apis/core-common/value-types.md +86 -0
- package/claude/references/sd-simplysm14/apis/core-node/README.md +6 -6
- package/claude/references/sd-simplysm14/apis/core-node/consola.md +3 -0
- package/claude/references/sd-simplysm14/apis/core-node/cpx.md +2 -2
- package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +1 -1
- package/claude/references/sd-simplysm14/apis/core-node/fsx.md +2 -2
- package/claude/references/sd-simplysm14/apis/core-node/worker.md +6 -3
- package/claude/references/sd-simplysm14/apis/excel/README.md +10 -10
- package/claude/references/sd-simplysm14/apis/excel/conditional-format.md +4 -2
- package/claude/references/sd-simplysm14/apis/excel/utils.md +1 -1
- package/claude/references/sd-simplysm14/apis/excel/workbook-worksheet.md +6 -6
- package/claude/references/sd-simplysm14/apis/lint/README.md +6 -32
- package/claude/references/sd-simplysm14/apis/lint/recommended.md +60 -0
- package/claude/references/sd-simplysm14/apis/lint/rules.md +17 -17
- package/claude/references/sd-simplysm14/apis/orm-common/README.md +15 -6
- package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +68 -102
- package/claude/references/sd-simplysm14/apis/orm-common/expr.md +75 -89
- package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +87 -99
- package/claude/references/sd-simplysm14/apis/orm-common/schema.md +110 -147
- package/claude/references/sd-simplysm14/apis/orm-common/types.md +48 -51
- package/claude/references/sd-simplysm14/apis/orm-node/README.md +8 -13
- package/claude/references/sd-simplysm14/apis/orm-node/db-conn.md +5 -5
- package/claude/references/sd-simplysm14/apis/sd-cli/README.md +9 -6
- package/claude/references/sd-simplysm14/apis/sd-cli/SdTsCompiler.md +9 -8
- package/claude/references/sd-simplysm14/apis/sd-cli/sd-config-types.md +23 -19
- package/claude/references/sd-simplysm14/apis/service-client/README.md +20 -12
- package/claude/references/sd-simplysm14/apis/service-client/orm.md +6 -6
- package/claude/references/sd-simplysm14/apis/service-client/transport.md +1 -1
- package/claude/references/sd-simplysm14/apis/service-common/README.md +35 -32
- package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +23 -22
- package/claude/references/sd-simplysm14/apis/service-common/protocol.md +23 -23
- package/claude/references/sd-simplysm14/apis/service-server/README.md +51 -43
- package/claude/references/sd-simplysm14/apis/service-server/service-authoring.md +6 -6
- package/claude/references/sd-simplysm14/apis/service-server/transport-internals.md +31 -21
- package/claude/references/sd-simplysm14/apis/service-server/v1-legacy.md +8 -8
- package/claude/references/sd-simplysm14/apis/storage/README.md +55 -49
- package/claude/references/sd-simplysm14/manuals/client-component.md +843 -740
- package/claude/references/sd-simplysm14/manuals/client-crud.md +8 -0
- package/claude/references/sd-simplysm14/manuals/client-demo.md +6 -16
- package/claude/references/sd-simplysm14/manuals/client-shared-data.md +26 -0
- package/claude/references/sd-simplysm14/manuals/logging.md +1 -1
- package/claude/references/sd-simplysm14/manuals/orm.md +15 -1
- package/claude/rules/sd-design-rules.md +7 -0
- package/claude/sd-system-prompt.md +5 -8
- package/claude/skills/sd-debug/SKILL.md +43 -0
- package/claude/skills/sd-debug/workflow.js +390 -0
- package/claude/skills/sd-demo/SKILL.md +18 -20
- package/claude/skills/sd-dev/SKILL.md +127 -24
- package/claude/skills/sd-docs/SKILL.md +5 -3
- package/claude/skills/sd-docs/references/subagent-prompt.md +2 -3
- package/claude/skills/sd-impl/SKILL.md +18 -18
- package/claude/skills/sd-manual/SKILL.md +1 -0
- package/claude/skills/sd-review/SKILL.md +24 -18
- package/claude/skills/sd-review/workflow.js +324 -0
- package/claude/skills/sd-spec/SKILL.md +96 -679
- package/claude/skills/sd-spec/references/example-spec.md +28 -50
- package/claude/skills/sd-spec/references/format-analyze.md +232 -0
- package/claude/skills/sd-spec/references/format-design.md +248 -0
- package/claude/skills/sd-spec/workflow-analyze.js +615 -0
- package/claude/skills/sd-spec/workflow-design.js +667 -0
- package/claude/skills/sd-unpack/scripts/handlers/office_com.py +5 -1
- package/package.json +1 -1
- package/scripts/postinstall.mjs +157 -18
- package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +0 -68
- package/claude/references/sd-simplysm14/apis/core-common/array-ext.md +0 -77
- package/claude/references/sd-simplysm14/apis/core-common/datetime.md +0 -86
- package/claude/skills/sd-skill/SKILL.md +0 -245
- package/claude/skills/sd-skill/scripts/run_eval.py +0 -380
|
@@ -1,79 +1,90 @@
|
|
|
1
|
-
# @simplysm/angular —
|
|
1
|
+
# @simplysm/angular — 라우팅·메뉴·권한(app-structure)
|
|
2
2
|
|
|
3
3
|
라우터 링크·현재 페이지 식별·뷰 컨텍스트(page/control/modal)·이탈 가드, 그리고 앱 구조 트리에서 메뉴·권한을 파생하는 군. 화면 컴포넌트의 표준 시그널 `viewType`, 권한 가드 `injectPermsSignal`, 사이드바/탑바 메뉴가 이 군에 의존.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 페이지 코드·뷰 타입·제목 시그널
|
|
6
|
+
|
|
7
|
+
injection 컨텍스트에서 호출하는 헬퍼들. 현재 라우트 상태를 시그널로 노출.
|
|
8
|
+
|
|
9
|
+
- `injectFullPageCodeSignal(): Signal<string>` — 전체 URL 경로를 점(`.`) 연결 코드로 반환(`/home/a/b` → `"a.b"`). 라우팅 변경 시 갱신.
|
|
10
|
+
- `injectCurrentPageCodeSignal(): Signal<string> | undefined` — 현재 컴포넌트 기준 상대 페이지 코드. `ActivatedRoute` 없으면 `undefined`.
|
|
11
|
+
- `injectViewTitleSignal(): Signal<string>` — 현재 화면 제목. 모달이면 모달 제목, 아니면 앱 구조에서 코드로 찾은 제목.
|
|
12
|
+
- `injectViewTypeSignal(): Signal<SdViewType>` — 화면이 동작 중인 컨텍스트. `SdViewType = "page"|"modal"|"control"`. 라우팅 진입(셀렉터=현재 코드)이면 `"page"`, 모달이면 `"modal"`, view 의 자식 등이면 `"control"`. `sd-base-container`/`sd-crud-*` 의 `[viewType]` 입력에 그대로 전달.
|
|
6
13
|
|
|
7
14
|
```ts
|
|
8
|
-
|
|
9
|
-
|
|
15
|
+
viewType = injectViewTypeSignal();
|
|
16
|
+
viewTitle = injectViewTitleSignal();
|
|
10
17
|
```
|
|
11
18
|
|
|
12
|
-
|
|
19
|
+
## setupCanDeactivate
|
|
13
20
|
|
|
14
|
-
|
|
21
|
+
라우터/모달 이탈 시점에 호출되는 가드를 등록. injection 컨텍스트에서 호출.
|
|
15
22
|
|
|
16
|
-
- `
|
|
23
|
+
- `setupCanDeactivate(fn: () => boolean): void` — `fn()` 이 `false` 면 이탈 차단. 모달이면 `SdActivatedModalProvider.canDeactivateFn` 설정, 페이지면 route 의 `canDeactivate` 에 push(파괴 시 자동 제거). detail 화면의 변경사항 가드에 사용.
|
|
17
24
|
|
|
18
|
-
|
|
25
|
+
```ts
|
|
26
|
+
setupCanDeactivate(() => this._orgData == null || obj.equal(this.data(), this._orgData) || confirm("변경사항이 있습니다. 진행할까요?"));
|
|
27
|
+
```
|
|
19
28
|
|
|
20
|
-
|
|
21
|
-
- `function injectCurrentPageCodeSignal(): Signal<string> | undefined` — 현재 `ActivatedRoute` 기준 상대 페이지 코드. 라우트 컨텍스트 없으면 `undefined`. 중첩 라우트에서 자기 위치 코드가 필요할 때.
|
|
29
|
+
## SdNavigateWindowProvider
|
|
22
30
|
|
|
23
|
-
|
|
31
|
+
새 창/탭으로 라우트를 여는 프로바이더. 현재 컨텍스트가 창 모드인지 판별.
|
|
24
32
|
|
|
25
|
-
- `
|
|
33
|
+
- `isWindow: boolean` — 현재가 `window=true` 쿼리로 열린 창인지.
|
|
34
|
+
- `open(navigate: string, params?: Record<string,string>, features?: string): void` — 창 모드이거나 `features` 가 있으면 `window.open` 으로 새 창(beforeunload 시 자식 창 정리), 아니면 `_blank` 새 탭으로 라우트 열기.
|
|
26
35
|
|
|
27
|
-
## SdRouterLink
|
|
36
|
+
## SdRouterLink
|
|
28
37
|
|
|
29
|
-
|
|
38
|
+
`[sdRouterLink]` 디렉티브. 클릭 시 옵션에 따라 라우팅/새 창/아웃렛 이동.
|
|
30
39
|
|
|
31
|
-
- `sdRouterLink
|
|
32
|
-
- `link` — 라우트 경로. `outletName` 있으면 named outlet 이동.
|
|
33
|
-
- `params` — 매트릭스 파라미터, `queryParams` — 쿼리 파라미터.
|
|
34
|
-
- `window` — Ctrl/Shift 클릭 또는 window 컨텍스트일 때 팝업 창 크기(기본 800x800).
|
|
35
|
-
- 미지정(`undefined`) 이면 클릭 무시 + 커서 기본. 메뉴 항목이 leaf 가 아닐 때 등.
|
|
36
|
-
- Alt+클릭은 무시. 사이드바/탑바 메뉴가 `getMenuRouterLinkOption(menu)` 결과를 이 입력에 바인딩.
|
|
40
|
+
- `sdRouterLink` (option) — `{ link, params?, window?: { width?, height? }, outletName?, queryParams? }`. `link` 가 이동 경로, `params` 가 matrix 파라미터, `window` 가 창 크기, `outletName` 이 named outlet, `queryParams` 가 쿼리. Ctrl/Shift+클릭이면 새 창, 창 모드면 팝업 창, 아니면 `Router.navigate`. Alt+클릭은 무시.
|
|
37
41
|
|
|
38
|
-
|
|
42
|
+
```html
|
|
43
|
+
<a [sdRouterLink]="{ link: '/home/goods/detail', params: { id: '5' } }">상세</a>
|
|
44
|
+
```
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
- `open(navigate: string, params?: Record<string,string>, features?: string): void` — 새 창/탭으로 라우트 열기. window 컨텍스트이거나 `features` 가 있으면 `window=true` 팝업으로(부모 unload 시 자동 close), 아니면 `_blank` 탭으로. `SdRouterLink` 내부 + 화면에서 보조 창을 띄울 때.
|
|
46
|
+
## 메뉴 유틸 (menu-utils)
|
|
42
47
|
|
|
43
|
-
|
|
48
|
+
`SdMenu` 로부터 라우터 링크 옵션·선택 여부를 계산. 사이드바/탑바 메뉴가 사용.
|
|
44
49
|
|
|
45
|
-
|
|
50
|
+
- `getMenuRouterLinkOption(menu: SdMenu): { link, queryParams } | undefined` — leaf 메뉴면 `"/home/"+코드체인` 링크와 쿼리파라미터 반환, 그룹/외부 url 메뉴면 `undefined`.
|
|
51
|
+
- `getIsMenuSelected(menu, fullPageCode?, customFn?): boolean` — `customFn` 있으면 그것으로, 없으면 현재 fullPageCode 와 메뉴 코드체인 일치 여부.
|
|
46
52
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
## SdAppStructureProvider<TModule>
|
|
54
|
+
|
|
55
|
+
앱 메뉴·권한 트리(`AppStructureItem[]`)에서 사용 가능 메뉴·권한을 파생하는 전역 프로바이더. `providedIn: "root"`.
|
|
50
56
|
|
|
51
|
-
- `
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
- `findTitleByFullCode(fullCode): string | undefined` / `getTitleByFullCode(fullCode): string`(못 찾으면 throw) / `getItemChainByFullCode(fullCode)` — 코드로 제목·항목 체인 조회.
|
|
57
|
+
- `usableModules: WritableSignal<TModule[] | undefined>` — 사용자가 보유한 모듈. 메뉴/권한 필터에 사용.
|
|
58
|
+
- `permRecord: WritableSignal<Record<string, boolean> | undefined>` — `"코드.액션"→보유여부` 권한 맵.
|
|
59
|
+
- `items: WritableSignal<AppStructureItem<TModule>[]>` — 앱 구조 원본.
|
|
60
|
+
- `initialize(items)` — 구조 트리 주입.
|
|
61
|
+
- `usableMenus`/`usableFlatMenus` — 모듈·권한으로 필터된 메뉴 트리/평면 메뉴(computed).
|
|
62
|
+
- `getPermsByFullCode(fullCodes, permKeys): K[]` — 해당 코드들에서 보유한 권한 키 배열. 권한 정의 자체가 없는 항목은 모든 키 통과.
|
|
63
|
+
- `getTitleByFullCode`/`findTitleByFullCode` — 코드로 제목 조회(전자는 미발견 시 throw, 후자는 `undefined`).
|
|
64
|
+
- `getItemChainByFullCode`/`getPermissionsByStructure` — 코드 체인·권한 트리 조회.
|
|
60
65
|
|
|
61
|
-
##
|
|
66
|
+
## injectPermsSignal
|
|
62
67
|
|
|
63
|
-
|
|
68
|
+
화면 컴포넌트가 권한을 시그널로 받는 헬퍼. injection 컨텍스트에서 호출.
|
|
69
|
+
|
|
70
|
+
- `injectPermsSignal<K>(viewCodes: string[], keys: K[]): Signal<K[]>` — `viewCodes` 권한 path 들에서 사용자가 보유한 `keys` 만 담은 배열을 반환. 템플릿/코드에서 `perms().includes("edit")` 식으로 인라인 가드.
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
perms = injectPermsSignal(["inventory.outbound"], ["use", "edit"]);
|
|
74
|
+
// this.perms().includes("use")
|
|
75
|
+
```
|
|
64
76
|
|
|
65
|
-
|
|
66
|
-
- `getFlatMenus(items, usableModules, permRecord): SdFlatMenu[]` — BFS 평탄화 메뉴.
|
|
67
|
-
- `getPermissions(items, codeChain, usableModules): SdPermission[]` — 권한표용 트리(leaf 의 `perms`/`subPerms` 포함).
|
|
68
|
-
- `getFlatPermissions(items, usableModules)` / `findTitleByFullCode` / `getTitleByFullCode` / `getItemChainByFullCode` / `getPermsByFullCode` — provider 동명 메서드의 구현.
|
|
77
|
+
## SdAppStructureUtils
|
|
69
78
|
|
|
70
|
-
|
|
79
|
+
`AppStructureItem[]` 에서 메뉴/권한/제목을 계산하는 정적 메서드 모음(추상 클래스). 대개 `SdAppStructureProvider` 가 내부에서 호출하지만 직접 쓸 수도 있음.
|
|
71
80
|
|
|
72
|
-
- `
|
|
73
|
-
- `
|
|
81
|
+
- `getMenus(items, codeChain, usableModules, permRecord): SdMenu[]` — 모듈·`use` 권한으로 필터된 메뉴 트리.
|
|
82
|
+
- `getFlatMenus(...)`: `SdFlatMenu[]` — 평면 메뉴(BFS, titleChain/codeChain/modulesChain 보유).
|
|
83
|
+
- `getPermissions(items, codeChain, usableModules): SdPermission[]` — 권한 트리(subPerms 를 children 으로).
|
|
84
|
+
- `getTitleByFullCode`/`findTitleByFullCode`/`getItemChainByFullCode`/`getPermsByFullCode`/`getFlatPermissions` — provider 와 동일 동작의 정적 버전.
|
|
74
85
|
|
|
75
|
-
## 타입
|
|
86
|
+
## 타입 (sd-app-structure.types)
|
|
76
87
|
|
|
77
|
-
- `SdMenu
|
|
78
|
-
- `SdFlatMenu<TModule
|
|
79
|
-
- `SdPermission<TModule
|
|
88
|
+
- `SdMenu` — `{ title; codeChain: string[]; url?; icon?; children? }`. 사이드바/탑바 메뉴 렌더 단위.
|
|
89
|
+
- `SdFlatMenu<TModule>` — `{ titleChain: string[]; codeChain: string[]; modulesChain: TModule[][] }`. 검색용 평면 메뉴.
|
|
90
|
+
- `SdPermission<TModule>` — `{ title; codeChain; modules; perms: ("use"|"edit")[] | undefined; children }`. 권한표(`sd-permission-table`) 입력 단위.
|
|
@@ -1,74 +1,91 @@
|
|
|
1
|
-
# @simplysm/angular — 공유 마스터 데이터
|
|
1
|
+
# @simplysm/angular — 공유 마스터 데이터
|
|
2
2
|
|
|
3
|
-
고객사·품목 등 자주 참조하는 마스터 데이터를 한 번 등록해 어느 화면에서든 공유
|
|
3
|
+
고객사·품목 등 자주 참조하는 마스터 데이터를 한 번 등록해 어느 화면에서든 공유 시그널로 쓰고, 그 데이터를 선택하는 드롭다운/버튼/리스트 컨트롤을 제공하는 군. 등록·항목 추가 절차는 `client-shared-data.md` 참조.
|
|
4
4
|
|
|
5
|
-
## SdSharedDataProvider<T>
|
|
5
|
+
## SdSharedDataProvider<T>
|
|
6
6
|
|
|
7
|
-
마스터 데이터를 이름별로
|
|
7
|
+
마스터 데이터를 이름별로 등록·로드·공유하는 추상 프로바이더. 앱에서 상속해 `initialize()` 안에서 `register`. `@Injectable()`.
|
|
8
8
|
|
|
9
|
-
- `
|
|
10
|
-
- `
|
|
11
|
-
- `
|
|
12
|
-
- `
|
|
13
|
-
- `
|
|
14
|
-
- `
|
|
9
|
+
- `loadingCount: WritableSignal<number>` — 로딩 중 항목 수. 0 보다 크면 로드 진행 중(`sd-base-container` 가 대기).
|
|
10
|
+
- `abstract initialize(): void` — 앱이 override 해 `register` 들을 호출.
|
|
11
|
+
- `register<K>(name, info: SharedDataInfo): void` — 이름으로 데이터 항목 등록. 재호출 시 기존 리스너/세대 갱신(이전 이벤트 무시).
|
|
12
|
+
- `getHandle<K>(name): SharedDataHandle<T[K]>` — 핸들 조회. 최초 조회 시 lazy 로드 + 변경 이벤트 리스너 등록. 미등록 이름이면 throw.
|
|
13
|
+
- `emitAsync<K>(name, changeKeys?): Promise<void>` — 데이터 변경을 다른 클라이언트/탭에 알림(`changeKeys` 지정 시 부분 갱신, 미지정 시 전체 리로드).
|
|
14
|
+
- `wait(): Promise<void>` — `loadingCount <= 0` 까지 대기.
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
`SdSharedDataChangeEvent` — `defineEvent` 로 정의된 공유 데이터 변경 이벤트(서비스 서버 경유 브로드캐스트).
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
- `SharedDataInfo<T>` — 등록 정보. `serviceKey: string`(이벤트 채널), `getter: (changeKeys?) => Promise<T[]>`(조회; changeKeys 주면 부분), `filter?: unknown`(이벤트 필터 매칭), `orderBy?: (item) => string|number|DateOnly|DateTime|Time|undefined`(정렬 키).
|
|
20
|
-
- `SharedDataHandle<T>` — `{ items: Signal<T[]>; get(key): T | undefined }`. 화면이 `useSharedSignal(name)` 으로 받아 `.items()`·`.get(id)` 사용.
|
|
21
|
-
- `SdSharedDataChangeEvent` — 변경 동기화에 쓰이는 `defineEvent`. payload `{ name; filter }`, data `(string|number)[] | undefined`.
|
|
18
|
+
## 타입 (shared-data.provider)
|
|
22
19
|
|
|
23
|
-
|
|
20
|
+
- `SharedDataBase<TKey>` — 모든 공유 항목이 상속할 매직 필드: `__valueKey: TKey`(키), `__searchText: string`(검색 텍스트), `__isHidden: boolean`(숨김 여부), `__parentKey?: TKey`(트리 부모 키).
|
|
21
|
+
- `SharedDataInfo<T>` — `register` 옵션. `serviceKey: string`(연결 키), `getter: (changeKeys?) => Promise<T[]>`(데이터 로더, `changeKeys` 주어지면 그 키만 재조회), `filter?: unknown`(이벤트 필터), `orderBy?: (item) => 정렬키`(정렬).
|
|
22
|
+
- `SharedDataHandle<T>` — `items: Signal<T[]>`(항목 시그널), `get(key): T | undefined`(키로 단건 조회).
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
```ts
|
|
25
|
+
override initialize() {
|
|
26
|
+
this.register("고객사", {
|
|
27
|
+
serviceKey: "MAIN",
|
|
28
|
+
getter: async (changeKeys) => this._appOrm.connectAsync((db) => { /* ... */ }),
|
|
29
|
+
orderBy: (item) => item.code,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
```
|
|
26
33
|
|
|
27
|
-
|
|
34
|
+
## SdSharedDataSelect
|
|
28
35
|
|
|
29
|
-
|
|
36
|
+
공유 데이터를 드롭다운으로 선택하는 컨트롤. selector `sd-shared-data-select`. 검색·트리(`__parentKey`)·관리/선택 모달 지원.
|
|
30
37
|
|
|
31
|
-
|
|
38
|
+
- `value: model<단일|배열>` — 선택된 키(들). `selectMode` 에 따라 단건/배열.
|
|
39
|
+
- `items: input.required<TItem[]>` — 공유 데이터 항목 배열(보통 `sharedX.items()`).
|
|
40
|
+
- `selectMode: "single"|"multi"` — 선택 모드(기본 `"single"`). 다중 선택이면 `"multi"`.
|
|
41
|
+
- `required`/`disabled`/`useUndefined`/`inset`/`inline: boolean` — 필수/비활성/미지정 항목 노출/inset 스타일/인라인.
|
|
42
|
+
- `size: "sm"|"lg"` — 컨트롤 크기.
|
|
43
|
+
- `filterFn: (item, index, ...params) => boolean` + `filterFnParams: any[]` — 표시 항목 필터(추가 파라미터 주입).
|
|
44
|
+
- `modal: SdSelectModalInfo<TModal>` — 관리·선택 모달. 열릴 때 `selectMode`/현재 선택키가 주입되고 닫힘 결과로 선택 갱신.
|
|
45
|
+
- `editModal: SdModalInfo<SdModalContentDef<boolean>>` — 관리 전용 모달(선택을 바꾸지 않음).
|
|
46
|
+
- `getIsHiddenFn`/`getSearchTextFn: (item, index) => ...` — 숨김 판정·검색 텍스트(기본 `__isHidden`/`__searchText`).
|
|
47
|
+
- `displayOrderByFn: (item) => 정렬키` — 표시 정렬.
|
|
48
|
+
- 컨텐츠: `<ng-template [itemOf]="...">` 로 항목 렌더, `#undefinedTpl` 로 미지정 항목 표시.
|
|
32
49
|
|
|
33
|
-
|
|
34
|
-
-
|
|
50
|
+
```html
|
|
51
|
+
<sd-shared-data-select [items]="sharedCustomers.items()" [(value)]="data().customerId" [required]="true">
|
|
52
|
+
<ng-template [itemOf]="sharedCustomers.items()" let-item="item">{{ item.name }}</ng-template>
|
|
53
|
+
</sd-shared-data-select>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## SdSharedDataSelectButton
|
|
57
|
+
|
|
58
|
+
공유 데이터를 모달로만 선택하는 버튼형 컨트롤. selector `sd-shared-data-select-button`.
|
|
59
|
+
|
|
60
|
+
- `value: model<단일|배열>` — 선택 키(들).
|
|
61
|
+
- `items: input<TItem[]>` — 항목 배열.
|
|
62
|
+
- `modal: input.required<SdSelectModalInfo<TModal>>` — 선택 모달(필수).
|
|
35
63
|
- `selectMode: "single"|"multi"` — 선택 모드(기본 single).
|
|
36
|
-
- `required: boolean` —
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
- `
|
|
43
|
-
- `
|
|
44
|
-
- `
|
|
45
|
-
- 항목 템플릿: `<ng-template [itemOf]="items()" let-item="item">`, 미지정 표시 `#undefinedTpl`.
|
|
46
|
-
- 사용: `<sd-shared-data-select [items]="sharedCustomers.items()" [(value)]="data().customerId"><ng-template [itemOf]="sharedCustomers.items()" let-item="item">{{ item.name }}</ng-template></sd-shared-data-select>`.
|
|
47
|
-
|
|
48
|
-
### SdSharedDataSelectButton (`sd-shared-data-select-button`)
|
|
49
|
-
|
|
50
|
-
값 표시 + 모달 검색 버튼(드롭다운 없이 모달 전용). 항목 수가 많아 드롭다운이 부적합할 때.
|
|
51
|
-
|
|
52
|
-
- `value: model<...>` — 선택 키/키배열.
|
|
53
|
-
- `items: TItem[]` — 표시명 매핑용 항목 배열.
|
|
54
|
-
- `modal: input.required<SdSelectModalInfo<TModal>>` — 띄울 선택 모달.
|
|
55
|
-
- `selectMode: "single"|"multi"` / `disabled` / `required` / `inset` / `size` — 공통.
|
|
56
|
-
- 선택 항목 표시 템플릿: `<ng-template [itemOf]>`(필수).
|
|
57
|
-
|
|
58
|
-
### SdSharedDataSelectList (`sd-shared-data-select-list`)
|
|
59
|
-
|
|
60
|
-
검색창 + 리스트로 단건 선택(좌측 마스터 리스트 패널 등). `flex-column fill`.
|
|
61
|
-
|
|
62
|
-
- `selectedItem: model<TItem>` — 선택된 항목(키 아닌 항목 객체). `canChangeFn: (item|undefined) => boolean|Promise<boolean>` — 변경 가드.
|
|
63
|
-
- `items: input.required<TItem[]>` — 항목 배열(`__isHidden` 항목 자동 제외).
|
|
64
|
-
- `useUndefined: boolean` — "미지정" 항목 노출.
|
|
65
|
-
- `filterFn: (item, index) => boolean` — 추가 필터.
|
|
64
|
+
- `disabled`/`required`/`inset: boolean`, `size: "sm"|"lg"` — 상태/크기.
|
|
65
|
+
|
|
66
|
+
## SdSharedDataSelectList
|
|
67
|
+
|
|
68
|
+
좌측 마스터 목록형 선택 컨트롤(항목 객체를 모델로). selector `sd-shared-data-select-list`. 공유데이터+detail 합성 화면의 좌측에 사용.
|
|
69
|
+
|
|
70
|
+
- `selectedItem: model<TItem>` — 선택된 **항목 객체**(키가 아니라 객체).
|
|
71
|
+
- `items: input.required<TItem[]>` — 항목 배열.
|
|
72
|
+
- `canChangeFn: (item) => boolean | Promise<boolean>` — 선택 변경 허용 가드.
|
|
66
73
|
- `selectedIcon: string` — 선택 표시 아이콘.
|
|
67
|
-
- `
|
|
68
|
-
- `
|
|
69
|
-
- `
|
|
70
|
-
-
|
|
74
|
+
- `useUndefined: boolean` — 미지정 항목 노출.
|
|
75
|
+
- `filterFn: (item, index) => boolean` — 표시 필터.
|
|
76
|
+
- `modal: SdSelectModalInfo<TModal>` — 관리·선택 모달(목록 화면 재사용).
|
|
77
|
+
- `header: string` — 목록 헤더 라벨.
|
|
78
|
+
- `pageItemCount: number` — 페이지당 항목 수.
|
|
79
|
+
|
|
80
|
+
```html
|
|
81
|
+
<sd-shared-data-select-list [items]="sharedRoles.items()" [(selectedItem)]="selectedRole"
|
|
82
|
+
[header]="'역할'" [modal]="{ type: RoleList, title: '역할', inputs: {} }">
|
|
83
|
+
<ng-template [itemOf]="sharedRoles.items()" let-item="item">{{ item.name }}</ng-template>
|
|
84
|
+
</sd-shared-data-select-list>
|
|
85
|
+
```
|
|
71
86
|
|
|
72
87
|
## matchesSearchText
|
|
73
88
|
|
|
74
|
-
|
|
89
|
+
공백 분리 AND 검색 일치 판정 유틸(선택 컨트롤이 내부 사용).
|
|
90
|
+
|
|
91
|
+
- `matchesSearchText(itemText: string, searchQuery: string | undefined): boolean` — `searchQuery` 를 공백으로 나눈 모든 단어가(대소문자 무시) `itemText` 에 포함되면 true. 검색어 없으면 항상 true.
|
|
@@ -1,88 +1,79 @@
|
|
|
1
|
-
# @simplysm/angular — 시트
|
|
1
|
+
# @simplysm/angular — 시트(sd-sheet)
|
|
2
2
|
|
|
3
3
|
다건 목록·편집 표(그리드). 컬럼 디렉티브 + 셀 템플릿으로 구성하며, 선택·정렬·페이지·트리펼침·셀 편집·컬럼 고정/리사이즈/설정저장을 내장. `sd-crud-list` 는 이 시트를 감싼 표준 골격(crud.md). 셀 본문·정렬·폭 규약은 client-component.md "시트 컬럼·셀 표준" 을 따름.
|
|
4
4
|
|
|
5
|
-
## SdSheet<TItem>
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
- `
|
|
11
|
-
- `
|
|
12
|
-
- `
|
|
13
|
-
- `
|
|
14
|
-
- `
|
|
15
|
-
- `
|
|
16
|
-
- `
|
|
17
|
-
- `
|
|
18
|
-
- `
|
|
19
|
-
- `
|
|
20
|
-
- `
|
|
21
|
-
- `
|
|
22
|
-
- `
|
|
23
|
-
- `
|
|
24
|
-
- `
|
|
25
|
-
- `
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
- `
|
|
30
|
-
- `
|
|
31
|
-
- `
|
|
32
|
-
- `
|
|
33
|
-
- `
|
|
34
|
-
- `cellKeydown: output<SdSheetCellKeydownEventParam<TItem>>` — 셀에서 키 입력(`{ item; key; event }`. key=컬럼 key).
|
|
35
|
-
|
|
36
|
-
### 컬럼·셀
|
|
37
|
-
|
|
38
|
-
#### SdSheetColumn<T> (`sd-sheet-column`)
|
|
39
|
-
|
|
40
|
-
컬럼 정의 디렉티브. `<sd-sheet>`(또는 `sd-crud-list`) 직속 자식으로 둠.
|
|
41
|
-
|
|
42
|
-
- `key: input.required<string>` — 컬럼 식별 키(설정 저장·셀 키).
|
|
43
|
-
- `header: string | string[]` — 헤더 텍스트(배열이면 다단 헤더로 그룹).
|
|
44
|
-
- `headerStyle: string` — 헤더 셀 스타일.
|
|
45
|
-
- `tooltip: string` — 헤더 도움말(? 표시).
|
|
46
|
-
- `width: string` — 컬럼 폭(미지정=자동). px 지정은 명시 지시 시만(client-component.md).
|
|
47
|
-
- `fixed: boolean` — 좌측 고정 컬럼.
|
|
48
|
-
- `hidden: boolean` — 숨김.
|
|
49
|
-
- `collapse: boolean` — 접힘 컬럼.
|
|
50
|
-
- `disableSorting: boolean` — 헤더 클릭 정렬 비활성.
|
|
51
|
-
- `disableResizing: boolean` — 폭 드래그 리사이즈 비활성.
|
|
52
|
-
- `ordering: number` — 컬럼 정렬 순서.
|
|
53
|
-
- 템플릿: `<ng-template [cell]="items()" let-item="item">`(필수, 셀 본문), `#headerTpl`(헤더 커스텀), `#summaryTpl`(요약 행).
|
|
54
|
-
- `SdSheetCellContext<T> = { $implicit; item: T; index: number; depth: number; edit: boolean }` — 셀 컨텍스트. `let-edit="edit"` 로 편집 모드 여부.
|
|
55
|
-
|
|
56
|
-
#### SdSheetColumnCellTemplate<T> (`ng-template[cell]`)
|
|
5
|
+
## SdSheet<TItem>
|
|
6
|
+
|
|
7
|
+
selector `sd-sheet`. 직속 자식으로 `<sd-sheet-column>` 들을 둠.
|
|
8
|
+
|
|
9
|
+
입력:
|
|
10
|
+
- `key: string` — 컬럼 구성(폭/숨김/순서) 영속화 키. 지정 시 `injectSdSystemConfigResource` 로 저장/복원. 사용자별 컬럼 설정을 유지하려면 지정.
|
|
11
|
+
- `items: TItem[]` — 행 데이터.
|
|
12
|
+
- `trackByFn: (item, index) => unknown` — 행 키 함수(기본은 item 자체). 선택 키·재렌더 추적.
|
|
13
|
+
- `selectMode: "single"|"multi"` — 행 선택 모드. 미지정 시 선택 비활성. 다중 선택 화면이면 `"multi"`.
|
|
14
|
+
- `autoSelect: "click"|"focus"` — 자동 선택 트리거. `"click"` = 클릭 시 선택, `"focus"` = 포커스 이동만으로 선택. 키보드 위주 화면이면 `"focus"`.
|
|
15
|
+
- `getItemSelectableFn: (item) => boolean | string` — 행 선택 가능 여부(문자열 반환 시 불가 사유).
|
|
16
|
+
- `getChildrenFn: (item, index) => TItem[] | undefined` — 자식 행 반환(트리 모드). 값이 있으면 펼침 토글 표시.
|
|
17
|
+
- `useAutoSort: boolean` — 클라이언트 정렬. true 면 `sorts` 변경 시 시트가 `items` 를 직접 정렬. 서버측 정렬/페이징이면 false 로 두고 외부에서 재조회.
|
|
18
|
+
- `visiblePageCount: number` — 페이지네이터가 한 번에 보이는 페이지 번호 수(기본 10).
|
|
19
|
+
- `totalPageCount: number` — 서버 페이징 총 페이지 수(서버 페이징 시 지정, `itemsPerPage` 와 택일).
|
|
20
|
+
- `itemsPerPage: number` — 클라이언트 페이징 시 페이지당 행 수(0 이면 페이징 안 함).
|
|
21
|
+
- `focusMode: "row"|"cell"` — 키보드 포커스 단위(기본 `"cell"`). `"row"` = 행 전체 이동, `"cell"` = 셀 단위 이동. 셀 편집·복사 화면이면 `"cell"`.
|
|
22
|
+
- `inset: boolean` — 테두리/모서리 없는 inset 스타일.
|
|
23
|
+
- `contentStyle: string` — 본문 인라인 스타일.
|
|
24
|
+
- `getItemCellClassFn`/`getItemCellStyleFn: (item, colKey) => ...` — 셀별 클래스/스타일.
|
|
25
|
+
- `hideConfigBar: boolean` — 상단 컬럼 설정 바 숨김.
|
|
26
|
+
|
|
27
|
+
출력/모델:
|
|
28
|
+
- `itemKeydown: output<{ item, event }>` — 행 단위 키다운.
|
|
29
|
+
- `cellKeydown: output<{ item, key, event }>` — 셀 단위 키다운(`key` 는 컬럼 키).
|
|
30
|
+
- `selectedKeys: model<unknown[]>` — 선택된 행 키 배열(`trackByFn` 결과).
|
|
31
|
+
- `expandedItems: model<TItem[]>` — 펼쳐진 트리 행.
|
|
32
|
+
- `sorts: model<SortingDef[]>` — 정렬 상태(`{ key, desc }[]`).
|
|
33
|
+
- `currentPage: model<number>` — 현재 페이지(0 기반).
|
|
57
34
|
|
|
58
|
-
셀 본문 템플릿 디렉티브. `cell: input.required<T[]>` 는 타입 추론용 더미(실제 데이터는 시트 `items`). `let-item`/`let-index`/`let-depth`/`let-edit` 컨텍스트 제공.
|
|
59
|
-
|
|
60
|
-
사용:
|
|
61
35
|
```html
|
|
62
|
-
<sd-sheet [items]="items()" [(selectedKeys)]="selectedKeys" selectMode="single"
|
|
36
|
+
<sd-sheet [items]="items()" [(selectedKeys)]="selectedKeys" selectMode="single"
|
|
37
|
+
[trackByFn]="trackByFn" [(currentPage)]="page" [totalPageCount]="pageLength()">
|
|
63
38
|
<sd-sheet-column [key]="'name'" [header]="'이름'">
|
|
64
|
-
<ng-template [cell]="items()" let-item="item">
|
|
65
|
-
<div class="p-xs-sm">{{ item.name }}</div>
|
|
66
|
-
</ng-template>
|
|
39
|
+
<ng-template [cell]="items()" let-item="item"><div class="p-xs-sm">{{ item.name }}</div></ng-template>
|
|
67
40
|
</sd-sheet-column>
|
|
68
41
|
</sd-sheet>
|
|
69
42
|
```
|
|
70
43
|
|
|
71
|
-
|
|
44
|
+
## SdSheetColumn<T>
|
|
45
|
+
|
|
46
|
+
`sd-sheet-column` 디렉티브. 컬럼 1개를 정의.
|
|
47
|
+
|
|
48
|
+
- `key: input.required<string>` — 컬럼 식별 키(정렬·셀 키다운·구성 저장 단위).
|
|
49
|
+
- `header: string | string[]` — 헤더 텍스트. 배열이면 다단(그룹) 헤더.
|
|
50
|
+
- `headerStyle: string` — 헤더 셀 인라인 스타일.
|
|
51
|
+
- `tooltip: string` — 헤더 툴팁.
|
|
52
|
+
- `width: string` — 컬럼 폭(미지정이 기본=자동). px 지정은 명시 지시 시에만.
|
|
53
|
+
- `fixed: boolean` — 좌측 고정 컬럼.
|
|
54
|
+
- `hidden: boolean` — 숨김.
|
|
55
|
+
- `collapse: boolean` — 접힘(헤더만, 폭 최소).
|
|
56
|
+
- `disableSorting: boolean` — 정렬 비활성.
|
|
57
|
+
- `disableResizing: boolean` — 폭 리사이즈 비활성.
|
|
58
|
+
- `ordering: number` — 컬럼 표시 순서.
|
|
59
|
+
- 컨텐츠: `<ng-template [cell]="items()" let-item="item">`(셀 본문), `#headerTpl`(커스텀 헤더), `#summaryTpl`(요약 행).
|
|
60
|
+
|
|
61
|
+
셀 컨텍스트(`SdSheetCellContext`): `$implicit`/`item`/`index`/`depth`(트리 깊이)/`edit`(편집 모드 여부).
|
|
62
|
+
|
|
63
|
+
## SdSheetColumnCellTemplate<T>
|
|
72
64
|
|
|
73
|
-
|
|
65
|
+
`ng-template[cell]` 디렉티브. 셀 본문 템플릿에 타입 가드를 부여.
|
|
74
66
|
|
|
75
|
-
- `
|
|
76
|
-
- `close: output<SdSheetConfig | undefined>` — 변경된 설정(취소 시 undefined).
|
|
67
|
+
- `cell: input.required<T[]>` — 타입 추론용 더미(보통 `items()` 전달). 실제 데이터는 `<sd-sheet>` 의 `items` 가 보유.
|
|
77
68
|
|
|
78
|
-
|
|
69
|
+
## SdSheetConfigModal
|
|
79
70
|
|
|
80
|
-
|
|
81
|
-
- `SdSheetHeaderDef` — 헤더 셀 렌더 정의(`text/colspan/rowspan/isLastRow/fixed/colDef/colIndex`).
|
|
82
|
-
- `SdSheetConfig = { columnRecord: Record<string, { width?; hidden?; fixed?; ordering? }> }` — 영속되는 시트 설정.
|
|
83
|
-
- `SdSheetItemKeydownEventParam<T> = { item: T; event: KeyboardEvent }`.
|
|
84
|
-
- `SdSheetCellKeydownEventParam<T> = { item: T; key: string; event: KeyboardEvent }`.
|
|
71
|
+
컬럼 폭/숨김/고정/순서를 사용자에게 편집시키는 모달(`SdModalContentDef<SdSheetConfig>`). 시트 설정 바에서 자동 호출되므로 직접 띄울 일은 드묾.
|
|
85
72
|
|
|
86
|
-
|
|
73
|
+
## 타입 (types)
|
|
87
74
|
|
|
88
|
-
|
|
75
|
+
- `SdSheetColumnDef` — 컬럼 해석 결과(`key`/`header`/`width`/`fixed`/`hidden`/`collapse`/`disableSorting`/`disableResizing`/`ordering` 등).
|
|
76
|
+
- `SdSheetHeaderDef` — 다단 헤더 셀 정의(`text`/`colspan`/`rowspan`/`isLastRow`/`fixed`/`colDef`/`colIndex`).
|
|
77
|
+
- `SdSheetConfig` — 영속화되는 컬럼별 사용자 설정(`columnRecord[key] = { width?, hidden?, fixed?, ordering? }`).
|
|
78
|
+
- `SdSheetItemKeydownEventParam<T>` — `{ item, event }`(행 키다운 페이로드).
|
|
79
|
+
- `SdSheetCellKeydownEventParam<T>` — `{ item, key, event }`(셀 키다운 페이로드).
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
# @simplysm/capacitor-plugin-auto-update
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Android APK 자동 업데이트 Capacitor 플러그인. 부팅 시 서버 또는 외부 저장소의 최신 APK 를 받아 설치하는 오케스트레이터(`AutoUpdate`)와, APK 설치·설치 권한·앱 버전 조회를 다루는 저수준 정적 클래스(`ApkInstaller`)·타입을 제공. 공개 심볼은 모두 `static` 멤버만 가진 abstract 클래스이거나 인터페이스라 인스턴스 없이 클래스명으로 직접 호출. 비-Android(웹)에서는 폴백 구현으로 설치는 no-op, 권한은 항상 통과.
|
|
4
4
|
|
|
5
5
|
## 사용 트리거 인덱스
|
|
6
6
|
|
|
7
|
-
- **AutoUpdate** — 앱 부팅
|
|
8
|
-
- **ApkInstaller** —
|
|
9
|
-
- **ApkInstallerPlugin / VersionInfo** — Capacitor 네이티브 브리지
|
|
7
|
+
- **AutoUpdate** — 앱 부팅 시점에 "최신 확인 → 권한 → 다운로드 → 설치 → 앱 멈춤" 까지 한 번에 도는 진입점. 서버(`ServiceClient`) 연동 업데이트면 `run`, USB/외장 저장소 폴더에서 가져오면 `runByExternalStorage`.
|
|
8
|
+
- **ApkInstaller** — `AutoUpdate` 를 거치지 않고 설치 권한 확인/요청, 특정 APK 설치, 현재 앱 버전 직접 조회가 필요할 때 쓰는 저수준 정적 클래스.
|
|
9
|
+
- **ApkInstallerPlugin / VersionInfo** — Capacitor 네이티브 브리지 인터페이스와 버전 정보 형태. `ApkInstaller` 가 감싸므로 직접 호출보다는 반환 타입 참조용.
|
|
10
10
|
|
|
11
11
|
## AutoUpdate
|
|
12
12
|
|
|
13
|
-
`abstract class AutoUpdate` — 정적 메서드만 가진
|
|
13
|
+
`abstract class AutoUpdate` — 정적 메서드만 가진 부트 시 업데이트 오케스트레이터. 두 진입점 모두 Android 여부 확인 → 설치 권한 확인/요청 → 버전 비교 → 다운로드/설치 → 무한 freeze 순으로 일괄 처리. 진행 단계는 `log` 콜백으로 HTML 문자열을 흘려보내고, 도중 발생한 모든 예외를 잡아 `log` 로 오류 메시지를 표시한 뒤 영원히 resolve 되지 않는 무한 대기로 진입해 구버전 실행을 막음.
|
|
14
14
|
|
|
15
15
|
```typescript
|
|
16
16
|
static run(opt: { log: (messageHtml: string) => void; serviceClient: ServiceClient }): Promise<void>
|
|
17
17
|
static runByExternalStorage(opt: { log: (messageHtml: string) => void; dirPath: string }): Promise<void>
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
- log: (messageHtml: string) => void — 진행/오류 상태를 HTML 문자열로 받는 콜백. 매 단계마다 여러 번 호출되며 `"최신 버전 확인 중..."`, `"권한 확인 중..."`, 다운로드 진행률 `(NN.NN%)`, 권한 활성화·재시도 버튼 HTML, 오류 메시지 등이 인자로 들어옴. 부팅 스플래시 등에 그대로 `innerHTML` 로 렌더하는
|
|
21
|
-
- serviceClient: ServiceClient (`run` 전용) — `@simplysm/service-client` 의 서비스 클라이언트. 내부에서 `getService<AutoUpdateService>("AutoUpdate").getLastVersion("android")` 로 최신 버전·다운로드 경로를
|
|
22
|
-
- dirPath: string (`runByExternalStorage` 전용) —
|
|
20
|
+
- opt.log: (messageHtml: string) => void — 진행/오류 상태를 HTML 문자열로 받는 콜백. 매 단계마다 여러 번 호출되며 `"최신 버전 확인 중..."`, `"권한 확인 중..."`, 다운로드 진행률 `(NN.NN%)`, 권한 활성화·재시도 버튼 HTML, 오류 메시지 등이 인자로 들어옴. 부팅 스플래시 등에 그대로 `innerHTML` 로 렌더하는 용도 — 재시도/다운로드 버튼이 HTML 이므로 텍스트가 아닌 HTML 로 렌더해야 동작.
|
|
21
|
+
- opt.serviceClient: ServiceClient (`run` 전용) — `@simplysm/service-client` 의 서비스 클라이언트. 내부에서 `getService<AutoUpdateService>("AutoUpdate").getLastVersion("android")` 로 최신 버전·다운로드 경로를 조회하고 `serviceClient.hostUrl + downloadPath` 로 `fetchUrlBytes` 다운로드. 서버 연동 배포일 때 사용.
|
|
22
|
+
- opt.dirPath: string (`runByExternalStorage` 전용) — `external` 저장소(`FileSystem.getStoragePath("external")`) 루트 기준 상대 디렉토리 경로. 이 폴더의 비-디렉토리 항목 중 확장자가 `.apk` 이고 파일명(확장자 제외)이 `^[0-9.]*$`(숫자·점) 인 것을 버전으로 보고 `semver.maxSatisfying(..., "*")` 로 최신을 선정. 서버 없이 USB/SD 등으로 사이드로딩 배포할 때 사용.
|
|
23
23
|
|
|
24
|
-
동작 차이: `run` 은 다운로드한 바이트를 `appCache` 저장소의 `latest.apk` 로 써서 설치하고, `runByExternalStorage` 는 외부 저장소의 `<dirPath>/<version>.apk` 를 직접 설치 대상으로
|
|
24
|
+
동작 차이: `run` 은 다운로드한 바이트를 `appCache` 저장소의 `latest.apk` 로 써서 설치하고, `runByExternalStorage` 는 외부 저장소의 `<dirPath>/<version>.apk` 를 직접 설치 대상으로 삼음. 두 경로 모두 현재 버전(`ApkInstaller.getVersionInfo().versionName`)과 비교해 `semver.gt(최신, 현재)` 가 아니면(이미 최신·동일·낮음) 반환하고, 어느 한쪽이라도 유효한 semver 가 아니면 업데이트 확인을 건너뜀.
|
|
25
25
|
|
|
26
26
|
```typescript
|
|
27
27
|
// 앱 부트스트랩에서 (서버 기반)
|
|
@@ -30,11 +30,16 @@ await AutoUpdate.run({ log: (h) => (statusEl.innerHTML = h), serviceClient });
|
|
|
30
30
|
await AutoUpdate.runByExternalStorage({ log: (h) => (statusEl.innerHTML = h), dirPath: "myapp-apks" });
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
주의사항:
|
|
34
|
+
|
|
35
|
+
- 업데이트가 없거나 이미 최신이면 그냥 반환(freeze 안 함)하므로 후속 정상 부트로 이어가면 됨. 반대로 설치를 진행하거나 오류가 나면 무한 대기로 들어가 영원히 resolve 되지 않으니 호출 후속 코드에 의존하지 말 것 — 후속 코드는 "업데이트 없음" 경로에서만 실행됨.
|
|
36
|
+
- Android 외 환경(`navigator.userAgent` 에 "android" 없음)이면 `"Android만 지원됩니다."` throw → catch 에서 표시 후 freeze.
|
|
37
|
+
- 권한 미승인 시 설정 화면으로 보낸 뒤 최대 5분(1초 간격 300회) 동안 권한 부여를 폴링 대기.
|
|
38
|
+
- manifest 에 `REQUEST_INSTALL_PACKAGES` 가 없거나(`manifest:false`) 권한 확인 자체가 실패하면 "APK 파일을 다시 다운로드하여 설치해야 합니다(코드)." 안내(코드 1·2, `run` 은 다운로드 링크 버튼 포함)와 함께 throw.
|
|
34
39
|
|
|
35
40
|
## ApkInstaller
|
|
36
41
|
|
|
37
|
-
`abstract class ApkInstaller` — APK 설치 관련 네이티브 호출을 감싼 저수준 정적 클래스. Android 는 실제 인텐트/권한을 다루고, 브라우저(web)는
|
|
42
|
+
`abstract class ApkInstaller` — APK 설치 관련 네이티브 호출을 감싼 저수준 정적 클래스. Android 는 실제 인텐트/권한을 다루고, 브라우저(web)는 폴백 구현(설치 시 미지원 alert 후 정상 반환, 권한은 항상 `granted:true`/`manifest:true`, 버전은 `__VER__` env 또는 `0.0.0`). `AutoUpdate` 가 내부에서 쓰며, 자동 업데이트 UX 를 직접 구성하거나 권한·설치만 단독으로 다룰 때 직접 호출.
|
|
38
43
|
|
|
39
44
|
```typescript
|
|
40
45
|
static checkPermissions(): Promise<{ granted: boolean; manifest: boolean }>
|
|
@@ -43,10 +48,10 @@ static install(apkUri: string): Promise<void>
|
|
|
43
48
|
static getVersionInfo(): Promise<VersionInfo>
|
|
44
49
|
```
|
|
45
50
|
|
|
46
|
-
- checkPermissions()
|
|
47
|
-
- requestPermissions()
|
|
48
|
-
- install(apkUri: string)
|
|
49
|
-
- getVersionInfo()
|
|
51
|
+
- checkPermissions(): Promise<{ granted: boolean; manifest: boolean }> — 설치 권한 상태 조회. `granted` = `REQUEST_INSTALL_PACKAGES` 권한이 사용자에게 승인되었는지(false 면 `requestPermissions` 로 유도), `manifest` = 해당 권한이 앱 manifest 에 선언되어 있는지(false 면 권한 요청 자체가 불가 → APK 재설치 필요). 설치 전 사전 점검·재시도 폴링에 사용. 웹에서는 둘 다 true.
|
|
52
|
+
- requestPermissions(): Promise<void> — 설치 권한 요청. Android 에서는 시스템 설정 화면으로 이동시키며 즉시 부여되지 않으므로 이후 `checkPermissions` 폴링으로 승인 여부를 확인해야 함. 웹에서는 동작 없음.
|
|
53
|
+
- install(apkUri: string): Promise<void> — APK 설치 인텐트 실행. `apkUri` 는 로컬 파일 경로가 아니라 `content://` FileProvider URI (보통 `@simplysm/capacitor-plugin-file-system` 의 `FileSystem.getUri(파일경로)` 결과). 내부에서 `{ uri: apkUri }` 로 래핑해 플러그인에 전달. 웹에서는 미지원 alert 후 반환.
|
|
54
|
+
- getVersionInfo(): Promise<VersionInfo> — 현재 설치된 앱 버전 조회. 서버/외부 버전과 비교할 현재 버전 기준값. 웹 구현은 `versionName` 을 빌드 시 주입된 `env("__VER__")`(없으면 `"0.0.0"`), `versionCode` 를 `"0"` 으로 응답.
|
|
50
55
|
|
|
51
56
|
```typescript
|
|
52
57
|
const { granted, manifest } = await ApkInstaller.checkPermissions();
|
|
@@ -57,7 +62,7 @@ await ApkInstaller.install(await FileSystem.getUri(apkFilePath));
|
|
|
57
62
|
|
|
58
63
|
## ApkInstallerPlugin / VersionInfo
|
|
59
64
|
|
|
60
|
-
Capacitor `registerPlugin("ApkInstaller")` 로 등록되는 네이티브 브리지 인터페이스와 버전 정보 타입. `ApkInstaller` 의 정적 메서드가 이 인터페이스 구현체(네이티브 또는
|
|
65
|
+
Capacitor `registerPlugin("ApkInstaller")` 로 등록되는 네이티브 브리지 인터페이스와 버전 정보 타입. `ApkInstaller` 의 정적 메서드가 이 인터페이스 구현체(네이티브 또는 웹 폴백)에 위임하므로, 직접 구현·호출할 일은 드물고 주로 `getVersionInfo` 반환 형태 참조·웹 구현체 작성 시 본다.
|
|
61
66
|
|
|
62
67
|
```typescript
|
|
63
68
|
interface VersionInfo {
|
|
@@ -75,5 +80,5 @@ interface ApkInstallerPlugin {
|
|
|
75
80
|
|
|
76
81
|
- VersionInfo.versionName: string — 사람이 읽는 표시 버전(semver, 예 `"1.2.3"`). `AutoUpdate` 의 버전 비교(`semver.gt`/`semver.valid`)는 이 값을 semver 로 사용.
|
|
77
82
|
- VersionInfo.versionCode: string — Android 빌드 버전 코드의 문자열 표현. 웹 구현에서는 `"0"` 고정. 현재 업데이트 판정 로직은 `versionName` 만 사용하며 이 값은 표시·식별용.
|
|
78
|
-
- ApkInstallerPlugin.install(options: { uri: string }) — content URI APK
|
|
79
|
-
- ApkInstallerPlugin.checkPermissions / requestPermissions / getVersionInfo — 각각 `ApkInstaller` 의 동명 정적 메서드가 그대로 위임하는 원본 브리지 메서드(권한 조회 / 권한 요청 / 현재 버전 조회).
|
|
83
|
+
- ApkInstallerPlugin.install(options: { uri: string }): Promise<void> — content URI APK 설치(네이티브 측 진입점). `ApkInstaller.install(apkUri)` 가 `{ uri: apkUri }` 로 래핑해 호출하며 uri 는 `content://` FileProvider URI.
|
|
84
|
+
- ApkInstallerPlugin.checkPermissions / requestPermissions / getVersionInfo — 각각 `ApkInstaller` 의 동명 정적 메서드가 그대로 위임하는 원본 브리지 메서드(권한 조회 / 권한 요청 / 현재 버전 조회). 의미는 위 `ApkInstaller` 항목과 동일.
|