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 +5 -5
- package/dist/api.js +13 -3
- package/dist/cli.js +1 -1
- package/dist/developers.js +1 -1
- package/dist/init.js +1 -1
- package/dist/keys/core.js +1 -1
- package/dist/project.js +1 -1
- package/dist/sync/run.js +1 -1
- package/dist/tour-server.js +8 -8
- package/package.json +1 -1
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://
|
|
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://
|
|
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://
|
|
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://
|
|
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://
|
|
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://
|
|
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://
|
|
64
|
-
|
|
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://
|
|
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) {
|
package/dist/developers.js
CHANGED
|
@@ -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://
|
|
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://
|
|
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://
|
|
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://
|
|
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://
|
|
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'})`,
|
package/dist/tour-server.js
CHANGED
|
@@ -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://
|
|
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.
|
|
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": {
|