├── utils ├── error.js ├── index.js └── const.js ├── .gitignore ├── module ├── message.js └── error.js ├── package.json ├── index.js └── README.md /utils/error.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /module/message.js: -------------------------------------------------------------------------------- 1 | function Message() { 2 | 3 | } 4 | 5 | Message.prototype.loading = () => { 6 | console.log('fetching...') 7 | } 8 | 9 | module.exports = Message -------------------------------------------------------------------------------- /module/error.js: -------------------------------------------------------------------------------- 1 | function ErrorModule() {} 2 | 3 | ErrorModule.prototype.command = (err) => { 4 | if (err) { 5 | console.log(err); 6 | } 7 | } 8 | 9 | ErrorModule.prototype.titleNotExit = () => { 10 | throw new Error("Title not exits, please enter the correct title in type-challenge"); 11 | } 12 | 13 | module.exports = ErrorModule -------------------------------------------------------------------------------- /utils/index.js: -------------------------------------------------------------------------------- 1 | const urlMap = require('./const') 2 | 3 | function getRemoteName (localName) { 4 | return urlMap[localName] 5 | } 6 | 7 | function trimTitle (args) { 8 | return args.join("") 9 | } 10 | 11 | function handleTitle (args) { 12 | return args.join("-") 13 | } 14 | 15 | module.exports = { 16 | getRemoteName, 17 | trimTitle, 18 | handleTitle 19 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "type-challenge-helper", 3 | "version": "1.0.12", 4 | "description": "", 5 | "bin": { 6 | "tch": "index.js" 7 | }, 8 | "scripts": { 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "@octokit/rest": "^18.12.0", 15 | "commander": "^9.2.0", 16 | "github-files-fetcher": "^1.6.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const path = require('path'); 4 | const fs = require('fs') 5 | const process = require('child_process'); 6 | const { cwd } = require('process'); 7 | const { Command } = require('commander'); 8 | 9 | const Message = require('./module/message') 10 | const ErrorModule = require('./module/error') 11 | 12 | const { 13 | getRemoteName, 14 | trimTitle, 15 | handleTitle 16 | } = require('./utils'); 17 | 18 | const program = new Command(); 19 | const message = new Message(); 20 | const error = new ErrorModule(); 21 | 22 | function shellAction (dirName, commandDir) { 23 | const localName = trimTitle(dirName) 24 | const remoteName = getRemoteName(localName) 25 | 26 | if (!remoteName) { 27 | error.titleNotExit() 28 | } 29 | 30 | process.exec(`fetcher --url="https://github.com/type-challenges/type-challenges/blob/main/questions/${remoteName}/template.ts"`, { 31 | cwd: path.resolve(cwd(), commandDir) 32 | }, error.command()) 33 | 34 | process.exec(`fetcher --url="https://github.com/type-challenges/type-challenges/blob/main/questions/${remoteName}/test-cases.ts"`, { 35 | cwd: path.resolve(cwd(), commandDir) 36 | }, error.command()) 37 | } 38 | 39 | program 40 | .version('0.1.0') 41 | .argument("", 'folder name') 42 | .action((dirName) => { 43 | const commandDir = handleTitle(dirName) 44 | console.log(path.resolve(cwd(), commandDir)) 45 | 46 | fs.mkdir(commandDir, {}, () => { 47 | message.loading(); 48 | shellAction(dirName, commandDir) 49 | }) 50 | }) 51 | 52 | program 53 | .command("shell") 54 | .action(() => { 55 | }) 56 | 57 | program.parse(process.argv); 58 | 59 | 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #
type-challenge-helper
2 | 3 |

4 | 5 | 6 | 7 | 8 | 9 | 10 |

11 | 12 | # Intro: 13 | This tool will help you to fetch files from type-challenge. 14 | 15 | Enable you to use [type-challenges](https://github.com/type-challenges/type-challenges) efficiently. 16 | 17 | Enable type now: 18 | 19 | - [x] warm 20 | - [x] easy 21 | - [x] medium 22 | - [ ] hard 23 | - [ ] extreme 24 | 25 | # Before use: 26 | 27 | when you use this tool, ensure you have 28 | 29 | * A folder 30 | * Install the typescript in your folder 31 | * Have tsconfig.js in your folder 32 | 33 | # Install: 34 | 35 | ``` 36 | npm install -g type-challenges-helper github-files-fetcher 37 | ``` 38 | # Usage: 39 | 40 | ![usage](https://raw.githubusercontent.com/1084350607/github-image-repo/main/type-challenge-helper/usage.webp) 41 | 42 | use like this: 43 | 44 | ``` 45 | tch (type-challenges title) 46 | ``` 47 | 48 | eg: 49 | 50 | ``` 51 | tch Pick 52 | ``` 53 | 54 | This shell will generate a dir which name is same as the title, and include two files fetch from type-challenge: 55 | `template.ts` and `test-cases.ts`. 56 | 57 | Then just write your code in `template.ts` and check it in `test-cases.ts` 58 | 59 | ✨TODO: 60 | 61 | - [x] Directly fetch the template and test-cases.ts from type-challenge 62 | - [x] implement the remaining type in const.js 63 | - [ ] handle all the errors 64 | - [ ] timeout and network error 65 | - [ ] Fetch template file and typescript config 66 | - [ ] scaffold 67 | 68 | # Not work? 69 | 70 | This tools relays on your network, if you got a empty folder, follew the below: 71 | 72 | ## Setp1: 73 | ensure you install the whole deps, run the command in your termainal 74 | 75 | ``` 76 | tch 77 | ``` 78 | then 79 | ``` 80 | fetcher 81 | ``` 82 | 83 | ## step2: 84 | try to fetch files from github 85 | 86 | ``` 87 | fetcher --url=https://github.com/type-challenges/type-challenges/blob/main/questions/00191-medium-append-argument/template.ts 88 | ``` 89 | 90 | if no files, means your network is bad, try to improve that 91 | -------------------------------------------------------------------------------- /utils/const.js: -------------------------------------------------------------------------------- 1 | const easyMap = { 2 | "If": "00268-easy-if", 3 | "HelloWorld": "00013-warm-hello-world", 4 | "Pick": "00004-easy-pick", 5 | "Readonly": "00007-easy-readonly", 6 | "TupletoObject": "00011-easy-tuple-to-object", 7 | "FirstofArray": "00014-easy-first", 8 | "LengthofTuple":"00018-easy-tuple-length", 9 | "Exclude":"00043-easy-exclude", 10 | "Awaited":"00189-easy-awaited", 11 | "Concat":"00533-easy-concat", 12 | "Includes": "00898-easy-includes", 13 | "Push":"03057-easy-push", 14 | "Unshift": "03060-easy-unshift", 15 | "Parameters": "03312-easy-parameters" 16 | } 17 | 18 | const mediumMap = { 19 | "GetReturnType": "00002-medium-return-type", 20 | "Omit": "00003-medium-omit", 21 | "Readonly2": "00008-medium-readonly-2", 22 | "DeepReadonly": "00009-medium-deep-readonly", 23 | "TupletoUnion": "00010-medium-tuple-to-union", 24 | "ChainableOptions": "00012-medium-chainable-options", 25 | "LastofArray": "00015-medium-last", 26 | "Pop": "00016-medium-pop", 27 | "Promise.all": "00020-medium-promise-all", 28 | "TypeLookup": "00062-medium-type-lookup", 29 | "TrimLeft": "00106-medium-trimleft", 30 | "Trim": "00108-medium-trim", 31 | "Capitalize": "00110-medium-capitalize", 32 | "Replace": "00116-medium-replace", 33 | "ReplaceAll": "00119-medium-replaceall", 34 | "AppendArgument": "00191-medium-append-argument", 35 | "Permutation": "00296-medium-permutation", 36 | "LengthofString": "00298-medium-length-of-string", 37 | "Flatten": "00459-medium-flatten", 38 | "Appendtoobject": "00527-medium-append-to-object", 39 | "Absolute": "00529-medium-absolute", 40 | "StringtoUnion": "00531-medium-string-to-union", 41 | "Merge": "00599-medium-merge", 42 | "KebabCase": "00612-medium-kebabcase", 43 | "Diff": "00645-medium-diff", 44 | "AnyOf": "00949-medium-anyof", 45 | "IsNever": "01042-medium-isnever", 46 | "IsUnion": "01097-medium-isunion", 47 | "ReplaceKeys": "01130-medium-replacekeys", 48 | "RemoveIndexSignature": "01367-medium-remove-index-signature", 49 | "PercentageParser": "01978-medium-percentage-parser", 50 | "DropChar": "02070-medium-drop-char", 51 | "MinusOne": "02257-medium-minusone", 52 | "PickByType": "02595-medium-pickbytype", 53 | "StartsWith": "02688-medium-startswith", 54 | "EndsWith": "02693-medium-endswith", 55 | "PartialByKeys": "02757-medium-partialbykeys", 56 | "RequiredByKeys": "02759-medium-requiredbykeys", 57 | "Mutable": "02793-medium-mutable", 58 | "OmitByType": "02852-medium-omitbytype", 59 | "ObjectEntries": "02946-medium-objectentries", 60 | "Shift": "03062-medium-shift", 61 | "TupletoNestedObject": "03188-medium-tuple-to-nested-object", 62 | "Reverse": "03192-medium-reverse", 63 | "FlipArguments": "03196-medium-flip-arguments", 64 | "FlattenDepth": "03243-medium-flattendepth", 65 | "BEMStyleString": "03326-medium-bem-style-string", 66 | "InorderTraversal": "03376-medium-inordertraversal", 67 | "Flip": "04179-medium-flip", 68 | "FibonacciSequence": "04182-medium-fibonacci-sequence", 69 | "AllCombinations": "04260-medium-nomiwase", 70 | "GreaterThan": "04425-medium-greater-than", 71 | "Zip": "04471-medium-zip", 72 | "IsTuple": "04484-medium-istuple", 73 | "Chunk": "04499-medium-chunk", 74 | "Fill": "04518-medium-fill", 75 | "TrimRight": "04803-medium-trim-right", 76 | "Without": "05117-medium-without", 77 | "Trunc": "05140-medium-trunc", 78 | "IndexOf": "05153-medium-indexof", 79 | "Join": "05310-medium-join", 80 | "LastIndexOf": "05317-medium-lastindexof", 81 | "Unique": "05360-medium-unique", 82 | "MapTypes": "05821-medium-maptypes", 83 | "ConstructTuple": "07544-medium-construct-tuple", 84 | "NumberRange": "08640-medium-number-range", 85 | "Combination": "08767-medium-combination", 86 | "Subsequence": "08987-medium-subsequence" 87 | } 88 | 89 | const urlMap = { 90 | ...easyMap, 91 | ...mediumMap 92 | } 93 | module.exports = urlMap --------------------------------------------------------------------------------