busy-cli 0.2.0 → 0.3.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/cli/index.js +4 -3
- package/dist/commands/package.d.ts +5 -2
- package/dist/commands/package.d.ts.map +1 -1
- package/dist/commands/package.js +31 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +50 -30
- package/dist/package/manifest.d.ts +12 -0
- package/dist/package/manifest.d.ts.map +1 -1
- package/dist/package/manifest.js +118 -0
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +12 -8
- package/dist/types/schema.d.ts +1650 -76
- package/dist/types/schema.d.ts.map +1 -1
- package/dist/types/schema.js +12 -2
- package/package.json +1 -1
- package/src/__tests__/view-config.test.ts +277 -0
- package/src/cli/index.ts +4 -3
- package/src/commands/package.ts +32 -3
- package/src/index.ts +3 -0
- package/src/loader.ts +66 -38
- package/src/package/manifest.ts +138 -0
- package/src/parser.ts +12 -8
- package/src/types/schema.ts +17 -3
package/dist/cli/index.js
CHANGED
|
@@ -310,14 +310,15 @@ const packageCmd = program
|
|
|
310
310
|
// Package add
|
|
311
311
|
packageCmd
|
|
312
312
|
.command('add')
|
|
313
|
-
.description('Add a package from URL')
|
|
314
|
-
.argument('<url>', 'URL to the BUSY document')
|
|
313
|
+
.description('Add a package from URL or local folder')
|
|
314
|
+
.argument('<url>', 'URL or local path to the BUSY document or folder')
|
|
315
315
|
.option('-d, --dir <directory>', 'Workspace directory', '.')
|
|
316
|
+
.option('-r, --recursive', 'Recursively add all files from a local folder')
|
|
316
317
|
.action(async (url, options) => {
|
|
317
318
|
try {
|
|
318
319
|
const workspaceRoot = resolve(options.dir);
|
|
319
320
|
console.log(`\nAdding package from: ${url}\n`);
|
|
320
|
-
const result = await addPackage(workspaceRoot, url);
|
|
321
|
+
const result = await addPackage(workspaceRoot, url, { recursive: options.recursive });
|
|
321
322
|
console.log(` ID: ${result.id}`);
|
|
322
323
|
console.log(` Provider: ${result.provider}`);
|
|
323
324
|
console.log(` Version: ${result.version}`);
|
|
@@ -71,12 +71,15 @@ export declare function checkWorkspace(workspaceRoot: string, options?: {
|
|
|
71
71
|
skipExternal?: boolean;
|
|
72
72
|
}): Promise<CheckResult>;
|
|
73
73
|
/**
|
|
74
|
-
* Add a package from URL
|
|
74
|
+
* Add a package from URL or local folder
|
|
75
75
|
*
|
|
76
76
|
* If the URL points to a package.busy.md manifest, fetches the entire package.
|
|
77
|
+
* If it's a local directory with --recursive (or without a manifest), copies all files.
|
|
77
78
|
* Otherwise, fetches a single file.
|
|
78
79
|
*/
|
|
79
|
-
export declare function addPackage(workspaceRoot: string, url: string
|
|
80
|
+
export declare function addPackage(workspaceRoot: string, url: string, options?: {
|
|
81
|
+
recursive?: boolean;
|
|
82
|
+
}): Promise<AddResult>;
|
|
80
83
|
/**
|
|
81
84
|
* Remove a package
|
|
82
85
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package.d.ts","sourceRoot":"","sources":["../../src/commands/package.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAmB,YAAY,EAAiC,MAAM,sBAAsB,CAAC;AAKpG,OAAO,uBAAuB,CAAC;AAC/B,OAAO,wBAAwB,CAAC;AAChC,OAAO,wBAAwB,CAAC;AAChC,OAAO,qBAAqB,CAAC;AAE7B;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAkC9E;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CA8CtH;AAED
|
|
1
|
+
{"version":3,"file":"package.d.ts","sourceRoot":"","sources":["../../src/commands/package.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAmB,YAAY,EAAiC,MAAM,sBAAsB,CAAC;AAKpG,OAAO,uBAAuB,CAAC;AAC/B,OAAO,wBAAwB,CAAC;AAChC,OAAO,wBAAwB,CAAC;AAChC,OAAO,qBAAqB,CAAC;AAE7B;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAkC9E;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CA8CtH;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAgH1H;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAwBnG;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAQ7E;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAM3G;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA4ErG"}
|
package/dist/commands/package.js
CHANGED
|
@@ -8,7 +8,7 @@ import * as path from 'node:path';
|
|
|
8
8
|
import { CacheManager, deriveCachePath } from '../cache/index.js';
|
|
9
9
|
import { PackageRegistry, deriveEntryId, deriveCategory } from '../registry/index.js';
|
|
10
10
|
import { providerRegistry } from '../providers/index.js';
|
|
11
|
-
import { isPackageManifestUrl, fetchPackageFromManifest } from '../package/manifest.js';
|
|
11
|
+
import { isPackageManifestUrl, fetchPackageFromManifest, fetchPackageFromLocalFolder } from '../package/manifest.js';
|
|
12
12
|
// Ensure providers are registered
|
|
13
13
|
import '../providers/local.js';
|
|
14
14
|
import '../providers/github.js';
|
|
@@ -94,12 +94,40 @@ export async function checkWorkspace(workspaceRoot, options) {
|
|
|
94
94
|
};
|
|
95
95
|
}
|
|
96
96
|
/**
|
|
97
|
-
* Add a package from URL
|
|
97
|
+
* Add a package from URL or local folder
|
|
98
98
|
*
|
|
99
99
|
* If the URL points to a package.busy.md manifest, fetches the entire package.
|
|
100
|
+
* If it's a local directory with --recursive (or without a manifest), copies all files.
|
|
100
101
|
* Otherwise, fetches a single file.
|
|
101
102
|
*/
|
|
102
|
-
export async function addPackage(workspaceRoot, url) {
|
|
103
|
+
export async function addPackage(workspaceRoot, url, options) {
|
|
104
|
+
// Check if this is a local directory that should use folder-based discovery
|
|
105
|
+
if (url.startsWith('./') || url.startsWith('../') || url.startsWith('/') || (!url.includes('://') && !url.startsWith('http'))) {
|
|
106
|
+
const resolvedPath = path.isAbsolute(url) ? url : path.resolve(process.cwd(), url);
|
|
107
|
+
try {
|
|
108
|
+
const stat = await fs.stat(resolvedPath);
|
|
109
|
+
if (stat.isDirectory()) {
|
|
110
|
+
const manifestExists = await fs.stat(path.join(resolvedPath, 'package.busy.md'))
|
|
111
|
+
.then(() => true).catch(() => false);
|
|
112
|
+
if (options?.recursive || !manifestExists) {
|
|
113
|
+
// Use folder-based discovery: --recursive flag or no manifest available
|
|
114
|
+
const result = await fetchPackageFromLocalFolder(workspaceRoot, resolvedPath);
|
|
115
|
+
return {
|
|
116
|
+
id: result.name,
|
|
117
|
+
source: resolvedPath,
|
|
118
|
+
provider: 'local',
|
|
119
|
+
cached: result.cached,
|
|
120
|
+
version: result.version,
|
|
121
|
+
integrity: result.integrity,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
// Has manifest and not --recursive: fall through to manifest-based flow
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// Not a directory or doesn't exist - fall through to normal handling
|
|
129
|
+
}
|
|
130
|
+
}
|
|
103
131
|
// Check if this is a package manifest URL
|
|
104
132
|
if (isPackageManifestUrl(url)) {
|
|
105
133
|
// Use manifest-based package installation
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { loadRepo } from './loader.js';
|
|
2
2
|
export { buildContext, writeContext, get, parentsOf, childrenOf, getConceptContext } from './builders/context.js';
|
|
3
3
|
export { mergeRepos, extendRepo, loadRepoFromJSON } from './merge.js';
|
|
4
|
-
export type { DocId, Slug, Section, ConceptBase, BusyDocument, LocalDef, Operation, ImportDef, EdgeRole, Edge, File, Repo, ContextPayload, FrontMatter, } from './types/schema.js';
|
|
4
|
+
export type { DocId, Slug, Section, ConceptBase, BusyDocument, Playbook, View, Config, LocalDef, Operation, ImportDef, EdgeRole, Edge, File, Repo, ContextPayload, FrontMatter, } from './types/schema.js';
|
|
5
5
|
export type { BuildOpts, ConceptContext } from './builders/context.js';
|
|
6
6
|
export { DocIdSchema, SlugSchema, SectionIdSchema, ConceptIdSchema, SectionSchema, ConceptBaseSchema, LocalDefSchema, SetupSchema, OperationSchema, ImportDefSchema, BusyDocumentSchema, PlaybookSchema, EdgeRoleSchema, EdgeSchema, FileSchema, RepoSchema, ContextPayloadSchema, FrontMatterSchema, } from './types/schema.js';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,EAAE,SAAS,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAClH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGtE,YAAY,EACV,KAAK,EACL,IAAI,EACJ,OAAO,EACP,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,SAAS,EACT,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,cAAc,EACd,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvE,OAAO,EACL,WAAW,EACX,UAAU,EACV,eAAe,EACf,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,UAAU,EACV,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,EAAE,SAAS,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAClH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGtE,YAAY,EACV,KAAK,EACL,IAAI,EACJ,OAAO,EACP,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,SAAS,EACT,SAAS,EACT,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,cAAc,EACd,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGvE,OAAO,EACL,WAAW,EACX,UAAU,EACV,eAAe,EACf,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,UAAU,EACV,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC"}
|
package/dist/loader.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,IAAI,
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,IAAI,EAYL,MAAM,mBAAmB,CAAC;AAgB3B;;GAEG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqU7D"}
|
package/dist/loader.js
CHANGED
|
@@ -155,44 +155,52 @@ export async function loadRepo(globs) {
|
|
|
155
155
|
}
|
|
156
156
|
// Build final document structures with inline arrays
|
|
157
157
|
for (const [docId, parts] of docParts) {
|
|
158
|
-
const
|
|
158
|
+
const typesLower = parts.types.map((t) => t.toLowerCase());
|
|
159
|
+
const isPlaybook = typesLower.includes('playbook');
|
|
160
|
+
const isView = typesLower.includes('view');
|
|
161
|
+
const isConfig = typesLower.includes('config');
|
|
162
|
+
// Base fields shared across all document kinds
|
|
163
|
+
const baseFields = {
|
|
164
|
+
id: parts.docId,
|
|
165
|
+
docId: parts.docId,
|
|
166
|
+
slug: parts.docId.toLowerCase(),
|
|
167
|
+
name: parts.frontmatter.Name,
|
|
168
|
+
content: parts.content,
|
|
169
|
+
types: parts.types,
|
|
170
|
+
extends: parts.extends,
|
|
171
|
+
sectionRef: `${parts.docId}#`, // Root reference
|
|
172
|
+
imports: parts.imports,
|
|
173
|
+
localdefs: parts.localdefs,
|
|
174
|
+
setup: parts.setup,
|
|
175
|
+
operations: parts.operations,
|
|
176
|
+
};
|
|
159
177
|
if (isPlaybook) {
|
|
160
178
|
// Extract sequence from ExecutePlaybook operation
|
|
161
179
|
const sequence = extractPlaybookSequence(parts.sections);
|
|
180
|
+
const doc = { ...baseFields, kind: 'playbook', sequence };
|
|
181
|
+
docs.push(doc);
|
|
182
|
+
}
|
|
183
|
+
else if (isView) {
|
|
184
|
+
// Extract template section with full content (including children)
|
|
185
|
+
const displaySection = findSection(parts.sections, 'display');
|
|
186
|
+
let displayContent;
|
|
187
|
+
if (displaySection) {
|
|
188
|
+
// Reconstruct full template from section + children content
|
|
189
|
+
displayContent = getSectionFullContent(displaySection);
|
|
190
|
+
}
|
|
162
191
|
const doc = {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
slug: parts.docId.toLowerCase(),
|
|
167
|
-
name: parts.frontmatter.Name,
|
|
168
|
-
content: parts.content,
|
|
169
|
-
types: parts.types,
|
|
170
|
-
extends: parts.extends,
|
|
171
|
-
sectionRef: `${parts.docId}#`, // Root reference
|
|
172
|
-
imports: parts.imports,
|
|
173
|
-
localdefs: parts.localdefs,
|
|
174
|
-
setup: parts.setup,
|
|
175
|
-
operations: parts.operations,
|
|
176
|
-
sequence,
|
|
192
|
+
...baseFields,
|
|
193
|
+
kind: 'view',
|
|
194
|
+
display: displayContent,
|
|
177
195
|
};
|
|
178
196
|
docs.push(doc);
|
|
179
197
|
}
|
|
198
|
+
else if (isConfig) {
|
|
199
|
+
const doc = { ...baseFields, kind: 'config' };
|
|
200
|
+
docs.push(doc);
|
|
201
|
+
}
|
|
180
202
|
else {
|
|
181
|
-
const doc = {
|
|
182
|
-
kind: 'document',
|
|
183
|
-
id: parts.docId,
|
|
184
|
-
docId: parts.docId,
|
|
185
|
-
slug: parts.docId.toLowerCase(),
|
|
186
|
-
name: parts.frontmatter.Name,
|
|
187
|
-
content: parts.content,
|
|
188
|
-
types: parts.types,
|
|
189
|
-
extends: parts.extends,
|
|
190
|
-
sectionRef: `${parts.docId}#`, // Root reference
|
|
191
|
-
imports: parts.imports,
|
|
192
|
-
localdefs: parts.localdefs,
|
|
193
|
-
setup: parts.setup,
|
|
194
|
-
operations: parts.operations,
|
|
195
|
-
};
|
|
203
|
+
const doc = { ...baseFields, kind: 'document' };
|
|
196
204
|
docs.push(doc);
|
|
197
205
|
}
|
|
198
206
|
}
|
|
@@ -332,6 +340,18 @@ function resolveSymbol(nameOrLabel, currentDocId, localdefs, docs, symbols) {
|
|
|
332
340
|
}
|
|
333
341
|
return undefined;
|
|
334
342
|
}
|
|
343
|
+
/**
|
|
344
|
+
* Get the full content of a section including all nested children.
|
|
345
|
+
* Reconstructs the original markdown by walking the section tree.
|
|
346
|
+
*/
|
|
347
|
+
function getSectionFullContent(section) {
|
|
348
|
+
let content = section.content;
|
|
349
|
+
for (const child of section.children) {
|
|
350
|
+
const prefix = '#'.repeat(child.depth);
|
|
351
|
+
content += `\n${prefix} ${child.title}\n${getSectionFullContent(child)}`;
|
|
352
|
+
}
|
|
353
|
+
return content.trim();
|
|
354
|
+
}
|
|
335
355
|
/**
|
|
336
356
|
* Extract sequence of operations from a playbook's ExecutePlaybook operation
|
|
337
357
|
* Looks for sections with "Step" in the title and extracts Target metadata
|
|
@@ -56,4 +56,16 @@ export declare function parsePackageManifest(content: string): PackageManifest;
|
|
|
56
56
|
* Fetch a package from its manifest URL or local path
|
|
57
57
|
*/
|
|
58
58
|
export declare function fetchPackageFromManifest(workspaceRoot: string, manifestUrl: string): Promise<FetchPackageResult>;
|
|
59
|
+
/**
|
|
60
|
+
* Recursively discover all files in a directory.
|
|
61
|
+
* Skips hidden directories (e.g. .git, .libraries) and node_modules.
|
|
62
|
+
*/
|
|
63
|
+
export declare function discoverFiles(dirPath: string): Promise<string[]>;
|
|
64
|
+
/**
|
|
65
|
+
* Fetch a package from a local folder, copying all files.
|
|
66
|
+
*
|
|
67
|
+
* If a package.busy.md exists, its metadata (name, version, description) is used.
|
|
68
|
+
* Otherwise, metadata is derived from the folder name.
|
|
69
|
+
*/
|
|
70
|
+
export declare function fetchPackageFromLocalFolder(workspaceRoot: string, folderPath: string): Promise<FetchPackageResult>;
|
|
59
71
|
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/package/manifest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,uBAAuB,CAAC;AAC/B,OAAO,wBAAwB,CAAC;AAChC,OAAO,wBAAwB,CAAC;AAChC,OAAO,qBAAqB,CAAC;AAE7B;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,eAAe,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAazD;AAyBD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAiHrE;AAkBD;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CA4G7B"}
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/package/manifest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,uBAAuB,CAAC;AAC/B,OAAO,wBAAwB,CAAC;AAChC,OAAO,wBAAwB,CAAC;AAChC,OAAO,qBAAqB,CAAC;AAE7B;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,eAAe,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAazD;AAyBD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAiHrE;AAkBD;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CA4G7B;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAoBtE;AAED;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAC/C,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,kBAAkB,CAAC,CAqG7B"}
|
package/dist/package/manifest.js
CHANGED
|
@@ -262,4 +262,122 @@ export async function fetchPackageFromManifest(workspaceRoot, manifestUrl) {
|
|
|
262
262
|
integrity,
|
|
263
263
|
};
|
|
264
264
|
}
|
|
265
|
+
/**
|
|
266
|
+
* Recursively discover all files in a directory.
|
|
267
|
+
* Skips hidden directories (e.g. .git, .libraries) and node_modules.
|
|
268
|
+
*/
|
|
269
|
+
export async function discoverFiles(dirPath) {
|
|
270
|
+
const results = [];
|
|
271
|
+
async function walk(dir) {
|
|
272
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
273
|
+
for (const entry of entries) {
|
|
274
|
+
if (entry.name.startsWith('.') || entry.name === 'node_modules') {
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
const fullPath = path.join(dir, entry.name);
|
|
278
|
+
if (entry.isDirectory()) {
|
|
279
|
+
await walk(fullPath);
|
|
280
|
+
}
|
|
281
|
+
else if (entry.isFile()) {
|
|
282
|
+
results.push(fullPath);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
await walk(dirPath);
|
|
287
|
+
return results;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Fetch a package from a local folder, copying all files.
|
|
291
|
+
*
|
|
292
|
+
* If a package.busy.md exists, its metadata (name, version, description) is used.
|
|
293
|
+
* Otherwise, metadata is derived from the folder name.
|
|
294
|
+
*/
|
|
295
|
+
export async function fetchPackageFromLocalFolder(workspaceRoot, folderPath) {
|
|
296
|
+
const absolutePath = path.isAbsolute(folderPath)
|
|
297
|
+
? folderPath
|
|
298
|
+
: path.resolve(process.cwd(), folderPath);
|
|
299
|
+
// Verify it's a directory
|
|
300
|
+
const stat = await fs.stat(absolutePath);
|
|
301
|
+
if (!stat.isDirectory()) {
|
|
302
|
+
throw new Error(`Not a directory: ${absolutePath}`);
|
|
303
|
+
}
|
|
304
|
+
// Try to read manifest for metadata
|
|
305
|
+
const manifestPath = path.join(absolutePath, 'package.busy.md');
|
|
306
|
+
let manifest = null;
|
|
307
|
+
let manifestContent = null;
|
|
308
|
+
try {
|
|
309
|
+
manifestContent = await fs.readFile(manifestPath, 'utf-8');
|
|
310
|
+
manifest = parsePackageManifest(manifestContent);
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
// No manifest - that's fine
|
|
314
|
+
}
|
|
315
|
+
const packageName = manifest?.name || path.basename(absolutePath);
|
|
316
|
+
// Discover all files in the folder
|
|
317
|
+
const discoveredFiles = await discoverFiles(absolutePath);
|
|
318
|
+
// Filter out package.busy.md itself (handled separately)
|
|
319
|
+
const filesToCopy = discoveredFiles
|
|
320
|
+
.filter(f => path.basename(f) !== 'package.busy.md')
|
|
321
|
+
.map(f => ({
|
|
322
|
+
relativePath: path.relative(absolutePath, f),
|
|
323
|
+
absolutePath: f,
|
|
324
|
+
}));
|
|
325
|
+
// Initialize cache
|
|
326
|
+
const cache = new CacheManager(workspaceRoot);
|
|
327
|
+
await cache.init();
|
|
328
|
+
// Copy files
|
|
329
|
+
let combinedContent = '';
|
|
330
|
+
const documents = [];
|
|
331
|
+
for (const file of filesToCopy) {
|
|
332
|
+
try {
|
|
333
|
+
const content = await fs.readFile(file.absolutePath, 'utf-8');
|
|
334
|
+
combinedContent += content;
|
|
335
|
+
const cachePath = path.join(packageName, file.relativePath);
|
|
336
|
+
await cache.save(cachePath, content);
|
|
337
|
+
documents.push({
|
|
338
|
+
name: path.basename(file.relativePath, path.extname(file.relativePath)),
|
|
339
|
+
relativePath: './' + file.relativePath,
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
console.warn(`Warning: Failed to read ${file.absolutePath}: ${error}`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
// Save manifest if it exists
|
|
347
|
+
if (manifestContent) {
|
|
348
|
+
await cache.save(path.join(packageName, 'package.busy.md'), manifestContent);
|
|
349
|
+
}
|
|
350
|
+
// Calculate integrity
|
|
351
|
+
const integrity = calculateIntegrity(combinedContent);
|
|
352
|
+
// Add to registry
|
|
353
|
+
const registry = new PackageRegistry(workspaceRoot);
|
|
354
|
+
try {
|
|
355
|
+
await registry.load();
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
await registry.init();
|
|
359
|
+
await registry.load();
|
|
360
|
+
}
|
|
361
|
+
const entry = {
|
|
362
|
+
id: packageName,
|
|
363
|
+
description: manifest?.description || '',
|
|
364
|
+
source: absolutePath,
|
|
365
|
+
provider: 'local',
|
|
366
|
+
cached: `.libraries/${packageName}`,
|
|
367
|
+
version: manifest?.version || 'latest',
|
|
368
|
+
fetched: new Date().toISOString(),
|
|
369
|
+
integrity,
|
|
370
|
+
category: 'Packages',
|
|
371
|
+
};
|
|
372
|
+
registry.addPackage(entry);
|
|
373
|
+
await registry.save();
|
|
374
|
+
return {
|
|
375
|
+
name: packageName,
|
|
376
|
+
version: manifest?.version || 'latest',
|
|
377
|
+
description: manifest?.description || '',
|
|
378
|
+
documents,
|
|
379
|
+
cached: `.libraries/${packageName}`,
|
|
380
|
+
integrity,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
265
383
|
//# sourceMappingURL=manifest.js.map
|
package/dist/parser.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EACL,eAAe,IAAI,YAAY,EAAG,8CAA8C;AAChF,YAAY,EAGb,MAAM,mBAAmB,CAAC;AA6G3B;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,YAAY,CAiE1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,YAAY,GAAG,YAAY,EACrC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,GAAG,CAAC,MAAM,CAAa,GAC/B,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EACL,eAAe,IAAI,YAAY,EAAG,8CAA8C;AAChF,YAAY,EAGb,MAAM,mBAAmB,CAAC;AA6G3B;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,YAAY,CAiE1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,YAAY,GAAG,YAAY,EACrC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,GAAG,CAAC,MAAM,CAAa,GAC/B,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAAC,CA2D7C"}
|
package/dist/parser.js
CHANGED
|
@@ -170,13 +170,15 @@ export function resolveImports(document, basePath, visited = new Set()) {
|
|
|
170
170
|
for (const imp of document.imports) {
|
|
171
171
|
// Resolve the import path
|
|
172
172
|
const importPath = resolve(dirname(basePath), imp.path);
|
|
173
|
-
// Check for circular imports
|
|
173
|
+
// Check for circular imports — warn and skip instead of crashing
|
|
174
174
|
if (visited.has(importPath)) {
|
|
175
|
-
|
|
175
|
+
console.warn(`⚠ Circular import skipped: ${imp.path} (from ${basePath})`);
|
|
176
|
+
continue;
|
|
176
177
|
}
|
|
177
|
-
// Check if file exists
|
|
178
|
+
// Check if file exists — warn and skip instead of crashing
|
|
178
179
|
if (!existsSync(importPath)) {
|
|
179
|
-
|
|
180
|
+
console.warn(`⚠ Import not found: ${imp.path} (resolved to ${importPath})`);
|
|
181
|
+
continue;
|
|
180
182
|
}
|
|
181
183
|
// Mark as visited
|
|
182
184
|
visited.add(importPath);
|
|
@@ -192,7 +194,7 @@ export function resolveImports(document, basePath, visited = new Set()) {
|
|
|
192
194
|
const hasDefinition = importedDoc.definitions.some((def) => def.name.toLowerCase() === imp.anchor.toLowerCase() ||
|
|
193
195
|
slugify(def.name) === imp.anchor.toLowerCase());
|
|
194
196
|
if (!hasOperation && !hasDefinition) {
|
|
195
|
-
|
|
197
|
+
console.warn(`⚠ Anchor '${imp.anchor}' not found in ${imp.path}`);
|
|
196
198
|
}
|
|
197
199
|
}
|
|
198
200
|
// Store resolved document
|
|
@@ -201,10 +203,12 @@ export function resolveImports(document, basePath, visited = new Set()) {
|
|
|
201
203
|
const nestedResolved = resolveImports(importedDoc, importPath, visited);
|
|
202
204
|
Object.assign(resolved, nestedResolved);
|
|
203
205
|
}
|
|
204
|
-
|
|
205
|
-
//
|
|
206
|
-
|
|
206
|
+
catch (e) {
|
|
207
|
+
// Don't crash on nested resolution failures
|
|
208
|
+
console.warn(`⚠ Failed to resolve nested imports in ${imp.path}: ${e}`);
|
|
207
209
|
}
|
|
210
|
+
// NOTE: we intentionally keep importPath in `visited` — once resolved,
|
|
211
|
+
// don't re-resolve in other branches (prevents exponential recursion)
|
|
208
212
|
}
|
|
209
213
|
return resolved;
|
|
210
214
|
}
|