@khatastroffik/treefolder 1.1.0 → 1.2.1

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/README.md CHANGED
@@ -38,6 +38,7 @@ This is the recommanded and easiest approach.
38
38
  1. [Auto "root folder"](#auto-root-folder)
39
39
  1. [Auto "ignore paths"](#auto-ignore-paths)
40
40
  1. [Sort leaves "folders first"](#sort-leaves-folders-first)
41
+ 1. [List output](#list-output)
41
42
  1. [Styled output](#styled-output)
42
43
  1. [Version information](#version-information)
43
44
  1. [Verbose output](#verbose-output)
@@ -59,9 +60,15 @@ Notes:
59
60
 
60
61
  ### Sort leaves "folders first"
61
62
 
62
- By default, the list i.e. the leaves of the treeview are sorted following the _"folders first" principle_: All the folders are listed first, then all the files. All items are alphabetically sorted. This apply at any depth within the tree structure.
63
+ By default, the list or the leaves of the treeview are sorted following the _"folders first" principle_: All the folders are listed first, then all the files. All items are alphabetically sorted. This apply at any depth within the tree structure.
63
64
 
64
- This behavior can be _disabled_ using the command line argument `--unsorted`. In this case, all items are sorted the way the operating system does e.g. sorted by their names, regardless of their type (directory or file).
65
+ This behavior can be _disabled_ using the command line argument `--unsorted`. In this case, all items are sorted the way the operating system does by default e.g. sorted by their names, regardless of their type (directory or file).
66
+
67
+ ### List output
68
+
69
+ When the command line argument `--list` (short: `-l`) is used, all the folders and files will be displayed as a flat list instead of as a treeview.
70
+
71
+ Note: the command line arguments `--unsorted` and `--style colored` may also be applied to refine i.e. adapt the list output. See the [List output examples](docs/readme.md#list-output-examples)
65
72
 
66
73
  ### Styled output
67
74
 
@@ -70,7 +77,10 @@ The style can be defined using the command line argument `--style`or `-s` like s
70
77
 
71
78
  → Examples of styled output can be found in the additional documentation: [Styled output examples](docs/readme.md#styled-output-examples)
72
79
 
73
- Note: some environments i.e. shells may not display the symbols (which are represented using specific unicode code points like `U+1F5BF` or `U+1F5C1`) properly. Try to change the _font_ used in the shell in order to display the correct unicode symbols.
80
+ Notes:
81
+
82
+ - some shell environments may not display the symbols (which are represented using specific unicode code points like `U+1F5BF` or `U+1F5C1`) properly. Try to change the _font_ used in the shell or to change the code page used by your shell in the background to interpret the chars, in order to display the unicode symbols properly.
83
+ - On some shell environments e.g. under Windows OS, the output may still be faulty due to the OS automatically pre-formating the output in an inadequate way. Try to use another shell environment then.
74
84
 
75
85
  ### Version information
76
86
 
package/dist/index.js CHANGED
@@ -1,2 +1,42 @@
1
1
  #! /usr/bin/env node
2
- "use strict";var __createBinding=this&&this.__createBinding||(Object.create?function(e,o,n,t){void 0===t&&(t=n);var r=Object.getOwnPropertyDescriptor(o,n);r&&!("get"in r?!o.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return o[n]}}),Object.defineProperty(e,t,r)}:function(e,o,n,t){void 0===t&&(t=n),e[t]=o[n]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,o){Object.defineProperty(e,"default",{enumerable:!0,value:o})}:function(e,o){e.default=o}),__importStar=this&&this.__importStar||function(){var e=function(o){return e=Object.getOwnPropertyNames||function(e){var o=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(o[o.length]=n);return o},e(o)};return function(o){if(o&&o.__esModule)return o;var n={};if(null!=o)for(var t=e(o),r=0;r<t.length;r++)"default"!==t[r]&&__createBinding(n,o,t[r]);return __setModuleDefault(n,o),n}}(),__importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0});const node_fs_1=__importDefault(require("node:fs")),node_path_1=__importDefault(require("node:path")),node_process_1=require("node:process"),node_util_1=__importStar(require("node:util")),package_json_1=require("../package.json"),readdirPromise=node_util_1.default.promisify(node_fs_1.default.readdir),space=" ";var Style;!function(e){e.none="none",e.wireframe="wireframe",e.black="black",e.colored="colored"}(Style||(Style={}));const symbolStyles={none:{closed:"",open:"",file:""},wireframe:{closed:"🗀",open:"🗁",file:"🗋"},black:{closed:"🖿",open:"🖿",file:"🗎"},colored:{closed:"📁",open:"📂",file:"📄"}},parseArgsOptionsConfig={style:{type:"string",default:"none",short:"s"},verbose:{type:"boolean",default:!1},unsorted:{type:"boolean",default:!1,short:"u"},version:{type:"boolean",default:!1,short:"v"}},config={style:Style.none,symbols:symbolStyles.none,root:".",ignores:["node_modules","dist","build",".git",".husky\\_","logs",".angular","coverage"],verbose:!1,unsorted:!1};let folderCount=0,fileCount=0,ignoredCount=0,cliArgs={};function colorText(e){return(0,node_util_1.styleText)("number"==typeof e?"yellow":"blueBright",`${e}`)}async function getLatestVersion(){const e=await fetch("https://registry.npmjs.org/@khatastroffik/treefolder");await new Promise(e=>setTimeout(e,100));return(await e.json())["dist-tags"].latest}function compareFolderContentItems(e,o){return e.isDirectory()?o.isFile()?-1:e.name.localeCompare(o.name):o.isDirectory()?1:e.name.localeCompare(o.name)}function isIgnored(e,o){const n=config.ignores.includes(node_path_1.default.join(e,o));return n&&ignoredCount++,n}async function getFolderContent(e){const o=(await readdirPromise(e,{withFileTypes:!0})).filter(o=>!isIgnored(e,o.name));return config.unsorted?o:o.sort(compareFolderContentItems)}async function buildTree(e,o,n,t){const r=await getFolderContent(e),i=r.length<1?config.symbols.closed:config.symbols.open;let s=`${o+(n?"":t?`└─${i} `:`├─${i} `)}${n&&config.symbols.open?`${i} ${node_path_1.default.basename(e)}`:node_path_1.default.basename(e)}\n`;const l=n?"":t?" ":"│ ",a=r.length-1;for(let n=0;n<r.length;n++){const t=r[n];if(t.isDirectory()&&(s+=await buildTree(node_path_1.default.join(e,t.name),o+l,!1,n===a)),t.isFile()){fileCount++;s+=`${o+l+(n===a?`└─${config.symbols.file} `:`├─${config.symbols.file} `)+t.name}\n`}}return folderCount++,s}async function configure(){let e;try{e=(0,node_util_1.parseArgs)({options:parseArgsOptionsConfig,allowPositionals:!0,strict:!0})}catch(e){const o=e;return console.error(`[${(0,node_util_1.styleText)("red",o.name)}]: ${o.message}`),(0,node_process_1.exit)(1)}const{values:o,positionals:n}=e;if(o.version)return await version(),(0,node_process_1.exit)(0);config.style=Style[o.style]??config.style,config.symbols=symbolStyles[config.style],config.root=node_path_1.default.resolve(n.length>0?n[0]:config.root),config.ignores=config.ignores.map(e=>node_path_1.default.join(config.root,e)),config.unsorted=Boolean(o.unsorted),config.verbose=Boolean(o.verbose),cliArgs={...o,root:n[0]??"n/a"}}async function version(){let e;const o=await getLatestVersion();o&&o!==package_json_1.version&&(e=(0,node_util_1.styleText)("yellow",`\n┌─────────────────────────────────────────────────────┐\n| A new version of Treefolder is available: |\n| current: ${package_json_1.version} -> latest: ${o} |\n| |\n| Install the latest version with: |\n| "npm update -g @khatastroffik/treefolder@latest" |\n└─────────────────────────────────────────────────────┘\n`)),console.info(colorText(`\n Treefolder aka "tfold"\n Version ${package_json_1.version}\n \n https://npmjs.com/@khatastroffik/treefolder\n${e??'\n ┌─────────────────────────────────────────────┐\n | |\n ╭━┳━╭━╭━╮╮\n ┃┈┈┈┣▄╋▄┫\n ┃┈┃┈╰━╰━━━━━━╮ "K11K"\n ╰┳╯┈┈┈┈┈┈┈┈ ◢█◣ a very pragmatic dog\n ┃┈┈┈┈┈┈┈┈┈┈████\n ┃┈┈┈┈┈┈┈┈┈┈◥█◤\n ┃┈┈┈┈╭━┳━━━━╯\n ┣━━━━━━┫\n | |\n └──────────── made by khatastroffik ──────────┘\n '}`))}async function verbose(){config.verbose&&(console.info(colorText("\nCommand line arguments:")),console.info(cliArgs),console.info(colorText("\nTreefolder configuration:")),console.info(config,"\n"),console.info(colorText(`Scanned ${colorText(folderCount)} folders and ${colorText(fileCount)} files.`)),console.info(colorText(`Filtered out ${colorText(ignoredCount)} items (folders or files).`)))}async function main(){await configure();const e=await buildTree(config.root,"",!0,!0);console.info(e),await verbose()}main();
2
+ "use strict";var E=Object.create;var $=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var S=Object.getPrototypeOf,K=Object.prototype.hasOwnProperty;var _=(e,t,n,l)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of O(t))!K.call(e,r)&&r!==n&&$(e,r,{get:()=>t[r],enumerable:!(l=M(t,r))||l.enumerable});return e};var u=(e,t,n)=>(n=e!=null?E(S(e)):{},_(t||!e||!e.__esModule?$(n,"default",{value:e,enumerable:!0}):n,e));var h=u(require("node:path"));var s=class{static folderCount=1;static fileCount=0;static ignoredCount=0;static commandLineArgs={}};var b=require("node:process"),f=require("node:util");var p="1.2.0";function a(e){return(0,f.styleText)(typeof e=="number"?"yellow":"blueBright",`${e}`)}async function R(){let e=await fetch("https://registry.npmjs.org/@khatastroffik/treefolder");return await new Promise(l=>setTimeout(l,100)),(await e.json())["dist-tags"].latest}async function P(){if(o.version){let e=`
3
+ \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
4
+ | |
5
+ \u256D\u2501\u2533\u2501\u256D\u2501\u256D\u2501\u256E\u256E
6
+ \u2503\u2508\u2508\u2508\u2523\u2584\u254B\u2584\u252B
7
+ \u2503\u2508\u2503\u2508\u2570\u2501\u2570\u2501\u2501\u2501\u2501\u2501\u2501\u256E "K11K"
8
+ \u2570\u2533\u256F\u2508\u2508\u2508\u2508\u2508\u2508\u2508\u2508 \u25E2\u2588\u25E3 a very pragmatic dog
9
+ \u2503\u2508\u2508\u2508\u2508\u2508\u2508\u2508\u2508\u2508\u2508\u2588\u2588\u2588\u2588
10
+ \u2503\u2508\u2508\u2508\u2508\u2508\u2508\u2508\u2508\u2508\u2508\u25E5\u2588\u25E4
11
+ \u2503\u2508\u2508\u2508\u2508\u256D\u2501\u2533\u2501\u2501\u2501\u2501\u256F
12
+ \u2523\u2501\u2501\u2501\u2501\u2501\u2501\u252B
13
+ | |
14
+ \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 made by khatastroffik \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
15
+ `,t,n=await R();return n&&n!==p&&(t=(0,f.styleText)("yellow",`
16
+ \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
17
+ | A new version of Treefolder is available: |
18
+ | current: ${p} -> latest: ${n} |
19
+ | |
20
+ | Install the latest version with: |
21
+ | "npm update -g @khatastroffik/treefolder@latest" |
22
+ \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
23
+ `)),console.info(a(`
24
+ Treefolder aka "tfold"
25
+ Version ${p}
26
+
27
+ https://npmjs.com/@khatastroffik/treefolder
28
+ ${t??e}`)),(0,b.exit)(0)}}async function j(){o.verbose&&(console.info(a(`
29
+ Command line arguments:`)),console.info(s.commandLineArgs),console.info(a(`
30
+ Treefolder configuration:`)),console.info(o,`
31
+ `),console.info(a(`Scanned ${a(s.folderCount)} folders and ${a(s.fileCount)} files.`)),console.info(a(`Filtered out ${a(s.ignoredCount)} items (folders or files).`)))}var W={style:{type:"string",default:"none",short:"s"},verbose:{type:"boolean",default:!1},unsorted:{type:"boolean",default:!1,short:"u"},version:{type:"boolean",default:!1,short:"v"},list:{type:"boolean",default:!1,short:"l"}};function C(){try{return(0,f.parseArgs)({options:W,allowPositionals:!0,strict:!0})}catch(e){let t=e;return console.error(`[${(0,f.styleText)("red",t.name)}]: ${t.message}`),(0,b.exit)(1)}}var i=" ",x=(r=>(r.none="none",r.wireframe="wireframe",r.black="black",r.colored="colored",r))(x||{}),I={none:{closed:"",open:"",file:""},wireframe:{closed:"\u{1F5C0} ",open:"\u{1F5C1} ",file:"\u{1F5CB}"},black:{closed:"\u{1F5BF} ",open:"\u{1F5BF} ",file:"\u{1F5CE}"},colored:{closed:"\u{1F4C1} ",open:"\u{1F4C2} ",file:"\u{1F4C4}"}},o={style:"none",symbols:I.none,root:".",ignores:["node_modules","dist","build",".git",".husky\\_","logs",".angular","coverage"],verbose:!1,unsorted:!1,formatAsList:!1,version:!1};async function T(){let{values:e,positionals:t}=C();o.version=e.version,o.formatAsList=e.list,o.style=x[e.style]??o.style,o.symbols=I[o.style],o.root=h.default.resolve(t.length>0?t[0]:o.root),o.ignores=o.ignores.map(n=>h.default.join(o.root,n)),o.unsorted=!!e.unsorted,o.verbose=!!e.verbose,s.commandLineArgs={...e,root:t[0]??"n/a"}}var L=u(require("node:fs")),c=u(require("node:path")),g=u(require("node:util"));var q=g.default.promisify(L.default.readdir),k,w;function G(e){return`${e.indent+e.folderPrefix+e.foldersymbol+c.default.basename(e.folderName)}
32
+ `}function J(e){return`${e.indent+e.contentItemPrefix+e.entityPrefix+e.contentItem.name}
33
+ `}function Q(e){let t=e.folderName+c.default.sep;return o.style==="colored"&&(t=(0,g.styleText)("blueBright",t)),`${t}
34
+ `}function U(e){return`${c.default.join(e.contentItem.parentPath,e.contentItem.name)}
35
+ `}function X(e,t){return e.isDirectory()?t.isFile()?-1:e.name.localeCompare(t.name):t.isDirectory()?1:e.name.localeCompare(t.name)}function Y(e,t){let n=o.ignores.includes(c.default.join(e,t));return n&&s.ignoredCount++,n}async function Z(e){let t=(await q(e,{withFileTypes:!0})).filter(n=>!Y(e,n.name));return o.unsorted?t:t.sort(X)}async function A(e,t,n,l){let r=await Z(e),V=r.length<1?o.symbols.closed:o.symbols.open,N=n?"":(l?"\u2514\u2500":"\u251C\u2500")+(o.symbols.open?"":i),y=k({indent:t,folderPrefix:N,foldersymbol:V,folderName:e}),v=n?"":l?`${i}${i}${i}`:`\u2502${i}${i}`,F=r.length-1;for(let m=0;m<r.length;m++){let d=r[m];if(d.isDirectory()&&(y+=await A(c.default.join(e,d.name),t+v,!1,m===F)),d.isFile()){s.fileCount++;let B=m===F?`\u2514\u2500${o.symbols.file}${i}`:`\u251C\u2500${o.symbols.file}${i}`;y+=w({indent:t,contentItemPrefix:v,entityPrefix:B,contentItem:d})}}return s.folderCount++,y}async function D(){k=G,w=J,o.formatAsList&&(k=Q,w=U);let e=await A(o.root,"",!0,!0);console.info(e)}async function H(){await T(),await P(),await D(),await j()}H();
36
+ /*!
37
+ * @khatastroffik/treefolder
38
+ *
39
+ * License: MIT
40
+ * Copyright (c) 2026, Loïs Bégué
41
+ *
42
+ */
package/docs/readme.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Additional documentation
2
2
 
3
+ ## Table of Content
4
+
5
+ - [Styled output examples](#styled-output-examples)
6
+ - [List output examples](#list-output-examples)
7
+ - [Sources &amp; stories](#sources--stories)
8
+
3
9
  ## Styled output examples
4
10
 
5
11
  ### "none" Style &rarr; `--style=none`
@@ -96,6 +102,72 @@ treefolder
96
102
  └─🗋 tsconfig.json
97
103
  ```
98
104
 
105
+ ## List output examples
106
+
107
+ ### Simple list output &rarr; `--list`
108
+
109
+ This is the **default** format of the list output: it displays the full path of the items and all items are sorted using the _"folder first" principle_.
110
+
111
+ ```shell
112
+ C:\development\treefolder\
113
+ C:\development\treefolder\.husky\
114
+ C:\development\treefolder\.husky\pre-commit
115
+ C:\development\treefolder\.vscode\
116
+ C:\development\treefolder\.vscode\settings.json
117
+ C:\development\treefolder\docs\
118
+ C:\development\treefolder\docs\commit-messages-guideline.md
119
+ C:\development\treefolder\docs\readme.md
120
+ C:\development\treefolder\docs\tfold.jpg
121
+ C:\development\treefolder\src\
122
+ C:\development\treefolder\src\index.ts
123
+ C:\development\treefolder\.gitattributes
124
+ C:\development\treefolder\.gitignore
125
+ C:\development\treefolder\CHANGELOG.md
126
+ C:\development\treefolder\eslint.config.mjs
127
+ C:\development\treefolder\jest.config.js
128
+ C:\development\treefolder\LICENSE
129
+ C:\development\treefolder\package.json
130
+ C:\development\treefolder\pnpm-lock.yaml
131
+ C:\development\treefolder\pnpm-workspace.yaml
132
+ C:\development\treefolder\README.md
133
+ C:\development\treefolder\tsconfig.json
134
+ ```
135
+
136
+ ### Unsorted list output &rarr; `--list --unsorted`
137
+
138
+ In this use case, the list items are sorted the way the operating system does by default e.g. sorted by their names, regardless of their type (directory or file).
139
+
140
+ ```shell
141
+ C:\development\treefolder\
142
+ C:\development\treefolder\.gitattributes
143
+ C:\development\treefolder\.gitignore
144
+ C:\development\treefolder\.husky\
145
+ C:\development\treefolder\.husky\pre-commit
146
+ C:\development\treefolder\.vscode\
147
+ C:\development\treefolder\.vscode\settings.json
148
+ C:\development\treefolder\CHANGELOG.md
149
+ C:\development\treefolder\docs\
150
+ C:\development\treefolder\docs\commit-messages-guideline.md
151
+ C:\development\treefolder\docs\readme.md
152
+ C:\development\treefolder\docs\tfold.jpg
153
+ C:\development\treefolder\eslint.config.mjs
154
+ C:\development\treefolder\jest.config.js
155
+ C:\development\treefolder\LICENSE
156
+ C:\development\treefolder\package.json
157
+ C:\development\treefolder\pnpm-lock.yaml
158
+ C:\development\treefolder\pnpm-workspace.yaml
159
+ C:\development\treefolder\README.md
160
+ C:\development\treefolder\src\
161
+ C:\development\treefolder\src\index.ts
162
+ C:\development\treefolder\tsconfig.json
163
+ ```
164
+
165
+ ### Colored list output &rarr; `--list --style colored`
166
+
167
+ In this use case, the list output highlights i.e. colors the _directoy_ items in _bright blue_.
168
+
169
+ There's no _preview_ of such a generated output at the moment, though.
170
+
99
171
  ## Sources &amp; stories
100
172
 
101
173
  ### From trees and leaves
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khatastroffik/treefolder",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "devEngines": {
5
5
  "packageManager": [
6
6
  {
@@ -55,6 +55,7 @@
55
55
  "@eslint/markdown": "^7.5.1",
56
56
  "@types/jest": "^30.0.0",
57
57
  "@types/node": "^25.0.3",
58
+ "esbuild": "^0.27.2",
58
59
  "eslint": "^9.39.2",
59
60
  "eslint-plugin-format": "^1.1.0",
60
61
  "eslint-plugin-jest": "^29.12.1",
@@ -63,7 +64,6 @@
63
64
  "jest": "^30.2.0",
64
65
  "lint-staged": "^16.2.7",
65
66
  "rimraf": "^6.1.2",
66
- "terser": "^5.46.0",
67
67
  "ts-jest": "^29.4.6",
68
68
  "tsx": "^4.21.0",
69
69
  "typescript": "^5.9.3",
@@ -72,15 +72,35 @@
72
72
  "lint-staged": {
73
73
  "*.ts": "pnpm lintix"
74
74
  },
75
+ "commit-and-tag-version": {
76
+ "types": [
77
+ {
78
+ "type": "refactor",
79
+ "section": "Refactors",
80
+ "hidden": false
81
+ },
82
+ {
83
+ "type": "docs",
84
+ "section": "Documentation",
85
+ "hidden": false
86
+ },
87
+ {
88
+ "type": "build",
89
+ "section": "Build System / Dependencies",
90
+ "hidden": false
91
+ }
92
+ ]
93
+ },
75
94
  "scripts": {
76
95
  "test": "jest --passWithNoTests",
77
96
  "lint": "eslint .",
78
97
  "lintix": "eslint . --fix",
79
98
  "clean": "rimraf ./dist",
80
- "dev": "tsx watch src/index.ts",
99
+ "dev": "tsx watch --include \"src/**/*\" src/index.ts",
81
100
  "typecheck": "tsc --noEmit",
82
- "build": "pnpm clean && tsc",
83
- "build2prod": "pnpm build && terser dist/index.js -o dist/index.js -c -m",
101
+ "build": "pnpm clean && esbuild --bundle --minify --platform=node --outdir=dist ./src/index.ts",
102
+ "buildwatch": "pnpm build --watch --watch-delay=500",
103
+ "build2prod": "pnpm build --tree-shaking=true --analyze",
84
104
  "start": "node .",
85
105
  "pushtags": "git push --follow-tags origin main",
86
106
  "try-commit": "git hook run pre-commit",