git-stack-cli 1.0.2 → 1.0.4

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.
Files changed (79) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/index.cjs +3 -3
  3. package/package.json +15 -8
  4. package/rollup.config.mjs +46 -0
  5. package/scripts/.eslintrc.cjs +61 -0
  6. package/scripts/build-standalone.ts +73 -0
  7. package/scripts/core/create_asset.ts +21 -0
  8. package/scripts/core/file.ts +36 -0
  9. package/scripts/core/spawn.ts +62 -0
  10. package/scripts/npm-prepublishOnly.ts +8 -0
  11. package/scripts/release-brew.ts +69 -0
  12. package/scripts/release-github.ts +34 -0
  13. package/scripts/release-npm.ts +109 -0
  14. package/scripts/tsconfig.json +35 -0
  15. package/src/__fixtures__/metadata.ts +666 -0
  16. package/src/app/App.tsx +65 -0
  17. package/src/app/AutoUpdate.tsx +229 -0
  18. package/src/app/Await.tsx +82 -0
  19. package/src/app/Brackets.tsx +22 -0
  20. package/src/app/Command.tsx +19 -0
  21. package/src/app/Debug.tsx +52 -0
  22. package/src/app/DependencyCheck.tsx +155 -0
  23. package/src/app/Exit.tsx +25 -0
  24. package/src/app/FormatText.tsx +26 -0
  25. package/src/app/GatherMetadata.tsx +145 -0
  26. package/src/app/GithubApiError.tsx +78 -0
  27. package/src/app/LocalCommitStatus.tsx +70 -0
  28. package/src/app/LocalMergeRebase.tsx +230 -0
  29. package/src/app/LogTimestamp.tsx +12 -0
  30. package/src/app/Main.tsx +52 -0
  31. package/src/app/ManualRebase.tsx +308 -0
  32. package/src/app/MultiSelect.tsx +246 -0
  33. package/src/app/Output.tsx +37 -0
  34. package/src/app/Parens.tsx +21 -0
  35. package/src/app/PostRebaseStatus.tsx +33 -0
  36. package/src/app/PreLocalMergeRebase.tsx +31 -0
  37. package/src/app/PreSelectCommitRanges.tsx +31 -0
  38. package/src/app/Providers.tsx +11 -0
  39. package/src/app/RebaseCheck.tsx +96 -0
  40. package/src/app/SelectCommitRanges.tsx +372 -0
  41. package/src/app/Status.tsx +82 -0
  42. package/src/app/StatusTable.tsx +155 -0
  43. package/src/app/Store.tsx +252 -0
  44. package/src/app/Table.tsx +137 -0
  45. package/src/app/TextInput.tsx +88 -0
  46. package/src/app/Url.tsx +19 -0
  47. package/src/app/Waterfall.tsx +37 -0
  48. package/src/app/YesNoPrompt.tsx +73 -0
  49. package/src/command.ts +78 -0
  50. package/src/core/CommitMetadata.ts +212 -0
  51. package/src/core/Metadata.test.ts +41 -0
  52. package/src/core/Metadata.ts +51 -0
  53. package/src/core/StackSummaryTable.test.ts +157 -0
  54. package/src/core/StackSummaryTable.ts +127 -0
  55. package/src/core/Timer.ts +44 -0
  56. package/src/core/assertNever.ts +4 -0
  57. package/src/core/cache.ts +49 -0
  58. package/src/core/capitalize.ts +5 -0
  59. package/src/core/chalk.ts +103 -0
  60. package/src/core/clamp.ts +6 -0
  61. package/src/core/cli.ts +161 -0
  62. package/src/core/colors.ts +23 -0
  63. package/src/core/date.ts +25 -0
  64. package/src/core/fetch_json.ts +26 -0
  65. package/src/core/github.tsx +215 -0
  66. package/src/core/invariant.ts +5 -0
  67. package/src/core/is_command_available.ts +21 -0
  68. package/src/core/is_finite_value.ts +3 -0
  69. package/src/core/json.ts +32 -0
  70. package/src/core/match_group.ts +10 -0
  71. package/src/core/read_json.ts +12 -0
  72. package/src/core/safe_quote.ts +10 -0
  73. package/src/core/semver_compare.ts +27 -0
  74. package/src/core/short_id.ts +87 -0
  75. package/src/core/sleep.ts +3 -0
  76. package/src/core/wrap_index.ts +11 -0
  77. package/src/index.tsx +22 -0
  78. package/src/types/global.d.ts +7 -0
  79. package/tsconfig.json +53 -0
package/README.md CHANGED
@@ -96,5 +96,5 @@ npm run release:npm
96
96
  ### Homebrew + Github
97
97
 
98
98
  ```bash
99
- npm run release:github
99
+ npm run release:brew
100
100
  ```
@@ -26826,7 +26826,7 @@ function Url(props) {
26826
26826
  }
26827
26827
 
26828
26828
  function is_command_available(command) {
26829
- const PATH = process.env["PATH"];
26829
+ const PATH = process.env.PATH;
26830
26830
  invariant(PATH, "PATH env must exist");
26831
26831
  const path_list = PATH.split(path.delimiter);
26832
26832
  for (const dir of path_list) {
@@ -28680,7 +28680,7 @@ function RebaseCheck(props) {
28680
28680
  patch({ status });
28681
28681
  }
28682
28682
  catch (err) {
28683
- actions.error("Unable to check for rebase.");
28683
+ actions.error("Must be run from within a git repository.");
28684
28684
  if (err instanceof Error) {
28685
28685
  if (actions.isDebug()) {
28686
28686
  actions.error(err.message);
@@ -34080,7 +34080,7 @@ async function command() {
34080
34080
  .wrap(null)
34081
34081
  // disallow unknown options
34082
34082
  .strict()
34083
- .version("1.0.2" )
34083
+ .version("1.0.4" )
34084
34084
  .showHidden("show-hidden", "Show hidden options via `git stack help --show-hidden`")
34085
34085
  .help("help", "Show usage via `git stack help`").argv);
34086
34086
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-stack-cli",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "",
5
5
  "author": "magus",
6
6
  "license": "MIT",
@@ -13,22 +13,29 @@
13
13
  "git-stack": "dist/cjs/index.cjs"
14
14
  },
15
15
  "files": [
16
- "dist/cjs"
16
+ "dist/cjs",
17
+ "scripts",
18
+ "src",
19
+ "package-lock.json",
20
+ "rollup.config.mjs",
21
+ "tsconfig.json"
17
22
  ],
18
23
  "scripts": {
19
24
  "dev": "npm run build -- --watch",
20
25
  "build": "rollup -c rollup.config.mjs",
21
- "build:standalone": "bun run scripts/prepare-standalone.ts",
22
- "release:github": "bun run scripts/publish-release.ts",
23
- "release:npm": "npm publish",
26
+ "build:standalone": "bun run scripts/build-standalone.ts",
27
+ "release:npm": "bun run scripts/release-npm.ts",
28
+ "release:github": "bun run scripts/release-github.ts",
29
+ "release:brew": "bun run scripts/release-brew.ts",
24
30
  "lint:check": "eslint . --cache",
25
31
  "lint": "npm run lint:check -- --fix",
26
32
  "prettier:check": "prettier ./src --check --cache",
27
33
  "prettier": "npm run prettier:check -- --write",
28
- "test": "bun test src",
34
+ "test": "bun test",
29
35
  "test:watch": "npm run test -- --watch",
30
- "test:all": "npm run prettier:check && npm run lint:check && npm run build",
31
- "prepublishOnly": "npm run test:all"
36
+ "test:types": "tsc",
37
+ "test:all": "npm run prettier:check && npm run lint:check && npm run test:types",
38
+ "prepublishOnly": "bun run scripts/npm-prepublishOnly.ts"
32
39
  },
33
40
  "dependencies": {
34
41
  "chalk": "^5.3.0",
@@ -0,0 +1,46 @@
1
+ // npm i -D rollup @rollup/plugin-json @rollup/plugin-node-resolve @rollup/plugin-commonjs
2
+
3
+ import * as fs from "node:fs/promises";
4
+ import path from "node:path";
5
+ import * as url from "node:url";
6
+
7
+ import alias from "@rollup/plugin-alias";
8
+ import commonjs from "@rollup/plugin-commonjs";
9
+ import json from "@rollup/plugin-json";
10
+ import nodeResolve from "@rollup/plugin-node-resolve";
11
+ import replace from "@rollup/plugin-replace";
12
+ import typescript from "@rollup/plugin-typescript";
13
+
14
+ const SCRIPT_DIR = path.dirname(url.fileURLToPath(import.meta.url));
15
+ const PACKAGE_JSON_PATH = path.join(SCRIPT_DIR, "package.json");
16
+
17
+ const package_json_str = await fs.readFile(PACKAGE_JSON_PATH, "utf-8");
18
+ const package_json = JSON.parse(package_json_str);
19
+
20
+ export default {
21
+ input: "src/index.tsx",
22
+
23
+ output: {
24
+ file: "dist/cjs/index.cjs",
25
+ format: "cjs",
26
+ inlineDynamicImports: true,
27
+ },
28
+
29
+ plugins: [
30
+ // force line break
31
+ typescript(),
32
+ alias({
33
+ entries: [{ find: /^~\//, replacement: "./src/" }],
34
+ }),
35
+ nodeResolve({ exportConditions: ["node"] }),
36
+ commonjs(),
37
+ json(),
38
+ replace({
39
+ preventAssignment: true,
40
+ values: {
41
+ "process.env.NODE_ENV": JSON.stringify("production"),
42
+ "process.env.CLI_VERSION": JSON.stringify(String(package_json.version)),
43
+ },
44
+ }),
45
+ ],
46
+ };
@@ -0,0 +1,61 @@
1
+ const path = require("node:path");
2
+ const import_eslint = require("../config/eslint/import.eslint.cjs");
3
+
4
+ /** @type {import('eslint').Linter.Config} */
5
+ module.exports = {
6
+ root: true,
7
+
8
+ ignorePatterns: [],
9
+
10
+ overrides: [
11
+ {
12
+ files: [".eslintrc.{js,cjs}"],
13
+
14
+ parserOptions: {
15
+ ecmaVersion: 13, // ES2022
16
+ sourceType: "script",
17
+ },
18
+
19
+ env: {
20
+ node: true,
21
+ },
22
+ },
23
+
24
+ {
25
+ files: ["**/*.{ts,tsx}"],
26
+
27
+ parser: "@typescript-eslint/parser",
28
+ parserOptions: {
29
+ ecmaVersion: "latest",
30
+ sourceType: "script",
31
+ project: path.resolve(__dirname, "tsconfig.json"),
32
+ },
33
+
34
+ env: {
35
+ node: true,
36
+ },
37
+
38
+ settings: {
39
+ "import/resolver": {
40
+ typescript: true,
41
+ node: true,
42
+ },
43
+ },
44
+
45
+ extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
46
+
47
+ plugins: ["@typescript-eslint", "import"],
48
+
49
+ rules: {
50
+ "@typescript-eslint/consistent-type-imports": [
51
+ "error",
52
+ { prefer: "type-imports", fixStyle: "separate-type-imports" },
53
+ ],
54
+ "@typescript-eslint/no-explicit-any": "off",
55
+ "@typescript-eslint/no-floating-promises": ["error"],
56
+
57
+ ...import_eslint.rules,
58
+ },
59
+ },
60
+ ],
61
+ };
@@ -0,0 +1,73 @@
1
+ import * as fs from "node:fs/promises";
2
+ import path from "node:path";
3
+
4
+ import * as file from "~/core/file";
5
+ import { spawn } from "~/core/spawn";
6
+
7
+ // get paths relative to this script
8
+ const SCRIPT_DIR = import.meta.dir;
9
+ const PROJECT_DIR = path.join(SCRIPT_DIR, "..");
10
+ const NODE_MODULES_BIN = path.join(PROJECT_DIR, "node_modules", ".bin");
11
+ const DIST_DIR = path.join(PROJECT_DIR, "dist");
12
+ const CJS_DIR = path.join(DIST_DIR, "cjs");
13
+ const STANDALONE_DIR = path.join(DIST_DIR, "standalone");
14
+
15
+ const ARG_LIST = process.argv.slice(2);
16
+ const [maybe_target] = ARG_LIST;
17
+
18
+ let TARGET = "node18-linux-x64,node18-macos-x64,node18-win-x64";
19
+ if (maybe_target) {
20
+ TARGET = maybe_target;
21
+ }
22
+
23
+ console.debug(`Building for target [${TARGET}]`);
24
+
25
+ // clear entire dist output directory
26
+ await fs.rmdir(DIST_DIR, { recursive: true });
27
+ await fs.mkdir(DIST_DIR, { recursive: true });
28
+
29
+ const package_json = await file.read_json(
30
+ path.join(PROJECT_DIR, "package.json")
31
+ );
32
+
33
+ // prettier-ignore
34
+ const { name, version, description, author, license, repository } = package_json;
35
+
36
+ // include fields necessary for standalone executable build
37
+ const standalone_package_json = {
38
+ name,
39
+ version,
40
+ description,
41
+ author,
42
+ license,
43
+ repository,
44
+ bin: {
45
+ "git-stack": "index.js",
46
+ },
47
+ };
48
+
49
+ await file.write_json(
50
+ path.join(STANDALONE_DIR, "package.json"),
51
+ standalone_package_json
52
+ );
53
+
54
+ process.chdir(PROJECT_DIR);
55
+
56
+ process.env.NODE_ENV = "production";
57
+
58
+ // run typescript build to generate module output
59
+ await spawn("npm run build");
60
+
61
+ await fs.cp(
62
+ path.join(CJS_DIR, "index.cjs"),
63
+ path.join(STANDALONE_DIR, "index.js")
64
+ );
65
+
66
+ process.chdir(STANDALONE_DIR);
67
+
68
+ // run pkg to build standalone executable
69
+ await spawn([
70
+ path.join(NODE_MODULES_BIN, "pkg"),
71
+ "package.json",
72
+ `--targets=${TARGET}`,
73
+ ]);
@@ -0,0 +1,21 @@
1
+ import { spawn } from "~/core/spawn";
2
+
3
+ // https://github.com/magus/git-stack-cli/releases/download/0.8.9/git-stack-cli-linux
4
+ export async function create_asset(filepath: string, options: Options) {
5
+ const sha256_cmd = await spawn.sync(`shasum -a 256 ${filepath}`);
6
+ const match = sha256_cmd.stdout.match(/(?<sha256>[^\s]+)/i);
7
+
8
+ if (!match?.groups) {
9
+ throw new Error(`unable to get sha256 for ${filepath}`);
10
+ }
11
+
12
+ const sha256 = match.groups.sha256;
13
+
14
+ const url = `https://github.com/magus/git-stack-cli/releases/download/${options.version}/${filepath}`;
15
+
16
+ return { filepath, sha256, url };
17
+ }
18
+
19
+ type Options = {
20
+ version: string;
21
+ };
@@ -0,0 +1,36 @@
1
+ import * as fs from "node:fs/promises";
2
+
3
+ export async function read_json(filepath: string) {
4
+ const file = Bun.file(filepath);
5
+ const json = await file.json();
6
+ return json;
7
+ }
8
+
9
+ export async function write_json(filepath: string, data: any) {
10
+ const file = Bun.file(filepath);
11
+ await Bun.write(file, JSON.stringify(data, null, 2));
12
+ }
13
+
14
+ export async function read_text(filepath: string) {
15
+ const file = Bun.file(filepath);
16
+ const text = await file.text();
17
+ return text;
18
+ }
19
+
20
+ export async function write_text(filepath: string, text: string) {
21
+ const file = Bun.file(filepath);
22
+ await Bun.write(file, text);
23
+ }
24
+
25
+ export async function exists(filepath: string) {
26
+ try {
27
+ await fs.access(filepath);
28
+ return true;
29
+ } catch {
30
+ return false;
31
+ }
32
+ }
33
+
34
+ export async function rm(filepath: string) {
35
+ await fs.rm(filepath);
36
+ }
@@ -0,0 +1,62 @@
1
+ export async function spawn(unsafe_cmd: CommandLike) {
2
+ const cmd = get_cmd(unsafe_cmd);
3
+
4
+ console.debug();
5
+ console.debug("[spawn]", cmd.str);
6
+
7
+ const env = process.env;
8
+ const proc = await Bun.spawn(cmd.parts, {
9
+ env,
10
+ stdout: "inherit",
11
+ stderr: "inherit",
12
+ });
13
+
14
+ await proc.exited;
15
+
16
+ if (proc.exitCode) {
17
+ console.error(`(${proc.exitCode})`, cmd.str);
18
+
19
+ if (!process.env.GS_NO_CHECK) {
20
+ process.exit(proc.exitCode);
21
+ }
22
+ }
23
+
24
+ console.debug("[end]", cmd.str);
25
+
26
+ return { proc };
27
+ }
28
+
29
+ spawn.sync = async function spawnSync(unsafe_cmd: CommandLike) {
30
+ const cmd = get_cmd(unsafe_cmd);
31
+
32
+ console.debug();
33
+ console.debug("[spawn.sync]", cmd.str);
34
+
35
+ const env = process.env;
36
+ const proc = await Bun.spawnSync(cmd.parts, { env });
37
+
38
+ const stdout = String(proc.stdout).trim();
39
+ const stderr = String(proc.stderr).trim();
40
+
41
+ console.debug("[end]", cmd.str);
42
+ console.debug({ stdout, stderr });
43
+
44
+ return { proc, stdout, stderr };
45
+ };
46
+
47
+ type CommandLike = string | Array<string>;
48
+
49
+ function get_cmd(unsafe_cmd: CommandLike) {
50
+ let str;
51
+ let parts;
52
+
53
+ if (Array.isArray(unsafe_cmd)) {
54
+ parts = unsafe_cmd;
55
+ str = unsafe_cmd.join(" ");
56
+ } else {
57
+ parts = unsafe_cmd.split(" ");
58
+ str = unsafe_cmd;
59
+ }
60
+
61
+ return { parts, str };
62
+ }
@@ -0,0 +1,8 @@
1
+ // simply check for flag set by `scripts/release-npm`
2
+ // ensure we are publishing through the custom script
3
+
4
+ if (!process.env.GS_RELEASE_NPM) {
5
+ console.error("Must publish using `npm run release:npm`");
6
+ console.error();
7
+ process.exit(10);
8
+ }
@@ -0,0 +1,69 @@
1
+ import path from "node:path";
2
+
3
+ import { create_asset } from "~/core/create_asset";
4
+ import * as file from "~/core/file";
5
+ import { spawn } from "~/core/spawn";
6
+
7
+ // get paths relative to this script
8
+ const SCRIPT_DIR = import.meta.dir;
9
+ const PROJECT_DIR = path.join(SCRIPT_DIR, "..");
10
+ const DIST_DIR = path.join(PROJECT_DIR, "dist");
11
+ const STANDALONE_DIR = path.join(DIST_DIR, "standalone");
12
+ const HOMEBREW_DIR = path.join(PROJECT_DIR, "homebrew");
13
+
14
+ const package_json = await file.read_json(
15
+ path.join(PROJECT_DIR, "package.json")
16
+ );
17
+
18
+ const version = package_json.version;
19
+
20
+ process.chdir(STANDALONE_DIR);
21
+
22
+ const linux_asset = await create_asset("git-stack-cli-linux", { version });
23
+ const macos_asset = await create_asset("git-stack-cli-macos", { version });
24
+ const win_asset = await create_asset("git-stack-cli-win.exe", { version });
25
+
26
+ console.debug({ linux_asset, macos_asset, win_asset });
27
+
28
+ const re_token = (name: string) => new RegExp(`{{ ${name} }}`, "g");
29
+
30
+ process.chdir(HOMEBREW_DIR);
31
+
32
+ let formula = await file.read_text("git-stack.rb.template");
33
+
34
+ formula = formula.replace(re_token("version"), version);
35
+ formula = formula.replace(re_token("mac_bin"), macos_asset.filepath);
36
+ formula = formula.replace(re_token("mac_sha256"), macos_asset.sha256);
37
+ formula = formula.replace(re_token("linux_bin"), linux_asset.filepath);
38
+ formula = formula.replace(re_token("linux_sha256"), linux_asset.sha256);
39
+
40
+ await file.write_text("git-stack.rb", formula);
41
+
42
+ await spawn.sync(`git commit -a -m ${version}`);
43
+ await spawn.sync(`git push`);
44
+
45
+ process.chdir(PROJECT_DIR);
46
+
47
+ await spawn(`npm i`);
48
+
49
+ await spawn.sync(`git commit -a -m ${version}`);
50
+ await spawn.sync(`git push`);
51
+
52
+ // -a: create tag on last commit
53
+ // -m: message
54
+ await spawn.sync(`git tag -a ${version} -m ${version}`);
55
+ await spawn.sync(`git push origin ${version}`);
56
+
57
+ await spawn.sync(`gh release create ${version} -t ${version} --generate-notes`);
58
+
59
+ process.chdir(STANDALONE_DIR);
60
+
61
+ await spawn.sync(`gh release upload ${version} ${linux_asset.filepath}`);
62
+ await spawn.sync(`gh release upload ${version} ${macos_asset.filepath}`);
63
+ await spawn.sync(`gh release upload ${version} ${win_asset.filepath}`);
64
+
65
+ console.debug();
66
+ console.debug("✅", "published", version);
67
+ console.debug();
68
+ console.debug("https://github.com/magus/homebrew-git-stack");
69
+ console.debug();
@@ -0,0 +1,34 @@
1
+ import path from "node:path";
2
+
3
+ import { create_asset } from "~/core/create_asset";
4
+ import * as file from "~/core/file";
5
+ import { spawn } from "~/core/spawn";
6
+
7
+ // get paths relative to this script
8
+ const SCRIPT_DIR = import.meta.dir;
9
+ const PROJECT_DIR = path.join(SCRIPT_DIR, "..");
10
+
11
+ const package_json = await file.read_json(
12
+ path.join(PROJECT_DIR, "package.json")
13
+ );
14
+
15
+ const version = package_json.version;
16
+
17
+ await spawn("npm pack");
18
+
19
+ // prettier-ignore
20
+ const tarball_asset = (
21
+ await create_asset(`git-stack-cli-${version}.tgz`, { version })
22
+ );
23
+
24
+ await spawn.sync(`gh release create ${version} -t ${version} --generate-notes`);
25
+
26
+ await spawn.sync(`gh release upload ${version} ${tarball_asset.filepath}`);
27
+
28
+ await file.rm(tarball_asset.filepath);
29
+
30
+ console.debug();
31
+ console.debug("✅", "published", version);
32
+ console.debug();
33
+ console.debug("https://github.com/magus/git-stack-cli/releases");
34
+ console.debug();
@@ -0,0 +1,109 @@
1
+ import * as fs from "node:fs/promises";
2
+ import path from "node:path";
3
+
4
+ import * as file from "~/core/file";
5
+ import { spawn } from "~/core/spawn";
6
+
7
+ process.env.NODE_ENV = "production";
8
+
9
+ // get paths relative to this script
10
+ const SCRIPT_DIR = import.meta.dir;
11
+ const PROJECT_DIR = path.join(SCRIPT_DIR, "..");
12
+ const DIST_DIR = path.join(PROJECT_DIR, "dist");
13
+
14
+ // clear entire dist output directory
15
+ await fs.rmdir(DIST_DIR, { recursive: true });
16
+ await fs.mkdir(DIST_DIR, { recursive: true });
17
+
18
+ process.chdir(PROJECT_DIR);
19
+
20
+ const package_json = await file.read_json(
21
+ path.join(PROJECT_DIR, "package.json")
22
+ );
23
+
24
+ const version = package_json.version;
25
+
26
+ const git_tag = await spawn.sync(`git tag -l ${version}`);
27
+
28
+ if (git_tag.stdout) {
29
+ console.error(`tag [${version}] already exists`);
30
+ if (!process.env.GS_NO_CHECK) {
31
+ process.exit(1);
32
+ }
33
+ }
34
+
35
+ // install all dependencies even though we are NODE_ENV=production
36
+ await spawn(`npm install --production=false`);
37
+
38
+ await spawn(`npm run test:all`);
39
+
40
+ await spawn(`npm run build`);
41
+
42
+ // confirm all files specified exist
43
+ for (const filepath of package_json.files) {
44
+ if (!(await file.exists(filepath))) {
45
+ console.error("missing required file in package.json files", filepath);
46
+ if (!process.env.GS_NO_CHECK) {
47
+ process.exit(2);
48
+ }
49
+ }
50
+ }
51
+
52
+ process.env.GS_RELEASE_NPM = "true";
53
+ console.info("Publishing to NPM requires a one-time password");
54
+ const otp = await input("Enter OTP: ");
55
+ await spawn(`npm publish --otp=${otp}`);
56
+
57
+ process.chdir(PROJECT_DIR);
58
+
59
+ await spawn.sync(`git commit -a -m ${version}`);
60
+ await spawn.sync(`git push`);
61
+
62
+ // -a: create tag on last commit
63
+ // -m: message
64
+ await spawn.sync(`git tag -a ${version} -m ${version}`);
65
+ await spawn.sync(`git push origin ${version}`);
66
+
67
+ console.debug();
68
+ console.debug("✅", "published", version);
69
+ console.debug();
70
+ console.debug("https://www.npmjs.com/package/git-stack-cli");
71
+ console.debug();
72
+
73
+ // // https://github.com/magus/git-stack-cli/releases/download/0.8.9/git-stack-cli-linux
74
+ // async function create_asset(name: string) {
75
+ // const sha256_cmd = await spawn.sync(`shasum -a 256 ${name}`);
76
+ // const match = sha256_cmd.stdout.match(/(?<sha256>[^\s]+)/i);
77
+
78
+ // if (!match?.groups) {
79
+ // throw new Error(`unable to get sha256 for ${name}`);
80
+ // }
81
+
82
+ // const sha256 = match.groups.sha256;
83
+
84
+ // const url = `https://github.com/magus/git-stack-cli/releases/download/${version}/${name}`;
85
+
86
+ // return { name, sha256, url };
87
+ // }
88
+
89
+ // function reFind(list: Array<string>, re: RegExp) {
90
+ // for (const str of list) {
91
+ // const match = str.match(re);
92
+
93
+ // if (match?.groups) {
94
+ // return match.groups.value;
95
+ // }
96
+ // }
97
+
98
+ // return null;
99
+ // }
100
+
101
+ async function input(prompt: string) {
102
+ process.stdout.write(prompt);
103
+ for await (const value of console) {
104
+ if (value) {
105
+ return value;
106
+ }
107
+ process.stdout.write(prompt);
108
+ }
109
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "compilerOptions": {
3
+ "lib": ["ESNext"],
4
+ "target": "ESNext",
5
+ "module": "ESNext",
6
+ "moduleDetection": "force",
7
+ "jsx": "react-jsx",
8
+ "allowJs": true,
9
+
10
+ "baseUrl": ".",
11
+ "paths": {
12
+ "~/*": ["./*"]
13
+ },
14
+
15
+ "types": [
16
+ // add bun-types for resolving imports
17
+ //
18
+ // import { test, expect } from "bun:test";
19
+ //
20
+ "bun-types"
21
+ ],
22
+
23
+ /* Bundler mode */
24
+ "moduleResolution": "bundler",
25
+ "allowImportingTsExtensions": true,
26
+ "verbatimModuleSyntax": true,
27
+ "noEmit": true,
28
+
29
+ /* Linting */
30
+ "skipLibCheck": true,
31
+ "strict": true,
32
+ "noFallthroughCasesInSwitch": true,
33
+ "forceConsistentCasingInFileNames": true
34
+ }
35
+ }