busy-cli 0.1.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 +129 -0
- package/dist/builders/context.d.ts +50 -0
- package/dist/builders/context.d.ts.map +1 -0
- package/dist/builders/context.js +190 -0
- package/dist/cache/index.d.ts +100 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +270 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +463 -0
- package/dist/commands/package.d.ts +96 -0
- package/dist/commands/package.d.ts.map +1 -0
- package/dist/commands/package.js +285 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/loader.d.ts +6 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +361 -0
- package/dist/merge.d.ts +16 -0
- package/dist/merge.d.ts.map +1 -0
- package/dist/merge.js +102 -0
- package/dist/package/manifest.d.ts +59 -0
- package/dist/package/manifest.d.ts.map +1 -0
- package/dist/package/manifest.js +265 -0
- package/dist/parser.d.ts +28 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +220 -0
- package/dist/parsers/frontmatter.d.ts +14 -0
- package/dist/parsers/frontmatter.d.ts.map +1 -0
- package/dist/parsers/frontmatter.js +110 -0
- package/dist/parsers/imports.d.ts +48 -0
- package/dist/parsers/imports.d.ts.map +1 -0
- package/dist/parsers/imports.js +147 -0
- package/dist/parsers/links.d.ts +12 -0
- package/dist/parsers/links.d.ts.map +1 -0
- package/dist/parsers/links.js +79 -0
- package/dist/parsers/localdefs.d.ts +6 -0
- package/dist/parsers/localdefs.d.ts.map +1 -0
- package/dist/parsers/localdefs.js +132 -0
- package/dist/parsers/operations.d.ts +32 -0
- package/dist/parsers/operations.d.ts.map +1 -0
- package/dist/parsers/operations.js +313 -0
- package/dist/parsers/sections.d.ts +15 -0
- package/dist/parsers/sections.d.ts.map +1 -0
- package/dist/parsers/sections.js +173 -0
- package/dist/parsers/tools.d.ts +30 -0
- package/dist/parsers/tools.d.ts.map +1 -0
- package/dist/parsers/tools.js +178 -0
- package/dist/parsers/triggers.d.ts +35 -0
- package/dist/parsers/triggers.d.ts.map +1 -0
- package/dist/parsers/triggers.js +219 -0
- package/dist/providers/base.d.ts +60 -0
- package/dist/providers/base.d.ts.map +1 -0
- package/dist/providers/base.js +34 -0
- package/dist/providers/github.d.ts +18 -0
- package/dist/providers/github.d.ts.map +1 -0
- package/dist/providers/github.js +109 -0
- package/dist/providers/gitlab.d.ts +18 -0
- package/dist/providers/gitlab.d.ts.map +1 -0
- package/dist/providers/gitlab.js +101 -0
- package/dist/providers/index.d.ts +13 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +17 -0
- package/dist/providers/local.d.ts +31 -0
- package/dist/providers/local.d.ts.map +1 -0
- package/dist/providers/local.js +116 -0
- package/dist/providers/url.d.ts +16 -0
- package/dist/providers/url.d.ts.map +1 -0
- package/dist/providers/url.js +45 -0
- package/dist/registry/index.d.ts +99 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +320 -0
- package/dist/types/schema.d.ts +3259 -0
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/types/schema.js +258 -0
- package/dist/utils/logger.d.ts +19 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +23 -0
- package/dist/utils/slugify.d.ts +14 -0
- package/dist/utils/slugify.d.ts.map +1 -0
- package/dist/utils/slugify.js +28 -0
- package/package.json +61 -0
- package/src/__tests__/cache.test.ts +393 -0
- package/src/__tests__/cli-package.test.ts +667 -0
- package/src/__tests__/fixtures/automated-workflow.busy.md +84 -0
- package/src/__tests__/fixtures/concept.busy.md +30 -0
- package/src/__tests__/fixtures/document.busy.md +44 -0
- package/src/__tests__/fixtures/simple-operation.busy.md +45 -0
- package/src/__tests__/fixtures/tool-document.busy.md +71 -0
- package/src/__tests__/fixtures/tool.busy.md +54 -0
- package/src/__tests__/imports.test.ts +244 -0
- package/src/__tests__/integration.test.ts +432 -0
- package/src/__tests__/operations.test.ts +408 -0
- package/src/__tests__/package-manifest.test.ts +455 -0
- package/src/__tests__/providers.test.ts +672 -0
- package/src/__tests__/registry.test.ts +402 -0
- package/src/__tests__/schema.test.ts +467 -0
- package/src/__tests__/tools.test.ts +376 -0
- package/src/__tests__/triggers.test.ts +312 -0
- package/src/builders/context.ts +294 -0
- package/src/cache/index.ts +312 -0
- package/src/cli/index.ts +514 -0
- package/src/commands/package.ts +392 -0
- package/src/index.ts +46 -0
- package/src/loader.ts +474 -0
- package/src/merge.ts +126 -0
- package/src/package/manifest.ts +349 -0
- package/src/parser.ts +278 -0
- package/src/parsers/frontmatter.ts +135 -0
- package/src/parsers/imports.ts +196 -0
- package/src/parsers/links.ts +108 -0
- package/src/parsers/localdefs.ts +166 -0
- package/src/parsers/operations.ts +404 -0
- package/src/parsers/sections.ts +230 -0
- package/src/parsers/tools.ts +215 -0
- package/src/parsers/triggers.ts +252 -0
- package/src/providers/base.ts +77 -0
- package/src/providers/github.ts +129 -0
- package/src/providers/gitlab.ts +121 -0
- package/src/providers/index.ts +25 -0
- package/src/providers/local.ts +129 -0
- package/src/providers/url.ts +56 -0
- package/src/registry/index.ts +408 -0
- package/src/types/schema.ts +369 -0
- package/src/utils/logger.ts +25 -0
- package/src/utils/slugify.ts +31 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache Manager for .libraries/
|
|
3
|
+
*
|
|
4
|
+
* Manages local cache of fetched packages.
|
|
5
|
+
*/
|
|
6
|
+
import { promises as fs } from 'node:fs';
|
|
7
|
+
import * as path from 'node:path';
|
|
8
|
+
import * as crypto from 'node:crypto';
|
|
9
|
+
/**
|
|
10
|
+
* Calculate SHA256 integrity hash of content
|
|
11
|
+
*/
|
|
12
|
+
export function calculateIntegrity(content) {
|
|
13
|
+
const hash = crypto.createHash('sha256').update(content, 'utf-8').digest('hex');
|
|
14
|
+
return `sha256:${hash}`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Verify content matches integrity hash
|
|
18
|
+
*/
|
|
19
|
+
export function verifyIntegrity(content, integrity) {
|
|
20
|
+
if (!integrity.startsWith('sha256:')) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
const calculated = calculateIntegrity(content);
|
|
24
|
+
return calculated === integrity;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Derive cache path from parsed URL
|
|
28
|
+
*
|
|
29
|
+
* For GitHub/GitLab: {repo}/{path-from-blob}
|
|
30
|
+
* For generic URLs: {domain}/{path}
|
|
31
|
+
*/
|
|
32
|
+
export function deriveCachePath(parsed) {
|
|
33
|
+
if (parsed.provider === 'github' || parsed.provider === 'gitlab') {
|
|
34
|
+
// Use repo name + path
|
|
35
|
+
return `${parsed.repo}/${parsed.path}`;
|
|
36
|
+
}
|
|
37
|
+
// Generic URL - extract domain and path
|
|
38
|
+
if (parsed.rawUrl) {
|
|
39
|
+
try {
|
|
40
|
+
const url = new URL(parsed.rawUrl);
|
|
41
|
+
// Combine hostname with pathname (remove leading slash)
|
|
42
|
+
const pathname = parsed.path.startsWith('/') ? parsed.path.slice(1) : parsed.path;
|
|
43
|
+
return `${url.hostname}/${pathname}`;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// Fallback to just using the path
|
|
47
|
+
return parsed.path.startsWith('/') ? parsed.path.slice(1) : parsed.path;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return parsed.path.startsWith('/') ? parsed.path.slice(1) : parsed.path;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Cache Manager
|
|
54
|
+
*
|
|
55
|
+
* Manages the .libraries/ cache directory.
|
|
56
|
+
*/
|
|
57
|
+
export class CacheManager {
|
|
58
|
+
_workspaceRoot;
|
|
59
|
+
_librariesPath;
|
|
60
|
+
constructor(workspaceRoot) {
|
|
61
|
+
this._workspaceRoot = workspaceRoot;
|
|
62
|
+
this._librariesPath = path.join(workspaceRoot, '.libraries');
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get workspace root path
|
|
66
|
+
*/
|
|
67
|
+
get workspaceRoot() {
|
|
68
|
+
return this._workspaceRoot;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get .libraries path
|
|
72
|
+
*/
|
|
73
|
+
get librariesPath() {
|
|
74
|
+
return this._librariesPath;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Initialize cache directory
|
|
78
|
+
*/
|
|
79
|
+
async init() {
|
|
80
|
+
await fs.mkdir(this._librariesPath, { recursive: true });
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Save content to cache
|
|
84
|
+
*/
|
|
85
|
+
async save(cachePath, content) {
|
|
86
|
+
const fullPath = this.getFullPath(cachePath);
|
|
87
|
+
// Create parent directories
|
|
88
|
+
await fs.mkdir(path.dirname(fullPath), { recursive: true });
|
|
89
|
+
// Write content
|
|
90
|
+
await fs.writeFile(fullPath, content, 'utf-8');
|
|
91
|
+
// Calculate integrity
|
|
92
|
+
const integrity = calculateIntegrity(content);
|
|
93
|
+
return {
|
|
94
|
+
path: cachePath,
|
|
95
|
+
fullPath,
|
|
96
|
+
integrity,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Read content from cache
|
|
101
|
+
*/
|
|
102
|
+
async read(cachePath) {
|
|
103
|
+
const fullPath = this.getFullPath(cachePath);
|
|
104
|
+
return fs.readFile(fullPath, 'utf-8');
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Check if file exists in cache
|
|
108
|
+
*/
|
|
109
|
+
async exists(cachePath) {
|
|
110
|
+
const fullPath = this.getFullPath(cachePath);
|
|
111
|
+
try {
|
|
112
|
+
await fs.stat(fullPath);
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Delete file from cache
|
|
121
|
+
*/
|
|
122
|
+
async delete(cachePath) {
|
|
123
|
+
const fullPath = this.getFullPath(cachePath);
|
|
124
|
+
try {
|
|
125
|
+
await fs.unlink(fullPath);
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
// Ignore if file doesn't exist
|
|
129
|
+
if (error.code !== 'ENOENT') {
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
// Clean up empty parent directories
|
|
135
|
+
await this.cleanEmptyDirs(path.dirname(fullPath));
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* List all cached files
|
|
139
|
+
*/
|
|
140
|
+
async list() {
|
|
141
|
+
const files = [];
|
|
142
|
+
try {
|
|
143
|
+
await this.walkDir(this._librariesPath, files);
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
// Return empty if .libraries doesn't exist
|
|
147
|
+
if (error.code === 'ENOENT') {
|
|
148
|
+
return [];
|
|
149
|
+
}
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
return files;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Remove all cached files
|
|
156
|
+
*/
|
|
157
|
+
async clean() {
|
|
158
|
+
const files = await this.list();
|
|
159
|
+
for (const file of files) {
|
|
160
|
+
const fullPath = this.getFullPath(file);
|
|
161
|
+
await fs.unlink(fullPath);
|
|
162
|
+
}
|
|
163
|
+
// Clean up all empty directories
|
|
164
|
+
try {
|
|
165
|
+
await this.cleanAllEmptyDirs(this._librariesPath);
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
// Ignore errors during cleanup
|
|
169
|
+
}
|
|
170
|
+
return files.length;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Verify integrity of cached file
|
|
174
|
+
*/
|
|
175
|
+
async verifyIntegrity(cachePath, integrity) {
|
|
176
|
+
try {
|
|
177
|
+
const content = await this.read(cachePath);
|
|
178
|
+
return verifyIntegrity(content, integrity);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Get full filesystem path from cache path
|
|
186
|
+
*/
|
|
187
|
+
getFullPath(cachePath) {
|
|
188
|
+
return path.join(this._librariesPath, cachePath);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get cache path from full filesystem path
|
|
192
|
+
*/
|
|
193
|
+
getCachePath(fullPath) {
|
|
194
|
+
if (!fullPath.startsWith(this._librariesPath)) {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
const relativePath = path.relative(this._librariesPath, fullPath);
|
|
198
|
+
// Make sure it's not outside (no .. components)
|
|
199
|
+
if (relativePath.startsWith('..')) {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
return relativePath;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Walk directory recursively to collect files
|
|
206
|
+
*/
|
|
207
|
+
async walkDir(dir, files) {
|
|
208
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
209
|
+
for (const entry of entries) {
|
|
210
|
+
const fullPath = path.join(dir, entry.name);
|
|
211
|
+
if (entry.isDirectory()) {
|
|
212
|
+
await this.walkDir(fullPath, files);
|
|
213
|
+
}
|
|
214
|
+
else if (entry.isFile()) {
|
|
215
|
+
const cachePath = this.getCachePath(fullPath);
|
|
216
|
+
if (cachePath) {
|
|
217
|
+
files.push(cachePath);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Clean up empty directories from a path up to .libraries
|
|
224
|
+
*/
|
|
225
|
+
async cleanEmptyDirs(dir) {
|
|
226
|
+
// Don't go above .libraries
|
|
227
|
+
if (dir === this._librariesPath || !dir.startsWith(this._librariesPath)) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
const entries = await fs.readdir(dir);
|
|
232
|
+
if (entries.length === 0) {
|
|
233
|
+
await fs.rmdir(dir);
|
|
234
|
+
// Recurse to parent
|
|
235
|
+
await this.cleanEmptyDirs(path.dirname(dir));
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
// Ignore errors
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Clean all empty directories under .libraries
|
|
244
|
+
*/
|
|
245
|
+
async cleanAllEmptyDirs(dir) {
|
|
246
|
+
try {
|
|
247
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
248
|
+
for (const entry of entries) {
|
|
249
|
+
if (entry.isDirectory()) {
|
|
250
|
+
const subDir = path.join(dir, entry.name);
|
|
251
|
+
await this.cleanAllEmptyDirs(subDir);
|
|
252
|
+
// Try to remove if empty
|
|
253
|
+
try {
|
|
254
|
+
const subEntries = await fs.readdir(subDir);
|
|
255
|
+
if (subEntries.length === 0) {
|
|
256
|
+
await fs.rmdir(subDir);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
// Ignore
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
catch {
|
|
266
|
+
// Ignore errors
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
|