create-task-ops 0.1.4 → 0.1.5

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 CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  - 새 리포를 빠르게 시작
8
8
  - 기존 리포에 task-ops 구조 주입
9
- - `tasks/*.md` 와 Task API 계약을 기본으로 포함
9
+ - `tasks/*.md` 와 OrbitOps API 계약을 기본으로 포함
10
10
 
11
11
  ## 사용 예시
12
12
 
@@ -33,7 +33,7 @@ npx create-task-ops add --docs-only
33
33
  - `create-task-ops create my-project`
34
34
  위와 같지만 명시적으로 create를 적는 형태
35
35
  - `create-task-ops add`
36
- 현재 리포에 task docs + Task API 추가
36
+ 현재 리포에 task docs + OrbitOps API 추가
37
37
  - `create-task-ops add --docs-only`
38
38
  현재 리포에 문서와 task 파일 규약만 추가
39
39
 
@@ -55,13 +55,24 @@ npx create-task-ops add --docs-only
55
55
  - `AGENT.md`
56
56
  - `docs/TASK_API_CONTRACT.md`
57
57
  - `docs/DASHBOARD_CONNECTION.md`
58
- - `app/api/health/route.ts`
59
- - `app/api/tasks/route.ts`
60
- - `app/api/tasks/[id]/route.ts`
58
+ - `app/api/orbitops/health/route.ts`
59
+ - `app/api/orbitops/tasks/route.ts`
60
+ - `app/api/orbitops/tasks/[id]/route.ts`
61
61
  - `lib/task-api.ts`
62
62
 
63
63
  즉 기존 `package.json`, `app/page.tsx`, `app/layout.tsx`, `tsconfig.json` 같은 루트 파일은 건드리지 않는다.
64
64
 
65
+ 기본 동작에서 기존 `CLAUDE.md`, `AGENT.md`, `tasks/*`, `docs/*` 같은 운영 문서는 스킵한다.
66
+
67
+ 대신 아래 receiver 경로가 이미 있으면 충돌 가능성이 크므로 경고 후 중단한다.
68
+
69
+ - `app/api/orbitops/health/route.ts`
70
+ - `app/api/orbitops/tasks/route.ts`
71
+ - `app/api/orbitops/tasks/[id]/route.ts`
72
+ - `lib/task-api.ts`
73
+
74
+ 이 receiver 파일까지 강제로 교체하려면 `--force` 를 쓴다.
75
+
65
76
  ## 로컬 테스트
66
77
 
67
78
  ```bash
@@ -9,9 +9,9 @@ const args = process.argv.slice(2);
9
9
  const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
10
10
  const templatesRoot = path.join(packageRoot, "templates");
11
11
  const addApiFiles = [
12
- "app/api/health/route.ts",
13
- "app/api/tasks/route.ts",
14
- "app/api/tasks/[id]/route.ts",
12
+ "app/api/orbitops/health/route.ts",
13
+ "app/api/orbitops/tasks/route.ts",
14
+ "app/api/orbitops/tasks/[id]/route.ts",
15
15
  "lib/task-api.ts",
16
16
  ];
17
17
 
@@ -86,7 +86,7 @@ function renderTemplate(content, projectName) {
86
86
  return content.replaceAll("__PROJECT_NAME__", projectName);
87
87
  }
88
88
 
89
- function copyTemplateTree(sourceDir, targetDir, projectName, force) {
89
+ function copyTemplateTree(sourceDir, targetDir, projectName, force, skipExisting = false) {
90
90
  mkdirSync(targetDir, { recursive: true });
91
91
  const files = listFiles(sourceDir);
92
92
 
@@ -96,6 +96,11 @@ function copyTemplateTree(sourceDir, targetDir, projectName, force) {
96
96
  const targetFolder = path.dirname(targetPath);
97
97
  mkdirSync(targetFolder, { recursive: true });
98
98
 
99
+ if (existsSync(targetPath) && skipExisting && !force) {
100
+ console.log(`Skipping existing file: ${targetPath}`);
101
+ continue;
102
+ }
103
+
99
104
  if (existsSync(targetPath) && !force) {
100
105
  console.error(`Refusing to overwrite existing file: ${targetPath}`);
101
106
  console.error("Use --force if you want to replace scaffolded files.");
@@ -107,7 +112,7 @@ function copyTemplateTree(sourceDir, targetDir, projectName, force) {
107
112
  }
108
113
  }
109
114
 
110
- function copySelectedFiles(sourceDir, targetDir, projectName, force, selectedFiles) {
115
+ function copySelectedFiles(sourceDir, targetDir, projectName, force, selectedFiles, skipExisting = false) {
111
116
  mkdirSync(targetDir, { recursive: true });
112
117
 
113
118
  for (const relativeFile of selectedFiles) {
@@ -116,9 +121,15 @@ function copySelectedFiles(sourceDir, targetDir, projectName, force, selectedFil
116
121
  const targetFolder = path.dirname(targetPath);
117
122
  mkdirSync(targetFolder, { recursive: true });
118
123
 
124
+ if (existsSync(targetPath) && skipExisting && !force) {
125
+ console.log(`Skipping existing file: ${targetPath}`);
126
+ continue;
127
+ }
128
+
119
129
  if (existsSync(targetPath) && !force) {
120
- console.error(`Refusing to overwrite existing file: ${targetPath}`);
121
- console.error("Use --force if you want to replace scaffolded files.");
130
+ console.error(`Refusing to overwrite existing receiver file: ${targetPath}`);
131
+ console.error("This path is reserved for task API integration.");
132
+ console.error("Use --force if you want to replace the existing receiver files.");
122
133
  process.exit(1);
123
134
  }
124
135
 
@@ -156,12 +167,14 @@ function main() {
156
167
  const commonDir = path.join(templatesRoot, "common");
157
168
  const modeDir = path.join(templatesRoot, options.mode);
158
169
 
159
- copyTemplateTree(commonDir, targetDir, projectName, options.force);
170
+ const skipExistingDocs = options.command === "add";
171
+
172
+ copyTemplateTree(commonDir, targetDir, projectName, options.force, skipExistingDocs);
160
173
 
161
174
  if (options.command === "add" && options.mode === "api") {
162
- copySelectedFiles(modeDir, targetDir, projectName, options.force, addApiFiles);
175
+ copySelectedFiles(modeDir, targetDir, projectName, options.force, addApiFiles, false);
163
176
  } else {
164
- copyTemplateTree(modeDir, targetDir, projectName, options.force);
177
+ copyTemplateTree(modeDir, targetDir, projectName, options.force, skipExistingDocs);
165
178
  }
166
179
 
167
180
  console.log(`create-task-ops completed`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-task-ops",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Next.js-first task-ops scaffold generator for task docs and task APIs",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -6,7 +6,7 @@ export const dynamic = "force-dynamic";
6
6
  export async function GET() {
7
7
  return NextResponse.json({
8
8
  ok: true,
9
- service: "__PROJECT_NAME__-task-api",
9
+ service: "__PROJECT_NAME__-orbitops-api",
10
10
  updatedAt: new Date().toISOString(),
11
11
  });
12
12
  }
@@ -1,8 +1,8 @@
1
1
  export default function Home() {
2
2
  return (
3
3
  <main style={{ padding: 32, fontFamily: "sans-serif" }}>
4
- <h1>__PROJECT_NAME__ Task API</h1>
5
- <p>`/api/health`, `/api/tasks`, `/api/tasks/:id` 를 통해 중앙 대시보드와 연동한다.</p>
4
+ <h1>__PROJECT_NAME__ OrbitOps API</h1>
5
+ <p>`/api/orbitops/health`, `/api/orbitops/tasks`, `/api/orbitops/tasks/:id` 를 통해 중앙 대시보드와 연동한다.</p>
6
6
  </main>
7
7
  );
8
8
  }
@@ -1,12 +1,12 @@
1
1
  # Dashboard Connection
2
2
 
3
- 이 프로젝트를 중앙 task dashboard에 연결하려면 이 리포의 Task API를 외부에서 읽을 수 있어야 한다.
3
+ 이 프로젝트를 중앙 task dashboard에 연결하려면 이 리포의 OrbitOps API를 외부에서 읽을 수 있어야 한다.
4
4
 
5
5
  ## 제공 엔드포인트
6
6
 
7
- - `GET /api/health`
8
- - `GET /api/tasks`
9
- - `GET /api/tasks/:id`
7
+ - `GET /api/orbitops/health`
8
+ - `GET /api/orbitops/tasks`
9
+ - `GET /api/orbitops/tasks/:id`
10
10
 
11
11
  ## 로컬 개발 연결 예시
12
12
 
@@ -30,6 +30,6 @@
30
30
  ## 체크리스트
31
31
 
32
32
  1. `tasks/*.md` 가 최신 상태인가
33
- 2. `/api/tasks` 응답이 정상인가
33
+ 2. `/api/orbitops/tasks` 응답이 정상인가
34
34
  3. source `id` 와 `label` 이 명확한가
35
35
  4. 필요하면 API key 또는 reverse proxy 를 설정했는가
@@ -1,12 +1,12 @@
1
- # Task API Contract
1
+ # OrbitOps API Contract
2
2
 
3
3
  중앙 대시보드가 외부 리포를 읽기 위해 기대하는 최소 계약이다.
4
4
 
5
5
  ## Endpoints
6
6
 
7
- - `GET /api/health`
8
- - `GET /api/tasks`
9
- - `GET /api/tasks/:id`
7
+ - `GET /api/orbitops/health`
8
+ - `GET /api/orbitops/tasks`
9
+ - `GET /api/orbitops/tasks/:id`
10
10
 
11
11
  ## Task Fields
12
12
 
@@ -13,4 +13,4 @@ Task-ops 문서 모드로 생성된 프로젝트다.
13
13
 
14
14
  1. `tasks/example-task.md` 를 실제 작업으로 교체
15
15
  2. 리포 규약에 맞게 `CLAUDE.md`, `AGENT.md` 조정
16
- 3. 필요해지면 Next.js Task API를 추가
16
+ 3. 필요해지면 Next.js OrbitOps API를 추가
@@ -6,7 +6,7 @@ export const dynamic = "force-dynamic";
6
6
  export async function GET() {
7
7
  return NextResponse.json({
8
8
  ok: true,
9
- service: "__PROJECT_NAME__-task-api",
9
+ service: "__PROJECT_NAME__-orbitops-api",
10
10
  updatedAt: new Date().toISOString(),
11
11
  });
12
12
  }
@@ -7,9 +7,9 @@ export default async function Home() {
7
7
  <main className="page-shell">
8
8
  <section className="hero">
9
9
  <div className="hero-card">
10
- <span className="eyebrow">Task Ops</span>
10
+ <span className="eyebrow">OrbitOps</span>
11
11
  <h1>__PROJECT_NAME__</h1>
12
- <p>이 프로젝트는 task-first 운영 구조와 Next.js 기반 Task API를 기본으로 시작한다.</p>
12
+ <p>이 프로젝트는 task-first 운영 구조와 Next.js 기반 OrbitOps API를 기본으로 시작한다.</p>
13
13
  </div>
14
14
  </section>
15
15
  <section className="task-grid">