Socket
Socket
Sign inDemoInstall

destiny

Package Overview
Dependencies
56
Maintainers
1
Versions
23
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.6.1 to 0.6.2

.github/PULL_REQUEST_TEMPLATE.md

11

CHANGELOG.md

@@ -0,1 +1,12 @@

## [0.6.2](https://github.com/benawad/destiny/compare/v0.6.1...v0.6.2) (2020-04-29)
### Bug Fixes
* [#111](https://github.com/benawad/destiny/issues/111) ([3b05b2a](https://github.com/benawad/destiny/commit/3b05b2a6b371bd53276bc316393dfd6883c001aa))
* [#119](https://github.com/benawad/destiny/issues/119) ([366f8cf](https://github.com/benawad/destiny/commit/366f8cfdb200fdaffc820b4fb6b61893aed0fdc7))
* [#129](https://github.com/benawad/destiny/issues/129) ([2db66af](https://github.com/benawad/destiny/commit/2db66af44bf746e11251d1b6b7fff1830368ae97))
* **#125:** resolve home dir ([40b36a2](https://github.com/benawad/destiny/commit/40b36a22c0dbb86bf7217bae984ec0ffa4556c2e))
* check cycle when graphl is all globals ([7880933](https://github.com/benawad/destiny/commit/78809330a3be0c04484483a91e2dd5642c8915e9))
## [0.6.1](https://github.com/benawad/destiny/compare/v0.6.0...v0.6.1) (2020-04-25)

@@ -2,0 +13,0 @@

44

lib/destiny.js

@@ -13,2 +13,3 @@ #!/usr/bin/env node

var fs = _interopDefault(require('fs'));
var os = _interopDefault(require('os'));
var glob = _interopDefault(require('glob'));

@@ -190,8 +191,15 @@ var cosmiconfig = require('cosmiconfig');

function findImports(filePath) {
const reImport = /(?:(?:import|from)\s+|(?:import|require)\s*\()['"]((?:\.{1,2})(?:\/.+)?)['"]/gm;
const reComment = /\/\*[^]*?\*\/|^.*\/\/.*$/gm;
// match es5 & es6 imports
const _reImport = `(?:(?:import|from)\\s+|(?:import|require)\\s*\\()['"]((?:\\.{1,2})(?:\\/.+)?)['"]`;
const reImport = new RegExp(_reImport, "gm"); // match one & multi line(s) comments
const reComment = /\/\*[\s\S]*?\*\/|\/\/.*/gm; // match string which contain an import https://github.com/benawad/destiny/issues/111
const reOneLineString = new RegExp(`["'].*(${_reImport}).*["']`, "g"); // match multi lines string which contain an import https://github.com/benawad/destiny/issues/111
const reMultiLinesString = new RegExp(`\`[^]*(${_reImport})[^]*\``, "gm");
const importPaths = [];
const fileContent = fs.readFileSync(filePath, {
encoding: "utf8"
}).replace(reComment, "");
}).replace(reComment, "").replace(reOneLineString, "").replace(reMultiLinesString, "");
let matches;

@@ -222,3 +230,10 @@

const ext = getExtensionFromImport(relativePath);
const fileName = path.basename(relativePath, ext);
let fileName = path.basename(relativePath, ext); // this will cleanup index imports
// path.join("../add", ".") => "../add"
// instead of: path.join("../add", "index") => "../add/index"
if (fileName === "index") {
fileName = ".";
}
let newImport = path.join(relativeDirectory, fileName); // Ensures relative imports.

@@ -310,3 +325,3 @@

if (absPath == null) {
logger.error(`Cannot find import ${importPath}`);
logger.error(`Cannot find import ${importPath} for ${basedir}`);
continue;

@@ -469,3 +484,3 @@ }

if (pathWithExtension == null) {
logger.error(`Cannot find import ${importPath}`);
logger.error(`Cannot find import ${importPath} for ${filePath}`);
return;

@@ -618,3 +633,5 @@ }

for (const importFilePath of imports) {
if (importFilePath in tree) {
// if importFilePath includes .. then it's a global
// we don't store globals in tree, so check if cycle
if (importFilePath in tree || importFilePath.includes("..")) {
const cycle = hasCycle(importFilePath, graph, new Set());

@@ -801,3 +818,3 @@

var version = "0.6.1";
var version = "0.6.2";

@@ -822,3 +839,3 @@ /** Format the given options and print the help message */

const [longestFlag] = [...optionsWithJoinedFlags].sort((a, b) => b.flags.length - a.flags.length);
const descriptionsX = `${longestFlag.flags}${indent}${indent}`.length;
const descriptionsPosX = `${longestFlag.flags}${indent.repeat(2)}`.length;
const parsedOptionsMessage = optionsWithJoinedFlags.map(({

@@ -828,4 +845,4 @@ flags,

}) => {
const numOfSpacesToAdd = descriptionsX - flags.length;
return `${indent}${flags}${Array(numOfSpacesToAdd).fill(" ").join("")}${description}`;
const numOfSpacesToAdd = descriptionsPosX - flags.length;
return `${indent}${flags}${" ".repeat(numOfSpacesToAdd)}${description}`;
}).join("\n");

@@ -847,2 +864,4 @@ console.log(parsedOptionsMessage, "\n");

const resolveHomeDir = path => path.replace(/~\/|~(?!.)/, `${os.homedir()}/`);
const printVersion = () => console.log("v" + version);

@@ -904,3 +923,3 @@

{
if (fs.existsSync(arg) || glob.hasMagic(arg)) {
if (fs.existsSync(resolveHomeDir(arg)) || glob.hasMagic(arg)) {
var _cliConfig$include;

@@ -943,2 +962,3 @@

logger.debug("config used:", mergedConfig);
mergedConfig.include = mergedConfig.include.map(resolveHomeDir);
const restructureMap = getRestructureMap(mergedConfig.include);

@@ -945,0 +965,0 @@ const filesToEdit = Object.values(restructureMap).flat();

#!/usr/bin/env node
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0}),require("core-js/modules/es.array.flat"),require("core-js/modules/es.array.unscopables.flat"),require("core-js/modules/es.promise");var n=e(require("fs")),t=e(require("glob")),r=require("cosmiconfig"),o=require("fs-extra"),s=e(o),i=e(require("path")),l=e(require("chalk")),c=e(require("simple-git/promise")),a=e(require("resolve"));require("core-js/modules/es.symbol.description");let u="";const f=(e,n=0)=>{const t=e instanceof Error?e:l.red.bold("ERROR: ")+e;u+=`${e}\n`,console.error(t),console.log("If you think this is a bug, you can report it: https://github.com/benawad/destiny/issues"),process.exit(n)};let d=!1,p=null;const g=(e,...n)=>{if(!d)return;const t=Date.now(),r=l.magenta.bold("DEBUG: ")+l.yellow.bold(`+${p?t-p:0}ms `)+e;u+=`${e}\n`,console.info(r),p=t,n.length>0&&(console.group(),n.forEach(e=>{console.log(e,"\n")}),console.groupEnd())};var h=f,m=e=>{const n=l.green.bold("INFO: ")+e;u+=`${e}\n`,console.info(n)},b=e=>{u+=`${e}\n`,console.log(e)},y=e=>{const n=l.yellow.bold("WARN: ")+e;u+=`${e}\n`,console.warn(n)},v=()=>{d=!0},j=g,$=e=>{if(!d)return;const t=i.resolve(e);n.existsSync(t)&&f(`The debug file output already exist "${t}".\nPlease give a path to a non existing file.`),n.writeFileSync(t,u,"utf8"),g(`stdout written in "${t}"`)};const w=e=>s.lstatSync(e).isDirectory(),S=e=>s.lstatSync(e).isFile(),x=e=>{const n=t.sync(e),r=n.filter(e=>S(e));return j(`glob matches for "${e}":`,n),0===r.length&&h("Could not find any files for: "+e,1),r},F=e=>{const n=[],r=[e];for(;r.length>0;){const e=r.shift();if(null==e||0===e.length)break;if(t.hasMagic(e))n.push(...x(e));else{if(!s.existsSync(e)){h(`Unable to resolve the path: ${e}`);break}w(e)?r.push(i.resolve(e,"./**/*.*")):S(e)&&n.push(e)}}return n};async function O(e,n){return e.silent(!0).raw(["ls-files","--error-unmatch",n]).then(()=>!0).catch(()=>!1)}async function E(e,n){const t=c(n),r=await t.checkIsRepo();for(const[o,l]of Object.entries(e)){if(o.includes(".."))continue;const e=i.resolve(n,o),c=i.resolve(n,l);if(e===c)continue;const a=i.dirname(c);s.ensureDirSync(a);const u=r&&await O(t,e);j(`moving "${e}" to "${c}"`),u?await t.mv(e,c):s.renameSync(e,c)}}function k(e){const t=n.readdirSync(e);if(!t)return n.rmdirSync(e);for(const r of t){const t=i.resolve(e,r);n.lstatSync(t).isDirectory()&&(k(t),0===n.readdirSync(t).length&&(n.rmdirSync(t),j(`removing "${t}" as empty folder`)))}}function q(e){const t=/(?:(?:import|from)\s+|(?:import|require)\s*\()['"]((?:\.{1,2})(?:\/.+)?)['"]/gm,r=[],o=n.readFileSync(e,{encoding:"utf8"}).replace(/\/\*[^]*?\*\/|^.*\/\/.*$/gm,"");let s;for(;null!==(s=t.exec(o));)s.index===t.lastIndex&&t.lastIndex++,r.push(s[1]);return r}const A=(e,n,t)=>{const r=i.dirname(e),o=i.relative(r,n),s=i.dirname(o),l=function(e){const n=i.extname(e);return[".js",".jsx",".ts",".tsx"].includes(n)?n:void 0}(o),c=i.basename(o,l);let a=i.join(s,c);return!a.startsWith(".")&&(a="./"+a),a=t?a.replace(/\\/g,"/"):a.replace(/\/|\\+/g,"\\\\"),a},R=[".js",".json",".jsx",".sass",".scss",".svg",".ts",".d.ts",".tsx",".js.flow"],C=(e,n)=>{try{return a.sync(e,{basedir:n,extensions:R})}catch(e){return null}},I=(e,n)=>{for(const{tree:t,parentFolder:r}of n){const n=i.relative(r,e);if(n in t)return i.resolve(i.join(r,t[n]))}return e},D=(e,n,t)=>{let r=!0;for(const{tree:o,parentFolder:s,useForwardSlash:l}of t){r=l;const t=i.relative(s,e);if(t in o)return A(n,i.resolve(i.join(s,o[t])),l)}return A(n,e,r)},M=async(e,n)=>{m("Fixing imports."),((e,n)=>{for(const t of e){j(`checking imports of "${t}"`);const e=q(t);if(0===e.length){j(`no import found in "${t}"`);continue}const r=i.dirname(t),s=I(t,n),l=o.readFileSync(t).toString();let c=l.repeat(1);for(const o of e){const e=C(o,r);if(null==e){h(`Cannot find import ${o}`);continue}const i=D(e,s,n);null!=i&&o!==i&&(j(`replacing import of "${o}" by "${i}" in "${t}"`),c=c.replace(`'${o}'`,`'${i}'`).replace(`"${o}"`,`"${i}"`))}c!==l&&(j(`writing new imports of "${t}"`),o.writeFileSync(t,c))}})(e,n);for(const{tree:e,parentFolder:t}of n)m("Moving files."),await E(e,t),k(t);m("Restructure was successful!")},N=e=>e.replace(/([^/]+)(?=\.)/g,String.fromCharCode(Number.MAX_SAFE_INTEGER)+"$1"),P=(e,n)=>N(e).localeCompare(N(n)),G=e=>{const n=e.reduce((e,n)=>{const t=n.split("/");return t.forEach((n,r)=>e.add(((e,n)=>i.join(...e.slice(0,n)))(t,r+1))),e},new Set);return Array.from(n).sort(P)},T=e=>{const n=(e=>{const n=[];let t=[...e];for(;t.length>0;){const e=t.shift();if(null==e)break;t=t.map(n=>{return t=e,n.replace(new RegExp(`^(/*)${t.replace(/\//g,"")}(/+)`),"$1$2");var t}),n.push(e)}return n.map(e=>{var n;const t=e.split("/");return{text:null!=(n=t.pop())?n:"",position:t.length}})})(G(e)),t=n.reduce((e,t,r)=>{var o;const s=null!=(o=e[r-1])?o:"",i=n.slice(r+1),c=i.length>0&&i[0].position>t.position,a=(t.position>0?"│ ".repeat(t.position):"")+(((e,n)=>{for(const t of n)if(!(t.position>e.position))return t.position<e.position;return!0})(t,i)?"└──":"├──")+(c?l.bold.blue(t.text):t.text);return e.push(((e,n)=>Array.from(e).map((e,t)=>"│"===e&&(e=>"└"===e||" "===e)(n[t])?" ":e).join(""))(a,s)),e},[]).join("\n");return b(t),t},_=e=>{if(1===e.length)return i.dirname(e[0]);const[n,t]=e.length>2?e.sort((e,n)=>e.length-n.length):e,r=t.split(i.sep);return n.split(i.sep).filter((e,n)=>e===r[n]).join(i.sep)},U=e=>[/^\.git/].some(n=>n.test(e));const W=e=>/\.test\.|\.spec\.|\.stories\./.test(e);function V(e){const n=(e=>{const n={};return Object.keys(e).forEach(t=>{e[t].forEach(e=>{e in n||(n[e]=[]),n[e].push(t)})}),n})(e),t=Object.keys(e),r=t.filter(e=>{const t=n[e];return!t||!t.length||t.every(e=>W(e))});if(r.length)return r;const o={};t.forEach(e=>{const n=e.split("/").length;n in o||(o[n]=[]),o[n].push(e)});for(let e=1;e<10;e++)if(e in o)return o[e];return[]}const z=(e,n,t)=>{const r=n[e];if(t.has(e))return[...t,e];if(t.add(e),null==r||0===r.length)return null;for(const e of r){const r=z(e,n,new Set(t));if(r)return r}return null};const B=e=>{const n=e.split(i.sep);if(1!==n.length)return n.pop(),n.join(i.sep)},X=e=>{const n=e.split(i.sep);return[...n.slice(0,n.length-2),n[n.length-1]].join(i.sep)};function H(e,{avoidSingleFile:n}){return Object.entries(e).reduce((e,[t,r])=>{if(r.length<=1)return e;m(`Generating tree for: ${t}`);const{graph:o,files:s,useForwardSlash:c,parentFolder:a}=function(e){const n=_(e),t={},r=[];for(let o of e){if(U(o))continue;o=i.resolve(o);const e=i.relative(n,o);r.push(e),q(o).forEach(r=>{const s=C(r,i.dirname(o));if(null==s)return void h(`Cannot find import ${r}`);const l=i.relative(n,s);Array.isArray(t[e])||(t[e]=[]),t[e].includes(l)||t[e].push(l)})}return{files:r,graph:t,parentFolder:n,useForwardSlash:"/"===i.sep}}(r);let u=function(e,n){const t={},r=new Set,o={},s=new Set;let l=!1;const c=(e,n)=>{Array.isArray(o[e])||(o[e]=[]),o[e].push(n)},a=(e,n,t)=>{if(r.has(e)){const e=i.join(n,t.replace(/\//g,"-"));return m(`File renamed: ${t} -> ${e}`),e}return e},u=(e,n,o)=>{const f=i.basename(e);if(W(f))return void s.add(e);let d=i.basename(e,i.extname(e));const p=i.basename(i.dirname(e)),g=e.includes(".."),h=g?e:i.join(n,"index"===d&&p&&"."!==p?p+i.extname(e):f),m=a(h,n,e);d=i.basename(m,i.extname(m)),g||(t[e]=m,r.add(m));const b=o[e];if((null==b?void 0:b.length)>0){const e=i.join(n,d);for(const n of b)if(n in t){const e=z(n,o,new Set);e?(l=!0,y(`Dependency cycle detected: ${e.join(" -> ")}`)):c(n,m)}else c(n,m),u(n,e,o)}};for(const t of n)u(t,"",e);if(l||Object.entries(o).forEach(([e,n])=>{if(n.length<=1||e.includes(".."))return;const o=_(n),s=i.basename(e),l=i.dirname(e),c=i.join(o,"shared","index"===i.basename(s,i.extname(s))&&l&&"."!==l?i.join(l+i.extname(s)):s);t[e]=c,r.add(c)}),s.size>0)for(const n of s){const[o]=e[n];if(!o)continue;const s=t[o];if(!s)continue;const l=a(i.join(i.dirname(s),i.basename(n)),i.dirname(s),n);t[n]=l,r.add(l)}return t}(o,V(o));n&&(u=(e=>{const n={...e},t={};for(const[e,r]of Object.entries(n))t[r]=e;const r={},o=Object.values(n).sort((e,n)=>n.length-e.length);for(const e of o){const n=B(e);n&&(r[n]=n in r?r[n]+1:1)}for(const e of o){const o=B(e);if(!o)continue;let s=r[o],i=e,l=o;for(;1===s&&(l=B(i),l);)o===l?s=1:l in r&&(s=r[l]+1),r[l]=s,1===s&&(i=X(i));n[t[e]]=i}return n})(u));const f=new Set(Object.entries(o).flat(2)),d=s.filter(e=>!f.has(e));return b(l.bold.blue(a.split(i.sep).pop())),T(Object.values(u)),d.length>0&&y(`Found ${d.length} unused files:`+"\n"+d.join("\n")),e.push({parentFolder:a,tree:u,useForwardSlash:c}),e},[])}const{argv:J}=process,K={help:!1,include:[],version:!1,write:!1,avoidSingleFile:!1,debug:!1},L=e=>((e=>{console.log(l`{blue destiny} - Prettier for file structures.
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0}),require("core-js/modules/es.array.flat"),require("core-js/modules/es.array.unscopables.flat"),require("core-js/modules/es.promise");var n=e(require("fs")),t=e(require("os")),r=e(require("glob")),o=require("cosmiconfig"),s=require("fs-extra"),i=e(s),l=e(require("path")),c=e(require("chalk")),a=e(require("simple-git/promise")),u=e(require("resolve"));require("core-js/modules/es.symbol.description");let f="";const d=(e,n=0)=>{const t=e instanceof Error?e:c.red.bold("ERROR: ")+e;f+=`${e}\n`,console.error(t),console.log("If you think this is a bug, you can report it: https://github.com/benawad/destiny/issues"),process.exit(n)};let p=!1,g=null;const h=(e,...n)=>{if(!p)return;const t=Date.now(),r=c.magenta.bold("DEBUG: ")+c.yellow.bold(`+${g?t-g:0}ms `)+e;f+=`${e}\n`,console.info(r),g=t,n.length>0&&(console.group(),n.forEach(e=>{console.log(e,"\n")}),console.groupEnd())};var m=d,b=e=>{const n=c.green.bold("INFO: ")+e;f+=`${e}\n`,console.info(n)},y=e=>{f+=`${e}\n`,console.log(e)},v=e=>{const n=c.yellow.bold("WARN: ")+e;f+=`${e}\n`,console.warn(n)},$=()=>{p=!0},j=h,w=e=>{if(!p)return;const t=l.resolve(e);n.existsSync(t)&&d(`The debug file output already exist "${t}".\nPlease give a path to a non existing file.`),n.writeFileSync(t,f,"utf8"),h(`stdout written in "${t}"`)};const x=e=>i.lstatSync(e).isDirectory(),S=e=>i.lstatSync(e).isFile(),F=e=>{const n=r.sync(e),t=n.filter(e=>S(e));return j(`glob matches for "${e}":`,n),0===t.length&&m("Could not find any files for: "+e,1),t},E=e=>{const n=[],t=[e];for(;t.length>0;){const e=t.shift();if(null==e||0===e.length)break;if(r.hasMagic(e))n.push(...F(e));else{if(!i.existsSync(e)){m(`Unable to resolve the path: ${e}`);break}x(e)?t.push(l.resolve(e,"./**/*.*")):S(e)&&n.push(e)}}return n};async function O(e,n){return e.silent(!0).raw(["ls-files","--error-unmatch",n]).then(()=>!0).catch(()=>!1)}async function k(e,n){const t=a(n),r=await t.checkIsRepo();for(const[o,s]of Object.entries(e)){if(o.includes(".."))continue;const e=l.resolve(n,o),c=l.resolve(n,s);if(e===c)continue;const a=l.dirname(c);i.ensureDirSync(a);const u=r&&await O(t,e);j(`moving "${e}" to "${c}"`),u?await t.mv(e,c):i.renameSync(e,c)}}function q(e){const t=n.readdirSync(e);if(!t)return n.rmdirSync(e);for(const r of t){const t=l.resolve(e,r);n.lstatSync(t).isDirectory()&&(q(t),0===n.readdirSync(t).length&&(n.rmdirSync(t),j(`removing "${t}" as empty folder`)))}}function R(e){const t="(?:(?:import|from)\\s+|(?:import|require)\\s*\\()['\"]((?:\\.{1,2})(?:\\/.+)?)['\"]",r=new RegExp(t,"gm"),o=new RegExp(`["'].*(${t}).*["']`,"g"),s=new RegExp(`\`[^]*(${t})[^]*\``,"gm"),i=[],l=n.readFileSync(e,{encoding:"utf8"}).replace(/\/\*[\s\S]*?\*\/|\/\/.*/gm,"").replace(o,"").replace(s,"");let c;for(;null!==(c=r.exec(l));)c.index===r.lastIndex&&r.lastIndex++,i.push(c[1]);return i}const A=(e,n,t)=>{const r=l.dirname(e),o=l.relative(r,n),s=l.dirname(o),i=function(e){const n=l.extname(e);return[".js",".jsx",".ts",".tsx"].includes(n)?n:void 0}(o);let c=l.basename(o,i);"index"===c&&(c=".");let a=l.join(s,c);return!a.startsWith(".")&&(a="./"+a),a=t?a.replace(/\\/g,"/"):a.replace(/\/|\\+/g,"\\\\"),a},C=[".js",".json",".jsx",".sass",".scss",".svg",".ts",".d.ts",".tsx",".js.flow"],I=(e,n)=>{try{return u.sync(e,{basedir:n,extensions:C})}catch(e){return null}},D=(e,n)=>{for(const{tree:t,parentFolder:r}of n){const n=l.relative(r,e);if(n in t)return l.resolve(l.join(r,t[n]))}return e},M=(e,n,t)=>{let r=!0;for(const{tree:o,parentFolder:s,useForwardSlash:i}of t){r=i;const t=l.relative(s,e);if(t in o)return A(n,l.resolve(l.join(s,o[t])),i)}return A(n,e,r)},N=async(e,n)=>{b("Fixing imports."),((e,n)=>{for(const t of e){j(`checking imports of "${t}"`);const e=R(t);if(0===e.length){j(`no import found in "${t}"`);continue}const r=l.dirname(t),o=D(t,n),i=s.readFileSync(t).toString();let c=i.repeat(1);for(const s of e){const e=I(s,r);if(null==e){m(`Cannot find import ${s} for ${r}`);continue}const i=M(e,o,n);null!=i&&s!==i&&(j(`replacing import of "${s}" by "${i}" in "${t}"`),c=c.replace(`'${s}'`,`'${i}'`).replace(`"${s}"`,`"${i}"`))}c!==i&&(j(`writing new imports of "${t}"`),s.writeFileSync(t,c))}})(e,n);for(const{tree:e,parentFolder:t}of n)b("Moving files."),await k(e,t),q(t);b("Restructure was successful!")},P=e=>e.replace(/([^/]+)(?=\.)/g,String.fromCharCode(Number.MAX_SAFE_INTEGER)+"$1"),G=(e,n)=>P(e).localeCompare(P(n)),T=e=>{const n=e.reduce((e,n)=>{const t=n.split("/");return t.forEach((n,r)=>e.add(((e,n)=>l.join(...e.slice(0,n)))(t,r+1))),e},new Set);return Array.from(n).sort(G)},_=e=>{const n=(e=>{const n=[];let t=[...e];for(;t.length>0;){const e=t.shift();if(null==e)break;t=t.map(n=>{return t=e,n.replace(new RegExp(`^(/*)${t.replace(/\//g,"")}(/+)`),"$1$2");var t}),n.push(e)}return n.map(e=>{var n;const t=e.split("/");return{text:null!=(n=t.pop())?n:"",position:t.length}})})(T(e)),t=n.reduce((e,t,r)=>{var o;const s=null!=(o=e[r-1])?o:"",i=n.slice(r+1),l=i.length>0&&i[0].position>t.position,a=(t.position>0?"│ ".repeat(t.position):"")+(((e,n)=>{for(const t of n)if(!(t.position>e.position))return t.position<e.position;return!0})(t,i)?"└──":"├──")+(l?c.bold.blue(t.text):t.text);return e.push(((e,n)=>Array.from(e).map((e,t)=>"│"===e&&(e=>"└"===e||" "===e)(n[t])?" ":e).join(""))(a,s)),e},[]).join("\n");return y(t),t},U=e=>{if(1===e.length)return l.dirname(e[0]);const[n,t]=e.length>2?e.sort((e,n)=>e.length-n.length):e,r=t.split(l.sep);return n.split(l.sep).filter((e,n)=>e===r[n]).join(l.sep)},W=e=>[/^\.git/].some(n=>n.test(e));const V=e=>/\.test\.|\.spec\.|\.stories\./.test(e);function z(e){const n=(e=>{const n={};return Object.keys(e).forEach(t=>{e[t].forEach(e=>{e in n||(n[e]=[]),n[e].push(t)})}),n})(e),t=Object.keys(e),r=t.filter(e=>{const t=n[e];return!t||!t.length||t.every(e=>V(e))});if(r.length)return r;const o={};t.forEach(e=>{const n=e.split("/").length;n in o||(o[n]=[]),o[n].push(e)});for(let e=1;e<10;e++)if(e in o)return o[e];return[]}const B=(e,n,t)=>{const r=n[e];if(t.has(e))return[...t,e];if(t.add(e),null==r||0===r.length)return null;for(const e of r){const r=B(e,n,new Set(t));if(r)return r}return null};const X=e=>{const n=e.split(l.sep);if(1!==n.length)return n.pop(),n.join(l.sep)},H=e=>{const n=e.split(l.sep);return[...n.slice(0,n.length-2),n[n.length-1]].join(l.sep)};function J(e,{avoidSingleFile:n}){return Object.entries(e).reduce((e,[t,r])=>{if(r.length<=1)return e;b(`Generating tree for: ${t}`);const{graph:o,files:s,useForwardSlash:i,parentFolder:a}=function(e){const n=U(e),t={},r=[];for(let o of e){if(W(o))continue;o=l.resolve(o);const e=l.relative(n,o);r.push(e),R(o).forEach(r=>{const s=I(r,l.dirname(o));if(null==s)return void m(`Cannot find import ${r} for ${o}`);const i=l.relative(n,s);Array.isArray(t[e])||(t[e]=[]),t[e].includes(i)||t[e].push(i)})}return{files:r,graph:t,parentFolder:n,useForwardSlash:"/"===l.sep}}(r);let u=function(e,n){const t={},r=new Set,o={},s=new Set;let i=!1;const c=(e,n)=>{Array.isArray(o[e])||(o[e]=[]),o[e].push(n)},a=(e,n,t)=>{if(r.has(e)){const e=l.join(n,t.replace(/\//g,"-"));return b(`File renamed: ${t} -> ${e}`),e}return e},u=(e,n,o)=>{const f=l.basename(e);if(V(f))return void s.add(e);let d=l.basename(e,l.extname(e));const p=l.basename(l.dirname(e)),g=e.includes(".."),h=g?e:l.join(n,"index"===d&&p&&"."!==p?p+l.extname(e):f),m=a(h,n,e);d=l.basename(m,l.extname(m)),g||(t[e]=m,r.add(m));const b=o[e];if((null==b?void 0:b.length)>0){const e=l.join(n,d);for(const n of b)if(n in t||n.includes("..")){const e=B(n,o,new Set);e?(i=!0,v(`Dependency cycle detected: ${e.join(" -> ")}`)):c(n,m)}else c(n,m),u(n,e,o)}};for(const t of n)u(t,"",e);if(i||Object.entries(o).forEach(([e,n])=>{if(n.length<=1||e.includes(".."))return;const o=U(n),s=l.basename(e),i=l.dirname(e),c=l.join(o,"shared","index"===l.basename(s,l.extname(s))&&i&&"."!==i?l.join(i+l.extname(s)):s);t[e]=c,r.add(c)}),s.size>0)for(const n of s){const[o]=e[n];if(!o)continue;const s=t[o];if(!s)continue;const i=a(l.join(l.dirname(s),l.basename(n)),l.dirname(s),n);t[n]=i,r.add(i)}return t}(o,z(o));n&&(u=(e=>{const n={...e},t={};for(const[e,r]of Object.entries(n))t[r]=e;const r={},o=Object.values(n).sort((e,n)=>n.length-e.length);for(const e of o){const n=X(e);n&&(r[n]=n in r?r[n]+1:1)}for(const e of o){const o=X(e);if(!o)continue;let s=r[o],i=e,l=o;for(;1===s&&(l=X(i),l);)o===l?s=1:l in r&&(s=r[l]+1),r[l]=s,1===s&&(i=H(i));n[t[e]]=i}return n})(u));const f=new Set(Object.entries(o).flat(2)),d=s.filter(e=>!f.has(e));return y(c.bold.blue(a.split(l.sep).pop())),_(Object.values(u)),d.length>0&&v(`Found ${d.length} unused files:`+"\n"+d.join("\n")),e.push({parentFolder:a,tree:u,useForwardSlash:i}),e},[])}const{argv:K}=process,L={help:!1,include:[],version:!1,write:!1,avoidSingleFile:!1,debug:!1},Q=e=>e.replace(/~\/|~(?!.)/,`${t.homedir()}/`),Y=e=>((e=>{console.log(c`{blue destiny} - Prettier for file structures.

@@ -11,2 +11,2 @@ {bold USAGE}

{bold OPTIONS}
`);const n=e.map(e=>({...e,flags:e.flags.join(", ")})),[t]=[...n].sort((e,n)=>n.flags.length-e.flags.length),r=`${t.flags} `.length,o=n.map(({flags:e,description:n})=>{const t=r-e.length;return` ${e}${Array(t).fill(" ").join("")}${n}`}).join("\n");console.log(o,"\n")})([{flags:["-V","--version"],description:"Output version number"},{flags:["-h","--help"],description:"Output usage information"},{flags:["-w","--write"],description:"Restructure and edit folders and files"},{flags:["-S","--avoid-single-file"],description:"Flag to indicate if single files in folders should be avoided"},{flags:["--debug [?output file]"],description:"Print debugging info"}]),process.exit(e)),Q=async e=>{const o=(e=>{var n,t;const o=null!=(n=null==(t=r.cosmiconfigSync("destiny").search())?void 0:t.config)?n:{};return{...K,...o,...e}})((e=>{const r={};for(;e.length>0;){const s=e.shift();if(null==s)break;switch(s){case"-h":case"--help":r.help=!0;break;case"-V":case"--version":r.version=!0;break;case"-w":case"--write":r.write=!0;break;case"-S":case"--avoid-single-file":r.avoidSingleFile=!0;break;case"--debug":r.debug=!(e[0]&&!e[0].startsWith("-"))||e.shift();break;default:var o;if(n.existsSync(s)||t.hasMagic(s))r.include=[...null!=(o=r.include)?o:[],s]}}return r})(e));if(o.help)return L(0);if(o.version)return console.log("v0.6.1");if(0===o.include.length)return L(1);o.debug&&v(),process.on("exit",()=>{"string"==typeof o.debug&&$(o.debug),j("exiting")}),j("version: 0.6.1"),j("config used:",o);const s=o.include.reduce((e,n)=>({...e,[n]:F(n)}),{});const i=Object.values(s).flat();if(j("restructured map:",s),0===i.length)return void h("Could not find any files to restructure",1);const l=H(s,o);j("generated tree(s):",l),o.write&&await M(i,l)};Q(J.slice(2,J.length)),exports.run=Q;
`);const n=e.map(e=>({...e,flags:e.flags.join(", ")})),[t]=[...n].sort((e,n)=>n.flags.length-e.flags.length),r=`${t.flags}${" ".repeat(2)}`.length,o=n.map(({flags:e,description:n})=>{const t=r-e.length;return` ${e}${" ".repeat(t)}${n}`}).join("\n");console.log(o,"\n")})([{flags:["-V","--version"],description:"Output version number"},{flags:["-h","--help"],description:"Output usage information"},{flags:["-w","--write"],description:"Restructure and edit folders and files"},{flags:["-S","--avoid-single-file"],description:"Flag to indicate if single files in folders should be avoided"},{flags:["--debug [?output file]"],description:"Print debugging info"}]),process.exit(e)),Z=async e=>{const t=(e=>{var n,t;const r=null!=(n=null==(t=o.cosmiconfigSync("destiny").search())?void 0:t.config)?n:{};return{...L,...r,...e}})((e=>{const t={};for(;e.length>0;){const s=e.shift();if(null==s)break;switch(s){case"-h":case"--help":t.help=!0;break;case"-V":case"--version":t.version=!0;break;case"-w":case"--write":t.write=!0;break;case"-S":case"--avoid-single-file":t.avoidSingleFile=!0;break;case"--debug":t.debug=!(e[0]&&!e[0].startsWith("-"))||e.shift();break;default:var o;if(n.existsSync(Q(s))||r.hasMagic(s))t.include=[...null!=(o=t.include)?o:[],s]}}return t})(e));if(t.help)return Y(0);if(t.version)return console.log("v0.6.2");if(0===t.include.length)return Y(1);t.debug&&$(),process.on("exit",()=>{"string"==typeof t.debug&&w(t.debug),j("exiting")}),j("version: 0.6.2"),j("config used:",t),t.include=t.include.map(Q);const s=t.include.reduce((e,n)=>({...e,[n]:E(n)}),{});const i=Object.values(s).flat();if(j("restructured map:",s),0===i.length)return void m("Could not find any files to restructure",1);const l=J(s,t);j("generated tree(s):",l),t.write&&await N(i,l)};Z(K.slice(2,K.length)),exports.run=Z;
{
"name": "destiny",
"version": "0.6.1",
"version": "0.6.2",
"description": "Prettier for file structures",

@@ -5,0 +5,0 @@ "license": "MIT",

@@ -49,5 +49,5 @@ # Destiny

- This is a work in progress and 100% has bugs of some kind in it
- BEFORE running this tool on your codebase, make sure you have commited to git or made a backup (I don't expect the tool to destroy your work (although it's possible), but just in case you don't like the results)
- BEFORE running this tool on your codebase, make sure you have committed to git or made a backup (I don't expect the tool to destroy your work (although it's possible), but just in case you don't like the results)
- Snapshot tests don't format correctly
- Only works on JavaScript/TypeScript codebases (althought this concept could probably be extended to any language)
- Only works on JavaScript/TypeScript codebases (although this concept could probably be extended to any language)

@@ -54,0 +54,0 @@ ## How to run it

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc