create-task-ops 0.1.4 → 0.1.6
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 +17 -6
- package/bin/create-task-ops.js +24 -11
- package/package.json +1 -1
- package/templates/api/app/api/{health → orbitops/health}/route.ts +1 -1
- package/templates/{full/app/api → api/app/api/orbitops}/tasks/[id]/route.ts +1 -1
- package/templates/{full/app/api → api/app/api/orbitops}/tasks/route.ts +1 -1
- package/templates/api/app/page.tsx +2 -2
- package/templates/common/docs/DASHBOARD_CONNECTION.md +5 -5
- package/templates/common/docs/TASK_API_CONTRACT.md +4 -4
- package/templates/docs/README.md +1 -1
- package/templates/full/app/api/{health → orbitops/health}/route.ts +1 -1
- package/templates/{api/app/api → full/app/api/orbitops}/tasks/[id]/route.ts +1 -1
- package/templates/{api/app/api → full/app/api/orbitops}/tasks/route.ts +1 -1
- package/templates/full/app/page.tsx +3 -3
- /package/templates/api/lib/{task-api.ts → orbitops/task-api.ts} +0 -0
- /package/templates/full/lib/{task-api.ts → orbitops/task-api.ts} +0 -0
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
- 새 리포를 빠르게 시작
|
|
8
8
|
- 기존 리포에 task-ops 구조 주입
|
|
9
|
-
- `tasks/*.md` 와
|
|
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 +
|
|
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`
|
|
61
|
-
- `lib/task-api.ts`
|
|
58
|
+
- `app/api/orbitops/health/route.ts`
|
|
59
|
+
- `app/api/orbitops/tasks/route.ts`
|
|
60
|
+
- `app/api/orbitops/tasks/[id]/route.ts`
|
|
61
|
+
- `lib/orbitops/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/orbitops/task-api.ts`
|
|
73
|
+
|
|
74
|
+
이 receiver 파일까지 강제로 교체하려면 `--force` 를 쓴다.
|
|
75
|
+
|
|
65
76
|
## 로컬 테스트
|
|
66
77
|
|
|
67
78
|
```bash
|
package/bin/create-task-ops.js
CHANGED
|
@@ -9,10 +9,10 @@ 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",
|
|
15
|
-
"lib/task-api.ts",
|
|
12
|
+
"app/api/orbitops/health/route.ts",
|
|
13
|
+
"app/api/orbitops/tasks/route.ts",
|
|
14
|
+
"app/api/orbitops/tasks/[id]/route.ts",
|
|
15
|
+
"lib/orbitops/task-api.ts",
|
|
16
16
|
];
|
|
17
17
|
|
|
18
18
|
function parseArgs(argv) {
|
|
@@ -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("
|
|
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
|
-
|
|
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,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__
|
|
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에 연결하려면 이 리포의
|
|
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
|
-
#
|
|
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
|
|
package/templates/docs/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getTasks } from "@/lib/task-api";
|
|
1
|
+
import { getTasks } from "@/lib/orbitops/task-api";
|
|
2
2
|
|
|
3
3
|
export default async function Home() {
|
|
4
4
|
const tasks = await getTasks();
|
|
@@ -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">
|
|
10
|
+
<span className="eyebrow">OrbitOps</span>
|
|
11
11
|
<h1>__PROJECT_NAME__</h1>
|
|
12
|
-
<p>이 프로젝트는 task-first 운영 구조와 Next.js 기반
|
|
12
|
+
<p>이 프로젝트는 task-first 운영 구조와 Next.js 기반 OrbitOps API를 기본으로 시작한다.</p>
|
|
13
13
|
</div>
|
|
14
14
|
</section>
|
|
15
15
|
<section className="task-grid">
|
|
File without changes
|
|
File without changes
|