@repokit/core 1.3.7 → 1.6.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.
Files changed (36) hide show
  1. package/dist/CommandParser.d.mts +9 -0
  2. package/dist/CommandParser.mjs +55 -0
  3. package/dist/ConcurrencyPool.d.mts +13 -0
  4. package/dist/ConcurrencyPool.mjs +24 -0
  5. package/dist/ConfigurationParser.d.mts +9 -0
  6. package/dist/ConfigurationParser.mjs +27 -0
  7. package/dist/RepoKitCommand.d.mts +17 -0
  8. package/dist/RepoKitCommand.mjs +16 -0
  9. package/dist/RepoKitConfig.d.mts +25 -0
  10. package/dist/RepoKitConfig.mjs +25 -0
  11. package/dist/TSCompiler.d.mts +9 -0
  12. package/dist/TSCompiler.mjs +20 -0
  13. package/dist/commands/parse_commands.d.mts +1 -0
  14. package/dist/commands/parse_commands.mjs +9 -0
  15. package/dist/commands/parse_configuration.d.mts +1 -0
  16. package/dist/commands/parse_configuration.mjs +9 -0
  17. package/dist/index.d.mts +4 -0
  18. package/dist/index.mjs +4 -0
  19. package/dist/templates/command_template.mjs +5 -0
  20. package/dist/templates/configuration_template.mjs +5 -0
  21. package/dist/types.d.mts +25 -0
  22. package/dist/types.mjs +1 -0
  23. package/externals/CommandParser.ts +10 -9
  24. package/externals/ConcurrencyPool.ts +24 -0
  25. package/externals/ConfigurationParser.ts +4 -2
  26. package/externals/TSCompiler.ts +26 -0
  27. package/installation/install.sh +6 -27
  28. package/internals/configuration/configuration.rs +9 -2
  29. package/internals/file_walker/walker.rs +1 -5
  30. package/internals/internal_commands/register_command.rs +1 -1
  31. package/internals/internal_commands/typescript_command.rs +3 -4
  32. package/internals/internal_filesystem/internal_filesystem.rs +8 -5
  33. package/package.json +25 -8
  34. package/externals/TaskPooler.ts +0 -31
  35. /package/externals/templates/{command_template.ts → command_template.txt} +0 -0
  36. /package/externals/templates/{configuration_template.ts → configuration_template.txt} +0 -0
@@ -0,0 +1,9 @@
1
+ //#region externals/CommandParser.d.ts
2
+ declare class CommandParser {
3
+ private static compiler?;
4
+ static parse(): Promise<void>;
5
+ private static parseCommand;
6
+ private static parsePaths;
7
+ }
8
+ //#endregion
9
+ export { CommandParser };
@@ -0,0 +1,55 @@
1
+ import { TSCompiler } from "./TSCompiler.mjs";
2
+ import { RepoKitCommand } from "./RepoKitCommand.mjs";
3
+ import { ConcurrencyPool } from "./ConcurrencyPool.mjs";
4
+ import { parseArgs } from "node:util";
5
+ import { stat } from "node:fs/promises";
6
+ import { existsSync } from "node:fs";
7
+
8
+ //#region externals/CommandParser.ts
9
+ var CommandParser = class {
10
+ static compiler;
11
+ static async parse() {
12
+ const { paths, root } = this.parsePaths();
13
+ if (!root || !existsSync(root) || !(await stat(root)).isDirectory()) return console.log(JSON.stringify([]));
14
+ this.compiler = new TSCompiler(root, "parse_commands");
15
+ const pool = new ConcurrencyPool();
16
+ const pathList = paths.split(",").filter(Boolean);
17
+ const commands = await Promise.all(pathList.map((path) => pool.enqueue(() => this.parseCommand(path))));
18
+ console.log(JSON.stringify(commands.flat()));
19
+ }
20
+ static async parseCommand(path) {
21
+ const commands = [];
22
+ const declaredExports = await this.compiler?.compile?.(path);
23
+ for (const key in declaredExports) if (declaredExports[key] instanceof RepoKitCommand) commands.push({
24
+ ...declaredExports[key],
25
+ location: path
26
+ });
27
+ return commands;
28
+ }
29
+ static parsePaths() {
30
+ try {
31
+ return parseArgs({ options: {
32
+ paths: {
33
+ default: "",
34
+ multiple: false,
35
+ short: "p",
36
+ type: "string"
37
+ },
38
+ root: {
39
+ default: "",
40
+ multiple: false,
41
+ short: "r",
42
+ type: "string"
43
+ }
44
+ } }).values;
45
+ } catch {
46
+ return {
47
+ paths: "",
48
+ root: ""
49
+ };
50
+ }
51
+ }
52
+ };
53
+
54
+ //#endregion
55
+ export { CommandParser };
@@ -0,0 +1,13 @@
1
+ import { AsyncTask } from "./types.mjs";
2
+
3
+ //#region externals/ConcurrencyPool.d.ts
4
+ declare class ConcurrencyPool<T> {
5
+ readonly maxConcurrency: number;
6
+ private readonly IDs;
7
+ private readonly activeTasks;
8
+ constructor(maxConcurrency?: number);
9
+ enqueue(task: AsyncTask<T>): Promise<T>;
10
+ private executeTask;
11
+ }
12
+ //#endregion
13
+ export { ConcurrencyPool };
@@ -0,0 +1,24 @@
1
+ import { AutoIncrementingID } from "@figliolia/event-emitter";
2
+
3
+ //#region externals/ConcurrencyPool.ts
4
+ var ConcurrencyPool = class {
5
+ IDs = new AutoIncrementingID();
6
+ activeTasks = /* @__PURE__ */ new Map();
7
+ constructor(maxConcurrency = 10) {
8
+ this.maxConcurrency = maxConcurrency;
9
+ }
10
+ async enqueue(task) {
11
+ if (this.activeTasks.size === this.maxConcurrency) await Promise.race(Array.from(this.activeTasks.values()));
12
+ return this.executeTask(task);
13
+ }
14
+ executeTask(task) {
15
+ const ID = this.IDs.get();
16
+ const promise = task();
17
+ this.activeTasks.set(ID, promise);
18
+ promise.finally(() => this.activeTasks.delete(ID));
19
+ return promise;
20
+ }
21
+ };
22
+
23
+ //#endregion
24
+ export { ConcurrencyPool };
@@ -0,0 +1,9 @@
1
+ import { TSCompiler } from "./TSCompiler.mjs";
2
+
3
+ //#region externals/ConfigurationParser.d.ts
4
+ declare class ConfigurationParser extends TSCompiler {
5
+ static parse(): Promise<void>;
6
+ private static parseRoot;
7
+ }
8
+ //#endregion
9
+ export { ConfigurationParser };
@@ -0,0 +1,27 @@
1
+ import { TSCompiler } from "./TSCompiler.mjs";
2
+ import { RepoKitConfig } from "./RepoKitConfig.mjs";
3
+ import { parseArgs } from "node:util";
4
+ import { existsSync } from "node:fs";
5
+ import { join } from "node:path";
6
+
7
+ //#region externals/ConfigurationParser.ts
8
+ var ConfigurationParser = class extends TSCompiler {
9
+ static async parse() {
10
+ const root = this.parseRoot();
11
+ const path = join(root, "repokit.ts");
12
+ if (!existsSync(path)) return;
13
+ const config = await new TSCompiler(root, "parse_configuration").compile(path);
14
+ for (const key in config) if (config[key] instanceof RepoKitConfig) return console.log(JSON.stringify(config[key].toScoped(path)));
15
+ }
16
+ static parseRoot() {
17
+ return parseArgs({ options: { root: {
18
+ default: "",
19
+ multiple: false,
20
+ short: "r",
21
+ type: "string"
22
+ } } }).values.root;
23
+ }
24
+ };
25
+
26
+ //#endregion
27
+ export { ConfigurationParser };
@@ -0,0 +1,17 @@
1
+ import { ICommand, IRepoKitCommand } from "./types.mjs";
2
+
3
+ //#region externals/RepoKitCommand.d.ts
4
+ declare class RepoKitCommand {
5
+ name: string;
6
+ owner: string;
7
+ description: string;
8
+ commands: Record<string, ICommand>;
9
+ constructor({
10
+ name,
11
+ description,
12
+ owner,
13
+ commands
14
+ }: IRepoKitCommand);
15
+ }
16
+ //#endregion
17
+ export { RepoKitCommand };
@@ -0,0 +1,16 @@
1
+ //#region externals/RepoKitCommand.ts
2
+ var RepoKitCommand = class {
3
+ name;
4
+ owner;
5
+ description;
6
+ commands;
7
+ constructor({ name, description, owner = "", commands = {} }) {
8
+ this.name = name;
9
+ this.owner = owner;
10
+ this.commands = commands;
11
+ this.description = description;
12
+ }
13
+ };
14
+
15
+ //#endregion
16
+ export { RepoKitCommand };
@@ -0,0 +1,25 @@
1
+ import { RepoKitCommand } from "./RepoKitCommand.mjs";
2
+ import { ICommand, IRepoKitConfig } from "./types.mjs";
3
+
4
+ //#region externals/RepoKitConfig.d.ts
5
+ declare class RepoKitConfig implements Required<IRepoKitConfig> {
6
+ project: string;
7
+ thirdParty: RepoKitCommand[];
8
+ commands: Record<string, ICommand>;
9
+ constructor({
10
+ project,
11
+ commands,
12
+ thirdParty
13
+ }: IRepoKitConfig);
14
+ toScoped(location: string): this & {
15
+ thirdParty: {
16
+ location: string;
17
+ name: string;
18
+ owner: string;
19
+ description: string;
20
+ commands: Record<string, ICommand>;
21
+ }[];
22
+ };
23
+ }
24
+ //#endregion
25
+ export { RepoKitConfig };
@@ -0,0 +1,25 @@
1
+ import { RepoKitCommand } from "./RepoKitCommand.mjs";
2
+
3
+ //#region externals/RepoKitConfig.ts
4
+ var RepoKitConfig = class {
5
+ project;
6
+ thirdParty;
7
+ commands;
8
+ constructor({ project, commands = {}, thirdParty = [] }) {
9
+ this.project = project;
10
+ this.commands = commands;
11
+ this.thirdParty = thirdParty.map((command) => new RepoKitCommand(command));
12
+ }
13
+ toScoped(location) {
14
+ return {
15
+ ...this,
16
+ thirdParty: this.thirdParty.map((command) => ({
17
+ ...command,
18
+ location
19
+ }))
20
+ };
21
+ }
22
+ };
23
+
24
+ //#endregion
25
+ export { RepoKitConfig };
@@ -0,0 +1,9 @@
1
+ //#region externals/TSCompiler.d.ts
2
+ declare class TSCompiler {
3
+ readonly root: string;
4
+ readonly command: string;
5
+ constructor(root: string, command: string);
6
+ compile(path: string): Promise<any>;
7
+ }
8
+ //#endregion
9
+ export { TSCompiler };
@@ -0,0 +1,20 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { transform } from "@swc/core";
3
+
4
+ //#region externals/TSCompiler.ts
5
+ var TSCompiler = class {
6
+ constructor(root, command) {
7
+ this.root = root;
8
+ this.command = command;
9
+ }
10
+ async compile(path) {
11
+ const source = (await readFile(path)).toString();
12
+ const result = await transform(source, { module: { type: "es6" } });
13
+ const config = eval(result.code);
14
+ console.log(config);
15
+ return config;
16
+ }
17
+ };
18
+
19
+ //#endregion
20
+ export { TSCompiler };
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,9 @@
1
+ import { CommandParser } from "../CommandParser.mjs";
2
+
3
+ //#region externals/commands/parse_commands.ts
4
+ (async () => {
5
+ await CommandParser.parse();
6
+ })();
7
+
8
+ //#endregion
9
+ export { };
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,9 @@
1
+ import { ConfigurationParser } from "../ConfigurationParser.mjs";
2
+
3
+ //#region externals/commands/parse_configuration.ts
4
+ (async () => {
5
+ await ConfigurationParser.parse();
6
+ })();
7
+
8
+ //#endregion
9
+ export { };
@@ -0,0 +1,4 @@
1
+ import { RepoKitCommand } from "./RepoKitCommand.mjs";
2
+ import { AsyncTask, ICommand, ILocatedCommand, IRepoKitCommand, IRepoKitConfig } from "./types.mjs";
3
+ import { RepoKitConfig } from "./RepoKitConfig.mjs";
4
+ export { AsyncTask, ICommand, ILocatedCommand, IRepoKitCommand, IRepoKitConfig, RepoKitCommand, RepoKitConfig };
package/dist/index.mjs ADDED
@@ -0,0 +1,4 @@
1
+ import { RepoKitCommand } from "./RepoKitCommand.mjs";
2
+ import { RepoKitConfig } from "./RepoKitConfig.mjs";
3
+
4
+ export { RepoKitCommand, RepoKitConfig };
@@ -0,0 +1,5 @@
1
+ //#region externals/templates/command_template.txt
2
+ var command_template_default = "import { RepoKitCommand } from \"@repokit/core\";\n\n/**\n * Please fill out this command file with your desired settings\n */\nexport const Commands = new RepoKitCommand({\n name: \"<Your Package Name>\",\n owner: \"<Optional Team or Individual>\",\n description: \"<Your Package Description>\",\n commands: {\n \"<your-first-command>\": {\n command: \"<insert shell command here>\",\n description: \"A description for using your command\",\n },\n \"<your-second-command>\": {\n command: \"<insert shell command here>\",\n description: \"A description for using your command\",\n },\n \"<your-third-command>\": {\n command: \"<insert shell command here>\",\n description: \"A description for using your command\",\n },\n },\n});\n";
3
+
4
+ //#endregion
5
+ export { command_template_default as default };
@@ -0,0 +1,5 @@
1
+ //#region externals/templates/configuration_template.txt
2
+ var configuration_template_default = "import { RepoKitConfig } from \"@repokit/core\";\n\n/**\n * Please fill out this config file with your desired\n * repokit settings\n */\nexport const RepoKit = new RepoKitConfig({\n project: \"Your Project Name\",\n commands: {\n \"<your-first-command>\": {\n command: \"<insert shell command here>\",\n description: \"A description for using your command\",\n },\n \"<your-second-command>\": {\n command: \"<insert shell command here>\",\n description: \"A description for using your command\",\n },\n \"<your-third-command>\": {\n command: \"<insert shell command here>\",\n description: \"A description for using your command\",\n },\n },\n});\n";
3
+
4
+ //#endregion
5
+ export { configuration_template_default as default };
@@ -0,0 +1,25 @@
1
+ import { RepoKitCommand } from "./RepoKitCommand.mjs";
2
+
3
+ //#region externals/types.d.ts
4
+ interface IRepoKitConfig {
5
+ project: string;
6
+ thirdParty?: RepoKitCommand[];
7
+ commands?: Record<string, ICommand>;
8
+ }
9
+ interface IRepoKitCommand {
10
+ name: string;
11
+ owner?: string;
12
+ description: string;
13
+ commands: Record<string, ICommand>;
14
+ }
15
+ interface ICommand {
16
+ command: string;
17
+ description: string;
18
+ args?: Record<string, string>;
19
+ }
20
+ interface ILocatedCommand extends IRepoKitCommand {
21
+ location: string;
22
+ }
23
+ type AsyncTask<T> = () => Promise<T>;
24
+ //#endregion
25
+ export { AsyncTask, ICommand, ILocatedCommand, IRepoKitCommand, IRepoKitConfig };
package/dist/types.mjs ADDED
@@ -0,0 +1 @@
1
+ export { };
@@ -1,32 +1,33 @@
1
1
  import { parseArgs } from "node:util";
2
- import { join } from "node:path";
3
2
  import { stat } from "node:fs/promises";
4
3
  import { existsSync } from "node:fs";
5
4
 
6
5
  import type { ILocatedCommand } from "./types";
7
- import { TaskPooler } from "./TaskPooler";
6
+ import { TSCompiler } from "./TSCompiler";
8
7
  import { RepoKitCommand } from "./RepoKitCommand";
8
+ import { ConcurrencyPool } from "./ConcurrencyPool";
9
9
  /* oxlint-disable typescript-eslint(no-misused-spread) */
10
10
 
11
11
  export class CommandParser {
12
+ private static compiler?: TSCompiler;
13
+
12
14
  public static async parse() {
13
15
  const { paths, root } = this.parsePaths();
14
16
  if (!root || !existsSync(root) || !(await stat(root)).isDirectory()) {
15
17
  return console.log(JSON.stringify([]));
16
18
  }
19
+ this.compiler = new TSCompiler(root, "parse_commands");
20
+ const pool = new ConcurrencyPool<ILocatedCommand[]>();
17
21
  const pathList = paths.split(",").filter(Boolean);
18
- const pool = new TaskPooler<ILocatedCommand[]>();
19
- const results = await Promise.all(
20
- pathList.map(path =>
21
- pool.enqueue(() => this.parseCommand(join(root, path))),
22
- ),
22
+ const commands = await Promise.all(
23
+ pathList.map(path => pool.enqueue(() => this.parseCommand(path))),
23
24
  );
24
- console.log(JSON.stringify(results.flat()));
25
+ console.log(JSON.stringify(commands.flat()));
25
26
  }
26
27
 
27
28
  private static async parseCommand(path: string) {
28
29
  const commands: ILocatedCommand[] = [];
29
- const declaredExports = await import(path);
30
+ const declaredExports = await this.compiler?.compile?.(path);
30
31
  for (const key in declaredExports) {
31
32
  if (declaredExports[key] instanceof RepoKitCommand) {
32
33
  commands.push({ ...declaredExports[key], location: path });
@@ -0,0 +1,24 @@
1
+ import { AutoIncrementingID } from "@figliolia/event-emitter";
2
+
3
+ import type { AsyncTask } from "./types";
4
+
5
+ export class ConcurrencyPool<T> {
6
+ private readonly IDs = new AutoIncrementingID();
7
+ private readonly activeTasks = new Map<string, Promise<T>>();
8
+ constructor(public readonly maxConcurrency: number = 10) {}
9
+
10
+ public async enqueue(task: AsyncTask<T>) {
11
+ if (this.activeTasks.size === this.maxConcurrency) {
12
+ await Promise.race(Array.from(this.activeTasks.values()));
13
+ }
14
+ return this.executeTask(task);
15
+ }
16
+
17
+ private executeTask(task: AsyncTask<T>) {
18
+ const ID = this.IDs.get();
19
+ const promise = task();
20
+ this.activeTasks.set(ID, promise);
21
+ void promise.finally(() => this.activeTasks.delete(ID));
22
+ return promise;
23
+ }
24
+ }
@@ -2,16 +2,18 @@ import { parseArgs } from "node:util";
2
2
  import { join } from "node:path";
3
3
  import { existsSync } from "node:fs";
4
4
 
5
+ import { TSCompiler } from "./TSCompiler";
5
6
  import { RepoKitConfig } from "./RepoKitConfig";
6
7
 
7
- export class ConfigurationParser {
8
+ export class ConfigurationParser extends TSCompiler {
8
9
  public static async parse() {
9
10
  const root = this.parseRoot();
10
11
  const path = join(root, "repokit.ts");
11
12
  if (!existsSync(path)) {
12
13
  return;
13
14
  }
14
- const config = await import(path);
15
+ const compiler = new TSCompiler(root, "parse_configuration");
16
+ const config = await compiler.compile(path);
15
17
  for (const key in config) {
16
18
  if (config[key] instanceof RepoKitConfig) {
17
19
  return console.log(JSON.stringify(config[key].toScoped(path)));
@@ -0,0 +1,26 @@
1
+ import { basename, resolve } from "node:path";
2
+ import { readFile, rm, writeFile } from "node:fs/promises";
3
+
4
+ import { transform } from "@swc/core";
5
+
6
+ export class TSCompiler {
7
+ private static readonly TMP_FILE_NAME = ".repokit_tmp.js";
8
+ constructor(
9
+ public readonly root: string,
10
+ public readonly command: string,
11
+ ) {}
12
+
13
+ public async compile(path: string) {
14
+ const source = (await readFile(path)).toString();
15
+ const result = await transform(source, {
16
+ module: {
17
+ type: "es6",
18
+ },
19
+ });
20
+ const target = `${resolve(path, "../")}/${basename(path)}${TSCompiler.TMP_FILE_NAME}`;
21
+ await writeFile(target, result.code);
22
+ const config = await import(target);
23
+ await rm(target, { force: true });
24
+ return config;
25
+ }
26
+ }
@@ -1,20 +1,16 @@
1
1
 
2
2
  CWD=$(pwd)
3
3
 
4
- MODULE_DIRECTORY="node_modules"
5
-
6
- if [[ "$CWD" != *"$MODULE_DIRECTORY"* ]]; then
7
- yarn symlink;
8
- exit 0;
9
- fi
10
-
11
4
  REPLACEMENT="/node_modules"
12
5
  FALLBACK_ROOT="${CWD%${REPLACEMENT}*}"
13
6
 
14
- SCRIPT_ORIGIN=$(pwd)
15
7
  GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
16
8
  REPO_ROOT=${GIT_ROOT:-$FALLBACK_ROOT}
17
9
 
10
+ if [[ "$CWD" != *"$REPLACEMENT"* ]]; then
11
+ exit 0;
12
+ fi
13
+
18
14
 
19
15
  cd $REPO_ROOT
20
16
 
@@ -29,28 +25,11 @@ else
29
25
  curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
30
26
  fi
31
27
 
32
- if npm list --depth=0 tsx; then
33
- echo "Found tsx installation"
34
- else
35
- # Node Dependencies installation
36
- if [ -f "${REPO_ROOT}/yarn.lock" ]; then
37
- yarn global add tsx
38
- elif [ -f "${REPO_ROOT}/pnpm-lock.yaml" ]; then
39
- pnpm add -g tsx
40
- elif [ -f "${REPO_ROOT}/package-lock.json" ]; then
41
- npm i -g tsx
42
- else
43
- echo "No node.js package manager detected"
44
- echo "Run npm init to create your node.js project"
45
- fi
46
- fi
47
-
48
-
49
28
  echo "Installing Repokit CLI"
50
29
 
51
- cd $SCRIPT_ORIGIN
30
+ cd $CWD
52
31
 
53
- echo "Compiling from $SCRIPT_ORIGIN"
32
+ echo "Compiling from $CWD"
54
33
 
55
34
  . "$HOME/.cargo/env"
56
35
  RUSTFLAGS="-Awarnings" cargo build --release
@@ -12,11 +12,18 @@ impl Configuration {
12
12
  let file_path = format!("{root}/repokit.ts");
13
13
  let path = Path::new(&file_path);
14
14
  if path.exists() {
15
- return;
15
+ Logger::info(
16
+ format!(
17
+ "I found a Repokit configuration without an exported {} instance",
18
+ Logger::blue("RepokitConfig")
19
+ )
20
+ .as_str(),
21
+ );
22
+ return Logger::exit_with_info("Please create an instance and export it");
16
23
  }
17
24
  Configuration::welcome();
18
25
  let mut source =
19
- InternalFileSystem::new(root).resolve_template("configuration_template.ts");
26
+ InternalFileSystem::new(root).resolve_template("configuration_template.txt");
20
27
  let mut target = FileBuilder::create(path, |_| Logger::file_create_error());
21
28
  FileBuilder::copy_to(&mut source, &mut target, |_| Logger::file_write_error());
22
29
  Logger::info(
@@ -19,14 +19,10 @@ impl ParallelVisitor for TSFileVisitor {
19
19
  let root_replacer = format!("{}/", self.root);
20
20
  let repokit_import_matcher =
21
21
  Regex::new(r#"(require\(|from[\s*]?)['"]@repokit/core["'][\)]?[;]?$"#).unwrap();
22
- let template_matcher = Regex::new(r"externals\/templates\/[^\s]*?_template\.ts$").unwrap();
23
22
  if let Ok(entry) = entry {
24
23
  let path = entry.path();
25
24
  let path_string = path.to_str().map_or("", |f| f);
26
- if entry.file_type().is_some_and(|ft| ft.is_file())
27
- && path_string.ends_with(".ts")
28
- && !template_matcher.is_match(path_string)
29
- {
25
+ if entry.file_type().is_some_and(|ft| ft.is_file()) && path_string.ends_with(".ts") {
30
26
  let mut open_comment = false;
31
27
  let file: File = FileBuilder::open(path_string, |_| Logger::open_file_error());
32
28
  let reader: BufReader<File> = BufReader::new(file);
@@ -89,7 +89,7 @@ impl InternalExecutable for RegisterCommand {
89
89
  Logger::info("Registering a new command");
90
90
  let command_path = self.validate_path(args);
91
91
  let mut source =
92
- InternalFileSystem::new(&self.scope.root).resolve_template("command_template.ts");
92
+ InternalFileSystem::new(&self.scope.root).resolve_template("command_template.txt");
93
93
  let mut target = FileBuilder::create(&command_path, |_| Logger::file_create_error());
94
94
  FileBuilder::copy_to(&mut source, &mut target, |_| Logger::file_write_error());
95
95
  Logger::info("Creating command file");
@@ -22,8 +22,7 @@ impl TypescriptCommand {
22
22
  }
23
23
 
24
24
  pub fn parse_configuration(&self) -> RepoKitConfig {
25
- let executable =
26
- InternalFileSystem::new(&self.root).resolve_command("parse_configuration.ts");
25
+ let executable = InternalFileSystem::new(&self.root).resolve_command("parse_configuration");
27
26
  let stdout = self.execute(format!("{executable} --root {}", &self.root).as_str());
28
27
  if stdout.is_empty() {
29
28
  Configuration::create(&self.root);
@@ -34,7 +33,7 @@ impl TypescriptCommand {
34
33
 
35
34
  pub fn parse_commands(&self, path_list: &MutexGuard<Vec<String>>) -> Vec<RepoKitCommand> {
36
35
  let paths = path_list.join(",");
37
- let executable = InternalFileSystem::new(&self.root).resolve_command("parse_commands.ts");
36
+ let executable = InternalFileSystem::new(&self.root).resolve_command("parse_commands");
38
37
  let stdout =
39
38
  self.execute(format!("{executable} --paths {paths} --root {}", self.root).as_str());
40
39
  let result: Result<Vec<RepoKitCommand>, serde_json::Error> = serde_json::from_str(&stdout);
@@ -52,7 +51,7 @@ impl TypescriptCommand {
52
51
  }
53
52
 
54
53
  fn execute(&self, args: &str) -> String {
55
- Executor::exec(format!("npx tsx {args}"), |cmd| {
54
+ Executor::exec(format!("node {args}"), |cmd| {
56
55
  cmd.current_dir(Path::new(&self.root))
57
56
  })
58
57
  }
@@ -25,8 +25,11 @@ impl InternalFileSystem {
25
25
  path.join(segment).normalize()
26
26
  }
27
27
 
28
- pub fn resolve_command(&self, file_name: &str) -> String {
29
- self.path_buf_to_str(self.commands_directory().join(file_name))
28
+ pub fn resolve_command(&self, command_name: &str) -> String {
29
+ self.path_buf_to_str(
30
+ self.commands_directory()
31
+ .join(format!("{command_name}.mjs")),
32
+ )
30
33
  }
31
34
 
32
35
  pub fn resolve_template(&self, file_name: &str) -> File {
@@ -56,15 +59,15 @@ impl InternalFileSystem {
56
59
  }
57
60
 
58
61
  fn commands_directory(&self) -> PathBuf {
59
- self.absolute(format!("{}/commands", self.package_directory()).as_str())
62
+ self.absolute(format!("{}/dist/commands", self.package_directory()).as_str())
60
63
  }
61
64
 
62
65
  fn templates_directory(&self) -> PathBuf {
63
- self.absolute(format!("{}/templates", self.package_directory()).as_str())
66
+ self.absolute(format!("{}/externals/templates", self.package_directory()).as_str())
64
67
  }
65
68
 
66
69
  fn package_directory(&self) -> String {
67
- format!("./node_modules/{}/externals", self.package_name())
70
+ format!("./node_modules/{}", self.package_name())
68
71
  }
69
72
 
70
73
  fn package_name(&self) -> String {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@repokit/core",
3
- "version": "1.3.7",
3
+ "version": "1.6.0",
4
4
  "description": "A knowledgebase for your repository - wrapped in a CLI",
5
5
  "keywords": [
6
6
  "cli",
@@ -15,31 +15,48 @@
15
15
  "type": "git",
16
16
  "url": "git+https://github.com/alexfigliolia/repokit.git"
17
17
  },
18
- "main": "externals/index.ts",
18
+ "files": [
19
+ "media",
20
+ "dist",
21
+ "externals",
22
+ "internals",
23
+ "installation",
24
+ "Cargo.lock",
25
+ "Cargo.toml"
26
+ ],
27
+ "main": "./dist/index.mjs",
28
+ "module": "./dist/index.mjs",
29
+ "types": "./dist/index.d.mjs",
19
30
  "publishConfig": {
20
31
  "access": "public"
21
32
  },
22
33
  "scripts": {
23
34
  "build:all": "yarn lint:ts && yarn lint:rust && yarn install:rust",
24
35
  "build:rust": "cargo build --release",
36
+ "build:ts": "tsx devserver/run.ts",
37
+ "clean:ts": "tsx devserver/run.ts -c",
25
38
  "grant:exec": "chmod -R +x ./installation",
26
39
  "install:rust": "yarn build:rust && cargo install --path .",
27
40
  "lint:rust": "cargo clippy --fix --allow-dirty",
28
41
  "lint:ts": "yarn oxlint --type-aware --type-check --report-unused-disable-directives --fix && yarn oxfmt",
42
+ "package:ts": "yarn lint:ts && yarn lint:rust && yarn build:ts",
29
43
  "postinstall": "yarn grant:exec && ./installation/install.sh",
30
44
  "repokit": "yarn install:rust && repokit",
31
- "run:dev": "yarn symlink && cargo run --package repokit --bin repokit",
32
- "symlink": "yarn grant:exec && ./installation/symlink.sh"
45
+ "run:dev": "yarn build:ts && cargo run --package repokit --bin repokit",
46
+ "watch:ts": "tsx devserver/run.ts -w"
33
47
  },
34
48
  "dependencies": {
35
- "@figliolia/event-emitter": "^1.1.6",
36
- "tsx": "^4.21.0"
49
+ "@figliolia/event-emitter": "^1.2.0",
50
+ "@swc/core": "^1.15.18"
37
51
  },
38
52
  "devDependencies": {
39
- "@types/node": "^25.2.1",
40
- "oxfmt": "^0.33.0",
53
+ "@figliolia/child-process": "^1.0.4",
54
+ "@types/node": "^25.3.0",
55
+ "oxfmt": "^0.34.0",
41
56
  "oxlint": "^1.42.0",
42
57
  "oxlint-tsgolint": "^0.14.0",
58
+ "tsdown": "^0.20.3",
59
+ "tsx": "^4.21.0",
43
60
  "typescript": "^5.9.3"
44
61
  }
45
62
  }
@@ -1,31 +0,0 @@
1
- import { AutoIncrementingID } from "@figliolia/event-emitter";
2
-
3
- import type { AsyncTask } from "./types";
4
-
5
- export class TaskPooler<T> {
6
- private readonly IDs = new AutoIncrementingID();
7
- private readonly runningTasks = new Map<string, Promise<T>>();
8
- constructor(public maxSize = 10) {}
9
-
10
- public enqueue(task: AsyncTask<T>) {
11
- return new Promise<T>(resolve => {
12
- if (this.runningTasks.size < 10) {
13
- return resolve(this.indexRunningTask(task));
14
- }
15
- resolve(this.indexBehindNextOpening(task));
16
- });
17
- }
18
-
19
- private indexRunningTask(task: AsyncTask<T>) {
20
- const ID = this.IDs.get();
21
- const promise = task();
22
- this.runningTasks.set(ID, promise);
23
- void promise.finally(() => this.runningTasks.delete(ID));
24
- return promise;
25
- }
26
-
27
- private async indexBehindNextOpening(task: AsyncTask<T>) {
28
- await Promise.race(this.runningTasks.values());
29
- return this.indexRunningTask(task);
30
- }
31
- }