@unlimitechcloud/devlink 1.0.2
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/AGENTS.md +880 -0
- package/LICENSE +21 -0
- package/README.md +335 -0
- package/dist/__tests__/e2e.spec.d.ts +8 -0
- package/dist/__tests__/e2e.spec.d.ts.map +1 -0
- package/dist/__tests__/e2e.spec.js +253 -0
- package/dist/__tests__/e2e.spec.js.map +1 -0
- package/dist/__tests__/integration.spec.d.ts +8 -0
- package/dist/__tests__/integration.spec.d.ts.map +1 -0
- package/dist/__tests__/integration.spec.js +274 -0
- package/dist/__tests__/integration.spec.js.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +610 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/consumers.d.ts +37 -0
- package/dist/commands/consumers.d.ts.map +1 -0
- package/dist/commands/consumers.js +107 -0
- package/dist/commands/consumers.js.map +1 -0
- package/dist/commands/docs.d.ts +59 -0
- package/dist/commands/docs.d.ts.map +1 -0
- package/dist/commands/docs.js +262 -0
- package/dist/commands/docs.js.map +1 -0
- package/dist/commands/docs.spec.d.ts +5 -0
- package/dist/commands/docs.spec.d.ts.map +1 -0
- package/dist/commands/docs.spec.js +213 -0
- package/dist/commands/docs.spec.js.map +1 -0
- package/dist/commands/index.d.ts +13 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +13 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/install.d.ts +31 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +234 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/list.d.ts +22 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +45 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/list.spec.d.ts +5 -0
- package/dist/commands/list.spec.d.ts.map +1 -0
- package/dist/commands/list.spec.js +95 -0
- package/dist/commands/list.spec.js.map +1 -0
- package/dist/commands/prune.d.ts +27 -0
- package/dist/commands/prune.d.ts.map +1 -0
- package/dist/commands/prune.js +74 -0
- package/dist/commands/prune.js.map +1 -0
- package/dist/commands/publish.d.ts +16 -0
- package/dist/commands/publish.d.ts.map +1 -0
- package/dist/commands/publish.js +225 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/publish.spec.d.ts +5 -0
- package/dist/commands/publish.spec.d.ts.map +1 -0
- package/dist/commands/publish.spec.js +98 -0
- package/dist/commands/publish.spec.js.map +1 -0
- package/dist/commands/push.d.ts +16 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/push.js +164 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/remove.d.ts +24 -0
- package/dist/commands/remove.d.ts.map +1 -0
- package/dist/commands/remove.js +80 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/remove.spec.d.ts +5 -0
- package/dist/commands/remove.spec.d.ts.map +1 -0
- package/dist/commands/remove.spec.js +87 -0
- package/dist/commands/remove.spec.js.map +1 -0
- package/dist/commands/resolve.d.ts +20 -0
- package/dist/commands/resolve.d.ts.map +1 -0
- package/dist/commands/resolve.js +52 -0
- package/dist/commands/resolve.js.map +1 -0
- package/dist/commands/resolve.spec.d.ts +5 -0
- package/dist/commands/resolve.spec.d.ts.map +1 -0
- package/dist/commands/resolve.spec.js +87 -0
- package/dist/commands/resolve.spec.js.map +1 -0
- package/dist/commands/verify.d.ts +32 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +127 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +70 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +65 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +116 -0
- package/dist/constants.js.map +1 -0
- package/dist/constants.spec.d.ts +5 -0
- package/dist/constants.spec.d.ts.map +1 -0
- package/dist/constants.spec.js +72 -0
- package/dist/constants.spec.js.map +1 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +9 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/installations.d.ts +79 -0
- package/dist/core/installations.d.ts.map +1 -0
- package/dist/core/installations.js +207 -0
- package/dist/core/installations.js.map +1 -0
- package/dist/core/installations.spec.d.ts +5 -0
- package/dist/core/installations.spec.d.ts.map +1 -0
- package/dist/core/installations.spec.js +261 -0
- package/dist/core/installations.spec.js.map +1 -0
- package/dist/core/lock.d.ts +37 -0
- package/dist/core/lock.d.ts.map +1 -0
- package/dist/core/lock.js +198 -0
- package/dist/core/lock.js.map +1 -0
- package/dist/core/lock.spec.d.ts +5 -0
- package/dist/core/lock.spec.d.ts.map +1 -0
- package/dist/core/lock.spec.js +161 -0
- package/dist/core/lock.spec.js.map +1 -0
- package/dist/core/registry.d.ts +80 -0
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/core/registry.js +231 -0
- package/dist/core/registry.js.map +1 -0
- package/dist/core/registry.spec.d.ts +5 -0
- package/dist/core/registry.spec.d.ts.map +1 -0
- package/dist/core/registry.spec.js +281 -0
- package/dist/core/registry.spec.js.map +1 -0
- package/dist/core/resolver.d.ts +55 -0
- package/dist/core/resolver.d.ts.map +1 -0
- package/dist/core/resolver.js +127 -0
- package/dist/core/resolver.js.map +1 -0
- package/dist/core/resolver.spec.d.ts +5 -0
- package/dist/core/resolver.spec.d.ts.map +1 -0
- package/dist/core/resolver.spec.js +202 -0
- package/dist/core/resolver.spec.js.map +1 -0
- package/dist/core/store.d.ts +65 -0
- package/dist/core/store.d.ts.map +1 -0
- package/dist/core/store.js +245 -0
- package/dist/core/store.js.map +1 -0
- package/dist/core/store.spec.d.ts +5 -0
- package/dist/core/store.spec.d.ts.map +1 -0
- package/dist/core/store.spec.js +195 -0
- package/dist/core/store.spec.js.map +1 -0
- package/dist/formatters/flat.d.ts +41 -0
- package/dist/formatters/flat.d.ts.map +1 -0
- package/dist/formatters/flat.js +131 -0
- package/dist/formatters/flat.js.map +1 -0
- package/dist/formatters/flat.spec.d.ts +5 -0
- package/dist/formatters/flat.spec.d.ts.map +1 -0
- package/dist/formatters/flat.spec.js +130 -0
- package/dist/formatters/flat.spec.js.map +1 -0
- package/dist/formatters/index.d.ts +6 -0
- package/dist/formatters/index.d.ts.map +1 -0
- package/dist/formatters/index.js +6 -0
- package/dist/formatters/index.js.map +1 -0
- package/dist/formatters/tree.d.ts +29 -0
- package/dist/formatters/tree.d.ts.map +1 -0
- package/dist/formatters/tree.js +256 -0
- package/dist/formatters/tree.js.map +1 -0
- package/dist/formatters/tree.spec.d.ts +5 -0
- package/dist/formatters/tree.spec.d.ts.map +1 -0
- package/dist/formatters/tree.spec.js +127 -0
- package/dist/formatters/tree.spec.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/installer.d.ts +13 -0
- package/dist/installer.d.ts.map +1 -0
- package/dist/installer.js +171 -0
- package/dist/installer.js.map +1 -0
- package/dist/store.d.ts +78 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +344 -0
- package/dist/store.js.map +1 -0
- package/dist/types.d.ts +235 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/docs/README.md +68 -0
- package/docs/inspection/consumers.md +178 -0
- package/docs/inspection/list.md +182 -0
- package/docs/inspection/resolve.md +172 -0
- package/docs/installation/configuration.md +238 -0
- package/docs/installation/install.md +184 -0
- package/docs/maintenance/prune.md +159 -0
- package/docs/maintenance/remove.md +174 -0
- package/docs/maintenance/verify.md +174 -0
- package/docs/publishing/publish.md +146 -0
- package/docs/publishing/push.md +146 -0
- package/docs/store/locking.md +118 -0
- package/docs/store/namespaces.md +141 -0
- package/docs/store/structure.md +163 -0
- package/package.json +58 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consumers Command - Listar proyectos consumidores
|
|
3
|
+
*/
|
|
4
|
+
import { withStoreLock } from "../core/lock.js";
|
|
5
|
+
import { readInstallations, writeInstallations, getConsumers, getConsumersByNamespace, getAllProjects, getProject, pruneDeadProjects, } from "../core/installations.js";
|
|
6
|
+
import { formatConsumersTree } from "../formatters/tree.js";
|
|
7
|
+
import { formatConsumersFlat } from "../formatters/flat.js";
|
|
8
|
+
/**
|
|
9
|
+
* Get consumers info
|
|
10
|
+
*/
|
|
11
|
+
export async function getConsumersInfo(options = {}) {
|
|
12
|
+
const installations = await readInstallations();
|
|
13
|
+
let pruned;
|
|
14
|
+
// Handle prune option
|
|
15
|
+
if (options.prune) {
|
|
16
|
+
pruned = await withStoreLock(async () => {
|
|
17
|
+
const removed = await pruneDeadProjects(installations);
|
|
18
|
+
if (removed.length > 0) {
|
|
19
|
+
await writeInstallations(installations);
|
|
20
|
+
}
|
|
21
|
+
return removed;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
const consumers = [];
|
|
25
|
+
if (options.package) {
|
|
26
|
+
// Filter by package
|
|
27
|
+
const packageConsumers = getConsumers(installations, options.package, {
|
|
28
|
+
namespace: options.namespace,
|
|
29
|
+
});
|
|
30
|
+
for (const { projectPath, info } of packageConsumers) {
|
|
31
|
+
consumers.push({
|
|
32
|
+
projectPath,
|
|
33
|
+
packages: [{
|
|
34
|
+
name: options.package,
|
|
35
|
+
version: info.version,
|
|
36
|
+
namespace: info.namespace,
|
|
37
|
+
}],
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else if (options.namespace) {
|
|
42
|
+
// Filter by namespace
|
|
43
|
+
const nsConsumers = getConsumersByNamespace(installations, options.namespace);
|
|
44
|
+
for (const { projectPath, packages } of nsConsumers) {
|
|
45
|
+
consumers.push({
|
|
46
|
+
projectPath,
|
|
47
|
+
packages: Object.entries(packages).map(([name, info]) => ({
|
|
48
|
+
name,
|
|
49
|
+
version: info.version,
|
|
50
|
+
namespace: info.namespace,
|
|
51
|
+
})),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// All consumers
|
|
57
|
+
const projects = getAllProjects(installations);
|
|
58
|
+
for (const projectPath of projects) {
|
|
59
|
+
const project = getProject(installations, projectPath);
|
|
60
|
+
if (!project)
|
|
61
|
+
continue;
|
|
62
|
+
consumers.push({
|
|
63
|
+
projectPath,
|
|
64
|
+
packages: Object.entries(project.packages).map(([name, info]) => ({
|
|
65
|
+
name,
|
|
66
|
+
version: info.version,
|
|
67
|
+
namespace: info.namespace,
|
|
68
|
+
})),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return { consumers, pruned };
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Format consumers output
|
|
76
|
+
*/
|
|
77
|
+
export async function listConsumers(options = {}) {
|
|
78
|
+
const { consumers, pruned } = await getConsumersInfo(options);
|
|
79
|
+
let output;
|
|
80
|
+
if (options.flat) {
|
|
81
|
+
output = formatConsumersFlat(consumers);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
output = formatConsumersTree(consumers);
|
|
85
|
+
}
|
|
86
|
+
if (pruned && pruned.length > 0) {
|
|
87
|
+
output += `\n\n🧹 Pruned ${pruned.length} dead project(s):\n`;
|
|
88
|
+
for (const p of pruned) {
|
|
89
|
+
output += ` - ${p}\n`;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return output;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* CLI handler for consumers command
|
|
96
|
+
*/
|
|
97
|
+
export async function handleConsumers(args) {
|
|
98
|
+
try {
|
|
99
|
+
const output = await listConsumers(args);
|
|
100
|
+
console.log(output);
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
console.error(`✗ Consumers failed: ${error.message}`);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=consumers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consumers.js","sourceRoot":"","sources":["../../src/commands/consumers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Docs Command - Display embedded documentation
|
|
3
|
+
*/
|
|
4
|
+
export interface DocEntry {
|
|
5
|
+
name: string;
|
|
6
|
+
path: string;
|
|
7
|
+
type: "file" | "directory";
|
|
8
|
+
children?: DocEntry[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Get the docs directory path (relative to package root)
|
|
12
|
+
*/
|
|
13
|
+
export declare function getDocsPath(): string;
|
|
14
|
+
/**
|
|
15
|
+
* Get the AGENTS.md path
|
|
16
|
+
*/
|
|
17
|
+
export declare function getAgentsPath(): string;
|
|
18
|
+
/**
|
|
19
|
+
* Normalize a path for comparison (lowercase, no .md extension)
|
|
20
|
+
*/
|
|
21
|
+
export declare function normalizePath(p: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Build documentation tree from filesystem
|
|
24
|
+
*/
|
|
25
|
+
export declare function buildDocTree(dirPath: string, relativePath?: string): DocEntry[];
|
|
26
|
+
/**
|
|
27
|
+
* Find a document by path (case insensitive)
|
|
28
|
+
*/
|
|
29
|
+
export declare function findDocument(tree: DocEntry[], searchPath: string): {
|
|
30
|
+
entry: DocEntry;
|
|
31
|
+
fullPath: string;
|
|
32
|
+
} | null;
|
|
33
|
+
/**
|
|
34
|
+
* Format the documentation tree for display
|
|
35
|
+
*/
|
|
36
|
+
export declare function formatTree(entries: DocEntry[], prefix?: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Format directory listing
|
|
39
|
+
*/
|
|
40
|
+
export declare function formatDirectoryListing(entry: DocEntry): string;
|
|
41
|
+
/**
|
|
42
|
+
* Read and return document content
|
|
43
|
+
*/
|
|
44
|
+
export declare function readDocument(docPath: string, docsDir?: string): string | null;
|
|
45
|
+
/**
|
|
46
|
+
* Read AGENTS.md
|
|
47
|
+
*/
|
|
48
|
+
export declare function readAgents(agentsPath?: string): string | null;
|
|
49
|
+
/**
|
|
50
|
+
* Main docs command handler
|
|
51
|
+
*/
|
|
52
|
+
export declare function handleDocs(args: {
|
|
53
|
+
document?: string;
|
|
54
|
+
}): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Print docs help
|
|
57
|
+
*/
|
|
58
|
+
export declare function printDocsHelp(): void;
|
|
59
|
+
//# sourceMappingURL=docs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/commands/docs.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAGpC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,GAAE,MAAW,GAAG,QAAQ,EAAE,CAoCnF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,EAAE,EAChB,UAAU,EAAE,MAAM,GACjB;IAAE,KAAK,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA+B9C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,MAAM,GAAE,MAAW,GAAG,MAAM,CAoB3E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAoB9D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS7E;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAO7D;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsE3E;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CA2BpC"}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Docs Command - Display embedded documentation
|
|
3
|
+
*/
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
/**
|
|
10
|
+
* Get the docs directory path (relative to package root)
|
|
11
|
+
*/
|
|
12
|
+
export function getDocsPath() {
|
|
13
|
+
// From dist/commands/docs.js, go up to package root
|
|
14
|
+
return path.resolve(__dirname, "../../docs");
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Get the AGENTS.md path
|
|
18
|
+
*/
|
|
19
|
+
export function getAgentsPath() {
|
|
20
|
+
return path.resolve(__dirname, "../../AGENTS.md");
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Normalize a path for comparison (lowercase, no .md extension)
|
|
24
|
+
*/
|
|
25
|
+
export function normalizePath(p) {
|
|
26
|
+
return p.toLowerCase().replace(/\.md$/, "").replace(/\\/g, "/");
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build documentation tree from filesystem
|
|
30
|
+
*/
|
|
31
|
+
export function buildDocTree(dirPath, relativePath = "") {
|
|
32
|
+
const entries = [];
|
|
33
|
+
try {
|
|
34
|
+
const items = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
35
|
+
for (const item of items) {
|
|
36
|
+
if (item.name.startsWith("."))
|
|
37
|
+
continue;
|
|
38
|
+
const itemPath = path.join(dirPath, item.name);
|
|
39
|
+
const relPath = relativePath ? `${relativePath}/${item.name}` : item.name;
|
|
40
|
+
if (item.isDirectory()) {
|
|
41
|
+
entries.push({
|
|
42
|
+
name: item.name,
|
|
43
|
+
path: relPath,
|
|
44
|
+
type: "directory",
|
|
45
|
+
children: buildDocTree(itemPath, relPath),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
else if (item.name.endsWith(".md")) {
|
|
49
|
+
entries.push({
|
|
50
|
+
name: item.name.replace(/\.md$/, ""),
|
|
51
|
+
path: relPath.replace(/\.md$/, ""),
|
|
52
|
+
type: "file",
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Directory doesn't exist or can't be read
|
|
59
|
+
}
|
|
60
|
+
return entries.sort((a, b) => {
|
|
61
|
+
// Directories first, then files
|
|
62
|
+
if (a.type !== b.type)
|
|
63
|
+
return a.type === "directory" ? -1 : 1;
|
|
64
|
+
return a.name.localeCompare(b.name);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Find a document by path (case insensitive)
|
|
69
|
+
*/
|
|
70
|
+
export function findDocument(tree, searchPath) {
|
|
71
|
+
const normalized = normalizePath(searchPath);
|
|
72
|
+
const parts = normalized.split("/").filter(Boolean);
|
|
73
|
+
let current = tree;
|
|
74
|
+
let currentPath = "";
|
|
75
|
+
for (let i = 0; i < parts.length; i++) {
|
|
76
|
+
const part = parts[i];
|
|
77
|
+
const isLast = i === parts.length - 1;
|
|
78
|
+
const found = current.find((e) => normalizePath(e.name) === part);
|
|
79
|
+
if (!found)
|
|
80
|
+
return null;
|
|
81
|
+
currentPath = currentPath ? `${currentPath}/${found.name}` : found.name;
|
|
82
|
+
if (isLast) {
|
|
83
|
+
return { entry: found, fullPath: currentPath };
|
|
84
|
+
}
|
|
85
|
+
if (found.type === "directory" && found.children) {
|
|
86
|
+
current = found.children;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Format the documentation tree for display
|
|
96
|
+
*/
|
|
97
|
+
export function formatTree(entries, prefix = "") {
|
|
98
|
+
const lines = [];
|
|
99
|
+
for (let i = 0; i < entries.length; i++) {
|
|
100
|
+
const entry = entries[i];
|
|
101
|
+
const isLast = i === entries.length - 1;
|
|
102
|
+
const connector = isLast ? "└── " : "├── ";
|
|
103
|
+
const childPrefix = isLast ? " " : "│ ";
|
|
104
|
+
if (entry.type === "directory") {
|
|
105
|
+
lines.push(`${prefix}${connector}${entry.name}/`);
|
|
106
|
+
if (entry.children && entry.children.length > 0) {
|
|
107
|
+
lines.push(formatTree(entry.children, prefix + childPrefix));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
lines.push(`${prefix}${connector}${entry.name}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return lines.join("\n");
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Format directory listing
|
|
118
|
+
*/
|
|
119
|
+
export function formatDirectoryListing(entry) {
|
|
120
|
+
const lines = [];
|
|
121
|
+
lines.push(`📁 ${entry.path}/\n`);
|
|
122
|
+
if (entry.children && entry.children.length > 0) {
|
|
123
|
+
lines.push("Documents:");
|
|
124
|
+
for (const child of entry.children) {
|
|
125
|
+
if (child.type === "file") {
|
|
126
|
+
lines.push(` ${child.name}`);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
lines.push(` ${child.name}/`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
lines.push("");
|
|
133
|
+
lines.push(`Usage: devlink docs ${entry.path}/<document>`);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
lines.push("(empty directory)");
|
|
137
|
+
}
|
|
138
|
+
return lines.join("\n");
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Read and return document content
|
|
142
|
+
*/
|
|
143
|
+
export function readDocument(docPath, docsDir) {
|
|
144
|
+
const dir = docsDir || getDocsPath();
|
|
145
|
+
const fullPath = path.join(dir, docPath + ".md");
|
|
146
|
+
try {
|
|
147
|
+
return fs.readFileSync(fullPath, "utf-8");
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Read AGENTS.md
|
|
155
|
+
*/
|
|
156
|
+
export function readAgents(agentsPath) {
|
|
157
|
+
const filePath = agentsPath || getAgentsPath();
|
|
158
|
+
try {
|
|
159
|
+
return fs.readFileSync(filePath, "utf-8");
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Main docs command handler
|
|
167
|
+
*/
|
|
168
|
+
export async function handleDocs(args) {
|
|
169
|
+
const docsDir = getDocsPath();
|
|
170
|
+
const tree = buildDocTree(docsDir);
|
|
171
|
+
// Add AGENTS.md as a special top-level entry
|
|
172
|
+
const fullTree = [
|
|
173
|
+
{ name: "agents", path: "agents", type: "file" },
|
|
174
|
+
...tree,
|
|
175
|
+
];
|
|
176
|
+
// No argument: show full tree
|
|
177
|
+
if (!args.document) {
|
|
178
|
+
console.log(`
|
|
179
|
+
📚 DevLink Documentation
|
|
180
|
+
|
|
181
|
+
${formatTree(fullTree)}
|
|
182
|
+
|
|
183
|
+
Usage:
|
|
184
|
+
devlink docs <document> Show document content
|
|
185
|
+
devlink docs <directory> List documents in directory
|
|
186
|
+
|
|
187
|
+
Examples:
|
|
188
|
+
devlink docs agents AI agent guide (comprehensive)
|
|
189
|
+
devlink docs store List store documents
|
|
190
|
+
devlink docs store/namespaces Show namespaces documentation
|
|
191
|
+
`);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const searchPath = args.document;
|
|
195
|
+
const normalizedSearch = normalizePath(searchPath);
|
|
196
|
+
// Special case: agents
|
|
197
|
+
if (normalizedSearch === "agents" || normalizedSearch === "agent" || normalizedSearch === "ai") {
|
|
198
|
+
const content = readAgents();
|
|
199
|
+
if (content) {
|
|
200
|
+
console.log(content);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
console.error("Error: AGENTS.md not found");
|
|
204
|
+
process.exit(1);
|
|
205
|
+
}
|
|
206
|
+
// Search in tree
|
|
207
|
+
const result = findDocument(tree, searchPath);
|
|
208
|
+
if (!result) {
|
|
209
|
+
console.error(`Document not found: ${searchPath}`);
|
|
210
|
+
console.error("");
|
|
211
|
+
console.error("Available documents:");
|
|
212
|
+
console.error(formatTree(fullTree));
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
const { entry, fullPath } = result;
|
|
216
|
+
if (entry.type === "directory") {
|
|
217
|
+
// Show directory listing
|
|
218
|
+
console.log(formatDirectoryListing(entry));
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
// Read and display file
|
|
222
|
+
const content = readDocument(fullPath);
|
|
223
|
+
if (content) {
|
|
224
|
+
console.log(content);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
console.error(`Error: Could not read ${fullPath}.md`);
|
|
228
|
+
process.exit(1);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Print docs help
|
|
233
|
+
*/
|
|
234
|
+
export function printDocsHelp() {
|
|
235
|
+
console.log(`
|
|
236
|
+
devlink docs - Display embedded documentation
|
|
237
|
+
|
|
238
|
+
USAGE
|
|
239
|
+
devlink docs [document]
|
|
240
|
+
|
|
241
|
+
DESCRIPTION
|
|
242
|
+
Access DevLink documentation directly from the command line.
|
|
243
|
+
Without arguments, shows the documentation tree.
|
|
244
|
+
With a document path, displays that document's content.
|
|
245
|
+
With a directory path, lists documents in that directory.
|
|
246
|
+
|
|
247
|
+
ARGUMENTS
|
|
248
|
+
[document] Document or directory path (case insensitive, .md optional)
|
|
249
|
+
|
|
250
|
+
EXAMPLES
|
|
251
|
+
devlink docs Show documentation tree
|
|
252
|
+
devlink docs agents AI agent guide (comprehensive)
|
|
253
|
+
devlink docs store List store documents
|
|
254
|
+
devlink docs store/namespaces Show namespaces documentation
|
|
255
|
+
devlink docs STORE/NAMESPACES Same (case insensitive)
|
|
256
|
+
devlink docs publishing/push Show push command documentation
|
|
257
|
+
|
|
258
|
+
SPECIAL DOCUMENTS
|
|
259
|
+
agents Complete self-contained guide for AI agents
|
|
260
|
+
`);
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=docs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../../src/commands/docs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs.spec.d.ts","sourceRoot":"","sources":["../../src/commands/docs.spec.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Docs Command - Unit tests
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
5
|
+
import fs from "fs/promises";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import os from "os";
|
|
8
|
+
import { normalizePath, buildDocTree, findDocument, formatTree, formatDirectoryListing, readDocument, readAgents, } from "./docs.js";
|
|
9
|
+
const TEST_DOCS_PATH = path.join(os.tmpdir(), "devlink-docs-test-" + Date.now());
|
|
10
|
+
describe("Docs Command", () => {
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
// Create test documentation structure
|
|
13
|
+
await fs.mkdir(TEST_DOCS_PATH, { recursive: true });
|
|
14
|
+
// Create directories
|
|
15
|
+
await fs.mkdir(path.join(TEST_DOCS_PATH, "store"), { recursive: true });
|
|
16
|
+
await fs.mkdir(path.join(TEST_DOCS_PATH, "publishing"), { recursive: true });
|
|
17
|
+
await fs.mkdir(path.join(TEST_DOCS_PATH, "empty-dir"), { recursive: true });
|
|
18
|
+
// Create files
|
|
19
|
+
await fs.writeFile(path.join(TEST_DOCS_PATH, "README.md"), "# Documentation Index\n\nWelcome to docs.");
|
|
20
|
+
await fs.writeFile(path.join(TEST_DOCS_PATH, "store", "structure.md"), "# Store Structure\n\nThe store is located at ~/.devlink");
|
|
21
|
+
await fs.writeFile(path.join(TEST_DOCS_PATH, "store", "namespaces.md"), "# Namespaces\n\nNamespaces provide isolation.");
|
|
22
|
+
await fs.writeFile(path.join(TEST_DOCS_PATH, "publishing", "publish.md"), "# Publish Command\n\nPublish packages to the store.");
|
|
23
|
+
// Create AGENTS.md
|
|
24
|
+
await fs.writeFile(path.join(TEST_DOCS_PATH, "AGENTS.md"), "# Agent Guide\n\nComplete guide for AI agents.");
|
|
25
|
+
});
|
|
26
|
+
afterEach(async () => {
|
|
27
|
+
await fs.rm(TEST_DOCS_PATH, { recursive: true, force: true });
|
|
28
|
+
});
|
|
29
|
+
describe("normalizePath", () => {
|
|
30
|
+
it("should convert to lowercase", () => {
|
|
31
|
+
expect(normalizePath("STORE/NAMESPACES")).toBe("store/namespaces");
|
|
32
|
+
});
|
|
33
|
+
it("should remove .md extension", () => {
|
|
34
|
+
expect(normalizePath("store/namespaces.md")).toBe("store/namespaces");
|
|
35
|
+
});
|
|
36
|
+
it("should normalize backslashes", () => {
|
|
37
|
+
expect(normalizePath("store\\namespaces")).toBe("store/namespaces");
|
|
38
|
+
});
|
|
39
|
+
it("should handle combined cases", () => {
|
|
40
|
+
expect(normalizePath("STORE\\NAMESPACES.MD")).toBe("store/namespaces");
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe("buildDocTree", () => {
|
|
44
|
+
it("should build tree from directory", () => {
|
|
45
|
+
const tree = buildDocTree(TEST_DOCS_PATH);
|
|
46
|
+
// Should have directories first, then files
|
|
47
|
+
expect(tree.length).toBeGreaterThan(0);
|
|
48
|
+
// Find store directory
|
|
49
|
+
const storeDir = tree.find(e => e.name === "store");
|
|
50
|
+
expect(storeDir).toBeDefined();
|
|
51
|
+
expect(storeDir?.type).toBe("directory");
|
|
52
|
+
expect(storeDir?.children?.length).toBe(2);
|
|
53
|
+
});
|
|
54
|
+
it("should sort directories before files", () => {
|
|
55
|
+
const tree = buildDocTree(TEST_DOCS_PATH);
|
|
56
|
+
// First entries should be directories
|
|
57
|
+
const firstDir = tree.findIndex(e => e.type === "directory");
|
|
58
|
+
const firstFile = tree.findIndex(e => e.type === "file");
|
|
59
|
+
if (firstDir !== -1 && firstFile !== -1) {
|
|
60
|
+
expect(firstDir).toBeLessThan(firstFile);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
it("should exclude hidden files", async () => {
|
|
64
|
+
await fs.writeFile(path.join(TEST_DOCS_PATH, ".hidden.md"), "hidden");
|
|
65
|
+
const tree = buildDocTree(TEST_DOCS_PATH);
|
|
66
|
+
const hidden = tree.find(e => e.name === ".hidden");
|
|
67
|
+
expect(hidden).toBeUndefined();
|
|
68
|
+
});
|
|
69
|
+
it("should only include .md files", async () => {
|
|
70
|
+
await fs.writeFile(path.join(TEST_DOCS_PATH, "test.txt"), "text file");
|
|
71
|
+
const tree = buildDocTree(TEST_DOCS_PATH);
|
|
72
|
+
const txtFile = tree.find(e => e.name === "test");
|
|
73
|
+
expect(txtFile).toBeUndefined();
|
|
74
|
+
});
|
|
75
|
+
it("should handle empty directories", () => {
|
|
76
|
+
const tree = buildDocTree(TEST_DOCS_PATH);
|
|
77
|
+
const emptyDir = tree.find(e => e.name === "empty-dir");
|
|
78
|
+
expect(emptyDir).toBeDefined();
|
|
79
|
+
expect(emptyDir?.children).toEqual([]);
|
|
80
|
+
});
|
|
81
|
+
it("should return empty array for non-existent directory", () => {
|
|
82
|
+
const tree = buildDocTree("/non/existent/path");
|
|
83
|
+
expect(tree).toEqual([]);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe("findDocument", () => {
|
|
87
|
+
it("should find file by exact path", () => {
|
|
88
|
+
const tree = buildDocTree(TEST_DOCS_PATH);
|
|
89
|
+
const result = findDocument(tree, "store/structure");
|
|
90
|
+
expect(result).not.toBeNull();
|
|
91
|
+
expect(result?.entry.name).toBe("structure");
|
|
92
|
+
expect(result?.entry.type).toBe("file");
|
|
93
|
+
});
|
|
94
|
+
it("should find file case insensitively", () => {
|
|
95
|
+
const tree = buildDocTree(TEST_DOCS_PATH);
|
|
96
|
+
const result = findDocument(tree, "STORE/STRUCTURE");
|
|
97
|
+
expect(result).not.toBeNull();
|
|
98
|
+
expect(result?.entry.name).toBe("structure");
|
|
99
|
+
});
|
|
100
|
+
it("should find directory", () => {
|
|
101
|
+
const tree = buildDocTree(TEST_DOCS_PATH);
|
|
102
|
+
const result = findDocument(tree, "store");
|
|
103
|
+
expect(result).not.toBeNull();
|
|
104
|
+
expect(result?.entry.type).toBe("directory");
|
|
105
|
+
});
|
|
106
|
+
it("should return null for non-existent path", () => {
|
|
107
|
+
const tree = buildDocTree(TEST_DOCS_PATH);
|
|
108
|
+
const result = findDocument(tree, "nonexistent/path");
|
|
109
|
+
expect(result).toBeNull();
|
|
110
|
+
});
|
|
111
|
+
it("should handle path with .md extension", () => {
|
|
112
|
+
const tree = buildDocTree(TEST_DOCS_PATH);
|
|
113
|
+
const result = findDocument(tree, "store/structure.md");
|
|
114
|
+
expect(result).not.toBeNull();
|
|
115
|
+
expect(result?.entry.name).toBe("structure");
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
describe("formatTree", () => {
|
|
119
|
+
it("should format tree with connectors", () => {
|
|
120
|
+
const entries = [
|
|
121
|
+
{ name: "dir", path: "dir", type: "directory", children: [] },
|
|
122
|
+
{ name: "file", path: "file", type: "file" },
|
|
123
|
+
];
|
|
124
|
+
const output = formatTree(entries);
|
|
125
|
+
expect(output).toContain("├── dir/");
|
|
126
|
+
expect(output).toContain("└── file");
|
|
127
|
+
});
|
|
128
|
+
it("should format nested directories", () => {
|
|
129
|
+
const entries = [
|
|
130
|
+
{
|
|
131
|
+
name: "parent",
|
|
132
|
+
path: "parent",
|
|
133
|
+
type: "directory",
|
|
134
|
+
children: [
|
|
135
|
+
{ name: "child", path: "parent/child", type: "file" },
|
|
136
|
+
],
|
|
137
|
+
},
|
|
138
|
+
];
|
|
139
|
+
const output = formatTree(entries);
|
|
140
|
+
expect(output).toContain("└── parent/");
|
|
141
|
+
expect(output).toContain("└── child");
|
|
142
|
+
});
|
|
143
|
+
it("should handle empty array", () => {
|
|
144
|
+
const output = formatTree([]);
|
|
145
|
+
expect(output).toBe("");
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
describe("formatDirectoryListing", () => {
|
|
149
|
+
it("should format directory with children", () => {
|
|
150
|
+
const entry = {
|
|
151
|
+
name: "store",
|
|
152
|
+
path: "store",
|
|
153
|
+
type: "directory",
|
|
154
|
+
children: [
|
|
155
|
+
{ name: "structure", path: "store/structure", type: "file" },
|
|
156
|
+
{ name: "namespaces", path: "store/namespaces", type: "file" },
|
|
157
|
+
],
|
|
158
|
+
};
|
|
159
|
+
const output = formatDirectoryListing(entry);
|
|
160
|
+
expect(output).toContain("📁 store/");
|
|
161
|
+
expect(output).toContain("Documents:");
|
|
162
|
+
expect(output).toContain("structure");
|
|
163
|
+
expect(output).toContain("namespaces");
|
|
164
|
+
expect(output).toContain("Usage: devlink docs store/<document>");
|
|
165
|
+
});
|
|
166
|
+
it("should handle empty directory", () => {
|
|
167
|
+
const entry = {
|
|
168
|
+
name: "empty",
|
|
169
|
+
path: "empty",
|
|
170
|
+
type: "directory",
|
|
171
|
+
children: [],
|
|
172
|
+
};
|
|
173
|
+
const output = formatDirectoryListing(entry);
|
|
174
|
+
expect(output).toContain("(empty directory)");
|
|
175
|
+
});
|
|
176
|
+
it("should show subdirectories with trailing slash", () => {
|
|
177
|
+
const entry = {
|
|
178
|
+
name: "parent",
|
|
179
|
+
path: "parent",
|
|
180
|
+
type: "directory",
|
|
181
|
+
children: [
|
|
182
|
+
{ name: "subdir", path: "parent/subdir", type: "directory", children: [] },
|
|
183
|
+
],
|
|
184
|
+
};
|
|
185
|
+
const output = formatDirectoryListing(entry);
|
|
186
|
+
expect(output).toContain("subdir/");
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
describe("readDocument", () => {
|
|
190
|
+
it("should read document content", () => {
|
|
191
|
+
const content = readDocument("store/structure", TEST_DOCS_PATH);
|
|
192
|
+
expect(content).not.toBeNull();
|
|
193
|
+
expect(content).toContain("# Store Structure");
|
|
194
|
+
});
|
|
195
|
+
it("should return null for non-existent document", () => {
|
|
196
|
+
const content = readDocument("nonexistent", TEST_DOCS_PATH);
|
|
197
|
+
expect(content).toBeNull();
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
describe("readAgents", () => {
|
|
201
|
+
it("should read AGENTS.md content", () => {
|
|
202
|
+
const agentsPath = path.join(TEST_DOCS_PATH, "AGENTS.md");
|
|
203
|
+
const content = readAgents(agentsPath);
|
|
204
|
+
expect(content).not.toBeNull();
|
|
205
|
+
expect(content).toContain("# Agent Guide");
|
|
206
|
+
});
|
|
207
|
+
it("should return null for non-existent file", () => {
|
|
208
|
+
const content = readAgents("/nonexistent/AGENTS.md");
|
|
209
|
+
expect(content).toBeNull();
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
//# sourceMappingURL=docs.spec.js.map
|