docugate 0.4.1 → 0.4.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/README.md CHANGED
@@ -147,7 +147,7 @@ On Pro it carries on:
147
147
  7. Asks where the API console sends requests from: the reader's browser, or through DocuGate with no CORS setup.
148
148
  8. Switches on API keys, with a scope per OpenAPI tag to start from, makes the verify secret, offers to put it in `.env` when git ignores that file, and prints the lines your Express, Hono or Fastify backend needs.
149
149
 
150
- Everything it sets stays editable in the space's settings on [trydocugate.site](https://www.trydocugate.site/dashboard).
150
+ Everything it sets stays editable in the space's settings on [trydocugate.site](https://trydocugate.site/dashboard).
151
151
 
152
152
  ## Docs that keep up with your code
153
153
 
@@ -412,11 +412,11 @@ cd server && npx docugate connect # pick the project, or start a new one
412
412
  cd ../public && npx docugate connect # pick the same project
413
413
  ```
414
414
 
415
- The first codebase's docs sit at the top of the project's space; each one after it gets a section named after what it is (`frontend/`, `backend/`), so two pages with the same name cannot clash. A docs folder the space already reads is not added twice. Change the sections, or add repositories by hand, in a space's settings on [trydocugate.site](https://www.trydocugate.site/dashboard). Feeding one project from several codebases needs Pro or an organization plan.
415
+ The first codebase's docs sit at the top of the project's space; each one after it gets a section named after what it is (`frontend/`, `backend/`), so two pages with the same name cannot clash. A docs folder the space already reads is not added twice. Change the sections, or add repositories by hand, in a space's settings on [trydocugate.site](https://trydocugate.site/dashboard). Feeding one project from several codebases needs Pro or an organization plan.
416
416
 
417
417
  Run `init` and `check` in each repository that contributes docs, and answer the role question in each: the tour lives in the frontend, and its `source` lines can point into the backend. Every one gets its own `docugate.json`, naming its own docs folder. `check` reads the repository it is run in, which is why its 300-page limit is per repository rather than per space.
418
418
 
419
- See [Merging repositories](https://www.trydocugate.site/docs/merging-repositories).
419
+ See [Merging repositories](https://trydocugate.site/docs/merging-repositories).
420
420
 
421
421
  ---
422
422
 
@@ -471,7 +471,7 @@ const verdict = await verifyKey(key, { secret: process.env.DOCUGATE_VERIFY_SECRE
471
471
  if (!verdict.valid) return deny(verdict.code) // REVOKED, EXPIRED, USAGE_EXCEEDED, ...
472
472
  ```
473
473
 
474
- `verifyKey` answers for every key, valid or not, and throws a `KeyServiceError` only when it could not get an answer. By default every request asks DocuGate, which is what makes a revoked key stop at once; `cacheSeconds` trades that for speed, and `failOpen` decides what happens when DocuGate cannot be reached (by default, the request is refused). The options, the exact request, and what each result means are in [API keys](https://www.trydocugate.site/docs/api-keys).
474
+ `verifyKey` answers for every key, valid or not, and throws a `KeyServiceError` only when it could not get an answer. By default every request asks DocuGate, which is what makes a revoked key stop at once; `cacheSeconds` trades that for speed, and `failOpen` decides what happens when DocuGate cannot be reached (by default, the request is refused). The options, the exact request, and what each result means are in [API keys](https://trydocugate.site/docs/api-keys).
475
475
 
476
476
  ---
477
477
 
@@ -488,7 +488,7 @@ One per repository, at its root.
488
488
  | `sync` | Settings for `docugate sync`; see [Docs that keep up with your code](#docs-that-keep-up-with-your-code). The DocuGate site ignores it. |
489
489
  | `sidebar` | File and folder names in the order the sidebar should show them. Orders this repository's own pages, not the whole space. |
490
490
  | `api.generate` | Defaults for `docugate openapi`. |
491
- | `api.spec` | Where the OpenAPI file is, for a repository that does not keep it at `openapi.json` in the root or the docs folder. DocuGate draws an [API reference](https://www.trydocugate.site/docs/api-reference) from it. |
491
+ | `api.spec` | Where the OpenAPI file is, for a repository that does not keep it at `openapi.json` in the root or the docs folder. DocuGate draws an [API reference](https://trydocugate.site/docs/api-reference) from it. |
492
492
 
493
493
  ---
494
494
 
package/dist/api.js CHANGED
@@ -22,7 +22,7 @@ export function detectAgent(env = process.env) {
22
22
  return 'Terminal';
23
23
  }
24
24
  /** Module-level default, captured at import time (used by CLI commands). */
25
- export const BASE_URL = process.env.DOCUGATE_URL ?? 'https://www.trydocugate.site';
25
+ export const BASE_URL = process.env.DOCUGATE_URL ?? 'https://trydocugate.site';
26
26
  const ERROR_MESSAGES = {
27
27
  pro_required_sources: 'Connecting more than one repository to a space needs DocuGate Pro',
28
28
  space_limit: 'The free plan has one space. Connect this repository to it, or upgrade to Pro',
@@ -60,8 +60,18 @@ export async function apiFetch(path, init = {}) {
60
60
  headers['x-docugate-version'] = CLI_VERSION;
61
61
  }
62
62
  // Re-read the env at call time so tests that set DOCUGATE_URL after import work.
63
- const base = process.env.DOCUGATE_URL ?? 'https://www.trydocugate.site';
64
- const res = await fetch(`${base}${path}`, { ...init, headers });
63
+ const base = process.env.DOCUGATE_URL ?? 'https://trydocugate.site';
64
+ let res = await fetch(`${base}${path}`, { ...init, headers, redirect: 'manual' });
65
+ // fetch drops the Authorization header when a redirect changes host, so a
66
+ // move between www.trydocugate.site and trydocugate.site read as signed out.
67
+ // Followed here instead, once, and only between two names of the same site.
68
+ const moved = res.status >= 301 && res.status <= 308 ? res.headers.get('location') : null;
69
+ if (moved) {
70
+ const to = new URL(moved, base);
71
+ const bare = (host) => host.replace(/^www\./, '');
72
+ if (to.protocol === 'https:' && bare(to.host) === bare(new URL(base).host))
73
+ res = await fetch(to, { ...init, headers, redirect: 'manual' });
74
+ }
65
75
  // Renew token if the server sent a fresh one.
66
76
  const renewed = res.headers.get('x-docugate-token');
67
77
  if (renewed && !envToken)
package/dist/cli.js CHANGED
@@ -23,7 +23,7 @@ import { startTourServer } from './tour-server.js';
23
23
  import { login, clearCredentials, loadCredentials } from './auth.js';
24
24
  import { BASE_URL, getSession } from './api.js';
25
25
  import { dim, gold, green, hint, isMintty, plural, red, suggest, yellow } from './ui.js';
26
- const SITE = 'https://www.trydocugate.site';
26
+ const SITE = 'https://trydocugate.site';
27
27
  /** True while the launch menu is running: its commands do not print their own "Next". */
28
28
  let inMenu = false;
29
29
  function fail(message, tip) {
@@ -13,7 +13,7 @@ import { bold, dim, gold, green, plural, yellow } from './ui.js';
13
13
  // console sends requests, switches on API keys and hands over the verify
14
14
  // secret with the lines the backend needs. Every step says what it is about to
15
15
  // do, and nothing that already exists is overwritten.
16
- const SITE = 'https://www.trydocugate.site';
16
+ const SITE = 'https://trydocugate.site';
17
17
  /** Folders never worth walking for a spec. */
18
18
  const SKIP = new Set(['node_modules', '.git', 'dist', 'build', '.next', 'out', 'coverage', 'vendor', '.venv', 'venv', 'target']);
19
19
  /** File names that are, by convention, an API description. */
package/dist/init.js CHANGED
@@ -480,7 +480,7 @@ export async function initFlow(root, options = {}) {
480
480
  saveRole(root, role);
481
481
  }
482
482
  // ── Step 3: sign in and connect this repository ───────────────────────────
483
- const BASE_URL = options.baseUrl ?? process.env.DOCUGATE_URL ?? 'https://www.trydocugate.site';
483
+ const BASE_URL = options.baseUrl ?? process.env.DOCUGATE_URL ?? 'https://trydocugate.site';
484
484
  let connectError;
485
485
  // In CI (no TTY) skip sign-in entirely (hint already printed in the early-return branch above).
486
486
  if (!io.isTTY) {
package/dist/keys/core.js CHANGED
@@ -9,7 +9,7 @@ import { looksLikeKey } from './format.js';
9
9
  * request. This file is that question and what to do with the answer. The
10
10
  * adapters for Express, Hono and Fastify are a few lines on top of it.
11
11
  */
12
- const DEFAULT_BASE_URL = 'https://www.trydocugate.site';
12
+ const DEFAULT_BASE_URL = 'https://trydocugate.site';
13
13
  /** DocuGate could not be asked, or refused to answer. Never means a key is bad. */
14
14
  export class KeyServiceError extends Error {
15
15
  constructor(message, options) {
package/dist/project.js CHANGED
@@ -18,7 +18,7 @@ import { bold, dim, green, plural, red, yellow } from './ui.js';
18
18
  export const PROJECT_TYPES = ['frontend', 'backend', 'serverless', 'monorepo'];
19
19
  export const FREQUENCIES = ['push', 'daily', 'weekly', 'off'];
20
20
  const TOKENS_FILE = () => join(process.env.DOCUGATE_HOME ?? join(homedir(), '.docugate'), 'projects.json');
21
- const base = () => process.env.DOCUGATE_URL ?? 'https://www.trydocugate.site';
21
+ const base = () => process.env.DOCUGATE_URL ?? 'https://trydocugate.site';
22
22
  function readTokens() {
23
23
  try {
24
24
  return JSON.parse(readFileSync(TOKENS_FILE(), 'utf8'));
package/dist/sync/run.js CHANGED
@@ -90,7 +90,7 @@ export async function runSync(root, options = {}, deps = {}) {
90
90
  writeSyncState(root, { lastSha: changes.to, lastRunAt: (deps.now ?? new Date()).toISOString() });
91
91
  if (options.pr) {
92
92
  const prFn = deps.prFn ?? defaultPr({ git, env });
93
- const siteUrl = env.DOCUGATE_URL ?? 'https://www.trydocugate.site';
93
+ const siteUrl = env.DOCUGATE_URL ?? 'https://trydocugate.site';
94
94
  result.pr = await prFn({
95
95
  root,
96
96
  title: `docs: sync with code changes (${changes.commits.length} commit${changes.commits.length === 1 ? '' : 's'})`,
@@ -104,7 +104,7 @@ export function publishedDocsUrl(root) {
104
104
  const space = loadConfig(root).config.space;
105
105
  if (!space || !/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(space))
106
106
  return undefined;
107
- return `${process.env.DOCUGATE_URL ?? 'https://www.trydocugate.site'}/${space}`;
107
+ return `${process.env.DOCUGATE_URL ?? 'https://trydocugate.site'}/${space}`;
108
108
  }
109
109
  function handleGetEvents(req, res, root) {
110
110
  const tourDir = join(root, '.docugate', 'tour');
@@ -379,13 +379,13 @@ export function startTourServer(root, port) {
379
379
  // Somebody opened the tour server itself. Say what it is and where to go.
380
380
  const screens = loadTours(root).length;
381
381
  res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
382
- res.end(`<!doctype html><html lang="en"><head><meta charset="utf-8"><title>DocuGate tour server</title>
383
- <style>body{margin:0;min-height:100vh;display:grid;place-items:center;background:#0F1014;color:#F5F0E3;font:15px/1.6 system-ui,sans-serif}
384
- main{max-width:440px;padding:32px;border:1px solid #25273a;border-radius:16px;background:#15173a}
385
- h1{font-size:20px;margin:0 0 8px}p{margin:0 0 12px;color:#aaa597}b{color:#F4C43F;font-weight:600}
386
- .dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:#45d483;margin-right:8px}</style></head>
387
- <body><main><h1><span class="dot"></span>The DocuGate tour server is running</h1>
388
- <p>This is not a page to open. It feeds the Tour button in your app (${screens} screen${screens === 1 ? '' : 's'} in <b>.docugate/tour/</b>).</p>
382
+ res.end(`<!doctype html><html lang="en"><head><meta charset="utf-8"><title>DocuGate tour server</title>
383
+ <style>body{margin:0;min-height:100vh;display:grid;place-items:center;background:#0F1014;color:#F5F0E3;font:15px/1.6 system-ui,sans-serif}
384
+ main{max-width:440px;padding:32px;border:1px solid #25273a;border-radius:16px;background:#15173a}
385
+ h1{font-size:20px;margin:0 0 8px}p{margin:0 0 12px;color:#aaa597}b{color:#F4C43F;font-weight:600}
386
+ .dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:#45d483;margin-right:8px}</style></head>
387
+ <body><main><h1><span class="dot"></span>The DocuGate tour server is running</h1>
388
+ <p>This is not a page to open. It feeds the Tour button in your app (${screens} screen${screens === 1 ? '' : 's'} in <b>.docugate/tour/</b>).</p>
389
389
  <p>Open <b>your app</b> instead, for example <b>http://localhost:5173</b> or <b>http://localhost:3000</b>. The Tour button is in the bottom-right corner.</p></main></body></html>`);
390
390
  }
391
391
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docugate",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "Command-line tools for DocuGate: set up, check and prepare the documentation DocuGate reads straight from your repository. Also checks DocuGate API keys from Express, Hono and Fastify.",
5
5
  "type": "module",
6
6
  "bin": {