@prosopo/datasets-fs 3.0.39 → 3.0.77
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/.turbo/turbo-build$colon$cjs.log +7 -5
- package/.turbo/turbo-build$colon$tsc.log +35 -0
- package/.turbo/turbo-build.log +12 -6
- package/CHANGELOG.md +290 -0
- package/dist/cjs/cli/cli.cjs +4 -3
- package/dist/cli/cli.d.ts +9 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +2 -1
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/cliCommand.d.ts +17 -0
- package/dist/cli/cliCommand.d.ts.map +1 -0
- package/dist/cli/cliCommand.js +31 -0
- package/dist/cli/cliCommand.js.map +1 -0
- package/dist/cli/cliCommandComposite.d.ts +14 -0
- package/dist/cli/cliCommandComposite.d.ts.map +1 -0
- package/dist/cli/cliCommandComposite.js +32 -0
- package/dist/cli/cliCommandComposite.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +34 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/flatten.d.ts +59 -0
- package/dist/commands/flatten.d.ts.map +1 -0
- package/dist/commands/flatten.js +95 -0
- package/dist/commands/flatten.js.map +1 -0
- package/dist/commands/generate.d.ts +115 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +150 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/generateV1.d.ts +179 -0
- package/dist/commands/generateV1.d.ts.map +1 -0
- package/dist/commands/generateV1.js +169 -0
- package/dist/commands/generateV1.js.map +1 -0
- package/dist/commands/generateV2.d.ts +189 -0
- package/dist/commands/generateV2.d.ts.map +1 -0
- package/dist/commands/generateV2.js +204 -0
- package/dist/commands/generateV2.js.map +1 -0
- package/dist/commands/get.d.ts +35 -0
- package/dist/commands/get.d.ts.map +1 -0
- package/dist/commands/get.js +92 -0
- package/dist/commands/get.js.map +1 -0
- package/dist/commands/labels.d.ts +47 -0
- package/dist/commands/labels.d.ts.map +1 -0
- package/dist/commands/labels.js +48 -0
- package/dist/commands/labels.js.map +1 -0
- package/dist/commands/relocate.d.ts +71 -0
- package/dist/commands/relocate.d.ts.map +1 -0
- package/dist/commands/relocate.js +81 -0
- package/dist/commands/relocate.js.map +1 -0
- package/dist/commands/resize.d.ts +69 -0
- package/dist/commands/resize.d.ts.map +1 -0
- package/dist/commands/resize.js +112 -0
- package/dist/commands/resize.js.map +1 -0
- package/dist/dummy.d.ts +2 -0
- package/dist/dummy.d.ts.map +1 -0
- package/dist/dummy.js +28 -0
- package/dist/dummy.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js.map +1 -0
- package/dist/tests/data/flat/data.json +364 -0
- package/dist/tests/data/flat_resized/captchas_v1.json +5155 -0
- package/dist/tests/data/flat_resized/captchas_v2.json +5305 -0
- package/dist/tests/data/flat_resized/data.json +364 -0
- package/dist/tests/lodash.unit.test.d.ts +2 -0
- package/dist/tests/lodash.unit.test.d.ts.map +1 -0
- package/dist/tests/lodash.unit.test.js +29 -0
- package/dist/tests/lodash.unit.test.js.map +1 -0
- package/dist/tests/mocked.unit.test.d.ts +2 -0
- package/dist/tests/mocked.unit.test.d.ts.map +1 -0
- package/dist/tests/mocked.unit.test.js +252 -0
- package/dist/tests/mocked.unit.test.js.map +1 -0
- package/dist/tests/utils.d.ts +35 -0
- package/dist/tests/utils.d.ts.map +1 -0
- package/dist/tests/utils.js +101 -0
- package/dist/tests/utils.js.map +1 -0
- package/dist/utils/input.d.ts +24 -0
- package/dist/utils/input.d.ts.map +1 -0
- package/dist/utils/input.js +35 -0
- package/dist/utils/input.js.map +1 -0
- package/dist/utils/inputOutput.d.ts +21 -0
- package/dist/utils/inputOutput.d.ts.map +1 -0
- package/dist/utils/inputOutput.js +10 -0
- package/dist/utils/inputOutput.js.map +1 -0
- package/dist/utils/output.d.ts +36 -0
- package/dist/utils/output.d.ts.map +1 -0
- package/dist/utils/output.js +62 -0
- package/dist/utils/output.js.map +1 -0
- package/package.json +12 -9
- package/src/cli/cli.ts +84 -0
- package/src/cli/cliCommand.ts +68 -0
- package/src/cli/cliCommandComposite.ts +54 -0
- package/src/cli.ts +50 -0
- package/src/commands/flatten.ts +152 -0
- package/src/commands/generate.ts +218 -0
- package/src/commands/generateV1.ts +273 -0
- package/src/commands/generateV2.ts +293 -0
- package/src/commands/get.ts +115 -0
- package/src/commands/labels.ts +78 -0
- package/src/commands/relocate.ts +109 -0
- package/src/commands/resize.ts +171 -0
- package/src/dummy.ts +52 -0
- package/src/index.ts +14 -0
- package/src/tests/data/flat/data.json +364 -0
- package/src/tests/data/flat/images/0x1038adbe1bc5ffb5e1f180ce9fa5f727a02a43d950ba630d0a3003c95aa67609cbce9121428095180fb0442aa52b8eb4c9af3ab4497db072919e6fe65e70682b.png +0 -0
- package/src/tests/data/flat/images/0x1e72b814d54da74f13a5bdc56629dd0e9c6a33ac193870b3560194cff405c0c0dee3165ef4cd41cd6251df3024ac743ef8f1548a85861bc3ba680734f9ea3269.png +0 -0
- package/src/tests/data/flat/images/0x1f7c611483d586630dd7cc35b2114212b2a771e709dc3e05eaa400bf34c08f59e484e4cc63658c63cee63988ea1989896f1dcd2d9c5bbdfdab4b3710017bb5fd.png +0 -0
- package/src/tests/data/flat/images/0x20b2c989b9e8689d903490cc5cadafdf3a86a5d5e1445f42a8f77465ae659688a9cf2e3272f6c0d1945da26f1bcfcb6d21954c18c2bde806214e629d3b9d89a8.png +0 -0
- package/src/tests/data/flat/images/0x2a707f216df918ace936313a986faadf45141438f0d22953d1ccae7417a1a29b40bf5940a7355f035473dd5c75ef30127d8a057c1901d4f2d2950561b78b253d.png +0 -0
- package/src/tests/data/flat/images/0x2abca0559027978fdd6f4459745f13a4e2d10ac4f16e68dd1b4e236f19462b892d749cac2baf2d1a714b592593176e6309d192ce5363d7f4707c4e0aa6b18abb.png +0 -0
- package/src/tests/data/flat/images/0x2e72dcae73dcd9347896d7c32d9674b885a0beac8ae9acc24eb23e3244a169f2d4b17a2958d24dc87be1e3ae1bfe73fe1b0748a4653a191630fb86f3b58bb4a9.png +0 -0
- package/src/tests/data/flat/images/0x329e1e9223cc4747ff9c6306dc3affdbcceff0e629f19503ad548ca1a82da61d3781986cbd267b98f756f9bb2c8e7a879be5085028069eb3f380d5a32be81ed4.png +0 -0
- package/src/tests/data/flat/images/0x33a99c18c2794a36a0d524a76733a59d10743c04246263c8afe3ace1a96f73e40f964add43ec3d6d8efa9beeaa56eda6ece598fe1e3b520047b83886d6983a83.png +0 -0
- package/src/tests/data/flat/images/0x3992f2d799a25f4ce8e5177fa8df1d76f5afc33cc1738677d5f660ee11c963303926f6d9cd634755f0bb57a9bd0d15073a8fbe3543f569e26a34100b705ef161.png +0 -0
- package/src/tests/data/flat/images/0x42b08dc541114729b85ef41bb07755c8cc9fc635055bda4e8e6d80b6ee43c3d5f702bd76ba2e6abf45f4d9bba2a070c2d3dd76205f7189539b55a95f2e928ece.jpeg +0 -0
- package/src/tests/data/flat/images/0x4390534b3a60fbf35f456da7a0bd7c86652dbf33e2ba739b1610d5bbe008353113ceeedb68b0672fd74ad015812f02181c4e29ea9cd937a90f21e2514e79dbea.jpeg +0 -0
- package/src/tests/data/flat/images/0x46f2eb852f938dfd0b879a93c8098931186ecacae49a2821e4c43fade1660030bdf03938caa278a9acc78dd1751c467c857a7689c659508933010034be01be7d.png +0 -0
- package/src/tests/data/flat/images/0x48bb86605fcd86ad2f471746d200bdf4124dad0db82066e4624ec57921ad743b750de21504f3979e33c7261dc8f54a6c84eab6308e5752b74096b12b6dde629d.png +0 -0
- package/src/tests/data/flat/images/0x494bc81803193093ac9b6c0c4a5f91dc24e85641718cc0f4c9f8778f488fb14c80b10ad03d4982adbb74f2b6157bf02d30e0a6874e53780c5657d90029331601.png +0 -0
- package/src/tests/data/flat/images/0x4f6de6838022ac6d4c2cea1ab2f4471041c43d6bf765f249e96ddea235e96472041a8125daaadd728a7dc218535d92524f0c3335807807783034c27e3b743718.png +0 -0
- package/src/tests/data/flat/images/0x50c5e0685168371ad05ca4946ca1434b34769ad26dd9bb825ee504ab77260b3002ddf7a8d24474e94cdc18d5798bae7bac868336fb7c33193f9c86f77e949fba.png +0 -0
- package/src/tests/data/flat/images/0x53e69925b5e8dfb60c07e5dfc44742474f5004428e6f3cd8c8a3892ff86d2211cff97d6b0d4c50930786761117b17f579ca7c2d4379d7836c2435c657950b902.png +0 -0
- package/src/tests/data/flat/images/0x5442346936e3ce8d1b4e78f4c60e64e79b4e92b59877055557a01639643eb933f26b3e8d588361688a2f6a0c66558f06f2615028271af1eedfa66fd90b63a91b.jpeg +0 -0
- package/src/tests/data/flat/images/0x54ca27391394ad7b5c98c5d9a3875e4527d33dd0a1ba72401e39991e4093837a52d7f936c619722fd7ce602cda7cbe89c01b0c3b526a3dd61bcfb60b364951d7.png +0 -0
- package/src/tests/data/flat/images/0x5ebabefb53c4d07cd1ec002547f452ec6053840dcc28b2e507364c5307a28cbc3d9698a24f09ed01985aa290da3acd4d86aea2f9f53753f0bcca994953e474eb.png +0 -0
- package/src/tests/data/flat/images/0x615c5079cd4b29a062acbb916780720c0eeb91cd82d9c5f78c9a73ddda29d8842ff85a0d99e863405861d83fd275b78bcead4f61ca8edc3cb94e7093e0a134c7.png +0 -0
- package/src/tests/data/flat/images/0x647083b9336b47b04310e52dc5e370f64ba2bf2f78bd66196af880acd4ea1f8a132a1f8ed25be2a796d43dc40fd151548387ab4de6823758cf774cb619819be0.png +0 -0
- package/src/tests/data/flat/images/0x65341641633dd9baa7bb44fab08b9edd6610db285dcdc887c46221af8623711ce2b546a79743ce7240d783f2e9008751ab82cf2f8341e321b6b887b00a13ef85.png +0 -0
- package/src/tests/data/flat/images/0x686b4a49ecf931afd1b9c74e5a24c907b47f81d2a95579338e3949e8948da6ad3b79e8918d65b779e8bd306e7b7502463eabfc6fe94611c04a46030403d18102.png +0 -0
- package/src/tests/data/flat/images/0x68b2d1f5c248de0eef95f94d9d2dac3c97c8a67f5a2516b50128ae384c7674c7c88fd4e646e9ce3a2e5514cc4b0b36f2078abc57fd1cec605642f8c5ad04e160.png +0 -0
- package/src/tests/data/flat/images/0x69fe4e2faf45b992867f5fcc7be8aea91b332b4769affa4c081264d3a72ea180d9fbe4aac4048cab7413f8e8167565c694e0f9d9d602b24871103c932ecb326a.jpeg +0 -0
- package/src/tests/data/flat/images/0x6e63ab048e72fd41aa59b1434a5b95f1eb2099438ef0a171db1226cde3cda867b99e021d8628c70bedec891ce5bf0e88c302770808f069813a73d77b1771b433.png +0 -0
- package/src/tests/data/flat/images/0x75b79fc445b2bd17231b4f0dc170b646b14d2f732c0236b1bbef10876923ea02ecadd6aabb08ded4f70ba6a96d8789a3131e70a0d79b2644a266f1cfb5821a88.png +0 -0
- package/src/tests/data/flat/images/0x76521ba228624fe9522c8e2d83a1968346e9fab7228446b9f2971064e1992decaba658c11b4bad4767ddeb16e46689270a923b4cf42744d6e1130c86993cc285.png +0 -0
- package/src/tests/data/flat/images/0x7e9747cdd5678279cf005a57a65064080348ba230d63a3a134db327b83c05ace94338cda19002fcba60a18d6ad621477059417ae2e4518eb37655231823fc314.png +0 -0
- package/src/tests/data/flat/images/0x8384c8c5bce81541dd0fb19f2f573964cf318dab654f2792af5656073c1bc22bbe6e73e81e9f6cd9244bd1f7262160854c648683f6cfe3b14f751ba716f511fb.png +0 -0
- package/src/tests/data/flat/images/0x860e81897a1b0204fb5edf3e2355e97990b25badfba7f5bb5632b16dd6da13592fc918a8784f7f4efd0550334479b604cb0a239dc58d83739eadc84fb879996f.png +0 -0
- package/src/tests/data/flat/images/0x86df2da9d3e28bc5313bc1619e2127b538ef2bb08053c36e53a2ede6ba565d67aed2c65202fb180d578f7265d5b4d1c54a09f7e52b0afd12437699a9884642b7.png +0 -0
- package/src/tests/data/flat/images/0x90b87fdaff3e58d32f85d941cad8ac08bf84e0b4fc5c95249e1cc9099dc4aae8271eb701ffcd7617ba886db35357f40b6eda18356c5cbf3894dd3b78d1a24b97.png +0 -0
- package/src/tests/data/flat/images/0x93db31c0522148040443c135d25abc6e3deb37578e4a14d6dd8c7000e0ea6d69c78840e069784ee6e9f2d3524c78c33264a3f8e93eef343942ae7e15d1ba720c.png +0 -0
- package/src/tests/data/flat/images/0x9e682c515b2e8aade0ddfde284ee2cbc61153807602b78476738a2a4842ffe2cc34ff481ad521146a55615877bf9e62655164499dfce41aa75416c192d06ecf6.png +0 -0
- package/src/tests/data/flat/images/0xab7bd3f47ed451578ada004482674ded11a4fac2297552b0e214eb1fe24cdd3355763a7d983b8b8d34197266aa5c2cb1c32382699d8ba7b98a42358c67009649.png +0 -0
- package/src/tests/data/flat/images/0xacaa0f9c8d9bb6660c5047db2e09e2b35e567fa193db03ba32eb62ea4d27d736d61246f1949f64de111d222abc3f84ac400af013da1115140743ce7dce571dea.png +0 -0
- package/src/tests/data/flat/images/0xb1842196f070d2a608eac92ff489cd825f0d379ec0d02a4a736a58aea8035224e584b59dac99f7d27326791299989bbe3cdfbb9972c16d285afb6094639e7fee.png +0 -0
- package/src/tests/data/flat/images/0xb313323422cb06c93b37309d097869de24ff74146c2693bb5a0df5e7d26c5d8fa502bd98f0f4905ccfd00b66299f25d0ecf18b25b9b715a1bada9c3442b2ebc0.jpeg +0 -0
- package/src/tests/data/flat/images/0xbc0568a00d104800cc8732cda70e154cc71fe2a890d84a593071685f63b1af89ebb74736752750c0ad385ce0e2fd4acd808d2eeb18f4c5ad0d0f1eee1d57351a.png +0 -0
- package/src/tests/data/flat/images/0xc12ed6e8c7b674a8e6bdd0042b9a0debc8c16973195072f833b205ca7635b9d0f2da04a225347f7234f9d23ac4e579c00817a24657e06447158ed4420da47749.png +0 -0
- package/src/tests/data/flat/images/0xc2594429d72436068dfa5902593658843b3908eddfed9b83f5f0ecebce181278a07f35b443832d5f65ee31f9e4624155d3c729ebbc49c2f950e01348860c12c1.png +0 -0
- package/src/tests/data/flat/images/0xc5c2d1a2a27b758bba3551b96153c8e8fbf8122fd2b78584b23930ce885ff980ffb35cd23829ed3b3a4c3ec9472f3949bf9faeace92addcb9fa23bf87b105e0d.png +0 -0
- package/src/tests/data/flat/images/0xc6c918e59541d4013e41f40937290f10d6485b8c630e0ec3d0c903c85dc30dde523270df43a74bd75e966ee02bdafce588fae7a2f73c00545a27e84e1ce1b396.png +0 -0
- package/src/tests/data/flat/images/0xc8c98569e856f28f25783cc70ebfe249645107ed272b0ab0f83869c7686b255041d0b413755bf58cf1e0c3eaa0b89e5b55100eaeb715ed7a83c6ae289223535a.png +0 -0
- package/src/tests/data/flat/images/0xd76617a835930389357f28b5d7243bd25aeb45aaaf2257e249a8827bc12222a021b0cf46bb69d408fa7770f79aa0a1cbb28b0ca4438e7fc44b4f73d3b6260a38.jpeg +0 -0
- package/src/tests/data/flat/images/0xd9a3fba1abef24113643624d098e580808ec3952b9eda9dc5f8f1b63afa5401849c4457eb3fb1ddb17a7aa8d24e5cb54a2daafff84426177ecafccbb865770ef.jpeg +0 -0
- package/src/tests/data/flat/images/0xe6e6e36125ae28553d26600090be932511ae21fb6f0029485111dec2cd9c55ed1d568536e6125debb62481075c700e12cc6a3994d1846318a420cd616f82593d.png +0 -0
- package/src/tests/data/flat/images/0xe88a72fb70a000b24a73bc781ecc8b0ef0e66779346067f467722438266e0177a2bbc94be1ff3e0282c7484a13869e22ae8bc184590a4b59106ebc234806b243.jpeg +0 -0
- package/src/tests/data/flat/images/0xea764f65041a907eba37761807cd24ca38fa16517ca4bf25a114609bcc343e48da350efbca1f676337f8e251f8b3a35be8a28a4488db9280ec79de251ffb25c1.png +0 -0
- package/src/tests/data/flat/images/0xebdd539eceb3ba21f5ab2f541641dcb11b7c1c2429dfddd2d880d874bbdf643949b7e976c82c0a531e2bebc1f4dadcd602dcb4d706d54527bcfe30a410c0d115.png +0 -0
- package/src/tests/data/flat/images/0xebf84491d7b258e71d21e16b75f29163a2d5a20e6c5176d989c0ff3ff12ac3e9203193133ce222602c95cf574983fab2bb27b9e2f7b572c870f91a3bf17e5eb7.jpeg +0 -0
- package/src/tests/data/flat/images/0xefe4b1ba734f887e3ce2776110eab7a0d6ae7c6d74e08194be9374c1ff1a4cddd8993dc43e5cf4b6d256dc1156f3b26ceaec9182b98b8b11cfa3c8c3bb1dc8ca.png +0 -0
- package/src/tests/data/flat/images/0xf154d51d2999f623fc0f375a94d4d1e77d54ce4888d7af8e766b2ea5a02eed902bc56149bf348ee1a50bc2c9ab78d2c780f55b431db6ce4b23fe3b71a32ca641.png +0 -0
- package/src/tests/data/flat/images/0xf91877c76deba75bc5760238f61e77806a8486d1a6b09bab13e13c08de8b2cfd74a0f22057064cca459ee64be44be4301de887a72fc1c4c31acc9a02f14a345c.png +0 -0
- package/src/tests/data/flat/images/0xfa48acf1439c2537d1d3268796dfec0777e605c87b5092be55cbaeb1318782c6761de8d01951c99cd28a61ebc353ab6ab18de1dc6977dfc406ac1d8649a5bcfa.png +0 -0
- package/src/tests/data/flat/images/0xfec746312e0fcb2631eb0486a3ed88e35ba95737aadef55aa95cdcdec9fc1a3276eb2de555bbc4f467b8c900b53581a3375390064afd9c9634a45978ebb5bd3e.png +0 -0
- package/src/tests/data/flat/images/0xfeda2fa5da1b8b068baf09870cd4fd3a1ba01e14fc79e759c11e2c1a8ef7d75fc5cf49a86d06c94b371f30aec5c4afd1a4f583881fd62afc40cb012cd3d50b85.png +0 -0
- package/src/tests/data/flat_resized/captchas_v1.json +5155 -0
- package/src/tests/data/flat_resized/captchas_v2.json +5305 -0
- package/src/tests/data/flat_resized/data.json +364 -0
- package/src/tests/data/flat_resized/images/0x00db19a7c62a7ed3998c596215d455077cfa6ea6a9a0d9e5e9189cbde565cf1cc11e18046e01434a67937e9574c35ac3a1ed293dc2bb606e8d419aed61edf70e.png +0 -0
- package/src/tests/data/flat_resized/images/0x02606f6d654cc3780b67077783d8b1d0d482b224ccd0908f9e38e55a16cf6e5eb62b42559e48d881107d00fe2fe3d0d275879d700dcde504c855576548101503.png +0 -0
- package/src/tests/data/flat_resized/images/0x0398b3b46e8e5ffe4206919c2f0f30b94c8867097533128b12df6ff241e2e97764acf8d8fd2955875594b11c2a41f0d3e0071843f09f67a2dbad678072db4455.png +0 -0
- package/src/tests/data/flat_resized/images/0x0659321c2c380fab15f2405128e2439faac7cb8555e217bcafa5bc8a354d6cfce7015203e5e61101a31dfbc637a8d5c65d85b6ee48867499895957c4db5af16a.png +0 -0
- package/src/tests/data/flat_resized/images/0x077d377cd794017fffc8c70c12fc056d7f03f1e24c54b56bc6c13af8a75f033b0883b64502b9afa5329819ac429318ca42f4e2cb5b446ca7a3b5a169ca5354a2.png +0 -0
- package/src/tests/data/flat_resized/images/0x0e3aafb28186acb2b51acd0123c55650b5019c0854e1e478ef1e61aba0033cc3b9d651e314602929a077a67fde2bfbe68c99ec89823abb381a8994aa7098e63a.png +0 -0
- package/src/tests/data/flat_resized/images/0x1a1b08462b094f2def0d8e2659dd1bfe3dbf25fc5b06222b45471d6a84c19f6f69ed996190e05de668bd4afe6df30c6f2b942a3047503e70d95034b155695c45.png +0 -0
- package/src/tests/data/flat_resized/images/0x1e553d6c4afd65c3441aa00970ca9e5919c1c9efc19ee800e45d61eb26e442e7a7dd9a80b34882a18887856b14e9df9e6dd979427bbdbb9e8090df394b0844b7.png +0 -0
- package/src/tests/data/flat_resized/images/0x22938433d07d39fcfbb9538233f57b537d673b0c6022d2cb1b730e42a43b317a50313def95c6e651b0ca1154510ea462a4feee3a0e71bc8f42837bd0e1737c41.png +0 -0
- package/src/tests/data/flat_resized/images/0x25e0a29caac87e8258350c623bba6aebf0a427f0419bde1889d3b365de8f83ad5dfd4c5e8bf7952da3e8864a689b9f0ddc730d6184e85a7b420d349c3d7b8ecd.png +0 -0
- package/src/tests/data/flat_resized/images/0x2670edc73900aac804f21106694f1f1d46ce843abb622f5b638e7974f3dcec96ad031000205786f2745a72f8397e63a410058b16cca850418cda76c82629375c.png +0 -0
- package/src/tests/data/flat_resized/images/0x367af181b8fb20198197e3d7c0b52a36c2ff3ac4dc790056a7d055b0baee38c03a9038c79fc59510764de08bbb7c14307c2d21ebcb4313599782687cb40a0646.png +0 -0
- package/src/tests/data/flat_resized/images/0x3d02bf1afaea86d6cc0aea9e84c6745f845faa308ceac297166fd0850a944f808b10728c2f38f67ea87962ca4a1b4f4074bbaa630caf0d91998184a32e11a77d.png +0 -0
- package/src/tests/data/flat_resized/images/0x3e8e0f6276b6ab68722cc3e827c0a4a9d7d1575ace6527a3c76e103c0f3a4259530d3a6e626af0b19e35a5d13505013c67553fe498b0fe0e7a4060d4003324a8.png +0 -0
- package/src/tests/data/flat_resized/images/0x4190ae0531224be458e3a14e13af0751311ea350636a365f9144438555c56cea075a70d2c6d0c64fb8311ff674cd2b357b0c07de388a5014129e159b9f29d31b.png +0 -0
- package/src/tests/data/flat_resized/images/0x42c68ccc53bc41eb731952ea2adce62be61a7b81c167f6f0b2ba4ee1d2d449d45c44eddc48f9c169902cf35ba1c8739a09848faf8c632775ca257026e4a79f8f.png +0 -0
- package/src/tests/data/flat_resized/images/0x441aee1e0f3c90af8f5d96eece0d476a722fe93883aff615c3c966fac27e814c451eb6fb92ad18c20ae5c798fc23b55a180db9c4d416e8cb3ea0b85cec7565f7.png +0 -0
- package/src/tests/data/flat_resized/images/0x46640f912f03eb60cd4afbb8d6fc14b2f0c14ab93dee203681ab997cd7e43cb58d1782b31d549a158180c7a2f9b2c500c848a2047e740d8c4ac14a320d607320.png +0 -0
- package/src/tests/data/flat_resized/images/0x475b502023789ec81e8653253906a75d0e4e17857117b367999268a5b0b7a8638256eca95d8cc7280a275de8c884a442abb3dd3f7b9f28f2de79df39628ba8a6.png +0 -0
- package/src/tests/data/flat_resized/images/0x4ce6c8a8dd7b35afebf35ee25514694c947bcb082acd370fa5cee4b650548bcf0e21a864e1a99320dea5369f1b3a6b5240bcbca420972a8f1ec06a713b900b82.png +0 -0
- package/src/tests/data/flat_resized/images/0x4fb674a19e4db835814fffc3872df8a661694e0deec3af347cd19e199c5539e5988c72052e79f21e0035d328d522aec983ac2379209eebd56859bdd5f400a70c.png +0 -0
- package/src/tests/data/flat_resized/images/0x5068adcbae2342e7208e394f57b5921df657b1e53b2696cfcb885a9298597fd7645ee1f1a0ff423be46645ca3a30d929ca59a23139ecab0e6ffecd76f3bc6558.png +0 -0
- package/src/tests/data/flat_resized/images/0x511c1fb6c24e2db829767c0503ed3fb5d83d2fc512bd4f53879f2a639095a05b9a104f968dae26e8fa2385c9978c55fa0a646fa07694b6403e4497ad7ad10a59.png +0 -0
- package/src/tests/data/flat_resized/images/0x55709825a4883482be0d647137464f012f61009149ebe8d27b2ad8445064741592795a3d02da53fc9b42e049d0e8d764ba195541267baa2788cd6985197647f8.png +0 -0
- package/src/tests/data/flat_resized/images/0x5cafe30f3eed6c7e6f64e34a081e50317892ac7f235c5fe865e224d8363d65b1b2d9f1f6c8b5736c0f3a932740b9b31eefd7f0ec13a16e4dfca541012adc0b2d.png +0 -0
- package/src/tests/data/flat_resized/images/0x69926ed2721a19f01cf8829611399412e74e5780c64f00c1610aba0a832d9e440399f13471e8cc019fcc2ec372571d1b1a583a967f21fa1cd68607cadf2f7f8c.png +0 -0
- package/src/tests/data/flat_resized/images/0x72b1fdf0560059de27bc796fd0ac98e083277157b2ac2ee1f5812ab4e34a781aa15b7372961dc69c4f562df5143ce356b184acd9409803ce1d443ca39d257952.png +0 -0
- package/src/tests/data/flat_resized/images/0x760fa7f860a1e0925b827f6aa83e52d7e76a70f55e263da07c6997b6c641987f78dc208ce97cec2eb3d68a2e653acc7d308ce4e242891573b4d50281822f5485.png +0 -0
- package/src/tests/data/flat_resized/images/0x77fe0772ef80332ac3cb48d5c84be6fefec0ad90607ec45c509edda2a6b63e389895693821a9ee99a2d824cf71fa9bea4458ca3de8353ae60f489fa6e3961878.png +0 -0
- package/src/tests/data/flat_resized/images/0x7da2f1e8dd907863f6ffd9dd3a3d24d3ac28797a3429210c24be3c83e1cc6028e040250e7c765f99a85a3edd7d0a3978b46a8bfff134120b309c494d7484e24d.png +0 -0
- package/src/tests/data/flat_resized/images/0x7f45ee498813ebe3d314d9071d126341ab14887d8754d5571d4858f93a07c7a8d19687a76f3f2f42dc110f573626c32f52475bc6e0d8b714c2773a13cf08f8bd.png +0 -0
- package/src/tests/data/flat_resized/images/0x8343903b4ce3b63ffc4a66e805a18dc1cc136a91c8f67f15f261aec61c9ad58ad1856c84fe0ac97d1edc4b21f6b5b1842cc7b211328e460ed75bfad3dbb9ff16.png +0 -0
- package/src/tests/data/flat_resized/images/0x884c86c6b69bd29db658b3612f484bdf78e1420434082a68636f69e3d90e3cd76cf9718e099ff0ab16d7f27d8c5a3c09dcbd136d9ee01cd1d4ec72de672bea66.png +0 -0
- package/src/tests/data/flat_resized/images/0x88f06b2a1ce4f7e9b491a84919b59939a76baea88a48e88e95ebe48383cc15631d8524b7a9ec73cc4cba7568dcc1c7bddef4ff45c6992300e10111baf4a61971.png +0 -0
- package/src/tests/data/flat_resized/images/0x8ca8bc45e79bd59205fbd77b24e09e4c6ee437f27d02fc30b825037cfae6f2583f7b9d0b6a004c5a2ef9774ca1d3b45ffb94fdfabcffcdddfcd5838f2a489d3b.png +0 -0
- package/src/tests/data/flat_resized/images/0x8cf36665bbccaec073e346777f974edbbd7ec534e78426d6ae13dc39740271024527e945fef06d8dd78b1345c87e1b3f90f28385531910d3a0795f45a7030438.png +0 -0
- package/src/tests/data/flat_resized/images/0x9134327ca5ec7a5c6e1f6d8e8aa395c445d439dc32c1bbc84721b18d04fcee8394a559c362bcf6bb1e92e2d8edcf6d5dd73f1cf302a38dd646bbed2d27a6ce8f.png +0 -0
- package/src/tests/data/flat_resized/images/0x9401d4dde02ebdcdd64827653b90b3337485c8fb59796ee6dbefd3866404b47ca4663175b7acfad49eac177baeb8df7304bced6713f85d50767144dcb436c66c.png +0 -0
- package/src/tests/data/flat_resized/images/0x977448bb1fa3594a3d91b2a37acd6967ca42252f0062ed5253040f200230395e7924a4dcc392bf26ec6d2c7c1d3204db2c5fcedb4c9d21a2a90ee018df2e6ae6.png +0 -0
- package/src/tests/data/flat_resized/images/0x99da74b964a5dd03c619aa375ccf5dd69eb34fba3bf0e48f8e34ce2c9a1f4bf5fffcd1be4fcebebfdea61ab27bb8d36060950d6c19b7c8a89c7316a724db7a4c.png +0 -0
- package/src/tests/data/flat_resized/images/0x9b7dfbc8196a9d5b140f56b7eec0467c9d8a3e38ff7c017c33700040f6c98e2b79a0960f7a919d7f1ed7b435a49dce508b113ebda88331629ee8492ca29439af.png +0 -0
- package/src/tests/data/flat_resized/images/0xa6d77ccef52e07120c9295502b9dc972107f704abf6f4fd57dd2b8664db9fdc2c104e30e69e2c61cf1d88f8cdaeea204a2c332d49fd7ad1f61bbda7ea22bb77e.png +0 -0
- package/src/tests/data/flat_resized/images/0xa791e01f34c89768df8a82869d31e5ce813adb84a3cdc7be5ebe55503375fc89d49974a3a8987292b92423ded092e488130957f4725e93d21c14d0a91a2f81ed.png +0 -0
- package/src/tests/data/flat_resized/images/0xb31d7cab98df328d0f4a32b2969ec8e294cb4c2d1ab8bf46471a113b63c0d39c3ccb5cca55a8b46a2161c836a9fb1643e0d673e933cf21c8e4f4e46f0e1f0e96.png +0 -0
- package/src/tests/data/flat_resized/images/0xbc50b9d2fc9272318a3a51e555ab744a1205112d38e308caac67975ff367fabc636a6567072bdd3bda1368ccc78863c6ea115f91cb7e4a57349baca6d6d01e24.png +0 -0
- package/src/tests/data/flat_resized/images/0xc322ec6d7a03c9baade16ee7a71414edfe6839d7cbe5805f3632d158616d9b51f455d1daa39167359a189878905ec8d77f3e44022ec4481197f85a98d38ed345.png +0 -0
- package/src/tests/data/flat_resized/images/0xc5293e66e847653ca0361f1fd1460c573a66be57b769a8a41b8fb8b42da4417ff1a91c4ef037ca5b2a1f0b5797dc62db2090d88047a80a09e93eacc080e60bb2.png +0 -0
- package/src/tests/data/flat_resized/images/0xc8d934f2e7ac8429086669bb0788296844946834b5a3d2f3a44db276e06d7856c3782692d8bb9ba4122098d4027ca3642f32cdc7978f44493634b21b82c735c7.png +0 -0
- package/src/tests/data/flat_resized/images/0xc9473fa10f0aa11856eef9683cf99fa7f2bac77e5b0ab0f08a99c002289b0ca684bfbe7504dd3124dea9fb1f4be68caf09a4c3fa0bfa890a371ace855e649c16.png +0 -0
- package/src/tests/data/flat_resized/images/0xd3dd338481d82174ef911f76605f1c9ecf20660a65e23ab2130211c6533d018b021303d37423a641188cbe56a447beee86916cea9be935b1cbca88eb1c1c31fb.png +0 -0
- package/src/tests/data/flat_resized/images/0xd8df8225474e38f1034448afeee0bdcb2888f7ea09ef5f280317cf2c8a3be2f804b0e36fe5769c1f20de3de5b87e174b7bac19807cc5f181938344d53326df7f.png +0 -0
- package/src/tests/data/flat_resized/images/0xde8990cc77d25bdc35d4c258113dc8243af7dfb5ce3a1b00ac2e656ce84ea06c1d2a0d9740787eb1dbcc70226f18a3eaf0e16f627d828ad56d22ebc3ffa8ec49.png +0 -0
- package/src/tests/data/flat_resized/images/0xdf36bf20893c56da991a71f1244aaf032cf938334ce4645a856e96a2170508e5ba6b74948f43314eda7782e1169051e4ee1b276b9b8a048e08068f4d3af3e55a.png +0 -0
- package/src/tests/data/flat_resized/images/0xe8198b8b0e5c51c576f50853c448467a55e33005cc185225a57849c63e84267c340d2d142d391955053ebe14b0322550480341468cf5e9fcaedbf73873e9b245.png +0 -0
- package/src/tests/data/flat_resized/images/0xe94dcbd223afb4dfc9fb7f04095114ce611e6acb5b34384aef88728ab85dd30dcd8581bab1b66e0c6c370e75d03d7f8ac222eacb25d211f91a805ef63099fe3c.png +0 -0
- package/src/tests/data/flat_resized/images/0xeeeb9ef59478b2dada8acea00d7d3de0f163de5f8beea5128808fd43e616f89312476541912e0e1b29881bd58f28713bd3ebae0fbd29e0b3fb60ff310386b808.png +0 -0
- package/src/tests/data/flat_resized/images/0xef422469bc366be01145782e49c5b31a6c58f7d3945291c374a4e23196686121639c2fef9e7f967b37a958fda67cce10e92fc927f6c32b0f0f0ceeaea31ae0ad.png +0 -0
- package/src/tests/data/flat_resized/images/0xf17c8e32e5ab57f059d1c9478d2891d9354673608e8c0826d2e488807ae869a63721bf7be34855ba555f36fc9d722e4f1f78033a4996fe3562328f93c0bd88e4.png +0 -0
- package/src/tests/data/flat_resized/images/0xf5fe66c66f4b33e003096b4bb2c5d0ca52638b5ae4dab7b5e5925bb56c1393feb68f2552320883ba54debf91c400be7d9e6727c020bab1d07738d269f0793bcf.png +0 -0
- package/src/tests/data/flat_resized/images/0xf9ce625ee02e278eff475f7920b6fa7617c7078ed61e9ec50375fd47acb0c1aaeda231a779d0b76fb22a5a4e618779a70bff135bf02ebc8b68739d1fad67134c.png +0 -0
- package/src/tests/data/flat_resized/labels.json +13 -0
- package/src/tests/data/flat_resized/relocated_data.json +364 -0
- package/src/tests/data/hierarchical/bird/Screenshot from 2023-10-12 16-30-52.png +0 -0
- package/src/tests/data/hierarchical/bird/Screenshot from 2023-10-12 16-31-26.png +0 -0
- package/src/tests/data/hierarchical/bird/Screenshot from 2023-10-12 16-31-40.png +0 -0
- package/src/tests/data/hierarchical/bird/Screenshot from 2023-10-12 16-32-07.png +0 -0
- package/src/tests/data/hierarchical/bird/Screenshot from 2023-10-12 16-32-25.png +0 -0
- package/src/tests/data/hierarchical/bird/test_image_png_15.png +0 -0
- package/src/tests/data/hierarchical/bus/01.02.jpeg +0 -0
- package/src/tests/data/hierarchical/bus/01.03.jpeg +0 -0
- package/src/tests/data/hierarchical/bus/01.04.jpeg +0 -0
- package/src/tests/data/hierarchical/bus/Screenshot from 2023-10-12 16-33-02.png +0 -0
- package/src/tests/data/hierarchical/bus/Screenshot from 2023-10-12 16-33-21.png +0 -0
- package/src/tests/data/hierarchical/bus/Screenshot from 2023-10-12 16-33-32.png +0 -0
- package/src/tests/data/hierarchical/car/Screenshot from 2023-10-12 16-34-03.png +0 -0
- package/src/tests/data/hierarchical/car/Screenshot from 2023-10-12 16-34-14.png +0 -0
- package/src/tests/data/hierarchical/car/Screenshot from 2023-10-12 16-34-24.png +0 -0
- package/src/tests/data/hierarchical/car/test_image_png_25.png +0 -0
- package/src/tests/data/hierarchical/car/test_image_png_71.png +0 -0
- package/src/tests/data/hierarchical/car/test_image_png_89.png +0 -0
- package/src/tests/data/hierarchical/cat/test_image_png_22.png +0 -0
- package/src/tests/data/hierarchical/cat/test_image_png_24.png +0 -0
- package/src/tests/data/hierarchical/cat/test_image_png_33.png +0 -0
- package/src/tests/data/hierarchical/cat/test_image_png_5.png +0 -0
- package/src/tests/data/hierarchical/cat/test_image_png_78.png +0 -0
- package/src/tests/data/hierarchical/cat/test_image_png_93.png +0 -0
- package/src/tests/data/hierarchical/deer/Screenshot from 2023-10-12 16-34-51.png +0 -0
- package/src/tests/data/hierarchical/deer/Screenshot from 2023-10-12 16-34-57.png +0 -0
- package/src/tests/data/hierarchical/deer/Screenshot from 2023-10-12 16-35-03.png +0 -0
- package/src/tests/data/hierarchical/deer/test_image_png_17.png +0 -0
- package/src/tests/data/hierarchical/deer/test_image_png_52.png +0 -0
- package/src/tests/data/hierarchical/deer/test_image_png_70.png +0 -0
- package/src/tests/data/hierarchical/dog/test_image_png_16.png +0 -0
- package/src/tests/data/hierarchical/dog/test_image_png_27.png +0 -0
- package/src/tests/data/hierarchical/dog/test_image_png_28.png +0 -0
- package/src/tests/data/hierarchical/dog/test_image_png_40.png +0 -0
- package/src/tests/data/hierarchical/dog/test_image_png_51.png +0 -0
- package/src/tests/data/hierarchical/dog/test_image_png_79.png +0 -0
- package/src/tests/data/hierarchical/dog/test_image_png_90.png +0 -0
- package/src/tests/data/hierarchical/dog/test_image_png_95.png +0 -0
- package/src/tests/data/hierarchical/horse/Screenshot from 2023-10-12 16-35-31.png +0 -0
- package/src/tests/data/hierarchical/horse/Screenshot from 2023-10-12 16-35-37.png +0 -0
- package/src/tests/data/hierarchical/horse/Screenshot from 2023-10-12 16-35-48.png +0 -0
- package/src/tests/data/hierarchical/horse/test_image_png_20.png +0 -0
- package/src/tests/data/hierarchical/horse/test_image_png_26.png +0 -0
- package/src/tests/data/hierarchical/horse/test_image_png_32.png +0 -0
- package/src/tests/data/hierarchical/horse/test_image_png_44.png +0 -0
- package/src/tests/data/hierarchical/horse/test_image_png_94.png +0 -0
- package/src/tests/data/hierarchical/plane/01.05.jpeg +0 -0
- package/src/tests/data/hierarchical/plane/01.06.jpeg +0 -0
- package/src/tests/data/hierarchical/plane/01.07.jpeg +0 -0
- package/src/tests/data/hierarchical/plane/test_image_png_4.png +0 -0
- package/src/tests/data/hierarchical/plane/test_image_png_61.png +0 -0
- package/src/tests/data/hierarchical/plane/test_image_png_69.png +0 -0
- package/src/tests/data/hierarchical/plane/test_image_png_82.png +0 -0
- package/src/tests/data/hierarchical/plane/test_image_png_85.png +0 -0
- package/src/tests/data/hierarchical/train/01.01.jpeg +0 -0
- package/src/tests/data/hierarchical/train/01.08.jpeg +0 -0
- package/src/tests/data/hierarchical/train/01.09.jpeg +0 -0
- package/src/tests/data/hierarchical/train/Screenshot from 2023-10-12 16-36-19.png +0 -0
- package/src/tests/data/hierarchical/train/Screenshot from 2023-10-12 16-36-27.png +0 -0
- package/src/tests/data/hierarchical/train/Screenshot from 2023-10-12 16-36-43.png +0 -0
- package/src/tests/lodash.unit.test.ts +43 -0
- package/src/tests/mocked.unit.test.ts +341 -0
- package/src/tests/utils.ts +152 -0
- package/src/utils/input.ts +58 -0
- package/src/utils/inputOutput.ts +29 -0
- package/src/utils/output.ts +86 -0
- package/tsconfig.cjs.json +36 -0
- package/tsconfig.json +37 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/tsconfig.types.json +9 -0
- package/vite.cjs.config.ts +1 -1
- package/vite.esm.config.ts +1 -1
- package/vite.test.config.ts +1 -1
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
// Copyright 2021-2026 Prosopo (UK) Ltd.
|
|
4
|
+
//
|
|
5
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
// you may not use this file except in compliance with the License.
|
|
7
|
+
// You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
// See the License for the specific language governing permissions and
|
|
15
|
+
// limitations under the License.
|
|
16
|
+
import { CaptchasContainerSchema, DataSchema } from "@prosopo/types";
|
|
17
|
+
import { hexHash } from "@prosopo/util-crypto";
|
|
18
|
+
import { getRootDir, getTestResultsDir } from "@prosopo/workspace";
|
|
19
|
+
import sharp from "sharp";
|
|
20
|
+
import { afterAll, beforeAll, describe, test } from "vitest";
|
|
21
|
+
import { Flatten } from "../commands/flatten.js";
|
|
22
|
+
import { GenerateV1 } from "../commands/generateV1.js";
|
|
23
|
+
import { GenerateV2 } from "../commands/generateV2.js";
|
|
24
|
+
import { Labels } from "../commands/labels.js";
|
|
25
|
+
import { Relocate } from "../commands/relocate.js";
|
|
26
|
+
import { Resize } from "../commands/resize.js";
|
|
27
|
+
import {
|
|
28
|
+
captchasEqFs,
|
|
29
|
+
fsEq,
|
|
30
|
+
fsWalk,
|
|
31
|
+
restoreRepoDir,
|
|
32
|
+
substituteRepoDir,
|
|
33
|
+
} from "./utils.js";
|
|
34
|
+
|
|
35
|
+
describe("dataset commands", () => {
|
|
36
|
+
const pkgDir = path.relative(getRootDir(), __dirname);
|
|
37
|
+
const pkgInternalPath = pkgDir.replace(`${__dirname}/`, "");
|
|
38
|
+
const testResultsDir = `${getTestResultsDir()}/${pkgInternalPath}`;
|
|
39
|
+
|
|
40
|
+
beforeAll(() => {
|
|
41
|
+
// substitute the repo path in the data for tests
|
|
42
|
+
substituteRepoDir();
|
|
43
|
+
fs.mkdirSync(`${testResultsDir}`, { recursive: true });
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
afterAll(() => {
|
|
47
|
+
// restore repo path back to placeholder
|
|
48
|
+
restoreRepoDir();
|
|
49
|
+
// remove test results
|
|
50
|
+
if (fs.existsSync(`${testResultsDir}`)) {
|
|
51
|
+
fs.rmdirSync(`${testResultsDir}`, { recursive: true });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("labels", async () => {
|
|
56
|
+
const input = `${__dirname}/data/flat_resized/data.json`;
|
|
57
|
+
const output = `${testResultsDir}/labels.json`;
|
|
58
|
+
const labels = new Labels();
|
|
59
|
+
labels.logger.setLogLevel("error");
|
|
60
|
+
await labels.exec({
|
|
61
|
+
input,
|
|
62
|
+
output,
|
|
63
|
+
});
|
|
64
|
+
// make sure the results are the same as the expected results
|
|
65
|
+
fsEq(output, `${__dirname}/data/flat_resized/labels.json`);
|
|
66
|
+
|
|
67
|
+
// make sure there's one class per hierarchical directory
|
|
68
|
+
const content = fs.readFileSync(output).toString();
|
|
69
|
+
const labelsJson = JSON.parse(content.toString());
|
|
70
|
+
const foundLabels = labelsJson.labels as string[];
|
|
71
|
+
const categories = fs.readdirSync(`${__dirname}/data/hierarchical`);
|
|
72
|
+
if (JSON.stringify(foundLabels) !== JSON.stringify(categories)) {
|
|
73
|
+
throw new Error(`expected ${categories} but found ${foundLabels}`);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("generate v2", async () => {
|
|
78
|
+
const input = `${__dirname}/data/flat_resized/data.json`;
|
|
79
|
+
const output = `${testResultsDir}/captchas_v2.json`;
|
|
80
|
+
const minIncorrect = 1;
|
|
81
|
+
const minCorrect = 1;
|
|
82
|
+
const minLabelled = 2;
|
|
83
|
+
const maxLabelled = 7;
|
|
84
|
+
const generate = new GenerateV2();
|
|
85
|
+
generate.logger.setLogLevel("error");
|
|
86
|
+
await generate.exec({
|
|
87
|
+
labelled: input,
|
|
88
|
+
unlabelled: input,
|
|
89
|
+
overwrite: true,
|
|
90
|
+
output,
|
|
91
|
+
count: 100,
|
|
92
|
+
seed: 0,
|
|
93
|
+
minIncorrect,
|
|
94
|
+
minCorrect,
|
|
95
|
+
minLabelled,
|
|
96
|
+
maxLabelled,
|
|
97
|
+
allowDuplicates: true,
|
|
98
|
+
});
|
|
99
|
+
// make sure the results are the same as the expected results
|
|
100
|
+
if (
|
|
101
|
+
!captchasEqFs(output, `${__dirname}/data/flat_resized/captchas_v2.json`)
|
|
102
|
+
) {
|
|
103
|
+
throw new Error("captchas not equal");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// test that the solutions array and unlabelled array per captcha never conflict
|
|
107
|
+
const content = fs.readFileSync(output).toString();
|
|
108
|
+
const captchasJson = JSON.parse(content.toString());
|
|
109
|
+
const captchas = CaptchasContainerSchema.parse(captchasJson);
|
|
110
|
+
for (const captcha of captchas.captchas) {
|
|
111
|
+
const solutions = captcha.solution;
|
|
112
|
+
const unlabelled = captcha.unlabelled;
|
|
113
|
+
// both should not be undefined
|
|
114
|
+
if (solutions === undefined || unlabelled === undefined) {
|
|
115
|
+
console.log(captcha);
|
|
116
|
+
throw new Error("solutions or unlabelled array is undefined");
|
|
117
|
+
}
|
|
118
|
+
for (const solution of solutions) {
|
|
119
|
+
// solution should not be in unlabelled
|
|
120
|
+
if (unlabelled.includes(solution)) {
|
|
121
|
+
throw new Error(`solution ${solution} is also in unlabelled array`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// check the correct, incorrect, labelled and unlabelled distribution
|
|
125
|
+
const nCorrect = solutions.length;
|
|
126
|
+
const nUnlabelled = unlabelled.length;
|
|
127
|
+
const nIncorrect = 9 - nCorrect - nUnlabelled;
|
|
128
|
+
const nLabelled = nCorrect + nIncorrect;
|
|
129
|
+
if (nCorrect < minCorrect) {
|
|
130
|
+
throw new Error(
|
|
131
|
+
`expected at least ${minCorrect} correct but found ${nCorrect}`,
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
if (nIncorrect < minIncorrect) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
`expected at least ${minIncorrect} incorrect but found ${nIncorrect}`,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
if (nLabelled < minLabelled) {
|
|
140
|
+
throw new Error(
|
|
141
|
+
`expected at least ${minLabelled} labelled but found ${nLabelled}`,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
if (nLabelled > maxLabelled) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
`expected at most ${maxLabelled} labelled but found ${nLabelled}`,
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
if (nUnlabelled !== 9 - nLabelled) {
|
|
150
|
+
throw new Error(
|
|
151
|
+
`expected ${9 - nLabelled} unlabelled but found ${nUnlabelled}`,
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test("generate v1", async () => {
|
|
158
|
+
const input = `${__dirname}/data/flat_resized/data.json`;
|
|
159
|
+
const output = `${testResultsDir}/captchas_v1.json`;
|
|
160
|
+
const generate = new GenerateV1();
|
|
161
|
+
generate.logger.setLogLevel("error");
|
|
162
|
+
await generate.exec({
|
|
163
|
+
labelled: input,
|
|
164
|
+
unlabelled: input,
|
|
165
|
+
overwrite: true,
|
|
166
|
+
output,
|
|
167
|
+
solved: 50,
|
|
168
|
+
unsolved: 50,
|
|
169
|
+
seed: 0,
|
|
170
|
+
minCorrect: 1,
|
|
171
|
+
maxCorrect: 6,
|
|
172
|
+
allowDuplicates: true,
|
|
173
|
+
});
|
|
174
|
+
// make sure the results are the same as the expected results
|
|
175
|
+
if (
|
|
176
|
+
!captchasEqFs(output, `${__dirname}/data/flat_resized/captchas_v1.json`)
|
|
177
|
+
) {
|
|
178
|
+
throw new Error("captchas not equal");
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test("resizes data", async () => {
|
|
183
|
+
const input = `${__dirname}/data/flat/data.json`;
|
|
184
|
+
const output = `${testResultsDir}/flat_resized`;
|
|
185
|
+
const resize = new Resize();
|
|
186
|
+
resize.logger.setLogLevel("error");
|
|
187
|
+
await resize.exec({
|
|
188
|
+
input,
|
|
189
|
+
output,
|
|
190
|
+
overwrite: true,
|
|
191
|
+
square: true,
|
|
192
|
+
size: 128,
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// make sure the results are the same as the expected results
|
|
196
|
+
const expected = `${__dirname}/data/flat_resized`;
|
|
197
|
+
fsEq(output, expected);
|
|
198
|
+
|
|
199
|
+
// check data in resized dir is all 128x128
|
|
200
|
+
for (const pth of fsWalk(output)) {
|
|
201
|
+
// if pth is not img, ignore
|
|
202
|
+
if (
|
|
203
|
+
!pth.endsWith(".jpg") &&
|
|
204
|
+
!pth.endsWith(".jpeg") &&
|
|
205
|
+
!pth.endsWith(".png")
|
|
206
|
+
) {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
const image = sharp(pth);
|
|
210
|
+
const metadata = await image.metadata();
|
|
211
|
+
if (metadata.width !== 128 || metadata.height !== 128) {
|
|
212
|
+
throw new Error(`image ${pth} is not 128x128`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
test("relocates data", async () => {
|
|
218
|
+
const input = `${__dirname}/data/flat_resized/data.json`;
|
|
219
|
+
const output = `${testResultsDir}/relocated_data.json`;
|
|
220
|
+
const relocate = new Relocate();
|
|
221
|
+
relocate.logger.setLogLevel("error");
|
|
222
|
+
await relocate.exec({
|
|
223
|
+
input,
|
|
224
|
+
output,
|
|
225
|
+
overwrite: true,
|
|
226
|
+
to: "newwebsite.com",
|
|
227
|
+
from: "${repo}",
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// make sure the results are the same as the expected results
|
|
231
|
+
const expected = `${__dirname}/data/flat_resized/relocated_data.json`;
|
|
232
|
+
fsEq(output, expected);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
test("flattens hierarchical data", async () => {
|
|
236
|
+
const input = `${__dirname}/data/hierarchical`;
|
|
237
|
+
const output = `${testResultsDir}/flat`;
|
|
238
|
+
const flatten = new Flatten();
|
|
239
|
+
flatten.logger.setLogLevel("error");
|
|
240
|
+
await flatten.exec({
|
|
241
|
+
input,
|
|
242
|
+
output,
|
|
243
|
+
overwrite: true,
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// make sure the results are the same as the expected results
|
|
247
|
+
const expected = `${__dirname}/data/flat`;
|
|
248
|
+
fsEq(output, expected);
|
|
249
|
+
|
|
250
|
+
// read data json
|
|
251
|
+
const content = fs.readFileSync(`${output}/data.json`).toString();
|
|
252
|
+
const dataJson = JSON.parse(content.toString());
|
|
253
|
+
const data = DataSchema.parse(dataJson);
|
|
254
|
+
|
|
255
|
+
// check each image from the hierarchical data is in the flat data
|
|
256
|
+
let hierCount = 0;
|
|
257
|
+
for (const pth of fsWalk(input)) {
|
|
258
|
+
// if pth is not img, ignore
|
|
259
|
+
if (
|
|
260
|
+
!pth.endsWith(".jpg") &&
|
|
261
|
+
!pth.endsWith(".jpeg") &&
|
|
262
|
+
!pth.endsWith(".png")
|
|
263
|
+
) {
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
hierCount++;
|
|
267
|
+
// get the category
|
|
268
|
+
const category = pth.split("/").slice(-2)[0];
|
|
269
|
+
const content = fs.readFileSync(pth);
|
|
270
|
+
// check the image is in the flat data
|
|
271
|
+
let name = "";
|
|
272
|
+
for (const pth2 of fsWalk(output)) {
|
|
273
|
+
// if pth2 is not file, ignore
|
|
274
|
+
if (!fs.statSync(pth2).isFile()) {
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
const content2 = fs.readFileSync(pth2);
|
|
278
|
+
if (content.equals(content2)) {
|
|
279
|
+
const str = pth2.split("/").slice(-1)[0];
|
|
280
|
+
if (str === undefined) {
|
|
281
|
+
throw new Error(`unable to parse ${pth2}`);
|
|
282
|
+
}
|
|
283
|
+
name = str;
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (!name) {
|
|
289
|
+
throw new Error(`unable to find image ${pth} in output`);
|
|
290
|
+
}
|
|
291
|
+
// check the image is in the data json
|
|
292
|
+
const item = data.items.find((item) => {
|
|
293
|
+
const name2 = item.data.split("/").slice(-1)[0];
|
|
294
|
+
if (name2 !== name) {
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
return true;
|
|
298
|
+
});
|
|
299
|
+
if (item === undefined) {
|
|
300
|
+
throw new Error(`unable to find image ${pth} in data.json`);
|
|
301
|
+
}
|
|
302
|
+
// correct name, so check category
|
|
303
|
+
if (item.label !== category) {
|
|
304
|
+
throw new Error(`expected ${category} but found ${item.label}`);
|
|
305
|
+
}
|
|
306
|
+
// type should be image
|
|
307
|
+
if (item.type !== "image") {
|
|
308
|
+
throw new Error(`expected image type but found ${item.type}`);
|
|
309
|
+
}
|
|
310
|
+
// file name should be the hash
|
|
311
|
+
if (item.hash !== name.split(".")[0]) {
|
|
312
|
+
throw new Error(
|
|
313
|
+
`expected ${name.split(".")[0]} hash but found ${item.hash}`,
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
// hash should be the hash of the image content
|
|
317
|
+
const hash = hexHash(content);
|
|
318
|
+
if (item.hash !== hash) {
|
|
319
|
+
throw new Error(`expected ${hash} hash but found ${item.hash}`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// count the number of images in the flat data
|
|
324
|
+
let flatCount = 0;
|
|
325
|
+
for (const pth of fsWalk(output)) {
|
|
326
|
+
if (
|
|
327
|
+
!pth.endsWith(".jpg") &&
|
|
328
|
+
!pth.endsWith(".jpeg") &&
|
|
329
|
+
!pth.endsWith(".png")
|
|
330
|
+
) {
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
flatCount++;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// check same number of images in flat data
|
|
337
|
+
if (hierCount !== flatCount) {
|
|
338
|
+
throw new Error(`expected ${hierCount} images but found ${flatCount}`);
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
});
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
// Copyright 2021-2026 Prosopo (UK) Ltd.
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
import {
|
|
16
|
+
type CaptchasContainer,
|
|
17
|
+
CaptchasContainerSchema,
|
|
18
|
+
DataSchema,
|
|
19
|
+
} from "@prosopo/types";
|
|
20
|
+
import { at } from "@prosopo/util";
|
|
21
|
+
|
|
22
|
+
// recursively list files in a directory
|
|
23
|
+
export function* fsWalk(
|
|
24
|
+
pth: string,
|
|
25
|
+
options?: {
|
|
26
|
+
filesFirst?: boolean; // if true, depth first (i.e. yield files inside a dir before the dir itself, recursively), else yield in encounter order (i.e. dir first, then files inside, recursively)
|
|
27
|
+
},
|
|
28
|
+
): Generator<string> {
|
|
29
|
+
// if path is a directory, recurse
|
|
30
|
+
const isDir = fs.existsSync(pth) && fs.statSync(pth).isDirectory();
|
|
31
|
+
let subpaths = isDir ? fs.readdirSync(pth) : [];
|
|
32
|
+
subpaths = subpaths.map((f) => `${pth}/${f}`);
|
|
33
|
+
if (!options?.filesFirst) {
|
|
34
|
+
yield pth;
|
|
35
|
+
}
|
|
36
|
+
for (const subpath of subpaths) {
|
|
37
|
+
yield* fsWalk(subpath, options);
|
|
38
|
+
}
|
|
39
|
+
if (options?.filesFirst) {
|
|
40
|
+
yield pth;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// test whether two files/dirs are equal, recursively comparing contents as required
|
|
45
|
+
export const fsEq = (pth1: string, pth2: string) => {
|
|
46
|
+
const it1 = fsWalk(pth1);
|
|
47
|
+
const it2 = fsWalk(pth2);
|
|
48
|
+
// drop the root path
|
|
49
|
+
const files1 = [...it1].map((f) => f.slice(pth1.length));
|
|
50
|
+
const files2 = [...it2].map((f) => f.slice(pth2.length));
|
|
51
|
+
if (files1.length !== files2.length) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
// sort files so in same order
|
|
55
|
+
files1.sort();
|
|
56
|
+
files2.sort();
|
|
57
|
+
if (!files1.every((f, i) => f === files2[i])) {
|
|
58
|
+
// the two lists of files are not the same
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
// compare contents of each file
|
|
62
|
+
for (let i = 0; i < files1.length; i++) {
|
|
63
|
+
const file1 = pth1 + at(files1, i);
|
|
64
|
+
const file2 = pth2 + at(files2, i);
|
|
65
|
+
const stat1 = fs.statSync(file1);
|
|
66
|
+
if (stat1.isDirectory()) {
|
|
67
|
+
// already checked above
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
// files, so compare contents
|
|
71
|
+
const content1 = fs.readFileSync(file1);
|
|
72
|
+
const content2 = fs.readFileSync(file2);
|
|
73
|
+
if (!content1.equals(content2)) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export const readDataJson = (pth: string) => {
|
|
81
|
+
let content = fs.readFileSync(pth).toString();
|
|
82
|
+
// TODO use getPaths() here to find the repo dir
|
|
83
|
+
content = content.replaceAll("${repo}", `${__dirname}/../../../..`);
|
|
84
|
+
const dataJson = JSON.parse(content.toString());
|
|
85
|
+
const data = DataSchema.parse(dataJson);
|
|
86
|
+
return data;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export const readCaptchasJson = (pth: string) => {
|
|
90
|
+
const content = fs.readFileSync(pth).toString();
|
|
91
|
+
const dataJson = JSON.parse(content);
|
|
92
|
+
const captchas = CaptchasContainerSchema.parse(dataJson);
|
|
93
|
+
return captchas;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const captchasEqFs = (pth1: string, pth2: string) => {
|
|
97
|
+
const data1 = readCaptchasJson(pth1);
|
|
98
|
+
const data2 = readCaptchasJson(pth2);
|
|
99
|
+
return captchasEq(data1, data2);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export const captchasEq = (
|
|
103
|
+
first: CaptchasContainer,
|
|
104
|
+
second: CaptchasContainer,
|
|
105
|
+
) => {
|
|
106
|
+
if (first.captchas.length !== second.captchas.length) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
for (let i = 0; i < first.captchas.length; i++) {
|
|
110
|
+
const captcha1 = at(first.captchas, i);
|
|
111
|
+
const captcha2 = at(second.captchas, i);
|
|
112
|
+
// salts should not be the same as generated on the fly and not stored!
|
|
113
|
+
if (captcha1.salt === captcha2.salt) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
// everything else should be the same
|
|
117
|
+
const { salt: salt1, ...rest1 } = captcha1;
|
|
118
|
+
const { salt: salt2, ...rest2 } = captcha2;
|
|
119
|
+
if (JSON.stringify(rest1) !== JSON.stringify(rest2)) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return true;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export const substituteRepoDir = () => {
|
|
127
|
+
// read all json files in the test data dir
|
|
128
|
+
for (const pth of fsWalk(`${__dirname}/data`)) {
|
|
129
|
+
if (!pth.endsWith(".json")) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
// make a backup of each file
|
|
133
|
+
fs.copyFileSync(pth, `${pth}.bak`);
|
|
134
|
+
// replace ${repo} with the path to the repo
|
|
135
|
+
let content = fs.readFileSync(pth).toString();
|
|
136
|
+
// TODO use getPaths() here to find the repo dir
|
|
137
|
+
content = content.replaceAll("${repo}", `${__dirname}/../../../..`);
|
|
138
|
+
// rewrite the file
|
|
139
|
+
fs.writeFileSync(pth, content);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export const restoreRepoDir = () => {
|
|
144
|
+
// read all json files in the test data dir
|
|
145
|
+
for (const pth of fsWalk(`${__dirname}/data`)) {
|
|
146
|
+
if (!pth.endsWith(".json")) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
// restore the backup of each file
|
|
150
|
+
fs.renameSync(`${pth}.bak`, pth);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { ProsopoDatasetError, ProsopoError } from "@prosopo/common";
|
|
3
|
+
// Copyright 2021-2026 Prosopo (UK) Ltd.
|
|
4
|
+
//
|
|
5
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
// you may not use this file except in compliance with the License.
|
|
7
|
+
// You may obtain a copy of the License at
|
|
8
|
+
//
|
|
9
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
//
|
|
11
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
// See the License for the specific language governing permissions and
|
|
15
|
+
// limitations under the License.
|
|
16
|
+
import * as z from "zod";
|
|
17
|
+
import { CliCommand } from "../cli/cliCommand.js";
|
|
18
|
+
|
|
19
|
+
export const InputArgsSchema = z.object({
|
|
20
|
+
input: z.string(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export type InputArgs = z.infer<typeof InputArgsSchema>;
|
|
24
|
+
|
|
25
|
+
export class InputCliCommand<
|
|
26
|
+
T extends typeof InputArgsSchema,
|
|
27
|
+
> extends CliCommand<T> {
|
|
28
|
+
public override getArgSchema(): T {
|
|
29
|
+
throw new ProsopoError("DEVELOPER.METHOD_NOT_IMPLEMENTED");
|
|
30
|
+
}
|
|
31
|
+
public override getDescription(): string {
|
|
32
|
+
throw new ProsopoError("DEVELOPER.METHOD_NOT_IMPLEMENTED");
|
|
33
|
+
}
|
|
34
|
+
public override getOptions() {
|
|
35
|
+
return {
|
|
36
|
+
input: {
|
|
37
|
+
string: true,
|
|
38
|
+
alias: "in",
|
|
39
|
+
demand: true,
|
|
40
|
+
description: "The input path",
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public override async _check(args: InputArgs) {
|
|
46
|
+
this.logger.debug(() => ({ msg: "input _check" }));
|
|
47
|
+
await super._check(args);
|
|
48
|
+
// input must exist
|
|
49
|
+
if (!fs.existsSync(args.input)) {
|
|
50
|
+
throw new ProsopoDatasetError(
|
|
51
|
+
new Error(`input path does not exist: ${args.input}`),
|
|
52
|
+
{
|
|
53
|
+
translationKey: "FS.FILE_NOT_FOUND",
|
|
54
|
+
},
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Copyright 2021-2026 Prosopo (UK) Ltd.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
import type * as z from "zod";
|
|
15
|
+
import { CliCommandComposite } from "../cli/cliCommandComposite.js";
|
|
16
|
+
import { InputArgsSchema, InputCliCommand } from "./input.js";
|
|
17
|
+
import { OutputArgsSchema, OutputCliCommand } from "./output.js";
|
|
18
|
+
|
|
19
|
+
export const InputOutputArgsSchema = InputArgsSchema.merge(OutputArgsSchema);
|
|
20
|
+
|
|
21
|
+
export type InputOutputArgs = z.infer<typeof InputOutputArgsSchema>;
|
|
22
|
+
|
|
23
|
+
export abstract class InputOutputCliCommand<
|
|
24
|
+
T extends typeof InputOutputArgsSchema,
|
|
25
|
+
> extends CliCommandComposite<T> {
|
|
26
|
+
constructor() {
|
|
27
|
+
super([new InputCliCommand<T>(), new OutputCliCommand<T>()]);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { ProsopoEnvError, ProsopoError } from "@prosopo/common";
|
|
3
|
+
import { lodash } from "@prosopo/util/lodash";
|
|
4
|
+
import { boolean, object, string, type infer as zInfer } from "zod";
|
|
5
|
+
// Copyright 2021-2026 Prosopo (UK) Ltd.
|
|
6
|
+
//
|
|
7
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
// you may not use this file except in compliance with the License.
|
|
9
|
+
// You may obtain a copy of the License at
|
|
10
|
+
//
|
|
11
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
//
|
|
13
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
// See the License for the specific language governing permissions and
|
|
17
|
+
// limitations under the License.
|
|
18
|
+
import { CliCommand } from "../cli/cliCommand.js";
|
|
19
|
+
|
|
20
|
+
export const OutputArgsSchema = object({
|
|
21
|
+
output: string(),
|
|
22
|
+
overwrite: boolean().optional(),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export type OutputArgs = zInfer<typeof OutputArgsSchema>;
|
|
26
|
+
|
|
27
|
+
export class OutputCliCommand<
|
|
28
|
+
T extends typeof OutputArgsSchema,
|
|
29
|
+
> extends CliCommand<T> {
|
|
30
|
+
#outputExists = false;
|
|
31
|
+
|
|
32
|
+
public outputExists() {
|
|
33
|
+
return this.#outputExists;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public override getArgSchema(): T {
|
|
37
|
+
throw new ProsopoError("DEVELOPER.METHOD_NOT_IMPLEMENTED");
|
|
38
|
+
}
|
|
39
|
+
public override getDescription(): string {
|
|
40
|
+
throw new ProsopoError("DEVELOPER.METHOD_NOT_IMPLEMENTED");
|
|
41
|
+
}
|
|
42
|
+
public override getOptions() {
|
|
43
|
+
return lodash().merge(super.getOptions(), {
|
|
44
|
+
output: {
|
|
45
|
+
alias: "out",
|
|
46
|
+
string: true,
|
|
47
|
+
demand: true,
|
|
48
|
+
description: "The output path",
|
|
49
|
+
},
|
|
50
|
+
overwrite: {
|
|
51
|
+
boolean: true,
|
|
52
|
+
description: "Overwrite files in the output path if they already exist",
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public override async _check(args: OutputArgs) {
|
|
58
|
+
this.logger.debug(() => ({ msg: "Output _check" }));
|
|
59
|
+
await super._check(args);
|
|
60
|
+
|
|
61
|
+
// record whether output already exists
|
|
62
|
+
this.#outputExists = fs.existsSync(args.output);
|
|
63
|
+
|
|
64
|
+
// output must not exist, unless overwrite is true
|
|
65
|
+
if (this.outputExists()) {
|
|
66
|
+
if (!args.overwrite) {
|
|
67
|
+
throw new ProsopoEnvError(
|
|
68
|
+
new Error(`output path already exists: ${args.output}`),
|
|
69
|
+
{
|
|
70
|
+
translationKey: "FS.FILE_ALREADY_EXISTS",
|
|
71
|
+
},
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public override async _run(args: OutputArgs) {
|
|
78
|
+
this.logger.debug(() => ({ msg: "Output run" }));
|
|
79
|
+
await super._run(args);
|
|
80
|
+
if (args.overwrite && this.outputExists()) {
|
|
81
|
+
// if overwrite is true, delete the output directory
|
|
82
|
+
this.logger.info(() => ({ msg: "cleaning output directory..." }));
|
|
83
|
+
fs.rmSync(args.output, { recursive: true });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.cjs.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"rootDir": "./src",
|
|
5
|
+
"outDir": "./dist/cjs"
|
|
6
|
+
},
|
|
7
|
+
"include": [
|
|
8
|
+
"./src/**/*.ts",
|
|
9
|
+
"./src/**/*.json",
|
|
10
|
+
"./src/**/*.d.ts",
|
|
11
|
+
"./src/**/*.tsx"
|
|
12
|
+
],
|
|
13
|
+
"references": [
|
|
14
|
+
{
|
|
15
|
+
"path": "../../dev/config/tsconfig.cjs.json"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"path": "../common/tsconfig.cjs.json"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"path": "../logger/tsconfig.cjs.json"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"path": "../util/tsconfig.cjs.json"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"path": "../types/tsconfig.cjs.json"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"path": "../util-crypto/tsconfig.cjs.json"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"path": "../../dev/workspace/tsconfig.cjs.json"
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|