@doxbrix/doxloop 0.1.3 → 0.1.5
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/CHANGELOG.md +39 -0
- package/README.md +97 -41
- package/assets/doxbrix-preview.css +8 -0
- package/dist/agents.d.ts +21 -0
- package/dist/agents.d.ts.map +1 -1
- package/dist/agents.js +63 -1
- package/dist/agents.js.map +1 -1
- package/dist/args.d.ts.map +1 -1
- package/dist/args.js +2 -1
- package/dist/args.js.map +1 -1
- package/dist/auth.js +47 -4
- package/dist/auth.js.map +1 -1
- package/dist/author.d.ts +3 -5
- package/dist/author.d.ts.map +1 -1
- package/dist/author.js +7 -4
- package/dist/author.js.map +1 -1
- package/dist/cli.js +346 -72
- package/dist/cli.js.map +1 -1
- package/dist/doxbrix-markdown.js +39 -1
- package/dist/doxbrix-markdown.js.map +1 -1
- package/dist/interactive.d.ts +17 -0
- package/dist/interactive.d.ts.map +1 -0
- package/dist/interactive.js +343 -0
- package/dist/interactive.js.map +1 -0
- package/dist/preview.d.ts.map +1 -1
- package/dist/preview.js +194 -0
- package/dist/preview.js.map +1 -1
- package/dist/project.d.ts +8 -0
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +124 -11
- package/dist/project.js.map +1 -1
- package/dist/prompts.d.ts +41 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +294 -0
- package/dist/prompts.js.map +1 -0
- package/dist/settings.d.ts +6 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +519 -0
- package/dist/settings.js.map +1 -0
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +46 -0
- package/dist/sync.js.map +1 -1
- package/dist/types.d.ts +18 -1
- package/dist/types.d.ts.map +1 -1
- package/docs/agent-compatibility.md +5 -0
- package/docs/ci-and-automation.md +10 -0
- package/docs/doxbrix-http-api.md +2 -1
- package/docs/project-format.md +13 -1
- package/docs/security-model.md +4 -2
- package/package.json +1 -1
- package/skills/doxloop-authoring/references/project-format.md +20 -0
- package/dist/public-deploy-confirmation.d.ts +0 -5
- package/dist/public-deploy-confirmation.d.ts.map +0 -1
- package/dist/public-deploy-confirmation.js +0 -22
- package/dist/public-deploy-confirmation.js.map +0 -1
package/dist/settings.js
ADDED
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
import { relative, resolve } from 'node:path';
|
|
2
|
+
import { detectAgents } from './agents.js';
|
|
3
|
+
import { apiUrl } from './auth.js';
|
|
4
|
+
import { generatorCatalogEntry } from './generators.js';
|
|
5
|
+
import { isSpecUrl, loadProject, parseDesignReference, parseSpec, saveProjectSettings, validateProjectSourceBoundaries, } from './project.js';
|
|
6
|
+
import { heading, note, promptConfirm, promptSelect, promptText, } from './prompts.js';
|
|
7
|
+
export async function runSettingsWizard(root, cwd, io = { input: process.stdin, output: process.stdout }) {
|
|
8
|
+
heading(io, 'Doxloop — project settings');
|
|
9
|
+
while (true) {
|
|
10
|
+
const project = await loadProject(root);
|
|
11
|
+
const area = await promptSelect({
|
|
12
|
+
message: `What would you like to change for "${project.title}"?`,
|
|
13
|
+
choices: [
|
|
14
|
+
{ value: 'show', label: 'Show all settings' },
|
|
15
|
+
{ value: 'title', label: 'Site title and identity' },
|
|
16
|
+
{ value: 'evidence', label: 'Product evidence' },
|
|
17
|
+
{ value: 'agent', label: 'Default authoring agent' },
|
|
18
|
+
{ value: 'documentation', label: 'Documentation preferences' },
|
|
19
|
+
{ value: 'references', label: 'Design references' },
|
|
20
|
+
{ value: 'screenshots', label: 'Application screenshots' },
|
|
21
|
+
{ value: 'deployment', label: 'Deployment' },
|
|
22
|
+
{ value: 'generator', label: 'Documentation generator' },
|
|
23
|
+
{ value: 'exit', label: 'Exit' },
|
|
24
|
+
],
|
|
25
|
+
io,
|
|
26
|
+
});
|
|
27
|
+
if (area === 'exit')
|
|
28
|
+
return;
|
|
29
|
+
if (area === 'show') {
|
|
30
|
+
io.output.write(`\n${formatProjectSettings(root, project)}\n\n`);
|
|
31
|
+
}
|
|
32
|
+
else if (area === 'title') {
|
|
33
|
+
await editTitle(root, project, io);
|
|
34
|
+
}
|
|
35
|
+
else if (area === 'evidence') {
|
|
36
|
+
await editEvidence(root, cwd, project, io);
|
|
37
|
+
}
|
|
38
|
+
else if (area === 'agent') {
|
|
39
|
+
await editAgent(root, io);
|
|
40
|
+
}
|
|
41
|
+
else if (area === 'documentation') {
|
|
42
|
+
await editDocumentation(root, project.documentation, io);
|
|
43
|
+
}
|
|
44
|
+
else if (area === 'references') {
|
|
45
|
+
await editReferences(root, project, io);
|
|
46
|
+
}
|
|
47
|
+
else if (area === 'screenshots') {
|
|
48
|
+
await editScreenshots(root, project, io);
|
|
49
|
+
}
|
|
50
|
+
else if (area === 'deployment') {
|
|
51
|
+
await editDeployment(root, project, io);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
showGenerator(project, io);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export function formatProjectSettings(root, project) {
|
|
59
|
+
const generator = generatorCatalogEntry(project.generator)?.displayName ?? project.generator;
|
|
60
|
+
const evidence = project.sources.length === 0
|
|
61
|
+
? 'None configured'
|
|
62
|
+
: project.sources
|
|
63
|
+
.map((source) => `${source.name}: ${(source.kind ?? 'directory') === 'openapi' ? 'OpenAPI ' : ''}${source.path}`)
|
|
64
|
+
.join('\n ');
|
|
65
|
+
const deployment = effectiveDeployment(project);
|
|
66
|
+
return `Project\n Root: ${root}\n Title: ${project.title}\n Generator: ${generator}\n Agent: ${project.defaultAgent ?? 'Choose at authoring time'}\n\nEvidence\n ${evidence}\n\nDocumentation\n Audience: ${project.documentation.primaryAudience ?? 'Agent will determine'}\n Locale: ${project.documentation.locale}\n Tone: ${project.documentation.tone.join(', ')}\n\nApplication screenshots\n ${project.application ? `${project.application.screenshots?.policy ?? 'requested'} at ${project.application.baseUrl}` : 'Not configured'}\n\nDeployment\n Name: ${deployment.name}\n Slug: ${deployment.slug}\n Visibility: ${deployment.visibility}\n Destination: ${deployment.apiUrl}`;
|
|
67
|
+
}
|
|
68
|
+
export function effectiveDeployment(project, fallbackApiUrl) {
|
|
69
|
+
return {
|
|
70
|
+
name: project.deployment?.name?.trim() || project.title,
|
|
71
|
+
slug: project.deployment?.slug?.trim() || slugify(project.title),
|
|
72
|
+
visibility: project.deployment?.visibility ?? 'private',
|
|
73
|
+
apiUrl: apiUrl(project.deployment?.apiUrl ?? fallbackApiUrl),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
async function editTitle(root, project, io) {
|
|
77
|
+
const title = await promptText({ message: 'Site title', initial: project.title, io });
|
|
78
|
+
if (title === project.title) {
|
|
79
|
+
note(io, 'No change.');
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
await saveProjectSettings(root, { title });
|
|
83
|
+
note(io, `✓ Site title changed to ${title}. The next authoring run will synchronize generator-native site metadata.`);
|
|
84
|
+
}
|
|
85
|
+
async function editEvidence(root, cwd, project, io) {
|
|
86
|
+
const action = await promptSelect({
|
|
87
|
+
message: 'Product evidence',
|
|
88
|
+
choices: [
|
|
89
|
+
{ value: 'view', label: 'View configured evidence' },
|
|
90
|
+
{ value: 'directory', label: 'Add a source directory' },
|
|
91
|
+
{ value: 'spec', label: 'Add an API specification' },
|
|
92
|
+
{
|
|
93
|
+
value: 'remove',
|
|
94
|
+
label: 'Remove evidence',
|
|
95
|
+
...(project.sources.length === 0 ? { disabled: 'nothing configured' } : {}),
|
|
96
|
+
},
|
|
97
|
+
{ value: 'back', label: 'Back' },
|
|
98
|
+
],
|
|
99
|
+
io,
|
|
100
|
+
});
|
|
101
|
+
if (action === 'back')
|
|
102
|
+
return;
|
|
103
|
+
if (action === 'view') {
|
|
104
|
+
note(io, project.sources.length === 0
|
|
105
|
+
? 'No product evidence is configured.'
|
|
106
|
+
: project.sources
|
|
107
|
+
.map((source) => `${source.name}: ${(source.kind ?? 'directory') === 'openapi' ? 'OpenAPI — ' : ''}${source.path}`)
|
|
108
|
+
.join('\n'));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (action === 'remove') {
|
|
112
|
+
const source = await promptSelect({
|
|
113
|
+
message: 'Remove which evidence?',
|
|
114
|
+
choices: project.sources.map((candidate) => ({
|
|
115
|
+
value: candidate,
|
|
116
|
+
label: candidate.name,
|
|
117
|
+
hint: candidate.path,
|
|
118
|
+
})),
|
|
119
|
+
io,
|
|
120
|
+
});
|
|
121
|
+
if (!(await promptConfirm({
|
|
122
|
+
message: `Remove "${source.name}" from the configured evidence?`,
|
|
123
|
+
initial: false,
|
|
124
|
+
io,
|
|
125
|
+
}))) {
|
|
126
|
+
note(io, 'No change.');
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const sources = project.sources.filter((candidate) => candidate !== source);
|
|
130
|
+
const application = project.application?.source === source.name
|
|
131
|
+
? withoutApplicationSource(project.application)
|
|
132
|
+
: project.application;
|
|
133
|
+
await saveProjectSettings(root, { sources, application });
|
|
134
|
+
note(io, `✓ Removed ${source.name}. No product files were changed.`);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const name = await promptText({
|
|
138
|
+
message: 'Evidence name',
|
|
139
|
+
initial: uniqueSourceName(project.sources, action === 'spec' ? 'api' : 'product'),
|
|
140
|
+
validate: (value) => validateSourceName(project.sources, value),
|
|
141
|
+
io,
|
|
142
|
+
});
|
|
143
|
+
if (action === 'directory') {
|
|
144
|
+
const location = await promptText({
|
|
145
|
+
message: 'Path to product source',
|
|
146
|
+
validate: async (value) => {
|
|
147
|
+
const candidate = {
|
|
148
|
+
name,
|
|
149
|
+
path: portableRelative(root, resolve(cwd, value)),
|
|
150
|
+
};
|
|
151
|
+
return validationProblem(() => validateProjectSourceBoundaries(root, [...project.sources, candidate]));
|
|
152
|
+
},
|
|
153
|
+
io,
|
|
154
|
+
});
|
|
155
|
+
const absolute = resolve(cwd, location);
|
|
156
|
+
const source = {
|
|
157
|
+
name,
|
|
158
|
+
path: portableRelative(root, absolute),
|
|
159
|
+
};
|
|
160
|
+
const sources = [...project.sources, source];
|
|
161
|
+
await validateProjectSourceBoundaries(root, sources);
|
|
162
|
+
await saveProjectSettings(root, { sources });
|
|
163
|
+
note(io, `✓ Added read-only product source ${absolute}.`);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const location = await promptText({
|
|
167
|
+
message: 'OpenAPI specification file or URL',
|
|
168
|
+
validate: async (value) => {
|
|
169
|
+
try {
|
|
170
|
+
const candidate = parseSpec(`${name}=${value}`);
|
|
171
|
+
const normalized = isSpecUrl(candidate.path)
|
|
172
|
+
? candidate
|
|
173
|
+
: {
|
|
174
|
+
...candidate,
|
|
175
|
+
path: portableRelative(root, resolve(cwd, candidate.path)),
|
|
176
|
+
};
|
|
177
|
+
return validationProblem(() => validateProjectSourceBoundaries(root, [...project.sources, normalized]));
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
return error instanceof Error ? error.message : String(error);
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
io,
|
|
184
|
+
});
|
|
185
|
+
const parsed = parseSpec(`${name}=${location}`);
|
|
186
|
+
const source = isSpecUrl(parsed.path)
|
|
187
|
+
? parsed
|
|
188
|
+
: { ...parsed, path: portableRelative(root, resolve(cwd, parsed.path)) };
|
|
189
|
+
const sources = [...project.sources, source];
|
|
190
|
+
await validateProjectSourceBoundaries(root, sources);
|
|
191
|
+
await saveProjectSettings(root, { sources });
|
|
192
|
+
note(io, `✓ Added OpenAPI evidence ${source.path}.`);
|
|
193
|
+
}
|
|
194
|
+
async function editAgent(root, io) {
|
|
195
|
+
const detected = await detectAgents();
|
|
196
|
+
if (detected.length === 0) {
|
|
197
|
+
note(io, 'No supported agent CLI was found on PATH. Install Codex, Claude Code, or Gemini first.');
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const labels = {
|
|
201
|
+
codex: 'Codex',
|
|
202
|
+
claude: 'Claude Code',
|
|
203
|
+
gemini: 'Gemini',
|
|
204
|
+
};
|
|
205
|
+
const agent = await promptSelect({
|
|
206
|
+
message: 'Default authoring agent',
|
|
207
|
+
choices: detected.map((candidate) => ({
|
|
208
|
+
value: candidate.name,
|
|
209
|
+
label: labels[candidate.name],
|
|
210
|
+
})),
|
|
211
|
+
io,
|
|
212
|
+
});
|
|
213
|
+
await saveProjectSettings(root, { defaultAgent: agent });
|
|
214
|
+
note(io, `✓ Default agent changed to ${labels[agent]}.`);
|
|
215
|
+
}
|
|
216
|
+
async function editDocumentation(root, documentation, io) {
|
|
217
|
+
const field = await promptSelect({
|
|
218
|
+
message: 'Documentation preferences',
|
|
219
|
+
choices: [
|
|
220
|
+
{ value: 'audience', label: 'Primary audience' },
|
|
221
|
+
{ value: 'locale', label: 'Locale' },
|
|
222
|
+
{ value: 'tone', label: 'Tone' },
|
|
223
|
+
{ value: 'outcomes', label: 'Priority reader outcomes' },
|
|
224
|
+
{ value: 'back', label: 'Back' },
|
|
225
|
+
],
|
|
226
|
+
io,
|
|
227
|
+
});
|
|
228
|
+
if (field === 'back')
|
|
229
|
+
return;
|
|
230
|
+
const next = { ...documentation };
|
|
231
|
+
if (field === 'audience') {
|
|
232
|
+
next.primaryAudience = await promptText({
|
|
233
|
+
message: 'Primary audience',
|
|
234
|
+
initial: documentation.primaryAudience ?? 'Developers',
|
|
235
|
+
io,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
else if (field === 'locale') {
|
|
239
|
+
next.locale = await promptText({
|
|
240
|
+
message: 'Locale',
|
|
241
|
+
initial: documentation.locale,
|
|
242
|
+
io,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
else if (field === 'tone') {
|
|
246
|
+
next.tone = commaList(await promptText({
|
|
247
|
+
message: 'Tone, separated by commas',
|
|
248
|
+
initial: documentation.tone.join(', '),
|
|
249
|
+
validate: validateCommaList,
|
|
250
|
+
io,
|
|
251
|
+
}));
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
next.priorityOutcomes = commaList(await promptText({
|
|
255
|
+
message: 'Priority outcomes, separated by commas',
|
|
256
|
+
initial: documentation.priorityOutcomes?.join(', ') ?? 'Reach a first successful result',
|
|
257
|
+
validate: validateCommaList,
|
|
258
|
+
io,
|
|
259
|
+
}));
|
|
260
|
+
}
|
|
261
|
+
await saveProjectSettings(root, { documentation: next });
|
|
262
|
+
note(io, '✓ Documentation preferences updated.');
|
|
263
|
+
}
|
|
264
|
+
async function editReferences(root, project, io) {
|
|
265
|
+
const action = await promptSelect({
|
|
266
|
+
message: 'Design references',
|
|
267
|
+
choices: [
|
|
268
|
+
{ value: 'add', label: 'Add a public documentation site' },
|
|
269
|
+
{
|
|
270
|
+
value: 'remove',
|
|
271
|
+
label: 'Remove a design reference',
|
|
272
|
+
...(project.designReferences.length === 0
|
|
273
|
+
? { disabled: 'nothing configured' }
|
|
274
|
+
: {}),
|
|
275
|
+
},
|
|
276
|
+
{ value: 'back', label: 'Back' },
|
|
277
|
+
],
|
|
278
|
+
io,
|
|
279
|
+
});
|
|
280
|
+
if (action === 'back')
|
|
281
|
+
return;
|
|
282
|
+
if (action === 'add') {
|
|
283
|
+
const raw = await promptText({
|
|
284
|
+
message: 'Documentation site URL',
|
|
285
|
+
validate: (value) => {
|
|
286
|
+
try {
|
|
287
|
+
parseDesignReference(value);
|
|
288
|
+
return undefined;
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
return error instanceof Error ? error.message : String(error);
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
io,
|
|
295
|
+
});
|
|
296
|
+
const reference = parseDesignReference(raw);
|
|
297
|
+
const urls = new Set(project.designReferences.map((item) => item.url));
|
|
298
|
+
urls.add(reference.url);
|
|
299
|
+
await saveProjectSettings(root, {
|
|
300
|
+
designReferences: [...urls].map((url) => ({ url })),
|
|
301
|
+
});
|
|
302
|
+
note(io, `✓ Added ${reference.url}.`);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
const reference = await promptSelect({
|
|
306
|
+
message: 'Remove which reference?',
|
|
307
|
+
choices: project.designReferences.map((item) => ({
|
|
308
|
+
value: item,
|
|
309
|
+
label: item.url,
|
|
310
|
+
})),
|
|
311
|
+
io,
|
|
312
|
+
});
|
|
313
|
+
await saveProjectSettings(root, {
|
|
314
|
+
designReferences: project.designReferences.filter((item) => item !== reference),
|
|
315
|
+
});
|
|
316
|
+
note(io, `✓ Removed ${reference.url}.`);
|
|
317
|
+
}
|
|
318
|
+
async function editScreenshots(root, project, io) {
|
|
319
|
+
const action = await promptSelect({
|
|
320
|
+
message: 'Application screenshots',
|
|
321
|
+
choices: [
|
|
322
|
+
{
|
|
323
|
+
value: 'configure',
|
|
324
|
+
label: project.application ? 'Change application URL' : 'Configure application',
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
value: 'policy',
|
|
328
|
+
label: 'Screenshot policy',
|
|
329
|
+
...(!project.application ? { disabled: 'configure an application first' } : {}),
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
value: 'remove',
|
|
333
|
+
label: 'Remove application configuration',
|
|
334
|
+
...(!project.application ? { disabled: 'nothing configured' } : {}),
|
|
335
|
+
},
|
|
336
|
+
{ value: 'back', label: 'Back' },
|
|
337
|
+
],
|
|
338
|
+
io,
|
|
339
|
+
});
|
|
340
|
+
if (action === 'back')
|
|
341
|
+
return;
|
|
342
|
+
if (action === 'remove') {
|
|
343
|
+
await saveProjectSettings(root, { application: undefined });
|
|
344
|
+
note(io, '✓ Application screenshot configuration removed.');
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
if (action === 'configure') {
|
|
348
|
+
const baseUrl = await promptText({
|
|
349
|
+
message: 'Application base URL',
|
|
350
|
+
initial: project.application?.baseUrl ?? 'http://localhost:3000',
|
|
351
|
+
validate: validateApplicationUrl,
|
|
352
|
+
io,
|
|
353
|
+
});
|
|
354
|
+
const application = {
|
|
355
|
+
...project.application,
|
|
356
|
+
baseUrl: new URL(baseUrl).toString().replace(/\/$/, ''),
|
|
357
|
+
screenshots: project.application?.screenshots ?? { policy: 'requested' },
|
|
358
|
+
};
|
|
359
|
+
await saveProjectSettings(root, { application });
|
|
360
|
+
note(io, `✓ Application configured at ${application.baseUrl}.`);
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
const policy = await promptSelect({
|
|
364
|
+
message: 'When should Doxloop capture screenshots?',
|
|
365
|
+
choices: [
|
|
366
|
+
{ value: 'requested', label: 'Only when requested' },
|
|
367
|
+
{ value: 'auto', label: 'Automatically for visible UI workflows' },
|
|
368
|
+
{ value: 'off', label: 'Never' },
|
|
369
|
+
],
|
|
370
|
+
initialIndex: project.application?.screenshots?.policy === 'auto'
|
|
371
|
+
? 1
|
|
372
|
+
: project.application?.screenshots?.policy === 'off'
|
|
373
|
+
? 2
|
|
374
|
+
: 0,
|
|
375
|
+
io,
|
|
376
|
+
});
|
|
377
|
+
await saveProjectSettings(root, {
|
|
378
|
+
application: {
|
|
379
|
+
...project.application,
|
|
380
|
+
screenshots: { ...project.application.screenshots, policy },
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
note(io, `✓ Screenshot policy changed to ${policy}.`);
|
|
384
|
+
}
|
|
385
|
+
async function editDeployment(root, project, io) {
|
|
386
|
+
const effective = effectiveDeployment(project);
|
|
387
|
+
const field = await promptSelect({
|
|
388
|
+
message: 'Deployment settings',
|
|
389
|
+
choices: [
|
|
390
|
+
{ value: 'name', label: 'Hosted project name', hint: effective.name },
|
|
391
|
+
{ value: 'slug', label: 'Project address', hint: effective.slug },
|
|
392
|
+
{ value: 'visibility', label: 'Visibility', hint: effective.visibility },
|
|
393
|
+
{ value: 'api', label: 'Doxbrix destination', hint: effective.apiUrl },
|
|
394
|
+
{ value: 'back', label: 'Back' },
|
|
395
|
+
],
|
|
396
|
+
io,
|
|
397
|
+
});
|
|
398
|
+
if (field === 'back')
|
|
399
|
+
return;
|
|
400
|
+
const deployment = { ...project.deployment };
|
|
401
|
+
if (field === 'name') {
|
|
402
|
+
deployment.name = await promptText({
|
|
403
|
+
message: 'Hosted project name',
|
|
404
|
+
initial: effective.name,
|
|
405
|
+
io,
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
else if (field === 'slug') {
|
|
409
|
+
deployment.slug = await promptText({
|
|
410
|
+
message: 'Project address',
|
|
411
|
+
initial: effective.slug,
|
|
412
|
+
validate: (value) => /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(value)
|
|
413
|
+
? undefined
|
|
414
|
+
: 'Use lowercase letters, numbers, and single hyphens.',
|
|
415
|
+
io,
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
else if (field === 'visibility') {
|
|
419
|
+
deployment.visibility = await promptSelect({
|
|
420
|
+
message: 'Deployment visibility',
|
|
421
|
+
choices: [
|
|
422
|
+
{ value: 'private', label: 'Private', hint: 'available only to authorized viewers' },
|
|
423
|
+
{ value: 'public', label: 'Public', hint: 'anyone on the internet can access it' },
|
|
424
|
+
],
|
|
425
|
+
initialIndex: effective.visibility === 'public' ? 1 : 0,
|
|
426
|
+
io,
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
deployment.apiUrl = await promptText({
|
|
431
|
+
message: 'Doxbrix API destination',
|
|
432
|
+
initial: effective.apiUrl,
|
|
433
|
+
validate: validateApiUrl,
|
|
434
|
+
io,
|
|
435
|
+
});
|
|
436
|
+
deployment.apiUrl = apiUrl(deployment.apiUrl);
|
|
437
|
+
}
|
|
438
|
+
await saveProjectSettings(root, { deployment });
|
|
439
|
+
note(io, '✓ Deployment settings updated.');
|
|
440
|
+
}
|
|
441
|
+
function showGenerator(project, io) {
|
|
442
|
+
const generator = generatorCatalogEntry(project.generator)?.displayName ?? project.generator;
|
|
443
|
+
note(io, `Current generator: ${generator}\nChanging generators in place could overwrite generator-native files. Create a new project with \`doxloop init\` when you need to migrate frameworks.`);
|
|
444
|
+
}
|
|
445
|
+
function withoutApplicationSource(application) {
|
|
446
|
+
const { source: _source, startCommand: _startCommand, ...remaining } = application;
|
|
447
|
+
return remaining;
|
|
448
|
+
}
|
|
449
|
+
function uniqueSourceName(sources, base) {
|
|
450
|
+
const used = new Set(sources.map((source) => source.name));
|
|
451
|
+
if (!used.has(base))
|
|
452
|
+
return base;
|
|
453
|
+
let suffix = 2;
|
|
454
|
+
while (used.has(`${base}-${suffix}`))
|
|
455
|
+
suffix += 1;
|
|
456
|
+
return `${base}-${suffix}`;
|
|
457
|
+
}
|
|
458
|
+
function validateSourceName(sources, value) {
|
|
459
|
+
if (!/^[a-z][a-z0-9-]*$/.test(value)) {
|
|
460
|
+
return 'Use lowercase letters, numbers, and hyphens; start with a letter.';
|
|
461
|
+
}
|
|
462
|
+
return sources.some((source) => source.name === value)
|
|
463
|
+
? `Evidence named "${value}" already exists.`
|
|
464
|
+
: undefined;
|
|
465
|
+
}
|
|
466
|
+
function portableRelative(root, absolute) {
|
|
467
|
+
return relative(root, absolute).split('\\').join('/');
|
|
468
|
+
}
|
|
469
|
+
function commaList(value) {
|
|
470
|
+
return value
|
|
471
|
+
.split(',')
|
|
472
|
+
.map((item) => item.trim())
|
|
473
|
+
.filter(Boolean);
|
|
474
|
+
}
|
|
475
|
+
function validateCommaList(value) {
|
|
476
|
+
return commaList(value).length > 0 ? undefined : 'Enter at least one value.';
|
|
477
|
+
}
|
|
478
|
+
function validateApplicationUrl(value) {
|
|
479
|
+
try {
|
|
480
|
+
const url = new URL(value);
|
|
481
|
+
if (!['http:', 'https:'].includes(url.protocol))
|
|
482
|
+
return 'Use an HTTP or HTTPS URL.';
|
|
483
|
+
if (url.username || url.password || url.search || url.hash) {
|
|
484
|
+
return 'Remove credentials, query parameters, and fragments.';
|
|
485
|
+
}
|
|
486
|
+
return undefined;
|
|
487
|
+
}
|
|
488
|
+
catch {
|
|
489
|
+
return 'Enter a valid HTTP or HTTPS URL.';
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
function validateApiUrl(value) {
|
|
493
|
+
try {
|
|
494
|
+
apiUrl(value);
|
|
495
|
+
return undefined;
|
|
496
|
+
}
|
|
497
|
+
catch (error) {
|
|
498
|
+
return error instanceof Error ? error.message : String(error);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
async function validationProblem(operation) {
|
|
502
|
+
try {
|
|
503
|
+
await operation();
|
|
504
|
+
return undefined;
|
|
505
|
+
}
|
|
506
|
+
catch (error) {
|
|
507
|
+
return error instanceof Error ? error.message : String(error);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
function slugify(value) {
|
|
511
|
+
const slug = value
|
|
512
|
+
.toLowerCase()
|
|
513
|
+
.normalize('NFKD')
|
|
514
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
515
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
516
|
+
.replace(/^-+|-+$/g, '');
|
|
517
|
+
return slug || 'documentation';
|
|
518
|
+
}
|
|
519
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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"}
|
package/dist/sync.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAIxE,eAAO,MAAM,eAAe,QAAsC,CAAA;AAMlE,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAQpE;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,aAAa,EAAE,GACvB,OAAO,CAAC,SAAS,CAAC,CA+BpB;AAED,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,aAAa,EAAE,GACvB,OAAO,CAAC,YAAY,EAAE,CAAC,CAgDzB;AA0BD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAwCnE"}
|
package/dist/sync.js
CHANGED
|
@@ -4,6 +4,8 @@ import { lstat, readFile, readlink, writeFile } from 'node:fs/promises';
|
|
|
4
4
|
import { join, resolve } from 'node:path';
|
|
5
5
|
import { promisify } from 'node:util';
|
|
6
6
|
import { pathExists, readJson } from './fs.js';
|
|
7
|
+
import { isSpecUrl, sourceKind } from './project.js';
|
|
8
|
+
const SPEC_BASELINE = 'openapi-spec';
|
|
7
9
|
export const SYNC_STATE_FILE = join('.doxloop', 'sync-state.json');
|
|
8
10
|
const MAX_LISTED_FILES = 40;
|
|
9
11
|
const run = promisify(execFile);
|
|
@@ -20,6 +22,19 @@ export async function readSyncState(root) {
|
|
|
20
22
|
export async function recordSyncState(root, sources) {
|
|
21
23
|
const state = { schemaVersion: 1, sources: {} };
|
|
22
24
|
for (const source of sources) {
|
|
25
|
+
if (sourceKind(source) === 'openapi') {
|
|
26
|
+
if (isSpecUrl(source.path))
|
|
27
|
+
continue;
|
|
28
|
+
const fingerprint = await specFileFingerprint(resolve(root, source.path));
|
|
29
|
+
if (fingerprint) {
|
|
30
|
+
state.sources[source.name] = {
|
|
31
|
+
commit: SPEC_BASELINE,
|
|
32
|
+
recordedAt: new Date().toISOString(),
|
|
33
|
+
contentFingerprint: fingerprint,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
23
38
|
const commit = await headCommit(resolve(root, source.path));
|
|
24
39
|
if (commit) {
|
|
25
40
|
const sourcePath = resolve(root, source.path);
|
|
@@ -37,6 +52,10 @@ export async function collectSourceChanges(root, sources) {
|
|
|
37
52
|
const state = await readSyncState(root);
|
|
38
53
|
const changes = [];
|
|
39
54
|
for (const source of sources) {
|
|
55
|
+
if (sourceKind(source) === 'openapi') {
|
|
56
|
+
changes.push(await collectSpecChange(root, source, state));
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
40
59
|
const path = resolve(root, source.path);
|
|
41
60
|
if (!(await pathExists(path))) {
|
|
42
61
|
changes.push({ ...source, kind: 'missing-path' });
|
|
@@ -76,6 +95,27 @@ export async function collectSourceChanges(root, sources) {
|
|
|
76
95
|
}
|
|
77
96
|
return changes;
|
|
78
97
|
}
|
|
98
|
+
async function collectSpecChange(root, source, state) {
|
|
99
|
+
if (isSpecUrl(source.path))
|
|
100
|
+
return { ...source, kind: 'spec-remote' };
|
|
101
|
+
const fingerprint = await specFileFingerprint(resolve(root, source.path));
|
|
102
|
+
if (!fingerprint)
|
|
103
|
+
return { ...source, kind: 'missing-path' };
|
|
104
|
+
const record = state.sources[source.name];
|
|
105
|
+
if (record?.contentFingerprint === fingerprint) {
|
|
106
|
+
return { ...source, kind: 'spec-unchanged' };
|
|
107
|
+
}
|
|
108
|
+
return { ...source, kind: 'spec-changed' };
|
|
109
|
+
}
|
|
110
|
+
async function specFileFingerprint(path) {
|
|
111
|
+
try {
|
|
112
|
+
const content = await readFile(path);
|
|
113
|
+
return createHash('sha256').update(content).digest('hex');
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
79
119
|
export function formatSourceChanges(changes) {
|
|
80
120
|
if (changes.length === 0)
|
|
81
121
|
return '';
|
|
@@ -84,6 +124,12 @@ export function formatSourceChanges(changes) {
|
|
|
84
124
|
switch (change.kind) {
|
|
85
125
|
case 'missing-path':
|
|
86
126
|
return `${heading}: the configured path does not exist. Report this instead of guessing.`;
|
|
127
|
+
case 'spec-remote':
|
|
128
|
+
return `${heading}: remote API specification. Fetch the current document and compare it with the documented API surface before updating.`;
|
|
129
|
+
case 'spec-unchanged':
|
|
130
|
+
return `${heading}: the API specification is unchanged since the last documentation sync.`;
|
|
131
|
+
case 'spec-changed':
|
|
132
|
+
return `${heading}: the API specification changed since the last documentation sync, or no baseline is recorded yet. Compare it with the documented endpoints and update every affected page; the baseline is recorded when this task completes.`;
|
|
87
133
|
case 'not-git':
|
|
88
134
|
return `${heading}: not a Git repository, so no change baseline is available. Inspect the source directly.`;
|
|
89
135
|
case 'no-baseline':
|