@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,64 @@
|
|
|
1
|
+
## @simplysm/core-node — consola
|
|
2
|
+
|
|
3
|
+
`consola` 전역 인스턴스 셋업 + 컬러 콘솔 리포터 + JSON 파일 회전 리포터. Node 앱(서버·CLI) 진입점에서 `setupConsola()` 1회 호출하면 환경에 맞게 reporter 가 구성됨.
|
|
4
|
+
|
|
5
|
+
### setupConsola
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
interface SetupConsolaOptions { cli?: boolean; }
|
|
9
|
+
setupConsola(opts?: SetupConsolaOptions): void;
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
- `cli: true` 또는 `env.DEV` 가 truthy → dev 모드.
|
|
13
|
+
- `SD_DEBUG` truthy: `PrettyReporter` 하나만, debug 까지.
|
|
14
|
+
- 아니면: `createFileReporter()` + `withMaxLevel(new PrettyReporter(), LogLevels.info)` — 파일에는 debug 까지, 콘솔에는 info 이상만.
|
|
15
|
+
- 그 외 (prod): `createFileReporter()` 하나만, debug 까지.
|
|
16
|
+
|
|
17
|
+
모든 경로에서 `consola.level = LogLevels.debug`.
|
|
18
|
+
|
|
19
|
+
### PrettyReporter
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
class PrettyReporter implements ConsolaReporter {}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- 색상 자동 감지: `NO_COLOR` 있으면 off, `FORCE_COLOR` 있으면 on, TTY 면 on, win32 면 on.
|
|
26
|
+
- 타입별 아이콘/색 (info=cyan, success/ready=green, warn=yellow, error/fatal/fail=red, start=magenta, debug=gear, trace=arrow).
|
|
27
|
+
- `logObj.type === "box"` 면 `> tag`, `> title`, `> 각 줄` 형태로 박스 렌더.
|
|
28
|
+
- `logObj.tag !== ""` 면 `[tag]` 가 회색으로 prefix.
|
|
29
|
+
- level < 2 (error/fatal/warn) 는 `stderr`, 그 외 `stdout` 으로 출력. 추가로 badge 처리(앞뒤 빈 줄).
|
|
30
|
+
- args 중 `Error.stack` 가진 객체는 재귀적으로 cause 체인까지 풀어서 stack 정리 (cwd 제거, `file://` 제거, 들여쓰기).
|
|
31
|
+
- `type === "trace"` 면 즉시 stack 첨부.
|
|
32
|
+
|
|
33
|
+
### createFileReporter
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
interface FileReporterOptions {
|
|
37
|
+
maxSize?: number; // default 20MB
|
|
38
|
+
maxDays?: number; // default 14
|
|
39
|
+
}
|
|
40
|
+
createFileReporter(options?: FileReporterOptions): ConsolaReporter;
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- 출력 디렉토리: `<cwd>/.logs` (자동 mkdir).
|
|
44
|
+
- 파일명: `app.<YYYY-MM-DD>.log` → 크기 초과 시 `app.<YYYY-MM-DD>.<n>.log` 로 순번.
|
|
45
|
+
- 로그 1줄 = JSON: `{ time(ISO), level, tag?, err?: {message,stack}, msg? }`. `Error` arg 는 `err` 필드로, 그 외는 모두 `String` 화 후 공백 조인되어 `msg`.
|
|
46
|
+
- 날짜 바뀌면 회전 + 그날 첫 write 에서 `maxDays` 이전 `app.YYYY-MM-DD.*.log` 정리.
|
|
47
|
+
|
|
48
|
+
### withMaxLevel
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
withMaxLevel(reporter: ConsolaReporter, maxLevel: number): ConsolaReporter;
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`logObj.level > maxLevel` 인 항목을 drop. `setupConsola` 가 dev 콘솔 리포터에 `LogLevels.info` 로 적용.
|
|
55
|
+
|
|
56
|
+
### 사용 예
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { setupConsola } from "@simplysm/core-node";
|
|
60
|
+
|
|
61
|
+
setupConsola({ cli: true }); // 진입점 1회
|
|
62
|
+
consola.info("server started");
|
|
63
|
+
consola.withTag("db").debug({ sql, params });
|
|
64
|
+
```
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
## @simplysm/core-node — cpx
|
|
2
|
+
|
|
3
|
+
`import { cpx } from "@simplysm/core-node"` — 자식 프로세스 spawn + 시스템 인코딩 감지. Windows `chcp` 코드 페이지 또는 POSIX `LANG/LC_ALL` 의 charset 부분을 보고 stdout/stderr 를 적절히 디코딩.
|
|
4
|
+
|
|
5
|
+
### 인코딩 감지
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
cpx.getSystemEncoding(): string // 최초 1회 감지 후 모듈 캐시
|
|
9
|
+
cpx.resetEncodingCache(): void
|
|
10
|
+
cpx.codePageToEncoding(codePage: number): string // 65001→utf-8, 949→euc-kr, 932→shift-jis, 936→gbk, 950→big5, 1252/1251/1250/874→windows-* / 그 외 utf-8
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
감지 실패 시 `utf-8` fallback.
|
|
14
|
+
|
|
15
|
+
### 디코딩
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
cpx.decodeBytes(raw: Uint8Array, systemEncoding?: string): string
|
|
19
|
+
// utf-8 이면 바로 디코딩.
|
|
20
|
+
// 그 외 인코딩이면 먼저 utf-8 strict 시도 → 실패 시 systemEncoding 으로 fallback.
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### spawn / spawnSync
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
interface SpawnResult { stdout: string; stderr: string; exitCode: number; }
|
|
27
|
+
|
|
28
|
+
cpx.spawn(cmd, args, opts?: SpawnOptions & { reject?: boolean }): SpawnProcess
|
|
29
|
+
cpx.spawnSync(cmd, args, opts?: SpawnSyncOptions & { reject?: boolean }): SpawnResult
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- 기본 `stdio: "pipe"`. `process.env` 와 `opts.env` 머지해 자식에 전달.
|
|
33
|
+
- stdout/stderr 가 pipe 면 모아서 `decodeBytes` 로 문자열화.
|
|
34
|
+
- `exitCode !== 0` 이고 `reject !== false` 면 throw (`Command failed: <cmd> <args>`).
|
|
35
|
+
- `cpx.spawn` 은 `SpawnProcess` 반환 (PromiseLike + `pid` + `kill(signal?)`).
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
const r = await cpx.spawn("git", ["status", "--porcelain"]);
|
|
39
|
+
console.log(r.stdout);
|
|
40
|
+
|
|
41
|
+
const proc = cpx.spawn("pnpm", ["watch"], { reject: false });
|
|
42
|
+
process.on("SIGINT", () => proc.kill());
|
|
43
|
+
const { exitCode } = await proc;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### resolveStdioPipe
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
cpx.resolveStdioPipe(stdio): { stdout: boolean; stderr: boolean }
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
stdio 값(`"pipe"`, `"inherit"`, 배열, `undefined`)에서 stdout/stderr 각각 pipe 여부 판정. spawn 자체가 내부 사용하므로 사용자 호출 거의 없음.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
## @simplysm/core-node — FsWatcher
|
|
2
|
+
|
|
3
|
+
chokidar 래퍼. 짧은 시간 내 이벤트를 병합해서 콜백 1회만 호출하고, Windows 의 EPERM (감시 디렉토리 사라짐 등) 발생 시 watcher 자동 재시작. 모듈 로드 시 `fs.FSWatcher.prototype.emit` 을 한 번 패치해서, listener 없는 인스턴스의 orphan `error` 이벤트로 인한 uncaughtException 도 swallow.
|
|
4
|
+
|
|
5
|
+
### 시그니처
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
type FsWatcherEvent = "add" | "addDir" | "change" | "unlink" | "unlinkDir";
|
|
9
|
+
|
|
10
|
+
interface FsWatcherChangeInfo {
|
|
11
|
+
event: FsWatcherEvent;
|
|
12
|
+
path: PosixPath; // 항상 슬래시 경로
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
class FsWatcher {
|
|
16
|
+
static watch(paths: string[], options?: chokidar.ChokidarOptions): Promise<FsWatcher>;
|
|
17
|
+
|
|
18
|
+
onChange(
|
|
19
|
+
opt: { delay?: number },
|
|
20
|
+
cb: (changes: FsWatcherChangeInfo[]) => void | Promise<void>,
|
|
21
|
+
): this;
|
|
22
|
+
|
|
23
|
+
close(): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 동작 디테일
|
|
28
|
+
|
|
29
|
+
- `paths` 의 각 원소에서 glob 메타문자(`* ? { [ ]`) 이전 부분을 `chokidar.watch` 대상 디렉토리로 추출하고, 실제 변경 알림은 원래 패턴에 대해 `minimatch(path, p, { dot: true })` 또는 `minimatch(path, p + "/**")` 매칭만 통과.
|
|
30
|
+
- 항상 `ignoreInitial: true` 로 chokidar 호출. 사용자가 `options.ignoreInitial: false` 를 주면 첫 콜백을 빈 배열로 1회 호출 (실제 파일 목록은 포함하지 않음 — 이벤트 병합 모델과의 충돌 방지).
|
|
31
|
+
- `onChange` 의 `delay` 로 `DebounceQueue` 생성. 윈도우 내 같은 파일의 이벤트는 lookup 테이블로 병합:
|
|
32
|
+
- `add+change` → `add`
|
|
33
|
+
- `add+unlink` → 제거 (생성 직후 삭제 상쇄)
|
|
34
|
+
- `addDir+unlinkDir` → 제거
|
|
35
|
+
- `unlink+add` → `add`
|
|
36
|
+
- `unlink+change` → `change`
|
|
37
|
+
- `unlinkDir+addDir` → `addDir`
|
|
38
|
+
- 미정의 조합은 뒤 이벤트로 덮어쓰기.
|
|
39
|
+
- `error` 의 code 가 `EPERM` 이면 watcher 종료 → 1초 대기 → 재생성 → 등록된 모든 핸들러 재부착 → ready 대기. 최대 3회 시도 후 포기 (에러 로그만).
|
|
40
|
+
|
|
41
|
+
### 사용 예
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
const watcher = await FsWatcher.watch(["src/**/*.ts", "tests/**/*.ts"]);
|
|
45
|
+
watcher.onChange({ delay: 300 }, (changes) => {
|
|
46
|
+
for (const { event, path } of changes) {
|
|
47
|
+
consola.info(`${event}: ${path}`);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// 종료
|
|
52
|
+
await watcher.close();
|
|
53
|
+
```
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
## @simplysm/core-node — fsx
|
|
2
|
+
|
|
3
|
+
`import { fsx } from "@simplysm/core-node"` — 파일/디렉토리 IO 헬퍼. 동기·비동기 쌍으로 제공. 모든 함수는 오류를 `SdError(원본, targetPath)` 로 wrap 해서 throw.
|
|
4
|
+
|
|
5
|
+
### 존재/생성/삭제
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
fsx.existsSync(p): boolean
|
|
9
|
+
fsx.exists(p): Promise<boolean>
|
|
10
|
+
fsx.mkdirSync(p): void // recursive
|
|
11
|
+
fsx.mkdir(p): Promise<void> // recursive
|
|
12
|
+
fsx.rmSync(p): void // recursive, force, 재시도 없음
|
|
13
|
+
fsx.rm(p): Promise<void> // recursive, force, 6회/500ms 재시도 (파일 잠금 대응)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
동기 rm 은 재시도 없음 — Windows 잠금 가능성 있으면 비동기 `rm` 사용.
|
|
17
|
+
|
|
18
|
+
### 복사
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
fsx.copySync(src, dst, filter?): void
|
|
22
|
+
fsx.copy(src, dst, filter?): Promise<void>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- `src` 없으면 no-op.
|
|
26
|
+
- `filter(absolutePath): boolean` — 각 하위 항목 절대 경로로 호출. 최상위 `src` 자체는 필터 대상 아님. 디렉토리에 false 반환 시 그 하위 전체 스킵.
|
|
27
|
+
- 파일 복사 6회/500ms 재시도 (sync 는 busy-wait).
|
|
28
|
+
|
|
29
|
+
### 읽기/쓰기
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
fsx.readSync(p): string // utf-8
|
|
33
|
+
fsx.read(p): Promise<string>
|
|
34
|
+
fsx.readBytesSync(p): Uint8Array
|
|
35
|
+
fsx.readBytes(p): Promise<Uint8Array>
|
|
36
|
+
fsx.readJsonSync<T>(p): T // @simplysm/core-common json.parse
|
|
37
|
+
fsx.readJson<T>(p): Promise<T>
|
|
38
|
+
|
|
39
|
+
fsx.writeSync(p, data: string|Uint8Array): void // 상위 디렉토리 자동 생성, flush:true
|
|
40
|
+
fsx.write(p, data): Promise<void>
|
|
41
|
+
fsx.writeJsonSync(p, data, { replacer?, space? }?): void
|
|
42
|
+
fsx.writeJson(p, data, { replacer?, space? }?): Promise<void>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
JSON 파싱 실패 시 `SdError` 메시지에 파일 경로 + 본문 500자 미리보기 포함.
|
|
46
|
+
|
|
47
|
+
### 디렉토리/정보
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
fsx.readdirSync(p): string[]
|
|
51
|
+
fsx.readdir(p): Promise<string[]>
|
|
52
|
+
fsx.statSync(p): fs.Stats // 심볼릭 링크 따라감
|
|
53
|
+
fsx.stat(p): Promise<fs.Stats>
|
|
54
|
+
fsx.lstatSync(p): fs.Stats // 심볼릭 링크 따라가지 않음
|
|
55
|
+
fsx.lstat(p): Promise<fs.Stats>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Glob / 트리 유틸
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
fsx.globSync(pattern, options?: GlobOptions): string[] // 항상 절대 경로, 백슬래시 → 슬래시
|
|
62
|
+
fsx.glob(pattern, options?): Promise<string[]>
|
|
63
|
+
|
|
64
|
+
fsx.clearEmptyDirectory(dirPath): Promise<void> // 빈 디렉토리 재귀 삭제
|
|
65
|
+
|
|
66
|
+
fsx.findAllParentChildPathsSync(childGlob, fromPath, rootPath?): string[]
|
|
67
|
+
fsx.findAllParentChildPaths(childGlob, fromPath, rootPath?): Promise<string[]>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`findAllParentChildPaths*`: `fromPath` 에서 루트 방향으로 부모를 순회하며 각 디렉토리에 `childGlob` 적용. `rootPath` 미지정 또는 `fromPath` 가 `rootPath` 하위가 아니면 파일 시스템 루트까지 진행. `pnpm-workspace.yaml` 같은 ancestor 설정 파일 탐색에 사용.
|
|
71
|
+
|
|
72
|
+
사용 예:
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import { fsx } from "@simplysm/core-node";
|
|
76
|
+
|
|
77
|
+
await fsx.mkdir(path.resolve(out, "dist"));
|
|
78
|
+
const tsFiles = await fsx.glob("src/**/*.ts");
|
|
79
|
+
const cfg = await fsx.readJson<MyConfig>("sd.config.json");
|
|
80
|
+
await fsx.copy(src, dst, (p) => !p.includes(`${path.sep}node_modules${path.sep}`));
|
|
81
|
+
```
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
## @simplysm/core-node — pathx
|
|
2
|
+
|
|
3
|
+
`import { pathx } from "@simplysm/core-node"` — 경로 변환·비교 유틸. POSIX 스타일 통일과 cwd 기준 target 필터링용.
|
|
4
|
+
|
|
5
|
+
### PosixPath 브랜드 타입
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
type PosixPath = string & { [POSIX]: never };
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`posix()` 또는 `posixResolve()` 결과에만 부여. 슬래시 경로임을 타입으로 보장.
|
|
12
|
+
|
|
13
|
+
### 변환
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
pathx.posix(p: string): PosixPath
|
|
17
|
+
// 백슬래시 → 슬래시 만. resolve 안 함.
|
|
18
|
+
// posix("C:\\Users\\test") === "C:/Users/test"
|
|
19
|
+
|
|
20
|
+
pathx.posixResolve(...args: string[]): PosixPath
|
|
21
|
+
// path.resolve 후 슬래시화. 항상 절대 경로.
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 비교/판정
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
pathx.isChildPath(child, parent): boolean
|
|
28
|
+
// posixResolve 정규화 후 비교. 동일 경로면 false.
|
|
29
|
+
|
|
30
|
+
pathx.changeFileDirectory(filePath, fromDir, toDir): string
|
|
31
|
+
// filePath 의 fromDir 부분을 toDir 로 치환.
|
|
32
|
+
// filePath === fromDir 이면 toDir 반환.
|
|
33
|
+
// filePath 가 fromDir 하위가 아니면 ArgumentError throw.
|
|
34
|
+
|
|
35
|
+
pathx.basenameWithoutExt(filePath): string
|
|
36
|
+
// path.basename(p, path.extname(p)). "a/b/c.spec.ts" → "c.spec"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### target 필터링
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
pathx.filterByTargets(files: string[], targets: string[], cwd: string): string[]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- `targets` 가 비면 `files` 그대로 반환.
|
|
46
|
+
- 각 `target` 은 cwd 기준 상대 경로 (POSIX 권장).
|
|
47
|
+
- `files` 각 원소를 cwd 기준 상대 POSIX 로 변환 후 `relative === target || relative.startsWith(target + "/")` 매칭.
|
|
48
|
+
- `files` 는 cwd 하위 절대 경로 가정 — 외부 경로는 `../` 로 변환되어 매칭에서 빠짐.
|
|
49
|
+
|
|
50
|
+
CLI 의 `-t <project>` 처럼 사용자 지정 부분 경로로 후보를 좁힐 때 사용.
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
const files = ["/proj/src/a.ts", "/proj/tests/c.ts"];
|
|
54
|
+
pathx.filterByTargets(files, ["src"], "/proj"); // ["/proj/src/a.ts"]
|
|
55
|
+
```
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
## @simplysm/core-node — Worker
|
|
2
|
+
|
|
3
|
+
`worker_threads` 위의 타입 안전 RPC. 워커 측에서 `createWorker(methods)` 로 default export 하면, 메인 측에서 `Worker.create<typeof import("./worker")>(path)` 로 메서드 직접 호출 + 이벤트 수신 가능한 Proxy 를 얻는다. 메시지 인코딩은 `@simplysm/core-common` 의 `transfer.encode/decode` 사용 (Uint8Array 등 transferable 자동 처리).
|
|
4
|
+
|
|
5
|
+
### 타입
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
interface WorkerModule {
|
|
9
|
+
default: {
|
|
10
|
+
__methods: Record<string, (...args: any[]) => unknown>;
|
|
11
|
+
__events: Record<string, unknown>;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type PromisifyMethods<T> = {
|
|
16
|
+
[K in keyof T]: T[K] extends (...args: infer P) => infer R
|
|
17
|
+
? (...args: P) => Promise<Awaited<R>>
|
|
18
|
+
: never;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type WorkerProxy<TModule extends WorkerModule> =
|
|
22
|
+
PromisifyMethods<TModule["default"]["__methods"]> & {
|
|
23
|
+
on<E extends keyof TModule["default"]["__events"] & string>(
|
|
24
|
+
event: E, listener: (data: TModule["default"]["__events"][E]) => void,
|
|
25
|
+
): void;
|
|
26
|
+
off<E extends keyof TModule["default"]["__events"] & string>(event: E, listener): void;
|
|
27
|
+
terminate(): Promise<void>;
|
|
28
|
+
};
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
메서드는 항상 `Promise<Awaited<R>>` 로 노출. `on`/`off`/`terminate` 는 예약어 — 워커 메서드명으로 사용 금지.
|
|
32
|
+
|
|
33
|
+
### Worker.create (메인 측)
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
Worker.create<TModule extends WorkerModule>(
|
|
37
|
+
filePath: string,
|
|
38
|
+
opt?: Omit<WorkerOptions, "stdout" | "stderr">,
|
|
39
|
+
): WorkerProxy<TModule>;
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
- `filePath`: `file://` URL 또는 절대 경로.
|
|
43
|
+
- 실행 모드는 `import.meta.filename` 확장자로 결정:
|
|
44
|
+
- `.ts` (개발/tsx) → 내부 `lib/worker-dev-proxy.js` 를 띄우고 워커 파일을 argv 로 전달, tsx 로 동적 로드.
|
|
45
|
+
- `.js` (프로덕션) → 워커 파일을 그대로 `new Worker(workerPath, ...)`.
|
|
46
|
+
- 항상 `stdout: true, stderr: true` 로 워커 띄우고 메인의 stdout/stderr 로 pipe. 워커 내부의 `process.stdout.write` 도 메시지 프로토콜(`type: "log"`)로 메인에 전달되어 그대로 stdout 에 출력 — 워커의 `console.log` 가 메인 터미널에 보임.
|
|
47
|
+
- `opt.env` 는 `process.env` 와 머지되어 워커에 전달.
|
|
48
|
+
- 워커 비정상 종료(`exit code !== 0`) 또는 `error` 발생 시 대기 중 모든 호출이 reject. `terminate()` 호출 시에도 in-flight 요청은 모두 reject.
|
|
49
|
+
|
|
50
|
+
### createWorker (워커 측)
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
function createWorker<
|
|
54
|
+
TMethods extends Record<string, (...args: any[]) => unknown>,
|
|
55
|
+
TEvents extends Record<string, unknown> = Record<string, never>,
|
|
56
|
+
>(methods: TMethods): {
|
|
57
|
+
send<E extends keyof TEvents & string>(event: E, data?: TEvents[E]): void;
|
|
58
|
+
__methods: TMethods;
|
|
59
|
+
__events: TEvents;
|
|
60
|
+
};
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- 워커 스레드에서만 호출 (`parentPort == null` 이면 `SdError` throw).
|
|
64
|
+
- `methods` 의 각 함수는 메인에서 `worker.<name>(...args)` 로 호출되어 결과/throw 가 그대로 전달됨. async 함수도 await 처리됨.
|
|
65
|
+
- 알 수 없는 메서드/잘못된 메시지 형식 호출 시 `SdError` 로 응답.
|
|
66
|
+
- 반환값 객체에 `send(event, data?)` 가 있어 워커 → 메인 단방향 이벤트 가능. `TEvents` 제네릭으로 이벤트 이름·페이로드 타입 보장. 반환값은 반드시 `export default` 해야 메인의 `typeof import(...)` 추론이 동작.
|
|
67
|
+
|
|
68
|
+
### WorkerRequest / WorkerResponse
|
|
69
|
+
|
|
70
|
+
내부 메시지 프로토콜 (사용자가 직접 다룰 일 없음).
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
interface WorkerRequest { id: string; method: string; params: unknown[]; }
|
|
74
|
+
|
|
75
|
+
type WorkerResponse =
|
|
76
|
+
| { request: WorkerRequest; type: "return"; body?: unknown }
|
|
77
|
+
| { request: WorkerRequest; type: "error"; body: Error }
|
|
78
|
+
| { type: "event"; event: string; body?: unknown }
|
|
79
|
+
| { type: "log"; body: string };
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 사용 예
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
// worker.ts
|
|
86
|
+
import { createWorker } from "@simplysm/core-node";
|
|
87
|
+
|
|
88
|
+
interface Events { progress: number; }
|
|
89
|
+
|
|
90
|
+
const methods = {
|
|
91
|
+
async heavy(x: number) {
|
|
92
|
+
sender.send("progress", 50);
|
|
93
|
+
return x * 2;
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const sender = createWorker<typeof methods, Events>(methods);
|
|
98
|
+
export default sender;
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
// main.ts
|
|
103
|
+
import { Worker } from "@simplysm/core-node";
|
|
104
|
+
|
|
105
|
+
const worker = Worker.create<typeof import("./worker")>(
|
|
106
|
+
new URL("./worker.ts", import.meta.url).href,
|
|
107
|
+
);
|
|
108
|
+
worker.on("progress", (p) => consola.info(`${p}%`));
|
|
109
|
+
const result = await worker.heavy(21); // 42
|
|
110
|
+
await worker.terminate();
|
|
111
|
+
```
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# @simplysm/excel
|
|
2
|
+
|
|
3
|
+
OOXML(xlsx) 워크북을 lazy-load 로 읽고 쓰는 클래스 묶음. ZIP 내부 XML 을 접근 시점에만 파싱한다.
|
|
4
|
+
|
|
5
|
+
## 사용 트리거 인덱스
|
|
6
|
+
- **`ExcelWorkbook`** — xlsx 바이트/Blob 을 열거나 새 워크북을 만들 때. 사용 후 `close()` 필수.
|
|
7
|
+
- **`ExcelWorksheet`** — 시트 단위로 셀/행/열 접근, 데이터테이블 입출력, 틀 고정/줌, 조건부 서식, 이미지 삽입.
|
|
8
|
+
- **`ExcelCell` / `ExcelRow` / `ExcelCol`** — 단일 셀 값·수식·스타일·병합, 행/열 전체 셀 일괄 접근, 열 너비.
|
|
9
|
+
- **`ExcelWrapper`** — Zod 스키마로 헤더·타입을 정의해 레코드 배열로 read/write.
|
|
10
|
+
- **`ExcelUtils`** — `"A1"`↔좌표, 범위 주소, Excel 직렬 날짜 ↔ 타임스탬프, numFmt 변환.
|
|
11
|
+
- **타입 (`ExcelValueType`, `ExcelStyleOptions`, `ExcelFont`, `ExcelConditionalRule` 등)** — 입력 옵션·반환값 정의.
|
|
12
|
+
|
|
13
|
+
## ExcelWorkbook
|
|
14
|
+
```typescript
|
|
15
|
+
new ExcelWorkbook(arg?: Blob | Bytes)
|
|
16
|
+
getWorksheetNames(): Promise<string[]>
|
|
17
|
+
addWorksheet(name): Promise<ExcelWorksheet>
|
|
18
|
+
getWorksheet(nameOrIndex: string | number): Promise<ExcelWorksheet> // 인덱스 0 기반
|
|
19
|
+
setDefaultStyle(opts: ExcelStyleOptions): Promise<void> // cellXfs[0] 덮어쓰기
|
|
20
|
+
toBytes(): Promise<Bytes>
|
|
21
|
+
toBlob(): Promise<Blob> // xlsx MIME
|
|
22
|
+
close(): Promise<void> // 멱등, 이후 모든 메서드는 throw
|
|
23
|
+
```
|
|
24
|
+
패턴: `const wb = new ExcelWorkbook(bytes); try { ... } finally { await wb.close(); }`. 인자 생략 시 빈 워크북.
|
|
25
|
+
|
|
26
|
+
## ExcelWorksheet
|
|
27
|
+
```typescript
|
|
28
|
+
getName() / setName(newName)
|
|
29
|
+
row(r) / col(c) / cell(r, c) // 모두 0 기반, 동기 반환
|
|
30
|
+
getRange(): Promise<ExcelAddressRangePoint>
|
|
31
|
+
getCells(): Promise<ExcelCell[][]> // 전체 2D
|
|
32
|
+
getDataTable(opt?: { headerRowIndex?; checkEndColIndex?; usableHeaderNameFn? })
|
|
33
|
+
// 레코드 배열. 중복 헤더면 throw
|
|
34
|
+
setDataMatrix(matrix: ExcelValueType[][]) // 0,0 부터
|
|
35
|
+
setRecords(records: Record<string, ExcelValueType>[]) // 첫 행 헤더 자동
|
|
36
|
+
copyCell / copyRow / copyCellStyle / copyRowStyle / insertCopyRow
|
|
37
|
+
setZoom(percent) / freezeAt({ r?, c? })
|
|
38
|
+
addConditionalFormat({ ref, rules: ExcelConditionalRule[] }) // 호출마다 priority 누적
|
|
39
|
+
addImage({ bytes, ext, from, to? }) // ext 는 mime lookup. to 생략 시 from+1,+1
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## ExcelCell / ExcelRow / ExcelCol
|
|
43
|
+
```typescript
|
|
44
|
+
// ExcelCell
|
|
45
|
+
cell.addr // { r, c }
|
|
46
|
+
getValue() / setValue(val: ExcelValueType) // string/number/boolean/DateOnly/DateTime/Time/undefined
|
|
47
|
+
getFormula() / setFormula(val) // 셀 타입 "str" 로 설정
|
|
48
|
+
merge(endR, endC) // 현재 셀부터 (endR,endC) 까지
|
|
49
|
+
getStyleId() / setStyleId(id)
|
|
50
|
+
setStyle(opts: ExcelStyleOptions) // 기존 스타일에 clone-merge
|
|
51
|
+
|
|
52
|
+
// ExcelRow / ExcelCol
|
|
53
|
+
row.cell(c) / col.cell(r)
|
|
54
|
+
row.getCells() / col.getCells()
|
|
55
|
+
col.setWidth(size)
|
|
56
|
+
```
|
|
57
|
+
값 setter 에 `undefined` → 셀 삭제. Date/Time 계열은 numFmt 자동 설정.
|
|
58
|
+
|
|
59
|
+
## ExcelWrapper
|
|
60
|
+
```typescript
|
|
61
|
+
new ExcelWrapper(schema: z.ZodObject) // .describe() 가 Excel 헤더명
|
|
62
|
+
read(file, wsNameOrIndex = 0, { excludes? }?): Promise<z.infer<S>[]> // 내부에서 워크북 close
|
|
63
|
+
write(wsName, records, { excludes? }?): Promise<ExcelWorkbook> // 호출자가 close 필수
|
|
64
|
+
```
|
|
65
|
+
write: 모든 셀 테두리, 필수(non-optional/nullable/default) 비-boolean 필드 헤더는 노란 배경, 첫 행 freeze, 줌 85%.
|
|
66
|
+
|
|
67
|
+
## ExcelUtils
|
|
68
|
+
```typescript
|
|
69
|
+
stringifyAddr({r,c}) / parseCellAddr("B3") // {r:2,c:1}
|
|
70
|
+
stringifyColAddr(0) // "A" parseColAddr("AA") // 26
|
|
71
|
+
stringifyRangeAddr / parseRangeAddr("A1:C3")
|
|
72
|
+
convertTimeTickToNumber(tick) / convertNumberToTimeTick(serial) // Excel 1899-12-30 기준
|
|
73
|
+
convertNumFmtIdToName / convertNumFmtCodeToName / convertNumFmtNameToId
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## 타입 요약
|
|
77
|
+
- `ExcelValueType` = `number | string | DateOnly | DateTime | Time | boolean | undefined`.
|
|
78
|
+
- `ExcelStyleOptions`: `background`(ARGB 8자리), `border: ExcelBorderPosition[]`, `horizontalAlign`, `verticalAlign`, `numberFormat` (`"number"|"string"|"DateOnly"|"DateTime"|"Time"`), `numberFormatCode` (커스텀, 우선), `font: ExcelFont`.
|
|
79
|
+
- `ExcelFont`: `size, family, bold, italic, underline, color(ARGB), strike`. 미지정 속성은 OOXML 에 emit 안 됨 → Excel 기본값.
|
|
80
|
+
- `ExcelConditionalRule`: `{type:"cellIs", op, value, style}` | `{type:"text", op:"contains"|"notContains"|"beginsWith"|"endsWith", value, style}` | `{type:"expression", formula, style}`. `style` = `ExcelConditionalRuleStyle` (`background`, `fontColor`, `fontWeight`).
|
|
81
|
+
- `ExcelAddressPoint = {r,c}` / `ExcelAddressRangePoint = {s,e}` 모두 0 기반.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# @simplysm/lint
|
|
2
|
+
|
|
3
|
+
Simplysm 컨벤션용 ESLint 플러그인 패키지. 커스텀 규칙 묶음(`./eslint-plugin`)과 typescript-eslint·angular-eslint 통합 flat config 프리셋(`./eslint-recommended`)을 제공한다.
|
|
4
|
+
|
|
5
|
+
## 사용 트리거 인덱스
|
|
6
|
+
|
|
7
|
+
- **`./eslint-recommended` (default export)** — 프로젝트 `eslint.config.{js,mjs,cjs}` 에서 그대로 spread 해 simplysm 표준 lint 규칙을 적용할 때.
|
|
8
|
+
- **`./eslint-plugin` (default export)** — recommended 를 사용하지 않고 개별 규칙만 골라 쓰거나, 다른 flat config 에서 `@simplysm/<rule>` 로 참조할 때.
|
|
9
|
+
|
|
10
|
+
## `./eslint-recommended`
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
// eslint.config.mjs
|
|
14
|
+
import recommended from "@simplysm/lint/eslint-recommended";
|
|
15
|
+
export default recommended;
|
|
16
|
+
// 또는 추가 config 와 함께
|
|
17
|
+
export default [...recommended, { /* overrides */ }];
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`typescript-eslint.config(...)` 결과(flat config 배열). 다음을 합쳐 export 한다:
|
|
21
|
+
|
|
22
|
+
- `ignores`: `**/node_modules/**`, `**/dist/**`, `**/.*/**` (디렉터리 단위 스킵).
|
|
23
|
+
- `**/*.{js,mjs,cjs}` 블록: globals=node, 플러그인 `import`/`@simplysm`/`unused-imports`, `import/no-extraneous-dependencies` 예외 경로 = `**/lib/**`, `**/eslint.config.{js,cjs,mjs}`, `**/simplysm.{js,cjs,mjs}`, `**/vitest.config.{js,cjs,mjs}`.
|
|
24
|
+
- `angular.configs.tsRecommended` + `**/*.ts` 블록: `tseslint.parser` + `parserOptions.project: true`, `angular.processInlineTemplates` processor, `eslint-import-resolver-typescript` resolver(`alwaysTryTypes: true`).
|
|
25
|
+
- `**/*.html` 블록: `angular.configs.templateRecommended` + `templateAccessibility` extends, `@angular-eslint/template/eqeqeq` 는 `allowNullOrUndefined: true`, `label-has-associated-control` off, `template/no-any` error.
|
|
26
|
+
- `**/tests/**/*.ts` override: `no-console`, `import/no-extraneous-dependencies`, `@simplysm/ts-no-throw-not-implemented-error` off.
|
|
27
|
+
- `**/vitest.config.ts` override: `no-restricted-properties` off (vitest 가 `process` 접근 필요).
|
|
28
|
+
|
|
29
|
+
공통으로 강제되는 simplysm 컨벤션:
|
|
30
|
+
|
|
31
|
+
- `Buffer`/`buffer`/`events`/`eventemitter3` 금지 → `Uint8Array`/`@simplysm/core-common` 사용 유도.
|
|
32
|
+
- `process.env`/`import.meta.env` 직접 접근 금지 → `env("...")` 호출 강제. `env("NODE_ENV")` 자체 금지.
|
|
33
|
+
- `=== undefined` / `!== undefined` 금지 → `== null` / `!= null` 통일.
|
|
34
|
+
- TS 블록 전용: `naming-convention` 으로 `private` 멤버에 leading underscore(`_foo`) 강제, `strict-boolean-expressions` (nullable boolean/object 허용), `ban-ts-comment` (`ts-expect-error` 는 3자 이상 설명 필수), `only-throw-error`, `no-floating-promises` 등.
|
|
35
|
+
|
|
36
|
+
## `./eslint-plugin`
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
// eslint.config.mjs
|
|
40
|
+
import simplysm from "@simplysm/lint/eslint-plugin";
|
|
41
|
+
export default [{
|
|
42
|
+
plugins: { "@simplysm": simplysm },
|
|
43
|
+
rules: { "@simplysm/no-hard-private": "error" },
|
|
44
|
+
}];
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`{ rules: { ... } }` 형태의 ESLint 플러그인 객체. 노출 규칙(전부 `@simplysm/<name>` 으로 참조):
|
|
48
|
+
|
|
49
|
+
### `ng-no-async-effect` (problem)
|
|
50
|
+
`@angular/core`에서 import 한 `effect()` 1번째 인자가 async 함수면 보고. named/aliased/namespace import 모두 추적. `await` 이후 signal read 가 의존성 추적 밖으로 빠지는 문제 방지. 안내: 비동기 작업은 `void untracked(async () => { ... })` 로 감쌀 것.
|
|
51
|
+
|
|
52
|
+
### `ng-template-no-strict-null-check` (problem)
|
|
53
|
+
HTML 템플릿 바인딩에서 `=== null|undefined`, `!== null|undefined` 사용 시 보고. `== null`/`!= null` 로 통일 유도. autofix 없음(인라인 템플릿 offset 매핑 문제).
|
|
54
|
+
|
|
55
|
+
### `ng-template-no-todo-comments` (problem, recommended=warn)
|
|
56
|
+
HTML 주석 `<!-- TODO: ... -->` 를 정규식으로 탐지해 본문을 메시지로 보고. AST 방문자 없이 raw text 스캔.
|
|
57
|
+
|
|
58
|
+
### `ng-template-sd-require-binding-attrs` (problem, fixable)
|
|
59
|
+
`sd-*` 접두사 컴포넌트의 plain attribute 사용을 제한하고 property binding 으로 변환.
|
|
60
|
+
- 옵션: `selectorPrefixes`(기본 `["sd-"]`), `allowAttributes`(기본 `["id","class","style","title","tabindex","role"]`), `allowAttributePrefixes`(기본 `["aria-","data-","sd-"]`).
|
|
61
|
+
- Autofix: `foo="bar"` → `[foo]="'bar'"`, 값 없으면 `[foo]="true"`.
|
|
62
|
+
|
|
63
|
+
### `no-hard-private` (problem, fixable)
|
|
64
|
+
ES private 필드(`#field`, `#method()`, `accessor #field`, `this.#field`) 금지. TypeScript `private _field` 스타일 강제. Autofix 로 `#x` → `_x` 치환 + 선언부에 `private` 키워드 삽입(데코레이터/`static`/`async`/`readonly` 순서 보존). 동일 클래스에 `_x` 멤버가 이미 있으면 `nameConflict` 로 보고만(자동 수정 안 함).
|
|
65
|
+
|
|
66
|
+
### `no-subpath-imports-from-simplysm` (problem, fixable)
|
|
67
|
+
`@simplysm/<pkg>/src/...` 형태 import 금지. 정적 `import`, 동적 `import()`, `export ... from`, `export * from` 모두 검사. Autofix: `@simplysm/<pkg>` 로 단축.
|
|
68
|
+
|
|
69
|
+
### `ts-no-throw-not-implemented-error` (suggestion, recommended=warn)
|
|
70
|
+
`@simplysm/core-common` 에서 import 한 `NotImplementedError` 의 `new` 호출 보고. named/aliased/namespace import 추적. 인자가 비어있지 않은 문자열 리터럴이면 메시지에 그대로 노출(없으면 `"미구현"`). 동적 import 는 미지원. `**/tests/**/*.ts` 에서는 off.
|
|
71
|
+
|
|
72
|
+
### `ts-no-unused-injects` (problem, fixable)
|
|
73
|
+
클래스 내 `inject()` 로 초기화된 PropertyDefinition 중 같은 클래스 본문에서 식별자로 단 한 번도 참조되지 않는 필드 보고. Autofix 로 해당 필드 라인 제거.
|
|
74
|
+
|
|
75
|
+
### `ts-no-unused-protected-readonly` (problem, fixable)
|
|
76
|
+
`@Component({ template: "..." })` 클래스의 `protected readonly` 인스턴스 필드(=static 제외) 중 인라인 템플릿과 클래스 본문 모두에서 미참조면 보고·자동 제거. `templateUrl` 만 있는 경우(=`template` 프로퍼티 없음) 검사 스킵. 템플릿은 `@angular/compiler` 의 `parseTemplate` 로 파싱하며 `*ngFor` 로컬 변수, `@let`, `@if as alias`, `@for item/context`, `@switch`/`@defer` 트리거까지 스코프 처리.
|
|
77
|
+
|
|
78
|
+
## 규칙 작성용 유틸 (내부)
|
|
79
|
+
|
|
80
|
+
`createRule` 은 패키지 내부 규칙 정의 전용 헬퍼(`ESLintUtils.RuleCreator` 래퍼)로, 외부 export 표면(`exports` 필드) 에 노출되지 않는다. 소비자 코드에서 직접 사용하지 않음.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# @simplysm/orm-common
|
|
2
|
+
|
|
3
|
+
Dialect 독립 ORM 코어. `DbContext` 상속으로 테이블/뷰/프로시저를 등록하고, fluent builder + Expr AST 로 쿼리를 구성하면, 각 DBMS(MySQL/MSSQL/PostgreSQL) QueryBuilder 가 SQL 로 렌더한다. 실제 connect/execute 는 외부 executor 가 구현 (서버=`@simplysm/orm-node`, 클라이언트=`@simplysm/service-client` 의 OrmServiceClient).
|
|
4
|
+
|
|
5
|
+
## 사용 트리거 인덱스
|
|
6
|
+
|
|
7
|
+
- **`DbContext` (abstract class)** — DB 1개에 매핑되는 서브클래스를 만들 때. `protected queryable(Builder)` / `executable(Builder)` 로 테이블·뷰·프로시저를 인스턴스 프로퍼티로 등록, `connect()`/`transaction()` 로 실행 경계 잡고, DDL/`initialize()` 로 스키마 만들 때. 자세히: [db-context.md](./db-context.md)
|
|
8
|
+
- **Schema Builders** — `Table(name)`, `View(name)`, `Procedure(name)` 로 스키마 객체 정의할 때. Column / Index / Relation factory 포함. 자세히: [schema-builders.md](./schema-builders.md)
|
|
9
|
+
- **`Queryable` / `queryable()`** — `DbContext` 에 등록된 테이블/뷰에서 SELECT/INSERT/UPDATE/DELETE/UPSERT 빌더 체이닝, JOIN/include/recursive CTE/UNION/search 할 때. 자세히: [queryable.md](./queryable.md)
|
|
10
|
+
- **`Executable` / `executable()`** — 등록된 프로시저 호출 결과 받을 때. 자세히: [executable.md](./executable.md)
|
|
11
|
+
- **`expr` namespace + `ExprUnit`/`WhereExprUnit`** — `where`/`select`/`groupBy`/`having`/`update` 콜백 안에서 비교·논리·문자열·날짜·집계·윈도우·CASE·subquery 등 SQL 표현식 만들 때. dialect 독립 AST. 자세히: [expr.md](./expr.md)
|
|
12
|
+
- **`parseSearchQuery(text)`** — `Queryable.search()` 내부에서 쓰는 OR/`+`AND/`-`NOT/`"…"`/`*` 구문 파서. 직접 LIKE 패턴이 필요할 때만 외부 사용.
|
|
13
|
+
- **`QueryBuilder` (`createQueryBuilder(dialect)`, `QueryBuilderBase`, `ExprRendererBase`, `*QueryBuilder`, `*ExprRenderer`)** — executor 측에서 `QueryDef` 를 dialect SQL 로 렌더할 때. 응용 코드는 직접 호출 X.
|
|
14
|
+
- **`QueryDef` 타입군 (`./types/query-def`)** — executor·테스트에서 빌더가 만든 AST 를 직접 다룰 때. `QueryDef`, `SelectQueryDef`, `InsertQueryDef`, ..., `QueryDefObjectName`, `DDL_TYPES`, `DdlType`.
|
|
15
|
+
- **`Expr` 타입군 (`./types/expr`)** — Expr AST 노드 타입(`ExprColumn`/`ExprValue`/`ExprRaw`/`ExprEq`/...`ExprWindow`/`ExprSubquery`). `DateUnit`. ExprRenderer 구현·검사에서 사용.
|
|
16
|
+
- **`DataType` / `ColumnPrimitive*` (`./types/column`)** — SQL DataType union(`int`/`bigint`/`varchar`/`datetime`/`uuid`/...) 과 TS 타입 매핑(`ColumnPrimitiveMap`/`ColumnPrimitiveStr`/`ColumnPrimitive`/`ColumnMeta`). `dataTypeStrToColumnPrimitiveStr` 상수, `InferColumnPrimitiveFromDataType<T>` / `inferColumnPrimitiveStr(value)` 런타임 추론.
|
|
17
|
+
- **`Dialect` / `dialects` / `DataRecord` / `DbContextExecutor` / `ResultMeta` / `IsolationLevel` / `Migration` / `QueryBuildResult` (`./types/db`)** — executor 구현·DbContext 외부 인터페이스. `Migration[]` 은 DbContext 서브클래스의 `migrations` 프로퍼티로 오버라이드해 `initialize()` 에서 적용.
|
|
18
|
+
- **`DbContextBase` / `DbContextStatus` / `DbContextDdlMethods` (`./types/db-context-def`)** — 외부에서 DbContext 를 인터페이스로 다룰 때 (Queryable/Executable/ViewBuilder 가 의존).
|
|
19
|
+
- **`DbTransactionError` / `DbErrorCode`** — executor 가 트랜잭션 에러를 표준화해 throw, 호출측은 `instanceof` 로 분기. 코드: `NO_ACTIVE_TRANSACTION`, `TRANSACTION_ALREADY_STARTED`, `DEADLOCK`, `LOCK_TIMEOUT`.
|
|
20
|
+
- **`parseResults(rows, meta)` / `pickResultSets(rawResults, buildResult)` (`./utils/*`)** — executor 측 raw 결과 가공. `parseResults` 는 flat row → 중첩 객체(JOIN 그룹핑 + 타입 파싱). `pickResultSets(raw, { resultSetIndex, resultSetStride })` 는 다중 결과 셋에서 필요한 셋만 추출 (예: MySQL 배치 INSERT 의 OUTPUT SELECT).
|
|
21
|
+
- **`_Migration` / `SD_BUILDER`** — 내부용. `_Migration` 은 `_migration(code PK)` 시스템 테이블, `SD_BUILDER` 는 `queryable()`/`executable()` 팩토리 함수에 붙는 메타 심볼 (`initialize()` 가 DbContext 의 프로퍼티에서 builder 를 회수할 때 사용).
|
|
22
|
+
|
|
23
|
+
## QueryBuilder (인라인)
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { createQueryBuilder } from "@simplysm/orm-common";
|
|
27
|
+
const qb = createQueryBuilder("mysql"); // | "mssql" | "postgresql"
|
|
28
|
+
const { sql, resultSetIndex, resultSetStride } = qb.build(queryDef);
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`QueryBuilderBase.build(def)` 가 `def.type` 으로 동적 dispatch 하여 dialect 별 메서드 호출. 결과는 `QueryBuildResult { sql; resultSetIndex?; resultSetStride? }` — 여러 result set 이 돌아오는 dialect 별 패턴(MySQL OUTPUT INSERT 등)을 위해 추출 인덱스/스트라이드 동봉. executor 는 받은 raw set 배열을 `pickResultSets(raw, buildResult)` 로 좁힌다.
|
|
32
|
+
|
|
33
|
+
`createQueryBuilder(dialect)` 외에 dialect 클래스(`MysqlQueryBuilder`/`MssqlQueryBuilder`/`PostgresqlQueryBuilder` 와 대응 `*ExprRenderer`)도 export. 일반적으로 `createQueryBuilder` 만 쓰면 충분, 커스텀 확장 시 `QueryBuilderBase`/`ExprRendererBase` 상속.
|