@mintlify/cli 4.0.1189 → 4.0.1190
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/__test__/workflows/client.test.ts +126 -0
- package/bin/cli.js +2 -0
- package/bin/tsconfig.build.tsbuildinfo +1 -1
- package/bin/workflows/client.js +34 -0
- package/bin/workflows/index.js +267 -0
- package/bin/workflows/types.js +11 -0
- package/package.json +2 -2
- package/src/cli.tsx +2 -0
- package/src/workflows/client.ts +39 -0
- package/src/workflows/index.tsx +286 -0
- package/src/workflows/types.ts +68 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { createWorkflow, deleteWorkflow, listWorkflows } from '../../src/workflows/client.js';
|
|
2
|
+
import type { WorkflowBody } from '../../src/workflows/types.js';
|
|
3
|
+
|
|
4
|
+
vi.mock('../../src/keyring.js', () => ({
|
|
5
|
+
getAccessToken: vi.fn().mockResolvedValue(null),
|
|
6
|
+
getRefreshToken: vi.fn().mockResolvedValue(null),
|
|
7
|
+
storeCredentials: vi.fn().mockResolvedValue(undefined),
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
const mockFetch = vi.fn();
|
|
11
|
+
global.fetch = mockFetch;
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
vi.stubEnv('MINTLIFY_SESSION_TOKEN', 'test-token');
|
|
15
|
+
vi.stubEnv('MINTLIFY_API_URL', 'http://test-server:5000');
|
|
16
|
+
mockFetch.mockReset();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
vi.unstubAllEnvs();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
function mockOk(data: unknown, status = 200) {
|
|
24
|
+
mockFetch.mockResolvedValueOnce({
|
|
25
|
+
ok: true,
|
|
26
|
+
status,
|
|
27
|
+
json: () => Promise.resolve(data),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function mockError(status: number, body: string) {
|
|
32
|
+
mockFetch.mockResolvedValueOnce({
|
|
33
|
+
ok: false,
|
|
34
|
+
status,
|
|
35
|
+
statusText: 'Bad Request',
|
|
36
|
+
text: () => Promise.resolve(body),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function calledUrl(): string {
|
|
41
|
+
const arg = mockFetch.mock.calls[0]![0];
|
|
42
|
+
return typeof arg === 'string' ? arg : String(arg);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function calledInit(): RequestInit {
|
|
46
|
+
return mockFetch.mock.calls[0]![1] as RequestInit;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const body: WorkflowBody = {
|
|
50
|
+
name: 'My Workflow',
|
|
51
|
+
on: { cron: '0 6 * * *' },
|
|
52
|
+
prompt: 'Translate docs',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
describe('workflow client auth', () => {
|
|
56
|
+
it('throws when no session token is set', async () => {
|
|
57
|
+
vi.stubEnv('MINTLIFY_SESSION_TOKEN', '');
|
|
58
|
+
await expect(listWorkflows('docs')).rejects.toThrow('Not authenticated');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('sends bearer token header', async () => {
|
|
62
|
+
mockOk([]);
|
|
63
|
+
await listWorkflows('docs');
|
|
64
|
+
expect(mockFetch).toHaveBeenCalledWith(
|
|
65
|
+
expect.any(String),
|
|
66
|
+
expect.objectContaining({
|
|
67
|
+
headers: expect.objectContaining({ Authorization: 'Bearer test-token' }),
|
|
68
|
+
})
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('createWorkflow', () => {
|
|
74
|
+
it('POSTs the body to the subdomain-scoped URL', async () => {
|
|
75
|
+
mockOk({ _id: 'wf123', name: 'My Workflow' }, 201);
|
|
76
|
+
const result = await createWorkflow('docs', body);
|
|
77
|
+
|
|
78
|
+
expect(new URL(calledUrl()).pathname).toBe('/api/cli/workflows/docs');
|
|
79
|
+
const init = calledInit();
|
|
80
|
+
expect(init.method).toBe('POST');
|
|
81
|
+
expect(init.body).toBe(JSON.stringify(body));
|
|
82
|
+
expect(init.headers).toMatchObject({ 'Content-Type': 'application/json' });
|
|
83
|
+
expect(result).toMatchObject({ _id: 'wf123' });
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('encodes the subdomain', async () => {
|
|
87
|
+
mockOk({ _id: 'wf123' }, 201);
|
|
88
|
+
await createWorkflow('my docs/sub', body);
|
|
89
|
+
expect(new URL(calledUrl()).pathname).toBe('/api/cli/workflows/my%20docs%2Fsub');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('throws on API error', async () => {
|
|
93
|
+
mockError(400, 'Invalid request body');
|
|
94
|
+
await expect(createWorkflow('docs', body)).rejects.toThrow(
|
|
95
|
+
'API error (400): Invalid request body'
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe('listWorkflows', () => {
|
|
101
|
+
it('GETs the subdomain-scoped URL', async () => {
|
|
102
|
+
mockOk([{ _id: 'wf1' }, { _id: 'wf2' }]);
|
|
103
|
+
const result = await listWorkflows('docs');
|
|
104
|
+
|
|
105
|
+
expect(new URL(calledUrl()).pathname).toBe('/api/cli/workflows/docs');
|
|
106
|
+
const init = calledInit();
|
|
107
|
+
expect(init.method).toBeUndefined();
|
|
108
|
+
expect(result).toHaveLength(2);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe('deleteWorkflow', () => {
|
|
113
|
+
it('DELETEs by workflow id', async () => {
|
|
114
|
+
mockOk({ success: true });
|
|
115
|
+
await deleteWorkflow('docs', 'wf123');
|
|
116
|
+
|
|
117
|
+
expect(new URL(calledUrl()).pathname).toBe('/api/cli/workflows/docs/wf123');
|
|
118
|
+
expect(calledInit().method).toBe('DELETE');
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('encodes both segments', async () => {
|
|
122
|
+
mockOk({ success: true });
|
|
123
|
+
await deleteWorkflow('my docs', 'wf 123');
|
|
124
|
+
expect(new URL(calledUrl()).pathname).toBe('/api/cli/workflows/my%20docs/wf%20123');
|
|
125
|
+
});
|
|
126
|
+
});
|
package/bin/cli.js
CHANGED
|
@@ -33,6 +33,7 @@ import { scoreHandler } from './score/index.js';
|
|
|
33
33
|
import { status, getCliSubdomains } from './status.js';
|
|
34
34
|
import { trackTelemetryPreferenceChange } from './telemetry/track.js';
|
|
35
35
|
import { update } from './update.js';
|
|
36
|
+
import { workflowsBuilder } from './workflows/index.js';
|
|
36
37
|
export const cli = ({ packageName = 'mint' }) => {
|
|
37
38
|
const telemetryMiddleware = createTelemetryMiddleware();
|
|
38
39
|
render(_jsx(Logs, {}));
|
|
@@ -423,6 +424,7 @@ export const cli = ({ packageName = 'mint' }) => {
|
|
|
423
424
|
}
|
|
424
425
|
}))
|
|
425
426
|
.command('analytics', 'View analytics for your documentation', analyticsBuilder)
|
|
427
|
+
.command('workflow', 'Create and manage workflows', workflowsBuilder)
|
|
426
428
|
.command('score [url]', 'Run agent readiness checks on a docs site', (yargs) => yargs
|
|
427
429
|
.positional('url', {
|
|
428
430
|
type: 'string',
|