@g3nomaly/mods 0.0.0-stage → 0.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 +95 -0
- package/README.md +95 -2
- package/dist/cli/commands/add.d.ts +15 -0
- package/dist/cli/commands/add.d.ts.map +1 -0
- package/dist/cli/commands/add.js +25 -0
- package/dist/cli/commands/add.js.map +1 -0
- package/dist/cli/commands/init.d.ts +13 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +24 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/ls.d.ts +12 -0
- package/dist/cli/commands/ls.d.ts.map +1 -0
- package/dist/cli/commands/ls.js +20 -0
- package/dist/cli/commands/ls.js.map +1 -0
- package/dist/cli/commands/remove.d.ts +12 -0
- package/dist/cli/commands/remove.d.ts.map +1 -0
- package/dist/cli/commands/remove.js +28 -0
- package/dist/cli/commands/remove.js.map +1 -0
- package/dist/cli/commands/source.d.ts +29 -0
- package/dist/cli/commands/source.d.ts.map +1 -0
- package/dist/cli/commands/source.js +30 -0
- package/dist/cli/commands/source.js.map +1 -0
- package/dist/cli/commands/update.d.ts +12 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.js +13 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +95 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/project.d.ts +49 -0
- package/dist/cli/project.d.ts.map +1 -0
- package/dist/cli/project.js +58 -0
- package/dist/cli/project.js.map +1 -0
- package/dist/cli/viewer.d.ts +11 -0
- package/dist/cli/viewer.d.ts.map +1 -0
- package/dist/cli/viewer.js +32 -0
- package/dist/cli/viewer.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/registry/index.d.ts +7 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +7 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/locate.d.ts +16 -0
- package/dist/registry/locate.d.ts.map +1 -0
- package/dist/registry/locate.js +41 -0
- package/dist/registry/locate.js.map +1 -0
- package/dist/registry/manifest.d.ts +8 -0
- package/dist/registry/manifest.d.ts.map +1 -0
- package/dist/registry/manifest.js +13 -0
- package/dist/registry/manifest.js.map +1 -0
- package/dist/registry/readModDir.d.ts +20 -0
- package/dist/registry/readModDir.d.ts.map +1 -0
- package/dist/registry/readModDir.js +79 -0
- package/dist/registry/readModDir.js.map +1 -0
- package/dist/registry/readSource.d.ts +9 -0
- package/dist/registry/readSource.d.ts.map +1 -0
- package/dist/registry/readSource.js +27 -0
- package/dist/registry/readSource.js.map +1 -0
- package/dist/registry/types.d.ts +54 -0
- package/dist/registry/types.d.ts.map +1 -0
- package/dist/registry/types.js +20 -0
- package/dist/registry/types.js.map +1 -0
- package/dist/sources/builtins.d.ts +4 -0
- package/dist/sources/builtins.d.ts.map +1 -0
- package/dist/sources/builtins.js +5 -0
- package/dist/sources/builtins.js.map +1 -0
- package/dist/sources/index.d.ts +2 -0
- package/dist/sources/index.d.ts.map +1 -0
- package/dist/sources/index.js +3 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/viewer/extension.d.ts +18 -0
- package/dist/viewer/extension.d.ts.map +1 -0
- package/dist/viewer/extension.js +43 -0
- package/dist/viewer/extension.js.map +1 -0
- package/dist/viewer/index.d.ts +5 -0
- package/dist/viewer/index.d.ts.map +1 -0
- package/dist/viewer/index.js +4 -0
- package/dist/viewer/index.js.map +1 -0
- package/dist/viewer/settings.d.ts +31 -0
- package/dist/viewer/settings.d.ts.map +1 -0
- package/dist/viewer/settings.js +44 -0
- package/dist/viewer/settings.js.map +1 -0
- package/package.json +37 -4
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { resolveProjectRoot } from "@g3nomaly/core/config";
|
|
3
|
+
import type { InstallCommandContext, ManifestTarget } from "@g3nomaly/core/cli";
|
|
4
|
+
import type { SourceRegistry } from "@g3nomaly/core/installer";
|
|
5
|
+
import type { RegisteredSource } from "@g3nomaly/core/sources";
|
|
6
|
+
import type { ModMeta, ModRegistry } from "../registry/types";
|
|
7
|
+
/** `project` installs into the repository's `.claude/`, `user` into `~/.claude/` for every project. */
|
|
8
|
+
export declare const ScopeSchema: z.ZodEnum<{
|
|
9
|
+
project: "project";
|
|
10
|
+
user: "user";
|
|
11
|
+
}>;
|
|
12
|
+
export type Scope = z.infer<typeof ScopeSchema>;
|
|
13
|
+
/**
|
|
14
|
+
* One install scope opened for a command: where mods go, the `mods.json`
|
|
15
|
+
* that records them, and the root that sources resolve against.
|
|
16
|
+
*/
|
|
17
|
+
export interface ModProject {
|
|
18
|
+
scope: Scope;
|
|
19
|
+
/** Absolute root for local source paths and the `node_modules` lookup: the git project, or home for `user` outside one */
|
|
20
|
+
projectRoot: string;
|
|
21
|
+
/** Absolute `.claude/` directory of the scope */
|
|
22
|
+
claudeDir: string;
|
|
23
|
+
/** The one install destination with the `mods.json` that backs it */
|
|
24
|
+
target: ManifestTarget;
|
|
25
|
+
}
|
|
26
|
+
/** Injection point for tests; the real project root comes from git discovery. */
|
|
27
|
+
export interface ProjectDeps {
|
|
28
|
+
resolveProjectRoot?: typeof resolveProjectRoot;
|
|
29
|
+
home?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Opens the scope's `.claude/` directory and its `mods.json`. Exits with an
|
|
33
|
+
* error when the project scope is asked for outside a git repository.
|
|
34
|
+
*/
|
|
35
|
+
export declare function openModProject(scope: Scope, deps?: ProjectDeps): ModProject;
|
|
36
|
+
/** Built-in sources first, then the ones registered in this scope's `mods.json`. */
|
|
37
|
+
export declare function modSources(project: ModProject): RegisteredSource[];
|
|
38
|
+
/** What the core install and source commands print and check for mods. */
|
|
39
|
+
export declare const MOD_CONTEXT: InstallCommandContext<ModMeta>;
|
|
40
|
+
/** Installed mods of the scope. */
|
|
41
|
+
export declare function installedMods(project: ModProject): ModRegistry;
|
|
42
|
+
/**
|
|
43
|
+
* Reads every mod the scope's sources provide, or only those of `only`, and
|
|
44
|
+
* prints each warning. The caller disposes the result when done.
|
|
45
|
+
*
|
|
46
|
+
* @param only - Source name to read alone; exits when no such source is registered
|
|
47
|
+
*/
|
|
48
|
+
export declare function openModRegistry(project: ModProject, only?: string): Promise<SourceRegistry<ModMeta>>;
|
|
49
|
+
//# sourceMappingURL=project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/cli/project.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEhF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAI/D,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAG9D,uGAAuG;AACvG,eAAO,MAAM,WAAW;;;EAA8B,CAAC;AAEvD,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAKhD;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAQ,KAAK,CAAC;IACnB,0HAA0H;IAC1H,WAAW,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,SAAS,EAAI,MAAM,CAAC;IACpB,qEAAqE;IACrE,MAAM,EAAO,cAAc,CAAC;CAC7B;AAED,iFAAiF;AACjF,MAAM,WAAW,WAAW;IAC1B,kBAAkB,CAAC,EAAE,OAAO,kBAAkB,CAAC;IAC/C,IAAI,CAAC,EAAgB,MAAM,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,GAAE,WAAgB,GAAG,UAAU,CAiB/E;AAED,oFAAoF;AACpF,wBAAgB,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,gBAAgB,EAAE,CAElE;AAED,0EAA0E;AAC1E,eAAO,MAAM,WAAW,EAAE,qBAAqB,CAAC,OAAO,CAAgE,CAAC;AAExH,mCAAmC;AACnC,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,GAAG,WAAW,CAE9D;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAI1G"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// packages/mods/src/cli/project.ts
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { resolveProjectRoot } from "@g3nomaly/core/config";
|
|
6
|
+
import { lineError, narrowSources, orExit, reportSourceRegistry } from "@g3nomaly/core/cli";
|
|
7
|
+
import { installedEntries, loadInstallManifest, loadSourceRegistry, manifestSources } from "@g3nomaly/core/installer";
|
|
8
|
+
import { modsManifestPath } from "../registry/manifest";
|
|
9
|
+
import { readModSource } from "../registry/readSource";
|
|
10
|
+
import { ModMetaSchema } from "../registry/types";
|
|
11
|
+
import { BUILTIN_SOURCES } from "../sources/builtins";
|
|
12
|
+
/** `project` installs into the repository's `.claude/`, `user` into `~/.claude/` for every project. */
|
|
13
|
+
export const ScopeSchema = z.enum(["project", "user"]);
|
|
14
|
+
/** Folder under `.claude/` that Claude Code auto-loads plugins from, as `<name>@skills-dir`. */
|
|
15
|
+
const INSTALL_DIR = "skills";
|
|
16
|
+
/**
|
|
17
|
+
* Opens the scope's `.claude/` directory and its `mods.json`. Exits with an
|
|
18
|
+
* error when the project scope is asked for outside a git repository.
|
|
19
|
+
*/
|
|
20
|
+
export function openModProject(scope, deps = {}) {
|
|
21
|
+
const home = deps.home ?? os.homedir();
|
|
22
|
+
const found = (deps.resolveProjectRoot ?? resolveProjectRoot)();
|
|
23
|
+
if (scope === "project" && found === null) {
|
|
24
|
+
console.error(lineError("No project found — run g3n-mods inside a git repository, or pass --user to install for every project."));
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
const projectRoot = found ?? home;
|
|
28
|
+
const claudeDir = path.join(scope === "user" ? home : projectRoot, ".claude");
|
|
29
|
+
const manifest = orExit(() => loadInstallManifest(modsManifestPath(claudeDir), ModMetaSchema));
|
|
30
|
+
return {
|
|
31
|
+
scope,
|
|
32
|
+
projectRoot,
|
|
33
|
+
claudeDir,
|
|
34
|
+
target: { label: scope, installDir: path.join(claudeDir, INSTALL_DIR), store: manifest.store, manifest },
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** Built-in sources first, then the ones registered in this scope's `mods.json`. */
|
|
38
|
+
export function modSources(project) {
|
|
39
|
+
return manifestSources([project.target.manifest], BUILTIN_SOURCES);
|
|
40
|
+
}
|
|
41
|
+
/** What the core install and source commands print and check for mods. */
|
|
42
|
+
export const MOD_CONTEXT = { bin: "g3n-mods", noun: "mod", entrySchema: ModMetaSchema };
|
|
43
|
+
/** Installed mods of the scope. */
|
|
44
|
+
export function installedMods(project) {
|
|
45
|
+
return installedEntries(project.target.manifest, ModMetaSchema);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Reads every mod the scope's sources provide, or only those of `only`, and
|
|
49
|
+
* prints each warning. The caller disposes the result when done.
|
|
50
|
+
*
|
|
51
|
+
* @param only - Source name to read alone; exits when no such source is registered
|
|
52
|
+
*/
|
|
53
|
+
export async function openModRegistry(project, only) {
|
|
54
|
+
const registry = await loadSourceRegistry(narrowSources(modSources(project), only, "g3n-mods"), project.projectRoot, readModSource);
|
|
55
|
+
reportSourceRegistry(registry);
|
|
56
|
+
return registry;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/cli/project.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ViewerLocation } from "../viewer";
|
|
2
|
+
import type { ModProject } from "./project";
|
|
3
|
+
/**
|
|
4
|
+
* Sets up where mods are seen and prints what it found: the project's VS
|
|
5
|
+
* Code settings (project scope only) and the installed extension's version
|
|
6
|
+
* against the one the mod API needs.
|
|
7
|
+
*
|
|
8
|
+
* @param location - Where Claude opens; when absent, a location already set is kept
|
|
9
|
+
*/
|
|
10
|
+
export declare function setUpViewer(project: ModProject, location?: ViewerLocation): void;
|
|
11
|
+
//# sourceMappingURL=viewer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewer.d.ts","sourceRoot":"","sources":["../../src/cli/viewer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,IAAI,CAkBhF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// packages/mods/src/cli/viewer.ts
|
|
2
|
+
import { c, lineInfo, lineSuccess, lineWarn } from "@g3nomaly/core/cli";
|
|
3
|
+
import { MIN_ENGINE_VERSION, compareVersions, configureViewer, findClaudeExtension } from "../viewer";
|
|
4
|
+
/**
|
|
5
|
+
* Sets up where mods are seen and prints what it found: the project's VS
|
|
6
|
+
* Code settings (project scope only) and the installed extension's version
|
|
7
|
+
* against the one the mod API needs.
|
|
8
|
+
*
|
|
9
|
+
* @param location - Where Claude opens; when absent, a location already set is kept
|
|
10
|
+
*/
|
|
11
|
+
export function setUpViewer(project, location) {
|
|
12
|
+
if (project.scope === "project") {
|
|
13
|
+
const result = configureViewer(project.projectRoot, location);
|
|
14
|
+
if (result.kind === "written") {
|
|
15
|
+
console.log(lineSuccess(`VS Code opens Claude in its native UI ${c.dim(`(${c.file(result.file)})`)}`));
|
|
16
|
+
}
|
|
17
|
+
else if (result.kind === "unreadable") {
|
|
18
|
+
console.log(lineWarn(`${c.file(result.file)} is not plain JSON — add these settings by hand: ${JSON.stringify(result.settings)}`));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const extension = findClaudeExtension();
|
|
22
|
+
if (extension === null) {
|
|
23
|
+
console.log(lineWarn(`Claude Code for VS Code is not installed — mods draw in its native UI. Install it from the marketplace (anthropic.claude-code), ${MIN_ENGINE_VERSION} or newer.`));
|
|
24
|
+
}
|
|
25
|
+
else if (compareVersions(extension.version, MIN_ENGINE_VERSION) < 0) {
|
|
26
|
+
console.log(lineWarn(`Claude Code for VS Code is ${extension.version}; mods need ${MIN_ENGINE_VERSION} or newer. Update the extension.`));
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
console.log(lineInfo(`Claude Code for VS Code ${extension.version} draws mod panes. Run ${c.cmd("Claude Code: Open in New Window")} to give them a window of their own.`));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=viewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewer.js","sourceRoot":"","sources":["../../src/cli/viewer.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAItG;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,OAAmB,EAAE,QAAyB;IACxE,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC9D,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,yCAAyC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QACzG,CAAC;aAAM,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oDAAoD,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;QACrI,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,mBAAmB,EAAE,CAAC;IACxC,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,mIAAmI,kBAAkB,YAAY,CAAC,CAAC,CAAC;IAC3L,CAAC;SAAM,IAAI,eAAe,CAAC,SAAS,CAAC,OAAO,EAAE,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,8BAA8B,SAAS,CAAC,OAAO,eAAe,kBAAkB,kCAAkC,CAAC,CAAC,CAAC;IAC5I,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,2BAA2B,SAAS,CAAC,OAAO,yBAAyB,CAAC,CAAC,GAAG,CAAC,iCAAiC,CAAC,sCAAsC,CAAC,CAAC,CAAC;IAC7K,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from "./types";
|
|
2
|
+
export { isModDir, readModDir, PLUGIN_MANIFEST, HOOKS_MANIFEST } from "./readModDir";
|
|
3
|
+
export { locateMods } from "./locate";
|
|
4
|
+
export type { ModScan } from "./locate";
|
|
5
|
+
export { readModSource } from "./readSource";
|
|
6
|
+
export { modsManifestPath } from "./manifest";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AACA,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// packages/mods/src/registry/index.ts
|
|
2
|
+
export * from "./types";
|
|
3
|
+
export { isModDir, readModDir, PLUGIN_MANIFEST, HOOKS_MANIFEST } from "./readModDir";
|
|
4
|
+
export { locateMods } from "./locate";
|
|
5
|
+
export { readModSource } from "./readSource";
|
|
6
|
+
export { modsManifestPath } from "./manifest";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** The mod folders found in one source checkout, with what was skipped and why. */
|
|
2
|
+
export interface ModScan {
|
|
3
|
+
/** Absolute mod folders */
|
|
4
|
+
dirs: string[];
|
|
5
|
+
warnings: string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Finds the mods a source provides. A `marketplace.json` lists them by
|
|
9
|
+
* relative path; without one, the source root is the mod when it is one,
|
|
10
|
+
* else every mod folder directly under `mods/` or the root. Plugins that
|
|
11
|
+
* hold no hooks module are skipped with a warning.
|
|
12
|
+
*
|
|
13
|
+
* @param root - Absolute root of the source checkout
|
|
14
|
+
*/
|
|
15
|
+
export declare function locateMods(root: string): ModScan;
|
|
16
|
+
//# sourceMappingURL=locate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locate.d.ts","sourceRoot":"","sources":["../../src/registry/locate.ts"],"names":[],"mappings":"AAQA,mFAAmF;AACnF,MAAM,WAAW,OAAO;IACtB,2BAA2B;IAC3B,IAAI,EAAM,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAUD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAgBhD"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// packages/mods/src/registry/locate.ts
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { readMarketplace } from "@g3nomaly/core/installer";
|
|
5
|
+
import { isModDir } from "./readModDir";
|
|
6
|
+
const MODS_DIR = "mods";
|
|
7
|
+
/** Direct child folders of `dir`, leaving out hidden ones and `node_modules`. */
|
|
8
|
+
function childDirs(dir) {
|
|
9
|
+
if (!fs.existsSync(dir))
|
|
10
|
+
return [];
|
|
11
|
+
return fs.readdirSync(dir, { withFileTypes: true })
|
|
12
|
+
.filter((d) => d.isDirectory() && !d.name.startsWith(".") && d.name !== "node_modules")
|
|
13
|
+
.map((d) => path.join(dir, d.name));
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Finds the mods a source provides. A `marketplace.json` lists them by
|
|
17
|
+
* relative path; without one, the source root is the mod when it is one,
|
|
18
|
+
* else every mod folder directly under `mods/` or the root. Plugins that
|
|
19
|
+
* hold no hooks module are skipped with a warning.
|
|
20
|
+
*
|
|
21
|
+
* @param root - Absolute root of the source checkout
|
|
22
|
+
*/
|
|
23
|
+
export function locateMods(root) {
|
|
24
|
+
const marketplace = readMarketplace(root);
|
|
25
|
+
if (marketplace !== null) {
|
|
26
|
+
const warnings = [...marketplace.warnings];
|
|
27
|
+
const dirs = [];
|
|
28
|
+
for (const plugin of marketplace.plugins) {
|
|
29
|
+
if (isModDir(plugin.dir))
|
|
30
|
+
dirs.push(plugin.dir);
|
|
31
|
+
else
|
|
32
|
+
warnings.push(`${plugin.name}: a plugin without a hooks module, not a mod, skipped`);
|
|
33
|
+
}
|
|
34
|
+
return { dirs: dirs.sort(), warnings };
|
|
35
|
+
}
|
|
36
|
+
if (isModDir(root))
|
|
37
|
+
return { dirs: [root], warnings: [] };
|
|
38
|
+
const dirs = [...childDirs(path.join(root, MODS_DIR)), ...childDirs(root)].filter(isModDir);
|
|
39
|
+
return { dirs: [...new Set(dirs)].sort(), warnings: [] };
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=locate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locate.js","sourceRoot":"","sources":["../../src/registry/locate.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,MAAM,QAAQ,GAAG,MAAM,CAAC;AASxB,iFAAiF;AACjF,SAAS,SAAS,CAAC,GAAW;IAC5B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,OAAO,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;SAChD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC;SACtF,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,WAAW,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,KAAK,MAAM,MAAM,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;YACzC,IAAI,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;;gBAC3C,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,uDAAuD,CAAC,CAAC;QAC5F,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC;IACzC,CAAC;IAED,IAAI,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAE1D,MAAM,IAAI,GAAG,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5F,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path of `mods.json` in a Claude directory.
|
|
3
|
+
*
|
|
4
|
+
* @param claudeDir - Absolute `.claude` directory of the scope, e.g. `/home/me/app/.claude`
|
|
5
|
+
* @returns absolute path
|
|
6
|
+
*/
|
|
7
|
+
export declare function modsManifestPath(claudeDir: string): string;
|
|
8
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/registry/manifest.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE1D"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// packages/mods/src/registry/manifest.ts
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const MANIFEST_FILE = "mods.json";
|
|
4
|
+
/**
|
|
5
|
+
* Path of `mods.json` in a Claude directory.
|
|
6
|
+
*
|
|
7
|
+
* @param claudeDir - Absolute `.claude` directory of the scope, e.g. `/home/me/app/.claude`
|
|
8
|
+
* @returns absolute path
|
|
9
|
+
*/
|
|
10
|
+
export function modsManifestPath(claudeDir) {
|
|
11
|
+
return path.join(claudeDir, MANIFEST_FILE);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/registry/manifest.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,aAAa,GAAG,WAAW,CAAC;AAElC;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IAChD,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ReadContext } from "@g3nomaly/core/installer";
|
|
2
|
+
import type { ModMeta } from "./types";
|
|
3
|
+
export declare const PLUGIN_MANIFEST: string;
|
|
4
|
+
export declare const HOOKS_MANIFEST: string;
|
|
5
|
+
/** Whether `dir` is a plugin with a `hooks/hooks.json`, which makes it a mod; `readModDir` checks the rest. */
|
|
6
|
+
export declare function isModDir(dir: string): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Reads one mod folder into its registry entry. The key is the folder name,
|
|
9
|
+
* which must equal the `name` in its `plugin.json`, the name Claude Code
|
|
10
|
+
* loads it under; every installable file becomes a `files[]` entry at
|
|
11
|
+
* `<key>/<file>`.
|
|
12
|
+
*
|
|
13
|
+
* @param modDir - Absolute mod folder inside a source checkout
|
|
14
|
+
* @param context - Origin to record, the source as group, and the version to fall back on
|
|
15
|
+
* @throws when the folder is not a mod, its manifests are invalid, its name
|
|
16
|
+
* differs from its folder, its hooks module is not TypeScript, or it holds
|
|
17
|
+
* any JavaScript file
|
|
18
|
+
*/
|
|
19
|
+
export declare function readModDir(modDir: string, context: ReadContext): Promise<[string, ModMeta]>;
|
|
20
|
+
//# sourceMappingURL=readModDir.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readModDir.d.ts","sourceRoot":"","sources":["../../src/registry/readModDir.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAwB,OAAO,EAAE,MAAM,SAAS,CAAC;AAE7D,eAAO,MAAM,eAAe,QAA6C,CAAC;AAC1E,eAAO,MAAM,cAAc,QAAoC,CAAC;AAsBhE,+GAA+G;AAC/G,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE7C;AAWD;;;;;;;;;;;GAWG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA8BjG"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// packages/mods/src/registry/readModDir.ts
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { hashFile } from "@g3nomaly/core/hash";
|
|
6
|
+
import { listFiles } from "@g3nomaly/core/installer";
|
|
7
|
+
export const PLUGIN_MANIFEST = path.join(".claude-plugin", "plugin.json");
|
|
8
|
+
export const HOOKS_MANIFEST = path.join("hooks", "hooks.json");
|
|
9
|
+
/** Folders and files a mod folder may hold that are never installed: tests, the engine's type output, build state. */
|
|
10
|
+
const SKIPPED_DIRS = ["tests", path.join(".claude-plugin", "types")];
|
|
11
|
+
const SKIPPED_FILES = /(\.test\.tsx?$)|(^tsconfig\.json$)|(^\.DS_Store$)/;
|
|
12
|
+
const PluginManifestSchema = z.object({
|
|
13
|
+
name: z.string().regex(/^[a-z0-9][a-z0-9-]*$/, "use lowercase letters, digits and `-`"),
|
|
14
|
+
version: z.string().min(1).optional(),
|
|
15
|
+
description: z.string().optional(),
|
|
16
|
+
});
|
|
17
|
+
/** JavaScript in any form; a mod holding one is refused. */
|
|
18
|
+
const JAVASCRIPT_FILE = /\.(?:js|mjs|cjs|jsx)$/i;
|
|
19
|
+
/** Hooks modules are TypeScript only. */
|
|
20
|
+
const TYPESCRIPT_MODULE = /\.(?:ts|tsx|mts|cts)$/i;
|
|
21
|
+
const HooksManifestSchema = z.object({
|
|
22
|
+
modules: z.array(z.string().regex(TYPESCRIPT_MODULE, "must be a TypeScript file (.ts, .tsx, .mts, .cts)")).min(1),
|
|
23
|
+
});
|
|
24
|
+
/** Whether `dir` is a plugin with a `hooks/hooks.json`, which makes it a mod; `readModDir` checks the rest. */
|
|
25
|
+
export function isModDir(dir) {
|
|
26
|
+
return fs.existsSync(path.join(dir, PLUGIN_MANIFEST)) && fs.existsSync(path.join(dir, HOOKS_MANIFEST));
|
|
27
|
+
}
|
|
28
|
+
/** Kind of a file by the folder it sits in inside the mod. */
|
|
29
|
+
function fileType(relativeToMod) {
|
|
30
|
+
const [top] = relativeToMod.split(path.sep);
|
|
31
|
+
if (top === ".claude-plugin")
|
|
32
|
+
return "manifest";
|
|
33
|
+
if (top === "hooks")
|
|
34
|
+
return "hooks";
|
|
35
|
+
if (top === "types")
|
|
36
|
+
return "types";
|
|
37
|
+
return "asset";
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Reads one mod folder into its registry entry. The key is the folder name,
|
|
41
|
+
* which must equal the `name` in its `plugin.json`, the name Claude Code
|
|
42
|
+
* loads it under; every installable file becomes a `files[]` entry at
|
|
43
|
+
* `<key>/<file>`.
|
|
44
|
+
*
|
|
45
|
+
* @param modDir - Absolute mod folder inside a source checkout
|
|
46
|
+
* @param context - Origin to record, the source as group, and the version to fall back on
|
|
47
|
+
* @throws when the folder is not a mod, its manifests are invalid, its name
|
|
48
|
+
* differs from its folder, its hooks module is not TypeScript, or it holds
|
|
49
|
+
* any JavaScript file
|
|
50
|
+
*/
|
|
51
|
+
export async function readModDir(modDir, context) {
|
|
52
|
+
if (!isModDir(modDir)) {
|
|
53
|
+
throw new Error(`${modDir} is not a mod: it needs ${PLUGIN_MANIFEST} and ${HOOKS_MANIFEST}`);
|
|
54
|
+
}
|
|
55
|
+
const manifest = PluginManifestSchema.parse(JSON.parse(fs.readFileSync(path.join(modDir, PLUGIN_MANIFEST), "utf8")));
|
|
56
|
+
HooksManifestSchema.parse(JSON.parse(fs.readFileSync(path.join(modDir, HOOKS_MANIFEST), "utf8")));
|
|
57
|
+
const key = path.basename(modDir);
|
|
58
|
+
if (manifest.name !== key) {
|
|
59
|
+
throw new Error(`plugin.json names it "${manifest.name}", but its folder is "${key}"; they must match`);
|
|
60
|
+
}
|
|
61
|
+
const rels = listFiles(modDir, { skipDirs: SKIPPED_DIRS, skipFiles: SKIPPED_FILES });
|
|
62
|
+
const javascript = rels.filter((rel) => JAVASCRIPT_FILE.test(rel));
|
|
63
|
+
if (javascript.length > 0) {
|
|
64
|
+
throw new Error(`holds JavaScript (${javascript.join(", ")}); mods are TypeScript only`);
|
|
65
|
+
}
|
|
66
|
+
const files = [];
|
|
67
|
+
for (const rel of rels) {
|
|
68
|
+
files.push({ path: path.join(key, rel), type: fileType(rel), hash: await hashFile(path.join(modDir, rel)) });
|
|
69
|
+
}
|
|
70
|
+
return [key, {
|
|
71
|
+
name: manifest.name,
|
|
72
|
+
description: manifest.description,
|
|
73
|
+
version: manifest.version ?? context.version,
|
|
74
|
+
group: context.group,
|
|
75
|
+
origin: context.origin,
|
|
76
|
+
files,
|
|
77
|
+
}];
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=readModDir.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readModDir.js","sourceRoot":"","sources":["../../src/registry/readModDir.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ReadSource } from "@g3nomaly/core/installer";
|
|
2
|
+
import type { ModMeta } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Reads every mod a checked-out source provides, with the source as group.
|
|
5
|
+
* An unreadable mod is skipped with a warning. Handed to
|
|
6
|
+
* `loadSourceRegistry` by every mods command.
|
|
7
|
+
*/
|
|
8
|
+
export declare const readModSource: ReadSource<ModMeta>;
|
|
9
|
+
//# sourceMappingURL=readSource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readSource.d.ts","sourceRoot":"","sources":["../../src/registry/readSource.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAI3D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,UAAU,CAAC,OAAO,CAgB7C,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// packages/mods/src/registry/readSource.ts
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { errorMessage } from "@g3nomaly/core/utils";
|
|
4
|
+
import { locateMods } from "./locate";
|
|
5
|
+
import { readModDir } from "./readModDir";
|
|
6
|
+
/**
|
|
7
|
+
* Reads every mod a checked-out source provides, with the source as group.
|
|
8
|
+
* An unreadable mod is skipped with a warning. Handed to
|
|
9
|
+
* `loadSourceRegistry` by every mods command.
|
|
10
|
+
*/
|
|
11
|
+
export const readModSource = async (checkout) => {
|
|
12
|
+
const { dirs, warnings } = locateMods(checkout.dir);
|
|
13
|
+
const entries = [];
|
|
14
|
+
for (const modDir of dirs) {
|
|
15
|
+
try {
|
|
16
|
+
entries.push(await readModDir(modDir, {
|
|
17
|
+
origin: { source: checkout.name, dir: path.relative(checkout.dir, path.dirname(modDir)), commit: checkout.commit, version: checkout.version },
|
|
18
|
+
group: checkout.name,
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
warnings.push(`skipped ${path.relative(checkout.dir, modDir) || "."}: ${errorMessage(error)}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return { entries, warnings };
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=readSource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readSource.js","sourceRoot":"","sources":["../../src/registry/readSource.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAwB,KAAK,EAAE,QAAQ,EAAE,EAAE;IACnE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACpD,MAAM,OAAO,GAAwB,EAAE,CAAC;IAExC,KAAK,MAAM,MAAM,IAAI,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,MAAM,UAAU,CAAC,MAAM,EAAE;gBACpC,MAAM,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE;gBAC7I,KAAK,EAAG,QAAQ,CAAC,IAAI;aACtB,CAAC,CAAC,CAAC;QACN,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,QAAQ,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,GAAG,KAAK,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACjG,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAC/B,CAAC,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** What part of a mod a file is: its manifests, its hooks module, its type contract, or anything else it ships. */
|
|
3
|
+
export declare const ModFileTypeSchema: z.ZodEnum<{
|
|
4
|
+
asset: "asset";
|
|
5
|
+
hooks: "hooks";
|
|
6
|
+
manifest: "manifest";
|
|
7
|
+
types: "types";
|
|
8
|
+
}>;
|
|
9
|
+
export type ModFileType = z.infer<typeof ModFileTypeSchema>;
|
|
10
|
+
/** One installed or installable file of a mod; `path` is `<mod>/<file>`, relative to the install directory. */
|
|
11
|
+
export declare const ModFileSchema: z.ZodObject<{
|
|
12
|
+
path: z.ZodString;
|
|
13
|
+
hash: z.ZodOptional<z.ZodString>;
|
|
14
|
+
version: z.ZodOptional<z.ZodString>;
|
|
15
|
+
type: z.ZodEnum<{
|
|
16
|
+
asset: "asset";
|
|
17
|
+
hooks: "hooks";
|
|
18
|
+
manifest: "manifest";
|
|
19
|
+
types: "types";
|
|
20
|
+
}>;
|
|
21
|
+
}, z.core.$strip>;
|
|
22
|
+
export type ModFile = z.infer<typeof ModFileSchema>;
|
|
23
|
+
/**
|
|
24
|
+
* One installable mod. Built from a mod folder's `plugin.json` by
|
|
25
|
+
* `readModDir`, and written per install into `mods.json` by the `add` and
|
|
26
|
+
* `update` commands. `group` is the source name, so `ls` groups by source.
|
|
27
|
+
*/
|
|
28
|
+
export declare const ModMetaSchema: z.ZodObject<{
|
|
29
|
+
name: z.ZodString;
|
|
30
|
+
description: z.ZodOptional<z.ZodString>;
|
|
31
|
+
version: z.ZodOptional<z.ZodString>;
|
|
32
|
+
registryDependencies: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
33
|
+
origin: z.ZodObject<{
|
|
34
|
+
source: z.ZodString;
|
|
35
|
+
dir: z.ZodString;
|
|
36
|
+
commit: z.ZodOptional<z.ZodString>;
|
|
37
|
+
version: z.ZodOptional<z.ZodString>;
|
|
38
|
+
}, z.core.$strip>;
|
|
39
|
+
group: z.ZodString;
|
|
40
|
+
files: z.ZodArray<z.ZodObject<{
|
|
41
|
+
path: z.ZodString;
|
|
42
|
+
hash: z.ZodOptional<z.ZodString>;
|
|
43
|
+
version: z.ZodOptional<z.ZodString>;
|
|
44
|
+
type: z.ZodEnum<{
|
|
45
|
+
asset: "asset";
|
|
46
|
+
hooks: "hooks";
|
|
47
|
+
manifest: "manifest";
|
|
48
|
+
types: "types";
|
|
49
|
+
}>;
|
|
50
|
+
}, z.core.$strip>>;
|
|
51
|
+
}, z.core.$strip>;
|
|
52
|
+
export type ModMeta = z.infer<typeof ModMetaSchema>;
|
|
53
|
+
export type ModRegistry = Record<string, ModMeta>;
|
|
54
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,mHAAmH;AACnH,eAAO,MAAM,iBAAiB;;;;;EAAkD,CAAC;AAEjF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,+GAA+G;AAC/G,eAAO,MAAM,aAAa;;;;;;;;;;iBAExB,CAAC;AAEH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD;;;;GAIG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;iBAGxB,CAAC;AAEH,MAAM,MAAM,OAAO,GAAO,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AACxD,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// packages/mods/src/registry/types.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { BaseFileEntrySchema } from "@g3nomaly/core/registry";
|
|
4
|
+
import { OriginEntrySchema } from "@g3nomaly/core/installer";
|
|
5
|
+
/** What part of a mod a file is: its manifests, its hooks module, its type contract, or anything else it ships. */
|
|
6
|
+
export const ModFileTypeSchema = z.enum(["manifest", "hooks", "types", "asset"]);
|
|
7
|
+
/** One installed or installable file of a mod; `path` is `<mod>/<file>`, relative to the install directory. */
|
|
8
|
+
export const ModFileSchema = BaseFileEntrySchema.extend({
|
|
9
|
+
type: ModFileTypeSchema,
|
|
10
|
+
});
|
|
11
|
+
/**
|
|
12
|
+
* One installable mod. Built from a mod folder's `plugin.json` by
|
|
13
|
+
* `readModDir`, and written per install into `mods.json` by the `add` and
|
|
14
|
+
* `update` commands. `group` is the source name, so `ls` groups by source.
|
|
15
|
+
*/
|
|
16
|
+
export const ModMetaSchema = OriginEntrySchema.extend({
|
|
17
|
+
group: z.string().min(1),
|
|
18
|
+
files: z.array(ModFileSchema).min(1),
|
|
19
|
+
});
|
|
20
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,mHAAmH;AACnH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAIjF,+GAA+G;AAC/G,MAAM,CAAC,MAAM,aAAa,GAAG,mBAAmB,CAAC,MAAM,CAAC;IACtD,IAAI,EAAE,iBAAiB;CACxB,CAAC,CAAC;AAIH;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,iBAAiB,CAAC,MAAM,CAAC;IACpD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CACrC,CAAC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SourceRecord } from "@g3nomaly/core/sources";
|
|
2
|
+
/** Sources every install scope reads from without registering them; never written to `mods.json` and never removable. */
|
|
3
|
+
export declare const BUILTIN_SOURCES: SourceRecord;
|
|
4
|
+
//# sourceMappingURL=builtins.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../../src/sources/builtins.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,yHAAyH;AACzH,eAAO,MAAM,eAAe,EAAE,YAE7B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtins.js","sourceRoot":"","sources":["../../src/sources/builtins.ts"],"names":[],"mappings":"AAGA,yHAAyH;AACzH,MAAM,CAAC,MAAM,eAAe,GAAiB;IAC3C,UAAU,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,oBAAoB,EAAE;CAC3D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sources/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sources/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|