@simplysm/sd-claude 14.0.65 → 14.0.68
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} +134 -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 +191 -79
- package/claude/scripts/sd_paths.py +22 -0
- package/claude/sd-check-bash.py +19 -0
- package/claude/sd-statusline.py +7 -12
- package/claude/skills/sd-commit/SKILL.md +8 -3
- package/claude/skills/sd-demo/SKILL.md +103 -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 +149 -46
- package/claude/skills/sd-impl/evals/fixtures/case-001-new-screen/spec.md +55 -0
- package/claude/skills/sd-impl/evals/fixtures/case-002-auto-process/spec.md +55 -0
- package/claude/skills/sd-impl/evals/fixtures/case-003-update-screen/packages/client/src/pages/book-list.ts +22 -0
- package/claude/skills/sd-impl/evals/fixtures/case-003-update-screen/spec.md +57 -0
- package/claude/skills/sd-impl/evals/fixtures/case-004-ambiguous-spec/spec.md +58 -0
- package/claude/skills/sd-impl/evals/fixtures/case-005-id-mismatch/spec.md +52 -0
- package/claude/skills/sd-impl/evals/fixtures/case-006-with-reference-units/packages/client/src/pages//352/261/260/353/236/230/354/262/230//352/261/260/353/236/230/354/262/230-/353/252/251/353/241/235.test.ts +10 -0
- package/claude/skills/sd-impl/evals/fixtures/case-006-with-reference-units/packages/client/src/pages//352/261/260/353/236/230/354/262/230//352/261/260/353/236/230/354/262/230-/353/252/251/353/241/235.ts +11 -0
- package/claude/skills/sd-impl/evals/fixtures/case-006-with-reference-units/packages/server/src/data-access//352/261/260/353/236/230/354/262/230-/354/240/221/352/267/274.ts +12 -0
- package/claude/skills/sd-impl/evals/fixtures/case-006-with-reference-units/packages/server/src/models//352/261/260/353/236/230/354/262/230.ts +8 -0
- package/claude/skills/sd-impl/evals/fixtures/case-006-with-reference-units/spec.md +77 -0
- 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 +6 -3
- package/claude/skills/sd-impl/references/spec-cross-check.md +82 -0
- package/claude/skills/sd-skill/SKILL.md +4 -4
- package/claude/skills/sd-skill/evals/golden.jsonl +1 -2
- package/claude/skills/sd-skill/references/eval-authoring.md +31 -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/scripts/sd-entries.mjs +2 -2
- 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,77 @@
|
|
|
1
|
+
# @simplysm/orm-common — DbContext
|
|
2
|
+
|
|
3
|
+
DB 1개에 대응하는 추상 클래스. 서브클래싱하여 테이블/뷰/프로시저를 인스턴스 프로퍼티로 등록하고, connect/transaction/DDL/initialize 진입점을 제공한다. 실제 SQL 실행은 생성자에 주입된 `DbContextExecutor` 가 담당.
|
|
4
|
+
|
|
5
|
+
## 생성·등록
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
class MainDb extends DbContext {
|
|
9
|
+
user = this.queryable(User); // → () => Queryable<User.$inferSelect, typeof User>
|
|
10
|
+
vUser = this.queryable(UserSummary); // View 도 동일
|
|
11
|
+
getUserById = this.executable(GetUserById); // → () => Executable<TParams, TReturns>
|
|
12
|
+
|
|
13
|
+
migrations = [
|
|
14
|
+
{ name: "001-init", up: async (db) => { await db.createTable(User); } },
|
|
15
|
+
];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const db = new MainDb(executor, { database: "mydb", schema: "dbo" });
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
- `protected queryable(builder)`: `TableBuilder | ViewBuilder` 를 받아 호출시마다 새 alias 가 할당된 `Queryable` 을 만드는 팩토리 함수를 반환. 반환 함수에는 `SD_BUILDER` 심볼로 원본 builder 가 부착됨 (initialize 가 회수).
|
|
22
|
+
- `protected executable(builder)`: `ProcedureBuilder` → `Executable` 팩토리. 동일하게 `SD_BUILDER` 부착.
|
|
23
|
+
- `_migration` 프로퍼티: 시스템 마이그레이션 테이블(`_migration(code PK varchar(255))`) 이 자동 등록됨.
|
|
24
|
+
|
|
25
|
+
## 연결 / 트랜잭션
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
await db.connect(async () => { ... }); // connect + tx (auto commit/rollback)
|
|
29
|
+
await db.connect(async () => { ... }, "REPEATABLE_READ"); // isolation level
|
|
30
|
+
await db.connectWithoutTransaction(async () => { ... }); // connect only
|
|
31
|
+
await db.transaction(async () => { ... }); // 이미 connect 인 상태에서 tx 만
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- `status: "ready" | "connect" | "transact"`. 잘못된 진입(중복 connect, 중복 tx)은 throw.
|
|
35
|
+
- `connect()` 진입시 1회 `validateRelationsImpl` 호출 (relation 무결성 검사 — 잘못된 FK 정의는 여기서 throw).
|
|
36
|
+
- 본문 throw 시 자동 rollback → `_executor.close()` 후 status `ready` 복귀. rollback 중 `DbTransactionError(NO_ACTIVE_TRANSACTION)` 는 무시.
|
|
37
|
+
- `transaction()` 단독은 `status==="connect"` 일 때만. 이미 transact 면 throw.
|
|
38
|
+
- `executeDefs(defs, resultMetas?)`: `_executor.executeDefs` 위임. `status==="transact"` 중 DDL 포함 시 throw.
|
|
39
|
+
|
|
40
|
+
## DDL 실행
|
|
41
|
+
|
|
42
|
+
`createTable`, `dropTable`, `renameTable`, `createView`, `dropView`, `createProc`, `dropProc`, `addColumn`, `dropColumn`, `modifyColumn`, `renameColumn`, `addPrimaryKey`, `dropPrimaryKey`, `addForeignKey`, `addIndex`, `dropForeignKey`, `dropIndex`, `clearSchema({database, schema?})`, `schemaExists(database, schema?): Promise<boolean>`, `truncate(table)`, `switchFk(table, enabled)`.
|
|
43
|
+
|
|
44
|
+
각각 `executeDefs([...QueryDef])` 로 1건씩 실행. 트랜잭션 내에서는 `switchFk` 외 모두 차단(`executeDefs` 에서 검사).
|
|
45
|
+
|
|
46
|
+
대응 `getXxxQueryDef(...)` 형태의 *생성기* 메서드도 동일 시그니처로 제공 (실행 없이 `QueryDef` 만 반환). `initialize()` 가 배치 DDL 을 모을 때 사용.
|
|
47
|
+
|
|
48
|
+
`getCreateObjectQueryDef(builder)` — Table/View/Procedure 중 무엇이든 받아 알맞은 create DDL 반환.
|
|
49
|
+
|
|
50
|
+
## initialize
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
await db.initialize(); // 미적용 migration 만 실행
|
|
54
|
+
await db.initialize({ dbs: ["a", "b"] }); // 다중 DB
|
|
55
|
+
await db.initialize({ force: true }); // 스키마 clear + 전체 재생성 + 모든 migration 을 "적용됨" 등록
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
반환값: 실행된 migration 이 있으면 `true`, 아니면 `false`.
|
|
59
|
+
|
|
60
|
+
동작:
|
|
61
|
+
- `force=true`: `clearSchema` → DbContext 의 모든 등록 객체(`queryable`/`executable` 프로퍼티에서 `SD_BUILDER` 로 회수) create → `_Migration` 에 모든 migration name 등록 → `false`.
|
|
62
|
+
- `force=false`:
|
|
63
|
+
- `_Migration` 테이블 없음 = 신규 DB → 전체 create + 모든 migration 등록 → `false`.
|
|
64
|
+
- 있음 → 미적용 migration 만 순차 실행 → 실행분 있으면 `true`.
|
|
65
|
+
|
|
66
|
+
서브클래스가 `migrations: Migration[]` 를 오버라이드해 `{ name, up(db) }` 목록 제공.
|
|
67
|
+
|
|
68
|
+
## 헬퍼
|
|
69
|
+
|
|
70
|
+
- `database`/`schema` getter — 생성자 옵션 노출.
|
|
71
|
+
- `getNextAlias(): string` — `T1`, `T2`, ... alias 카운터. `connect`/`connectWithoutTransaction` 진입시 reset.
|
|
72
|
+
- `resetAliasCounter()`.
|
|
73
|
+
- `getQueryDefObjectName(tableOrView)` — Table/View 메타에서 `{database, schema, name}` 산출 (없으면 DbContext 옵션 fallback).
|
|
74
|
+
|
|
75
|
+
## 인터페이스
|
|
76
|
+
|
|
77
|
+
외부에서 DbContext 를 의존성으로 다룰 때는 `DbContextBase`(코어) + `DbContextDdlMethods`(DDL) 인터페이스 사용 (`./types/db-context-def`). `DbContext` 가 둘 다 구현.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# @simplysm/orm-common — Executable
|
|
2
|
+
|
|
3
|
+
저장 프로시저 호출 래퍼. `DbContext.executable(builder)` 가 만든 팩토리 호출(`db.getUserById()`)마다 새 인스턴스 반환.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
class Executable<TParams extends ColumnBuilderRecord, TReturns extends ColumnBuilderRecord> {
|
|
7
|
+
getExecProcQueryDef(params?: InferColumnExprs<TParams>): ExecProcQueryDef
|
|
8
|
+
async execute(params: InferColumnExprs<TParams>): Promise<InferColumnExprs<TReturns>[][]>
|
|
9
|
+
}
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
- `params` 의 각 값은 `ExprInput<T>` (= `ExprUnit<T> | T`). 리터럴이면 `expr.val(meta.type, value)` 로 자동 래핑.
|
|
13
|
+
- 프로시저에 `params` 가 정의되지 않은 builder 에 인자를 넘기면 throw.
|
|
14
|
+
- 반환은 결과 셋의 배열 (프로시저가 여러 SELECT 를 반환할 수 있음).
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
const [users] = await db.getUserById().execute({ userId: 1 });
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`executable(db, builder)` — 팩토리. `DbContext.executable` 의 내부 구현이며, `SD_BUILDER` 심볼로 builder 를 부착해야 `initialize()` 가 회수할 수 있다 (직접 쓰지 말고 `DbContext.executable` 사용 권장).
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# @simplysm/orm-common — expr
|
|
2
|
+
|
|
3
|
+
Dialect 독립 SQL 표현식 빌더. SQL 문자열 대신 JSON AST(`Expr`/`WhereExpr`) 를 만들어 `Queryable` 메타에 누적되고, QueryBuilder 가 DBMS 별로 렌더.
|
|
4
|
+
|
|
5
|
+
## 래퍼
|
|
6
|
+
|
|
7
|
+
- `ExprUnit<T extends ColumnPrimitive>` — `{ dataType: ColumnPrimitiveStr, expr: Expr }`. `.n` 게터로 `NonNullable<T>` 로 cast.
|
|
8
|
+
- `WhereExprUnit` — boolean 컨텍스트 (`where`/`having`/논리 연산자) 전용.
|
|
9
|
+
- `ExprInput<T> = ExprUnit<T> | T` — 리터럴도 받는 입력 타입.
|
|
10
|
+
- `expr.toExpr(value)` / `toExpr(value)` 헬퍼 — `ExprUnit` 이면 풀고, 아니면 `{type:"value", value}` 로 감쌈.
|
|
11
|
+
|
|
12
|
+
## 카테고리별 API
|
|
13
|
+
|
|
14
|
+
### 값 / 컬럼 / Raw
|
|
15
|
+
- `expr.val(dataType, value)` — 리터럴 → `ExprUnit`. `dataType ∈ "string"|"number"|"boolean"|"DateTime"|"DateOnly"|"Time"|"Uuid"|"Bytes"`.
|
|
16
|
+
- `expr.col(dataType, ...path)` — 컬럼 참조(주로 내부).
|
|
17
|
+
- `expr.raw(dataType)\`SQL ${interp}\`` — 태그드 템플릿. 보간값은 파라미터화. dialect 의존 함수 사용 시 escape hatch.
|
|
18
|
+
|
|
19
|
+
### 비교 / NULL (→ `WhereExprUnit`)
|
|
20
|
+
- `eq`, `gt`, `lt`, `gte`, `lte`(source, target)
|
|
21
|
+
- `between(source, from?, to?)`
|
|
22
|
+
- `null(source)` — IS NULL
|
|
23
|
+
- `like(source, pattern)`, `regexp(source, pattern)`
|
|
24
|
+
- `in(source, values[])`, `inQuery(source, queryable)` — `queryable` 은 1-컬럼 select 여야 함. `exists(queryable)`.
|
|
25
|
+
|
|
26
|
+
### 논리
|
|
27
|
+
- `not(WhereExprUnit)`, `and(WhereExprUnit[])`, `or(WhereExprUnit[])` — 빈 배열은 throw.
|
|
28
|
+
|
|
29
|
+
### 문자열 (→ `ExprUnit<string ...>`)
|
|
30
|
+
- `concat(...args)`, `left(s, n)`, `right(s, n)`, `trim(s)`
|
|
31
|
+
- `padStart(s, length, fillString)`, `replace(s, from, to)`
|
|
32
|
+
- `upper(s)`, `lower(s)`
|
|
33
|
+
- `length(s)` → number, `byteLength(s)` → number
|
|
34
|
+
- `substring(s, start, length?)`, `indexOf(s, search)` → number
|
|
35
|
+
|
|
36
|
+
### 숫자
|
|
37
|
+
- `abs`, `round(s, digits)`, `ceil`, `floor`.
|
|
38
|
+
|
|
39
|
+
### 날짜 (`DateUnit = "year"|"month"|"day"|"hour"|"minute"|"second"`)
|
|
40
|
+
- `year/month/day/hour/minute/second(source)`
|
|
41
|
+
- `isoWeek(d)`, `isoWeekStartDate(d)`, `isoYearMonth(d)`
|
|
42
|
+
- `dateDiff(unit, from, to)` → number
|
|
43
|
+
- `dateAdd(unit, source, value)`
|
|
44
|
+
- `formatDate(source, format: string)` — format 문자열은 dialect 변환.
|
|
45
|
+
|
|
46
|
+
### NULL 처리 / 조건
|
|
47
|
+
- `coalesce(...args)` — 첫 non-null. 마지막 인자가 NonNullable 이면 반환 타입도 NonNullable.
|
|
48
|
+
- `nullIf(source, value)`
|
|
49
|
+
- `is(WhereExprUnit)` → `ExprUnit<boolean>` (boolean 변환)
|
|
50
|
+
- `if(condition, then, else_)` → `ExprUnit<T>` — 결과 dataType 은 ExprUnit/non-null 리터럴에서 추론.
|
|
51
|
+
- `switch<T>()` → `SwitchExprBuilder<T>` — `.case(cond, then).case(...).default(value)` 체이닝.
|
|
52
|
+
|
|
53
|
+
### 집계 (GROUP BY 컨텍스트)
|
|
54
|
+
- `count(arg?, distinct?)` → number
|
|
55
|
+
- `sum(arg)`, `avg(arg)` → `number | undefined`
|
|
56
|
+
- `max(arg)`, `min(arg)` → `T | undefined`
|
|
57
|
+
- `greatest(...args)`, `least(...args)` — 행 내 최대/최소.
|
|
58
|
+
|
|
59
|
+
### 기타 스칼라
|
|
60
|
+
- `rowNum()` → number — MSSQL `ROW_NUMBER() OVER(...)` 가 아니라 dialect 별 row 식별 함수 (간단 시퀀스).
|
|
61
|
+
- `random()` → number, 0~1.
|
|
62
|
+
- `cast(source, targetType: DataType)` — 결과 dataType 은 `dataTypeStrToColumnPrimitiveStr` 매핑.
|
|
63
|
+
- `subquery(dataType, queryable)` — 1-컬럼 select 의 스칼라 서브쿼리.
|
|
64
|
+
|
|
65
|
+
### 윈도우 함수 (`WinSpecInput = { partitionBy?: ExprInput[], orderBy?: [ExprInput, "ASC"|"DESC"?][] }`)
|
|
66
|
+
- 순위: `rowNumber(spec)`, `rank(spec)`, `denseRank(spec)`, `ntile(n, spec)`
|
|
67
|
+
- 시퀀스 비교: `lag(column, spec, { offset?, default? })`, `lead(column, spec, { offset?, default? })`
|
|
68
|
+
- 첫/끝: `firstValue(column, spec)`, `lastValue(column, spec)`
|
|
69
|
+
- 집계 윈도우: `sumOver(column, spec)`, `avgOver(column, spec)`, `countOver(spec, column?)`, `minOver(column, spec)`, `maxOver(column, spec)`
|
|
70
|
+
|
|
71
|
+
## 예시
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
db.user()
|
|
75
|
+
.where(u => [
|
|
76
|
+
expr.eq(u.status, "active"),
|
|
77
|
+
expr.between(u.age, 18, 65),
|
|
78
|
+
expr.or([expr.like(u.name, "%kim%"), expr.like(u.email, "%kim%")]),
|
|
79
|
+
])
|
|
80
|
+
.select(u => ({
|
|
81
|
+
name: expr.concat(u.firstName, " ", u.lastName),
|
|
82
|
+
rank: expr.rowNumber({ partitionBy: [u.deptId], orderBy: [[u.score, "DESC"]] }),
|
|
83
|
+
label: expr.switch<string>()
|
|
84
|
+
.case(expr.gte(u.score, 90), "A")
|
|
85
|
+
.case(expr.gte(u.score, 80), "B")
|
|
86
|
+
.default("C"),
|
|
87
|
+
}))
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Expr AST 타입
|
|
91
|
+
|
|
92
|
+
세부 노드 타입은 `./types/expr` 의 union (`ExprColumn`/`ExprValue`/`ExprRaw`/...`ExprWindow`/`ExprSubquery`). 일반 사용자는 직접 다룰 필요 없음 — ExprRenderer 구현이나 디버깅·검증 시만.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# @simplysm/orm-common — Queryable
|
|
2
|
+
|
|
3
|
+
체이닝 SELECT/INSERT/UPDATE/DELETE/UPSERT 빌더. `DbContext.queryable(builder)` 가 만든 팩토리 호출(`db.user()`)마다 새 alias 가 할당된 새 `Queryable` 이 반환된다. 모든 체이닝 메서드는 새 인스턴스를 반환(immutable).
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
class Queryable<TData extends DataRecord, TFrom extends TableBuilder | never>
|
|
7
|
+
```
|
|
8
|
+
- `TData` — 결과 row 타입 (관계 include 포함).
|
|
9
|
+
- `TFrom` — CUD(INSERT/UPDATE/DELETE/UPSERT) 시 필요한 원본 TableBuilder. `select`/`join`/`union`/`wrap`/`groupBy`/`recursive`/`distinct` 한 후엔 `never` 가 되어 CUD 불가.
|
|
10
|
+
|
|
11
|
+
## 옵션 체이닝
|
|
12
|
+
|
|
13
|
+
- `.select(fn: cols => mapped)` — SELECT 컬럼/표현식 재구성. 원시 리터럴은 자동 `ExprUnit` 으로 래핑. → `Queryable<UnwrapQueryableRecord<R>, never>`.
|
|
14
|
+
- `.distinct()` — DISTINCT.
|
|
15
|
+
- `.lock()` — FOR UPDATE.
|
|
16
|
+
- `.top(n)` — TOP N (ORDER BY 무관).
|
|
17
|
+
- `.limit(skip, take)` — `orderBy` 필수, 없으면 throw.
|
|
18
|
+
- `.orderBy(fn | "key.path", "ASC" | "DESC"?)` — 누적. 문자열 overload 는 `obj.getChainValue` 로 컬럼 검색 (동적 정렬용).
|
|
19
|
+
- `.where(predicate: cols => WhereExprUnit[])` — 누적, AND 결합.
|
|
20
|
+
- `.search(cols => ExprUnit<string|undefined>[], text)` — `parseSearchQuery` 의 OR/AND(`+`)/NOT(`-`)/`"…"`/`*` 구문을 컬럼들에 LIKE 로 적용 (소문자 비교).
|
|
21
|
+
- `.groupBy(cols => ExprUnit[])` — `TFrom` → never.
|
|
22
|
+
- `.having(predicate)` — GROUP BY 후 필터, 누적 AND.
|
|
23
|
+
|
|
24
|
+
## JOIN / INCLUDE
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
.join(as, (qr, cols) => Queryable) // 1:N — { ..., [as]?: R[] }
|
|
28
|
+
.joinSingle(as, (qr, cols) => Queryable) // N:1 또는 1:1 — { ..., [as]?: R }
|
|
29
|
+
.include(item => item.user.company) // PathProxy 기반 자동 JOIN (TableBuilder 기반만)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- 콜백의 `qr: JoinQueryable` 은 `.from(table)` / `.select(customCols)` / `.union(...queries)` 제공.
|
|
33
|
+
- `.include` 는 `TableBuilder.relations` 정의를 따라 FK/RelationKey(=joinSingle) 또는 FKT/RelationKeyTarget(=join, `single:true` 면 joinSingle) 으로 풀림. 동일 경로 중복 호출은 무시. 다단계(`a.b.c`)는 부모 객체 안으로 nested 됨.
|
|
34
|
+
- PathProxy 는 ColumnPrimitive 필드 접근을 컴파일 에러로 막아 관계 키만 허용.
|
|
35
|
+
|
|
36
|
+
## Subquery / UNION / Recursive CTE
|
|
37
|
+
|
|
38
|
+
- `.wrap()` — 현재 Queryable 을 서브쿼리로 감싼 새 Queryable. `distinct()`/`groupBy()` 후 `count()` 직전에 필요.
|
|
39
|
+
- `Queryable.union(q1, q2, ...)` (static) — UNION (중복 제거). 2개 미만 throw. 첫 query 의 컬럼 구조 사용.
|
|
40
|
+
- `.recursive(fn: (cte: RecursiveQueryable<TData>) => Queryable<TData>)` — WITH RECURSIVE 생성. 콜백 안에서 `cte.from(table)` 한 결과에 `self` 프로퍼티(현재 CTE 자기 참조)가 부여됨. `.union(...)` 도 가능.
|
|
41
|
+
|
|
42
|
+
## 실행 (SELECT)
|
|
43
|
+
|
|
44
|
+
- `await qr.execute(): Promise<TData[]>`
|
|
45
|
+
- `await qr.single(): Promise<TData | undefined>` — 2개 이상이면 throw.
|
|
46
|
+
- `await qr.first(): Promise<TData | undefined>` — 내부 `top(1)`.
|
|
47
|
+
- `await qr.count(fn?): Promise<number>` — `distinct`/`groupBy` 후 직접 호출시 throw → `wrap()` 필요.
|
|
48
|
+
- `await qr.exists(): Promise<boolean>` — `top(1)` 으로 행 존재 확인.
|
|
49
|
+
|
|
50
|
+
## CUD (TFrom = TableBuilder 필요)
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
await q.insert(records);
|
|
54
|
+
const [{ id }] = await q.insert([{...}], ["id"]); // OUTPUT
|
|
55
|
+
|
|
56
|
+
await q.insertIfNotExists(record); // WHERE 조건과 결합
|
|
57
|
+
await q.insertIfNotExists(record, ["id"]); // 단건 반환
|
|
58
|
+
|
|
59
|
+
await q2.insertInto(TargetTable); // INSERT INTO ... SELECT
|
|
60
|
+
await q2.insertInto(TargetTable, ["id"]);
|
|
61
|
+
|
|
62
|
+
await q.update(cols => ({ name: expr.val("string", "x") }));
|
|
63
|
+
await q.update(cols => ({...}), ["id"]);
|
|
64
|
+
|
|
65
|
+
await q.delete();
|
|
66
|
+
await q.delete(["id", "name"]);
|
|
67
|
+
|
|
68
|
+
await q.upsert(updateFn); // UPDATE 또는 INSERT (existsSelectQuery=현재 where)
|
|
69
|
+
await q.upsert(updateFn, ["id"]);
|
|
70
|
+
await q.upsert(updateFn, insertFn);
|
|
71
|
+
await q.upsert(updateFn, insertFn, ["id"]);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- `insert(records)` 는 records 0건이면 noop. MSSQL 1000행 제한을 위해 청크 분할(`CHUNK_SIZE=1000`) — 각 청크는 별도 `executeDefs` 호출, OUTPUT 도 누적.
|
|
75
|
+
- `insert` 의 records 에 autoIncrement 컬럼 값이 명시되면 자동으로 `overrideIdentity` 켜짐.
|
|
76
|
+
- CUD 는 `TFrom` 이 `TableBuilder` 일 때만 — 아니면 `_getCudOutputDef` 에서 throw. ViewBuilder/Queryable 합성/Union 후엔 사용 불가.
|
|
77
|
+
- `await q.switchFk(enabled)` — TableBuilder/ViewBuilder 기반에서 FK on/off (트랜잭션 내 사용 가능).
|
|
78
|
+
|
|
79
|
+
## QueryDef 생성기 (실행 없이 def 만)
|
|
80
|
+
|
|
81
|
+
`getSelectQueryDef()`, `getInsertQueryDef(records, output?)`, `getInsertIfNotExistsQueryDef(record, output?)`, `getInsertIntoQueryDef(target, output?)`, `getUpdateQueryDef(recordFwd, output?)`, `getDeleteQueryDef(output?)`, `getUpsertQueryDef(updateFn, insertFn, output?)`, `getResultMeta(outputColumns?)`.
|
|
82
|
+
|
|
83
|
+
## 타입
|
|
84
|
+
|
|
85
|
+
`QueryableRecord<TData>` — `TData` 의 원시 필드를 `ExprUnit<T>`, 중첩 객체/배열은 재귀로 감싼 형태. `where`/`select` 콜백 인자 타입.
|
|
86
|
+
|
|
87
|
+
`QueryableWriteRecord<TData>` — `ExprInput<T>` (= `ExprUnit<T> | T`) 으로, `update`/`upsert` 의 record 값 입력 타입.
|
|
88
|
+
|
|
89
|
+
`UnwrapQueryableRecord<R>` — `.select` 결과를 다시 DataRecord 로 역추론.
|
|
90
|
+
|
|
91
|
+
`PathProxy<T>` — `.include` 인자 타입. 비-ColumnPrimitive 필드만 노출.
|
|
92
|
+
|
|
93
|
+
## 보조 함수
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
queryable(db, tableOrView, as?) // Queryable factory 생성. DbContext.queryable 의 내부 구현
|
|
97
|
+
getMatchedPrimaryKeys(fkCols, targetTable) // include 가 FK 컬럼과 대상 PK 매칭
|
|
98
|
+
```
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# @simplysm/orm-common — Schema Builders
|
|
2
|
+
|
|
3
|
+
테이블/뷰/프로시저를 fluent 로 정의하는 immutable 빌더. `DbContext` 의 `queryable()`/`executable()` 에 전달하여 등록한다. 모든 메서드는 `new Xxx({...this.meta, ...})` 형태로 새 인스턴스 반환.
|
|
4
|
+
|
|
5
|
+
## Table / TableBuilder
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { Table } from "@simplysm/orm-common";
|
|
9
|
+
|
|
10
|
+
const User = Table("User") // Table<TName>(name)
|
|
11
|
+
.database("mydb")
|
|
12
|
+
.schema("dbo") // MSSQL/PostgreSQL only
|
|
13
|
+
.description("사용자")
|
|
14
|
+
.columns((c) => ({
|
|
15
|
+
id: c.bigint().autoIncrement(),
|
|
16
|
+
name: c.varchar(100),
|
|
17
|
+
email: c.varchar(200).nullable(),
|
|
18
|
+
status: c.varchar(20).default("active"),
|
|
19
|
+
}))
|
|
20
|
+
.primaryKey("id") // 복합: .primaryKey("a","b")
|
|
21
|
+
.indexes((i) => [i.index("email").unique()])
|
|
22
|
+
.relations((r) => ({
|
|
23
|
+
posts: r.foreignKeyTarget(() => Post, "author"),
|
|
24
|
+
}));
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
타입 추론 프로퍼티 (`readonly $xxx!` — 런타임 값 X, 타입 추출용):
|
|
28
|
+
- `$inferSelect` — 컬럼 + (deep) 관계 (관계는 optional)
|
|
29
|
+
- `$inferColumns` — 컬럼만
|
|
30
|
+
- `$inferInsert` — `autoIncrement`/`nullable`/`default` 컬럼은 optional
|
|
31
|
+
- `$inferUpdate` — 모든 필드 optional
|
|
32
|
+
- `$columns`, `$relations` — 정의 자체
|
|
33
|
+
|
|
34
|
+
`meta`: `{ name; description?; database?; schema?; columns?; primaryKey?; relations?; indexes? }`.
|
|
35
|
+
|
|
36
|
+
## View / ViewBuilder
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import { View } from "@simplysm/orm-common";
|
|
40
|
+
|
|
41
|
+
const ActiveUsers = View("ActiveUsers")
|
|
42
|
+
.database("mydb")
|
|
43
|
+
.query((db: MainDb) =>
|
|
44
|
+
db.user().where(u => [expr.eq(u.status, "active")])
|
|
45
|
+
.select(u => ({ id: u.id, name: u.name })))
|
|
46
|
+
.relations(r => ({ posts: r.relationKeyTarget(() => Post, "author") }));
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
- `.query<TData>(viewFn: (db) => Queryable<TData>)` 의 viewFn 은 `queryable()` 호출시(=`createView` DDL 만들 때, `db.queryable(ViewBuilder)` 팩토리에서) 실행된다.
|
|
50
|
+
- View 의 관계는 `relationKey`/`relationKeyTarget` 만 사용 (DB FK 미생성).
|
|
51
|
+
- `$inferSelect: TData`.
|
|
52
|
+
|
|
53
|
+
## Procedure / ProcedureBuilder
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { Procedure } from "@simplysm/orm-common";
|
|
57
|
+
|
|
58
|
+
const GetUserById = Procedure("GetUserById")
|
|
59
|
+
.database("mydb")
|
|
60
|
+
.params(c => ({ userId: c.bigint() }))
|
|
61
|
+
.returns(c => ({ id: c.bigint(), name: c.varchar(100) }))
|
|
62
|
+
.body("SELECT id, name FROM User WHERE id = userId");
|
|
63
|
+
// MSSQL 본문은 @userId 사용. PostgreSQL 은 RETURN QUERY 필요.
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`$params`, `$returns` 타입 추론. `meta`: `{ name; description?; database?; schema?; params?; returns?; query? }`.
|
|
67
|
+
|
|
68
|
+
## Column Factory (`columns((c) => ...)` 안에서 사용)
|
|
69
|
+
|
|
70
|
+
`createColumnFactory()` 반환 객체의 메서드 — 모두 `ColumnBuilder<TValue, TMeta>` 반환:
|
|
71
|
+
|
|
72
|
+
| 메서드 | TS 타입 | SQL 매핑 |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| `int()` | number | INT |
|
|
75
|
+
| `bigint()` | number | BIGINT |
|
|
76
|
+
| `float()` | number | FLOAT/REAL |
|
|
77
|
+
| `double()` | number | DOUBLE |
|
|
78
|
+
| `decimal(precision, scale?)` | number | DECIMAL(p,s) |
|
|
79
|
+
| `varchar(length)` | string | VARCHAR(n) |
|
|
80
|
+
| `char(length)` | string | CHAR(n) |
|
|
81
|
+
| `text()` | string | TEXT/LONGTEXT |
|
|
82
|
+
| `binary()` | Bytes | LONGBLOB/VARBINARY(MAX)/BYTEA |
|
|
83
|
+
| `boolean()` | boolean | TINYINT(1)/BIT/BOOLEAN |
|
|
84
|
+
| `datetime()` | DateTime | DATETIME |
|
|
85
|
+
| `date()` | DateOnly | DATE |
|
|
86
|
+
| `time()` | Time | TIME |
|
|
87
|
+
| `uuid()` | Uuid | BINARY(16)/UNIQUEIDENTIFIER/UUID |
|
|
88
|
+
|
|
89
|
+
`ColumnBuilder` 체이닝:
|
|
90
|
+
- `.autoIncrement()` — INSERT 시 자동 증가, `$inferInsert` 에서 optional.
|
|
91
|
+
- `.nullable()` — TS 타입에 `| undefined` 추가.
|
|
92
|
+
- `.default(value)` — 기본값. `$inferInsert` 에서 optional.
|
|
93
|
+
- `.description(text)` — DDL Comment.
|
|
94
|
+
|
|
95
|
+
타입 유틸: `ColumnBuilderRecord`, `InferColumns<T>`, `InferColumnExprs<T>` (Executable params), `RequiredInsertKeys<T>`, `OptionalInsertKeys<T>`, `InferInsertColumns<T>`, `InferUpdateColumns<T>`, `DataToColumnBuilderRecord<TData>`.
|
|
96
|
+
|
|
97
|
+
## Index Factory (`indexes((i) => ...)` 안에서)
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
i.index("email").unique()
|
|
101
|
+
i.index("name", "createdAt").orderBy("ASC", "DESC")
|
|
102
|
+
i.index("createdAt").name("IX_Foo")
|
|
103
|
+
i.index("a").description("...")
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`IndexBuilder<TKeys>` 의 `meta`: `{ columns; name?; unique?; orderBy?; description? }`.
|
|
107
|
+
|
|
108
|
+
## Relation Factory (`relations((r) => ...)` 안에서)
|
|
109
|
+
|
|
110
|
+
Table 은 4개 모두, View 는 `relationKey`/`relationKeyTarget` 만 노출.
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
// N:1
|
|
114
|
+
r.foreignKey(["authorId"], () => User, { description?: string }) // DB FK 생성
|
|
115
|
+
r.relationKey(["companyId"], () => Company, { description?: string }) // 논리 관계 (FK X) — View 가능
|
|
116
|
+
|
|
117
|
+
// 1:N (기본) 또는 1:1 (single: true)
|
|
118
|
+
r.foreignKeyTarget(() => Post, "author")
|
|
119
|
+
r.foreignKeyTarget(() => Profile, "user", { single: true })
|
|
120
|
+
r.relationKeyTarget(() => UserSummary, "company", { single?, description? })
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
- `foreignKey` 의 두 번째 인자는 *대상 테이블 factory* `() => TableBuilder` (순환 참조 회피).
|
|
124
|
+
- `foreignKeyTarget` 의 두 번째 인자 `relationName` 은 대상 테이블에 정의된 자기방향 FK 의 키 이름.
|
|
125
|
+
- 메서드 체이닝(`.description()`/`.single()`)은 TS 순환 참조 (TS7022) 회피용으로 *제거됨* — 옵션은 마지막 `opts` 객체로만 전달.
|
|
126
|
+
- 빌더 클래스: `ForeignKeyBuilder`, `ForeignKeyTargetBuilder`, `RelationKeyBuilder`, `RelationKeyTargetBuilder`.
|
|
127
|
+
|
|
128
|
+
타입 유틸: `RelationBuilderRecord`, `ExtractRelationTarget<T>`, `ExtractRelationTargetResult<T>`, `InferDeepRelations<TRelations>` — 모두 관계를 optional 로 추론, 같은 테이블 재방문 시 더 깊이 들어가지 않음 (순환 끊김).
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# @simplysm/orm-node
|
|
2
|
+
|
|
3
|
+
Node.js 환경에서 `@simplysm/orm-common` 의 `DbContext` 를 실제 DB(MSSQL/MySQL/PostgreSQL)에 붙여 실행하기 위한 어댑터. 드라이버 모듈(`tedious`/`mysql2`/`pg`/`pg-copy-streams`)은 dialect 선택 시점에 지연 import.
|
|
4
|
+
|
|
5
|
+
## 사용 트리거 인덱스
|
|
6
|
+
|
|
7
|
+
- **`createOrm` / `Orm` / `OrmOptions`** — `DbContext` 서브클래스 + `DbConnConfig` 로 ORM 인스턴스를 만들고, 트랜잭션 유/무 콜백을 실행한다. 일반 ORM 사용의 진입점.
|
|
8
|
+
- **`createDbConn`** — `DbConnConfig` 만으로 저수준 `DbConn` 인스턴스를 직접 만든다. `DbContext` 없이 raw SQL/bulk insert 가 필요할 때.
|
|
9
|
+
- **`NodeDbContextExecutor`** — `DbContext` 의 executor 직접 주입이 필요할 때. 일반적으로는 `createOrm` 이 내부적으로 사용.
|
|
10
|
+
- **`MysqlDbConn` / `MssqlDbConn` / `PostgresqlDbConn`** — dialect별 `DbConn` 구현. 직접 `new` 하지 말고 `createDbConn` 사용. 타입 참조용으로만 import.
|
|
11
|
+
- **`DbConn` / `DbConnConfig` (+ `MysqlDbConnConfig` / `MssqlDbConnConfig` / `PostgresqlDbConnConfig`)** — 설정/연결 타입. 함수 시그니처·DI 토큰 등에서 참조.
|
|
12
|
+
- **`getDialectFromConfig`** — `DbConnConfig` → `Dialect` 변환(`mssql-azure` → `mssql`). 쿼리 빌더 선택 시.
|
|
13
|
+
- **`DB_CONN_CONNECT_TIMEOUT` (10s) / `DB_CONN_DEFAULT_TIMEOUT` (10m) / `DB_CONN_ERRORS`** — 타임아웃·에러 메시지 상수.
|
|
14
|
+
|
|
15
|
+
## createOrm
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
function createOrm<T extends DbContext>(
|
|
19
|
+
DbClass: new (executor: DbContextExecutor, opt: { database: string; schema?: string }) => T,
|
|
20
|
+
config: DbConnConfig,
|
|
21
|
+
options?: OrmOptions, // { database?: string; schema?: string } — config 보다 우선
|
|
22
|
+
): Orm<T>;
|
|
23
|
+
|
|
24
|
+
interface Orm<T> {
|
|
25
|
+
connect<R>(cb: (db: T) => Promise<R>, isolationLevel?: IsolationLevel): Promise<R>; // 트랜잭션
|
|
26
|
+
connectWithoutTransaction<R>(cb: (db: T) => Promise<R>): Promise<R>; // 트랜잭션 없음
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`database` 가 `options` 와 `config` 양쪽 모두 없으면 throw. 매 `connect*` 호출마다 새 `DbContext` 인스턴스를 만들어 콜백 종료 시 연결을 닫는다.
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
const orm = createOrm(MyDb, { dialect: "mysql", host, port, username, password, database });
|
|
34
|
+
await orm.connect(async (db) => db.user().execute());
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## createDbConn
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
function createDbConn(config: DbConnConfig): Promise<DbConn>;
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
dialect 에 따라 드라이버 모듈을 lazy import 한 뒤 해당 `DbConn` 구현 반환. **반환된 객체는 미연결 상태** — 호출자가 `conn.connect()` → 사용 → `conn.close()` 까지 책임. `DbConn` 은 `EventEmitter<{ close: void }>` 이며 다음 메서드 제공: `connect`, `close`, `beginTransaction(isolationLevel?)`, `commitTransaction`, `rollbackTransaction`, `execute(queries: string[])`, `executeParametrized(query, params?)`, `bulkInsert(tableName, columnMetas, records)`. `bulkInsert` 는 dialect별 네이티브 경로 사용(MSSQL: tedious BulkLoad / MySQL: `LOAD DATA LOCAL INFILE` 임시파일 / PostgreSQL: `COPY FROM STDIN`).
|
|
44
|
+
|
|
45
|
+
## DbConnConfig
|
|
46
|
+
|
|
47
|
+
dialect 분기 union. 공통 필드: `host`, `port?`, `username`, `password`, `database?`, `defaultIsolationLevel?`.
|
|
48
|
+
|
|
49
|
+
- `MysqlDbConnConfig` — `dialect: "mysql"`.
|
|
50
|
+
- `MssqlDbConnConfig` — `dialect: "mssql" | "mssql-azure"`, `schema?`. `mssql-azure` 는 `encrypt: true` 로 연결.
|
|
51
|
+
- `PostgresqlDbConnConfig` — `dialect: "postgresql"`, `schema?`.
|
|
52
|
+
|
|
53
|
+
## NodeDbContextExecutor
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
new NodeDbContextExecutor(config: DbConnConfig)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`DbContextExecutor` 구현. `connect` 시 내부에서 `createDbConn` + `conn.connect()` 수행. `executeDefs(defs, resultMetas?)` 는 `@simplysm/orm-common` 의 `createQueryBuilder` + `parseQueryResult` 를 사용해 `QueryDef[]` → SQL → 파싱 결과. `resultMetas` 가 전부 `null` 인 경우 단일 결합 SQL 1회로 묶어 실행. 미연결 상태에서 메서드 호출 시 `DB_CONN_ERRORS.NOT_CONNECTED` SdError throw.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# @simplysm/sd-claude
|
|
2
|
+
|
|
3
|
+
Claude Code 셋업 자산(`.claude/` 의 sd-* 스킬·룰·훅) 배포 및 `sd-claude` CLI 제공 패키지.
|
|
4
|
+
|
|
5
|
+
코드 API 없음 (npm 배포용). 외부에서 import 할 수 있는 라이브러리 심볼은 노출하지 않는다.
|
|
6
|
+
|
|
7
|
+
- `bin`: `sd-claude` — `auth save` / `auth switch` (저장된 Claude 계정 전환).
|
|
8
|
+
- `postinstall`: 설치 시 사용자 `~/.claude/` 로 자산 동기화.
|
|
9
|
+
- `prepack`: 배포 전 `.claude/` → `packages/sd-claude/claude/` 증분 복사.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# @simplysm/sd-cli
|
|
2
|
+
|
|
3
|
+
워크스페이스 빌드/배포 오케스트레이터. 라이브러리 export 는 `sd.config.ts` 작성용 타입과 Vitest Angular 플러그인, 그리고 외부 도구가 재사용할 `SdTsCompiler` 다. CLI 서브커맨드는 이 문서 대상 아님 (`pnpm sd-cli --help`).
|
|
4
|
+
|
|
5
|
+
## 사용 트리거 인덱스
|
|
6
|
+
- **`SdConfigFn` / `SdConfig` / `SdConfigParams`** — `sd.config.ts` 의 default export 타이핑. 자세히: [sd-config.md](./sd-config.md)
|
|
7
|
+
- **패키지별 설정 타입 (`SdBuildPackageConfig`, `SdClientPackageConfig`, `SdServerPackageConfig`, `SdScriptsPackageConfig`)** — `SdConfig.packages` 값 타이핑. 자세히: [sd-config.md](./sd-config.md)
|
|
8
|
+
- **`SdPublishConfig` / `SdPostPublishScriptConfig`** — `publish`·`postPublish` 항목 타이핑. 자세히: [sd-config.md](./sd-config.md)
|
|
9
|
+
- **`SdCapacitorConfig` / `SdElectronConfig` / `SdPwaConfig` / `SdBrowserSupportConfig`** — 클라이언트 패키지의 모바일/데스크톱/PWA/브라우저 지원 옵션. 자세히: [sd-config.md](./sd-config.md)
|
|
10
|
+
- **`sdAngularPlugin(options)`** — Vitest 의 `vite.config` (또는 `vitest.config`) 에서 Angular 패키지 AOT 컴파일이 필요할 때 plugin 으로 추가.
|
|
11
|
+
- **`SdTsCompiler` (+ `ISdTsCompilerOptions`, `ISdTsCompilerResult`)** — 사용자 코드에서 직접 호출할 일은 거의 없음. Angular/Non-Angular TS 패키지를 증분 컴파일·진단·lint·SCSS 통합 처리하는 엔진. `sd-cli` 내부 엔진(`engines/`, `orchestrators/`) 및 `sdAngularPlugin` 에서 사용. 외부에서 동일한 엔진을 재사용해야 할 때만 직접 import.
|
|
12
|
+
|
|
13
|
+
## sdAngularPlugin
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { sdAngularPlugin, type SdAngularPluginOptions } from "@simplysm/sd-cli";
|
|
17
|
+
|
|
18
|
+
// vitest.config.ts
|
|
19
|
+
plugins: [sdAngularPlugin({ pkg: "angular" })]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`pkg` 는 `sd.config.ts.packages` 키 (= `packages/<pkg>/` 디렉토리명). 패키지의 `.ts` 를 AOT 컴파일해 `transform` 훅에서 JS 로 치환한다. `tsconfig.json` 의 `angularCompilerOptions` 유무로 Angular 모드를 자동 감지. Vitest watch 의 `watchChange` 를 받아 증분 재컴파일. 첫 `buildStart` 전에 `config()` 호출 필수 (Vitest 가 자동 호출).
|
|
23
|
+
|
|
24
|
+
## SdTsCompiler
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { SdTsCompiler } from "@simplysm/sd-cli";
|
|
28
|
+
|
|
29
|
+
const compiler = new SdTsCompiler({
|
|
30
|
+
pkgDir: "/abs/path/to/packages/foo",
|
|
31
|
+
cwd: "/abs/path/to/workspace",
|
|
32
|
+
output: { js: true, dts: false }, // 출력 제어 — 둘 다 false 면 typecheck only
|
|
33
|
+
includeTests: false, // true 면 tests/ 도 rootNames 에 포함
|
|
34
|
+
lint: false,
|
|
35
|
+
globalScss: false,
|
|
36
|
+
});
|
|
37
|
+
const result = await compiler.compileAsync(/* modifiedFiles? */);
|
|
38
|
+
// result.diagnostics, result.errorCount, result.emitResults (Angular), ...
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
특징:
|
|
42
|
+
- 인스턴스를 재사용해 호출 간 incremental 빌드 (`tsBuildInfoFile` 은 `<pkgDir>/.cache/` 하위).
|
|
43
|
+
- `compileAsync(modifiedFiles)` 의 modifiedFiles 는 watch 모드의 변경 파일. 미전달 시 전체 affected 탐색.
|
|
44
|
+
- Angular 패키지(`tsconfig.angularCompilerOptions`)는 자동으로 NgtscProgram 사용. 결과의 `emitResults: { filename, contents, sourceFileName }[]` 를 호출자가 디스크/번들러에 전달. Non-Angular 은 `host.writeFile` 로 디스크에 직접 emit (결과의 `emitResults` undefined).
|
|
45
|
+
- `compilerOptionsTransformer` 로 target/module/outDir 등을 후처리 override 가능.
|
|
46
|
+
- `transformStylesheet`, `externalStylesheets`, `sourceFileCache` 는 Angular 클라이언트 빌드 통합용 (esbuild 플러그인이 사용).
|
|
47
|
+
- 단계별 try/catch 로 부분 복구 — 한 단계 실패해도 다른 진단/emit 결과는 유지.
|
|
48
|
+
- 결과의 `affectedFiles` 가 `undefined` 면 전역 변경 (전체 리빌드 신호).
|
|
49
|
+
|
|
50
|
+
전체 옵션·결과 필드 정의는 `packages/sd-cli/src/ts-compiler/sd-ts-compiler-options.ts`, `sd-ts-compiler-result.ts` 참조.
|