skrypt-ai 0.4.2 → 0.6.0
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/dist/auth/index.d.ts +13 -3
- package/dist/auth/index.js +101 -9
- package/dist/auth/keychain.d.ts +5 -0
- package/dist/auth/keychain.js +82 -0
- package/dist/auth/notices.d.ts +3 -0
- package/dist/auth/notices.js +42 -0
- package/dist/autofix/index.d.ts +0 -4
- package/dist/autofix/index.js +10 -24
- package/dist/capture/browser.d.ts +11 -0
- package/dist/capture/browser.js +173 -0
- package/dist/capture/diff.d.ts +23 -0
- package/dist/capture/diff.js +52 -0
- package/dist/capture/index.d.ts +23 -0
- package/dist/capture/index.js +210 -0
- package/dist/capture/naming.d.ts +17 -0
- package/dist/capture/naming.js +45 -0
- package/dist/capture/parser.d.ts +15 -0
- package/dist/capture/parser.js +80 -0
- package/dist/capture/types.d.ts +57 -0
- package/dist/capture/types.js +1 -0
- package/dist/cli.js +20 -3
- package/dist/commands/autofix.js +136 -120
- package/dist/commands/cron.js +58 -47
- package/dist/commands/deploy.js +123 -102
- package/dist/commands/generate.js +125 -7
- package/dist/commands/heal.d.ts +10 -0
- package/dist/commands/heal.js +201 -0
- package/dist/commands/i18n.js +146 -111
- package/dist/commands/import.d.ts +2 -0
- package/dist/commands/import.js +157 -0
- package/dist/commands/init.js +19 -7
- package/dist/commands/lint.js +50 -44
- package/dist/commands/llms-txt.js +59 -49
- package/dist/commands/login.js +63 -34
- package/dist/commands/mcp.js +6 -0
- package/dist/commands/monitor.js +13 -8
- package/dist/commands/qa.d.ts +2 -0
- package/dist/commands/qa.js +43 -0
- package/dist/commands/review-pr.js +108 -92
- package/dist/commands/sdk.js +128 -122
- package/dist/commands/security.d.ts +2 -0
- package/dist/commands/security.js +109 -0
- package/dist/commands/test.js +91 -92
- package/dist/commands/version.js +104 -75
- package/dist/commands/watch.js +130 -114
- package/dist/config/types.js +2 -2
- package/dist/context-hub/index.d.ts +23 -0
- package/dist/context-hub/index.js +179 -0
- package/dist/context-hub/mappings.d.ts +8 -0
- package/dist/context-hub/mappings.js +55 -0
- package/dist/context-hub/types.d.ts +33 -0
- package/dist/context-hub/types.js +1 -0
- package/dist/generator/generator.js +39 -6
- package/dist/generator/types.d.ts +7 -0
- package/dist/generator/writer.d.ts +3 -1
- package/dist/generator/writer.js +36 -7
- package/dist/importers/confluence.d.ts +5 -0
- package/dist/importers/confluence.js +137 -0
- package/dist/importers/detect.d.ts +20 -0
- package/dist/importers/detect.js +121 -0
- package/dist/importers/docusaurus.d.ts +5 -0
- package/dist/importers/docusaurus.js +279 -0
- package/dist/importers/gitbook.d.ts +5 -0
- package/dist/importers/gitbook.js +189 -0
- package/dist/importers/github.d.ts +8 -0
- package/dist/importers/github.js +99 -0
- package/dist/importers/index.d.ts +15 -0
- package/dist/importers/index.js +30 -0
- package/dist/importers/markdown.d.ts +6 -0
- package/dist/importers/markdown.js +105 -0
- package/dist/importers/mintlify.d.ts +5 -0
- package/dist/importers/mintlify.js +172 -0
- package/dist/importers/notion.d.ts +5 -0
- package/dist/importers/notion.js +174 -0
- package/dist/importers/readme.d.ts +5 -0
- package/dist/importers/readme.js +184 -0
- package/dist/importers/transform.d.ts +90 -0
- package/dist/importers/transform.js +457 -0
- package/dist/importers/types.d.ts +37 -0
- package/dist/importers/types.js +1 -0
- package/dist/llm/anthropic-client.d.ts +1 -0
- package/dist/llm/anthropic-client.js +3 -1
- package/dist/llm/index.d.ts +6 -4
- package/dist/llm/index.js +76 -261
- package/dist/llm/openai-client.d.ts +1 -0
- package/dist/llm/openai-client.js +7 -2
- package/dist/plugins/index.js +7 -0
- package/dist/qa/checks.d.ts +10 -0
- package/dist/qa/checks.js +492 -0
- package/dist/qa/fixes.d.ts +30 -0
- package/dist/qa/fixes.js +277 -0
- package/dist/qa/index.d.ts +29 -0
- package/dist/qa/index.js +187 -0
- package/dist/qa/types.d.ts +24 -0
- package/dist/qa/types.js +1 -0
- package/dist/scanner/csharp.d.ts +23 -0
- package/dist/scanner/csharp.js +421 -0
- package/dist/scanner/index.js +53 -26
- package/dist/scanner/java.d.ts +39 -0
- package/dist/scanner/java.js +318 -0
- package/dist/scanner/kotlin.d.ts +23 -0
- package/dist/scanner/kotlin.js +389 -0
- package/dist/scanner/php.d.ts +57 -0
- package/dist/scanner/php.js +351 -0
- package/dist/scanner/python.js +17 -0
- package/dist/scanner/ruby.d.ts +36 -0
- package/dist/scanner/ruby.js +431 -0
- package/dist/scanner/swift.d.ts +25 -0
- package/dist/scanner/swift.js +392 -0
- package/dist/scanner/types.d.ts +1 -1
- package/dist/template/content/docs/_navigation.json +46 -0
- package/dist/template/content/docs/_sidebars.json +684 -0
- package/dist/template/content/docs/core.md +4544 -0
- package/dist/template/content/docs/index.mdx +89 -0
- package/dist/template/content/docs/integrations.md +1158 -0
- package/dist/template/content/docs/llms-full.md +403 -0
- package/dist/template/content/docs/llms.txt +4588 -0
- package/dist/template/content/docs/other.md +10379 -0
- package/dist/template/content/docs/tools.md +746 -0
- package/dist/template/content/docs/types.md +531 -0
- package/dist/template/docs.json +13 -11
- package/dist/template/mdx-components.tsx +27 -2
- package/dist/template/package.json +6 -0
- package/dist/template/public/search-index.json +1 -1
- package/dist/template/scripts/build-search-index.mjs +149 -13
- package/dist/template/src/app/api/chat/route.ts +83 -128
- package/dist/template/src/app/docs/[...slug]/page.tsx +75 -20
- package/dist/template/src/app/docs/llms-full.md +151 -4
- package/dist/template/src/app/docs/llms.txt +2464 -847
- package/dist/template/src/app/docs/page.mdx +48 -38
- package/dist/template/src/app/layout.tsx +3 -1
- package/dist/template/src/app/page.tsx +22 -8
- package/dist/template/src/components/ai-chat.tsx +73 -64
- package/dist/template/src/components/breadcrumbs.tsx +21 -23
- package/dist/template/src/components/copy-button.tsx +13 -9
- package/dist/template/src/components/copy-page-button.tsx +54 -0
- package/dist/template/src/components/docs-layout.tsx +37 -25
- package/dist/template/src/components/header.tsx +51 -10
- package/dist/template/src/components/mdx/card.tsx +17 -3
- package/dist/template/src/components/mdx/code-block.tsx +13 -9
- package/dist/template/src/components/mdx/code-group.tsx +13 -8
- package/dist/template/src/components/mdx/heading.tsx +15 -2
- package/dist/template/src/components/mdx/highlighted-code.tsx +13 -8
- package/dist/template/src/components/mdx/index.tsx +2 -0
- package/dist/template/src/components/mdx/mermaid.tsx +110 -0
- package/dist/template/src/components/mdx/screenshot.tsx +150 -0
- package/dist/template/src/components/scroll-to-hash.tsx +48 -0
- package/dist/template/src/components/sidebar.tsx +12 -18
- package/dist/template/src/components/table-of-contents.tsx +9 -0
- package/dist/template/src/lib/highlight.ts +3 -88
- package/dist/template/src/lib/navigation.ts +159 -0
- package/dist/template/src/lib/search-types.ts +4 -1
- package/dist/template/src/lib/search.ts +30 -7
- package/dist/template/src/styles/globals.css +17 -6
- package/dist/utils/files.d.ts +9 -1
- package/dist/utils/files.js +59 -10
- package/dist/utils/validation.d.ts +0 -3
- package/dist/utils/validation.js +0 -26
- package/package.json +5 -1
package/dist/commands/autofix.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { readFileSync, writeFileSync } from 'fs';
|
|
3
|
-
import { resolve } from 'path';
|
|
3
|
+
import { resolve, dirname } from 'path';
|
|
4
4
|
import { loadConfig, checkApiKey } from '../config/index.js';
|
|
5
5
|
import { createLLMClient } from '../llm/index.js';
|
|
6
6
|
import { autoFixExample, createTypeScriptValidator, createPythonValidator } from '../autofix/index.js';
|
|
7
7
|
import { requirePro } from '../auth/index.js';
|
|
8
|
+
import { runQA, printQAReport, fixQAIssues, printFixReport } from '../qa/index.js';
|
|
8
9
|
export const autofixCommand = new Command('autofix')
|
|
9
10
|
.description('Auto-fix broken code examples in documentation')
|
|
10
11
|
.argument('<file>', 'Documentation file to fix (markdown/mdx)')
|
|
@@ -15,134 +16,149 @@ export const autofixCommand = new Command('autofix')
|
|
|
15
16
|
.option('--dry-run', 'Show fixes without writing')
|
|
16
17
|
.option('--language <lang>', 'Force language for validation')
|
|
17
18
|
.action(async (file, options) => {
|
|
18
|
-
// Pro feature - requires subscription
|
|
19
|
-
if (!await requirePro('autofix')) {
|
|
20
|
-
process.exit(1);
|
|
21
|
-
}
|
|
22
|
-
const config = loadConfig(options.config);
|
|
23
|
-
if (options.provider)
|
|
24
|
-
config.llm.provider = options.provider;
|
|
25
|
-
if (options.model)
|
|
26
|
-
config.llm.model = options.model;
|
|
27
|
-
const { ok, envKey } = checkApiKey(config.llm.provider);
|
|
28
|
-
if (!ok && envKey) {
|
|
29
|
-
console.error(`Error: ${envKey} environment variable required`);
|
|
30
|
-
process.exit(1);
|
|
31
|
-
}
|
|
32
|
-
const filePath = resolve(file);
|
|
33
|
-
console.log(`skrypt autofix`);
|
|
34
|
-
console.log(` file: ${filePath}`);
|
|
35
|
-
console.log(` provider: ${config.llm.provider}`);
|
|
36
|
-
console.log(` max iterations: ${options.maxIterations}`);
|
|
37
|
-
console.log('');
|
|
38
|
-
// Read the file
|
|
39
|
-
let content;
|
|
40
19
|
try {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const errObj = err;
|
|
45
|
-
if (errObj.code === 'ENOENT') {
|
|
46
|
-
console.error(`Error: File not found: ${filePath}`);
|
|
20
|
+
// Pro feature - requires subscription
|
|
21
|
+
if (!await requirePro('autofix')) {
|
|
22
|
+
process.exit(1);
|
|
47
23
|
}
|
|
48
|
-
|
|
49
|
-
|
|
24
|
+
const config = loadConfig(options.config);
|
|
25
|
+
if (options.provider)
|
|
26
|
+
config.llm.provider = options.provider;
|
|
27
|
+
if (options.model)
|
|
28
|
+
config.llm.model = options.model;
|
|
29
|
+
const { ok, envKey } = checkApiKey(config.llm.provider);
|
|
30
|
+
if (!ok && envKey) {
|
|
31
|
+
console.error(`Error: ${envKey} environment variable required`);
|
|
32
|
+
process.exit(1);
|
|
50
33
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
34
|
+
const filePath = resolve(file);
|
|
35
|
+
console.log(`skrypt autofix`);
|
|
36
|
+
console.log(` file: ${filePath}`);
|
|
37
|
+
console.log(` provider: ${config.llm.provider}`);
|
|
38
|
+
console.log(` max iterations: ${options.maxIterations}`);
|
|
39
|
+
console.log('');
|
|
40
|
+
// Read the file
|
|
41
|
+
let content;
|
|
42
|
+
try {
|
|
43
|
+
content = readFileSync(filePath, 'utf-8');
|
|
54
44
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
code,
|
|
69
|
-
index: match.index,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
if (codeBlocks.length === 0) {
|
|
73
|
-
console.log('No code blocks found in file.');
|
|
74
|
-
process.exit(0);
|
|
75
|
-
}
|
|
76
|
-
console.log(`Found ${codeBlocks.length} code block(s)`);
|
|
77
|
-
console.log('');
|
|
78
|
-
const client = createLLMClient({
|
|
79
|
-
provider: config.llm.provider,
|
|
80
|
-
model: config.llm.model,
|
|
81
|
-
baseUrl: config.llm.baseUrl,
|
|
82
|
-
});
|
|
83
|
-
const maxIterations = parseInt(options.maxIterations);
|
|
84
|
-
// Create validators
|
|
85
|
-
const validators = {
|
|
86
|
-
javascript: createTypeScriptValidator(),
|
|
87
|
-
typescript: createTypeScriptValidator(),
|
|
88
|
-
ts: createTypeScriptValidator(),
|
|
89
|
-
js: createTypeScriptValidator(),
|
|
90
|
-
python: createPythonValidator(),
|
|
91
|
-
py: createPythonValidator(),
|
|
92
|
-
};
|
|
93
|
-
let fixedCount = 0;
|
|
94
|
-
let failedCount = 0;
|
|
95
|
-
let newContent = content;
|
|
96
|
-
for (let i = 0; i < codeBlocks.length; i++) {
|
|
97
|
-
const block = codeBlocks[i];
|
|
98
|
-
if (!block)
|
|
99
|
-
continue;
|
|
100
|
-
const validator = validators[block.language.toLowerCase()];
|
|
101
|
-
if (!validator) {
|
|
102
|
-
console.log(`[${i + 1}/${codeBlocks.length}] Skipping ${block.language} (no validator)`);
|
|
103
|
-
continue;
|
|
45
|
+
catch (err) {
|
|
46
|
+
const errObj = err;
|
|
47
|
+
if (errObj.code === 'ENOENT') {
|
|
48
|
+
console.error(`Error: File not found: ${filePath}`);
|
|
49
|
+
}
|
|
50
|
+
else if (errObj.code === 'EACCES') {
|
|
51
|
+
console.error(`Error: Permission denied: ${filePath}`);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
55
|
+
console.error(`Error: Could not read file: ${filePath} (${message})`);
|
|
56
|
+
}
|
|
57
|
+
process.exit(1);
|
|
104
58
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
59
|
+
// Find all code blocks
|
|
60
|
+
const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
|
|
61
|
+
const codeBlocks = [];
|
|
62
|
+
let match;
|
|
63
|
+
while ((match = codeBlockRegex.exec(content)) !== null) {
|
|
64
|
+
const code = match[2];
|
|
65
|
+
if (!code)
|
|
66
|
+
continue;
|
|
67
|
+
codeBlocks.push({
|
|
68
|
+
match: match[0],
|
|
69
|
+
language: options.language || match[1] || 'javascript',
|
|
70
|
+
code,
|
|
71
|
+
index: match.index,
|
|
72
|
+
});
|
|
111
73
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
74
|
+
if (codeBlocks.length === 0) {
|
|
75
|
+
console.log('No code blocks found in file.');
|
|
76
|
+
process.exit(0);
|
|
77
|
+
}
|
|
78
|
+
console.log(`Found ${codeBlocks.length} code block(s)`);
|
|
79
|
+
console.log('');
|
|
80
|
+
const client = createLLMClient({
|
|
81
|
+
provider: config.llm.provider,
|
|
82
|
+
model: config.llm.model,
|
|
83
|
+
baseUrl: config.llm.baseUrl,
|
|
122
84
|
});
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const newBlock = '```' + block.language + '\n' + result.fixedCode + '```';
|
|
128
|
-
newContent = newContent.replace(block.match, newBlock);
|
|
85
|
+
const maxIterations = parseInt(options.maxIterations, 10);
|
|
86
|
+
if (isNaN(maxIterations) || maxIterations < 1) {
|
|
87
|
+
console.error('Error: --max-iterations must be a positive number');
|
|
88
|
+
process.exit(1);
|
|
129
89
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
90
|
+
// Create validators
|
|
91
|
+
const validators = {
|
|
92
|
+
javascript: createTypeScriptValidator(),
|
|
93
|
+
typescript: createTypeScriptValidator(),
|
|
94
|
+
ts: createTypeScriptValidator(),
|
|
95
|
+
js: createTypeScriptValidator(),
|
|
96
|
+
python: createPythonValidator(),
|
|
97
|
+
py: createPythonValidator(),
|
|
98
|
+
};
|
|
99
|
+
let fixedCount = 0;
|
|
100
|
+
let failedCount = 0;
|
|
101
|
+
let newContent = content;
|
|
102
|
+
for (let i = 0; i < codeBlocks.length; i++) {
|
|
103
|
+
const block = codeBlocks[i];
|
|
104
|
+
if (!block)
|
|
105
|
+
continue;
|
|
106
|
+
const validator = validators[block.language.toLowerCase()];
|
|
107
|
+
if (!validator) {
|
|
108
|
+
console.log(`[${i + 1}/${codeBlocks.length}] Skipping ${block.language} (no validator)`);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
console.log(`[${i + 1}/${codeBlocks.length}] Checking ${block.language} example...`);
|
|
112
|
+
// First check if it's valid
|
|
113
|
+
const initial = await validator(block.code);
|
|
114
|
+
if (initial.valid) {
|
|
115
|
+
console.log(` ✓ Already valid`);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
console.log(` ✗ Invalid: ${initial.errors[0]?.slice(0, 60)}...`);
|
|
119
|
+
console.log(` → Attempting to fix...`);
|
|
120
|
+
const result = await autoFixExample({
|
|
121
|
+
code: block.code,
|
|
122
|
+
language: block.language,
|
|
123
|
+
context: `Code example from documentation file: ${file}`,
|
|
124
|
+
}, client, {
|
|
125
|
+
maxIterations,
|
|
126
|
+
validateFn: validator,
|
|
127
|
+
language: block.language,
|
|
128
|
+
});
|
|
129
|
+
if (result.success) {
|
|
130
|
+
console.log(` ✓ Fixed in ${result.iterations} iteration(s)`);
|
|
131
|
+
fixedCount++;
|
|
132
|
+
// Replace in content
|
|
133
|
+
const newBlock = '```' + block.language + '\n' + result.fixedCode + '```';
|
|
134
|
+
newContent = newContent.replace(block.match, newBlock);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
console.log(` ✗ Could not fix after ${result.iterations} iterations`);
|
|
138
|
+
failedCount++;
|
|
139
|
+
}
|
|
133
140
|
}
|
|
141
|
+
console.log('');
|
|
142
|
+
console.log('=== Summary ===');
|
|
143
|
+
console.log(` Checked: ${codeBlocks.length}`);
|
|
144
|
+
console.log(` Fixed: ${fixedCount}`);
|
|
145
|
+
console.log(` Failed: ${failedCount}`);
|
|
146
|
+
if (fixedCount > 0 && !options.dryRun) {
|
|
147
|
+
writeFileSync(filePath, newContent);
|
|
148
|
+
console.log(`\nWrote fixes to ${filePath}`);
|
|
149
|
+
// Auto-fix then run QA on the fixed file's directory
|
|
150
|
+
const fixReport = fixQAIssues(dirname(filePath));
|
|
151
|
+
printFixReport(fixReport);
|
|
152
|
+
const qaReport = runQA(dirname(filePath));
|
|
153
|
+
printQAReport(qaReport);
|
|
154
|
+
}
|
|
155
|
+
else if (fixedCount > 0 && options.dryRun) {
|
|
156
|
+
console.log(`\n[dry run - no changes written]`);
|
|
157
|
+
}
|
|
158
|
+
console.log('\nDone!');
|
|
134
159
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
console.log(` Fixed: ${fixedCount}`);
|
|
139
|
-
console.log(` Failed: ${failedCount}`);
|
|
140
|
-
if (fixedCount > 0 && !options.dryRun) {
|
|
141
|
-
writeFileSync(filePath, newContent);
|
|
142
|
-
console.log(`\nWrote fixes to ${filePath}`);
|
|
143
|
-
}
|
|
144
|
-
else if (fixedCount > 0 && options.dryRun) {
|
|
145
|
-
console.log(`\n[dry run - no changes written]`);
|
|
160
|
+
catch (err) {
|
|
161
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
162
|
+
process.exit(1);
|
|
146
163
|
}
|
|
147
|
-
console.log('\nDone!');
|
|
148
164
|
});
|
package/dist/commands/cron.js
CHANGED
|
@@ -54,53 +54,64 @@ export const cronCommand = new Command('cron')
|
|
|
54
54
|
.option('-s, --schedule <cron>', 'Cron schedule (default: daily at 2am UTC)', '0 2 * * *')
|
|
55
55
|
.option('-f, --force', 'Overwrite existing workflow')
|
|
56
56
|
.action(async (repoPath, options) => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
57
|
+
try {
|
|
58
|
+
const resolvedPath = resolve(repoPath);
|
|
59
|
+
const workflowDir = join(resolvedPath, '.github', 'workflows');
|
|
60
|
+
const workflowPath = join(workflowDir, 'skrypt-docs.yml');
|
|
61
|
+
console.log('skrypt cron');
|
|
62
|
+
console.log(` repo: ${resolvedPath}`);
|
|
63
|
+
console.log(` schedule: ${options.schedule}`);
|
|
64
|
+
console.log('');
|
|
65
|
+
// Validate cron schedule format
|
|
66
|
+
if (options.schedule && !/^[\d\s*,\-/]+$/.test(options.schedule)) {
|
|
67
|
+
console.error('Error: Invalid cron schedule format');
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
// Check if workflow exists
|
|
71
|
+
if (existsSync(workflowPath) && !options.force) {
|
|
72
|
+
console.log('Workflow already exists. Use --force to overwrite.');
|
|
73
|
+
console.log(` ${workflowPath}`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
// Create workflow directory
|
|
77
|
+
mkdirSync(workflowDir, { recursive: true });
|
|
78
|
+
// Customize schedule if provided
|
|
79
|
+
let workflow = CRON_WORKFLOW;
|
|
80
|
+
if (options.schedule && options.schedule !== '0 2 * * *') {
|
|
81
|
+
workflow = workflow.replace("cron: '0 2 * * *'", `cron: '${options.schedule}'`);
|
|
82
|
+
}
|
|
83
|
+
// Write workflow
|
|
84
|
+
writeFileSync(workflowPath, workflow);
|
|
85
|
+
console.log(`✓ Created: ${workflowPath}`);
|
|
86
|
+
console.log('');
|
|
87
|
+
console.log('=== Setup Instructions ===');
|
|
88
|
+
console.log('');
|
|
89
|
+
console.log('1. Add secrets to your GitHub repository:');
|
|
90
|
+
console.log(' Settings > Secrets and variables > Actions');
|
|
91
|
+
console.log('');
|
|
92
|
+
console.log(' Required:');
|
|
93
|
+
console.log(' - SKRYPT_API_KEY: Get from https://skrypt.sh/dashboard/settings');
|
|
94
|
+
console.log('');
|
|
95
|
+
console.log(' For AI generation (one of):');
|
|
96
|
+
console.log(' - OPENAI_API_KEY');
|
|
97
|
+
console.log(' - ANTHROPIC_API_KEY');
|
|
98
|
+
console.log('');
|
|
99
|
+
console.log('2. Commit and push:');
|
|
100
|
+
console.log(' git add .github/');
|
|
101
|
+
console.log(' git commit -m "Add Skrypt auto-update workflow"');
|
|
102
|
+
console.log(' git push');
|
|
103
|
+
console.log('');
|
|
104
|
+
console.log('3. Trigger manually (optional):');
|
|
105
|
+
console.log(' Go to Actions > Skrypt Auto-Update Docs > Run workflow');
|
|
106
|
+
console.log('');
|
|
107
|
+
console.log('Common schedules:');
|
|
108
|
+
console.log(' "0 2 * * *" - Daily at 2am UTC');
|
|
109
|
+
console.log(' "0 2 * * 1" - Weekly on Monday');
|
|
110
|
+
console.log(' "0 2 1 * *" - Monthly on the 1st');
|
|
111
|
+
console.log(' "0 */6 * * *" - Every 6 hours');
|
|
69
112
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
let workflow = CRON_WORKFLOW;
|
|
74
|
-
if (options.schedule && options.schedule !== '0 2 * * *') {
|
|
75
|
-
workflow = workflow.replace("cron: '0 2 * * *'", `cron: '${options.schedule}'`);
|
|
113
|
+
catch (err) {
|
|
114
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
115
|
+
process.exit(1);
|
|
76
116
|
}
|
|
77
|
-
// Write workflow
|
|
78
|
-
writeFileSync(workflowPath, workflow);
|
|
79
|
-
console.log(`✓ Created: ${workflowPath}`);
|
|
80
|
-
console.log('');
|
|
81
|
-
console.log('=== Setup Instructions ===');
|
|
82
|
-
console.log('');
|
|
83
|
-
console.log('1. Add secrets to your GitHub repository:');
|
|
84
|
-
console.log(' Settings > Secrets and variables > Actions');
|
|
85
|
-
console.log('');
|
|
86
|
-
console.log(' Required:');
|
|
87
|
-
console.log(' - SKRYPT_API_KEY: Get from https://skrypt.sh/dashboard/settings');
|
|
88
|
-
console.log('');
|
|
89
|
-
console.log(' For AI generation (one of):');
|
|
90
|
-
console.log(' - OPENAI_API_KEY');
|
|
91
|
-
console.log(' - ANTHROPIC_API_KEY');
|
|
92
|
-
console.log('');
|
|
93
|
-
console.log('2. Commit and push:');
|
|
94
|
-
console.log(' git add .github/');
|
|
95
|
-
console.log(' git commit -m "Add Skrypt auto-update workflow"');
|
|
96
|
-
console.log(' git push');
|
|
97
|
-
console.log('');
|
|
98
|
-
console.log('3. Trigger manually (optional):');
|
|
99
|
-
console.log(' Go to Actions > Skrypt Auto-Update Docs > Run workflow');
|
|
100
|
-
console.log('');
|
|
101
|
-
console.log('Common schedules:');
|
|
102
|
-
console.log(' "0 2 * * *" - Daily at 2am UTC');
|
|
103
|
-
console.log(' "0 2 * * 1" - Weekly on Monday');
|
|
104
|
-
console.log(' "0 2 1 * *" - Monthly on the 1st');
|
|
105
|
-
console.log(' "0 */6 * * *" - Every 6 hours');
|
|
106
117
|
});
|
package/dist/commands/deploy.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { spawnSync, spawn } from 'child_process';
|
|
3
|
-
import { existsSync, readFileSync, statSync } from 'fs';
|
|
3
|
+
import { existsSync, readFileSync, statSync, unlinkSync } from 'fs';
|
|
4
4
|
import { resolve, join } from 'path';
|
|
5
5
|
import { homedir } from 'os';
|
|
6
6
|
import { createHash } from 'crypto';
|
|
@@ -81,8 +81,7 @@ async function buildSite(docsPath) {
|
|
|
81
81
|
return new Promise((resolve, reject) => {
|
|
82
82
|
const child = spawn('npm', ['run', 'build'], {
|
|
83
83
|
cwd: docsPath,
|
|
84
|
-
stdio: ['inherit', 'pipe', 'pipe']
|
|
85
|
-
shell: true
|
|
84
|
+
stdio: ['inherit', 'pipe', 'pipe']
|
|
86
85
|
});
|
|
87
86
|
child.stdout?.on('data', (data) => {
|
|
88
87
|
process.stdout.write(` ${data.toString().trim()}\n`);
|
|
@@ -208,113 +207,135 @@ export const deployCommand = new Command('deploy')
|
|
|
208
207
|
.option('--project <slug>', 'Project slug (e.g., my-docs)')
|
|
209
208
|
.option('--token <key>', 'API token (or set SKRYPT_API_KEY env var)')
|
|
210
209
|
.action(async (directory, options) => {
|
|
211
|
-
|
|
212
|
-
const docsPath = resolve(directory);
|
|
213
|
-
console.log('skrypt deploy');
|
|
214
|
-
console.log(` directory: ${docsPath}`);
|
|
215
|
-
console.log('');
|
|
216
|
-
// Validate directory
|
|
217
|
-
if (!existsSync(docsPath)) {
|
|
218
|
-
console.error(`Error: Directory not found: ${docsPath}`);
|
|
219
|
-
process.exit(1);
|
|
220
|
-
}
|
|
221
|
-
// Check for package.json (Next.js project)
|
|
222
|
-
const packageJsonPath = join(docsPath, 'package.json');
|
|
223
|
-
if (!existsSync(packageJsonPath)) {
|
|
224
|
-
console.error('Error: No package.json found. Is this a Skrypt docs site?');
|
|
225
|
-
console.error(' Run: skrypt init <directory>');
|
|
226
|
-
process.exit(1);
|
|
227
|
-
}
|
|
228
|
-
// Get API token
|
|
229
|
-
const apiToken = getApiToken(options);
|
|
230
|
-
if (!apiToken) {
|
|
231
|
-
console.error('Error: No API token found.');
|
|
232
|
-
console.error('');
|
|
233
|
-
console.error(' Provide a token using one of:');
|
|
234
|
-
console.error(' --token <key>');
|
|
235
|
-
console.error(' SKRYPT_API_KEY environment variable');
|
|
236
|
-
console.error(' skrypt login');
|
|
237
|
-
console.error('');
|
|
238
|
-
process.exit(1);
|
|
239
|
-
}
|
|
240
|
-
// Get project slug
|
|
241
|
-
const projectSlug = getProjectSlug(options, docsPath);
|
|
242
|
-
if (!projectSlug) {
|
|
243
|
-
console.error('Error: No project slug found.');
|
|
244
|
-
console.error('');
|
|
245
|
-
console.error(' Provide a project slug using one of:');
|
|
246
|
-
console.error(' --project <slug>');
|
|
247
|
-
console.error(' "slug" field in docs.json');
|
|
248
|
-
console.error('');
|
|
249
|
-
process.exit(1);
|
|
250
|
-
}
|
|
251
|
-
console.log(` project: ${projectSlug}`);
|
|
252
|
-
console.log('');
|
|
253
|
-
// Step 1: Build the site
|
|
254
|
-
console.log('Step 1: Building documentation site...');
|
|
255
|
-
let outDir;
|
|
210
|
+
let bundlePath;
|
|
256
211
|
try {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
console.
|
|
261
|
-
console.
|
|
262
|
-
|
|
263
|
-
|
|
212
|
+
const startTime = Date.now();
|
|
213
|
+
const docsPath = resolve(directory);
|
|
214
|
+
console.log('skrypt deploy');
|
|
215
|
+
console.log(` directory: ${docsPath}`);
|
|
216
|
+
console.log('');
|
|
217
|
+
// Validate directory
|
|
218
|
+
if (!existsSync(docsPath)) {
|
|
219
|
+
console.error(`Error: Directory not found: ${docsPath}`);
|
|
220
|
+
process.exit(1);
|
|
264
221
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
222
|
+
// Check for package.json (Next.js project)
|
|
223
|
+
const packageJsonPath = join(docsPath, 'package.json');
|
|
224
|
+
if (!existsSync(packageJsonPath)) {
|
|
225
|
+
console.error('Error: No package.json found. Is this a Skrypt docs site?');
|
|
226
|
+
console.error(' Run: skrypt init <directory>');
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
229
|
+
// Get API token
|
|
230
|
+
const apiToken = getApiToken(options);
|
|
231
|
+
if (!apiToken) {
|
|
232
|
+
console.error('Error: No API token found.');
|
|
233
|
+
console.error('');
|
|
234
|
+
console.error(' Provide a token using one of:');
|
|
235
|
+
console.error(' --token <key>');
|
|
236
|
+
console.error(' SKRYPT_API_KEY environment variable');
|
|
237
|
+
console.error(' skrypt login');
|
|
272
238
|
console.error('');
|
|
273
|
-
console.error('Error: Static export not found.');
|
|
274
|
-
console.error(' Add to next.config.mjs: output: "export"');
|
|
275
239
|
process.exit(1);
|
|
276
240
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
241
|
+
// Get project slug
|
|
242
|
+
const projectSlug = getProjectSlug(options, docsPath);
|
|
243
|
+
if (!projectSlug) {
|
|
244
|
+
console.error('Error: No project slug found.');
|
|
245
|
+
console.error('');
|
|
246
|
+
console.error(' Provide a project slug using one of:');
|
|
247
|
+
console.error(' --project <slug>');
|
|
248
|
+
console.error(' "slug" field in docs.json');
|
|
249
|
+
console.error('');
|
|
250
|
+
process.exit(1);
|
|
251
|
+
}
|
|
252
|
+
console.log(` project: ${projectSlug}`);
|
|
253
|
+
console.log('');
|
|
254
|
+
// Step 1: Build the site
|
|
255
|
+
console.log('Step 1: Building documentation site...');
|
|
256
|
+
let outDir;
|
|
257
|
+
try {
|
|
258
|
+
outDir = await buildSite(docsPath);
|
|
259
|
+
}
|
|
260
|
+
catch (err) {
|
|
261
|
+
console.error('');
|
|
262
|
+
console.error(`Error: Build failed`);
|
|
263
|
+
if (err instanceof Error) {
|
|
264
|
+
console.error(` ${err.message}`);
|
|
265
|
+
}
|
|
266
|
+
process.exit(1);
|
|
267
|
+
}
|
|
268
|
+
// Check build output exists
|
|
269
|
+
if (!existsSync(outDir)) {
|
|
270
|
+
// Try .next/static for non-static export
|
|
271
|
+
const nextDir = join(docsPath, '.next');
|
|
272
|
+
if (existsSync(nextDir)) {
|
|
273
|
+
console.error('');
|
|
274
|
+
console.error('Error: Static export not found.');
|
|
275
|
+
console.error(' Add to next.config.mjs: output: "export"');
|
|
276
|
+
process.exit(1);
|
|
277
|
+
}
|
|
278
|
+
console.error('');
|
|
279
|
+
console.error('Error: Build output not found.');
|
|
280
|
+
process.exit(1);
|
|
281
|
+
}
|
|
282
|
+
console.log(' Build completed successfully');
|
|
283
|
+
console.log('');
|
|
284
|
+
// Step 2: Bundle the output
|
|
285
|
+
console.log('Step 2: Creating deployment bundle...');
|
|
286
|
+
try {
|
|
287
|
+
bundlePath = await bundleOutput(outDir);
|
|
288
|
+
}
|
|
289
|
+
catch (err) {
|
|
290
|
+
console.error('');
|
|
291
|
+
console.error('Error: Failed to create bundle');
|
|
292
|
+
if (err instanceof Error) {
|
|
293
|
+
console.error(` ${err.message}`);
|
|
294
|
+
}
|
|
295
|
+
process.exit(1);
|
|
296
|
+
}
|
|
297
|
+
console.log('');
|
|
298
|
+
// Step 3: Upload
|
|
299
|
+
console.log('Step 3: Deploying to Skrypt...');
|
|
300
|
+
const result = await uploadBundle(bundlePath, projectSlug, apiToken);
|
|
301
|
+
if (!result.success) {
|
|
302
|
+
console.error('');
|
|
303
|
+
console.error(`Error: Deployment failed`);
|
|
304
|
+
console.error(` ${result.error}`);
|
|
305
|
+
// Clean up temp bundle
|
|
306
|
+
try {
|
|
307
|
+
unlinkSync(bundlePath);
|
|
308
|
+
}
|
|
309
|
+
catch { /* ignore cleanup errors */ }
|
|
310
|
+
process.exit(1);
|
|
311
|
+
}
|
|
312
|
+
// Clean up temp bundle
|
|
313
|
+
try {
|
|
314
|
+
unlinkSync(bundlePath);
|
|
315
|
+
}
|
|
316
|
+
catch { /* ignore cleanup errors */ }
|
|
317
|
+
// Success
|
|
318
|
+
const duration = Math.round((Date.now() - startTime) / 1000);
|
|
319
|
+
console.log('');
|
|
320
|
+
console.log('=== Deployment Successful ===');
|
|
321
|
+
console.log('');
|
|
322
|
+
console.log(` URL: ${result.url}`);
|
|
323
|
+
if (result.customDomain) {
|
|
324
|
+
console.log(` Custom domain: ${result.customDomain}`);
|
|
325
|
+
}
|
|
326
|
+
console.log(` Duration: ${duration}s`);
|
|
327
|
+
console.log('');
|
|
328
|
+
console.log('Your documentation is now live!');
|
|
329
|
+
console.log('');
|
|
288
330
|
}
|
|
289
331
|
catch (err) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
332
|
+
if (bundlePath) {
|
|
333
|
+
try {
|
|
334
|
+
unlinkSync(bundlePath);
|
|
335
|
+
}
|
|
336
|
+
catch { /* ignore cleanup errors */ }
|
|
294
337
|
}
|
|
338
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
295
339
|
process.exit(1);
|
|
296
340
|
}
|
|
297
|
-
console.log('');
|
|
298
|
-
// Step 3: Upload
|
|
299
|
-
console.log('Step 3: Deploying to Skrypt...');
|
|
300
|
-
const result = await uploadBundle(bundlePath, projectSlug, apiToken);
|
|
301
|
-
if (!result.success) {
|
|
302
|
-
console.error('');
|
|
303
|
-
console.error(`Error: Deployment failed`);
|
|
304
|
-
console.error(` ${result.error}`);
|
|
305
|
-
process.exit(1);
|
|
306
|
-
}
|
|
307
|
-
// Success
|
|
308
|
-
const duration = Math.round((Date.now() - startTime) / 1000);
|
|
309
|
-
console.log('');
|
|
310
|
-
console.log('=== Deployment Successful ===');
|
|
311
|
-
console.log('');
|
|
312
|
-
console.log(` URL: ${result.url}`);
|
|
313
|
-
if (result.customDomain) {
|
|
314
|
-
console.log(` Custom domain: ${result.customDomain}`);
|
|
315
|
-
}
|
|
316
|
-
console.log(` Duration: ${duration}s`);
|
|
317
|
-
console.log('');
|
|
318
|
-
console.log('Your documentation is now live!');
|
|
319
|
-
console.log('');
|
|
320
341
|
});
|