@simplysm/sd-claude 14.0.65 → 14.0.66
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-requirement-source-handling.md +64 -0
- package/claude/references/sd-simplysm14/README.md +44 -40
- package/claude/references/sd-simplysm14/apis/angular/README.md +95 -0
- package/claude/references/sd-simplysm14/apis/angular/app-structure.md +49 -0
- package/claude/references/sd-simplysm14/apis/angular/buttons.md +42 -0
- package/claude/references/sd-simplysm14/apis/angular/crud.md +35 -0
- package/claude/references/sd-simplysm14/apis/angular/forms.md +63 -0
- package/claude/references/sd-simplysm14/apis/angular/infrastructure.md +80 -0
- package/claude/references/sd-simplysm14/apis/angular/kanban.md +33 -0
- package/claude/references/sd-simplysm14/apis/angular/layout.md +41 -0
- package/claude/references/sd-simplysm14/apis/angular/modal.md +63 -0
- package/claude/references/sd-simplysm14/apis/angular/routing.md +45 -0
- package/claude/references/sd-simplysm14/apis/angular/select-dropdown.md +35 -0
- package/claude/references/sd-simplysm14/apis/angular/selection-managers.md +50 -0
- package/claude/references/sd-simplysm14/apis/angular/shared-data.md +42 -0
- package/claude/references/sd-simplysm14/apis/angular/sheet.md +52 -0
- package/claude/references/sd-simplysm14/apis/angular/toast.md +46 -0
- package/claude/references/sd-simplysm14/apis/angular/visual.md +41 -0
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +76 -0
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +83 -0
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +80 -0
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +39 -0
- package/claude/references/sd-simplysm14/apis/core-browser/README.md +112 -0
- package/claude/references/sd-simplysm14/apis/core-common/README.md +53 -0
- package/claude/references/sd-simplysm14/apis/core-common/extensions.md +123 -0
- package/claude/references/sd-simplysm14/apis/core-common/features.md +46 -0
- package/claude/references/sd-simplysm14/apis/core-common/types.md +114 -0
- package/claude/references/sd-simplysm14/apis/core-common/utils.md +158 -0
- package/claude/references/sd-simplysm14/apis/core-node/README.md +12 -0
- package/claude/references/sd-simplysm14/apis/core-node/consola.md +64 -0
- package/claude/references/sd-simplysm14/apis/core-node/cpx.md +52 -0
- package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +53 -0
- package/claude/references/sd-simplysm14/apis/core-node/fsx.md +81 -0
- package/claude/references/sd-simplysm14/apis/core-node/pathx.md +55 -0
- package/claude/references/sd-simplysm14/apis/core-node/worker.md +111 -0
- package/claude/references/sd-simplysm14/apis/excel/README.md +81 -0
- package/claude/references/sd-simplysm14/apis/lint/README.md +80 -0
- package/claude/references/sd-simplysm14/apis/orm-common/README.md +33 -0
- package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +77 -0
- package/claude/references/sd-simplysm14/apis/orm-common/executable.md +20 -0
- package/claude/references/sd-simplysm14/apis/orm-common/expr.md +92 -0
- package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +98 -0
- package/claude/references/sd-simplysm14/apis/orm-common/schema-builders.md +128 -0
- package/claude/references/sd-simplysm14/apis/orm-node/README.md +59 -0
- package/claude/references/sd-simplysm14/apis/sd-claude/README.md +9 -0
- package/claude/references/sd-simplysm14/apis/sd-cli/README.md +50 -0
- package/claude/references/sd-simplysm14/apis/sd-cli/sd-config.md +155 -0
- package/claude/references/sd-simplysm14/apis/service-client/README.md +92 -0
- package/claude/references/sd-simplysm14/apis/service-common/README.md +29 -0
- package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +63 -0
- package/claude/references/sd-simplysm14/apis/service-common/messages.md +56 -0
- package/claude/references/sd-simplysm14/apis/service-common/protocol.md +64 -0
- package/claude/references/sd-simplysm14/apis/service-common/service-types.md +43 -0
- package/claude/references/sd-simplysm14/apis/service-server/README.md +20 -0
- package/claude/references/sd-simplysm14/apis/service-server/auth.md +31 -0
- package/claude/references/sd-simplysm14/apis/service-server/builtin-services.md +47 -0
- package/claude/references/sd-simplysm14/apis/service-server/define-service.md +71 -0
- package/claude/references/sd-simplysm14/apis/service-server/internals.md +41 -0
- package/claude/references/sd-simplysm14/apis/service-server/server.md +66 -0
- package/claude/references/sd-simplysm14/apis/storage/README.md +69 -0
- package/claude/references/sd-simplysm14/{client-component.md → manuals/client-component.md} +133 -128
- package/claude/references/sd-simplysm14/manuals/client-crud.md +102 -0
- package/claude/references/sd-simplysm14/manuals/client-demo.md +128 -0
- package/claude/references/sd-simplysm14/manuals/client-rules.md +7 -0
- package/claude/references/sd-simplysm14/{client-setup.md → manuals/client-setup.md} +2 -2
- package/claude/references/sd-simplysm14/{client-tab.md → manuals/client-tab.md} +13 -11
- package/claude/references/sd-simplysm14/{orm-union.md → manuals/orm-union.md} +1 -1
- package/claude/references/sd-simplysm14/manuals/orm.md +75 -0
- package/claude/rules/sd-base-rules.md +172 -79
- package/claude/sd-check-bash.py +5 -0
- package/claude/sd-statusline.py +7 -12
- package/claude/skills/sd-commit/SKILL.md +7 -3
- package/claude/skills/sd-demo/SKILL.md +81 -62
- package/claude/skills/sd-demo/evals/fixtures/empty/.specs/260513120000_warehouse/spec.md +45 -0
- package/claude/skills/sd-demo/evals/fixtures/with-existing-screen/.specs/260513120000_warehouse/spec.md +42 -0
- package/claude/skills/sd-demo/evals/fixtures/with-existing-screen/packages/app/src/screens/dashboard/dashboard.view.ts +33 -0
- package/claude/skills/sd-demo/evals/fixtures/with-master-screen/.specs/260513120000_warehouse/spec.md +45 -0
- package/claude/skills/sd-demo/evals/fixtures/with-master-screen/packages/app/src/screens/dashboard/dashboard.view.ts +33 -0
- package/claude/skills/sd-demo/evals/fixtures/with-modal/.specs/260513120000_warehouse/spec.md +75 -0
- package/claude/skills/sd-demo/evals/fixtures/with-modal/packages/app/src/screens/dashboard/dashboard.view.ts +33 -0
- package/claude/skills/sd-demo/evals/fixtures/with-screens/.specs/260513120000_warehouse/spec.md +45 -0
- package/claude/skills/sd-demo/evals/fixtures/with-screens/packages/app/src/screens/dashboard/dashboard.view.ts +33 -0
- package/claude/skills/sd-demo/evals/golden.jsonl +5 -3
- package/claude/skills/sd-dev/SKILL.md +33 -63
- package/claude/skills/sd-dev/evals/fixtures/case-add/package.json +13 -0
- package/claude/skills/sd-dev/evals/fixtures/case-add/src/index.ts +10 -0
- package/claude/skills/sd-dev/evals/fixtures/case-add/tests/index.test.ts +11 -0
- package/claude/skills/sd-dev/evals/fixtures/case-add/tsconfig.json +12 -0
- package/claude/skills/sd-dev/evals/fixtures/case-bug/package.json +13 -0
- package/claude/skills/sd-dev/evals/fixtures/case-bug/src/index.ts +10 -0
- package/claude/skills/sd-dev/evals/fixtures/case-bug/tests/index.test.ts +11 -0
- package/claude/skills/sd-dev/evals/fixtures/case-bug/tsconfig.json +12 -0
- package/claude/skills/sd-dev/evals/fixtures/case-modify/package.json +13 -0
- package/claude/skills/sd-dev/evals/fixtures/case-modify/src/index.ts +10 -0
- package/claude/skills/sd-dev/evals/fixtures/case-modify/tests/index.test.ts +11 -0
- package/claude/skills/sd-dev/evals/fixtures/case-modify/tsconfig.json +12 -0
- package/claude/skills/sd-dev/evals/golden.jsonl +3 -3
- package/claude/skills/sd-docs/SKILL.md +53 -0
- package/claude/skills/sd-docs/evals/fixtures/new-write/.claude/references/sd-simplysm14/README.md +7 -0
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/package.json +5 -0
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/bar/src/index.ts +3 -0
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/package.json +6 -0
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/baz/src/index.ts +1 -0
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/package.json +5 -0
- package/claude/skills/sd-docs/evals/fixtures/new-write/packages/foo/src/index.ts +8 -0
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/README.md +7 -0
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/.claude/references/sd-simplysm14/apis/foo/README.md +3 -0
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/package.json +5 -0
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/bar/src/index.ts +3 -0
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/package.json +6 -0
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/baz/src/index.ts +1 -0
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/package.json +5 -0
- package/claude/skills/sd-docs/evals/fixtures/update-mixed/packages/foo/src/index.ts +8 -0
- package/claude/skills/sd-docs/evals/golden.jsonl +2 -0
- package/claude/skills/sd-docs/references/subagent-prompt.md +100 -0
- package/claude/skills/sd-impl/SKILL.md +125 -46
- package/claude/skills/sd-impl/evals/fixtures/case-new/.specs/260514120000_/352/261/260/353/236/230/354/262/230/spec.md +101 -0
- package/claude/skills/sd-impl/evals/fixtures/case-update/.specs/260514120000_/352/261/260/353/236/230/354/262/230/spec.md +101 -0
- package/claude/skills/sd-impl/evals/fixtures/case-update/src//352/261/260/353/236/230/354/262/230//352/261/260/353/236/230/354/262/230-/353/252/250/353/215/270.txt +1 -0
- package/claude/skills/sd-impl/evals/fixtures/case-update/src//352/261/260/353/236/230/354/262/230//352/261/260/353/236/230/354/262/230-/353/252/251/353/241/235.txt +1 -0
- package/claude/skills/sd-impl/evals/golden.jsonl +2 -3
- package/claude/skills/sd-skill/SKILL.md +3 -3
- package/claude/skills/sd-skill/evals/golden.jsonl +0 -1
- package/claude/skills/sd-skill/references/eval-authoring.md +15 -0
- package/claude/skills/sd-skill/references/eval-run.md +1 -1
- package/claude/skills/sd-skill/references/skill-authoring.md +8 -5
- package/claude/skills/sd-skill/scripts/run_eval.py +39 -60
- package/claude/skills/sd-spec/SKILL.md +163 -105
- package/claude/skills/sd-spec/references/example-spec.md +585 -0
- package/claude/skills/sd-spec/references/spec-authoring.md +287 -0
- package/claude/skills/sd-spec/references/spec-md-template.md +15 -93
- package/claude/skills/sd-unpack/SKILL.md +7 -1
- package/claude/skills/sd-unpack/scripts/handlers/_common.py +10 -0
- package/claude/skills/sd-unpack/scripts/handlers/eml_handler.py +5 -13
- package/claude/skills/sd-unpack/scripts/handlers/msg_handler.py +3 -12
- package/claude/skills/sd-unpack/scripts/handlers/office_com.py +23 -37
- package/claude/skills/sd-unpack/scripts/handlers/office_worker.py +1 -4
- package/claude/skills/sd-unpack/scripts/handlers/pdf_handler.py +4 -13
- package/claude/skills/sd-unpack/scripts/unpack.py +4 -4
- package/claude/skills/sd-use/SKILL.md +1 -0
- package/claude/skills/sd-wip/SKILL.md +38 -0
- package/claude/skills/sd-wip/evals/fixtures/with-artifact/projects/acct/_wip.md +3 -0
- package/claude/skills/sd-wip/evals/fixtures/with-artifact/projects/acct/spec.md +15 -0
- package/claude/skills/sd-wip/evals/fixtures/with-existing-wip/.wips/260101120000_acct.md +6 -0
- package/claude/skills/sd-wip/evals/fixtures/with-existing-wip-for-compact/.wips/260101120000_acct.md +14 -0
- package/claude/skills/sd-wip/evals/golden.jsonl +4 -0
- package/claude/skills/sd-wip/references/compact.md +79 -0
- package/package.json +1 -1
- package/claude/references/sd-simplysm14/orm.md +0 -11
- package/claude/skills/sd-demo/evals/fixtures/basic-single-req/.specs/260503143025/REQ-001-/354/236/205/352/263/240/354/247/200/354/213/234/354/204/234/352/270/264/352/270/211/355/221/234/354/213/234/spec.md +0 -27
- package/claude/skills/sd-demo/evals/fixtures/basic-single-req/.specs/260503143025/overview.md +0 -12
- package/claude/skills/sd-demo/evals/fixtures/basic-single-req/src/components/Button.tsx +0 -12
- package/claude/skills/sd-demo/evals/fixtures/basic-single-req/src/components/Input.tsx +0 -27
- package/claude/skills/sd-demo/evals/fixtures/mock-data-policy/.specs/260503143025/REQ-001-/352/261/260/353/236/230/354/262/230/353/252/251/353/241/235/355/231/224/353/251/264/spec.md +0 -25
- package/claude/skills/sd-demo/evals/fixtures/mock-data-policy/.specs/260503143025/overview.md +0 -12
- package/claude/skills/sd-demo/evals/fixtures/mock-data-policy/src/components/Input.tsx +0 -25
- package/claude/skills/sd-demo/evals/fixtures/mock-data-policy/src/pages/.gitkeep +0 -0
- package/claude/skills/sd-demo/evals/fixtures/multi-req-domain/.specs/260503143025/REQ-001-RTP/354/236/205/353/240/245/355/231/224/353/251/264/spec.md +0 -19
- package/claude/skills/sd-demo/evals/fixtures/multi-req-domain/.specs/260503143025/REQ-002-RTP/354/266/234/353/240/245/355/231/224/353/251/264/spec.md +0 -20
- package/claude/skills/sd-demo/evals/fixtures/multi-req-domain/.specs/260503143025/overview.md +0 -16
- package/claude/skills/sd-demo/evals/fixtures/multi-req-domain/src/components/Button.tsx +0 -6
- package/claude/skills/sd-demo/evals/fixtures/multi-req-domain/src/components/Input.tsx +0 -15
- package/claude/skills/sd-demo/evals/fixtures/multi-req-domain/src/pages/.gitkeep +0 -0
- package/claude/skills/sd-demo/references/demo-md-template.md +0 -92
- package/claude/skills/sd-dev/evals/fixtures/multi-req-stop-after-spec/.docs/20260301_/352/263/240/352/260/235/354/202/254_/354/236/205/352/263/240/354/232/224/354/262/255.eml +0 -5
- package/claude/skills/sd-dev/evals/fixtures/multi-req-stop-after-spec/.docs/20260305_/352/263/240/352/260/235/354/202/254_/354/266/234/352/263/240/354/232/224/354/262/255.eml +0 -6
- package/claude/skills/sd-dev/evals/fixtures/multi-req-stop-after-spec/.docs/20260310_/352/263/240/352/260/235/354/202/254_/352/266/214/355/225/234.eml +0 -6
- package/claude/skills/sd-dev/evals/fixtures/single-req-auto-chain/src/lib/.gitkeep +0 -0
- package/claude/skills/sd-dev/evals/fixtures/start-from-plan/.specs/260503143025/REQ-001-/355/225/240/354/235/270/352/263/204/354/202/260/spec.md +0 -12
- package/claude/skills/sd-dev/evals/fixtures/start-from-plan/src/lib/.gitkeep +0 -0
- package/claude/skills/sd-impl/evals/fixtures/basic-single-r/.specs/260503143025/REQ-001-/354/236/205/352/263/240/354/247/200/354/213/234/354/204/234/352/270/264/352/270/211/355/221/234/354/213/234/plan.md +0 -28
- package/claude/skills/sd-impl/evals/fixtures/basic-single-r/.specs/260503143025/REQ-001-/354/236/205/352/263/240/354/247/200/354/213/234/354/204/234/352/270/264/352/270/211/355/221/234/354/213/234/spec.md +0 -14
- package/claude/skills/sd-impl/evals/fixtures/basic-single-r/src/components/Input.tsx +0 -6
- package/claude/skills/sd-impl/evals/fixtures/basic-single-r/src/pages/.gitkeep +0 -0
- package/claude/skills/sd-impl/evals/fixtures/multi-r/.specs/260503143025/REQ-001-/352/261/260/353/236/230/354/262/230/353/252/251/353/241/235/plan.md +0 -40
- package/claude/skills/sd-impl/evals/fixtures/multi-r/.specs/260503143025/REQ-001-/352/261/260/353/236/230/354/262/230/353/252/251/353/241/235/spec.md +0 -13
- package/claude/skills/sd-impl/evals/fixtures/multi-r/src/components/Input.tsx +0 -25
- package/claude/skills/sd-impl/evals/fixtures/multi-r/src/pages/.gitkeep +0 -0
- package/claude/skills/sd-impl/evals/fixtures/with-test-file/.specs/260503143025/REQ-001-/355/225/240/354/235/270/352/263/204/354/202/260/plan.md +0 -26
- package/claude/skills/sd-impl/evals/fixtures/with-test-file/.specs/260503143025/REQ-001-/355/225/240/354/235/270/352/263/204/354/202/260/spec.md +0 -12
- package/claude/skills/sd-impl/evals/fixtures/with-test-file/src/lib/.gitkeep +0 -0
- package/claude/skills/sd-impl/references/impl-md-template.md +0 -87
- package/claude/skills/sd-impl/references/modes-and-failure.md +0 -65
- package/claude/skills/sd-plan/SKILL.md +0 -130
- package/claude/skills/sd-plan/evals/fixtures/already-implemented/.specs/260503143025/REQ-001-/354/202/254/354/232/251/354/236/220/353/252/251/353/241/235/spec.md +0 -14
- package/claude/skills/sd-plan/evals/fixtures/already-implemented/src/api/user.ts +0 -13
- package/claude/skills/sd-plan/evals/fixtures/already-implemented/src/components/Input.tsx +0 -15
- package/claude/skills/sd-plan/evals/fixtures/already-implemented/src/pages/UserList.tsx +0 -29
- package/claude/skills/sd-plan/evals/fixtures/basic-greenfield/.specs/260503143025/REQ-001-/354/236/205/352/263/240/354/247/200/354/213/234/354/204/234/352/270/264/352/270/211/355/221/234/354/213/234/spec.md +0 -17
- package/claude/skills/sd-plan/evals/fixtures/basic-greenfield/src/components/Input.tsx +0 -6
- package/claude/skills/sd-plan/evals/fixtures/basic-greenfield/src/pages/.gitkeep +0 -0
- package/claude/skills/sd-plan/evals/fixtures/demo-built/.specs/260503143025/DEMO-001-/352/261/260/353/236/230/354/262/230/demo.md +0 -26
- package/claude/skills/sd-plan/evals/fixtures/demo-built/.specs/260503143025/REQ-001-/352/261/260/353/236/230/354/262/230/353/252/251/353/241/235/355/231/224/353/251/264/spec.md +0 -15
- package/claude/skills/sd-plan/evals/fixtures/demo-built/src/components/Input.tsx +0 -25
- package/claude/skills/sd-plan/evals/fixtures/demo-built/src/data/mock-customer.ts +0 -16
- package/claude/skills/sd-plan/evals/fixtures/demo-built/src/pages/CustomerList.tsx +0 -25
- package/claude/skills/sd-plan/evals/golden.jsonl +0 -3
- package/claude/skills/sd-plan/references/plan-md-template.md +0 -138
- package/claude/skills/sd-spec/evals/fixtures/bulk-multi-source/.docs/20260122_/352/263/240/352/260/235/354/202/254_/354/236/205/352/263/240/354/247/200/354/213/234/354/204/234/352/260/234/354/204/240/354/232/224/354/262/255.eml +0 -20
- package/claude/skills/sd-spec/evals/fixtures/bulk-multi-source/.docs/20260205_/352/263/240/352/260/235/354/202/254_/354/266/234/352/263/240/355/231/224/353/251/264/352/264/200/353/240/250.eml +0 -17
- package/claude/skills/sd-spec/evals/fixtures/bulk-multi-source/.docs/20260301_/352/263/240/352/260/235/354/202/254_/352/266/214/355/225/234/354/262/264/352/263/204.eml +0 -18
- package/claude/skills/sd-spec/evals/fixtures/conflict-detection/.docs/20260317_/352/263/240/352/260/235/354/202/254_/352/270/264/352/270/211/354/262/230/353/246/254/353/260/251/354/271/250.eml +0 -17
- package/claude/skills/sd-spec/evals/fixtures/conflict-detection/.docs//355/232/214/354/235/230/353/214/200/353/263/270_20260320.txt +0 -13
- package/claude/skills/sd-spec/evals/fixtures/direct-simple/.gitkeep +0 -0
- package/claude/skills/sd-spec/evals/fixtures/spec-md-input/.specs/260101120000/REQ-001-test/spec.md +0 -19
- package/claude/skills/sd-spec/evals/fixtures/spec-md-input/.specs/260101120000/overview.md +0 -18
- package/claude/skills/sd-spec/evals/golden.jsonl +0 -4
- package/claude/skills/sd-spec/references/overview-md-template.md +0 -89
- package/claude/skills/sd-spec/references/raw-input-handling.md +0 -96
- package/claude/skills/sd-verify/SKILL.md +0 -96
- package/claude/skills/sd-verify/evals/fixtures/all-satisfied/.specs/260503143025/REQ-001-/355/225/240/354/235/270/352/263/204/354/202/260/impl.md +0 -20
- package/claude/skills/sd-verify/evals/fixtures/all-satisfied/.specs/260503143025/REQ-001-/355/225/240/354/235/270/352/263/204/354/202/260/plan.md +0 -14
- package/claude/skills/sd-verify/evals/fixtures/all-satisfied/.specs/260503143025/REQ-001-/355/225/240/354/235/270/352/263/204/354/202/260/spec.md +0 -12
- package/claude/skills/sd-verify/evals/fixtures/all-satisfied/src/lib/discount.test.ts +0 -11
- package/claude/skills/sd-verify/evals/fixtures/all-satisfied/src/lib/discount.ts +0 -7
- package/claude/skills/sd-verify/evals/fixtures/partial-mismatch/.specs/260503143025/REQ-001-/354/202/254/354/232/251/354/236/220/353/252/251/353/241/235/impl.md +0 -21
- package/claude/skills/sd-verify/evals/fixtures/partial-mismatch/.specs/260503143025/REQ-001-/354/202/254/354/232/251/354/236/220/353/252/251/353/241/235/plan.md +0 -21
- package/claude/skills/sd-verify/evals/fixtures/partial-mismatch/.specs/260503143025/REQ-001-/354/202/254/354/232/251/354/236/220/353/252/251/353/241/235/spec.md +0 -12
- package/claude/skills/sd-verify/evals/fixtures/partial-mismatch/src/pages/UserList.tsx +0 -19
- package/claude/skills/sd-verify/evals/fixtures/tdd-only/.specs/260503143025/REQ-001-/352/270/210/354/225/241/352/262/200/354/246/235/impl.md +0 -19
- package/claude/skills/sd-verify/evals/fixtures/tdd-only/.specs/260503143025/REQ-001-/352/270/210/354/225/241/352/262/200/354/246/235/plan.md +0 -14
- package/claude/skills/sd-verify/evals/fixtures/tdd-only/.specs/260503143025/REQ-001-/352/270/210/354/225/241/352/262/200/354/246/235/spec.md +0 -12
- package/claude/skills/sd-verify/evals/fixtures/tdd-only/src/lib/validate-amount.test.ts +0 -10
- package/claude/skills/sd-verify/evals/fixtures/tdd-only/src/lib/validate-amount.ts +0 -7
- package/claude/skills/sd-verify/evals/golden.jsonl +0 -3
- package/claude/skills/sd-verify/references/verify-md-template.md +0 -99
- /package/claude/skills/{sd-demo/evals/fixtures/basic-single-req/src/pages → sd-wip/evals/fixtures/empty}/.gitkeep +0 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# sd-crud-list / sd-crud-detail 매뉴얼
|
|
2
|
+
|
|
3
|
+
화면 작성 시 표준 목록 컴포넌트(`sd-crud-list`) 또는 표준 단건 편집 컴포넌트(`sd-crud-detail`) 를 채택하기로 결정했을 때의 사용법. 컴포넌트 일반 규약·데이터 흐름은 [client-component.md](./client-component.md).
|
|
4
|
+
|
|
5
|
+
## `sd-crud-list`
|
|
6
|
+
|
|
7
|
+
목록 화면의 표준 골격. 시트 + 검색 폼 + 등록/삭제/복구 버튼 + CTRL+S 저장 + 모달 선택 모드를 한꺼번에 처리.
|
|
8
|
+
|
|
9
|
+
### 표준 호출
|
|
10
|
+
|
|
11
|
+
```html
|
|
12
|
+
<sd-crud-list
|
|
13
|
+
[(ready)]="ready"
|
|
14
|
+
[initialized]="initialized()"
|
|
15
|
+
[(busyCount)]="busyCount"
|
|
16
|
+
[restricted]="!perms().includes('use')"
|
|
17
|
+
[readonly]="!canEdit()"
|
|
18
|
+
[viewType]="viewType()"
|
|
19
|
+
[selectMode]="selectMode() ?? 'multi'"
|
|
20
|
+
[key]="'<도메인-키>'"
|
|
21
|
+
[items]="items()"
|
|
22
|
+
[trackByFn]="trackByFn"
|
|
23
|
+
[(selectedKeys)]="selectedKeys"
|
|
24
|
+
[(currentPage)]="page"
|
|
25
|
+
[totalPageCount]="pageLength()"
|
|
26
|
+
[(sorts)]="sortingDefs"
|
|
27
|
+
(filterSubmit)="onFilterSubmit()"
|
|
28
|
+
(submit)="onSubmit()"
|
|
29
|
+
(create)="onCreate()"
|
|
30
|
+
(delete)="onDelete($event)"
|
|
31
|
+
(restore)="onRestore($event)"
|
|
32
|
+
>
|
|
33
|
+
<ng-template #filterTpl>...</ng-template>
|
|
34
|
+
<ng-template #toolTpl>...</ng-template>
|
|
35
|
+
|
|
36
|
+
<sd-sheet-column ...>
|
|
37
|
+
<ng-template [cell]="items()" let-item="item">...</ng-template>
|
|
38
|
+
</sd-sheet-column>
|
|
39
|
+
</sd-crud-list>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 슬롯 약속
|
|
43
|
+
|
|
44
|
+
| 슬롯 | 용도 |
|
|
45
|
+
| ------------------- | -------------------------------------------------------------------------- |
|
|
46
|
+
| `#filterTpl` | 검색 폼 필드. 있으면 상단에 조회 버튼과 함께 노출. |
|
|
47
|
+
| `#toolTpl` | 등록/삭제 버튼 옆 추가 도구 버튼. |
|
|
48
|
+
| `#commandTpl` | 상단(또는 modal/control 모드의 명령 영역) 추가 액션 버튼. |
|
|
49
|
+
| `#bottomCommandTpl` | modal 하단 좌측 영역. modal + selectMode 면 "선택 해제/확인" 과 함께 표시. |
|
|
50
|
+
|
|
51
|
+
`<sd-sheet-column>` 은 `<sd-crud-list>` 의 직속 자식으로 두면 내부 시트로 자동 투영된다.
|
|
52
|
+
|
|
53
|
+
### viewType 별 동작
|
|
54
|
+
|
|
55
|
+
- **`'page'`** — 라우팅 진입 단위. 상단에 저장 버튼.
|
|
56
|
+
- **`'control'`** — view 안에 임베드. 명령 영역에 저장 버튼.
|
|
57
|
+
- **`'modal'`** — 모달. `selectMode` 와 함께 쓰면 close 페이로드 `{ selectedKeys }` 자동 처리.
|
|
58
|
+
|
|
59
|
+
### 모달 선택 모드
|
|
60
|
+
|
|
61
|
+
`viewType="modal"` + `selectMode` 지정 시:
|
|
62
|
+
|
|
63
|
+
- `single` — 행 클릭 즉시 modal close.
|
|
64
|
+
- `multi` — 하단 "확인(N)" 버튼이 close 발생.
|
|
65
|
+
|
|
66
|
+
호출측은 `_sdModal.showAsync(...)` 결과로 `{ selectedKeys }` 페이로드 회수.
|
|
67
|
+
|
|
68
|
+
## `sd-crud-detail`
|
|
69
|
+
|
|
70
|
+
단일 레코드 편집 화면의 표준 골격. 폼 래핑 + CTRL+S/저장 버튼 + 모달의 "확인" 버튼 자동 처리.
|
|
71
|
+
|
|
72
|
+
### 표준 호출
|
|
73
|
+
|
|
74
|
+
```html
|
|
75
|
+
<sd-crud-detail
|
|
76
|
+
[(ready)]="ready"
|
|
77
|
+
[initialized]="initialized()"
|
|
78
|
+
[(busyCount)]="busyCount"
|
|
79
|
+
[restricted]="!perms().includes('use')"
|
|
80
|
+
[readonly]="!canEdit()"
|
|
81
|
+
[viewType]="viewType()"
|
|
82
|
+
(submit)="onSubmit()"
|
|
83
|
+
>
|
|
84
|
+
<ng-template #contentTpl>
|
|
85
|
+
<!-- 폼 본문 -->
|
|
86
|
+
</ng-template>
|
|
87
|
+
</sd-crud-detail>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 슬롯 약속
|
|
91
|
+
|
|
92
|
+
| 슬롯 | 용도 |
|
|
93
|
+
| -------------------- | ----------------------------------------------------------------- |
|
|
94
|
+
| `#contentTpl` (필수) | 폼 본문. `readonly` 면 `<sd-form>` 래핑 없이 그냥 표시된다. |
|
|
95
|
+
| `#commandTpl` | 상단/명령 영역 추가 버튼. |
|
|
96
|
+
| `#bottomCommandTpl` | modal 하단 좌측. modal 일 때 우측 "확인" 버튼이 항상 자동 추가됨. |
|
|
97
|
+
|
|
98
|
+
### viewType 별 동작
|
|
99
|
+
|
|
100
|
+
- **`'page'`** — 라우팅 진입 단위. 상단에 저장 버튼.
|
|
101
|
+
- **`'control'`** — view 안에 임베드. 명령 영역에 저장 버튼.
|
|
102
|
+
- **`'modal'`** — 모달. 하단 우측 "확인" 버튼이 자동.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# 클라이언트 데모 작성 매뉴얼
|
|
2
|
+
|
|
3
|
+
`@simplysm/angular` v14 로 spec.md §4.x 화면을 **데모** 로 옮길 때의 추가 처방. 컴포넌트 일반 규약(파일명·시그널·DI·핸들러·시트·폼·버튼·모달 호출·합성 패턴 등)은 [client-component.md](./client-component.md). 본 문서는 spec § → 산출물 매핑과 데모 한정 패턴만 다룬다.
|
|
4
|
+
|
|
5
|
+
## §4.x 화면 유형 → 파일 역할
|
|
6
|
+
|
|
7
|
+
| §4.x 패턴 | 파일 역할 |
|
|
8
|
+
| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
9
|
+
| 마스터(체크박스·`[E N]`·5버튼바) / 시트 단일 | `<domain>.list.ts` |
|
|
10
|
+
| 단건 입력 폼 | `<domain>.detail.ts` |
|
|
11
|
+
| 좌 목록 + 우 단건 | `<domain>.view.ts` + `.list.ts` + `.detail.ts` |
|
|
12
|
+
| 좌 헤더 목록 + 우(헤더 정보 + 라인 시트) 마스터-라인 | `<domain>.view.ts` + `.list.ts` + `.detail.ts` — 우 라인 영역은 `.detail.ts` (헤더 단건 + 라인) |
|
|
13
|
+
| 모달 (§동작에 `→ [화면.X] 을 모달로 띄움`) | `<domain>.modal.ts` |
|
|
14
|
+
| 프린트 양식 | `<domain>.print-template.ts` |
|
|
15
|
+
|
|
16
|
+
`<domain>` = 화면명 dash-case 영문 음역 슬러그. 같은 도메인 폴더에 같은 역할이 2개 이상이면 `<domain>-<갈래>.<역할>.ts`.
|
|
17
|
+
|
|
18
|
+
## 와이어프레임 권위
|
|
19
|
+
|
|
20
|
+
§4.x 와이어프레임이 모든 시각 요소(버튼·필터·시트·탭·검색)의 **존재·영역·순서** 결정의 1순위. 표준 슬롯/기본 UI 와 충돌 시 와이어프레임에 맞춰 슬롯을 비우거나 컴포넌트 교체. 줄 수·픽셀 좌표는 권위 X (폼 inline 자동 wrap 등 표현 한계).
|
|
21
|
+
|
|
22
|
+
`sd-crud-list` 의 표준 출력(`(create)/(delete)/(restore)`) 이 와이어프레임의 명시 버튼 위치를 가린다면 표준 출력 채택을 포기하고 슬롯 안에 `sd-button` 으로 직접 배치.
|
|
23
|
+
|
|
24
|
+
## 항목표 `종류` → 입력 컨트롤
|
|
25
|
+
|
|
26
|
+
[client-component.md "표준 입력 컨트롤"](./client-component.md) 표 적용. spec 의 `종류` 가 표 외 표기면 가장 가까운 매핑 + `// sd-demo: 종류 매핑 임의 — 확인 필요` 마커.
|
|
27
|
+
|
|
28
|
+
## 도메인 데이터 (더미)
|
|
29
|
+
|
|
30
|
+
- 컴포넌트 파일 안에 `interface DemoXxx { ... }` 로 spec §7 필드명만 일치하게 선언. 위에 `// sd-demo: 더미 타입 — 구현 단계에서 @모델/X 로 교체` 마커.
|
|
31
|
+
- list 의 `items` / detail 의 `data` 는 이 인라인 타입으로 signal 선언.
|
|
32
|
+
- 더미 데이터 1~수건 인라인 + `// sd-demo: 더미 — 구현 단계에서 교체` 마커.
|
|
33
|
+
|
|
34
|
+
## 권한 path
|
|
35
|
+
|
|
36
|
+
spec 에 권한 path 명시 없으면 임의 추정 + 마커:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
perms = injectPermsSignal(
|
|
40
|
+
["임의 권한 path"], // sd-demo: 권한 path 임의 — 확인 필요
|
|
41
|
+
["use", "edit"],
|
|
42
|
+
);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`restricted`/`readonly` 인라인 전달은 [client-component.md "권한 (perms)"](./client-component.md) 그대로.
|
|
46
|
+
|
|
47
|
+
## 액션 핸들러 (시뮬레이션 X)
|
|
48
|
+
|
|
49
|
+
데이터 변경 결과 반영 금지. 본문은 마커만:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
async onSaveClick() {
|
|
53
|
+
if (this.busyCount() > 0) return;
|
|
54
|
+
this.busyCount.update((v) => v + 1);
|
|
55
|
+
await this._sdToast.try(async () => {
|
|
56
|
+
// sd-demo: 미구현 — 동작 자리
|
|
57
|
+
});
|
|
58
|
+
this.busyCount.update((v) => v - 1);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## 모달
|
|
63
|
+
|
|
64
|
+
호출 측 후처리도 마커:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
const result = await this._sdModal.showAsync({ ... });
|
|
68
|
+
if (!result) return;
|
|
69
|
+
// sd-demo: 미구현 — 동작 자리
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
영역 한정 호출 (`→ [화면.Y] 의 <영역> — 선택 전용` 등) 은 모달 입력 시그널(`selectMode` 등)로 전달.
|
|
73
|
+
|
|
74
|
+
피호출 모달: `<sd-crud-detail>` 루트(`viewType='modal'` 자동 주입). 임의 `close` output 약속 만들지 X — `_sdModal.showAsync` 의 페이로드 회수 약속만 사용.
|
|
75
|
+
|
|
76
|
+
**동반 모달**: §동작에 `→ [화면.Y] 을 모달로 띄움` 으로 등장하는 모든 모달은 같은 호출에서 함께 생성. 이미 존재하면 재사용.
|
|
77
|
+
|
|
78
|
+
## 양식 매핑 (엑셀 업/다운로드)
|
|
79
|
+
|
|
80
|
+
§4.x 에 양식 매핑 표 있으면 `#toolTpl` 에 버튼만 (핸들러 본문은 마커):
|
|
81
|
+
|
|
82
|
+
```html
|
|
83
|
+
<ng-template #toolTpl>
|
|
84
|
+
<sd-button [size]="'sm'" [theme]="'link-success'" (click)="onExcelUploadClick()">
|
|
85
|
+
<ng-icon [svg]="tablerFileExcel" /> 엑셀 업로드
|
|
86
|
+
</sd-button>
|
|
87
|
+
<sd-button [size]="'sm'" [theme]="'link-primary'" (click)="onExcelDownloadClick()">
|
|
88
|
+
<ng-icon [svg]="tablerDownload" /> 엑셀 다운로드
|
|
89
|
+
</sd-button>
|
|
90
|
+
</ng-template>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## 상태별 와이어프레임
|
|
94
|
+
|
|
95
|
+
spec 이 `와이어프레임 (확정 전):` / `와이어프레임 (확정 후):` 로 분리하면:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
// sd-demo: 더미 — 구현 단계에서 교체
|
|
99
|
+
state = signal<"draft" | "confirmed">("draft");
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
```html
|
|
103
|
+
@if (state() === "draft") {
|
|
104
|
+
<!-- 확정 전 와이어프레임 반영 -->
|
|
105
|
+
} @else {
|
|
106
|
+
<!-- 확정 후 와이어프레임 반영 -->
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## "선택하세요." 빈 화면
|
|
111
|
+
|
|
112
|
+
list+detail 합성 view 의 빈 상태는 시연 시 눈에 띄게:
|
|
113
|
+
|
|
114
|
+
```html
|
|
115
|
+
<div
|
|
116
|
+
class="flex-fill tx-theme-gray-default p-xxl"
|
|
117
|
+
style="font-size: 48px; line-height: 1.5em"
|
|
118
|
+
>
|
|
119
|
+
<ng-icon [svg]="tablerArrowLeft" />
|
|
120
|
+
선택하세요.
|
|
121
|
+
</div>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
[client-component.md "list + detail 합성"](./client-component.md) 의 단순 `<div class="flex-fill p-default">선택하세요.</div>` 를 본 사례로 대체.
|
|
125
|
+
|
|
126
|
+
## 라우팅·메뉴 답습
|
|
127
|
+
|
|
128
|
+
답습 화면 1개의 라우팅·메뉴 등록 위치·방식 그대로. 라우트 경로는 화면명 dash-case 영문 음역 슬러그 (기존 슬러그 규칙 일관 시 답습). 메뉴 라벨은 spec 의 화면명 그대로.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 클라이언트 환경 셋업 매뉴얼
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
화면 작성 시점에는 거의 건드리지 않으며, 새 앱 부트스트랩이나 새 서비스/마스터 데이터 추가 시에만 본다.
|
|
4
4
|
|
|
5
5
|
## AppServiceProvider
|
|
6
6
|
|
|
@@ -148,7 +148,7 @@ export interface ISharedCustomer extends SharedDataBase<number> {
|
|
|
148
148
|
- getter 의 select 결과에 매직 필드 포함:
|
|
149
149
|
- `__valueKey` — 항목 키.
|
|
150
150
|
- `__searchText` — 검색 텍스트.
|
|
151
|
-
- `__isHidden` — 숨김 여부 (
|
|
151
|
+
- `__isHidden` — 숨김 여부 (예시: `isDeleted`).
|
|
152
152
|
- `getter(changeKeys)` 가 있으면 그 키들만 다시 조회 (incremental refresh).
|
|
153
153
|
- `orderBy` 는 정렬 키를 반환하는 함수 (`(item) => item.code`).
|
|
154
154
|
- `useSharedSignal<K>(name)` 헬퍼 함수를 같이 export — 컴포넌트는 inject 없이 이름만으로 접근.
|
|
@@ -13,23 +13,25 @@
|
|
|
13
13
|
|
|
14
14
|
## 표준 패턴
|
|
15
15
|
|
|
16
|
-
탭은
|
|
16
|
+
탭은 **상단 고정 + 본문 fill** 구조. flex-column 으로 탭바를 상단 고정, 본문은 `flex-fill` 안에 `@if` 분기.
|
|
17
17
|
|
|
18
18
|
```html
|
|
19
|
-
<
|
|
20
|
-
<
|
|
19
|
+
<div class="flex-column fill">
|
|
20
|
+
<div class="pb-default">
|
|
21
21
|
<sd-tab [(value)]="activeTab">
|
|
22
22
|
<sd-tab-item [value]="'info'">기본정보</sd-tab-item>
|
|
23
23
|
<sd-tab-item [value]="'history'">이력</sd-tab-item>
|
|
24
24
|
</sd-tab>
|
|
25
|
-
</
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div class="flex-fill">
|
|
28
|
+
@if (activeTab() === "info") {
|
|
29
|
+
<app-info-list />
|
|
30
|
+
} @else {
|
|
31
|
+
<app-history-list />
|
|
32
|
+
}
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
33
35
|
```
|
|
34
36
|
|
|
35
37
|
```ts
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
- 행 종류 구분 등 리터럴 값은 JS 값을 그대로 쓴다.
|
|
9
9
|
- 한쪽에만 있는 컬럼은 NULL 자리채움이 필요한데 타입 추론이 안 되므로 `expr.raw("<type>")\`NULL\`` 로 명시한다.
|
|
10
10
|
- 필터(`where`)는 union 전에 각 쿼리에 같은 조건으로 적용한다 — 각 소스에서 미리 행 수를 줄여야 union 비용이 작다 (predicate pushdown). union 결과에 필터를 걸면 두 소스를 다 읽은 뒤 거르게 되고, select 한 컬럼만 남아 join 컬럼으로 필터도 불가하다.
|
|
11
|
-
- 총 건수는 가능하면 **각 소스에서 따로 `count` 후 합산**한다. union 결과의 `count` 는 양쪽 SELECT 를 모두 실행해 머티리얼라이즈한 뒤 세지만, 각각 세면 단순 집계로 끝난다.
|
|
11
|
+
- 총 건수는 가능하면 **각 소스에서 따로 `count` 후 합산**한다. union 결과의 `count` 는 양쪽 SELECT 를 모두 실행해 머티리얼라이즈한 뒤 세지만, 각각 세면 단순 집계로 끝난다. 중복 제거가 필요해 합산이 부정확해질 때만 union 후 count.
|
|
12
12
|
- `Queryable.union(...)` 결과는 의미상 wrap 된 derived table 로, 그 위에서 호출되는 모든 fluent 연산자(`orderBy` / `limit` / `top` / `distinct` / `groupBy` / `having` / `where` / `select` / `join` 등)는 외부 union 위에 자동 적용된다. sub 별 적용(predicate pushdown 등)을 원하면 union 전에 각 sub-Queryable 에 미리 호출한다.
|
|
13
13
|
|
|
14
14
|
## 예시
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# ORM 작업 가이드
|
|
2
|
+
|
|
3
|
+
## 단일 쿼리 우선
|
|
4
|
+
|
|
5
|
+
연관 데이터는 select 의 `join` 으로 한 쿼리에 모아 가져온다. 여러 쿼리로 나눠 받아 코드(서버/UI)에서 합치지 않는다.
|
|
6
|
+
|
|
7
|
+
ORM 빌더로 표현 불가능한 경우, 작성 전 사용자 보고 후 중단.
|
|
8
|
+
|
|
9
|
+
예외: raw query로도 표현 불가하거나 단일 쿼리화가 명백히 비효율일 때만. 사유를 코드 주석에 남긴다.
|
|
10
|
+
|
|
11
|
+
이종 엔티티(예: 입고 + 출고)를 한 목록으로 보여줘야 할 때 두 결과를 코드에서 merge 하지 않으려면 → [orm-union.md](./orm-union.md) 참조.
|
|
12
|
+
|
|
13
|
+
## 조회 목록 표준 흐름
|
|
14
|
+
|
|
15
|
+
list / sheet 화면의 본 쿼리는 다음 순서로 작성한다:
|
|
16
|
+
|
|
17
|
+
1. root queryable 빌드 (`db.X()`).
|
|
18
|
+
2. 필요한 연관 데이터를 `joinSingle` 로 부착 — 본 행에 곧장 부착하지 않으면 안 되는 컬럼만. join 내부 쿼리도 동일 흐름 (`from → joinSingle → where → select`).
|
|
19
|
+
3. `.select((p) => ({ ...도출 컬럼들... }))` — coalesce / CASE WHEN / 산식 등 모든 도출을 한 번에 projection. select 콜백 안에서 로컬 `const` 로 산식을 잘게 나눠 가독성 확보.
|
|
20
|
+
4. WHERE 는 step 3 의 projected 컬럼 이름으로 직접 참조 (`r.psd`, `r.isCanceled`, `r.status`, …). framework 가 projected ExprUnit AST 를 WHERE 절에 그대로 inline 하므로 wrap 없이도 도출 컬럼 필터링이 동작한다.
|
|
21
|
+
5. `count()` 로 총 건수.
|
|
22
|
+
6. `orderBy(...).limit(page * size, size).execute()`.
|
|
23
|
+
|
|
24
|
+
WHERE / SELECT 양쪽에서 동일 도출 산식을 쓰겠다고 `buildDerived(p)` 같은 helper 함수 만들지 말 것 — step 3 의 projected 컬럼이 자동으로 그 역할을 한다.
|
|
25
|
+
|
|
26
|
+
화면 첫 진입 1회만 필요하고 refresh / 필터 변경에 무관한 데이터 (필터 dropdown 옵션 등) 는 본 목록 쿼리에 섞지 말 것. 별도 1회 effect 로 분리해 init 시점에만 로드한다.
|
|
27
|
+
|
|
28
|
+
## 안티패턴
|
|
29
|
+
|
|
30
|
+
### SELECT 절 안 `expr.subquery` / `expr.exists` 박지 말 것
|
|
31
|
+
|
|
32
|
+
도메인 boolean (`isCompleted`, `hasAny` 등) / 집계 (`SUM`, `COUNT`, `MAX`) 가 필요하면 `joinSingle` 안에서 `from + where + select(aggregate)` 로 묶어 outer 행에 컬럼으로 부착한다. SELECT column 에 subquery / exists 박으면 outer 행마다 inner 가 N 회 실행된다.
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
// 나쁜 예 — 행당 subquery N회
|
|
36
|
+
.select((p) => ({
|
|
37
|
+
isCompleted: expr.is(expr.exists(db.X().where(...))),
|
|
38
|
+
sumA: expr.subquery("number", db.Y().select(...)),
|
|
39
|
+
}))
|
|
40
|
+
|
|
41
|
+
// 좋은 예 — joinSingle 로 1회 부착, 컬럼으로 참조
|
|
42
|
+
.joinSingle("state", (q, p) =>
|
|
43
|
+
q.from(X).where((x) => [expr.eq(x.fk, p.id)])
|
|
44
|
+
.select((x) => ({
|
|
45
|
+
rowCount: expr.count(),
|
|
46
|
+
completedCount: expr.count(x.completedAt),
|
|
47
|
+
sumA: expr.sum(x.amount),
|
|
48
|
+
})),
|
|
49
|
+
)
|
|
50
|
+
.select((p) => ({
|
|
51
|
+
isCompleted: expr.gt(p.state!.completedCount, 0),
|
|
52
|
+
sumA: expr.coalesce(p.state!.sumA, 0),
|
|
53
|
+
}))
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 불필요한 `wrap()`
|
|
57
|
+
|
|
58
|
+
`wrap()` 은 framework 가 명시 요구하는 경우에만 쓴다 (대표적으로 `count()` after `distinct()` / `groupBy()` 호출 같은 명시 요구).
|
|
59
|
+
|
|
60
|
+
도출 컬럼 위에서 필터/정렬을 걸기 위해 wrap 을 끼우는 패턴은 불필요 — `.select(...).where((r) => [...])` 만으로 framework 가 projected ExprUnit AST 를 WHERE / ORDER BY 에 inline 한다.
|
|
61
|
+
|
|
62
|
+
"Layer 1 = materialize, Layer 2 = derive" 같은 다층 wrap 구조도 군더더기. 단일 select 안 로컬 `const` 로 산식 분리하면 동일 SQL 이 나온다.
|
|
63
|
+
|
|
64
|
+
## 스키마 정의
|
|
65
|
+
|
|
66
|
+
컬럼은 `NOT NULL` 기본. `.nullable()`/`.default(...)` 는 도메인 근거가 있을 때만 붙인다.
|
|
67
|
+
|
|
68
|
+
- `.nullable()`: 도메인상 값이 없을 수 있을 때만 (선택 입력, 미발생 이벤트 시각, 선택적 FK).
|
|
69
|
+
- `.default(...)`: 사용자가 명시 지시한 경우에만.
|
|
70
|
+
- "초기값 애매", "마이그레이션 중간 단계", "넣을 값 모름" 은 nullable/default 근거 아님. 호출자가 넣도록 강제하거나 backfill 후 `NOT NULL`로 전환.
|
|
71
|
+
|
|
72
|
+
## 삭제 전략
|
|
73
|
+
|
|
74
|
+
- **기초정보(마스터)**: soft delete (`isDisabled` 등). FK 참조 무결성 보존.
|
|
75
|
+
- **프로세스 문서(트랜잭션)**: 물리 delete. 상세 행 포함 캐스케이드. 단, 다른 테이블이 FK로 참조 중이면 삭제 차단하고 최종 사용자에게 toast 등으로 사유 안내.
|