create-task-ops 0.1.1 → 0.1.3
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
|
@@ -8,36 +8,51 @@
|
|
|
8
8
|
- 기존 리포에 task-ops 구조 주입
|
|
9
9
|
- `tasks/*.md` 와 Task API 계약을 기본으로 포함
|
|
10
10
|
|
|
11
|
-
## 모드
|
|
12
|
-
|
|
13
|
-
- `full`
|
|
14
|
-
Next.js 앱, 기본 대시보드 페이지, Task API, tasks 문서 포함
|
|
15
|
-
- `api`
|
|
16
|
-
Next.js 앱, Task API 중심, 최소 페이지 포함
|
|
17
|
-
- `docs`
|
|
18
|
-
`tasks/`, `CLAUDE.md`, `AGENT.md`, 계약 문서만 포함
|
|
19
|
-
|
|
20
11
|
## 사용 예시
|
|
21
12
|
|
|
22
13
|
```bash
|
|
23
14
|
node packages/create-task-ops/bin/create-task-ops.js my-project
|
|
24
|
-
node packages/create-task-ops/bin/create-task-ops.js my-project
|
|
25
|
-
node packages/create-task-ops/bin/create-task-ops.js
|
|
15
|
+
node packages/create-task-ops/bin/create-task-ops.js create my-project
|
|
16
|
+
node packages/create-task-ops/bin/create-task-ops.js add
|
|
17
|
+
node packages/create-task-ops/bin/create-task-ops.js add --docs-only
|
|
26
18
|
```
|
|
27
19
|
|
|
28
20
|
publish 후에는 아래처럼 쓸 수 있게 설계했다.
|
|
29
21
|
|
|
30
22
|
```bash
|
|
31
23
|
npx create-task-ops my-project
|
|
32
|
-
npx create-task-ops my-project
|
|
33
|
-
npx create-task-ops
|
|
24
|
+
npx create-task-ops create my-project
|
|
25
|
+
npx create-task-ops add
|
|
26
|
+
npx create-task-ops add --docs-only
|
|
34
27
|
```
|
|
35
28
|
|
|
29
|
+
## 명령 의미
|
|
30
|
+
|
|
31
|
+
- `create-task-ops my-project`
|
|
32
|
+
새 Next.js 기반 task-ops 프로젝트 생성
|
|
33
|
+
- `create-task-ops create my-project`
|
|
34
|
+
위와 같지만 명시적으로 create를 적는 형태
|
|
35
|
+
- `create-task-ops add`
|
|
36
|
+
현재 리포에 task docs + Task API 추가
|
|
37
|
+
- `create-task-ops add --docs-only`
|
|
38
|
+
현재 리포에 문서와 task 파일 규약만 추가
|
|
39
|
+
|
|
40
|
+
## 내부 생성 타입
|
|
41
|
+
|
|
42
|
+
- `create`
|
|
43
|
+
내부적으로 `full` 템플릿을 사용한다.
|
|
44
|
+
- `add`
|
|
45
|
+
내부적으로 `api` 템플릿을 사용한다.
|
|
46
|
+
- `add --docs-only`
|
|
47
|
+
내부적으로 `docs` 템플릿을 사용한다.
|
|
48
|
+
|
|
36
49
|
## 로컬 테스트
|
|
37
50
|
|
|
38
51
|
```bash
|
|
39
52
|
npm run create-task-ops -- my-project
|
|
40
|
-
npm run create-task-ops --
|
|
53
|
+
npm run create-task-ops -- create my-project
|
|
54
|
+
npm run create-task-ops -- add
|
|
55
|
+
npm run create-task-ops -- add --docs-only
|
|
41
56
|
cd packages/create-task-ops
|
|
42
57
|
npm run smoke:full
|
|
43
58
|
```
|
package/bin/create-task-ops.js
CHANGED
|
@@ -11,21 +11,30 @@ const templatesRoot = path.join(packageRoot, "templates");
|
|
|
11
11
|
|
|
12
12
|
function parseArgs(argv) {
|
|
13
13
|
const options = {
|
|
14
|
+
command: "create",
|
|
14
15
|
name: null,
|
|
15
16
|
mode: "full",
|
|
16
|
-
|
|
17
|
+
docsOnly: false,
|
|
17
18
|
force: false,
|
|
18
19
|
};
|
|
19
20
|
|
|
20
21
|
for (let index = 0; index < argv.length; index += 1) {
|
|
21
22
|
const arg = argv[index];
|
|
23
|
+
if (arg === "create") {
|
|
24
|
+
options.command = "create";
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (arg === "add") {
|
|
28
|
+
options.command = "add";
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
22
31
|
if (arg === "--mode") {
|
|
23
32
|
options.mode = argv[index + 1] ?? "full";
|
|
24
33
|
index += 1;
|
|
25
34
|
continue;
|
|
26
35
|
}
|
|
27
|
-
if (arg === "--
|
|
28
|
-
options.
|
|
36
|
+
if (arg === "--docs-only") {
|
|
37
|
+
options.docsOnly = true;
|
|
29
38
|
continue;
|
|
30
39
|
}
|
|
31
40
|
if (arg === "--force") {
|
|
@@ -47,6 +56,14 @@ function ensureMode(mode) {
|
|
|
47
56
|
}
|
|
48
57
|
}
|
|
49
58
|
|
|
59
|
+
function printUsage() {
|
|
60
|
+
console.log("Usage:");
|
|
61
|
+
console.log(" create-task-ops <project-name>");
|
|
62
|
+
console.log(" create-task-ops create <project-name>");
|
|
63
|
+
console.log(" create-task-ops add");
|
|
64
|
+
console.log(" create-task-ops add --docs-only");
|
|
65
|
+
}
|
|
66
|
+
|
|
50
67
|
function listFiles(dir, prefix = "") {
|
|
51
68
|
const entries = readdirSync(dir);
|
|
52
69
|
return entries.flatMap((entry) => {
|
|
@@ -86,15 +103,23 @@ function copyTemplateTree(sourceDir, targetDir, projectName, force) {
|
|
|
86
103
|
|
|
87
104
|
function main() {
|
|
88
105
|
const options = parseArgs(args);
|
|
106
|
+
if (options.command === "add") {
|
|
107
|
+
options.mode = options.docsOnly ? "docs" : "api";
|
|
108
|
+
}
|
|
89
109
|
ensureMode(options.mode);
|
|
90
110
|
|
|
111
|
+
if (options.command === "create" && !options.name) {
|
|
112
|
+
printUsage();
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
|
|
91
116
|
const inferredName = options.name ? path.basename(path.resolve(process.cwd(), options.name)) : path.basename(process.cwd());
|
|
92
117
|
const projectName = inferredName || "task-ops-project";
|
|
93
|
-
const targetDir = options.
|
|
118
|
+
const targetDir = options.command === "add"
|
|
94
119
|
? process.cwd()
|
|
95
120
|
: path.resolve(process.cwd(), options.name ?? projectName);
|
|
96
121
|
|
|
97
|
-
if (
|
|
122
|
+
if (options.command === "create" && existsSync(targetDir) && readdirSync(targetDir).length > 0 && !options.force) {
|
|
98
123
|
console.error(`Target directory is not empty: ${targetDir}`);
|
|
99
124
|
console.error("Use --force if you want to write scaffold files there.");
|
|
100
125
|
process.exit(1);
|
|
@@ -110,10 +135,11 @@ function main() {
|
|
|
110
135
|
|
|
111
136
|
console.log(`create-task-ops completed`);
|
|
112
137
|
console.log(`target: ${targetDir}`);
|
|
138
|
+
console.log(`command: ${options.command}`);
|
|
113
139
|
console.log(`mode: ${options.mode}`);
|
|
114
140
|
console.log(`project: ${projectName}`);
|
|
115
141
|
console.log(`next steps:`);
|
|
116
|
-
console.log(`1. cd ${options.
|
|
142
|
+
console.log(`1. cd ${options.command === "add" ? "." : projectName}`);
|
|
117
143
|
if (options.mode !== "docs") {
|
|
118
144
|
console.log(`2. npm install`);
|
|
119
145
|
console.log(`3. npm run dev`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-task-ops",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Next.js-first task-ops scaffold generator for task docs and task APIs",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"scripts": {
|
|
29
29
|
"pack:dry-run": "npm_config_cache=/tmp/npm-cache npm pack --dry-run",
|
|
30
30
|
"smoke:full": "node ./bin/create-task-ops.js /tmp/create-task-ops-full --mode full --force",
|
|
31
|
-
"smoke:
|
|
32
|
-
"smoke:docs": "
|
|
33
|
-
"prepublishOnly": "npm run smoke:docs && npm run pack:dry-run"
|
|
31
|
+
"smoke:add": "PACKAGE_DIR=\"$PWD\"; mkdir -p /tmp/create-task-ops-add && cd /tmp/create-task-ops-add && node \"$PACKAGE_DIR/bin/create-task-ops.js\" add --force",
|
|
32
|
+
"smoke:docs": "PACKAGE_DIR=\"$PWD\"; mkdir -p /tmp/create-task-ops-docs && cd /tmp/create-task-ops-docs && node \"$PACKAGE_DIR/bin/create-task-ops.js\" add --docs-only --force",
|
|
33
|
+
"prepublishOnly": "npm run smoke:add && npm run smoke:docs && npm run pack:dry-run"
|
|
34
34
|
},
|
|
35
35
|
"publishConfig": {
|
|
36
36
|
"access": "public"
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Dashboard Connection
|
|
2
|
+
|
|
3
|
+
이 프로젝트를 중앙 task dashboard에 연결하려면 이 리포의 Task API를 외부에서 읽을 수 있어야 한다.
|
|
4
|
+
|
|
5
|
+
## 제공 엔드포인트
|
|
6
|
+
|
|
7
|
+
- `GET /api/health`
|
|
8
|
+
- `GET /api/tasks`
|
|
9
|
+
- `GET /api/tasks/:id`
|
|
10
|
+
|
|
11
|
+
## 로컬 개발 연결 예시
|
|
12
|
+
|
|
13
|
+
프로젝트를 `3000` 포트에서 띄운 경우, 중앙 대시보드의 `task-sources.json` 에 아래처럼 추가한다.
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"sources": [
|
|
18
|
+
{
|
|
19
|
+
"id": "__PROJECT_NAME__",
|
|
20
|
+
"label": "__PROJECT_NAME__",
|
|
21
|
+
"type": "remote",
|
|
22
|
+
"baseUrl": "http://127.0.0.1:3000",
|
|
23
|
+
"enabled": true,
|
|
24
|
+
"timeoutMs": 3000
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## 체크리스트
|
|
31
|
+
|
|
32
|
+
1. `tasks/*.md` 가 최신 상태인가
|
|
33
|
+
2. `/api/tasks` 응답이 정상인가
|
|
34
|
+
3. source `id` 와 `label` 이 명확한가
|
|
35
|
+
4. 필요하면 API key 또는 reverse proxy 를 설정했는가
|
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000";
|
|
3
|
-
const response = await fetch(`${baseUrl}/api/tasks`, { cache: "no-store" }).catch(() => null);
|
|
4
|
-
if (!response?.ok) {
|
|
5
|
-
return [];
|
|
6
|
-
}
|
|
7
|
-
const payload = (await response.json()) as { tasks?: Array<{ id: string; title: string; status: string; progress: number; nextAction: string }> };
|
|
8
|
-
return payload.tasks ?? [];
|
|
9
|
-
}
|
|
1
|
+
import { getTasks } from "@/lib/task-api";
|
|
10
2
|
|
|
11
3
|
export default async function Home() {
|
|
12
4
|
const tasks = await getTasks();
|