@bryanchu10/create-template-ts 1.0.0 → 1.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Bryan Chu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,49 @@
1
+ [English](./README.md) · [繁體中文](./README.zh-TW.md)
2
+
3
+ # create-template-ts
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@bryanchu10/create-template-ts)](https://www.npmjs.com/package/@bryanchu10/create-template-ts)
6
+ [![npm downloads](https://img.shields.io/npm/dm/@bryanchu10/create-template-ts)](https://www.npmjs.com/package/@bryanchu10/create-template-ts)
7
+ [![license](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)
8
+ [![node](https://img.shields.io/badge/node-%3E%3D22-brightgreen?logo=node.js&logoColor=white)](https://nodejs.org)
9
+ [![pnpm](https://img.shields.io/badge/pnpm-%3E%3D9-F69220?logo=pnpm&logoColor=white)](https://pnpm.io)
10
+
11
+ Scaffold a modular TypeScript project for scripts and tooling.
12
+
13
+ ## Usage
14
+
15
+ **pnpm**
16
+ ```bash
17
+ pnpm create @bryanchu10/template-ts
18
+ ```
19
+
20
+ **npm**
21
+ ```bash
22
+ npx @bryanchu10/create-template-ts
23
+ ```
24
+
25
+ Follow the prompts to choose a project name and template. The CLI will fetch the latest package versions automatically.
26
+
27
+ ## Templates
28
+
29
+ | Template | Description |
30
+ |----------|-------------|
31
+ | `ts-script` | TypeScript script/tooling with neverthrow, ts-pattern, eslint, tsx, and rolldown |
32
+
33
+ ## Development
34
+
35
+ ```bash
36
+ pnpm install
37
+ pnpm dev # watch mode
38
+ pnpm build # bundle with rolldown
39
+ pnpm check # type check
40
+ pnpm lint # eslint
41
+ ```
42
+
43
+ ## Changelog
44
+
45
+ See [CHANGELOG.md](./CHANGELOG.md) for release history.
46
+
47
+ ## License
48
+
49
+ [MIT](./LICENSE) © Bryan Chu
@@ -0,0 +1,49 @@
1
+ [English](./README.md) · [繁體中文](./README.zh-TW.md)
2
+
3
+ # create-template-ts
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@bryanchu10/create-template-ts)](https://www.npmjs.com/package/@bryanchu10/create-template-ts)
6
+ [![npm downloads](https://img.shields.io/npm/dm/@bryanchu10/create-template-ts)](https://www.npmjs.com/package/@bryanchu10/create-template-ts)
7
+ [![license](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)
8
+ [![node](https://img.shields.io/badge/node-%3E%3D22-brightgreen?logo=node.js&logoColor=white)](https://nodejs.org)
9
+ [![pnpm](https://img.shields.io/badge/pnpm-%3E%3D9-F69220?logo=pnpm&logoColor=white)](https://pnpm.io)
10
+
11
+ 快速建立模組化的 TypeScript 專案,適合腳本與工具開發。
12
+
13
+ ## 使用方式
14
+
15
+ **pnpm**
16
+ ```bash
17
+ pnpm create @bryanchu10/template-ts
18
+ ```
19
+
20
+ **npm**
21
+ ```bash
22
+ npx @bryanchu10/create-template-ts
23
+ ```
24
+
25
+ 依照提示選擇專案名稱與範本,CLI 會自動抓取最新的套件版本。
26
+
27
+ ## 範本
28
+
29
+ | 範本 | 說明 |
30
+ |------|------|
31
+ | `ts-script` | TypeScript 腳本/工具專案,內含 neverthrow、ts-pattern、eslint、tsx、rolldown |
32
+
33
+ ## 開發
34
+
35
+ ```bash
36
+ pnpm install
37
+ pnpm dev # 監聽模式
38
+ pnpm build # 用 rolldown 打包
39
+ pnpm check # 型別檢查
40
+ pnpm lint # eslint
41
+ ```
42
+
43
+ ## 更新紀錄
44
+
45
+ 請見 [CHANGELOG.md](./CHANGELOG.md)。
46
+
47
+ ## 授權
48
+
49
+ [MIT](./LICENSE) © Bryan Chu
package/dist/index.js CHANGED
@@ -452,6 +452,17 @@ function R$2({ input: r = stdin, output: t = stdout, overwrite: s = !0, hideCurs
452
452
  };
453
453
  }
454
454
  const A$1 = (r) => "columns" in r && typeof r.columns == "number" ? r.columns : 80, L$1 = (r) => "rows" in r && typeof r.rows == "number" ? r.rows : 20;
455
+ function W(r, t, s, e = s, i = s, n) {
456
+ return wrapAnsi(t, A$1(r ?? stdout) - s.length, {
457
+ hard: !0,
458
+ trim: !1
459
+ }).split(`
460
+ `).map((u, a, l) => {
461
+ const c = n ? n(u, a) : u;
462
+ return a === 0 ? `${e}${c}` : a === l.length - 1 ? `${i}${c}` : `${s}${c}`;
463
+ }).join(`
464
+ `);
465
+ }
455
466
  let m$1 = class {
456
467
  input;
457
468
  output;
@@ -602,6 +613,33 @@ let m$1 = class {
602
613
  }
603
614
  }
604
615
  };
616
+ var ut$1 = class extends m$1 {
617
+ options;
618
+ cursor = 0;
619
+ get _selectedValue() {
620
+ return this.options[this.cursor];
621
+ }
622
+ changeValue() {
623
+ this.value = this._selectedValue.value;
624
+ }
625
+ constructor(t) {
626
+ super(t, !1), this.options = t.options;
627
+ const s = this.options.findIndex(({ value: i }) => i === t.initialValue), e = s === -1 ? 0 : s;
628
+ this.cursor = this.options[e].disabled ? f$1(e, 1, this.options) : e, this.changeValue(), this.on("cursor", (i) => {
629
+ switch (i) {
630
+ case "left":
631
+ case "up":
632
+ this.cursor = f$1(this.cursor, -1, this.options);
633
+ break;
634
+ case "down":
635
+ case "right":
636
+ this.cursor = f$1(this.cursor, 1, this.options);
637
+ break;
638
+ }
639
+ this.changeValue();
640
+ });
641
+ }
642
+ };
605
643
  var ht$1 = class extends m$1 {
606
644
  get userInputWithCursor() {
607
645
  if (this.state === "submit") return this.userInput;
@@ -629,7 +667,7 @@ var ht$1 = class extends m$1 {
629
667
  function ee() {
630
668
  return V.platform !== "win32" ? V.env.TERM !== "linux" : !!V.env.CI || !!V.env.WT_SESSION || !!V.env.TERMINUS_SUBLIME || V.env.ConEmuTask === "{cmd::Cmder}" || V.env.TERM_PROGRAM === "Terminus-Sublime" || V.env.TERM_PROGRAM === "vscode" || V.env.TERM === "xterm-256color" || V.env.TERM === "alacritty" || V.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
631
669
  }
632
- const tt = ee(), ot = () => process.env.CI === "true", w$1 = (t, i) => tt ? t : i, Tt = w$1("◆", "*"), at = w$1("■", "x"), ut = w$1("▲", "x"), H = w$1("◇", "o"), lt = w$1("┌", "T"), $ = w$1("│", "|"), x$1 = w$1("└", "—"), ht = w$1("●", "•"), pt = w$1("◆", "*"), mt = w$1("▲", "!"), gt = w$1("■", "x"), P$1 = (t) => {
670
+ const tt = ee(), ot = () => process.env.CI === "true", w$1 = (t, i) => tt ? t : i, Tt = w$1("◆", "*"), at = w$1("■", "x"), ut = w$1("▲", "x"), H = w$1("◇", "o"), lt = w$1("┌", "T"), $ = w$1("│", "|"), x$1 = w$1("└", "—"), z$1 = w$1("●", ">"), U = w$1("○", " "), ht = w$1("●", "•"), pt = w$1("◆", "*"), mt = w$1("▲", "!"), gt = w$1("■", "x"), P$1 = (t) => {
633
671
  switch (t) {
634
672
  case "initial":
635
673
  case "active": return styleText("cyan", Tt);
@@ -637,6 +675,50 @@ const tt = ee(), ot = () => process.env.CI === "true", w$1 = (t, i) => tt ? t :
637
675
  case "error": return styleText("yellow", ut);
638
676
  case "submit": return styleText("green", H);
639
677
  }
678
+ }, yt = (t) => {
679
+ switch (t) {
680
+ case "initial":
681
+ case "active": return styleText("cyan", $);
682
+ case "cancel": return styleText("red", $);
683
+ case "error": return styleText("yellow", $);
684
+ case "submit": return styleText("green", $);
685
+ }
686
+ }, Ot = (t, i, s, r, u, n = !1) => {
687
+ let a = i, c = 0;
688
+ if (n) for (let o = r - 1; o >= s && (a -= t[o].length, c++, !(a <= u)); o--);
689
+ else for (let o = s; o < r && (a -= t[o].length, c++, !(a <= u)); o++);
690
+ return {
691
+ lineCount: a,
692
+ removals: c
693
+ };
694
+ }, F$1 = ({ cursor: t, options: i, style: s, output: r = process.stdout, maxItems: u = Number.POSITIVE_INFINITY, columnPadding: n = 0, rowPadding: a = 4 }) => {
695
+ const c = A$1(r) - n, o = L$1(r), l = styleText("dim", "..."), d = Math.max(o - a, 0), g = Math.max(Math.min(u, d), 5);
696
+ let p = 0;
697
+ t >= g - 3 && (p = Math.max(Math.min(t - g + 3, i.length - g), 0));
698
+ let f = g < i.length && p > 0, h = g < i.length && p + g < i.length;
699
+ const I = Math.min(p + g, i.length), m = [];
700
+ let y = 0;
701
+ f && y++, h && y++;
702
+ const v = p + (f ? 1 : 0), C = I - (h ? 1 : 0);
703
+ for (let b = v; b < C; b++) {
704
+ const G = wrapAnsi(s(i[b], b === t), c, {
705
+ hard: !0,
706
+ trim: !1
707
+ }).split(`
708
+ `);
709
+ m.push(G), y += G.length;
710
+ }
711
+ if (y > d) {
712
+ let b = 0, G = 0, M = y;
713
+ const N = t - v;
714
+ let O = d;
715
+ const j = () => Ot(m, M, 0, N, O), k = () => Ot(m, M, N + 1, m.length, O, !0);
716
+ f ? ({lineCount: M, removals: b} = j(), M > O && (h || (O -= 1), {lineCount: M, removals: G} = k())) : (h || (O -= 1), {lineCount: M, removals: G} = k(), M > O && (O -= 1, {lineCount: M, removals: b} = j())), b > 0 && (f = !0, m.splice(0, b)), G > 0 && (h = !0, m.splice(m.length - G, G));
717
+ }
718
+ const S = [];
719
+ f && S.push(l);
720
+ for (const b of m) for (const G of b) S.push(G);
721
+ return h && S.push(l), S;
640
722
  };
641
723
  const R$1 = {
642
724
  message: (t = [], { symbol: i = styleText("gray", $), secondarySymbol: s = styleText("gray", $), output: r = process.stdout, spacing: u = 1, withGuide: n } = {}) => {
@@ -776,6 +858,59 @@ ${styleText("gray", x$1)} ` : "";
776
858
  return f;
777
859
  }
778
860
  };
861
+ }, it = (t, i) => t.includes(`
862
+ `) ? t.split(`
863
+ `).map((s) => i(s)).join(`
864
+ `) : i(t), xe = (t) => {
865
+ const i = (s, r) => {
866
+ const u = s.label ?? String(s.value);
867
+ switch (r) {
868
+ case "disabled": return `${styleText("gray", U)} ${it(u, (n) => styleText("gray", n))}${s.hint ? ` ${styleText("dim", `(${s.hint ?? "disabled"})`)}` : ""}`;
869
+ case "selected": return `${it(u, (n) => styleText("dim", n))}`;
870
+ case "active": return `${styleText("green", z$1)} ${u}${s.hint ? ` ${styleText("dim", `(${s.hint})`)}` : ""}`;
871
+ case "cancelled": return `${it(u, (n) => styleText(["strikethrough", "dim"], n))}`;
872
+ default: return `${styleText("dim", U)} ${it(u, (n) => styleText("dim", n))}`;
873
+ }
874
+ };
875
+ return new ut$1({
876
+ options: t.options,
877
+ signal: t.signal,
878
+ input: t.input,
879
+ output: t.output,
880
+ initialValue: t.initialValue,
881
+ render() {
882
+ const s = t.withGuide ?? h$1.withGuide, r = `${P$1(this.state)} `, u = `${yt(this.state)} `, n = W(t.output, t.message, u, r), a = `${s ? `${styleText("gray", $)}
883
+ ` : ""}${n}
884
+ `;
885
+ switch (this.state) {
886
+ case "submit": {
887
+ const c = s ? `${styleText("gray", $)} ` : "";
888
+ return `${a}${W(t.output, i(this.options[this.cursor], "selected"), c)}`;
889
+ }
890
+ case "cancel": {
891
+ const c = s ? `${styleText("gray", $)} ` : "";
892
+ return `${a}${W(t.output, i(this.options[this.cursor], "cancelled"), c)}${s ? `
893
+ ${styleText("gray", $)}` : ""}`;
894
+ }
895
+ default: {
896
+ const c = s ? `${styleText("cyan", $)} ` : "", o = s ? styleText("cyan", x$1) : "", l = a.split(`
897
+ `).length, d = s ? 2 : 1;
898
+ return `${a}${c}${F$1({
899
+ output: t.output,
900
+ cursor: this.cursor,
901
+ options: this.options,
902
+ maxItems: t.maxItems,
903
+ columnPadding: c.length,
904
+ rowPadding: l + d,
905
+ style: (g, p) => i(g, g.disabled ? "disabled" : p ? "active" : "inactive")
906
+ }).join(`
907
+ ${c}`)}
908
+ ${o}
909
+ `;
910
+ }
911
+ }
912
+ }
913
+ }).prompt();
779
914
  }, Nt = `${styleText("gray", $)} `, q = {
780
915
  message: async (t, { symbol: i = styleText("gray", $) } = {}) => {
781
916
  process.stdout.write(`${styleText("gray", $)}
@@ -835,26 +970,516 @@ ${i ? styleText("cyan", x$1) : ""}
835
970
  }
836
971
  }).prompt();
837
972
  //#endregion
838
- //#region src/constants/deps.ts
839
- const DEPS = ["ts-pattern"];
840
- const DEV_DEPS = [
841
- "@antfu/eslint-config",
842
- "eslint",
843
- "rolldown",
844
- "tsx",
845
- "typescript"
846
- ];
973
+ //#region node_modules/.pnpm/neverthrow@8.2.0/node_modules/neverthrow/dist/index.cjs.js
974
+ var require_index_cjs = /* @__PURE__ */ __commonJSMin(((exports) => {
975
+ const defaultErrorConfig = { withStackTrace: false };
976
+ const createNeverThrowError = (message, result, config = defaultErrorConfig) => {
977
+ return {
978
+ data: result.isOk() ? {
979
+ type: "Ok",
980
+ value: result.value
981
+ } : {
982
+ type: "Err",
983
+ value: result.error
984
+ },
985
+ message,
986
+ stack: config.withStackTrace ? (/* @__PURE__ */ new Error()).stack : void 0
987
+ };
988
+ };
989
+ /******************************************************************************
990
+ Copyright (c) Microsoft Corporation.
991
+
992
+ Permission to use, copy, modify, and/or distribute this software for any
993
+ purpose with or without fee is hereby granted.
994
+
995
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
996
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
997
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
998
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
999
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1000
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1001
+ PERFORMANCE OF THIS SOFTWARE.
1002
+ ***************************************************************************** */
1003
+ function __awaiter(thisArg, _arguments, P, generator) {
1004
+ function adopt(value) {
1005
+ return value instanceof P ? value : new P(function(resolve) {
1006
+ resolve(value);
1007
+ });
1008
+ }
1009
+ return new (P || (P = Promise))(function(resolve, reject) {
1010
+ function fulfilled(value) {
1011
+ try {
1012
+ step(generator.next(value));
1013
+ } catch (e) {
1014
+ reject(e);
1015
+ }
1016
+ }
1017
+ function rejected(value) {
1018
+ try {
1019
+ step(generator["throw"](value));
1020
+ } catch (e) {
1021
+ reject(e);
1022
+ }
1023
+ }
1024
+ function step(result) {
1025
+ result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
1026
+ }
1027
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
1028
+ });
1029
+ }
1030
+ function __values(o) {
1031
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
1032
+ if (m) return m.call(o);
1033
+ if (o && typeof o.length === "number") return { next: function() {
1034
+ if (o && i >= o.length) o = void 0;
1035
+ return {
1036
+ value: o && o[i++],
1037
+ done: !o
1038
+ };
1039
+ } };
1040
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
1041
+ }
1042
+ function __await(v) {
1043
+ return this instanceof __await ? (this.v = v, this) : new __await(v);
1044
+ }
1045
+ function __asyncGenerator(thisArg, _arguments, generator) {
1046
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
1047
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
1048
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function() {
1049
+ return this;
1050
+ }, i;
1051
+ function awaitReturn(f) {
1052
+ return function(v) {
1053
+ return Promise.resolve(v).then(f, reject);
1054
+ };
1055
+ }
1056
+ function verb(n, f) {
1057
+ if (g[n]) {
1058
+ i[n] = function(v) {
1059
+ return new Promise(function(a, b) {
1060
+ q.push([
1061
+ n,
1062
+ v,
1063
+ a,
1064
+ b
1065
+ ]) > 1 || resume(n, v);
1066
+ });
1067
+ };
1068
+ if (f) i[n] = f(i[n]);
1069
+ }
1070
+ }
1071
+ function resume(n, v) {
1072
+ try {
1073
+ step(g[n](v));
1074
+ } catch (e) {
1075
+ settle(q[0][3], e);
1076
+ }
1077
+ }
1078
+ function step(r) {
1079
+ r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r);
1080
+ }
1081
+ function fulfill(value) {
1082
+ resume("next", value);
1083
+ }
1084
+ function reject(value) {
1085
+ resume("throw", value);
1086
+ }
1087
+ function settle(f, v) {
1088
+ if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]);
1089
+ }
1090
+ }
1091
+ function __asyncDelegator(o) {
1092
+ var i, p;
1093
+ return i = {}, verb("next"), verb("throw", function(e) {
1094
+ throw e;
1095
+ }), verb("return"), i[Symbol.iterator] = function() {
1096
+ return this;
1097
+ }, i;
1098
+ function verb(n, f) {
1099
+ i[n] = o[n] ? function(v) {
1100
+ return (p = !p) ? {
1101
+ value: __await(o[n](v)),
1102
+ done: false
1103
+ } : f ? f(v) : v;
1104
+ } : f;
1105
+ }
1106
+ }
1107
+ function __asyncValues(o) {
1108
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
1109
+ var m = o[Symbol.asyncIterator], i;
1110
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function() {
1111
+ return this;
1112
+ }, i);
1113
+ function verb(n) {
1114
+ i[n] = o[n] && function(v) {
1115
+ return new Promise(function(resolve, reject) {
1116
+ v = o[n](v), settle(resolve, reject, v.done, v.value);
1117
+ });
1118
+ };
1119
+ }
1120
+ function settle(resolve, reject, d, v) {
1121
+ Promise.resolve(v).then(function(v) {
1122
+ resolve({
1123
+ value: v,
1124
+ done: d
1125
+ });
1126
+ }, reject);
1127
+ }
1128
+ }
1129
+ var ResultAsync = class ResultAsync {
1130
+ constructor(res) {
1131
+ this._promise = res;
1132
+ }
1133
+ static fromSafePromise(promise) {
1134
+ return new ResultAsync(promise.then((value) => new Ok(value)));
1135
+ }
1136
+ static fromPromise(promise, errorFn) {
1137
+ return new ResultAsync(promise.then((value) => new Ok(value)).catch((e) => new Err(errorFn(e))));
1138
+ }
1139
+ static fromThrowable(fn, errorFn) {
1140
+ return (...args) => {
1141
+ return new ResultAsync((() => __awaiter(this, void 0, void 0, function* () {
1142
+ try {
1143
+ return new Ok(yield fn(...args));
1144
+ } catch (error) {
1145
+ return new Err(errorFn ? errorFn(error) : error);
1146
+ }
1147
+ }))());
1148
+ };
1149
+ }
1150
+ static combine(asyncResultList) {
1151
+ return combineResultAsyncList(asyncResultList);
1152
+ }
1153
+ static combineWithAllErrors(asyncResultList) {
1154
+ return combineResultAsyncListWithAllErrors(asyncResultList);
1155
+ }
1156
+ map(f) {
1157
+ return new ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
1158
+ if (res.isErr()) return new Err(res.error);
1159
+ return new Ok(yield f(res.value));
1160
+ })));
1161
+ }
1162
+ andThrough(f) {
1163
+ return new ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
1164
+ if (res.isErr()) return new Err(res.error);
1165
+ const newRes = yield f(res.value);
1166
+ if (newRes.isErr()) return new Err(newRes.error);
1167
+ return new Ok(res.value);
1168
+ })));
1169
+ }
1170
+ andTee(f) {
1171
+ return new ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
1172
+ if (res.isErr()) return new Err(res.error);
1173
+ try {
1174
+ yield f(res.value);
1175
+ } catch (e) {}
1176
+ return new Ok(res.value);
1177
+ })));
1178
+ }
1179
+ orTee(f) {
1180
+ return new ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
1181
+ if (res.isOk()) return new Ok(res.value);
1182
+ try {
1183
+ yield f(res.error);
1184
+ } catch (e) {}
1185
+ return new Err(res.error);
1186
+ })));
1187
+ }
1188
+ mapErr(f) {
1189
+ return new ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
1190
+ if (res.isOk()) return new Ok(res.value);
1191
+ return new Err(yield f(res.error));
1192
+ })));
1193
+ }
1194
+ andThen(f) {
1195
+ return new ResultAsync(this._promise.then((res) => {
1196
+ if (res.isErr()) return new Err(res.error);
1197
+ const newValue = f(res.value);
1198
+ return newValue instanceof ResultAsync ? newValue._promise : newValue;
1199
+ }));
1200
+ }
1201
+ orElse(f) {
1202
+ return new ResultAsync(this._promise.then((res) => __awaiter(this, void 0, void 0, function* () {
1203
+ if (res.isErr()) return f(res.error);
1204
+ return new Ok(res.value);
1205
+ })));
1206
+ }
1207
+ match(ok, _err) {
1208
+ return this._promise.then((res) => res.match(ok, _err));
1209
+ }
1210
+ unwrapOr(t) {
1211
+ return this._promise.then((res) => res.unwrapOr(t));
1212
+ }
1213
+ /**
1214
+ * @deprecated will be removed in 9.0.0.
1215
+ *
1216
+ * You can use `safeTry` without this method.
1217
+ * @example
1218
+ * ```typescript
1219
+ * safeTry(async function* () {
1220
+ * const okValue = yield* yourResult
1221
+ * })
1222
+ * ```
1223
+ * Emulates Rust's `?` operator in `safeTry`'s body. See also `safeTry`.
1224
+ */
1225
+ safeUnwrap() {
1226
+ return __asyncGenerator(this, arguments, function* safeUnwrap_1() {
1227
+ return yield __await(yield __await(yield* __asyncDelegator(__asyncValues(yield __await(this._promise.then((res) => res.safeUnwrap()))))));
1228
+ });
1229
+ }
1230
+ then(successCallback, failureCallback) {
1231
+ return this._promise.then(successCallback, failureCallback);
1232
+ }
1233
+ [Symbol.asyncIterator]() {
1234
+ return __asyncGenerator(this, arguments, function* _a() {
1235
+ const result = yield __await(this._promise);
1236
+ if (result.isErr()) yield yield __await(errAsync(result.error));
1237
+ return yield __await(result.value);
1238
+ });
1239
+ }
1240
+ };
1241
+ function okAsync(value) {
1242
+ return new ResultAsync(Promise.resolve(new Ok(value)));
1243
+ }
1244
+ function errAsync(err) {
1245
+ return new ResultAsync(Promise.resolve(new Err(err)));
1246
+ }
1247
+ const fromPromise = ResultAsync.fromPromise;
1248
+ const fromSafePromise = ResultAsync.fromSafePromise;
1249
+ const fromAsyncThrowable = ResultAsync.fromThrowable;
1250
+ /**
1251
+ * Short circuits on the FIRST Err value that we find
1252
+ */
1253
+ const combineResultList = (resultList) => {
1254
+ let acc = ok([]);
1255
+ for (const result of resultList) if (result.isErr()) {
1256
+ acc = err(result.error);
1257
+ break;
1258
+ } else acc.map((list) => list.push(result.value));
1259
+ return acc;
1260
+ };
1261
+ const combineResultAsyncList = (asyncResultList) => ResultAsync.fromSafePromise(Promise.all(asyncResultList)).andThen(combineResultList);
1262
+ /**
1263
+ * Give a list of all the errors we find
1264
+ */
1265
+ const combineResultListWithAllErrors = (resultList) => {
1266
+ let acc = ok([]);
1267
+ for (const result of resultList) if (result.isErr() && acc.isErr()) acc.error.push(result.error);
1268
+ else if (result.isErr() && acc.isOk()) acc = err([result.error]);
1269
+ else if (result.isOk() && acc.isOk()) acc.value.push(result.value);
1270
+ return acc;
1271
+ };
1272
+ const combineResultAsyncListWithAllErrors = (asyncResultList) => ResultAsync.fromSafePromise(Promise.all(asyncResultList)).andThen(combineResultListWithAllErrors);
1273
+ exports.Result = void 0;
1274
+ (function(Result) {
1275
+ /**
1276
+ * Wraps a function with a try catch, creating a new function with the same
1277
+ * arguments but returning `Ok` if successful, `Err` if the function throws
1278
+ *
1279
+ * @param fn function to wrap with ok on success or err on failure
1280
+ * @param errorFn when an error is thrown, this will wrap the error result if provided
1281
+ */
1282
+ function fromThrowable(fn, errorFn) {
1283
+ return (...args) => {
1284
+ try {
1285
+ return ok(fn(...args));
1286
+ } catch (e) {
1287
+ return err(errorFn ? errorFn(e) : e);
1288
+ }
1289
+ };
1290
+ }
1291
+ Result.fromThrowable = fromThrowable;
1292
+ function combine(resultList) {
1293
+ return combineResultList(resultList);
1294
+ }
1295
+ Result.combine = combine;
1296
+ function combineWithAllErrors(resultList) {
1297
+ return combineResultListWithAllErrors(resultList);
1298
+ }
1299
+ Result.combineWithAllErrors = combineWithAllErrors;
1300
+ })(exports.Result || (exports.Result = {}));
1301
+ function ok(value) {
1302
+ return new Ok(value);
1303
+ }
1304
+ function err(err) {
1305
+ return new Err(err);
1306
+ }
1307
+ function safeTry(body) {
1308
+ const n = body().next();
1309
+ if (n instanceof Promise) return new ResultAsync(n.then((r) => r.value));
1310
+ return n.value;
1311
+ }
1312
+ var Ok = class {
1313
+ constructor(value) {
1314
+ this.value = value;
1315
+ }
1316
+ isOk() {
1317
+ return true;
1318
+ }
1319
+ isErr() {
1320
+ return !this.isOk();
1321
+ }
1322
+ map(f) {
1323
+ return ok(f(this.value));
1324
+ }
1325
+ mapErr(_f) {
1326
+ return ok(this.value);
1327
+ }
1328
+ andThen(f) {
1329
+ return f(this.value);
1330
+ }
1331
+ andThrough(f) {
1332
+ return f(this.value).map((_value) => this.value);
1333
+ }
1334
+ andTee(f) {
1335
+ try {
1336
+ f(this.value);
1337
+ } catch (e) {}
1338
+ return ok(this.value);
1339
+ }
1340
+ orTee(_f) {
1341
+ return ok(this.value);
1342
+ }
1343
+ orElse(_f) {
1344
+ return ok(this.value);
1345
+ }
1346
+ asyncAndThen(f) {
1347
+ return f(this.value);
1348
+ }
1349
+ asyncAndThrough(f) {
1350
+ return f(this.value).map(() => this.value);
1351
+ }
1352
+ asyncMap(f) {
1353
+ return ResultAsync.fromSafePromise(f(this.value));
1354
+ }
1355
+ unwrapOr(_v) {
1356
+ return this.value;
1357
+ }
1358
+ match(ok, _err) {
1359
+ return ok(this.value);
1360
+ }
1361
+ safeUnwrap() {
1362
+ const value = this.value;
1363
+ return (function* () {
1364
+ return value;
1365
+ })();
1366
+ }
1367
+ _unsafeUnwrap(_) {
1368
+ return this.value;
1369
+ }
1370
+ _unsafeUnwrapErr(config) {
1371
+ throw createNeverThrowError("Called `_unsafeUnwrapErr` on an Ok", this, config);
1372
+ }
1373
+ *[Symbol.iterator]() {
1374
+ return this.value;
1375
+ }
1376
+ };
1377
+ var Err = class {
1378
+ constructor(error) {
1379
+ this.error = error;
1380
+ }
1381
+ isOk() {
1382
+ return false;
1383
+ }
1384
+ isErr() {
1385
+ return !this.isOk();
1386
+ }
1387
+ map(_f) {
1388
+ return err(this.error);
1389
+ }
1390
+ mapErr(f) {
1391
+ return err(f(this.error));
1392
+ }
1393
+ andThrough(_f) {
1394
+ return err(this.error);
1395
+ }
1396
+ andTee(_f) {
1397
+ return err(this.error);
1398
+ }
1399
+ orTee(f) {
1400
+ try {
1401
+ f(this.error);
1402
+ } catch (e) {}
1403
+ return err(this.error);
1404
+ }
1405
+ andThen(_f) {
1406
+ return err(this.error);
1407
+ }
1408
+ orElse(f) {
1409
+ return f(this.error);
1410
+ }
1411
+ asyncAndThen(_f) {
1412
+ return errAsync(this.error);
1413
+ }
1414
+ asyncAndThrough(_f) {
1415
+ return errAsync(this.error);
1416
+ }
1417
+ asyncMap(_f) {
1418
+ return errAsync(this.error);
1419
+ }
1420
+ unwrapOr(v) {
1421
+ return v;
1422
+ }
1423
+ match(_ok, err) {
1424
+ return err(this.error);
1425
+ }
1426
+ safeUnwrap() {
1427
+ const error = this.error;
1428
+ return (function* () {
1429
+ yield err(error);
1430
+ throw new Error("Do not use this generator out of `safeTry`");
1431
+ })();
1432
+ }
1433
+ _unsafeUnwrap(config) {
1434
+ throw createNeverThrowError("Called `_unsafeUnwrap` on an Err", this, config);
1435
+ }
1436
+ _unsafeUnwrapErr(_) {
1437
+ return this.error;
1438
+ }
1439
+ *[Symbol.iterator]() {
1440
+ const self = this;
1441
+ yield self;
1442
+ return self;
1443
+ }
1444
+ };
1445
+ const fromThrowable = exports.Result.fromThrowable;
1446
+ exports.Err = Err;
1447
+ exports.Ok = Ok;
1448
+ exports.ResultAsync = ResultAsync;
1449
+ exports.err = err;
1450
+ exports.errAsync = errAsync;
1451
+ exports.fromAsyncThrowable = fromAsyncThrowable;
1452
+ exports.fromPromise = fromPromise;
1453
+ exports.fromSafePromise = fromSafePromise;
1454
+ exports.fromThrowable = fromThrowable;
1455
+ exports.ok = ok;
1456
+ exports.okAsync = okAsync;
1457
+ exports.safeTry = safeTry;
1458
+ }));
847
1459
  //#endregion
848
1460
  //#region src/constants/questions.ts
849
1461
  const DEFAULT_PROJECT_NAME = "ts-start";
850
1462
  //#endregion
1463
+ //#region src/constants/templates.ts
1464
+ const TEMPLATES = [{
1465
+ value: "ts-script",
1466
+ label: "ts-script",
1467
+ hint: "TypeScript script/tooling",
1468
+ deps: ["ts-pattern", "neverthrow"],
1469
+ devDeps: [
1470
+ "eslint",
1471
+ "@antfu/eslint-config",
1472
+ "tsx",
1473
+ "typescript",
1474
+ "rolldown"
1475
+ ]
1476
+ }];
1477
+ //#endregion
851
1478
  //#region src/utils/get-latest-ver.ts
852
- async function getLatestVer(pkg) {
1479
+ var import_index_cjs = require_index_cjs();
1480
+ function getLatestVer(pkg) {
853
1481
  const encoded = pkg.startsWith("@") ? pkg.replace("/", "%2F") : pkg;
854
- const res = await fetch(`https://registry.npmjs.org/${encoded}/latest`);
855
- if (!res.ok) throw new Error(`Failed to fetch version for ${pkg}`);
856
- const { version } = await res.json();
857
- return `^${version}`;
1482
+ return (0, import_index_cjs.fromPromise)(fetch(`https://registry.npmjs.org/${encoded}/latest`), (e) => e).andThen((response) => response.ok ? (0, import_index_cjs.fromPromise)(response.json(), (e) => e) : (0, import_index_cjs.err)(/* @__PURE__ */ new Error(`Failed to fetch version for ${pkg}`))).map(({ version }) => `^${version}`);
858
1483
  }
859
1484
  //#endregion
860
1485
  //#region node_modules/.pnpm/ts-pattern@5.9.0/node_modules/ts-pattern/dist/index.js
@@ -1260,64 +1885,107 @@ function F(t) {
1260
1885
  }
1261
1886
  //#endregion
1262
1887
  //#region src/utils/get-project-name.ts
1263
- async function getProjectName() {
1264
- return argv[2]?.trim() || await askProjectName();
1265
- }
1266
- async function askProjectName() {
1267
- return M(await Pe({
1888
+ function getProjectName() {
1889
+ const cliArg = argv[2]?.trim();
1890
+ return cliArg ? (0, import_index_cjs.okAsync)(cliArg) : (0, import_index_cjs.fromPromise)(Pe({
1268
1891
  message: "Project name",
1269
1892
  placeholder: DEFAULT_PROJECT_NAME,
1270
- defaultValue: DEFAULT_PROJECT_NAME
1271
- })).with(z.string, (name) => name).with(z.when(q$1), () => {
1272
- me("Operation cancelled");
1273
- exit(0);
1274
- }).exhaustive();
1893
+ defaultValue: DEFAULT_PROJECT_NAME,
1894
+ validate: validateProjectName
1895
+ }), (e) => e).andThen((answer) => M(answer).with(z.when(q$1), () => (0, import_index_cjs.err)(/* @__PURE__ */ new Error("Operation cancelled"))).with(z.string, (name) => (0, import_index_cjs.ok)(name)).exhaustive());
1896
+ }
1897
+ function validateProjectName(value) {
1898
+ const name = value ?? "";
1899
+ return [[(n) => /^[a-z0-9][a-z0-9-_]*$/.test(n), "Only lowercase letters, numbers, hyphens, and underscores"], [(n) => !n.startsWith("."), "Name cannot start with a dot"]].find(([predicate]) => !predicate(name))?.[1];
1900
+ }
1901
+ //#endregion
1902
+ //#region src/utils/get-template.ts
1903
+ function getTemplate() {
1904
+ return (0, import_index_cjs.fromPromise)(xe({
1905
+ message: "Select a template",
1906
+ options: [...TEMPLATES]
1907
+ }), (e) => e).andThen((answer) => M(answer).with(z.when(q$1), () => (0, import_index_cjs.err)(/* @__PURE__ */ new Error("Operation cancelled"))).with(z.string, (t) => (0, import_index_cjs.ok)(t)).exhaustive());
1275
1908
  }
1276
1909
  //#endregion
1277
1910
  //#region src/utils/resolve-new-dir.ts
1278
1911
  function resolveNewDir(projectName) {
1279
1912
  const targetDir = resolve(cwd(), projectName);
1280
- if (existsSync(targetDir)) {
1281
- me(`Directory already exists: ${targetDir}`);
1282
- exit(1);
1283
- }
1284
- return targetDir;
1913
+ return !existsSync(targetDir) ? (0, import_index_cjs.ok)(targetDir) : (0, import_index_cjs.err)(/* @__PURE__ */ new Error(`Directory already exists: ${targetDir}`));
1285
1914
  }
1286
1915
  //#endregion
1287
1916
  //#region src/index.ts
1288
- async function main() {
1917
+ (async () => {
1289
1918
  ge("create-template-ts");
1290
- const projectName = await getProjectName();
1291
- const targetDir = resolveNewDir(projectName);
1292
- const s = ft();
1293
- s.start("Fetching latest package versions");
1294
- const [depVers, devDepVers] = await Promise.all([Promise.all(DEPS.map(async (dep) => [dep, await getLatestVer(dep)])), Promise.all(DEV_DEPS.map(async (dep) => [dep, await getLatestVer(dep)]))]);
1295
- const deps = { ...Object.fromEntries(depVers) };
1296
- const devDeps = {
1297
- ...Object.fromEntries(devDepVers),
1298
- "@types/node": `^${version.match(/^v(\d+)/)?.[1]}`
1299
- };
1300
- s.stop("Fetched latest package versions");
1301
- const templateDir = join(import.meta.dirname, "../template");
1302
- mkdirSync(targetDir, { recursive: true });
1303
- cpSync(templateDir, targetDir, { recursive: true });
1304
- const gitignoreSrc = join(targetDir, "_gitignore");
1305
- const gitignoreDst = join(targetDir, ".gitignore");
1306
- if (existsSync(gitignoreSrc)) renameSync(gitignoreSrc, gitignoreDst);
1307
- const vscodeSrc = join(targetDir, "_vscode");
1308
- const vscodeDst = join(targetDir, ".vscode");
1309
- if (existsSync(vscodeSrc)) renameSync(vscodeSrc, vscodeDst);
1310
- const pkgPath = join(targetDir, "package.json");
1311
- const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
1312
- pkg.name = basename(projectName);
1313
- pkg.dependencies = deps;
1314
- pkg.devDependencies = devDeps;
1315
- writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 4)}\n`);
1316
- ye(`Done! Run:\n\n cd ${projectName}\n pnpm install`);
1919
+ await getProjectName().andThen((projectName) => getTemplate().map((template) => ({
1920
+ projectName,
1921
+ template
1922
+ }))).andThen(({ projectName, template }) => resolveNewDir(projectName).map((targetDir) => ({
1923
+ projectName,
1924
+ template,
1925
+ targetDir
1926
+ }))).andThen(({ projectName, template, targetDir }) => {
1927
+ const { deps, devDeps } = TEMPLATES.find((t) => t.value === template);
1928
+ const s = ft();
1929
+ s.start("Fetching latest package versions");
1930
+ return import_index_cjs.ResultAsync.combine([import_index_cjs.ResultAsync.combine([...deps].map((dep) => getLatestVer(dep))), import_index_cjs.ResultAsync.combine([...devDeps].map((dep) => getLatestVer(dep)))]).map(([depVers, devDepVers]) => {
1931
+ s.stop("Fetched latest package versions");
1932
+ return {
1933
+ projectName,
1934
+ template,
1935
+ targetDir,
1936
+ deps,
1937
+ devDeps,
1938
+ depVers,
1939
+ devDepVers
1940
+ };
1941
+ }).mapErr((error) => {
1942
+ s.stop("Failed to fetch package versions");
1943
+ return error;
1944
+ });
1945
+ }).andThen(({ projectName, template, targetDir, deps, devDeps, depVers, devDepVers }) => {
1946
+ const depsMap = Object.fromEntries(deps.map((dep, i) => [dep, depVers[i]]));
1947
+ const devDepsMap = {
1948
+ ...Object.fromEntries(devDeps.map((dep, i) => [dep, devDepVers[i]])),
1949
+ "@types/node": `^${version.match(/^v(\d+)/)?.[1]}`
1950
+ };
1951
+ const templateDir = join(import.meta.dirname, "../templates", template);
1952
+ const pkgPath = join(targetDir, "package.json");
1953
+ return safeMkdirSync(targetDir, { recursive: true }).andThen(() => safeCpSync(templateDir, targetDir, { recursive: true })).andThen(() => {
1954
+ const src = join(targetDir, "_gitignore");
1955
+ const dst = join(targetDir, ".gitignore");
1956
+ return existsSync(src) ? safeRenameSync(src, dst) : (0, import_index_cjs.ok)(void 0);
1957
+ }).andThen(() => {
1958
+ const src = join(targetDir, "_vscode");
1959
+ const dst = join(targetDir, ".vscode");
1960
+ return existsSync(src) ? safeRenameSync(src, dst) : (0, import_index_cjs.ok)(void 0);
1961
+ }).andThen(() => safeReadFileSync(pkgPath)).andThen((content) => safeJsonParse(content)).andThen((pkg) => {
1962
+ pkg.name = basename(projectName);
1963
+ pkg.dependencies = depsMap;
1964
+ pkg.devDependencies = devDepsMap;
1965
+ return safeWriteFileSync(pkgPath, `${JSON.stringify(pkg, null, 4)}\n`);
1966
+ }).map(() => projectName);
1967
+ }).match((projectName) => ye(`Done! Run:\n\n cd ${projectName}\n pnpm install`), (err) => {
1968
+ me(err.message);
1969
+ exit(1);
1970
+ });
1971
+ })();
1972
+ function safeMkdirSync(path, options) {
1973
+ return (0, import_index_cjs.fromThrowable)(mkdirSync, (e) => e)(path, options);
1974
+ }
1975
+ function safeCpSync(src, dest, options) {
1976
+ return (0, import_index_cjs.fromThrowable)(cpSync, (e) => e)(src, dest, options);
1977
+ }
1978
+ function safeRenameSync(oldPath, newPath) {
1979
+ return (0, import_index_cjs.fromThrowable)(renameSync, (e) => e)(oldPath, newPath);
1980
+ }
1981
+ function safeReadFileSync(path) {
1982
+ return (0, import_index_cjs.fromThrowable)((p) => readFileSync(p, "utf8"), (e) => e)(path);
1983
+ }
1984
+ function safeWriteFileSync(path, data) {
1985
+ return (0, import_index_cjs.fromThrowable)(writeFileSync, (e) => e)(path, data);
1986
+ }
1987
+ function safeJsonParse(text) {
1988
+ return (0, import_index_cjs.fromThrowable)((t) => JSON.parse(t), (e) => e)(text);
1317
1989
  }
1318
- main().catch((err) => {
1319
- console.error(err);
1320
- exit(1);
1321
- });
1322
1990
  //#endregion
1323
1991
  export {};
package/package.json CHANGED
@@ -1,12 +1,18 @@
1
1
  {
2
2
  "name": "@bryanchu10/create-template-ts",
3
3
  "type": "module",
4
- "version": "1.0.0",
4
+ "version": "1.1.0",
5
5
  "description": "Scaffold a modular TypeScript project for scripts and tooling",
6
+ "author": "Bryan Chu <bryanchu10@gmail.com> (https://github.com/bryanchu10)",
7
+ "license": "MIT",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/bryanchu10/create-template-ts"
11
+ },
6
12
  "bin": "./dist/index.js",
7
13
  "files": [
8
14
  "dist",
9
- "template"
15
+ "templates"
10
16
  ],
11
17
  "scripts": {
12
18
  "dev": "tsx watch src/index.ts",
@@ -17,6 +23,7 @@
17
23
  },
18
24
  "dependencies": {
19
25
  "@clack/prompts": "^1.4.0",
26
+ "neverthrow": "^8.2.0",
20
27
  "ts-pattern": "^5.9.0"
21
28
  },
22
29
  "devDependencies": {
@@ -14,9 +14,24 @@ export default antfu(
14
14
  "style/jsx-max-props-per-line": "off",
15
15
  "style/jsx-closing-bracket-location": ["error", "after-props"],
16
16
  "style/operator-linebreak": ["error", "before"],
17
+ "style/padding-line-between-statements": [
18
+ "error",
19
+ { blankLine: "always", prev: "*", next: "for" },
20
+ { blankLine: "always", prev: "for", next: "*" },
21
+ { blankLine: "always", prev: "*", next: "return" },
22
+ ],
17
23
  },
18
24
  },
19
25
  },
26
+ {
27
+ rules: {
28
+ "new-cap": ["error", {
29
+ capIsNew: true,
30
+ newIsCap: true,
31
+ properties: true,
32
+ }],
33
+ },
34
+ },
20
35
  {
21
36
  files: ["pnpm-workspace.yaml"],
22
37
  rules: {
File without changes
File without changes
File without changes
File without changes