From cefbbcbda23fc4caaad0fd3b9a5968d7b1adc96e Mon Sep 17 00:00:00 2001 From: Daniel Perez Alvarez Date: Sun, 2 Jul 2023 09:56:51 -0400 Subject: [PATCH] feat: add --stdin flag (#296) * feat: add --stdin flag * refactor: use get-stdin package * chore: fix getStdin call * chore: add test for --stdin flag * chore: adjust --stdin flag description * chore: move get-stream to devDependency * chore: fix extra line at eof * refactor: use testCLI for testing --stdin flag * chore: add test for \r\n https://github.com/keithamus/sort-package-json/pull/296#discussion_r1170890491 * chore: update test for \r\n https://github.com/keithamus/sort-package-json/pull/296#discussion_r1170896656 --- README.md | 8 +++++++ cli.js | 10 ++++++++ package-lock.json | 17 ++++++++++++++ package.json | 1 + tests/_helpers.js | 19 +++++++++++---- tests/cli.js | 12 ++++++++++ tests/snapshots/cli.js.md | 45 ++++++++++++++++++++++++++++++++++++ tests/snapshots/cli.js.snap | Bin 3820 -> 3992 bytes 8 files changed, 107 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 225dc958..f4c9e9be 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,14 @@ $ sort-package-json "**/package.json" --check --quiet $ sort-package-json "**/package.json" --quiet ``` +### `--stdin` flag + +To read from `stdin` and output the result to `stdout` use the `--stdin` flag. + +```bash +$ cat package.json | sort-package-json --stdin +``` + ## API ### Install diff --git a/cli.js b/cli.js index e1cb7bd9..8263ffa0 100755 --- a/cli.js +++ b/cli.js @@ -1,6 +1,7 @@ #!/usr/bin/env node import { globbySync } from 'globby' import fs from 'node:fs' +import getStdin from 'get-stdin' import sortPackageJson from './index.js' import Reporter from './reporter.js' @@ -23,6 +24,7 @@ If file/glob is omitted, './package.json' file will be processed. -q, --quiet Don't output success messages -h, --help Display this help -v, --version Display the package version + --stdin Read package.json from stdin `, ) } @@ -57,6 +59,10 @@ function sortPackageJsonFiles(patterns, options) { reporter.printSummary() } +async function sortPackageJsonFromStdin() { + process.stdout.write(sortPackageJson(await getStdin())) +} + function run() { const cliArguments = process.argv.slice(2) @@ -74,6 +80,10 @@ function run() { return showVersion() } + if (cliArguments.some((argument) => argument === '--stdin')) { + return sortPackageJsonFromStdin() + } + const patterns = [] let isCheck = false let shouldBeQuiet = false diff --git a/package-lock.json b/package-lock.json index 0b68397a..9ff5a7ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "detect-indent": "^7.0.1", "detect-newline": "^4.0.0", + "get-stdin": "^9.0.0", "git-hooks-list": "^3.0.0", "globby": "^13.1.2", "is-plain-obj": "^4.1.0", @@ -5595,6 +5596,17 @@ "node": ">=8.0.0" } }, + "node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -18230,6 +18242,11 @@ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true }, + "get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==" + }, "get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", diff --git a/package.json b/package.json index fe9952e0..b437f732 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "dependencies": { "detect-indent": "^7.0.1", "detect-newline": "^4.0.0", + "get-stdin": "^9.0.0", "git-hooks-list": "^3.0.0", "globby": "^13.1.2", "is-plain-obj": "^4.1.0", diff --git a/tests/_helpers.js b/tests/_helpers.js index 22f5957f..711e562d 100644 --- a/tests/_helpers.js +++ b/tests/_helpers.js @@ -120,7 +120,7 @@ function asItIs(t, { path, options }, excludeTypes = []) { } } -async function testCLI(t, { fixtures = [], args, message }) { +async function testCLI(t, { fixtures = [], args, message, stdin }) { const cwd = tempy.directory() fixtures = fixtures.map(({ file = 'package.json', content, expect }) => { @@ -145,6 +145,7 @@ async function testCLI(t, { fixtures = [], args, message }) { args, cwd, message, + stdin, }) for (const fixture of fixtures) { @@ -172,11 +173,19 @@ async function testCLI(t, { fixtures = [], args, message }) { ) } -function runCLI({ args = [], cwd = process.cwd() }) { +function runCLI({ args = [], cwd = process.cwd(), stdin }) { return new Promise((resolve) => { - execFile('node', [cliScript, ...args], { cwd }, (error, stdout, stderr) => { - resolve({ errorCode: error && error.code, stdout, stderr }) - }) + const cp = execFile( + 'node', + [cliScript, ...args], + { cwd }, + (error, stdout, stderr) => { + resolve({ errorCode: error && error.code, stdout, stderr }) + }, + ) + if (stdin) { + cp.stdin.end(stdin) + } }) } diff --git a/tests/cli.js b/tests/cli.js index 30388d26..d68ee298 100644 --- a/tests/cli.js +++ b/tests/cli.js @@ -488,3 +488,15 @@ test('run `cli --quiet` on 1 non-json file', macro.testCLI, { args: ['*/package.json', '--quiet'], message: 'Should output error message', }) + +test('run `cli --stdin` with input from stdin', macro.testCLI, { + args: ['--stdin'], + message: 'Should output sorted json', + stdin: `{\n "description": "Description",\n "name": "Name"\n}\n`, +}) + +test('run `cli --stdin` with input from stdin with \\r\\n', macro.testCLI, { + args: ['--stdin'], + message: 'The line feed should be CRLF in output', + stdin: `{\r\n "description": "Description",\r\n "name": "Name"\r\n}\r\n`, +}) diff --git a/tests/snapshots/cli.js.md b/tests/snapshots/cli.js.md index b939c937..8fcaed19 100644 --- a/tests/snapshots/cli.js.md +++ b/tests/snapshots/cli.js.md @@ -25,6 +25,7 @@ Generated by [AVA](https://avajs.dev). -q, --quiet Don't output success messages␊ -h, --help Display this help␊ -v, --version Display the package version␊ + --stdin Read package.json from stdin␊ ␊ `, }, @@ -52,6 +53,7 @@ Generated by [AVA](https://avajs.dev). -q, --quiet Don't output success messages␊ -h, --help Display this help␊ -v, --version Display the package version␊ + --stdin Read package.json from stdin␊ ␊ `, }, @@ -78,6 +80,7 @@ Generated by [AVA](https://avajs.dev). -q, --quiet Don't output success messages␊ -h, --help Display this help␊ -v, --version Display the package version␊ + --stdin Read package.json from stdin␊ ␊ `, }, @@ -105,6 +108,7 @@ Generated by [AVA](https://avajs.dev). -q, --quiet Don't output success messages␊ -h, --help Display this help␊ -v, --version Display the package version␊ + --stdin Read package.json from stdin␊ ␊ `, }, @@ -202,6 +206,7 @@ Generated by [AVA](https://avajs.dev). -q, --quiet Don't output success messages␊ -h, --help Display this help␊ -v, --version Display the package version␊ + --stdin Read package.json from stdin␊ ␊ `, }, @@ -1364,3 +1369,43 @@ Generated by [AVA](https://avajs.dev). stdout: '', }, } + +## run `cli --stdin` with input from stdin + +> Should output sorted json + + { + args: [ + '--stdin', + ], + fixtures: [], + result: { + errorCode: null, + stderr: '', + stdout: `{␊ + "name": "Name",␊ + "description": "Description"␊ + }␊ + `, + }, + } + +## run `cli --stdin` with input from stdin with \r\n + +> The line feed should be CRLF in output + + { + args: [ + '--stdin', + ], + fixtures: [], + result: { + errorCode: null, + stderr: '', + stdout: `{␍␊ + "name": "Name",␍␊ + "description": "Description"␍␊ + }␍␊ + `, + }, + } diff --git a/tests/snapshots/cli.js.snap b/tests/snapshots/cli.js.snap index daa915276216656c03897e93e5303c166be0e7d7..34c5643c25d6eed749f90066087550d89cddf2e6 100644 GIT binary patch literal 3992 zcmV;J4`=W}RzV4tmQ+xIN(mBIK!{SLaEQ_pTBuNqDnL*W zDkv&Zzc=${kGbCNdUw3GC+NfW&Tr54fB*OY|C{&bzP?^bj_+3QUUX2@Qko=Ylx$k) ziAyP=y*(*PnVyuIj%C!Otf@C0OeA7j?5fb4VXlcI|M+G;vJzh}05$^>a4O$8jc?r4 zdz~29cs}>-)TvWBzJ=q%96y=oZ-wD>@_oZJJ`z*^$@-K0j{mv|+WP#IEN<=66%3Oo36+ws7$_J~EBxxGw?c0^4}Y(MO7pKFaYt z$Da(FQ2tV9Om9rZCG1SLzQ)B(& zDnXSMtvwTq@5WE<*Qs(^xJJ%sDLJj~5U%M^{TV!$u{bJ z0ZO4^Nr3K^PW-*qqToFYc5Ofn5 zM@1>tD@wyNwj|}Oln@j#LoT6yECXUX+d*kEJj22h^Yonf@_CK;@_;K}UU241_;Y-I z0yvEy0cSe!%PWAbfWqcX$dxnt$2@O--b629K&Ejf6;pHaGvAt~;VNlKLB>%i zIQ#xA_@$|K>V)~a)1tW}(IS$!eGS+F?5#kHrgm@Y?%LIL<%TU=x9nQCVPls~m4Xa! ze3DF{B+Do%SxITB8$`-8N*Ca?;)vI0puDR-f2P8xom zoh)Z};J@~SI3!APhTKW>j?XDhLrmXFX9s#kB^Oy|+3&YUZqFaCyLdWdB=NM9*23F? zYz6VO@ZOJBdS8}PEOd5?5;D^vCwJICe!{@WGt;5^y47(oiuZV>3!&q6=P4tSjkEE~D}gHj zt-7)i zG{-1SO5w#lz9*+gU6Ru;@Oju;8?aXR26^3Ul&Q7%Yhe{+DPYV!`P!n9X9r0vNOb8-eR8 zU_q#Tuz&#H^N|3LVqZ^?BZl)|FyRR>!&0KQ4_d0z!oaVmg(bQC(Xr+7Wd;7tK&G<5 zuV26dzkjAwzmJe#s6266Ug%LS+0vevikqqxCrTgV06zmR15t*mM3(Y>wO+_Fo07%6 zOhtNO5@xZLFlA*-kNRGwzv@z^!{fLnp4rghL+8QZLKb;QDbY;@E(3N~lvTwG zc<@BMtIG#Cz)wh@0lXQU@Z34Wl8W^ZBIwDO$q}J|Bc&D}57eEY%w$o;eB95IDnxPC z0wQor1%jee#iAv}Mag}B%E-&u+3SS;pux6)3N|VX7E@tQzC8Lrt#0ll@MRj%5A3hYihio~ zbZg6>Y;jkMUPx0#=Gt4iEDjy1I}usH;?dV((8c1>COQd&Ja}?f1tMbO5xY2f$j4R} zsY~AFjW$;*AO?hGz7sQCJH2!5y)PD1{2ylbmnlST_Sc3f*5=rIK9w)$T79sb66Orh zYA%ok4%TJfHcHw<3w?|BEOc*%yDjyZ`Ak*{H~>slD}ve+f@ z#>6I~K@YLn6|S6J#)eSA2CG25AQn-QbovvjO*}9BXG%Yiq2BY72luf&7*X?=WzYOldygSTsTY*Es z8)5GlH9E=UDfa7EE3%I2DK7Id9t{;I%%*!ebR-KhWbaUPj_)b5i;#y4h1@e75tZKn zY+;3?oiIqyQ1nZ7I2u`+Y{aQ)xj1!E$#H6g8S^GP(Hx?aYe?E7Dxy7;mT4CKB5<4? zjy59%T?sr0{Jl!ysJfX$U529?oZ@JNBU)W}g`<2~;Tev?|C|8f=vLrhZNgE$d@#b% z)4UmuKH_~zn~WRxWkig5zzx9t?C61C<(hyUzz>3CW`ZO$xw&`6*^IUS=R7sb-mdUY zb3(rND~`GJD^3CtrvM$aR`QH3Wa?F4;S+9dv4u>2zlp|`r`fTkMm-B7=)9E+IxRls zK*nt)mEpy}-L#BiM4h>aH1mPIw2TUJmWhzFsJ4#IvRr^!WNG2_%W}e;Y^A5p9ucPT zF5i1PE)gbVMi{Ti(qKN;aUsoKwz4A3F8X+fV=>iSS#KwzM~Mx&nrWEE3w--)@~sh1 zUMJs%Yd-_l89T;ZLH)tM)Mpi zxsT-^M@e17PM0#hEcH9f_qzQpm%80tw_+Jf0Wal^X@l3$9D9(ZfH%V6X15&Mu7D$} z-y<%mv^fG|NaJpQq|vyoKgG@t(BX;sY)RS&lUwNUL^E5GdSKEAJPv$dHMdLBTFB8Q zzyaW8tAYiR6i8AaN#jG33J0>vlBAzZAW0$x*^$~vQhtQXkfe>dYHe>`k`Co1>5Y;l zX@uimQd#3(wz|wV?!~UjnxSNqfdp_DTL9mO$;ZHYsM!!(0FT1tHDEE+>}qyR_ApEi z1CvpYU09`>ENEZVZ~H0`!0{-6E<>m1Gln|K62f)9kA1x3GWKDx3* zx!s`(Ca|%W7Iv6R^T*L<4_UkE3-Y8Om~&&mo=Vu0?*<0!sV#e~6F>v@j7|2md$tlv zVA02QH`SBOMYGP4wlT?k+S-#zq`yEGEdMd^Jex_jmO(j8Vo&z`*Jx90I%qW$$N=|D zc#5rHPz)RTV@g6Ii>u3h#V-oUuU4SbERoGfsd!8iJr;**_*0FD_DH#Xx(2gPN9vfJ zbco4|Y!UKE#BYFydAgjd7wL$S90fiEPPTeklZ|u{E9o5DGZxx;*o2B~oO^y@*Pfse z1whsx<;KB|NBoA9z+My=Pf!l$@Y-O1WnK&JgfS<9I z}n`t?1ydu%1cl>nSjlfiY0nS${7=fu^0nXW>YBh&1=py#G zfvbpTT!Q@H}>0}uUJseins{*b9eqX`EVeYRAI8ikxuAw|EDM22J8$@8ha;gwF z*DV_=Qipji3;(ldF*E^EsuHMCjn)5Ot*5|`U2sigW;Jj{-MacLkHGIVY@xsQo4y)J zj}QfK1GhUjf5`Wk@BHd+=ht&v9NXKUPl0pIpyB=st3OBBp}vV;yxI>YpHoz2c9XAq zVVMxsxRT0fw76Vb@MCme)bes5^JVjT^cILmIZfvEatGtnYn5xA9OJ>jG5mLo^Y^yc yJ)?!;8ZFU%Ev9oU*qRgtDU}w5J`rA_8m!A-A|HLRY!z=>Y)B>=T z4C!QFg&&Iu00000000B+T?vdE)ft}gvAa0rDuIR^&9F@fB)bl~2?0_{3CWU%BPk>y z98I!bdv+#NvHwz)CKuSwhP*u_jN~?xcYD+4pK&1qU8zD+j!y$@F+Cqg|Q~`p5 zP(e|N`n{PqKIVG1*Piw64(Q9;p5LD9egF6W|2yX1{ys@g?o{tud_dGPnk43wd{*d9 zN*STEGc8KF-i(?}-doQYWno)Fe=*?F5kvSX7U{OMc^!83vW64NcqvnIG*SD z<6#pj9*l97%u}0AHk#Xx6BR{P*2pPQ|0F!svb{ysQZS)!Ift!sUZZbA=kQz9#DKU; zP-R8y%q5aL@vie)Rn7|6$T=+|XVq=OHT@Y$Ts9!deL_4Q-xiB)g0Vo2jHtnKEq+%MaB{i4CaC!&`AK0A|6s2wu}*i;)+Z3_ zjGB`Y*9lr0$4NdU7Q@71SX5M;c!`B*o~%H(!8RsJi9S&pnY}43=cSaOh&ggq^q(IT zv-vn}`6II}P2W6XCknjSAPU^?N`V)gDG>e)pC1EGS5(fNeetw+p!Vf`)t&&M)vIByCgeGC6B45%@962~~WMZn$365J1TvmfjggVm! z1)84%b0`JWe6GlWgp^6B1(8@}jgN5RT3V3t!wODlAP>rDsskHdYdXbPFdD@m0n=B3 zZNTmt6l2DQjT?G)^jx`q)8}k4-y*&}!W9MxeaODH&PGXqoFpN*&4vlRat) zdFZb=2nT=9#1W2JpvD|v6>wz@!f{;TLN%NR{6c&CKO>I+J5%DYD9Jf;C(S!PzdTql zn@cu7*e5ClXF1n?zdeF#{!r7o$l0TDkzF*e+zRAtaFM0=eyrl^sv5;&=SERM{5b5? z9QI8dH!%A6ak#l|^?XaDWZvuYVCggme_vs|#6R71&R|sW5)pv&fnMOohQv$FDivS0 z2M2}LVu=q%PH~Q|d%ePi(4U&FrHo28&cK&f0#^W9ePtsEsmD!7z0f73CSq!u7icrb zqz&auR>m*m3MpBqO!W5+;>-Rjb=8X^&YElEN(B6f0ZV|dTe%W-($y(Ee~{NtzR^B% zO<7AuYcSf^DY4jvaz2|9y7Zmerq^r0b|@Jf@%I8#vy#fHOlJw>{+T5FAdb zMI6atv-$R{-DqX)*~FmOzDj7f@w2^yY^Dv2SacD;-X7ay`PB$HX!FhSrKf5!Y(w)M z$Yc{z`2pDW(BXYpu|1R+b15GDq?~ES=Xpoa1spWu~={_3_5^IfNN`DL8x=6gaF_5kpPciUyqX`M&mzs z(i32|CF|@QvLu|Pj$e=TDr)kF$5)fD%JE+g+??jz(2wFgeiOIwsn zw6rUs;-+flfzn4fz)yioL6qS-k)`^!+AL(5N6BJdrZT-S3A4mXn5rVCM|{t`Uv`;eLubR_JQjIKDzSk^Ot-ViV@tt{A7>V zB^2u=M9_mVlOsY2M=DJ|?r%ClnZu%rIdsmGDnxPC0wQor4T7Rm#iAwUNy)u_%E-&u z+3SS;puv`a3N|VXl~Z9?u{;Z1=@R-9Dc#RF5a9jsr4#KiIE~f#yJ2uP9se*~gHB9a zvaI}W78?EE{Hf%w!wp+juWIfT@MR`20PJhZjDCjobQ{Z`e0f!iUPx0#7T8OxHXgB)lLvh)b&!PwC59);3s83Ue}OwE)Ni2bwZ&8zb$ZiM~a97P}Y6 zSj>8>LCkv4m07PlGb<8B!<<69$k(vg^-UP`vDhW?#v~!4K@YOo6|S9K#)eSI2CG25 z3j_#I*)1OnovqWuINAlc&2t9)~hOq|5g#$VHbz zrY?E0CTteMR*aB2z&deu?Z%>V84EiBI}r*Vz-a} zXt+FJHk+42MY1G9_I5>Q`W_;?2zj_v$UWT=QTg@2CYC$e4uceRMZaLXqtS)QhM$^Q z@Kfhk?59QkaJ&A~glx};sABHANqnMTns0!P{I=yJHAD}e`qzt_nf)i-izN_W(N zQydF-M6(MocT`L(Jl#?FpOe5H?F9}r#vK*Y2g4mb#hdQvL*AFL$+&S}g2z}0To2sG z_8#~u*9vR{z8?fLlO&iaOs6Z4W~}u;=h;^Fa)o!86Y{-Yam1xwaU6&^9f;Fh$Wh8F;L(KL$Tbr!(WECP1Z zG%AQ$CPU1k+A2ET1qXAwrGzse%PDjIlpZ>Jc$k(ueXr@bc$kpsVZ1y`)Ew4v9*tf$ zvpmcWI=sU%nQE)8wiD64#QH+cG(!CaUjB-_H2lfyQM4oQBldKEcr@E zikL`Q>OoO>q$xlG_<_|s*`3+HVe$d6Ho|dg#M_y{{6(0&0xXVl+}5bKT)_OdFnJi5 z(!z0HX|b5M1_9bc3(&^u6i*-?x2D@z%W;h5Io5I?t3Qs4s)k)IX?j)acbe~c`{kjgh2c50@cHmlU$K-9C_IpWH^?TX!GF!hFJ11*{l1&3r zz@2OXd=Dlc0qdYZnQxFZ8|d<87C|5A$gRWFXl_mKdgCkOf9~V@}x}EHS(r20y2{*_&)J3^%3^ z#8Aoq6%x0lMU}j|sFJt&q>{!>KZLzK0nCCLtziq-JutZ!_!KymEnGLkWG`?8h_QvM z4<>2g3E+b|Wp06R1;P~wmmk9A)qgg>tp6-4XGLPBYO32Tf<~>c(V*F&3mt|7*;I&h zs;#0qTm@@u*!syF7DBCMEsc<;Xz(X&kOgGk$uwEDm}W*52uZNMM(F?+p*)Do$}}W1 zFRbH36^db81qAW`p$e=CY}VP(HjHYS;)tv#7U z>I-BI@*e@uvzcTo8C1h0_GHh0jWxw)fmU;X9B}ufr`QSx#js%@p`;|TUb@_0{_Kz9 zY6UvYQu&;eNhUPWV{xeH9~(rphpVmAMa?=L$z!(DE+#LsMaYndUjq;EbU9Zq(h(&& z4153_Z*66*Hqu3`q;o9KSZL>A6DqTDuK9&sYl4Os09k)n=m&ecSmFB*t?)H^a_WHh zNJZM`wcMn>*P=b_ZZFS)()Q|MC}NEF*bdymt{%Qa$9r555W@~ zU$XS%NfX6Q5IVr zMp?MXi*-pJwz70WO_l?<0f*SiG6OPk5+DITWh=`kFgXf*1FG_^Iw{K}=x7R*WgIBW ziV|g!kiA!>E6Y4f0u|}Y&l;pJkGty2yUzO3dNOaUihcndGxt4O6nmDXF=TPgw*j*5 z@uw_}3BljC0jC4&*c#I^J~YPI5Opj`7~&%q#Ajboe4h15e2muhG4}QuK$g7O!xo7@ z!{o0(7d(H0EfSBy{5YHT|r}WfDikWL_(MYGnswc}*618a1Q5+1A*sfI#6!uCe)H z-MU>CFql