create-thally-docs 0.8.0 → 0.8.1

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/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # create-thally-docs
2
2
 
3
- Scaffold a new [Thally](https://github.com/thallylabs/thally) documentation project an
4
- agent-native docs site that serves every page to humans as polished HTML and to
5
- AI agents as structured JSON, JSON-LD, and Markdown from the same URL.
3
+ Scaffold the first customer-facing knowledge surface in a
4
+ [Thally](https://github.com/thallylabs/thally) product-knowledge pipeline. The
5
+ result is an open documentation site that serves every page to humans as
6
+ polished HTML and to agents as structured JSON, JSON-LD, and Markdown from the
7
+ same URL.
6
8
 
7
9
  ## Quick start
8
10
 
@@ -45,9 +47,14 @@ interactive question explicitly.
45
47
  | `create-thally-docs translate --locale <code>` | Translate content into another locale |
46
48
 
47
49
  Interactive migrations ask whether the source is Mintlify, Docusaurus, or
48
- another auto-detected platform. For scripts and CI, pass
50
+ another auto-detected platform. When automatic detection receives a live
51
+ website URL, the CLI recommends its source GitHub repository and requires
52
+ confirmation before continuing with the less precise website crawl. For
53
+ scripts and CI, pass
49
54
  `--platform mintlify`, `--platform docusaurus`, or `--platform auto`; `--yes`
50
55
  keeps backward-compatible auto-detection when no platform flag is supplied.
56
+ Explicit `--platform auto` and `--yes` runs print the live-site limitation
57
+ without introducing an interactive prompt.
51
58
 
52
59
  Prefer a single binary? Install [`@thallylabs/cli`](https://www.npmjs.com/package/@thallylabs/cli)
53
60
  and use `thally init`, which delegates here.
@@ -23,6 +23,8 @@ var EXCLUDE_PATHS = [
23
23
  "/.next/",
24
24
  "/.data/",
25
25
  "/.thally/",
26
+ // The first-party docs deployment pins its own canonical origin.
27
+ "/.env.production",
26
28
  "/thally-track.yml",
27
29
  "/CODEOWNERS",
28
30
  "/CLAUDE.md",
@@ -3,7 +3,7 @@ import {
3
3
  initGit,
4
4
  installDeps,
5
5
  scaffold
6
- } from "./chunk-5GIGIHI5.js";
6
+ } from "./chunk-RS6U2GSX.js";
7
7
 
8
8
  // src/migrate/index.ts
9
9
  import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  migrateDocs
4
- } from "./chunk-PZBQS5ZR.js";
4
+ } from "./chunk-SDZZYPSN.js";
5
5
  import {
6
6
  logo,
7
7
  readDocsJson,
@@ -9,15 +9,18 @@ import {
9
9
  slugify,
10
10
  success,
11
11
  writeDocsJson
12
- } from "./chunk-5GIGIHI5.js";
12
+ } from "./chunk-RS6U2GSX.js";
13
13
 
14
14
  // src/index.ts
15
15
  import { existsSync as existsSync3, readdirSync as readdirSync2 } from "fs";
16
16
  import { resolve as resolve2 } from "path";
17
17
 
18
18
  // src/prompts.ts
19
- import { input, select } from "@inquirer/prompts";
19
+ import { confirm, input, select } from "@inquirer/prompts";
20
20
  import { basename, resolve } from "path";
21
+ import {
22
+ parseGitHubRepositoryUrl
23
+ } from "@thallylabs/migrate";
21
24
  function parseMigrationPlatform(value) {
22
25
  if (!value || value === "auto") return void 0;
23
26
  if (value === "mintlify" || value === "docusaurus") return value;
@@ -36,6 +39,54 @@ async function gatherMigrationPlatform(value, useDefaults) {
36
39
  default: "mintlify"
37
40
  });
38
41
  }
42
+ var LIVE_URL_MIGRATION_WARNING = "Live website migration reconstructs documentation from public output and may need manual alignment. A source GitHub repository produces a more accurate migration. Use the Thally MCP afterward if the generated project needs refinement.";
43
+ function validateGitHubRepositorySource(value) {
44
+ try {
45
+ parseGitHubRepositoryUrl(value);
46
+ return true;
47
+ } catch (error) {
48
+ return error instanceof Error ? error.message : "Enter a valid public GitHub repository URL.";
49
+ }
50
+ }
51
+ async function resolveAutoDetectedMigrationSource(sourceUrl, shouldPrompt) {
52
+ const source = new URL(sourceUrl);
53
+ if (source.hostname.toLowerCase() === "github.com") return sourceUrl;
54
+ console.warn(`
55
+ \u26A0 ${LIVE_URL_MIGRATION_WARNING}`);
56
+ if (!shouldPrompt) return sourceUrl;
57
+ const sourcePreference = await select({
58
+ message: " Which source should Thally migrate?",
59
+ choices: [
60
+ {
61
+ name: "Source GitHub repository (recommended)",
62
+ value: "github"
63
+ },
64
+ {
65
+ name: "Continue with the live website URL",
66
+ value: "website"
67
+ }
68
+ ],
69
+ default: "github"
70
+ });
71
+ if (sourcePreference === "github") {
72
+ const repositoryUrl = await input({
73
+ message: " GitHub repository URL:",
74
+ validate: validateGitHubRepositorySource
75
+ });
76
+ parseGitHubRepositoryUrl(repositoryUrl);
77
+ return repositoryUrl;
78
+ }
79
+ const hasAcceptedAlignment = await confirm({
80
+ message: " Continue knowing the migration may need manual alignment, using the Thally MCP afterward if needed?",
81
+ default: false
82
+ });
83
+ if (!hasAcceptedAlignment) {
84
+ throw new Error(
85
+ "Migration cancelled. Re-run with the source GitHub repository for the most accurate result."
86
+ );
87
+ }
88
+ return sourceUrl;
89
+ }
39
90
  async function gatherAnswers(dirArg, useDefaults, installPreference) {
40
91
  let projectDir;
41
92
  if (dirArg) {
@@ -131,13 +182,26 @@ async function gatherAnswers(dirArg, useDefaults, installPreference) {
131
182
  }
132
183
 
133
184
  // src/index.ts
134
- import { parseGitHubRepositoryUrl } from "@thallylabs/migrate";
185
+ import { parseGitHubRepositoryUrl as parseGitHubRepositoryUrl2 } from "@thallylabs/migrate";
135
186
 
136
187
  // src/check.ts
137
188
  import { existsSync, readFileSync, readdirSync, statSync } from "fs";
138
189
  import { join, extname, relative } from "path";
139
190
  import { execFileSync } from "child_process";
191
+
192
+ // src/frontmatter.ts
140
193
  import matter from "gray-matter";
194
+ var FRONTMATTER_OPTIONS = {
195
+ engines: {
196
+ javascript: () => ({}),
197
+ js: () => ({})
198
+ }
199
+ };
200
+ function parseFrontmatter(raw) {
201
+ return matter(raw, FRONTMATTER_OPTIONS);
202
+ }
203
+
204
+ // src/check.ts
141
205
  import { parse as parseYaml } from "yaml";
142
206
  function gitLocal(projectDir, args2) {
143
207
  try {
@@ -373,7 +437,7 @@ async function runCheck(projectDir, options) {
373
437
  let lineOffset = 0;
374
438
  try {
375
439
  const raw = readFileSync(filePath, "utf8");
376
- const parsed = matter(raw);
440
+ const parsed = parseFrontmatter(raw);
377
441
  data = parsed.data;
378
442
  content = parsed.content;
379
443
  lineOffset = raw.slice(0, raw.indexOf(content)).split("\n").length - 1;
@@ -474,7 +538,6 @@ thally check: ${errors.length} error(s), ${warnings.length} warning(s)`);
474
538
  import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2, mkdirSync } from "fs";
475
539
  import { join as join2, dirname } from "path";
476
540
  import { input as input2 } from "@inquirer/prompts";
477
- import matter2 from "gray-matter";
478
541
  import Anthropic from "@anthropic-ai/sdk";
479
542
  import pLimit from "p-limit";
480
543
  function readDocsJson2(projectDir) {
@@ -654,11 +717,11 @@ async function runTranslateCommand(locale, pages, force, apiKey, model, yes, pro
654
717
  }
655
718
  console.log("");
656
719
  if (!yes) {
657
- const confirm = await input2({
720
+ const confirm2 = await input2({
658
721
  message: " Proceed? (Y/n):",
659
722
  default: "Y"
660
723
  });
661
- if (confirm.toLowerCase() === "n") {
724
+ if (confirm2.toLowerCase() === "n") {
662
725
  console.log("\n Aborted.");
663
726
  return;
664
727
  }
@@ -672,7 +735,7 @@ async function runTranslateCommand(locale, pages, force, apiKey, model, yes, pro
672
735
  ({ pageId, sourceFile, targetFile }) => limit(async () => {
673
736
  try {
674
737
  const sourceContent = readFileSync2(sourceFile, "utf8");
675
- const parsed = matter2(sourceContent);
738
+ const parsed = parseFrontmatter(sourceContent);
676
739
  if (!parsed.data.title) {
677
740
  console.warn(` \u26A0 ${pageId}: missing title in frontmatter \u2014 translating anyway`);
678
741
  }
@@ -732,7 +795,7 @@ function getFlagValue(flag) {
732
795
  return void 0;
733
796
  }
734
797
  async function runMigrateCommand() {
735
- const sourceUrl = positional[1];
798
+ let sourceUrl = positional[1];
736
799
  if (!sourceUrl) {
737
800
  console.error("\n \u274C Source URL is required.");
738
801
  console.error(" Usage: create-thally-docs migrate <github-or-docs-url> [output-dir] [options]");
@@ -743,12 +806,22 @@ async function runMigrateCommand() {
743
806
  try {
744
807
  source = new URL(sourceUrl);
745
808
  if (!["http:", "https:"].includes(source.protocol)) throw new Error("Only HTTP and HTTPS sources are supported.");
746
- if (source.hostname.toLowerCase() === "github.com") parseGitHubRepositoryUrl(sourceUrl);
809
+ if (source.hostname.toLowerCase() === "github.com") parseGitHubRepositoryUrl2(sourceUrl);
747
810
  } catch (err) {
748
811
  console.error(`
749
812
  \u274C ${err instanceof Error ? err.message : err}`);
750
813
  process.exit(1);
751
814
  }
815
+ const branch = getFlagValue("--branch");
816
+ const docsDir = getFlagValue("--docs-dir");
817
+ const yes = flags.includes("--yes") || flags.includes("-y");
818
+ const platformFlag = getFlagValue("--platform");
819
+ const platform = await gatherMigrationPlatform(platformFlag, yes);
820
+ if (platform === void 0) {
821
+ const shouldPromptForSource = platformFlag === void 0 && !yes;
822
+ sourceUrl = await resolveAutoDetectedMigrationSource(sourceUrl, shouldPromptForSource);
823
+ source = new URL(sourceUrl);
824
+ }
752
825
  const apiKey = getFlagValue("--api-key") ?? process.env.ANTHROPIC_API_KEY;
753
826
  const intoDir = getFlagValue("--into");
754
827
  const isInto = Boolean(intoDir);
@@ -758,13 +831,9 @@ async function runMigrateCommand() {
758
831
  } else if (positional[2]) {
759
832
  projectDir = resolve2(positional[2]);
760
833
  } else {
761
- const sourceName = source.hostname.toLowerCase() === "github.com" ? parseGitHubRepositoryUrl(sourceUrl).repo : source.pathname.split("/").filter(Boolean).at(-1) ?? source.hostname.split(".")[0];
834
+ const sourceName = source.hostname.toLowerCase() === "github.com" ? parseGitHubRepositoryUrl2(sourceUrl).repo : source.pathname.split("/").filter(Boolean).at(-1) ?? source.hostname.split(".")[0];
762
835
  projectDir = resolve2(`${slugify(sourceName)}-docs`);
763
836
  }
764
- const branch = getFlagValue("--branch");
765
- const docsDir = getFlagValue("--docs-dir");
766
- const yes = flags.includes("--yes") || flags.includes("-y");
767
- const platform = await gatherMigrationPlatform(getFlagValue("--platform"), yes);
768
837
  const maxPagesValue = getFlagValue("--max-pages");
769
838
  const maxPages = maxPagesValue ? Number(maxPagesValue) : void 0;
770
839
  if (maxPages !== void 0 && (!Number.isInteger(maxPages) || maxPages < 1 || maxPages > 1e3)) {
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  migrateDocs
4
- } from "../chunk-PZBQS5ZR.js";
5
- import "../chunk-5GIGIHI5.js";
4
+ } from "../chunk-SDZZYPSN.js";
5
+ import "../chunk-RS6U2GSX.js";
6
6
  export {
7
7
  migrateDocs
8
8
  };
package/dist/scaffold.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  scaffold
4
- } from "./chunk-5GIGIHI5.js";
4
+ } from "./chunk-RS6U2GSX.js";
5
5
  export {
6
6
  scaffold
7
7
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-thally-docs",
3
- "version": "0.8.0",
4
- "description": "Scaffold a new Thally documentation project",
3
+ "version": "0.8.1",
4
+ "description": "Scaffold the first documentation surface in a Thally product-knowledge pipeline.",
5
5
  "type": "module",
6
6
  "engines": {
7
7
  "node": ">=18"