@nshiab/setup-data-project 1.0.28 → 1.0.30
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/esm/helpers/ensureAgents.d.ts +1 -1
- package/esm/helpers/ensureAgents.d.ts.map +1 -1
- package/esm/helpers/ensureAgents.js +34 -13
- package/esm/helpers/ensureManagedSection.d.ts +9 -0
- package/esm/helpers/ensureManagedSection.d.ts.map +1 -0
- package/esm/helpers/ensureManagedSection.js +30 -0
- package/esm/helpers/ensureReadme.d.ts +1 -1
- package/esm/helpers/ensureReadme.d.ts.map +1 -1
- package/esm/helpers/ensureReadme.js +26 -12
- package/esm/helpers/gitignoreEntries.d.ts.map +1 -1
- package/esm/helpers/gitignoreEntries.js +1 -0
- package/esm/helpers/installPackagesAndFetchDocs.d.ts +3 -0
- package/esm/helpers/installPackagesAndFetchDocs.d.ts.map +1 -1
- package/esm/helpers/installPackagesAndFetchDocs.js +42 -34
- package/esm/helpers/packageRegistry.d.ts +1 -0
- package/esm/helpers/packageRegistry.d.ts.map +1 -1
- package/esm/helpers/packageRegistry.js +4 -0
- package/esm/helpers/projectManifest.d.ts +11 -0
- package/esm/helpers/projectManifest.d.ts.map +1 -0
- package/esm/helpers/projectManifest.js +73 -0
- package/esm/helpers/syncPackageDocs.d.ts +2 -0
- package/esm/helpers/syncPackageDocs.d.ts.map +1 -0
- package/esm/helpers/syncPackageDocs.js +27 -0
- package/esm/main.js +19 -14
- package/package.json +1 -1
- package/script/helpers/ensureAgents.d.ts +1 -1
- package/script/helpers/ensureAgents.d.ts.map +1 -1
- package/script/helpers/ensureAgents.js +33 -12
- package/script/helpers/ensureManagedSection.d.ts +9 -0
- package/script/helpers/ensureManagedSection.d.ts.map +1 -0
- package/script/helpers/ensureManagedSection.js +33 -0
- package/script/helpers/ensureReadme.d.ts +1 -1
- package/script/helpers/ensureReadme.d.ts.map +1 -1
- package/script/helpers/ensureReadme.js +26 -12
- package/script/helpers/gitignoreEntries.d.ts.map +1 -1
- package/script/helpers/gitignoreEntries.js +1 -0
- package/script/helpers/installPackagesAndFetchDocs.d.ts +3 -0
- package/script/helpers/installPackagesAndFetchDocs.d.ts.map +1 -1
- package/script/helpers/installPackagesAndFetchDocs.js +42 -33
- package/script/helpers/packageRegistry.d.ts +1 -0
- package/script/helpers/packageRegistry.d.ts.map +1 -1
- package/script/helpers/packageRegistry.js +5 -0
- package/script/helpers/projectManifest.d.ts +11 -0
- package/script/helpers/projectManifest.d.ts.map +1 -0
- package/script/helpers/projectManifest.js +77 -0
- package/script/helpers/syncPackageDocs.d.ts +2 -0
- package/script/helpers/syncPackageDocs.d.ts.map +1 -0
- package/script/helpers/syncPackageDocs.js +30 -0
- package/script/main.js +19 -14
- package/esm/helpers/getInstalledPackages.d.ts +0 -2
- package/esm/helpers/getInstalledPackages.d.ts.map +0 -1
- package/esm/helpers/getInstalledPackages.js +0 -29
- package/esm/helpers/updateProjectConfig.d.ts +0 -2
- package/esm/helpers/updateProjectConfig.d.ts.map +0 -1
- package/esm/helpers/updateProjectConfig.js +0 -42
- package/script/helpers/getInstalledPackages.d.ts +0 -2
- package/script/helpers/getInstalledPackages.d.ts.map +0 -1
- package/script/helpers/getInstalledPackages.js +0 -32
- package/script/helpers/updateProjectConfig.d.ts +0 -2
- package/script/helpers/updateProjectConfig.d.ts.map +0 -1
- package/script/helpers/updateProjectConfig.js +0 -45
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function ensureAgents(docsMapping: Record<string, string>, runtime: string):
|
|
1
|
+
export declare function ensureAgents(docsMapping: Record<string, string>, runtime: string, installedPackages?: string[]): void;
|
|
2
2
|
//# sourceMappingURL=ensureAgents.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ensureAgents.d.ts","sourceRoot":"","sources":["../../src/helpers/ensureAgents.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ensureAgents.d.ts","sourceRoot":"","sources":["../../src/helpers/ensureAgents.ts"],"names":[],"mappings":"AAOA,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,OAAO,EAAE,MAAM,EACf,iBAAiB,GAAE,MAAM,EAA6B,QAuHvD"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { log } from "@clack/prompts";
|
|
2
|
-
import {
|
|
3
|
-
import { SUPPORTED_PACKAGES } from "./packageRegistry.js";
|
|
4
|
-
export
|
|
2
|
+
import { ensureManagedSection } from "./ensureManagedSection.js";
|
|
3
|
+
import { getInstalledPackageConfigs, SUPPORTED_PACKAGES, } from "./packageRegistry.js";
|
|
4
|
+
export function ensureAgents(docsMapping, runtime, installedPackages = Object.keys(docsMapping)) {
|
|
5
5
|
let journalismFunctions = "";
|
|
6
6
|
let sdaClassesAndMethods = "";
|
|
7
|
+
let sdaDocsPath = "";
|
|
8
|
+
let sdaLibraryName = "";
|
|
7
9
|
for (const [pkg, doc] of Object.entries(docsMapping)) {
|
|
8
10
|
const pkgConfig = SUPPORTED_PACKAGES.find((p) => p.value === pkg);
|
|
9
11
|
const pkgType = pkgConfig?.type || "other";
|
|
@@ -21,6 +23,9 @@ export async function ensureAgents(docsMapping, runtime) {
|
|
|
21
23
|
.join("\n") + "\n";
|
|
22
24
|
}
|
|
23
25
|
else if (pkgType === "sda") {
|
|
26
|
+
const repoName = pkg.split("/")[1];
|
|
27
|
+
sdaDocsPath = `./docs/${repoName}.md`;
|
|
28
|
+
sdaLibraryName = pkgConfig?.label || repoName;
|
|
24
29
|
sdaClassesAndMethods = doc
|
|
25
30
|
.split("\n")
|
|
26
31
|
.filter((line) => line.trim().startsWith("#"))
|
|
@@ -45,6 +50,23 @@ export async function ensureAgents(docsMapping, runtime) {
|
|
|
45
50
|
const configFile = runtime === "deno" ? "deno.json" : "package.json";
|
|
46
51
|
const runSda = runtime === "deno" ? "deno task sda" : "npm run sda";
|
|
47
52
|
const runClean = runtime === "deno" ? "deno task clean" : "npm run clean";
|
|
53
|
+
const installedPackageConfigs = getInstalledPackageConfigs(installedPackages);
|
|
54
|
+
const importExamples = installedPackageConfigs.map((pkg) => {
|
|
55
|
+
const repoName = pkg.value.split("/")[1];
|
|
56
|
+
const identifier = repoName.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
57
|
+
return `import * as ${identifier} from "${pkg.value}";`;
|
|
58
|
+
});
|
|
59
|
+
let libraryGuidance = "";
|
|
60
|
+
if (installedPackageConfigs.length > 0) {
|
|
61
|
+
const libraryNames = installedPackageConfigs.map((pkg) => `"${pkg.label}"`)
|
|
62
|
+
.join(", ");
|
|
63
|
+
libraryGuidance = `
|
|
64
|
+
Always prioritize the installed ${libraryNames} libraries when relevant. They can be imported directly like this:
|
|
65
|
+
\`\`\`typescript
|
|
66
|
+
${importExamples.join("\n")}
|
|
67
|
+
\`\`\`
|
|
68
|
+
`;
|
|
69
|
+
}
|
|
48
70
|
let content = `Always verify if there is a ${configFile} file in the root of the project and familiarize yourself with the scripts available in it and the libraries already installed in the project.
|
|
49
71
|
|
|
50
72
|
Always use "sda" task when available (e.g. \`${runSda}\`).
|
|
@@ -62,13 +84,7 @@ If you need to create other TypeScript files, create them in the "sda/helpers" f
|
|
|
62
84
|
If you need to download data, always put the files in the "sda/data" folder, which is gitignored.
|
|
63
85
|
|
|
64
86
|
If you need to output data to a file, always put the file in the "sda/output" folder.
|
|
65
|
-
|
|
66
|
-
Always prioritize the use of the "journalism" and "simple-data-analysis" libraries when they are installed. These libraries can be used directly like this:
|
|
67
|
-
\`\`\`typescript
|
|
68
|
-
import { formatDate } from "@nshiab/journalism-format";
|
|
69
|
-
import { SimpleDB } from "@nshiab/simple-data-analysis";
|
|
70
|
-
\`\`\`
|
|
71
|
-
`;
|
|
87
|
+
${libraryGuidance}`;
|
|
72
88
|
if (journalismFunctions !== "") {
|
|
73
89
|
content += `
|
|
74
90
|
Here are the functions available in the "journalism" libraries. If one of the function might be relevant, read the complete documentation in the "./docs/" folder to properly use it.
|
|
@@ -76,11 +92,16 @@ ${journalismFunctions}`;
|
|
|
76
92
|
}
|
|
77
93
|
if (sdaClassesAndMethods !== "") {
|
|
78
94
|
content += `
|
|
79
|
-
Here are the classes and their methods available in the "
|
|
95
|
+
Here are the classes and their methods available in the "${sdaLibraryName}" library. If one of the classes or methods might be relevant, read the complete documentation at "${sdaDocsPath}" to properly use it. Remember that almost all methods are asynchronous, so you need to use \`await\` when calling them.
|
|
80
96
|
${sdaClassesAndMethods}`;
|
|
81
97
|
}
|
|
82
|
-
const status =
|
|
83
|
-
|
|
98
|
+
const status = ensureManagedSection({
|
|
99
|
+
path: "AGENTS.md",
|
|
100
|
+
name: "agents",
|
|
101
|
+
content,
|
|
102
|
+
createContent: (managedSection) => managedSection,
|
|
103
|
+
});
|
|
104
|
+
if (status === "created" || status === "updated") {
|
|
84
105
|
log.info("Updated AGENTS.md");
|
|
85
106
|
}
|
|
86
107
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface ManagedSectionOptions {
|
|
2
|
+
path: string;
|
|
3
|
+
name: string;
|
|
4
|
+
content: string;
|
|
5
|
+
createContent: (section: string) => string;
|
|
6
|
+
}
|
|
7
|
+
export declare function ensureManagedSection(options: ManagedSectionOptions): "created" | "updated" | "unchanged" | "missing-markers";
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=ensureManagedSection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensureManagedSection.d.ts","sourceRoot":"","sources":["../../src/helpers/ensureManagedSection.ts"],"names":[],"mappings":"AAGA,UAAU,qBAAqB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;CAC5C;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,qBAAqB,GAC7B,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,iBAAiB,CAmCzD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { log } from "@clack/prompts";
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
export function ensureManagedSection(options) {
|
|
4
|
+
const startMarker = `<!-- setup-data-project:${options.name}:start -->`;
|
|
5
|
+
const endMarker = `<!-- setup-data-project:${options.name}:end -->`;
|
|
6
|
+
const trimmedContent = options.content.trim();
|
|
7
|
+
const section = trimmedContent === ""
|
|
8
|
+
? `${startMarker}\n${endMarker}`
|
|
9
|
+
: `${startMarker}\n${trimmedContent}\n${endMarker}`;
|
|
10
|
+
if (!existsSync(options.path)) {
|
|
11
|
+
writeFileSync(options.path, options.createContent(section));
|
|
12
|
+
return "created";
|
|
13
|
+
}
|
|
14
|
+
const currentContent = readFileSync(options.path, "utf-8");
|
|
15
|
+
const start = currentContent.indexOf(startMarker);
|
|
16
|
+
const end = currentContent.indexOf(endMarker);
|
|
17
|
+
if (start === -1 || end === -1 || end < start) {
|
|
18
|
+
log.warn(`${options.path} was not updated because its setup-data-project markers ` +
|
|
19
|
+
`were not found. Add ${startMarker} and ${endMarker}, then rerun the ` +
|
|
20
|
+
"script.");
|
|
21
|
+
return "missing-markers";
|
|
22
|
+
}
|
|
23
|
+
const nextContent = currentContent.slice(0, start) + section +
|
|
24
|
+
currentContent.slice(end + endMarker.length);
|
|
25
|
+
if (nextContent === currentContent) {
|
|
26
|
+
return "unchanged";
|
|
27
|
+
}
|
|
28
|
+
writeFileSync(options.path, nextContent);
|
|
29
|
+
return "updated";
|
|
30
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function ensureReadme(runtime: string):
|
|
1
|
+
export declare function ensureReadme(runtime: string, installedPackages?: string[]): void;
|
|
2
2
|
//# sourceMappingURL=ensureReadme.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ensureReadme.d.ts","sourceRoot":"","sources":["../../src/helpers/ensureReadme.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ensureReadme.d.ts","sourceRoot":"","sources":["../../src/helpers/ensureReadme.ts"],"names":[],"mappings":"AAIA,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,iBAAiB,GAAE,MAAM,EAAO,QAwDjC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { log } from "@clack/prompts";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { ensureManagedSection } from "./ensureManagedSection.js";
|
|
3
|
+
import { getInstalledPackageConfigs } from "./packageRegistry.js";
|
|
4
|
+
export function ensureReadme(runtime, installedPackages = []) {
|
|
4
5
|
let runCommand = "npm run";
|
|
5
6
|
if (runtime === "deno") {
|
|
6
7
|
runCommand = "deno task";
|
|
@@ -8,13 +9,27 @@ export async function ensureReadme(runtime) {
|
|
|
8
9
|
else if (runtime === "bun") {
|
|
9
10
|
runCommand = "bun run";
|
|
10
11
|
}
|
|
11
|
-
const
|
|
12
|
+
const installedPackageConfigs = getInstalledPackageConfigs(installedPackages);
|
|
13
|
+
const hasSda = installedPackageConfigs.some((pkg) => pkg.type === "sda");
|
|
14
|
+
const hasJournalism = installedPackageConfigs.some((pkg) => pkg.type === "journalism");
|
|
15
|
+
const libraryLinks = [
|
|
16
|
+
hasSda
|
|
17
|
+
? "[simple-data-analysis](https://github.com/nshiab/simple-data-analysis)"
|
|
18
|
+
: "",
|
|
19
|
+
hasJournalism ? "[journalism](https://github.com/nshiab/journalism)" : "",
|
|
20
|
+
].filter(Boolean);
|
|
21
|
+
const librarySection = libraryLinks.length === 0
|
|
22
|
+
? ""
|
|
23
|
+
: `It's installing ${libraryLinks.join(" and ")} libraries, with up-to-date
|
|
24
|
+
documentation and AI agent instructions.`;
|
|
25
|
+
const status = ensureManagedSection({
|
|
26
|
+
path: "README.md",
|
|
27
|
+
name: "libraries",
|
|
28
|
+
content: librarySection,
|
|
29
|
+
createContent: (managedSection) => `This repository has been created with
|
|
12
30
|
[setup-data-project](https://github.com/nshiab/setup-data-project/).
|
|
13
31
|
|
|
14
|
-
|
|
15
|
-
[simple-data-analysis](https://github.com/nshiab/simple-data-analysis) and
|
|
16
|
-
[journalism](https://github.com/nshiab/journalism) libraries, with up-to-date
|
|
17
|
-
documentation and AI agent instructions.
|
|
32
|
+
${managedSection}
|
|
18
33
|
|
|
19
34
|
Here's the recommended workflow:
|
|
20
35
|
|
|
@@ -27,12 +42,11 @@ When working on your project, use the following command:
|
|
|
27
42
|
|
|
28
43
|
- \`${runCommand} sda\` will watch your \`sda/main.ts\` and its dependencies. Everytime
|
|
29
44
|
you'll save some changes, the data will be reprocessed.
|
|
30
|
-
- \`${runCommand} clean\` will remove
|
|
31
|
-
if present.
|
|
45
|
+
- \`${runCommand} clean\` will remove cache and temporary files, if present.
|
|
32
46
|
|
|
33
|
-
Have fun
|
|
34
|
-
|
|
35
|
-
if (status === "updated") {
|
|
47
|
+
Have fun!`,
|
|
48
|
+
});
|
|
49
|
+
if (status === "created" || status === "updated") {
|
|
36
50
|
log.info("Updated README.md");
|
|
37
51
|
}
|
|
38
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitignoreEntries.d.ts","sourceRoot":"","sources":["../../src/helpers/gitignoreEntries.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,
|
|
1
|
+
{"version":3,"file":"gitignoreEntries.d.ts","sourceRoot":"","sources":["../../src/helpers/gitignoreEntries.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,UAS7B,CAAC"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export declare const commandRunner: {
|
|
2
2
|
exec: any;
|
|
3
3
|
};
|
|
4
|
+
export declare function fetchPackageDocs(pkg: string, options?: {
|
|
5
|
+
silent?: boolean;
|
|
6
|
+
}): Promise<string | undefined>;
|
|
4
7
|
export declare function installPackagesAndFetchDocs(selectedPackages: string[], options?: {
|
|
5
8
|
silent?: boolean;
|
|
6
9
|
}): Promise<string | void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installPackagesAndFetchDocs.d.ts","sourceRoot":"","sources":["../../src/helpers/installPackagesAndFetchDocs.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,aAAa;;CAEzB,CAAC;AAEF,wBAAsB,2BAA2B,CAC/C,gBAAgB,EAAE,MAAM,EAAE,EAC1B,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"installPackagesAndFetchDocs.d.ts","sourceRoot":"","sources":["../../src/helpers/installPackagesAndFetchDocs.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,aAAa;;CAEzB,CAAC;AAEF,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA4C7B;AAED,wBAAsB,2BAA2B,CAC/C,gBAAgB,EAAE,MAAM,EAAE,EAC1B,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4DxB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { spinner } from "@clack/prompts";
|
|
1
|
+
import { log, spinner } from "@clack/prompts";
|
|
2
2
|
import * as childProcess from "node:child_process";
|
|
3
3
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
@@ -6,6 +6,44 @@ import { getRuntime } from "./getRuntime.js";
|
|
|
6
6
|
export const commandRunner = {
|
|
7
7
|
exec: childProcess.exec,
|
|
8
8
|
};
|
|
9
|
+
export async function fetchPackageDocs(pkg, options = {}) {
|
|
10
|
+
if (!existsSync("docs")) {
|
|
11
|
+
mkdirSync("docs");
|
|
12
|
+
}
|
|
13
|
+
const sFetch = spinner();
|
|
14
|
+
if (!options.silent) {
|
|
15
|
+
sFetch.start("Fetching documentation for " + pkg + "...");
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const repoName = pkg.split("/")[1];
|
|
19
|
+
const url = "https://raw.githubusercontent.com/nshiab/" + repoName +
|
|
20
|
+
"/refs/heads/main/llm.md";
|
|
21
|
+
const response = await fetch(url);
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
if (!options.silent) {
|
|
24
|
+
sFetch.stop("⚠️ No documentation (llm.md) found for " + pkg + ".");
|
|
25
|
+
}
|
|
26
|
+
log.warn(`Documentation for ${pkg} could not be refreshed. Rerun the script ` +
|
|
27
|
+
"later to try again.");
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
const docContent = await response.text();
|
|
31
|
+
writeFileSync(join("docs", repoName + ".md"), docContent);
|
|
32
|
+
if (!options.silent) {
|
|
33
|
+
sFetch.stop("✅ Documentation for " + pkg + " saved!");
|
|
34
|
+
}
|
|
35
|
+
return docContent;
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (!options.silent) {
|
|
39
|
+
sFetch.stop("❌ Failed to fetch documentation for " + pkg + ".");
|
|
40
|
+
}
|
|
41
|
+
log.warn(`Documentation for ${pkg} could not be refreshed. Rerun the script ` +
|
|
42
|
+
"later to try again.");
|
|
43
|
+
console.error(error);
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
9
47
|
export async function installPackagesAndFetchDocs(selectedPackages, options = {}) {
|
|
10
48
|
const runtime = getRuntime();
|
|
11
49
|
if (Array.isArray(selectedPackages) && selectedPackages.length > 0) {
|
|
@@ -52,39 +90,9 @@ export async function installPackagesAndFetchDocs(selectedPackages, options = {}
|
|
|
52
90
|
throw error;
|
|
53
91
|
}
|
|
54
92
|
}
|
|
55
|
-
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
const sFetch = spinner();
|
|
60
|
-
try {
|
|
61
|
-
if (!options.silent) {
|
|
62
|
-
sFetch.start("Fetching documentation for " + pkg + "...");
|
|
63
|
-
}
|
|
64
|
-
const repoName = pkg.split("/")[1];
|
|
65
|
-
const url = "https://raw.githubusercontent.com/nshiab/" + repoName +
|
|
66
|
-
"/refs/heads/main/llm.md";
|
|
67
|
-
const response = await fetch(url);
|
|
68
|
-
if (response.ok) {
|
|
69
|
-
const docContent = await response.text();
|
|
70
|
-
writeFileSync(join("docs", repoName + ".md"), docContent);
|
|
71
|
-
if (!options.silent) {
|
|
72
|
-
sFetch.stop("✅ Documentation for " + pkg + " saved!");
|
|
73
|
-
}
|
|
74
|
-
lastDoc = docContent;
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
if (!options.silent) {
|
|
78
|
-
sFetch.stop("⚠️ No documentation (llm.md) found for " + pkg +
|
|
79
|
-
". Skipping doc fetch.");
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
if (!options.silent) {
|
|
85
|
-
sFetch.stop("❌ Failed to fetch documentation for " + pkg + ".");
|
|
86
|
-
}
|
|
87
|
-
console.error(error);
|
|
93
|
+
const docContent = await fetchPackageDocs(pkg, options);
|
|
94
|
+
if (docContent !== undefined) {
|
|
95
|
+
lastDoc = docContent;
|
|
88
96
|
}
|
|
89
97
|
}
|
|
90
98
|
return lastDoc;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageRegistry.d.ts","sourceRoot":"","sources":["../../src/helpers/packageRegistry.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,KAAK,GAAG,YAAY,GAAG,OAAO,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,kBAAkB,EAAE,aAAa,EAwF7C,CAAC"}
|
|
1
|
+
{"version":3,"file":"packageRegistry.d.ts","sourceRoot":"","sources":["../../src/helpers/packageRegistry.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,KAAK,GAAG,YAAY,GAAG,OAAO,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,kBAAkB,EAAE,aAAa,EAwF7C,CAAC;AAEF,wBAAgB,0BAA0B,CACxC,iBAAiB,EAAE,MAAM,EAAE,GAC1B,aAAa,EAAE,CAGjB"}
|
|
@@ -78,3 +78,7 @@ export const SUPPORTED_PACKAGES = [
|
|
|
78
78
|
hint: "Functions to zip/unzip, sleep, reencode files, create nested directories...",
|
|
79
79
|
},
|
|
80
80
|
];
|
|
81
|
+
export function getInstalledPackageConfigs(installedPackages) {
|
|
82
|
+
const installedSet = new Set(installedPackages);
|
|
83
|
+
return SUPPORTED_PACKAGES.filter((pkg) => installedSet.has(pkg.value));
|
|
84
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type Runtime = "deno" | "node" | "bun";
|
|
2
|
+
export declare class ProjectManifest {
|
|
3
|
+
#private;
|
|
4
|
+
private constructor();
|
|
5
|
+
static open(runtime: Runtime): ProjectManifest;
|
|
6
|
+
reload(): void;
|
|
7
|
+
getInstalledPackages(): string[];
|
|
8
|
+
updateTasks(tasks: Record<string, string>): void;
|
|
9
|
+
}
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=projectManifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projectManifest.d.ts","sourceRoot":"","sources":["../../src/helpers/projectManifest.ts"],"names":[],"mappings":"AAEA,KAAK,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAGvC,qBAAa,eAAe;;IAM1B,OAAO;IAYP,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe;IA6B9C,MAAM,IAAI,IAAI;IAId,oBAAoB,IAAI,MAAM,EAAE;IAgBhC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;CAUjD"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
var _ProjectManifest_path, _ProjectManifest_taskKey, _ProjectManifest_dependencyKeys, _ProjectManifest_config;
|
|
13
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
14
|
+
export class ProjectManifest {
|
|
15
|
+
constructor(path, taskKey, dependencyKeys, config) {
|
|
16
|
+
_ProjectManifest_path.set(this, void 0);
|
|
17
|
+
_ProjectManifest_taskKey.set(this, void 0);
|
|
18
|
+
_ProjectManifest_dependencyKeys.set(this, void 0);
|
|
19
|
+
_ProjectManifest_config.set(this, void 0);
|
|
20
|
+
__classPrivateFieldSet(this, _ProjectManifest_path, path, "f");
|
|
21
|
+
__classPrivateFieldSet(this, _ProjectManifest_taskKey, taskKey, "f");
|
|
22
|
+
__classPrivateFieldSet(this, _ProjectManifest_dependencyKeys, dependencyKeys, "f");
|
|
23
|
+
__classPrivateFieldSet(this, _ProjectManifest_config, config, "f");
|
|
24
|
+
}
|
|
25
|
+
static open(runtime) {
|
|
26
|
+
if (existsSync("deno.json")) {
|
|
27
|
+
return new ProjectManifest("deno.json", "tasks", ["imports"], readManifest("deno.json"));
|
|
28
|
+
}
|
|
29
|
+
if (existsSync("package.json")) {
|
|
30
|
+
return new ProjectManifest("package.json", "scripts", ["dependencies", "devDependencies"], readManifest("package.json"));
|
|
31
|
+
}
|
|
32
|
+
return runtime === "deno"
|
|
33
|
+
? new ProjectManifest("deno.json", "tasks", ["imports"], { tasks: {} })
|
|
34
|
+
: new ProjectManifest("package.json", "scripts", ["dependencies", "devDependencies"], { name: "data-project", type: "module", scripts: {} });
|
|
35
|
+
}
|
|
36
|
+
reload() {
|
|
37
|
+
__classPrivateFieldSet(this, _ProjectManifest_config, readManifest(__classPrivateFieldGet(this, _ProjectManifest_path, "f")), "f");
|
|
38
|
+
}
|
|
39
|
+
getInstalledPackages() {
|
|
40
|
+
const installed = [];
|
|
41
|
+
for (const key of __classPrivateFieldGet(this, _ProjectManifest_dependencyKeys, "f")) {
|
|
42
|
+
const dependencies = __classPrivateFieldGet(this, _ProjectManifest_config, "f")[key];
|
|
43
|
+
if (dependencies && typeof dependencies === "object" &&
|
|
44
|
+
!Array.isArray(dependencies)) {
|
|
45
|
+
installed.push(...Object.keys(dependencies));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return installed;
|
|
49
|
+
}
|
|
50
|
+
updateTasks(tasks) {
|
|
51
|
+
const currentTasks = __classPrivateFieldGet(this, _ProjectManifest_config, "f")[__classPrivateFieldGet(this, _ProjectManifest_taskKey, "f")];
|
|
52
|
+
const existingTasks = currentTasks && typeof currentTasks === "object" &&
|
|
53
|
+
!Array.isArray(currentTasks)
|
|
54
|
+
? currentTasks
|
|
55
|
+
: {};
|
|
56
|
+
__classPrivateFieldGet(this, _ProjectManifest_config, "f")[__classPrivateFieldGet(this, _ProjectManifest_taskKey, "f")] = { ...existingTasks, ...tasks };
|
|
57
|
+
writeFileSync(__classPrivateFieldGet(this, _ProjectManifest_path, "f"), JSON.stringify(__classPrivateFieldGet(this, _ProjectManifest_config, "f"), null, 2), "utf-8");
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
_ProjectManifest_path = new WeakMap(), _ProjectManifest_taskKey = new WeakMap(), _ProjectManifest_dependencyKeys = new WeakMap(), _ProjectManifest_config = new WeakMap();
|
|
61
|
+
function readManifest(path) {
|
|
62
|
+
try {
|
|
63
|
+
const parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
64
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
65
|
+
throw new SyntaxError("the root value must be a JSON object");
|
|
66
|
+
}
|
|
67
|
+
return parsed;
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
const detail = error instanceof Error ? ` ${error.message}` : "";
|
|
71
|
+
throw new Error(`Failed to parse ${path}.${detail}`, { cause: error });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"syncPackageDocs.d.ts","sourceRoot":"","sources":["../../src/helpers/syncPackageDocs.ts"],"names":[],"mappings":"AAMA,wBAAsB,eAAe,CACnC,iBAAiB,EAAE,MAAM,EAAE,EAC3B,oBAAoB,GAAE,MAAM,EAAO,GAClC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA0BjC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { log } from "@clack/prompts";
|
|
2
|
+
import { existsSync, readFileSync, rmSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { fetchPackageDocs } from "./installPackagesAndFetchDocs.js";
|
|
5
|
+
import { SUPPORTED_PACKAGES } from "./packageRegistry.js";
|
|
6
|
+
export async function syncPackageDocs(installedPackages, docsAlreadyRefreshed = []) {
|
|
7
|
+
const installedSet = new Set(installedPackages);
|
|
8
|
+
const refreshedSet = new Set(docsAlreadyRefreshed);
|
|
9
|
+
const docsMapping = {};
|
|
10
|
+
for (const pkg of SUPPORTED_PACKAGES) {
|
|
11
|
+
const docPath = join("docs", pkg.value.split("/")[1] + ".md");
|
|
12
|
+
if (!installedSet.has(pkg.value)) {
|
|
13
|
+
if (existsSync(docPath)) {
|
|
14
|
+
rmSync(docPath);
|
|
15
|
+
log.info(`Removed stale documentation at ${docPath}.`);
|
|
16
|
+
}
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
if (!existsSync(docPath) && !refreshedSet.has(pkg.value)) {
|
|
20
|
+
await fetchPackageDocs(pkg.value, { silent: true });
|
|
21
|
+
}
|
|
22
|
+
if (existsSync(docPath)) {
|
|
23
|
+
docsMapping[pkg.value] = readFileSync(docPath, "utf-8");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return docsMapping;
|
|
27
|
+
}
|
package/esm/main.js
CHANGED
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
import { cancel, intro, isCancel, multiselect, outro, select, spinner, } from "@clack/prompts";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import { getRuntime } from "./helpers/getRuntime.js";
|
|
5
|
-
import { getInstalledPackages } from "./helpers/getInstalledPackages.js";
|
|
6
5
|
import { PACKAGE_OPTIONS } from "./helpers/packageOptions.js";
|
|
7
|
-
import { updateProjectConfig } from "./helpers/updateProjectConfig.js";
|
|
8
6
|
import { ensureGitignore } from "./helpers/ensureGitignore.js";
|
|
9
7
|
import { ensureReadme } from "./helpers/ensureReadme.js";
|
|
10
8
|
import { installPackagesAndFetchDocs } from "./helpers/installPackagesAndFetchDocs.js";
|
|
@@ -12,12 +10,16 @@ import { getProjectTasks } from "./helpers/getProjectTasks.js";
|
|
|
12
10
|
import { createFolderStructure } from "./helpers/createFolderStructure.js";
|
|
13
11
|
import { ensureEnvFile } from "./helpers/ensureEnvFile.js";
|
|
14
12
|
import { ensureAgents } from "./helpers/ensureAgents.js";
|
|
13
|
+
import { getInstalledPackageConfigs } from "./helpers/packageRegistry.js";
|
|
14
|
+
import { ProjectManifest } from "./helpers/projectManifest.js";
|
|
15
|
+
import { syncPackageDocs } from "./helpers/syncPackageDocs.js";
|
|
15
16
|
async function main() {
|
|
16
17
|
const runtime = getRuntime();
|
|
17
18
|
console.log();
|
|
18
19
|
intro(`Hi! 👋 (Running on ${runtime})`);
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
const projectManifest = ProjectManifest.open(runtime);
|
|
21
|
+
projectManifest.updateTasks(getProjectTasks());
|
|
22
|
+
const installedPackages = projectManifest.getInstalledPackages();
|
|
21
23
|
const options = PACKAGE_OPTIONS.map((opt) => ({
|
|
22
24
|
...opt,
|
|
23
25
|
label: installedPackages.includes(opt.value)
|
|
@@ -56,15 +58,11 @@ async function main() {
|
|
|
56
58
|
packagesToInstall.push(pkg);
|
|
57
59
|
}
|
|
58
60
|
}
|
|
59
|
-
const docsMapping = {};
|
|
60
61
|
const sInstall = spinner();
|
|
61
62
|
sInstall.start("Installing packages and fetching documentation...");
|
|
62
63
|
for (const pkg of packagesToInstall) {
|
|
63
64
|
try {
|
|
64
|
-
|
|
65
|
-
if (typeof doc === "string") {
|
|
66
|
-
docsMapping[pkg] = doc;
|
|
67
|
-
}
|
|
65
|
+
await installPackagesAndFetchDocs([pkg], { silent: true });
|
|
68
66
|
}
|
|
69
67
|
catch (error) {
|
|
70
68
|
sInstall.stop(`❌ Failed to install ${pkg}.`);
|
|
@@ -73,12 +71,19 @@ async function main() {
|
|
|
73
71
|
}
|
|
74
72
|
}
|
|
75
73
|
sInstall.stop("✅ Packages installed and documentation fetched.");
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
projectManifest.reload();
|
|
75
|
+
projectManifest.updateTasks(getProjectTasks());
|
|
76
|
+
const finalInstalledPackages = getInstalledPackageConfigs(projectManifest.getInstalledPackages()).map((pkg) => pkg.value);
|
|
77
|
+
const docsMapping = await syncPackageDocs(finalInstalledPackages, packagesToInstall);
|
|
78
|
+
await createFolderStructure(finalInstalledPackages);
|
|
78
79
|
ensureGitignore();
|
|
79
80
|
await ensureEnvFile();
|
|
80
|
-
await ensureReadme(runtime);
|
|
81
|
-
await ensureAgents(docsMapping, runtime);
|
|
81
|
+
await ensureReadme(runtime, finalInstalledPackages);
|
|
82
|
+
await ensureAgents(docsMapping, runtime, finalInstalledPackages);
|
|
82
83
|
outro("You are all set! 🙌");
|
|
83
84
|
}
|
|
84
|
-
main().catch(
|
|
85
|
+
main().catch((error) => {
|
|
86
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
87
|
+
console.error(`❌ Error: ${message}`);
|
|
88
|
+
process.exitCode = 1;
|
|
89
|
+
});
|
package/package.json
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function ensureAgents(docsMapping: Record<string, string>, runtime: string):
|
|
1
|
+
export declare function ensureAgents(docsMapping: Record<string, string>, runtime: string, installedPackages?: string[]): void;
|
|
2
2
|
//# sourceMappingURL=ensureAgents.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ensureAgents.d.ts","sourceRoot":"","sources":["../../src/helpers/ensureAgents.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ensureAgents.d.ts","sourceRoot":"","sources":["../../src/helpers/ensureAgents.ts"],"names":[],"mappings":"AAOA,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,OAAO,EAAE,MAAM,EACf,iBAAiB,GAAE,MAAM,EAA6B,QAuHvD"}
|