feat: watch mode
This commit is contained in:
		
							parent
							
								
									d2010834b7
								
							
						
					
					
						commit
						eebea195ab
					
				
					 2 changed files with 222 additions and 61 deletions
				
			
		| 
						 | 
				
			
			@ -1,79 +1,105 @@
 | 
			
		|||
 | 
			
		||||
import {Issue} from "./githubType.ts";
 | 
			
		||||
import {readAll} from "https://deno.land/std@0.135.0/streams/mod.ts"
 | 
			
		||||
import {parse as argParse} from "https://deno.land/std@0.135.0/flags/mod.ts";
 | 
			
		||||
import {normalize, join as pathJoin, fromFileUrl} from "https://deno.land/std@0.135.0/path/mod.ts";
 | 
			
		||||
import { Issue } from "./githubType.ts";
 | 
			
		||||
import { readAll } from "https://deno.land/std@0.135.0/streams/mod.ts"
 | 
			
		||||
import { parse as argParse } from "https://deno.land/std@0.135.0/flags/mod.ts";
 | 
			
		||||
import { normalize, join as pathJoin, fromFileUrl } from "https://deno.land/std@0.135.0/path/mod.ts";
 | 
			
		||||
import * as Eta from "https://deno.land/x/eta/mod.ts";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function printOverall(issues: Issue[]){
 | 
			
		||||
    const table = new Map<string,Issue[]>();
 | 
			
		||||
    issues.forEach((x)=>{
 | 
			
		||||
        const category = x.title.split(":")[0];
 | 
			
		||||
        if(!category) return;
 | 
			
		||||
        let c = table.get(category)
 | 
			
		||||
        if(!c){
 | 
			
		||||
            c = []
 | 
			
		||||
            table.set(category,c);
 | 
			
		||||
        }
 | 
			
		||||
        c.push(x);
 | 
			
		||||
    })
 | 
			
		||||
    let index = 1;
 | 
			
		||||
    for (const [c,issues] of table) {
 | 
			
		||||
        console.log(`### 2.2.${index++} ${c} Operation\n`);
 | 
			
		||||
        let subIndex = 1;
 | 
			
		||||
        for (const i of issues) {
 | 
			
		||||
            console.log(`${subIndex++}. #${i.number} ${i.title}`);
 | 
			
		||||
        }
 | 
			
		||||
        console.log("");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function printContent(issues: Issue[]){
 | 
			
		||||
    console.log(issues.map(i => `## (${i.number}) ${i.title}\n${i.body}`).join("\n\n"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function readContent(path?: string):Promise<string>{
 | 
			
		||||
async function readContent(path?: string): Promise<string> {
 | 
			
		||||
    let content = "[]";
 | 
			
		||||
    if(path){
 | 
			
		||||
    if (path) {
 | 
			
		||||
        content = await Deno.readTextFile(path);
 | 
			
		||||
    }
 | 
			
		||||
    else if(!Deno.isatty(Deno.stdin.rid)){
 | 
			
		||||
        const decoder = new TextDecoder(undefined, {ignoreBOM:true});
 | 
			
		||||
    else if (!Deno.isatty(Deno.stdin.rid)) {
 | 
			
		||||
        const decoder = new TextDecoder(undefined, { ignoreBOM: true });
 | 
			
		||||
        const buf = await readAll(Deno.stdin);
 | 
			
		||||
        content = decoder.decode(buf);
 | 
			
		||||
    }
 | 
			
		||||
    return content;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if(import.meta.main){
 | 
			
		||||
    const args = argParse(Deno.args);
 | 
			
		||||
    
 | 
			
		||||
    const url = new URL(import.meta.url)
 | 
			
		||||
    url.pathname = normalize(pathJoin(url.pathname,"..","template"));
 | 
			
		||||
    const path = fromFileUrl(url);
 | 
			
		||||
    Eta.configure({views: path});
 | 
			
		||||
    
 | 
			
		||||
    if(typeof args.path !== "string"){
 | 
			
		||||
async function readAndPrint(args: {
 | 
			
		||||
    path?: string,
 | 
			
		||||
    overall?: boolean,
 | 
			
		||||
    outpath?: string
 | 
			
		||||
}) {
 | 
			
		||||
    const c = await readContent(args.path);
 | 
			
		||||
    const issues = JSON.parse(c) as Issue[];
 | 
			
		||||
    issues.sort((a, b) => a.number - b.number);
 | 
			
		||||
    let print: string = "";
 | 
			
		||||
    if (args.overall) {
 | 
			
		||||
        print = await Eta.renderFile("overall.md.eta", {
 | 
			
		||||
            issues: issues
 | 
			
		||||
        }) as string;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        print = await Eta.renderFile("sr.md.eta", {
 | 
			
		||||
            issues: issues
 | 
			
		||||
        }) as string;
 | 
			
		||||
    }
 | 
			
		||||
    if (args.outpath) {
 | 
			
		||||
        Deno.writeTextFileSync(args.outpath, print);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        console.log(print);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function main() {
 | 
			
		||||
    const parsedArg = argParse(Deno.args);
 | 
			
		||||
    const { path, outpath, overall, w } = parsedArg;
 | 
			
		||||
 | 
			
		||||
    if (typeof path !== "undefined" && typeof path !== "string") {
 | 
			
		||||
        console.log("Please provide a path to the json file.");
 | 
			
		||||
        Deno.exit(1);
 | 
			
		||||
    }
 | 
			
		||||
    const c = await readContent(args.path);
 | 
			
		||||
    const issues = JSON.parse(c) as Issue[];
 | 
			
		||||
    if (typeof outpath !== "undefined" && typeof outpath !== "string") {
 | 
			
		||||
        console.log("Please provide a path to the output file.");
 | 
			
		||||
        Deno.exit(1);
 | 
			
		||||
    }
 | 
			
		||||
    if (typeof overall !== "undefined" && typeof overall !== "boolean") {
 | 
			
		||||
        console.log("Please provide a boolean value for overall.");
 | 
			
		||||
        Deno.exit(1);
 | 
			
		||||
    }
 | 
			
		||||
    if (typeof w !== "undefined" && typeof w !== "boolean") {
 | 
			
		||||
        console.log("Please provide a boolean value for w.");
 | 
			
		||||
        Deno.exit(1);
 | 
			
		||||
    }
 | 
			
		||||
    if (w && typeof path === "undefined") {
 | 
			
		||||
        console.log("Could not set watch mode without a path.");
 | 
			
		||||
        Deno.exit(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let print: string = "";
 | 
			
		||||
    if(args.overall){
 | 
			
		||||
        print = await Eta.renderFile("overall.md.eta",{
 | 
			
		||||
            issues: issues.sort((a,b)=>a.number-b.number)
 | 
			
		||||
        }) as string;
 | 
			
		||||
    }
 | 
			
		||||
    else{
 | 
			
		||||
        printContent(issues);
 | 
			
		||||
    }
 | 
			
		||||
    if(args.outpath){
 | 
			
		||||
        Deno.writeTextFileSync(args.outpath,print);
 | 
			
		||||
    }
 | 
			
		||||
    else{
 | 
			
		||||
        console.log(print);
 | 
			
		||||
    const url = new URL(import.meta.url)
 | 
			
		||||
    url.pathname = normalize(pathJoin(url.pathname, "..", "template"));
 | 
			
		||||
    const viewPath = fromFileUrl(url);
 | 
			
		||||
    Eta.configure({
 | 
			
		||||
        views: viewPath,
 | 
			
		||||
        "view cache": false,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const c = await readContent(path);
 | 
			
		||||
    const issues = JSON.parse(c) as Issue[];
 | 
			
		||||
    issues.sort((a, b) => a.number - b.number);
 | 
			
		||||
    await readAndPrint({ path, outpath, overall });
 | 
			
		||||
    if (w) {
 | 
			
		||||
        const watcher = Deno.watchFs([viewPath, path as string]);
 | 
			
		||||
        for await (const event of watcher) {
 | 
			
		||||
            if (event.kind === "modify") {
 | 
			
		||||
                Deno.stdout.write(
 | 
			
		||||
                    new TextEncoder().encode("\x1b[2J\x1b[0f"),
 | 
			
		||||
                );
 | 
			
		||||
                console.log(`reloading ${event.paths.join(", ")}`);
 | 
			
		||||
                readAndPrint({
 | 
			
		||||
                    path: path as string,
 | 
			
		||||
                    overall: overall as boolean,
 | 
			
		||||
                    outpath: outpath as string
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if (import.meta.main) {
 | 
			
		||||
    main();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										135
									
								
								tools/template/sr.md.eta
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								tools/template/sr.md.eta
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,135 @@
 | 
			
		|||
# 3. 상세요구사항(Specific Requirements)
 | 
			
		||||
 | 
			
		||||
> - 설계자가 요구사항을 만족하는 시스템을 설계할 수 있도록 모든 요구사항을 상세하게 포함해야 한다.
 | 
			
		||||
> - 테스터가 시스템이 위 요건을 충족하는지 테스트해야 한다.
 | 
			
		||||
> - 모든 요구사항은 사용자, 운영자, 다른 외부 시스템에 의해 외부적으로 인지할 수 있어야 한다.
 | 
			
		||||
> - 이 요구사항에는 시스템에 대한 모든 입력(자극)과 출력(응답) 그리고 입력 또는 출력 지원에 대한 응답으로 실행되는 모든 기능에 관한 설명이 포함되어야 한다.
 | 
			
		||||
> - 상세 요구사항을 작성하기 위한 원칙
 | 
			
		||||
>   1. 상세 요구사항은 "Characteristics of a good SRS"에 설명한 모든 특성을 준수하도록 작성되어야 한다.
 | 
			
		||||
>   1. 상세 요구사항은 관련이 있는 이전 문서들과 상호 참조되어야 한다.
 | 
			
		||||
>   1. 모든 요구사항은 고유하게 식별할 수 있어야 한다.
 | 
			
		||||
>   1. 가독성을 높이기 위해 요구사항을 구성할 때 주의를 기울여야 한다.
 | 
			
		||||
 | 
			
		||||
## 3.1. 외부 인터페이스 요구사항(External interface requirements)
 | 
			
		||||
 | 
			
		||||
해당되지 않음.
 | 
			
		||||
## 3.2. 기능 요구사항(Functional requirements)
 | 
			
		||||
 | 
			
		||||
<%~ it.issues.map(i => `### (${i.number}) ${i.title}\n${i.body}`).join("\n\n") %>
 | 
			
		||||
 | 
			
		||||
> - 기능 요구사항은 소프트웨어가 입력을 처리하고 출력을 생성하는 기본적인 행동을 정의해야 한다.
 | 
			
		||||
> - 포함하는 행동들
 | 
			
		||||
>   1. Validity checks on the inputs
 | 
			
		||||
>   1. Exact sequence of operations
 | 
			
		||||
>   1. Responses to abnormal situations, including
 | 
			
		||||
>      1. Overflow
 | 
			
		||||
>      1. Communication facilities
 | 
			
		||||
>      1. Error handling and recovery
 | 
			
		||||
>   1. Effect of parameters
 | 
			
		||||
>   1. Relationship of outputs to inputs, including
 | 
			
		||||
>      1. Input/output sequences
 | 
			
		||||
>      1. Formulas for input to output conversion
 | 
			
		||||
 | 
			
		||||
## 3.3. 성능 요구사항(Performance requirements)
 | 
			
		||||
 | 
			
		||||
> - 소프트웨어 또는 소프트웨어와 사람의 상호작용에 대하여 수치화된 정적/동적 요구사항이 명시되어야 한다.
 | 
			
		||||
> - 수치화된 정적 요구사항의 종류
 | 
			
		||||
>   1. 지원할 터미널 수
 | 
			
		||||
>   1. 지원할 동시 접속 사용자 수
 | 
			
		||||
>   1. 처리할 정보의 양과 유형작업 및 데이터의 양
 | 
			
		||||
 | 
			
		||||
## 3.4. 논리적 데이터베이스 요구사항(Logical database requirements)
 | 
			
		||||
 | 
			
		||||
> - 데이터베이스에 저장할 정보에 관한 논리적 요구사항을 지정해야 한다.
 | 
			
		||||
> - 논리적 요구사항의 종류
 | 
			
		||||
>   1. Types of information used by various functuons
 | 
			
		||||
>   1. Frequency of use
 | 
			
		||||
>   1. Accessing capabilities
 | 
			
		||||
>   1. Data entities and their relationships
 | 
			
		||||
>   1. Integrity constraints
 | 
			
		||||
>   1. Data retention requirements
 | 
			
		||||
 | 
			
		||||
## 3.5. 설계 제약사항(Design constraints)
 | 
			
		||||
 | 
			
		||||
> - 다른 표준, 하드웨어 한계 등에 의해 부과될 수 있는 설계 제약사항을 명시해야 한다.
 | 
			
		||||
 | 
			
		||||
### 3.5.1. 표준 준수(Standards compliance)
 | 
			
		||||
 | 
			
		||||
해당되지 않음.
 | 
			
		||||
## 3.6. 소프트웨어 시스템 속성(Software system attributes)
 | 
			
		||||
 | 
			
		||||
> - 요구사항으로 사용될 수 있는 소프트웨어의 여러 가지 속성 중 제품이 객관적으로 입증되는 데 필요한 속성을 명시해야 한다.
 | 
			
		||||
 | 
			
		||||
### 3.6.1. 신뢰성(Reliability)
 | 
			
		||||
 | 
			
		||||
> - 배포될 때 소프트웨어 시스템의 필수 신뢰성을 확립하는 데 필요한 요소를 명시해야 한다.
 | 
			
		||||
 | 
			
		||||
### 3.6.2. 가용성(Availability)
 | 
			
		||||
 | 
			
		||||
> - 검사, 복구, 재시작과 같이 전체 시스템에 대해 정의된 가용성 수준을 보장하는 데 필요한 요소가 지정되어야 한다.
 | 
			
		||||
 | 
			
		||||
### 3.6.3. 보안성(Security)
 | 
			
		||||
 | 
			
		||||
> - 실수 또는 악의적인 접근, 사용, 수정, 파괴, 공개로부터 소프트웨어를 보호하기 위한 요소를 명시해야 한다.
 | 
			
		||||
> - 포함될 수 있는 요구사항
 | 
			
		||||
>   1. Utilize certain cryptographical techinques
 | 
			
		||||
>   1. Keep specific log or history data sets
 | 
			
		||||
>   1. Assign certain functions to diffrent modules
 | 
			
		||||
>   1. Restrict communication between some areas of the program
 | 
			
		||||
>   1. Check data integrity for critical variables
 | 
			
		||||
 | 
			
		||||
### 3.6.4. 유지 보수성(Maintainability)
 | 
			
		||||
 | 
			
		||||
> - 소프트웨어 자체를 쉽게 유지 보수할 수 있는 속성을 명시해야 한다.
 | 
			
		||||
> - 모듈화, 인터페이스, 복잡성 등과 관련된 요구사항이 있을 수 있다.
 | 
			
		||||
 | 
			
		||||
### 3.6.5. 이식성(Portability)
 | 
			
		||||
 | 
			
		||||
해당되지 않음.
 | 
			
		||||
 | 
			
		||||
## 3.7. 상세 요구사항의 구성(Organizing the specific requirements)
 | 
			
		||||
 | 
			
		||||
> - 시스템의 세부 요구사항은 광범위한 경향이 있으므로 자료를 이해하기에 가장 적합한 방식으로 구성하는 방법을 세심하게 고려해야 한다.
 | 
			
		||||
 | 
			
		||||
### 3.7.1. 시스템 모드(System mode)
 | 
			
		||||
 | 
			
		||||
> - 일부 시스템은 운영 모드에 따라 상당히 다르게 작동할 수 있다.
 | 
			
		||||
>   - 예: 제어 시스템은 연습, 일반, 긴급 등의 여러 모드가 있을 수 있다.
 | 
			
		||||
 | 
			
		||||
### 3.7.2. 사용자 부류(User class)
 | 
			
		||||
 | 
			
		||||
> - 일부 시스템은 사용자의 부류에 따라 서로 다른 기능을 제공한다.
 | 
			
		||||
>   - 예: 엘리베이터 제어 시스템은 승객, 정비원, 소방관에게 서로 다른 기능을 제공한다.
 | 
			
		||||
 | 
			
		||||
### 3.7.3. 객체(Objects)
 | 
			
		||||
 | 
			
		||||
> - 객체는 시스템에서 현실 세계와 대응되는 개체이다.
 | 
			
		||||
> - 객체에는 각 각체의 상태(attributes) 및 객체의 행위(functions)가 포함된다.
 | 
			
		||||
>   - 이러한 행위는 services, methods, processes라고도 한다.
 | 
			
		||||
 | 
			
		||||
### 3.7.4. 특징(Feature)
 | 
			
		||||
 | 
			
		||||
> - 특징은 시스템에 의해 외부적으로 요구되는 서비스로서 원하는 결과를 얻기 위해서는 입력이 필요할 수도 있다.
 | 
			
		||||
>   - 예: 전화 시스템에서 특징들은 지역 내 통화, 착신 전환, 화상 통화를 포함한다.
 | 
			
		||||
> - 일반적으로 각 특징은 자극-반응의 순서로 설명된다.
 | 
			
		||||
 | 
			
		||||
### 3.7.5. 자극(Stimulus)
 | 
			
		||||
 | 
			
		||||
> - 일부 시스템은 자극의 측면에서 기능들을 설명할 때 가장 잘 구성될 수 있다.
 | 
			
		||||
>   - 예: 항공기 자동 착륙 시스템은 동력 상실, 윈드시어 등을 위해 구성될 수 있다.
 | 
			
		||||
 | 
			
		||||
### 3.7.6. 반응(Response)
 | 
			
		||||
 | 
			
		||||
> - 일부 시스템은 반응 생성을 지원하는 기능들을 설명할 때 가장 잘 구성될 수 있다.
 | 
			
		||||
>   - 예: 직원 시스템의 기능은 급여 생성과 관련된 기능들, 직원 목록 생성과 관련된 기능 등으로 구성될 수 있다.
 | 
			
		||||
 | 
			
		||||
### 3.7.7. 기능 계층(Functional hierarchy)
 | 
			
		||||
 | 
			
		||||
> - 위 조직 체계 중 유용한 수단이 없다면, 전체 기능은 공통 입력, 공통 출력 또는 공통 내부 데이터 접근에 의해 구성된 기능의 계층으로 구성될 수 있다.
 | 
			
		||||
> - 데이터 흐름 다이어그램과 데이터 사전을 사용하여 기능과 데이터 사이의 관계를 보여줄 수 있다.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### 3.7.8. Additional comments
 | 
			
		||||
 | 
			
		||||
> - 새로운 SRS를 고려할 때 두 가지 이상의 조직 기법이 적합할 수 있다.
 | 
			
		||||
>   - 이 경우 명세에 따른 시스템의 상세 요구사항에 맞춘 다중 계층의 요구사항을 구성한다.
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue