@simplysm/sd-claude 13.0.0-beta.11
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/README.md +41 -0
- package/claude/agents/sd-api-reviewer.md +81 -0
- package/claude/agents/sd-code-reviewer.md +49 -0
- package/claude/agents/sd-code-simplifier.md +50 -0
- package/claude/sd-statusline.js +270 -0
- package/claude/skills/sd-api-name-review/SKILL.md +49 -0
- package/claude/skills/sd-brainstorm/SKILL.md +55 -0
- package/claude/skills/sd-check/SKILL.md +88 -0
- package/claude/skills/sd-commit/SKILL.md +48 -0
- package/claude/skills/sd-explore/SKILL.md +63 -0
- package/claude/skills/sd-plan/SKILL.md +104 -0
- package/claude/skills/sd-plan-dev/SKILL.md +266 -0
- package/claude/skills/sd-plan-dev/code-quality-reviewer-prompt.md +69 -0
- package/claude/skills/sd-plan-dev/implementer-prompt.md +50 -0
- package/claude/skills/sd-plan-dev/spec-reviewer-prompt.md +38 -0
- package/claude/skills/sd-readme/SKILL.md +95 -0
- package/claude/skills/sd-review/SKILL.md +93 -0
- package/claude/skills/sd-skill/SKILL.md +639 -0
- package/claude/skills/sd-skill/anthropic-best-practices.md +1150 -0
- package/claude/skills/sd-skill/examples/CLAUDE_MD_TESTING.md +189 -0
- package/claude/skills/sd-skill/persuasion-principles.md +187 -0
- package/claude/skills/sd-skill/testing-skills-with-subagents.md +384 -0
- package/claude/skills/sd-tdd/SKILL.md +373 -0
- package/claude/skills/sd-tdd/testing-anti-patterns.md +299 -0
- package/claude/skills/sd-worktree/SKILL.md +82 -0
- package/claude/skills/sd-worktree/sd-worktree.mjs +128 -0
- package/dist/commands/install.js +64 -0
- package/dist/commands/install.js.map +7 -0
- package/dist/commands/uninstall.js +40 -0
- package/dist/commands/uninstall.js.map +7 -0
- package/dist/core-common/src/common.types.d.ts +74 -0
- package/dist/core-common/src/common.types.d.ts.map +1 -0
- package/dist/core-common/src/env.d.ts +6 -0
- package/dist/core-common/src/env.d.ts.map +1 -0
- package/dist/core-common/src/errors/argument-error.d.ts +25 -0
- package/dist/core-common/src/errors/argument-error.d.ts.map +1 -0
- package/dist/core-common/src/errors/not-implemented-error.d.ts +29 -0
- package/dist/core-common/src/errors/not-implemented-error.d.ts.map +1 -0
- package/dist/core-common/src/errors/sd-error.d.ts +27 -0
- package/dist/core-common/src/errors/sd-error.d.ts.map +1 -0
- package/dist/core-common/src/errors/timeout-error.d.ts +31 -0
- package/dist/core-common/src/errors/timeout-error.d.ts.map +1 -0
- package/dist/core-common/src/extensions/arr-ext.d.ts +15 -0
- package/dist/core-common/src/extensions/arr-ext.d.ts.map +1 -0
- package/dist/core-common/src/extensions/arr-ext.helpers.d.ts +19 -0
- package/dist/core-common/src/extensions/arr-ext.helpers.d.ts.map +1 -0
- package/dist/core-common/src/extensions/arr-ext.types.d.ts +215 -0
- package/dist/core-common/src/extensions/arr-ext.types.d.ts.map +1 -0
- package/dist/core-common/src/extensions/map-ext.d.ts +57 -0
- package/dist/core-common/src/extensions/map-ext.d.ts.map +1 -0
- package/dist/core-common/src/extensions/set-ext.d.ts +36 -0
- package/dist/core-common/src/extensions/set-ext.d.ts.map +1 -0
- package/dist/core-common/src/features/debounce-queue.d.ts +53 -0
- package/dist/core-common/src/features/debounce-queue.d.ts.map +1 -0
- package/dist/core-common/src/features/event-emitter.d.ts +66 -0
- package/dist/core-common/src/features/event-emitter.d.ts.map +1 -0
- package/dist/core-common/src/features/serial-queue.d.ts +47 -0
- package/dist/core-common/src/features/serial-queue.d.ts.map +1 -0
- package/dist/core-common/src/index.d.ts +32 -0
- package/dist/core-common/src/index.d.ts.map +1 -0
- package/dist/core-common/src/types/date-only.d.ts +152 -0
- package/dist/core-common/src/types/date-only.d.ts.map +1 -0
- package/dist/core-common/src/types/date-time.d.ts +96 -0
- package/dist/core-common/src/types/date-time.d.ts.map +1 -0
- package/dist/core-common/src/types/lazy-gc-map.d.ts +80 -0
- package/dist/core-common/src/types/lazy-gc-map.d.ts.map +1 -0
- package/dist/core-common/src/types/time.d.ts +68 -0
- package/dist/core-common/src/types/time.d.ts.map +1 -0
- package/dist/core-common/src/types/uuid.d.ts +35 -0
- package/dist/core-common/src/types/uuid.d.ts.map +1 -0
- package/dist/core-common/src/utils/bytes.d.ts +51 -0
- package/dist/core-common/src/utils/bytes.d.ts.map +1 -0
- package/dist/core-common/src/utils/date-format.d.ts +90 -0
- package/dist/core-common/src/utils/date-format.d.ts.map +1 -0
- package/dist/core-common/src/utils/json.d.ts +34 -0
- package/dist/core-common/src/utils/json.d.ts.map +1 -0
- package/dist/core-common/src/utils/num.d.ts +60 -0
- package/dist/core-common/src/utils/num.d.ts.map +1 -0
- package/dist/core-common/src/utils/obj.d.ts +258 -0
- package/dist/core-common/src/utils/obj.d.ts.map +1 -0
- package/dist/core-common/src/utils/path.d.ts +23 -0
- package/dist/core-common/src/utils/path.d.ts.map +1 -0
- package/dist/core-common/src/utils/primitive.d.ts +18 -0
- package/dist/core-common/src/utils/primitive.d.ts.map +1 -0
- package/dist/core-common/src/utils/str.d.ts +103 -0
- package/dist/core-common/src/utils/str.d.ts.map +1 -0
- package/dist/core-common/src/utils/template-strings.d.ts +84 -0
- package/dist/core-common/src/utils/template-strings.d.ts.map +1 -0
- package/dist/core-common/src/utils/transferable.d.ts +47 -0
- package/dist/core-common/src/utils/transferable.d.ts.map +1 -0
- package/dist/core-common/src/utils/wait.d.ts +19 -0
- package/dist/core-common/src/utils/wait.d.ts.map +1 -0
- package/dist/core-common/src/utils/xml.d.ts +36 -0
- package/dist/core-common/src/utils/xml.d.ts.map +1 -0
- package/dist/core-common/src/zip/sd-zip.d.ts +80 -0
- package/dist/core-common/src/zip/sd-zip.d.ts.map +1 -0
- package/dist/core-node/src/features/fs-watcher.d.ts +70 -0
- package/dist/core-node/src/features/fs-watcher.d.ts.map +1 -0
- package/dist/core-node/src/index.d.ts +7 -0
- package/dist/core-node/src/index.d.ts.map +1 -0
- package/dist/core-node/src/utils/fs.d.ts +197 -0
- package/dist/core-node/src/utils/fs.d.ts.map +1 -0
- package/dist/core-node/src/utils/path.d.ts +75 -0
- package/dist/core-node/src/utils/path.d.ts.map +1 -0
- package/dist/core-node/src/worker/create-worker.d.ts +23 -0
- package/dist/core-node/src/worker/create-worker.d.ts.map +1 -0
- package/dist/core-node/src/worker/types.d.ts +67 -0
- package/dist/core-node/src/worker/types.d.ts.map +1 -0
- package/dist/core-node/src/worker/worker.d.ts +27 -0
- package/dist/core-node/src/worker/worker.d.ts.map +1 -0
- package/dist/sd-claude/src/commands/install.d.ts +14 -0
- package/dist/sd-claude/src/commands/install.d.ts.map +1 -0
- package/dist/sd-claude/src/commands/uninstall.d.ts +10 -0
- package/dist/sd-claude/src/commands/uninstall.d.ts.map +1 -0
- package/dist/sd-claude/src/sd-claude.d.ts +8 -0
- package/dist/sd-claude/src/sd-claude.d.ts.map +1 -0
- package/dist/sd-claude.js +40 -0
- package/dist/sd-claude.js.map +7 -0
- package/package.json +30 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sd-worktree
|
|
3
|
+
description: Use when starting new feature work, bug fixes, or any task that benefits from branch isolation - creates a git worktree under .worktrees/ and guides to next planning step
|
|
4
|
+
model: haiku
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# sd-worktree
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
Create, merge, and clean up git worktrees under `.worktrees/`. Uses the current branch of the main working tree as the source branch.
|
|
12
|
+
|
|
13
|
+
**Important**: Claude Code's working directory (cd) shifts between main and worktree, so always verify the cd location before and after each command.
|
|
14
|
+
|
|
15
|
+
## Target Worktree Resolution
|
|
16
|
+
|
|
17
|
+
For all commands, the target worktree name is resolved in this order:
|
|
18
|
+
1. Explicitly provided in args → use as-is
|
|
19
|
+
2. Current cd is inside `.worktrees/<name>/` → use that `<name>` (auto-detected)
|
|
20
|
+
3. Neither applies → ask the user
|
|
21
|
+
|
|
22
|
+
## Commands
|
|
23
|
+
|
|
24
|
+
### add — Create a worktree
|
|
25
|
+
|
|
26
|
+
Take a work description from args, determine a kebab-case name, then run:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Run from main
|
|
30
|
+
node .claude/skills/sd-worktree/sd-worktree.mjs add <name>
|
|
31
|
+
cd .worktrees/<name> # Move into the worktree
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- All subsequent work should be done inside the worktree
|
|
35
|
+
- Suggest next steps:
|
|
36
|
+
1. **brainstorming** (`/sd-brainstorm`)
|
|
37
|
+
2. **writing-plans** (`/sd-plan`)
|
|
38
|
+
|
|
39
|
+
### rebase — Rebase onto main branch
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Can be run from inside the worktree
|
|
43
|
+
node .claude/skills/sd-worktree/sd-worktree.mjs rebase [name]
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
- Rebases the worktree branch onto the latest commit of the main branch
|
|
47
|
+
- Errors if uncommitted changes exist → commit or stash first
|
|
48
|
+
- Use when you want a clean history before merging
|
|
49
|
+
|
|
50
|
+
### merge — Merge into main branch
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Can be run from inside the worktree (script sets cwd to main)
|
|
54
|
+
node .claude/skills/sd-worktree/sd-worktree.mjs merge [name]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- Merges the worktree branch into the main working tree's current branch with `--no-ff`
|
|
58
|
+
- Errors if uncommitted changes exist → commit or stash first
|
|
59
|
+
- After merge, always `cd <project-root>` (required for subsequent clean)
|
|
60
|
+
|
|
61
|
+
### clean — Remove worktree and delete branch
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Must cd to main first (worktree directory will be deleted)
|
|
65
|
+
cd <project-root>
|
|
66
|
+
node .claude/skills/sd-worktree/sd-worktree.mjs clean <name>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- Runs `git worktree remove` + `git branch -d`
|
|
70
|
+
- Script blocks execution if run from inside the worktree → must cd to main first
|
|
71
|
+
|
|
72
|
+
## Full Workflow Example
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
(main: 13.x) → /sd-worktree add modal-migration
|
|
76
|
+
→ cd .worktrees/modal-migration
|
|
77
|
+
(worktree) → ... work ...
|
|
78
|
+
(worktree) → /sd-worktree rebase # (optional) rebase onto latest main
|
|
79
|
+
(worktree) → /sd-worktree merge
|
|
80
|
+
(worktree) → cd <project-root>
|
|
81
|
+
(main: 13.x) → /sd-worktree clean modal-migration
|
|
82
|
+
```
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
|
|
6
|
+
const [cmd, ...args] = process.argv.slice(2);
|
|
7
|
+
|
|
8
|
+
function run(command, opts) {
|
|
9
|
+
execSync(command, { encoding: "utf-8", stdio: "inherit", ...opts });
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function getOutput(command) {
|
|
13
|
+
return execSync(command, { encoding: "utf-8" }).trim();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// 메인 working tree 경로 (worktree 안에서 실행해도 정확)
|
|
17
|
+
const mainWorktree = getOutput("git worktree list --porcelain").split("\n")[0].replace("worktree ", "");
|
|
18
|
+
|
|
19
|
+
function detectWorktreeName() {
|
|
20
|
+
const cwd = process.cwd();
|
|
21
|
+
const worktreesDir = resolve(mainWorktree, ".worktrees");
|
|
22
|
+
if (cwd.startsWith(worktreesDir + "/")) {
|
|
23
|
+
return cwd.slice(worktreesDir.length + 1).split("/")[0];
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getMainBranch() {
|
|
29
|
+
return getOutput(`git -C "${mainWorktree}" rev-parse --abbrev-ref HEAD`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
switch (cmd) {
|
|
33
|
+
case "add": {
|
|
34
|
+
const name = args[0];
|
|
35
|
+
if (!name) {
|
|
36
|
+
console.error("Usage: sd-worktree.mjs add <kebab-case-name>");
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
const worktreePath = resolve(mainWorktree, ".worktrees", name);
|
|
40
|
+
if (existsSync(worktreePath)) {
|
|
41
|
+
console.error(`Already exists: ${worktreePath}`);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
const branch = getMainBranch();
|
|
45
|
+
console.log(`Creating worktree: .worktrees/${name} (from ${branch})`);
|
|
46
|
+
run(`git worktree add "${worktreePath}" -b "${name}"`);
|
|
47
|
+
console.log("Installing dependencies...");
|
|
48
|
+
run("pnpm install", { cwd: worktreePath });
|
|
49
|
+
console.log(`\nReady: ${worktreePath}`);
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
case "merge": {
|
|
54
|
+
const name = args[0] ?? detectWorktreeName();
|
|
55
|
+
if (!name) {
|
|
56
|
+
console.error("Usage: sd-worktree.mjs merge [name] (or run inside .worktrees/<name>)");
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
// uncommitted 변경 확인
|
|
60
|
+
const worktreePath_m = resolve(mainWorktree, ".worktrees", name);
|
|
61
|
+
if (existsSync(worktreePath_m)) {
|
|
62
|
+
const status = getOutput(`git -C "${worktreePath_m}" status --porcelain`);
|
|
63
|
+
if (status) {
|
|
64
|
+
console.error(`Error: worktree '${name}' has uncommitted changes:\n${status}`);
|
|
65
|
+
console.error("Commit or stash changes before merging.");
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const branch = getMainBranch();
|
|
70
|
+
console.log(`Merging '${name}' into '${branch}'...`);
|
|
71
|
+
run(`git merge "${name}" --no-ff`, { cwd: mainWorktree });
|
|
72
|
+
console.log(`\nMerged '${name}' into '${branch}'.`);
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
case "rebase": {
|
|
77
|
+
const name = args[0] ?? detectWorktreeName();
|
|
78
|
+
if (!name) {
|
|
79
|
+
console.error("Usage: sd-worktree.mjs rebase [name] (or run inside .worktrees/<name>)");
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
const worktreePath_r = resolve(mainWorktree, ".worktrees", name);
|
|
83
|
+
if (!existsSync(worktreePath_r)) {
|
|
84
|
+
console.error(`Error: worktree '${name}' does not exist.`);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
// uncommitted 변경 확인
|
|
88
|
+
const statusR = getOutput(`git -C "${worktreePath_r}" status --porcelain`);
|
|
89
|
+
if (statusR) {
|
|
90
|
+
console.error(`Error: worktree '${name}' has uncommitted changes:\n${statusR}`);
|
|
91
|
+
console.error("Commit or stash changes before rebasing.");
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
const branchR = getMainBranch();
|
|
95
|
+
console.log(`Rebasing '${name}' onto '${branchR}'...`);
|
|
96
|
+
run(`git rebase "${branchR}"`, { cwd: worktreePath_r });
|
|
97
|
+
console.log(`\nRebased '${name}' onto '${branchR}'.`);
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
case "clean": {
|
|
102
|
+
const name = args[0] ?? detectWorktreeName();
|
|
103
|
+
if (!name) {
|
|
104
|
+
console.error("Usage: sd-worktree.mjs clean [name] (or run inside .worktrees/<name>)");
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
// worktree 안에서 실행 시 차단
|
|
108
|
+
const worktreePath = resolve(mainWorktree, ".worktrees", name);
|
|
109
|
+
const cwd = process.cwd();
|
|
110
|
+
if (cwd === worktreePath || cwd.startsWith(worktreePath + "/")) {
|
|
111
|
+
console.error(`Error: Cannot clean '${name}' from inside its worktree.`);
|
|
112
|
+
console.error(`Run: cd "${mainWorktree}" && node .claude/skills/sd-worktree/sd-worktree.mjs clean ${name}`);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
if (existsSync(worktreePath)) {
|
|
116
|
+
console.log(`Removing worktree: .worktrees/${name}`);
|
|
117
|
+
run(`git worktree remove "${worktreePath}"`, { cwd: mainWorktree });
|
|
118
|
+
}
|
|
119
|
+
console.log(`Deleting branch: ${name}`);
|
|
120
|
+
run(`git branch -d "${name}"`, { cwd: mainWorktree });
|
|
121
|
+
console.log(`\nCleaned up '${name}'.`);
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
default:
|
|
126
|
+
console.error("Usage: sd-worktree.mjs <add|merge|rebase|clean> [name]");
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import { consola } from "consola";
|
|
4
|
+
import { fsGlob, fsExists, fsCopy, fsRm, fsMkdir, fsReadJson, fsWriteJson } from "@simplysm/core-node";
|
|
5
|
+
function findPackageRoot(startDir) {
|
|
6
|
+
let dir = startDir;
|
|
7
|
+
while (!fs.existsSync(path.join(dir, "package.json"))) {
|
|
8
|
+
const parent = path.dirname(dir);
|
|
9
|
+
if (parent === dir) throw new Error("package.json\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
10
|
+
dir = parent;
|
|
11
|
+
}
|
|
12
|
+
return dir;
|
|
13
|
+
}
|
|
14
|
+
async function findSdEntries(baseDir) {
|
|
15
|
+
const [rootEntries, subEntries] = await Promise.all([
|
|
16
|
+
fsGlob(path.join(baseDir, "sd-*")),
|
|
17
|
+
fsGlob(path.join(baseDir, "*/sd-*"))
|
|
18
|
+
]);
|
|
19
|
+
return [...rootEntries, ...subEntries];
|
|
20
|
+
}
|
|
21
|
+
async function runInstall(_options) {
|
|
22
|
+
const cwd = process.cwd();
|
|
23
|
+
const logger = consola.withTag("sd:claude:install");
|
|
24
|
+
const pkgRoot = findPackageRoot(import.meta.dirname);
|
|
25
|
+
const sourceDir = path.join(pkgRoot, "claude");
|
|
26
|
+
if (!await fsExists(sourceDir)) {
|
|
27
|
+
consola.error(`\uC5D0\uC14B \uB514\uB809\uD1A0\uB9AC\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${sourceDir}`);
|
|
28
|
+
process.exitCode = 1;
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const sourceEntries = await findSdEntries(sourceDir);
|
|
32
|
+
if (sourceEntries.length === 0) {
|
|
33
|
+
logger.warn("\uC124\uCE58\uD560 sd-* \uC5D0\uC14B\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const targetDir = path.join(cwd, ".claude");
|
|
37
|
+
if (await fsExists(targetDir)) {
|
|
38
|
+
const existingEntries = await findSdEntries(targetDir);
|
|
39
|
+
for (const entry of existingEntries) {
|
|
40
|
+
await fsRm(entry);
|
|
41
|
+
logger.debug(`\uC0AD\uC81C: ${path.relative(cwd, entry)}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
await fsMkdir(targetDir);
|
|
45
|
+
for (const entry of sourceEntries) {
|
|
46
|
+
const relativePath = path.relative(sourceDir, entry);
|
|
47
|
+
const targetPath = path.join(targetDir, relativePath);
|
|
48
|
+
await fsCopy(entry, targetPath);
|
|
49
|
+
logger.info(`\uC124\uCE58: .claude/${relativePath}`);
|
|
50
|
+
}
|
|
51
|
+
const settingsPath = path.join(targetDir, "settings.json");
|
|
52
|
+
const sdStatusLineCommand = "node .claude/sd-statusline.js";
|
|
53
|
+
const settings = await fsExists(settingsPath) ? await fsReadJson(settingsPath) : {};
|
|
54
|
+
if (settings["statusLine"] == null) {
|
|
55
|
+
settings["statusLine"] = { type: "command", command: sdStatusLineCommand };
|
|
56
|
+
await fsWriteJson(settingsPath, settings, { space: 2 });
|
|
57
|
+
logger.info("settings.json\uC5D0 statusLine \uC124\uC815 \uCD94\uAC00");
|
|
58
|
+
}
|
|
59
|
+
logger.info(`${sourceEntries.length}\uAC1C\uC758 sd-* \uD56D\uBAA9\uC744 \uC124\uCE58\uD588\uC2B5\uB2C8\uB2E4.`);
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
runInstall
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/commands/install.ts"],
|
|
4
|
+
"sourcesContent": ["import path from \"path\";\nimport fs from \"fs\";\nimport { consola } from \"consola\";\nimport { fsGlob, fsExists, fsCopy, fsRm, fsMkdir, fsReadJson, fsWriteJson } from \"@simplysm/core-node\";\n\n//#region Types\n\n/**\n * Install \uBA85\uB839 \uC635\uC158\n */\nexport interface InstallOptions {}\n\n//#endregion\n\n//#region Utilities\n\n/**\n * import.meta.dirname\uC5D0\uC11C \uC0C1\uC704\uB85C \uC62C\uB77C\uAC00\uBA70 package.json\uC744 \uCC3E\uC544 \uD328\uD0A4\uC9C0 \uB8E8\uD2B8\uB97C \uBC18\uD658\uD55C\uB2E4.\n */\nfunction findPackageRoot(startDir: string): string {\n let dir = startDir;\n while (!fs.existsSync(path.join(dir, \"package.json\"))) {\n const parent = path.dirname(dir);\n if (parent === dir) throw new Error(\"package.json\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.\");\n dir = parent;\n }\n return dir;\n}\n\n/**\n * sd-* \uD328\uD134\uC5D0 \uB9E4\uCE6D\uB418\uB294 \uD30C\uC77C/\uD3F4\uB354\uB97C \uD0D0\uC0C9\uD55C\uB2E4.\n */\nasync function findSdEntries(baseDir: string): Promise<string[]> {\n const [rootEntries, subEntries] = await Promise.all([\n fsGlob(path.join(baseDir, \"sd-*\")),\n fsGlob(path.join(baseDir, \"*/sd-*\")),\n ]);\n return [...rootEntries, ...subEntries];\n}\n\n//#endregion\n\n//#region Main\n\n/**\n * Claude Code \uC2A4\uD0AC/\uC5D0\uC774\uC804\uD2B8\uB97C \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8\uC5D0 \uC124\uCE58\uD55C\uB2E4.\n *\n * \uD328\uD0A4\uC9C0\uC758 `claude/` \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C sd-* \uC5D0\uC14B\uC744 \uC77D\uC5B4\n * \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8\uC758 `.claude/`\uC5D0 \uBCF5\uC0AC\uD55C\uB2E4.\n * \uAE30\uC874 sd-* \uD56D\uBAA9\uC740 \uC804\uCCB4 \uC0AD\uC81C \uD6C4 \uC0C8\uB85C \uBCF5\uC0AC\uD55C\uB2E4.\n */\nexport async function runInstall(_options: InstallOptions): Promise<void> {\n const cwd = process.cwd();\n const logger = consola.withTag(\"sd:claude:install\");\n\n // \uD328\uD0A4\uC9C0\uC758 claude/ \uB514\uB809\uD1A0\uB9AC\n const pkgRoot = findPackageRoot(import.meta.dirname);\n const sourceDir = path.join(pkgRoot, \"claude\");\n\n if (!(await fsExists(sourceDir))) {\n consola.error(`\uC5D0\uC14B \uB514\uB809\uD1A0\uB9AC\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${sourceDir}`);\n process.exitCode = 1;\n return;\n }\n\n // \uC18C\uC2A4\uC5D0\uC11C sd-* \uD56D\uBAA9 \uD0D0\uC0C9\n const sourceEntries = await findSdEntries(sourceDir);\n if (sourceEntries.length === 0) {\n logger.warn(\"\uC124\uCE58\uD560 sd-* \uC5D0\uC14B\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\");\n return;\n }\n\n // \uB300\uC0C1 .claude/ \uB514\uB809\uD1A0\uB9AC\n const targetDir = path.join(cwd, \".claude\");\n\n // \uAE30\uC874 sd-* \uC0AD\uC81C\n if (await fsExists(targetDir)) {\n const existingEntries = await findSdEntries(targetDir);\n for (const entry of existingEntries) {\n await fsRm(entry);\n logger.debug(`\uC0AD\uC81C: ${path.relative(cwd, entry)}`);\n }\n }\n\n // \uBCF5\uC0AC\n await fsMkdir(targetDir);\n for (const entry of sourceEntries) {\n const relativePath = path.relative(sourceDir, entry);\n const targetPath = path.join(targetDir, relativePath);\n await fsCopy(entry, targetPath);\n logger.info(`\uC124\uCE58: .claude/${relativePath}`);\n }\n\n // settings.json\uC5D0 statusLine \uC124\uC815\n const settingsPath = path.join(targetDir, \"settings.json\");\n const sdStatusLineCommand = \"node .claude/sd-statusline.js\";\n const settings = (await fsExists(settingsPath)) ? await fsReadJson<Record<string, unknown>>(settingsPath) : {};\n\n if (settings[\"statusLine\"] == null) {\n settings[\"statusLine\"] = { type: \"command\", command: sdStatusLineCommand };\n await fsWriteJson(settingsPath, settings, { space: 2 });\n logger.info(\"settings.json\uC5D0 statusLine \uC124\uC815 \uCD94\uAC00\");\n }\n\n logger.info(`${sourceEntries.length}\uAC1C\uC758 sd-* \uD56D\uBAA9\uC744 \uC124\uCE58\uD588\uC2B5\uB2C8\uB2E4.`);\n}\n\n//#endregion\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,SAAS,eAAe;AACxB,SAAS,QAAQ,UAAU,QAAQ,MAAM,SAAS,YAAY,mBAAmB;AAgBjF,SAAS,gBAAgB,UAA0B;AACjD,MAAI,MAAM;AACV,SAAO,CAAC,GAAG,WAAW,KAAK,KAAK,KAAK,cAAc,CAAC,GAAG;AACrD,UAAM,SAAS,KAAK,QAAQ,GAAG;AAC/B,QAAI,WAAW,IAAK,OAAM,IAAI,MAAM,kEAA0B;AAC9D,UAAM;AAAA,EACR;AACA,SAAO;AACT;AAKA,eAAe,cAAc,SAAoC;AAC/D,QAAM,CAAC,aAAa,UAAU,IAAI,MAAM,QAAQ,IAAI;AAAA,IAClD,OAAO,KAAK,KAAK,SAAS,MAAM,CAAC;AAAA,IACjC,OAAO,KAAK,KAAK,SAAS,QAAQ,CAAC;AAAA,EACrC,CAAC;AACD,SAAO,CAAC,GAAG,aAAa,GAAG,UAAU;AACvC;AAaA,eAAsB,WAAW,UAAyC;AACxE,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,SAAS,QAAQ,QAAQ,mBAAmB;AAGlD,QAAM,UAAU,gBAAgB,YAAY,OAAO;AACnD,QAAM,YAAY,KAAK,KAAK,SAAS,QAAQ;AAE7C,MAAI,CAAE,MAAM,SAAS,SAAS,GAAI;AAChC,YAAQ,MAAM,6FAAuB,SAAS,EAAE;AAChD,YAAQ,WAAW;AACnB;AAAA,EACF;AAGA,QAAM,gBAAgB,MAAM,cAAc,SAAS;AACnD,MAAI,cAAc,WAAW,GAAG;AAC9B,WAAO,KAAK,sEAAoB;AAChC;AAAA,EACF;AAGA,QAAM,YAAY,KAAK,KAAK,KAAK,SAAS;AAG1C,MAAI,MAAM,SAAS,SAAS,GAAG;AAC7B,UAAM,kBAAkB,MAAM,cAAc,SAAS;AACrD,eAAW,SAAS,iBAAiB;AACnC,YAAM,KAAK,KAAK;AAChB,aAAO,MAAM,iBAAO,KAAK,SAAS,KAAK,KAAK,CAAC,EAAE;AAAA,IACjD;AAAA,EACF;AAGA,QAAM,QAAQ,SAAS;AACvB,aAAW,SAAS,eAAe;AACjC,UAAM,eAAe,KAAK,SAAS,WAAW,KAAK;AACnD,UAAM,aAAa,KAAK,KAAK,WAAW,YAAY;AACpD,UAAM,OAAO,OAAO,UAAU;AAC9B,WAAO,KAAK,yBAAe,YAAY,EAAE;AAAA,EAC3C;AAGA,QAAM,eAAe,KAAK,KAAK,WAAW,eAAe;AACzD,QAAM,sBAAsB;AAC5B,QAAM,WAAY,MAAM,SAAS,YAAY,IAAK,MAAM,WAAoC,YAAY,IAAI,CAAC;AAE7G,MAAI,SAAS,YAAY,KAAK,MAAM;AAClC,aAAS,YAAY,IAAI,EAAE,MAAM,WAAW,SAAS,oBAAoB;AACzE,UAAM,YAAY,cAAc,UAAU,EAAE,OAAO,EAAE,CAAC;AACtD,WAAO,KAAK,0DAAiC;AAAA,EAC/C;AAEA,SAAO,KAAK,GAAG,cAAc,MAAM,4EAAqB;AAC1D;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { consola } from "consola";
|
|
3
|
+
import { fsGlob, fsExists, fsRm, fsReadJson, fsWriteJson } from "@simplysm/core-node";
|
|
4
|
+
async function runUninstall(_options) {
|
|
5
|
+
const cwd = process.cwd();
|
|
6
|
+
const logger = consola.withTag("sd:claude:uninstall");
|
|
7
|
+
const targetDir = path.join(cwd, ".claude");
|
|
8
|
+
if (!await fsExists(targetDir)) {
|
|
9
|
+
logger.warn(".claude \uB514\uB809\uD1A0\uB9AC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const [rootEntries, subEntries] = await Promise.all([
|
|
13
|
+
fsGlob(path.join(targetDir, "sd-*")),
|
|
14
|
+
fsGlob(path.join(targetDir, "*/sd-*"))
|
|
15
|
+
]);
|
|
16
|
+
const entries = [...rootEntries, ...subEntries];
|
|
17
|
+
if (entries.length === 0) {
|
|
18
|
+
logger.warn("\uC0AD\uC81C\uD560 sd-* \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
for (const entry of entries) {
|
|
22
|
+
await fsRm(entry);
|
|
23
|
+
logger.info(`\uC0AD\uC81C: .claude/${path.relative(targetDir, entry)}`);
|
|
24
|
+
}
|
|
25
|
+
const settingsPath = path.join(targetDir, "settings.json");
|
|
26
|
+
if (await fsExists(settingsPath)) {
|
|
27
|
+
const settings = await fsReadJson(settingsPath);
|
|
28
|
+
const currentCommand = settings["statusLine"]?.["command"];
|
|
29
|
+
if (currentCommand === "node .claude/sd-statusline.js") {
|
|
30
|
+
delete settings["statusLine"];
|
|
31
|
+
await fsWriteJson(settingsPath, settings, { space: 2 });
|
|
32
|
+
logger.info("settings.json\uC5D0\uC11C statusLine \uC124\uC815 \uC81C\uAC70");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
logger.info(`${entries.length}\uAC1C\uC758 sd-* \uD56D\uBAA9\uC744 \uC81C\uAC70\uD588\uC2B5\uB2C8\uB2E4.`);
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
runUninstall
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=uninstall.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/commands/uninstall.ts"],
|
|
4
|
+
"sourcesContent": ["import path from \"path\";\nimport { consola } from \"consola\";\nimport { fsGlob, fsExists, fsRm, fsReadJson, fsWriteJson } from \"@simplysm/core-node\";\n\n//#region Types\n\n/**\n * Uninstall \uBA85\uB839 \uC635\uC158\n */\nexport interface UninstallOptions {}\n\n//#endregion\n\n//#region Main\n\n/**\n * \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8\uC758 `.claude/`\uC5D0\uC11C sd-* \uC2A4\uD0AC/\uC5D0\uC774\uC804\uD2B8\uB97C \uC81C\uAC70\uD55C\uB2E4.\n */\nexport async function runUninstall(_options: UninstallOptions): Promise<void> {\n const cwd = process.cwd();\n const logger = consola.withTag(\"sd:claude:uninstall\");\n\n const targetDir = path.join(cwd, \".claude\");\n\n if (!(await fsExists(targetDir))) {\n logger.warn(\".claude \uB514\uB809\uD1A0\uB9AC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.\");\n return;\n }\n\n const [rootEntries, subEntries] = await Promise.all([\n fsGlob(path.join(targetDir, \"sd-*\")),\n fsGlob(path.join(targetDir, \"*/sd-*\")),\n ]);\n const entries = [...rootEntries, ...subEntries];\n\n if (entries.length === 0) {\n logger.warn(\"\uC0AD\uC81C\uD560 sd-* \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.\");\n return;\n }\n\n for (const entry of entries) {\n await fsRm(entry);\n logger.info(`\uC0AD\uC81C: .claude/${path.relative(targetDir, entry)}`);\n }\n\n // settings.json\uC5D0\uC11C statusLine \uC81C\uAC70\n const settingsPath = path.join(targetDir, \"settings.json\");\n if (await fsExists(settingsPath)) {\n const settings = await fsReadJson<Record<string, unknown>>(settingsPath);\n const currentCommand = (settings[\"statusLine\"] as Record<string, unknown> | undefined)?.[\"command\"];\n if (currentCommand === \"node .claude/sd-statusline.js\") {\n delete settings[\"statusLine\"];\n await fsWriteJson(settingsPath, settings, { space: 2 });\n logger.info(\"settings.json\uC5D0\uC11C statusLine \uC124\uC815 \uC81C\uAC70\");\n }\n }\n\n logger.info(`${entries.length}\uAC1C\uC758 sd-* \uD56D\uBAA9\uC744 \uC81C\uAC70\uD588\uC2B5\uB2C8\uB2E4.`);\n}\n\n//#endregion\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,UAAU;AACjB,SAAS,eAAe;AACxB,SAAS,QAAQ,UAAU,MAAM,YAAY,mBAAmB;AAgBhE,eAAsB,aAAa,UAA2C;AAC5E,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,SAAS,QAAQ,QAAQ,qBAAqB;AAEpD,QAAM,YAAY,KAAK,KAAK,KAAK,SAAS;AAE1C,MAAI,CAAE,MAAM,SAAS,SAAS,GAAI;AAChC,WAAO,KAAK,kEAAqB;AACjC;AAAA,EACF;AAEA,QAAM,CAAC,aAAa,UAAU,IAAI,MAAM,QAAQ,IAAI;AAAA,IAClD,OAAO,KAAK,KAAK,WAAW,MAAM,CAAC;AAAA,IACnC,OAAO,KAAK,KAAK,WAAW,QAAQ,CAAC;AAAA,EACvC,CAAC;AACD,QAAM,UAAU,CAAC,GAAG,aAAa,GAAG,UAAU;AAE9C,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO,KAAK,sEAAoB;AAChC;AAAA,EACF;AAEA,aAAW,SAAS,SAAS;AAC3B,UAAM,KAAK,KAAK;AAChB,WAAO,KAAK,yBAAe,KAAK,SAAS,WAAW,KAAK,CAAC,EAAE;AAAA,EAC9D;AAGA,QAAM,eAAe,KAAK,KAAK,WAAW,eAAe;AACzD,MAAI,MAAM,SAAS,YAAY,GAAG;AAChC,UAAM,WAAW,MAAM,WAAoC,YAAY;AACvE,UAAM,iBAAkB,SAAS,YAAY,IAA4C,SAAS;AAClG,QAAI,mBAAmB,iCAAiC;AACtD,aAAO,SAAS,YAAY;AAC5B,YAAM,YAAY,cAAc,UAAU,EAAE,OAAO,EAAE,CAAC;AACtD,aAAO,KAAK,gEAAkC;AAAA,IAChD;AAAA,EACF;AAEA,SAAO,KAAK,GAAG,QAAQ,MAAM,4EAAqB;AACpD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { DateTime } from "./types/date-time";
|
|
2
|
+
import { DateOnly } from "./types/date-only";
|
|
3
|
+
import { Time } from "./types/time";
|
|
4
|
+
import { Uuid } from "./types/uuid";
|
|
5
|
+
/**
|
|
6
|
+
* Buffer 대신 사용하는 바이너리 타입
|
|
7
|
+
*/
|
|
8
|
+
export type Bytes = Uint8Array;
|
|
9
|
+
/**
|
|
10
|
+
* Primitive 타입 매핑
|
|
11
|
+
* orm-common과 공유
|
|
12
|
+
*/
|
|
13
|
+
export type PrimitiveTypeMap = {
|
|
14
|
+
string: string;
|
|
15
|
+
number: number;
|
|
16
|
+
boolean: boolean;
|
|
17
|
+
DateTime: DateTime;
|
|
18
|
+
DateOnly: DateOnly;
|
|
19
|
+
Time: Time;
|
|
20
|
+
Uuid: Uuid;
|
|
21
|
+
Bytes: Bytes;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Primitive 타입 문자열 키
|
|
25
|
+
*/
|
|
26
|
+
export type PrimitiveTypeStr = keyof PrimitiveTypeMap;
|
|
27
|
+
/**
|
|
28
|
+
* Primitive 타입 유니온
|
|
29
|
+
*/
|
|
30
|
+
export type PrimitiveType = PrimitiveTypeMap[PrimitiveTypeStr] | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* 깊은 Partial 타입
|
|
33
|
+
*
|
|
34
|
+
* 객체의 모든 속성을 재귀적으로 선택적(optional)으로 만듭니다.
|
|
35
|
+
* Primitive 타입(string, number, boolean 등)은 그대로 유지하고,
|
|
36
|
+
* 객체/배열 타입만 재귀적으로 Partial을 적용합니다.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* interface User {
|
|
41
|
+
* name: string;
|
|
42
|
+
* profile: {
|
|
43
|
+
* age: number;
|
|
44
|
+
* address: { city: string };
|
|
45
|
+
* };
|
|
46
|
+
* }
|
|
47
|
+
*
|
|
48
|
+
* // 모든 깊이의 속성이 선택적이 됨
|
|
49
|
+
* const partial: DeepPartial<User> = {
|
|
50
|
+
* profile: { address: {} }
|
|
51
|
+
* };
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export type DeepPartial<T> = Partial<{
|
|
55
|
+
[K in keyof T]: T[K] extends PrimitiveType ? T[K] : DeepPartial<T[K]>;
|
|
56
|
+
}>;
|
|
57
|
+
/**
|
|
58
|
+
* 생성자 타입
|
|
59
|
+
*
|
|
60
|
+
* 클래스 생성자를 타입으로 표현할 때 사용합니다.
|
|
61
|
+
* 주로 의존성 주입, 팩토리 패턴, instanceof 체크 등에서 활용됩니다.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* function create<T>(ctor: Type<T>): T {
|
|
65
|
+
* return new ctor();
|
|
66
|
+
* }
|
|
67
|
+
*
|
|
68
|
+
* class MyClass { name = "test"; }
|
|
69
|
+
* const instance = create(MyClass); // MyClass 인스턴스
|
|
70
|
+
*/
|
|
71
|
+
export interface Type<T> extends Function {
|
|
72
|
+
new (...args: unknown[]): T;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=common.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.types.d.ts","sourceRoot":"","sources":["../../../../core-common/src/common.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAIpC;;GAEG;AACH,MAAM,MAAM,KAAK,GAAG,UAAU,CAAC;AAM/B;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,gBAAgB,CAAC;AAEtD;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,gBAAgB,CAAC,gBAAgB,CAAC,GAAG,SAAS,CAAC;AAM3E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,OAAO,CAAC;KAClC,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACtE,CAAC,CAAC;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,IAAI,CAAC,CAAC,CAAE,SAAQ,QAAQ;IACvC,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;CAC7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../../core-common/src/env.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,GAAG,EAAE;IAChB,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAKxB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SdError } from "./sd-error";
|
|
2
|
+
/**
|
|
3
|
+
* 인수 오류
|
|
4
|
+
*
|
|
5
|
+
* 잘못된 인수를 받았을 때 발생시키는 에러이다.
|
|
6
|
+
* 인수 객체를 YAML 형식으로 메시지에 포함하여 디버깅을 용이하게 한다.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* // 인수 객체만 전달
|
|
10
|
+
* throw new ArgumentError({ userId: 123, name: null });
|
|
11
|
+
* // 결과 메시지: "인수가 잘못되었습니다.\n\nuserId: 123\nname: null"
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // 커스텀 메시지와 인수 객체 전달
|
|
15
|
+
* throw new ArgumentError("유효하지 않은 사용자", { userId: 123 });
|
|
16
|
+
* // 결과 메시지: "유효하지 않은 사용자\n\nuserId: 123"
|
|
17
|
+
*/
|
|
18
|
+
export declare class ArgumentError extends SdError {
|
|
19
|
+
/** 기본 메시지("인수가 잘못되었습니다.")와 함께 인수 객체를 YAML 형식으로 출력 */
|
|
20
|
+
constructor(argObj: Record<string, unknown>);
|
|
21
|
+
/** 커스텀 메시지와 함께 인수 객체를 YAML 형식으로 출력 */
|
|
22
|
+
constructor(message: string, argObj: Record<string, unknown>);
|
|
23
|
+
constructor(arg1: Record<string, unknown> | string, arg2?: Record<string, unknown>);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=argument-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"argument-error.d.ts","sourceRoot":"","sources":["../../../../../core-common/src/errors/argument-error.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,aAAc,SAAQ,OAAO;IACxC,qDAAqD;gBACzC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC3C,sCAAsC;gBAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBAChD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAYnF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { SdError } from "./sd-error";
|
|
2
|
+
/**
|
|
3
|
+
* 미구현 오류
|
|
4
|
+
*
|
|
5
|
+
* 아직 구현되지 않은 기능을 호출했을 때 발생시키는 에러이다.
|
|
6
|
+
* 추상 메서드 스텁, 향후 구현 예정인 분기 등에 사용한다.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* // 추상 메서드 구현 전
|
|
10
|
+
* class BaseService {
|
|
11
|
+
* process(): void {
|
|
12
|
+
* throw new NotImplementedError("서브클래스에서 구현 필요");
|
|
13
|
+
* }
|
|
14
|
+
* }
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // 향후 구현 예정 분기
|
|
18
|
+
* switch (type) {
|
|
19
|
+
* case "A": return handleA();
|
|
20
|
+
* case "B": throw new NotImplementedError(`타입 ${type} 처리`);
|
|
21
|
+
* }
|
|
22
|
+
*/
|
|
23
|
+
export declare class NotImplementedError extends SdError {
|
|
24
|
+
/**
|
|
25
|
+
* @param message 추가 설명 메시지
|
|
26
|
+
*/
|
|
27
|
+
constructor(message?: string);
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=not-implemented-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"not-implemented-error.d.ts","sourceRoot":"","sources":["../../../../../core-common/src/errors/not-implemented-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,mBAAoB,SAAQ,OAAO;IAC9C;;OAEG;gBACS,OAAO,CAAC,EAAE,MAAM;CAI7B"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 오류의 Tree 구조 구성이 가능한 오류 클래스
|
|
3
|
+
* ES2024 cause 속성 활용
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* // 원인 에러를 감싸서 생성
|
|
7
|
+
* try {
|
|
8
|
+
* await fetch(url);
|
|
9
|
+
* } catch (err) {
|
|
10
|
+
* throw new SdError(err, "API 호출 실패", "사용자 로드 실패");
|
|
11
|
+
* }
|
|
12
|
+
* // 결과 메시지: "사용자 로드 실패 => API 호출 실패 => 원본 에러 메시지"
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // 메시지만으로 생성
|
|
16
|
+
* throw new SdError("잘못된 상태", "처리 불가");
|
|
17
|
+
* // 결과 메시지: "처리 불가 => 잘못된 상태"
|
|
18
|
+
*/
|
|
19
|
+
export declare class SdError extends Error {
|
|
20
|
+
cause?: Error;
|
|
21
|
+
/** 원인 에러를 감싸서 생성. 메시지는 역순으로 연결됨 (상위 메시지 => 하위 메시지 => 원인 메시지) */
|
|
22
|
+
constructor(cause: Error, ...messages: string[]);
|
|
23
|
+
/** 메시지만으로 생성. 메시지는 역순으로 연결됨 (상위 메시지 => 하위 메시지) */
|
|
24
|
+
constructor(...messages: string[]);
|
|
25
|
+
constructor(arg1?: unknown, ...messages: string[]);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=sd-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sd-error.d.ts","sourceRoot":"","sources":["../../../../../core-common/src/errors/sd-error.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,OAAQ,SAAQ,KAAK;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC;IAEvB,gEAAgE;gBACpD,KAAK,EAAE,KAAK,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE;IAC/C,kDAAkD;gBACtC,GAAG,QAAQ,EAAE,MAAM,EAAE;gBACrB,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE;CA2BlD"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { SdError } from "./sd-error";
|
|
2
|
+
/**
|
|
3
|
+
* 타임아웃 오류
|
|
4
|
+
*
|
|
5
|
+
* 대기 시간이 초과되었을 때 발생하는 에러이다.
|
|
6
|
+
* Wait.until() 등의 비동기 대기 함수에서 최대 시도 횟수를 초과하면 자동으로 발생한다.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* // Wait.until에서 자동 발생
|
|
10
|
+
* try {
|
|
11
|
+
* await Wait.until(() => isReady, 100, 50); // 100ms 간격, 최대 50회
|
|
12
|
+
* } catch (err) {
|
|
13
|
+
* if (err instanceof TimeoutError) {
|
|
14
|
+
* console.log("시간 초과");
|
|
15
|
+
* }
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // 직접 발생
|
|
20
|
+
* if (elapsed > maxTime) {
|
|
21
|
+
* throw new TimeoutError(undefined, "API 응답 대기 초과");
|
|
22
|
+
* }
|
|
23
|
+
*/
|
|
24
|
+
export declare class TimeoutError extends SdError {
|
|
25
|
+
/**
|
|
26
|
+
* @param count 시도 횟수
|
|
27
|
+
* @param message 추가 메시지
|
|
28
|
+
*/
|
|
29
|
+
constructor(count?: number, message?: string);
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=timeout-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeout-error.d.ts","sourceRoot":"","sources":["../../../../../core-common/src/errors/timeout-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,YAAa,SAAQ,OAAO;IACvC;;;OAGG;gBACS,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAM7C"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Array 확장 메서드
|
|
3
|
+
*
|
|
4
|
+
* @remarks 각 메서드의 TSDoc은 타입 정의 파일(arr-ext.types.ts) 참조
|
|
5
|
+
*/
|
|
6
|
+
import "./map-ext";
|
|
7
|
+
import type { ReadonlyArrayExt, MutableArrayExt } from "./arr-ext.types";
|
|
8
|
+
declare global {
|
|
9
|
+
interface ReadonlyArray<T> extends ReadonlyArrayExt<T> {
|
|
10
|
+
}
|
|
11
|
+
interface Array<T> extends ReadonlyArrayExt<T>, MutableArrayExt<T> {
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export type { ArrayDiffsResult, ArrayDiffs2Result, TreeArray, ComparableType } from "./arr-ext.types";
|
|
15
|
+
//# sourceMappingURL=arr-ext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arr-ext.d.ts","sourceRoot":"","sources":["../../../../../core-common/src/extensions/arr-ext.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,WAAW,CAAC;AAUnB,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EAIhB,MAAM,iBAAiB,CAAC;AA2uBzB,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,aAAa,CAAC,CAAC,CAAE,SAAQ,gBAAgB,CAAC,CAAC,CAAC;KAAG;IACzD,UAAU,KAAK,CAAC,CAAC,CAAE,SAAQ,gBAAgB,CAAC,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC;KAAG;CACtE;AAID,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Array 확장 헬퍼 함수
|
|
3
|
+
*/
|
|
4
|
+
import type { ComparableType } from "./arr-ext.types";
|
|
5
|
+
/**
|
|
6
|
+
* DateTime, DateOnly, Time을 비교 가능한 primitive 값으로 변환
|
|
7
|
+
*/
|
|
8
|
+
export declare function toComparable(value: ComparableType): string | number | boolean | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* 정렬을 위한 비교 함수
|
|
11
|
+
*
|
|
12
|
+
* @param pp 비교 대상 1
|
|
13
|
+
* @param pn 비교 대상 2
|
|
14
|
+
* @param desc true: 내림차순, false: 오름차순
|
|
15
|
+
* @returns 음수: pp가 앞, 0: 같음, 양수: pn이 앞
|
|
16
|
+
* @note null/undefined 값은 오름차순 시 앞으로, 내림차순 시 뒤로 정렬됨
|
|
17
|
+
*/
|
|
18
|
+
export declare function compareForOrder(pp: ComparableType, pn: ComparableType, desc: boolean): number;
|
|
19
|
+
//# sourceMappingURL=arr-ext.helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arr-ext.helpers.d.ts","sourceRoot":"","sources":["../../../../../core-common/src/extensions/arr-ext.helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAKzF;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAuB7F"}
|