@nshiab/setup-data-project 2.0.1 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +15 -7
  2. package/esm/helpers/combinePlotDocs.d.ts +2 -0
  3. package/esm/helpers/combinePlotDocs.d.ts.map +1 -0
  4. package/esm/helpers/combinePlotDocs.js +111 -0
  5. package/esm/helpers/ensureAgents.d.ts.map +1 -1
  6. package/esm/helpers/ensureAgents.js +11 -1
  7. package/esm/helpers/fetchPackageDocs.d.ts +4 -0
  8. package/esm/helpers/fetchPackageDocs.d.ts.map +1 -1
  9. package/esm/helpers/fetchPlotDocs.d.ts +5 -0
  10. package/esm/helpers/fetchPlotDocs.d.ts.map +1 -0
  11. package/esm/helpers/fetchPlotDocs.js +103 -0
  12. package/esm/helpers/getInstalledPackageVersions.d.ts.map +1 -1
  13. package/esm/helpers/getInstalledPackageVersions.js +8 -5
  14. package/esm/helpers/installPackages.d.ts.map +1 -1
  15. package/esm/helpers/installPackages.js +1 -11
  16. package/esm/helpers/packageRegistry.d.ts +1 -0
  17. package/esm/helpers/packageRegistry.d.ts.map +1 -1
  18. package/esm/helpers/packageRegistry.js +12 -7
  19. package/esm/helpers/parseArguments.d.ts +7 -0
  20. package/esm/helpers/parseArguments.d.ts.map +1 -0
  21. package/esm/helpers/parseArguments.js +30 -0
  22. package/esm/helpers/plotDocPages.d.ts +2 -0
  23. package/esm/helpers/plotDocPages.d.ts.map +1 -0
  24. package/esm/helpers/plotDocPages.js +46 -0
  25. package/esm/helpers/syncPackageDocs.d.ts.map +1 -1
  26. package/esm/helpers/syncPackageDocs.js +9 -5
  27. package/esm/main.js +15 -5
  28. package/package.json +1 -1
  29. package/script/helpers/combinePlotDocs.d.ts +2 -0
  30. package/script/helpers/combinePlotDocs.d.ts.map +1 -0
  31. package/script/helpers/combinePlotDocs.js +114 -0
  32. package/script/helpers/ensureAgents.d.ts.map +1 -1
  33. package/script/helpers/ensureAgents.js +11 -1
  34. package/script/helpers/fetchPackageDocs.d.ts +4 -0
  35. package/script/helpers/fetchPackageDocs.d.ts.map +1 -1
  36. package/script/helpers/fetchPlotDocs.d.ts +5 -0
  37. package/script/helpers/fetchPlotDocs.d.ts.map +1 -0
  38. package/script/helpers/fetchPlotDocs.js +106 -0
  39. package/script/helpers/getInstalledPackageVersions.d.ts.map +1 -1
  40. package/script/helpers/getInstalledPackageVersions.js +8 -5
  41. package/script/helpers/installPackages.d.ts.map +1 -1
  42. package/script/helpers/installPackages.js +1 -11
  43. package/script/helpers/packageRegistry.d.ts +1 -0
  44. package/script/helpers/packageRegistry.d.ts.map +1 -1
  45. package/script/helpers/packageRegistry.js +13 -8
  46. package/script/helpers/parseArguments.d.ts +7 -0
  47. package/script/helpers/parseArguments.d.ts.map +1 -0
  48. package/script/helpers/parseArguments.js +34 -0
  49. package/script/helpers/plotDocPages.d.ts +2 -0
  50. package/script/helpers/plotDocPages.d.ts.map +1 -0
  51. package/script/helpers/plotDocPages.js +49 -0
  52. package/script/helpers/syncPackageDocs.d.ts.map +1 -1
  53. package/script/helpers/syncPackageDocs.js +8 -4
  54. package/script/main.js +15 -5
package/README.md CHANGED
@@ -5,7 +5,7 @@ configurations, and documentation.
5
5
 
6
6
  ```sh
7
7
  # Deno
8
- deno run --min-dep-age=0 -A jsr:@nshiab/setup-data-project
8
+ deno run -A jsr:@nshiab/setup-data-project
9
9
 
10
10
  # Node
11
11
  npx @nshiab/setup-data-project
@@ -14,9 +14,17 @@ npx @nshiab/setup-data-project
14
14
  bunx @nshiab/setup-data-project
15
15
  ```
16
16
 
17
- The Deno dependency-age bypass is temporary while the 2.0 dependencies are newly
18
- published. It is tracked for removal in
19
- [issue #15](https://github.com/nshiab/setup-data-project/issues/15).
17
+ To select a library without prompts, add `--sda` or `--sda-core`:
18
+
19
+ ```sh
20
+ deno run -A jsr:@nshiab/setup-data-project --sda
21
+ npx @nshiab/setup-data-project --sda-core
22
+ bunx @nshiab/setup-data-project --sda
23
+ ```
24
+
25
+ These flags still create the usual project files and documentation, preserve
26
+ existing package versions, and cannot be combined. Without a flag, library
27
+ selection is interactive. Use `--help` for usage.
20
28
 
21
29
  - Creates a standardized folder structure.
22
30
  - Ensures necessary files like `.env`, `.gitignore`, and `README.md` exist.
@@ -24,9 +32,9 @@ published. It is tracked for removal in
24
32
  [simple-data-analysis-core](https://github.com/nshiab/simple-data-analysis-core),
25
33
  the full
26
34
  [simple-data-analysis](https://github.com/nshiab/simple-data-analysis/)
27
- package, and [journalism](https://github.com/nshiab/journalism) libraries,
28
- then fetches their README files and complete API documentation from the
29
- matching version tags on GitHub for LLM use.
35
+ package, and [journalism](https://github.com/nshiab/journalism) libraries.
36
+ - Downloads version-matched library documentation for LLM use and links it from
37
+ `AGENTS.md`.
30
38
  - Updates project configuration (e.g., `deno.json` or `package.json`) with
31
39
  relevant tasks.
32
40
 
@@ -0,0 +1,2 @@
1
+ export declare function combinePlotDocs(version: string, documents: Map<string, string>): string;
2
+ //# sourceMappingURL=combinePlotDocs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"combinePlotDocs.d.ts","sourceRoot":"","sources":["../../src/helpers/combinePlotDocs.ts"],"names":[],"mappings":"AAIA,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,MAAM,CA4GR"}
@@ -0,0 +1,111 @@
1
+ import { posix } from "node:path";
2
+ // The Plot source uses ATX headings, explicit VitePress IDs, and Markdown fences.
3
+ // Keep code verbatim; rewrite only prose links and anchors while joining pages.
4
+ export function combinePlotDocs(version, documents) {
5
+ const pages = [...documents.keys()].sort();
6
+ const source = `https://github.com/observablehq/plot/tree/v${version}/docs`;
7
+ const anchors = new Map();
8
+ const sections = new Map();
9
+ const pageId = (page) => `plot-${page.replace(/\.md$/, "").replaceAll("/", "--")}`;
10
+ for (const page of pages) {
11
+ const ids = new Map();
12
+ const headings = [];
13
+ const counts = new Map();
14
+ proseLines(documents.get(page), (line, number) => {
15
+ for (const match of line.matchAll(/\bid=["']([^"']+)["']/g)) {
16
+ ids.set(match[1], `${pageId(page)}--${match[1]}`);
17
+ }
18
+ const heading = line.match(/^ {0,3}#{1,6}\s+(.+?)\s*#*\s*$/);
19
+ if (!heading)
20
+ return line;
21
+ const explicit = heading[1].match(/\{#([^}]+)\}/)?.[1];
22
+ const title = heading[1].replace(/\s*\{#[^}]+\}/g, "");
23
+ const slug = explicit ?? title.replace(/<[^>]*>/g, "")
24
+ .toLowerCase().replace(/[^\p{L}\p{N}_\s-]/gu, "")
25
+ .trim().replace(/\s+/g, "-");
26
+ const count = counts.get(slug) ?? 0;
27
+ counts.set(slug, count + 1);
28
+ const localId = `${slug}${count ? `-${count}` : ""}`;
29
+ const id = `${pageId(page)}--${localId}`;
30
+ ids.set(localId, id);
31
+ headings.push({ line: number, title, id });
32
+ return line;
33
+ });
34
+ anchors.set(page, ids);
35
+ sections.set(page, headings);
36
+ }
37
+ function link(target, page) {
38
+ if (/^(?:[a-z][a-z\d+.-]*:|\/\/)/i.test(target))
39
+ return target;
40
+ const [pathAndQuery, fragment] = target.split("#", 2);
41
+ const path = pathAndQuery.split("?", 1)[0];
42
+ const resolved = path === "" ? page : posix.normalize(path.startsWith("/")
43
+ ? path.slice(1)
44
+ : posix.join(posix.dirname(page), path));
45
+ const markdown = [resolved, `${resolved}.md`, `${resolved}/index.md`]
46
+ .find((candidate) => documents.has(candidate));
47
+ if (markdown) {
48
+ const id = fragment
49
+ ? anchors.get(markdown)?.get(decodeURIComponent(fragment))
50
+ : pageId(markdown);
51
+ if (id)
52
+ return `#${id}`;
53
+ // Preserve an upstream target when a fragment is not a known heading/ID.
54
+ return `${source}/${markdown}${fragment ? `#${fragment}` : ""}`;
55
+ }
56
+ if (resolved.endsWith(".md")) {
57
+ return `${source}/${resolved}${fragment ? `#${fragment}` : ""}`;
58
+ }
59
+ const base = "https://raw.githubusercontent.com/observablehq/plot/" +
60
+ `refs/tags/v${version}/docs/`;
61
+ return path.startsWith("/")
62
+ ? new URL(`public${target}`, base).href
63
+ : new URL(target, `${base}${page}`).href;
64
+ }
65
+ const contents = pages.flatMap((page) => [
66
+ `- [${page}](#${pageId(page)})`,
67
+ ...(sections.get(page) ?? []).map(({ title, id }) => ` - [${title.replace(/[\[\]]/g, "")}](#${id})`),
68
+ ]).join("\n");
69
+ const combined = pages.map((page) => {
70
+ const headings = new Map(sections.get(page).map((heading) => [heading.line, heading]));
71
+ const body = proseLines(documents.get(page), (line, number) => {
72
+ const heading = headings.get(number);
73
+ // Inline code also remains verbatim. Plot's prose links have simple destinations.
74
+ line = line.split(/(`+[^`]*`+)/g).map((part, index) => {
75
+ if (index % 2)
76
+ return part;
77
+ return part.replace(/(\]\()([^\s)]+)([^)]*\))/g, (_, before, target, after) => `${before}${link(target, page)}${after}`).replace(/^( {0,3}\[[^\]]+\]:\s*)(\S+)/, (_, before, target) => `${before}${link(target, page)}`).replace(/(?<!:)\b(href|src)=(["'])([^"']+)\2/g, (_, attr, quote, target) => `${attr}=${quote}${link(target, page)}${quote}`).replace(/\bid=(["'])([^"']+)\1/g, (_, quote, id) => `id=${quote}${anchors.get(page)?.get(id) ?? id}${quote}`);
78
+ }).join("");
79
+ return heading
80
+ ? `<a id="${heading.id}"></a>\n\n${line.replace(/\s*\{#[^}]+\}/g, "")}`
81
+ : line;
82
+ });
83
+ return `<a id="${pageId(page)}"></a>\n\n# ${page}\n\nSource: ${source}/${page}\n\n${body}`;
84
+ }).join("\n\n---\n\n");
85
+ return `# Observable Plot ${version}\n\nPackage: \`@observablehq/plot@${version}\`. Source: [v${version}](${source}).\n\nThis reference combines selected upstream documentation for static charts and maps. Introductory and site pages, interaction helpers, and the Auto and Tip marks are omitted. Vue components and plot fences are retained as source examples. Use the table of contents to find API signatures and examples; links to omitted pages lead to the tagged upstream documentation.\n\n## Table of contents\n\n${contents}\n\n---\n\n${combined}\n\n<!-- setup-data-project:observable-plot:${version}:complete -->\n`;
86
+ }
87
+ function proseLines(content, transform) {
88
+ let fence;
89
+ let script = false;
90
+ return content.split("\n").map((line, number) => {
91
+ const marker = line.match(/^ {0,3}(`{3,}|~{3,})/);
92
+ if (fence) {
93
+ if (marker?.[1][0] === fence.character &&
94
+ marker[1].length >= fence.length && /^ {0,3}(?:`+|~+)\s*$/.test(line))
95
+ fence = undefined;
96
+ return line;
97
+ }
98
+ if (marker) {
99
+ fence = { character: marker[1][0], length: marker[1].length };
100
+ return line;
101
+ }
102
+ if (/^\s*<script\b/.test(line))
103
+ script = true;
104
+ if (script) {
105
+ if (/<\/script>/.test(line))
106
+ script = false;
107
+ return line;
108
+ }
109
+ return transform(line, number);
110
+ }).join("\n");
111
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"ensureAgents.d.ts","sourceRoot":"","sources":["../../src/helpers/ensureAgents.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAOzD,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACxC,OAAO,EAAE,MAAM,EACf,iBAAiB,GAAE,MAAM,EAA6B,QAqLvD"}
1
+ {"version":3,"file":"ensureAgents.d.ts","sourceRoot":"","sources":["../../src/helpers/ensureAgents.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAOzD,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACxC,OAAO,EAAE,MAAM,EACf,iBAAiB,GAAE,MAAM,EAA6B,QA+LvD"}
@@ -100,6 +100,14 @@ Always prioritize the installed ${libraryNames} ${libraryNoun} when relevant.
100
100
  const docs = docsMapping[pkg.value];
101
101
  if (!docs)
102
102
  return [];
103
+ if (docs.plot) {
104
+ return [
105
+ "- `@observablehq/plot`: use Observable Plot to create charts and maps " +
106
+ "with `writeChart` and `writeMap`. Import with " +
107
+ '`import { plot } from "@observablehq/plot";`. ' +
108
+ "Documentation and examples at `./docs/observable-plot/llm.md`",
109
+ ];
110
+ }
103
111
  const repoName = pkg.value.split("/")[1];
104
112
  const availableDocs = [
105
113
  docs.readme === undefined
@@ -115,13 +123,15 @@ Always prioritize the installed ${libraryNames} ${libraryNoun} when relevant.
115
123
  });
116
124
  if (documentationGuidance.length > 0) {
117
125
  libraryGuidance += `
126
+ The \`docs/\` folder contains long, exhaustive library references. Search for the relevant methods or topics, then read only the matching sections and any related definitions or examples you need.
127
+
118
128
  The following documentation was fetched for the exact installed library versions. Consult it when relevant:
119
129
 
120
130
  ${documentationGuidance.join("\n")}
121
131
  `;
122
132
  }
123
133
  if (importExamples.length > 0) {
124
- libraryGuidance += `APIs can be imported with named imports like this:
134
+ libraryGuidance += `APIs can be imported like this:
125
135
  \`\`\`typescript
126
136
  ${importExamples.join("\n")}
127
137
  \`\`\`
@@ -1,6 +1,10 @@
1
1
  export interface PackageDocs {
2
2
  readme?: string;
3
3
  llm?: string;
4
+ plot?: {
5
+ version: string;
6
+ pages: string[];
7
+ };
4
8
  }
5
9
  export declare function fetchPackageDocs(pkg: string, version: string, options?: {
6
10
  silent?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"fetchPackageDocs.d.ts","sourceRoot":"","sources":["../../src/helpers/fetchPackageDocs.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAiBD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,WAAW,CAAC,CA4DtB"}
1
+ {"version":3,"file":"fetchPackageDocs.d.ts","sourceRoot":"","sources":["../../src/helpers/fetchPackageDocs.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAC7C;AAiBD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,WAAW,CAAC,CA4DtB"}
@@ -0,0 +1,5 @@
1
+ import type { PackageDocs } from "./fetchPackageDocs.js";
2
+ export declare function fetchPlotDocs(version: string, options?: {
3
+ preferStored?: boolean;
4
+ }): Promise<PackageDocs>;
5
+ //# sourceMappingURL=fetchPlotDocs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetchPlotDocs.d.ts","sourceRoot":"","sources":["../../src/helpers/fetchPlotDocs.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGzD,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GACvC,OAAO,CAAC,WAAW,CAAC,CAsCtB"}
@@ -0,0 +1,103 @@
1
+ import { log } from "@clack/prompts";
2
+ import { mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { combinePlotDocs } from "./combinePlotDocs.js";
5
+ import { PLOT_DOC_PAGES } from "./plotDocPages.js";
6
+ // Publish one reference only after every tagged page has been fetched.
7
+ export async function fetchPlotDocs(version, options = {}) {
8
+ const tag = `v${version}`;
9
+ const directory = join("docs", "observable-plot");
10
+ try {
11
+ let llm;
12
+ if (options.preferStored !== false) {
13
+ try {
14
+ const response = await fetch("https://raw.githubusercontent.com/nshiab/setup-data-project/" +
15
+ `refs/heads/main/docs-cache/observable-plot/${version}/llm.md`);
16
+ if (response.ok) {
17
+ const cached = await response.text();
18
+ if (isStoredReference(cached, version))
19
+ llm = cached;
20
+ }
21
+ }
22
+ catch {
23
+ // A cache is an optimization. An unavailable cache never blocks the tag.
24
+ }
25
+ }
26
+ if (llm === undefined)
27
+ llm = await generateReference(version);
28
+ mkdirSync(directory, { recursive: true });
29
+ const temporaryPath = join(directory, ".llm.md.tmp");
30
+ try {
31
+ writeFileSync(temporaryPath, llm);
32
+ renameSync(temporaryPath, join(directory, "llm.md"));
33
+ }
34
+ finally {
35
+ rmSync(temporaryPath, { force: true });
36
+ }
37
+ return { llm, plot: { version, pages: [...PLOT_DOC_PAGES] } };
38
+ }
39
+ catch (error) {
40
+ log.warn(`Could not fetch complete Observable Plot documentation for ${tag}. ` +
41
+ "Existing files were preserved, but may not match the installed " +
42
+ "version. Plot documentation will not be included in AGENTS.md. " +
43
+ String(error));
44
+ return {};
45
+ }
46
+ }
47
+ async function generateReference(version) {
48
+ const tag = `v${version}`;
49
+ const pages = PLOT_DOC_PAGES;
50
+ const documents = new Map();
51
+ const failed = [];
52
+ // Fetch in small batches to avoid overwhelming GitHub on the first run.
53
+ for (let offset = 0; offset < pages.length; offset += 8) {
54
+ await Promise.all(pages.slice(offset, offset + 8).map(async (page) => {
55
+ try {
56
+ const url = "https://raw.githubusercontent.com/observablehq/plot/" +
57
+ `refs/tags/${tag}/docs/${page}`;
58
+ const response = await fetch(url);
59
+ if (!response.ok)
60
+ throw new Error(`HTTP ${response.status}`);
61
+ const content = await response.text();
62
+ documents.set(page, content);
63
+ }
64
+ catch {
65
+ failed.push(page);
66
+ }
67
+ }));
68
+ }
69
+ if (failed.length > 0) {
70
+ throw new Error(`Could not fetch ${failed.length} Markdown pages`);
71
+ }
72
+ return combinePlotDocs(version, documents);
73
+ }
74
+ function isStoredReference(content, version) {
75
+ const source = `https://github.com/observablehq/plot/tree/v${version}/docs`;
76
+ const metadata = content.split(/\n\s*\n/)[1]?.replace(/\s+/g, " ");
77
+ if (!content.startsWith(`# Observable Plot ${version}\n\n`) ||
78
+ metadata !==
79
+ `Package: \`@observablehq/plot@${version}\`. Source: [v${version}](${source}).` ||
80
+ !content.trimEnd().endsWith(`<!-- setup-data-project:observable-plot:${version}:complete -->`))
81
+ return false;
82
+ // Match actual page sections, not TOC entries. Require every selected page
83
+ // exactly once and some upstream heading/content after its source record.
84
+ const sections = [
85
+ ...content.matchAll(/<a id="(plot-[^"]+)"><\/a>\n\n# ([^\n]+\.md)\n\nSource:\s+([^\s]+)\n\n/g),
86
+ ];
87
+ if (sections.length !== PLOT_DOC_PAGES.length)
88
+ return false;
89
+ const found = new Set();
90
+ for (let index = 0; index < sections.length; index++) {
91
+ const section = sections[index];
92
+ const page = section[2];
93
+ const id = `plot-${page.replace(/\.md$/, "").replaceAll("/", "--")}`;
94
+ if (!PLOT_DOC_PAGES.includes(page) || found.has(page) || section[1] !== id ||
95
+ section[3] !== `${source}/${page}`)
96
+ return false;
97
+ const body = content.slice(section.index + section[0].length, sections[index + 1]?.index);
98
+ if (!/^#{1,6}\s+\S/m.test(body))
99
+ return false;
100
+ found.add(page);
101
+ }
102
+ return true;
103
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"getInstalledPackageVersions.d.ts","sourceRoot":"","sources":["../../src/helpers/getInstalledPackageVersions.ts"],"names":[],"mappings":"AAKA,wBAAgB,2BAA2B,CACzC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACxC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAuBxB"}
1
+ {"version":3,"file":"getInstalledPackageVersions.d.ts","sourceRoot":"","sources":["../../src/helpers/getInstalledPackageVersions.ts"],"names":[],"mappings":"AAKA,wBAAgB,2BAA2B,CACzC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACxC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA0BxB"}
@@ -8,10 +8,12 @@ export function getInstalledPackageVersions(packageSpecifiers) {
8
8
  : undefined;
9
9
  const versions = {};
10
10
  for (const [pkg, specifier] of Object.entries(packageSpecifiers)) {
11
+ const denoVersion = specifier.startsWith("jsr:") || specifier.startsWith("npm:")
12
+ ? getDenoLockVersion(pkg, specifier, denoLock)
13
+ : undefined;
11
14
  const version = specifier.startsWith("jsr:")
12
- ? getDenoLockVersion(pkg, specifier, denoLock) ??
13
- getExactVersion(specifier)
14
- : getNodeModulesVersion(pkg) ??
15
+ ? denoVersion ?? getExactVersion(specifier)
16
+ : denoVersion ?? getNodeModulesVersion(pkg) ??
15
17
  getPackageLockVersion(pkg, packageLock) ??
16
18
  getBunLockVersion(pkg, bunLock) ??
17
19
  getExactVersion(specifier);
@@ -28,7 +30,7 @@ function getNodeModulesVersion(pkg) {
28
30
  : undefined;
29
31
  }
30
32
  function getDenoLockVersion(pkg, specifier, lock) {
31
- if (!lock || !specifier.startsWith("jsr:"))
33
+ if (!lock)
32
34
  return undefined;
33
35
  const specifiers = asObject(lock.specifiers);
34
36
  if (!specifiers)
@@ -36,7 +38,8 @@ function getDenoLockVersion(pkg, specifier, lock) {
36
38
  const directVersion = specifiers[specifier];
37
39
  if (typeof directVersion === "string")
38
40
  return getExactVersion(directVersion);
39
- const prefix = `jsr:${pkg}@`;
41
+ const protocol = specifier.startsWith("npm:") ? "npm" : "jsr";
42
+ const prefix = `${protocol}:${pkg}@`;
40
43
  const matchingVersions = Object.entries(specifiers)
41
44
  .filter(([key, value]) => key.startsWith(prefix) && typeof value === "string")
42
45
  .flatMap(([, value]) => {
@@ -1 +1 @@
1
- {"version":3,"file":"installPackages.d.ts","sourceRoot":"","sources":["../../src/helpers/installPackages.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,aAAa;;CAEzB,CAAC;AASF,wBAAsB,eAAe,CACnC,gBAAgB,EAAE,MAAM,EAAE,EAC1B,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,IAAI,CAAC,CAmDf"}
1
+ {"version":3,"file":"installPackages.d.ts","sourceRoot":"","sources":["../../src/helpers/installPackages.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,aAAa;;CAEzB,CAAC;AAEF,wBAAsB,eAAe,CACnC,gBAAgB,EAAE,MAAM,EAAE,EAC1B,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,IAAI,CAAC,CA8Cf"}
@@ -4,12 +4,6 @@ import { getRuntime } from "./getRuntime.js";
4
4
  export const commandRunner = {
5
5
  exec: childProcess.exec,
6
6
  };
7
- // Temporary: remove this bypass after the 2.0 release window.
8
- // https://github.com/nshiab/setup-data-project/issues/15
9
- const PACKAGES_WITH_FRESH_DENO_RELEASES = new Set([
10
- "@nshiab/simple-data-analysis-core",
11
- "@nshiab/simple-data-analysis",
12
- ]);
13
7
  export async function installPackages(selectedPackages, options = {}) {
14
8
  const runtime = getRuntime();
15
9
  for (const selectedPackage of selectedPackages) {
@@ -21,12 +15,8 @@ export async function installPackages(selectedPackages, options = {}) {
21
15
  for (const pkg of packagesToInstall) {
22
16
  const s = spinner();
23
17
  const isObservablePlot = pkg === "@observablehq/plot";
24
- const minimumDependencyAgeOption = PACKAGES_WITH_FRESH_DENO_RELEASES.has(pkg) ? " --min-dep-age=0" : "";
25
18
  const installCmd = runtime === "deno"
26
- ? (isObservablePlot
27
- ? "deno add npm:" + pkg
28
- : "deno add" + minimumDependencyAgeOption + " jsr:" +
29
- pkg)
19
+ ? (isObservablePlot ? "deno add npm:" + pkg : "deno add jsr:" + pkg)
30
20
  : runtime === "bun"
31
21
  ? "bun add " + pkg
32
22
  : "npm install " + pkg;
@@ -5,5 +5,6 @@ export interface PackageConfig {
5
5
  hint?: string;
6
6
  }
7
7
  export declare const SUPPORTED_PACKAGES: PackageConfig[];
8
+ export declare const DOCUMENTED_PACKAGES: PackageConfig[];
8
9
  export declare function getInstalledPackageConfigs(installedPackages: string[]): PackageConfig[];
9
10
  //# sourceMappingURL=packageRegistry.d.ts.map
@@ -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;AAEF,wBAAgB,0BAA0B,CACxC,iBAAiB,EAAE,MAAM,EAAE,GAC1B,aAAa,EAAE,CAGjB"}
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;AAGF,eAAO,MAAM,mBAAmB,EAAE,aAAa,EAG9C,CAAC;AAEF,wBAAgB,0BAA0B,CACxC,iBAAiB,EAAE,MAAM,EAAE,GAC1B,aAAa,EAAE,CAGjB"}
@@ -1,16 +1,16 @@
1
1
  export const SUPPORTED_PACKAGES = [
2
- {
3
- value: "@nshiab/simple-data-analysis-core",
4
- label: "simple-data-analysis-core",
5
- type: "sda",
6
- hint: "No fluff. Great for constrained environments, like a cheap server.",
7
- },
8
2
  {
9
3
  value: "@nshiab/simple-data-analysis",
10
4
  label: "simple-data-analysis",
11
5
  type: "sda",
12
6
  hint: "All the core functionality, plus methods for dataviz, AI, Google sheets, etc.",
13
7
  },
8
+ {
9
+ value: "@nshiab/simple-data-analysis-core",
10
+ label: "simple-data-analysis-core",
11
+ type: "sda",
12
+ hint: "No fluff. Great for constrained environments, like a cheap server.",
13
+ },
14
14
  {
15
15
  value: "@nshiab/journalism-ai",
16
16
  label: "journalism-ai",
@@ -78,7 +78,12 @@ export const SUPPORTED_PACKAGES = [
78
78
  hint: "Functions to zip/unzip, sleep, reencode files, create nested directories...",
79
79
  },
80
80
  ];
81
+ // Plot is installed alongside charting libraries, but is not a setup menu option.
82
+ export const DOCUMENTED_PACKAGES = [
83
+ ...SUPPORTED_PACKAGES,
84
+ { value: "@observablehq/plot", label: "Observable Plot", type: "other" },
85
+ ];
81
86
  export function getInstalledPackageConfigs(installedPackages) {
82
87
  const installedSet = new Set(installedPackages);
83
- return SUPPORTED_PACKAGES.filter((pkg) => installedSet.has(pkg.value));
88
+ return DOCUMENTED_PACKAGES.filter((pkg) => installedSet.has(pkg.value));
84
89
  }
@@ -0,0 +1,7 @@
1
+ export interface CliOptions {
2
+ help: boolean;
3
+ package?: string;
4
+ }
5
+ export declare const CLI_HELP = "Usage: setup-data-project [--sda | --sda-core] [--help]\n\n --sda Select simple-data-analysis without prompting.\n --sda-core Select simple-data-analysis-core without prompting.\n -h, --help Show this help and exit.\n\nWithout a package flag, choose packages interactively.\nPackage flags keep existing versions and still set up project files and docs.\n--sda and --sda-core cannot be combined.";
6
+ export declare function parseArguments(args: string[]): CliOptions;
7
+ //# sourceMappingURL=parseArguments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseArguments.d.ts","sourceRoot":"","sources":["../../src/helpers/parseArguments.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,QAAQ,0ZAQoB,CAAC;AAE1C,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAoBzD"}
@@ -0,0 +1,30 @@
1
+ export const CLI_HELP = `Usage: setup-data-project [--sda | --sda-core] [--help]
2
+
3
+ --sda Select simple-data-analysis without prompting.
4
+ --sda-core Select simple-data-analysis-core without prompting.
5
+ -h, --help Show this help and exit.
6
+
7
+ Without a package flag, choose packages interactively.
8
+ Package flags keep existing versions and still set up project files and docs.
9
+ --sda and --sda-core cannot be combined.`;
10
+ export function parseArguments(args) {
11
+ const options = { help: false };
12
+ for (const arg of args) {
13
+ if (arg === "--help" || arg === "-h") {
14
+ options.help = true;
15
+ }
16
+ else if (arg === "--sda" || arg === "--sda-core") {
17
+ const pkg = arg === "--sda"
18
+ ? "@nshiab/simple-data-analysis"
19
+ : "@nshiab/simple-data-analysis-core";
20
+ if (options.package && options.package !== pkg) {
21
+ throw new Error("--sda and --sda-core cannot be combined.");
22
+ }
23
+ options.package = pkg;
24
+ }
25
+ else {
26
+ throw new Error(`Unknown argument: ${arg}. Use --help for usage.`);
27
+ }
28
+ }
29
+ return options;
30
+ }
@@ -0,0 +1,2 @@
1
+ export declare const PLOT_DOC_PAGES: string[];
2
+ //# sourceMappingURL=plotDocPages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plotDocPages.d.ts","sourceRoot":"","sources":["../../src/helpers/plotDocPages.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc,EAAE,MAAM,EA2C3B,CAAC"}
@@ -0,0 +1,46 @@
1
+ // Static chart creation references. Keep this explicit so new upstream pages do
2
+ // not silently expand the installed agent reference.
3
+ export const PLOT_DOC_PAGES = [
4
+ "features/plots.md",
5
+ "features/marks.md",
6
+ "features/scales.md",
7
+ "features/projections.md",
8
+ "features/legends.md",
9
+ "features/facets.md",
10
+ "features/formats.md",
11
+ "features/curves.md",
12
+ "transforms/bin.md",
13
+ "transforms/group.md",
14
+ "transforms/stack.md",
15
+ "transforms/normalize.md",
16
+ "transforms/centroid.md",
17
+ "transforms/sort.md",
18
+ "marks/area.md",
19
+ "marks/arrow.md",
20
+ "marks/axis.md",
21
+ "marks/bar.md",
22
+ "marks/bollinger.md",
23
+ "marks/box.md",
24
+ "marks/cell.md",
25
+ "marks/contour.md",
26
+ "marks/delaunay.md",
27
+ "marks/density.md",
28
+ "marks/difference.md",
29
+ "marks/dot.md",
30
+ "marks/frame.md",
31
+ "marks/geo.md",
32
+ "marks/grid.md",
33
+ "marks/hexgrid.md",
34
+ "marks/image.md",
35
+ "marks/line.md",
36
+ "marks/linear-regression.md",
37
+ "marks/link.md",
38
+ "marks/raster.md",
39
+ "marks/rect.md",
40
+ "marks/rule.md",
41
+ "marks/text.md",
42
+ "marks/tick.md",
43
+ "marks/tree.md",
44
+ "marks/vector.md",
45
+ "marks/waffle.md",
46
+ ].sort();
@@ -1 +1 @@
1
- {"version":3,"file":"syncPackageDocs.d.ts","sourceRoot":"","sources":["../../src/helpers/syncPackageDocs.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAG3E,wBAAsB,eAAe,CACnC,iBAAiB,EAAE,MAAM,EAAE,EAC3B,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACxC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CA+CtC"}
1
+ {"version":3,"file":"syncPackageDocs.d.ts","sourceRoot":"","sources":["../../src/helpers/syncPackageDocs.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAI3E,wBAAsB,eAAe,CACnC,iBAAiB,EAAE,MAAM,EAAE,EAC3B,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACxC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAkDtC"}
@@ -2,12 +2,14 @@ import { log } from "@clack/prompts";
2
2
  import { existsSync, mkdirSync, renameSync, rmSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  import { fetchPackageDocs } from "./fetchPackageDocs.js";
5
- import { SUPPORTED_PACKAGES } from "./packageRegistry.js";
5
+ import { fetchPlotDocs } from "./fetchPlotDocs.js";
6
+ import { DOCUMENTED_PACKAGES } from "./packageRegistry.js";
6
7
  export async function syncPackageDocs(installedPackages, installedVersions) {
7
8
  const installedSet = new Set(installedPackages);
8
9
  const docsMapping = {};
9
- for (const pkg of SUPPORTED_PACKAGES) {
10
- const repoName = pkg.value.split("/")[1];
10
+ for (const pkg of DOCUMENTED_PACKAGES) {
11
+ const isPlot = pkg.value === "@observablehq/plot";
12
+ const repoName = isPlot ? "observable-plot" : pkg.value.split("/")[1];
11
13
  const docsDirectory = join("docs", repoName);
12
14
  const llmDocsPath = join(docsDirectory, "llm.md");
13
15
  const legacyDocsPath = join("docs", repoName + ".md");
@@ -37,8 +39,10 @@ export async function syncPackageDocs(installedPackages, installedVersions) {
37
39
  "included in AGENTS.md.");
38
40
  continue;
39
41
  }
40
- const docs = await fetchPackageDocs(pkg.value, version, { silent: true });
41
- if (docs.readme !== undefined || docs.llm !== undefined) {
42
+ const docs = isPlot
43
+ ? await fetchPlotDocs(version)
44
+ : await fetchPackageDocs(pkg.value, version, { silent: true });
45
+ if (docs.readme !== undefined || docs.llm !== undefined || docs.plot) {
42
46
  docsMapping[pkg.value] = docs;
43
47
  }
44
48
  }
package/esm/main.js CHANGED
@@ -14,7 +14,13 @@ import { getInstalledPackageConfigs } from "./helpers/packageRegistry.js";
14
14
  import { ProjectManifest } from "./helpers/projectManifest.js";
15
15
  import { syncPackageDocs } from "./helpers/syncPackageDocs.js";
16
16
  import { getInstalledPackageVersions } from "./helpers/getInstalledPackageVersions.js";
17
+ import { CLI_HELP, parseArguments } from "./helpers/parseArguments.js";
17
18
  async function main() {
19
+ const cliOptions = parseArguments(process.argv.slice(2));
20
+ if (cliOptions.help) {
21
+ console.log(CLI_HELP);
22
+ return;
23
+ }
18
24
  const runtime = getRuntime();
19
25
  console.log();
20
26
  intro(`Hi! 👋 (Running on ${runtime})`);
@@ -27,11 +33,13 @@ async function main() {
27
33
  ? `${opt.label} \x1b[2m(installed)\x1b[22m`
28
34
  : opt.label,
29
35
  }));
30
- const selectedPackages = (await multiselect({
31
- message: "Which libraries would you like to install?\n\x1b[2m(space to select, arrows to navigate, enter to confirm)\x1b[22m\n",
32
- options,
33
- required: false,
34
- }));
36
+ const selectedPackages = cliOptions.package
37
+ ? [cliOptions.package]
38
+ : (await multiselect({
39
+ message: "Which libraries would you like to install?\n\x1b[2m(space to select, arrows to navigate, enter to confirm)\x1b[22m\n",
40
+ options,
41
+ required: false,
42
+ }));
35
43
  if (isCancel(selectedPackages)) {
36
44
  cancel("Installation cancelled.");
37
45
  process.exit(0);
@@ -40,6 +48,8 @@ async function main() {
40
48
  const packagesToInstall = [];
41
49
  for (const pkg of selectedPackages) {
42
50
  if (alreadyInstalled.includes(pkg)) {
51
+ if (cliOptions.package)
52
+ continue;
43
53
  const action = await select({
44
54
  message: `${pkg} is already installed. What would you like to do?`,
45
55
  options: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nshiab/setup-data-project",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "description": "Quickly kick off a project using simple-data-analysis-core, simple-data-analysis, and journalism libraries.",
5
5
  "repository": {
6
6
  "type": "git",