@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.
- package/dist/CommandParser.d.mts +9 -0
- package/dist/CommandParser.mjs +55 -0
- package/dist/ConcurrencyPool.d.mts +13 -0
- package/dist/ConcurrencyPool.mjs +24 -0
- package/dist/ConfigurationParser.d.mts +9 -0
- package/dist/ConfigurationParser.mjs +27 -0
- package/dist/RepoKitCommand.d.mts +17 -0
- package/dist/RepoKitCommand.mjs +16 -0
- package/dist/RepoKitConfig.d.mts +25 -0
- package/dist/RepoKitConfig.mjs +25 -0
- package/dist/TSCompiler.d.mts +9 -0
- package/dist/TSCompiler.mjs +20 -0
- package/dist/commands/parse_commands.d.mts +1 -0
- package/dist/commands/parse_commands.mjs +9 -0
- package/dist/commands/parse_configuration.d.mts +1 -0
- package/dist/commands/parse_configuration.mjs +9 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.mjs +4 -0
- package/dist/templates/command_template.mjs +5 -0
- package/dist/templates/configuration_template.mjs +5 -0
- package/dist/types.d.mts +25 -0
- package/dist/types.mjs +1 -0
- package/externals/CommandParser.ts +10 -9
- package/externals/ConcurrencyPool.ts +24 -0
- package/externals/ConfigurationParser.ts +4 -2
- package/externals/TSCompiler.ts +26 -0
- package/installation/install.sh +6 -27
- package/internals/configuration/configuration.rs +9 -2
- package/internals/file_walker/walker.rs +1 -5
- package/internals/internal_commands/register_command.rs +1 -1
- package/internals/internal_commands/typescript_command.rs +3 -4
- package/internals/internal_filesystem/internal_filesystem.rs +8 -5
- package/package.json +25 -8
- package/externals/TaskPooler.ts +0 -31
- /package/externals/templates/{command_template.ts → command_template.txt} +0 -0
- /package/externals/templates/{configuration_template.ts → configuration_template.txt} +0 -0
|
@@ -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,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 @@
|
|
|
1
|
+
export { };
|
package/dist/index.d.mts
ADDED
|
@@ -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,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 };
|
package/dist/types.d.mts
ADDED
|
@@ -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 {
|
|
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
|
|
19
|
-
|
|
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(
|
|
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
|
|
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
|
|
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
|
+
}
|
package/installation/install.sh
CHANGED
|
@@ -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 $
|
|
30
|
+
cd $CWD
|
|
52
31
|
|
|
53
|
-
echo "Compiling from $
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
|
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!("
|
|
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,
|
|
29
|
-
self.path_buf_to_str(
|
|
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/{}
|
|
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
|
+
"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
|
-
"
|
|
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
|
|
32
|
-
"
|
|
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.
|
|
36
|
-
"
|
|
49
|
+
"@figliolia/event-emitter": "^1.2.0",
|
|
50
|
+
"@swc/core": "^1.15.18"
|
|
37
51
|
},
|
|
38
52
|
"devDependencies": {
|
|
39
|
-
"@
|
|
40
|
-
"
|
|
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
|
}
|
package/externals/TaskPooler.ts
DELETED
|
@@ -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
|
-
}
|
|
File without changes
|
|
File without changes
|