@synergenius/flow-weaver 0.30.0 → 0.30.1
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 +18 -6
- package/dist/cli/commands/describe.js +1 -1
- package/dist/cli/commands/diagram.js +3 -0
- package/dist/cli/commands/diff.js +2 -2
- package/dist/cli/commands/run.js +2 -2
- package/dist/cli/commands/serve.js +11 -0
- package/dist/cli/commands/validate.js +1 -1
- package/dist/cli/flow-weaver.mjs +106 -224
- package/dist/cli/index.js +0 -11
- package/dist/doc-metadata/extractors/cli-commands.js +0 -10
- package/dist/generated-version.d.ts +1 -1
- package/dist/generated-version.js +1 -1
- package/docs/reference/cli-reference.md +1 -25
- package/package.json +1 -1
- package/dist/cli/commands/changelog.d.ts +0 -13
- package/dist/cli/commands/changelog.js +0 -135
package/README.md
CHANGED
|
@@ -18,15 +18,27 @@ Flow Weaver is a TypeScript workflow compiler. Define workflows with JSDoc annot
|
|
|
18
18
|
|
|
19
19
|
Build AI agent workflows, data pipelines, or automation scripts through natural language using MCP tools in Claude Code, Cursor, Windsurf, VS Code, JetBrains, Codex, or any MCP-compatible editor. Or write them by hand with annotations the same way you write JSDoc today.
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## About me & my vision
|
|
22
|
+
|
|
23
|
+
Hey, I am [Ricardo Morais](https://linkedin.com/in/moraispgsi), the project's founder and owner.
|
|
24
|
+
|
|
25
|
+
I have always wondered why Visual Programming never took off. After understanding why I tried to address most of the concerns from the development community:
|
|
26
|
+
- No lock-in: code is compiled and yours, not dependent on this library. You can remove the annotation after compiling and the file is standalone.
|
|
27
|
+
- The code is the source of truth, visual part runs on top, this allows you to create your workflows visually in the Studio, at the end of the day it is just plain Typescript code that you or any LLM can understand and iterate.
|
|
28
|
+
- It being just code opens a lot of doors for you, like using Git for version control, doing all sort of stuff you already do with code like testing, linting, automating, everything.
|
|
29
|
+
- In the era of LLMs and agents, being able to have that control is crucial, it is not a black box, you can see everything and so can your assistant.
|
|
22
30
|
|
|
23
|
-
|
|
31
|
+
As of now this is a solo project and I am building it in the open. There is a lot to do and rough edges to smooth out. If you run into issues or have questions, the [Discord](https://discord.gg/6Byh3ur2bk) is the best place to reach out. Every issue and question gets a response. I genuinely want to hear from you.
|
|
32
|
+
|
|
33
|
+
If this resonates with what you have been looking for, give it a try and let me know how it goes. Stars, feedback, and honest criticism all help equally.
|
|
34
|
+
|
|
35
|
+
## Project Status
|
|
24
36
|
|
|
25
|
-
|
|
37
|
+
Flow Weaver is in **beta**. The compiler, validator, CLI, and MCP tools are stable and thoroughly tested. The test suite covers thousands of cases across parsing, compilation, validation, diffing, and deployment. CI runs on every commit.
|
|
26
38
|
|
|
27
39
|
**Flow Weaver Studio**, the browser-based visual IDE, is the next major milestone and is being actively built. Core editing (canvas, terminal, diagnostics) is live today. The visual debugger, AI chat assistant, version history, and deployment dashboard are in progress. You can follow development on Discord or in the [GitHub releases](https://github.com/synergenius-fw/flow-weaver/releases).
|
|
28
40
|
|
|
29
|
-
Breaking changes may occur between minor versions during
|
|
41
|
+
Breaking changes may still occur between minor versions during beta. Pin your version in `package.json` if stability matters for your project.
|
|
30
42
|
|
|
31
43
|
## Capabilities
|
|
32
44
|
|
|
@@ -224,11 +236,11 @@ export async function supportAgent(
|
|
|
224
236
|
|
|
225
237
|
Run `fw --help` or `fw <command> --help` for full options.
|
|
226
238
|
|
|
227
|
-
## Flow Weaver Studio (
|
|
239
|
+
## Flow Weaver Studio (Beta)
|
|
228
240
|
|
|
229
241
|
A browser-based visual IDE for building workflows. Canvas editor, integrated terminal, real-time diagnostics, and the full CLI available in the cloud.
|
|
230
242
|
|
|
231
|
-
Studio is in
|
|
243
|
+
Studio is in beta. Core editing is live. The visual debugger, AI chat assistant, version history, and deployment dashboard are being actively developed and will ship incrementally. The cloud platform is not yet production-ready, and paid plans are not available yet. Use it to explore and experiment, but expect rough edges.
|
|
232
244
|
|
|
233
245
|
[Open Studio](https://flowweaver.ai/studio) · [Learn more](https://flowweaver.ai/features)
|
|
234
246
|
|
|
@@ -349,7 +349,7 @@ export async function describeCommand(input, options = {}) {
|
|
|
349
349
|
}
|
|
350
350
|
try {
|
|
351
351
|
// Parse the workflow
|
|
352
|
-
const parseResult = await parseWorkflow(filePath, { workflowName });
|
|
352
|
+
const parseResult = await parseWorkflow(filePath, { workflowName, projectDir: path.dirname(filePath) });
|
|
353
353
|
if (parseResult.errors.length > 0) {
|
|
354
354
|
throw new Error(`Parse errors:\n${parseResult.errors.map((err) => ` ${err}`).join('\n')}`);
|
|
355
355
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import * as fs from 'fs';
|
|
6
6
|
import * as path from 'path';
|
|
7
7
|
import { fileToSVG, fileToHTML, fileToASCII } from '../../diagram/index.js';
|
|
8
|
+
import { parser } from '../../parser.js';
|
|
8
9
|
import { logger } from '../utils/logger.js';
|
|
9
10
|
import { safeWriteFile } from '../utils/safe-write.js';
|
|
10
11
|
const ASCII_FORMATS = new Set(['ascii', 'ascii-compact', 'text']);
|
|
@@ -14,6 +15,8 @@ export async function diagramCommand(input, options = {}) {
|
|
|
14
15
|
if (!fs.existsSync(filePath)) {
|
|
15
16
|
throw new Error(`File not found: ${filePath}`);
|
|
16
17
|
}
|
|
18
|
+
// Load marketplace pack tag handlers before parsing
|
|
19
|
+
await parser.loadPackHandlers(path.dirname(filePath));
|
|
17
20
|
let result;
|
|
18
21
|
if (ASCII_FORMATS.has(format)) {
|
|
19
22
|
result = fileToASCII(filePath, { ...diagramOptions, format });
|
|
@@ -21,8 +21,8 @@ export async function diffCommand(file1, file2, options = {}) {
|
|
|
21
21
|
try {
|
|
22
22
|
// Parse both workflows
|
|
23
23
|
const [result1, result2] = await Promise.all([
|
|
24
|
-
parseWorkflow(filePath1, { workflowName }),
|
|
25
|
-
parseWorkflow(filePath2, { workflowName }),
|
|
24
|
+
parseWorkflow(filePath1, { workflowName, projectDir: path.dirname(filePath1) }),
|
|
25
|
+
parseWorkflow(filePath2, { workflowName, projectDir: path.dirname(filePath2) }),
|
|
26
26
|
]);
|
|
27
27
|
if (result1.errors.length > 0) {
|
|
28
28
|
throw new Error(`Parse errors in ${file1}:\n${result1.errors.map((err) => ` ${err}`).join('\n')}`);
|
package/dist/cli/commands/run.js
CHANGED
|
@@ -184,7 +184,7 @@ async function runCommandInner(input, options) {
|
|
|
184
184
|
let executionOrder = resumeExecutionOrder;
|
|
185
185
|
if (!executionOrder) {
|
|
186
186
|
const source = fs.readFileSync(filePath, 'utf8');
|
|
187
|
-
const parsed = await parseWorkflow(source, { workflowName: options.workflow });
|
|
187
|
+
const parsed = await parseWorkflow(source, { workflowName: options.workflow, projectDir: path.dirname(filePath) });
|
|
188
188
|
if (parsed.errors.length === 0) {
|
|
189
189
|
executionOrder = getTopologicalOrder(parsed.ast);
|
|
190
190
|
}
|
|
@@ -427,7 +427,7 @@ export async function validateMockConfig(mocks, filePath, workflowName) {
|
|
|
427
427
|
}
|
|
428
428
|
// Quick-parse the workflow to check which built-in node types are used
|
|
429
429
|
try {
|
|
430
|
-
const result = await parseWorkflow(filePath, { workflowName });
|
|
430
|
+
const result = await parseWorkflow(filePath, { workflowName, projectDir: path.dirname(filePath) });
|
|
431
431
|
if (result.errors.length > 0 || !result.ast?.instances)
|
|
432
432
|
return;
|
|
433
433
|
const usedNodeTypes = new Set(result.ast.instances.map((i) => i.nodeType));
|
|
@@ -30,6 +30,17 @@ import { logger } from '../utils/logger.js';
|
|
|
30
30
|
* ```
|
|
31
31
|
*/
|
|
32
32
|
export async function serveCommand(dir, options) {
|
|
33
|
+
// Check fastify is installed before proceeding
|
|
34
|
+
try {
|
|
35
|
+
await import('fastify');
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
logger.error('The serve command requires fastify. Install it with:');
|
|
39
|
+
logger.newline();
|
|
40
|
+
logger.log(' npm install fastify');
|
|
41
|
+
logger.newline();
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
33
44
|
const workflowDir = path.resolve(dir || '.');
|
|
34
45
|
// Validate directory exists
|
|
35
46
|
if (!fs.existsSync(workflowDir)) {
|
|
@@ -62,7 +62,7 @@ export async function validateCommand(input, options = {}) {
|
|
|
62
62
|
}
|
|
63
63
|
try {
|
|
64
64
|
// Parse the workflow
|
|
65
|
-
const parseResult = await parseWorkflow(file, { workflowName, projectDir:
|
|
65
|
+
const parseResult = await parseWorkflow(file, { workflowName, projectDir: path.dirname(path.resolve(file)) });
|
|
66
66
|
if (parseResult.warnings.length > 0) {
|
|
67
67
|
if (!json && !quiet) {
|
|
68
68
|
logger.warn(`Parse warnings in ${fileName}:`);
|
package/dist/cli/flow-weaver.mjs
CHANGED
|
@@ -5987,7 +5987,7 @@ var VERSION;
|
|
|
5987
5987
|
var init_generated_version = __esm({
|
|
5988
5988
|
"src/generated-version.ts"() {
|
|
5989
5989
|
"use strict";
|
|
5990
|
-
VERSION = "0.30.
|
|
5990
|
+
VERSION = "0.30.1";
|
|
5991
5991
|
}
|
|
5992
5992
|
});
|
|
5993
5993
|
|
|
@@ -9844,14 +9844,14 @@ var require_read_wasm = __commonJS({
|
|
|
9844
9844
|
var fs49 = __require("fs");
|
|
9845
9845
|
var path54 = __require("path");
|
|
9846
9846
|
module.exports = function readWasm() {
|
|
9847
|
-
return new Promise((
|
|
9847
|
+
return new Promise((resolve39, reject) => {
|
|
9848
9848
|
const wasmPath = path54.join(__dirname, "mappings.wasm");
|
|
9849
9849
|
fs49.readFile(wasmPath, null, (error2, data) => {
|
|
9850
9850
|
if (error2) {
|
|
9851
9851
|
reject(error2);
|
|
9852
9852
|
return;
|
|
9853
9853
|
}
|
|
9854
|
-
|
|
9854
|
+
resolve39(data.buffer);
|
|
9855
9855
|
});
|
|
9856
9856
|
});
|
|
9857
9857
|
};
|
|
@@ -12059,7 +12059,7 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
12059
12059
|
let latestResultPromise;
|
|
12060
12060
|
let provideLatestResult;
|
|
12061
12061
|
if (isContext)
|
|
12062
|
-
requestCallbacks["on-end"] = (id, request2) => new Promise((
|
|
12062
|
+
requestCallbacks["on-end"] = (id, request2) => new Promise((resolve39) => {
|
|
12063
12063
|
buildResponseToResult(request2, (err, result, onEndErrors, onEndWarnings) => {
|
|
12064
12064
|
const response = {
|
|
12065
12065
|
errors: onEndErrors,
|
|
@@ -12069,7 +12069,7 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
12069
12069
|
latestResultPromise = void 0;
|
|
12070
12070
|
provideLatestResult = void 0;
|
|
12071
12071
|
sendResponse(id, response);
|
|
12072
|
-
|
|
12072
|
+
resolve39();
|
|
12073
12073
|
});
|
|
12074
12074
|
});
|
|
12075
12075
|
sendRequest(refs, request, (error2, response) => {
|
|
@@ -12086,10 +12086,10 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
12086
12086
|
let didDispose = false;
|
|
12087
12087
|
const result = {
|
|
12088
12088
|
rebuild: () => {
|
|
12089
|
-
if (!latestResultPromise) latestResultPromise = new Promise((
|
|
12089
|
+
if (!latestResultPromise) latestResultPromise = new Promise((resolve39, reject) => {
|
|
12090
12090
|
let settlePromise;
|
|
12091
12091
|
provideLatestResult = (err, result2) => {
|
|
12092
|
-
if (!settlePromise) settlePromise = () => err ? reject(err) :
|
|
12092
|
+
if (!settlePromise) settlePromise = () => err ? reject(err) : resolve39(result2);
|
|
12093
12093
|
};
|
|
12094
12094
|
const triggerAnotherBuild = () => {
|
|
12095
12095
|
const request2 = {
|
|
@@ -12110,7 +12110,7 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
12110
12110
|
});
|
|
12111
12111
|
return latestResultPromise;
|
|
12112
12112
|
},
|
|
12113
|
-
watch: (options2 = {}) => new Promise((
|
|
12113
|
+
watch: (options2 = {}) => new Promise((resolve39, reject) => {
|
|
12114
12114
|
if (!streamIn.hasFS) throw new Error(`Cannot use the "watch" API in this environment`);
|
|
12115
12115
|
const keys = {};
|
|
12116
12116
|
const delay = getFlag(options2, keys, "delay", mustBeInteger);
|
|
@@ -12122,10 +12122,10 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
12122
12122
|
if (delay) request2.delay = delay;
|
|
12123
12123
|
sendRequest(refs, request2, (error22) => {
|
|
12124
12124
|
if (error22) reject(new Error(error22));
|
|
12125
|
-
else
|
|
12125
|
+
else resolve39(void 0);
|
|
12126
12126
|
});
|
|
12127
12127
|
}),
|
|
12128
|
-
serve: (options2 = {}) => new Promise((
|
|
12128
|
+
serve: (options2 = {}) => new Promise((resolve39, reject) => {
|
|
12129
12129
|
if (!streamIn.hasFS) throw new Error(`Cannot use the "serve" API in this environment`);
|
|
12130
12130
|
const keys = {};
|
|
12131
12131
|
const port = getFlag(options2, keys, "port", mustBeValidPortNumber);
|
|
@@ -12163,28 +12163,28 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
12163
12163
|
sendResponse(id, {});
|
|
12164
12164
|
};
|
|
12165
12165
|
}
|
|
12166
|
-
|
|
12166
|
+
resolve39(response2);
|
|
12167
12167
|
});
|
|
12168
12168
|
}),
|
|
12169
|
-
cancel: () => new Promise((
|
|
12170
|
-
if (didDispose) return
|
|
12169
|
+
cancel: () => new Promise((resolve39) => {
|
|
12170
|
+
if (didDispose) return resolve39();
|
|
12171
12171
|
const request2 = {
|
|
12172
12172
|
command: "cancel",
|
|
12173
12173
|
key: buildKey
|
|
12174
12174
|
};
|
|
12175
12175
|
sendRequest(refs, request2, () => {
|
|
12176
|
-
|
|
12176
|
+
resolve39();
|
|
12177
12177
|
});
|
|
12178
12178
|
}),
|
|
12179
|
-
dispose: () => new Promise((
|
|
12180
|
-
if (didDispose) return
|
|
12179
|
+
dispose: () => new Promise((resolve39) => {
|
|
12180
|
+
if (didDispose) return resolve39();
|
|
12181
12181
|
didDispose = true;
|
|
12182
12182
|
const request2 = {
|
|
12183
12183
|
command: "dispose",
|
|
12184
12184
|
key: buildKey
|
|
12185
12185
|
};
|
|
12186
12186
|
sendRequest(refs, request2, () => {
|
|
12187
|
-
|
|
12187
|
+
resolve39();
|
|
12188
12188
|
scheduleOnDisposeCallbacks();
|
|
12189
12189
|
refs.unref();
|
|
12190
12190
|
});
|
|
@@ -12223,7 +12223,7 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
12223
12223
|
onLoad: []
|
|
12224
12224
|
};
|
|
12225
12225
|
i++;
|
|
12226
|
-
let
|
|
12226
|
+
let resolve39 = (path310, options = {}) => {
|
|
12227
12227
|
if (!isSetupDone) throw new Error('Cannot call "resolve" before plugin setup has completed');
|
|
12228
12228
|
if (typeof path310 !== "string") throw new Error(`The path to resolve must be a string`);
|
|
12229
12229
|
let keys2 = /* @__PURE__ */ Object.create(null);
|
|
@@ -12267,7 +12267,7 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
12267
12267
|
};
|
|
12268
12268
|
let promise = setup({
|
|
12269
12269
|
initialOptions,
|
|
12270
|
-
resolve:
|
|
12270
|
+
resolve: resolve39,
|
|
12271
12271
|
onStart(callback) {
|
|
12272
12272
|
let registeredText = `This error came from the "onStart" callback registered here:`;
|
|
12273
12273
|
let registeredNote = extractCallerV8(new Error(registeredText), streamIn, "onStart");
|
|
@@ -13145,46 +13145,46 @@ More information: The file containing the code for esbuild's JavaScript API (${_
|
|
|
13145
13145
|
}
|
|
13146
13146
|
};
|
|
13147
13147
|
longLivedService = {
|
|
13148
|
-
build: (options) => new Promise((
|
|
13148
|
+
build: (options) => new Promise((resolve39, reject) => {
|
|
13149
13149
|
service.buildOrContext({
|
|
13150
13150
|
callName: "build",
|
|
13151
13151
|
refs,
|
|
13152
13152
|
options,
|
|
13153
13153
|
isTTY: isTTY2(),
|
|
13154
13154
|
defaultWD,
|
|
13155
|
-
callback: (err, res) => err ? reject(err) :
|
|
13155
|
+
callback: (err, res) => err ? reject(err) : resolve39(res)
|
|
13156
13156
|
});
|
|
13157
13157
|
}),
|
|
13158
|
-
context: (options) => new Promise((
|
|
13158
|
+
context: (options) => new Promise((resolve39, reject) => service.buildOrContext({
|
|
13159
13159
|
callName: "context",
|
|
13160
13160
|
refs,
|
|
13161
13161
|
options,
|
|
13162
13162
|
isTTY: isTTY2(),
|
|
13163
13163
|
defaultWD,
|
|
13164
|
-
callback: (err, res) => err ? reject(err) :
|
|
13164
|
+
callback: (err, res) => err ? reject(err) : resolve39(res)
|
|
13165
13165
|
})),
|
|
13166
|
-
transform: (input, options) => new Promise((
|
|
13166
|
+
transform: (input, options) => new Promise((resolve39, reject) => service.transform({
|
|
13167
13167
|
callName: "transform",
|
|
13168
13168
|
refs,
|
|
13169
13169
|
input,
|
|
13170
13170
|
options: options || {},
|
|
13171
13171
|
isTTY: isTTY2(),
|
|
13172
13172
|
fs: fsAsync,
|
|
13173
|
-
callback: (err, res) => err ? reject(err) :
|
|
13173
|
+
callback: (err, res) => err ? reject(err) : resolve39(res)
|
|
13174
13174
|
})),
|
|
13175
|
-
formatMessages: (messages, options) => new Promise((
|
|
13175
|
+
formatMessages: (messages, options) => new Promise((resolve39, reject) => service.formatMessages({
|
|
13176
13176
|
callName: "formatMessages",
|
|
13177
13177
|
refs,
|
|
13178
13178
|
messages,
|
|
13179
13179
|
options,
|
|
13180
|
-
callback: (err, res) => err ? reject(err) :
|
|
13180
|
+
callback: (err, res) => err ? reject(err) : resolve39(res)
|
|
13181
13181
|
})),
|
|
13182
|
-
analyzeMetafile: (metafile, options) => new Promise((
|
|
13182
|
+
analyzeMetafile: (metafile, options) => new Promise((resolve39, reject) => service.analyzeMetafile({
|
|
13183
13183
|
callName: "analyzeMetafile",
|
|
13184
13184
|
refs,
|
|
13185
13185
|
metafile: typeof metafile === "string" ? metafile : JSON.stringify(metafile),
|
|
13186
13186
|
options,
|
|
13187
|
-
callback: (err, res) => err ? reject(err) :
|
|
13187
|
+
callback: (err, res) => err ? reject(err) : resolve39(res)
|
|
13188
13188
|
}))
|
|
13189
13189
|
};
|
|
13190
13190
|
return longLivedService;
|
|
@@ -13262,13 +13262,13 @@ error: ${text}`);
|
|
|
13262
13262
|
worker.postMessage(msg);
|
|
13263
13263
|
let status = Atomics.wait(sharedBufferView, 0, 0);
|
|
13264
13264
|
if (status !== "ok" && status !== "not-equal") throw new Error("Internal error: Atomics.wait() failed: " + status);
|
|
13265
|
-
let { message: { id: id2, resolve:
|
|
13265
|
+
let { message: { id: id2, resolve: resolve39, reject, properties } } = worker_threads2.receiveMessageOnPort(mainPort);
|
|
13266
13266
|
if (id !== id2) throw new Error(`Internal error: Expected id ${id} but got id ${id2}`);
|
|
13267
13267
|
if (reject) {
|
|
13268
13268
|
applyProperties(reject, properties);
|
|
13269
13269
|
throw reject;
|
|
13270
13270
|
}
|
|
13271
|
-
return
|
|
13271
|
+
return resolve39;
|
|
13272
13272
|
};
|
|
13273
13273
|
worker.unref();
|
|
13274
13274
|
return {
|
|
@@ -50419,7 +50419,7 @@ async function describeCommand(input, options = {}) {
|
|
|
50419
50419
|
throw new Error(`File not found: ${filePath}`);
|
|
50420
50420
|
}
|
|
50421
50421
|
try {
|
|
50422
|
-
const parseResult = await parseWorkflow(filePath, { workflowName });
|
|
50422
|
+
const parseResult = await parseWorkflow(filePath, { workflowName, projectDir: path12.dirname(filePath) });
|
|
50423
50423
|
if (parseResult.errors.length > 0) {
|
|
50424
50424
|
throw new Error(`Parse errors:
|
|
50425
50425
|
${parseResult.errors.map((err) => ` ${err}`).join("\n")}`);
|
|
@@ -52506,6 +52506,7 @@ async function diagramCommand(input, options = {}) {
|
|
|
52506
52506
|
if (!fs14.existsSync(filePath)) {
|
|
52507
52507
|
throw new Error(`File not found: ${filePath}`);
|
|
52508
52508
|
}
|
|
52509
|
+
await parser.loadPackHandlers(path13.dirname(filePath));
|
|
52509
52510
|
let result;
|
|
52510
52511
|
if (ASCII_FORMATS.has(format)) {
|
|
52511
52512
|
result = fileToASCII(filePath, { ...diagramOptions, format });
|
|
@@ -52527,6 +52528,7 @@ var init_diagram2 = __esm({
|
|
|
52527
52528
|
"src/cli/commands/diagram.ts"() {
|
|
52528
52529
|
"use strict";
|
|
52529
52530
|
init_diagram();
|
|
52531
|
+
init_parser2();
|
|
52530
52532
|
init_logger();
|
|
52531
52533
|
init_safe_write();
|
|
52532
52534
|
ASCII_FORMATS = /* @__PURE__ */ new Set(["ascii", "ascii-compact", "text"]);
|
|
@@ -52570,8 +52572,8 @@ async function diffCommand(file1, file2, options = {}) {
|
|
|
52570
52572
|
}
|
|
52571
52573
|
try {
|
|
52572
52574
|
const [result1, result2] = await Promise.all([
|
|
52573
|
-
parseWorkflow(filePath1, { workflowName }),
|
|
52574
|
-
parseWorkflow(filePath2, { workflowName })
|
|
52575
|
+
parseWorkflow(filePath1, { workflowName, projectDir: path14.dirname(filePath1) }),
|
|
52576
|
+
parseWorkflow(filePath2, { workflowName, projectDir: path14.dirname(filePath2) })
|
|
52575
52577
|
]);
|
|
52576
52578
|
if (result1.errors.length > 0) {
|
|
52577
52579
|
throw new Error(`Parse errors in ${file1}:
|
|
@@ -52660,7 +52662,7 @@ async function validateCommand(input, options = {}) {
|
|
|
52660
52662
|
logger.progress(i + 1, files.length, fileName);
|
|
52661
52663
|
}
|
|
52662
52664
|
try {
|
|
52663
|
-
const parseResult = await parseWorkflow(file, { workflowName, projectDir:
|
|
52665
|
+
const parseResult = await parseWorkflow(file, { workflowName, projectDir: path15.dirname(path15.resolve(file)) });
|
|
52664
52666
|
if (parseResult.warnings.length > 0) {
|
|
52665
52667
|
if (!json2 && !quiet) {
|
|
52666
52668
|
logger.warn(`Parse warnings in ${fileName}:`);
|
|
@@ -54396,13 +54398,13 @@ var init_promise_polyfill = __esm({
|
|
|
54396
54398
|
// Available starting from Node 22
|
|
54397
54399
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers
|
|
54398
54400
|
static withResolver() {
|
|
54399
|
-
let
|
|
54401
|
+
let resolve39;
|
|
54400
54402
|
let reject;
|
|
54401
54403
|
const promise = new Promise((res, rej) => {
|
|
54402
|
-
|
|
54404
|
+
resolve39 = res;
|
|
54403
54405
|
reject = rej;
|
|
54404
54406
|
});
|
|
54405
|
-
return { promise, resolve:
|
|
54407
|
+
return { promise, resolve: resolve39, reject };
|
|
54406
54408
|
}
|
|
54407
54409
|
};
|
|
54408
54410
|
}
|
|
@@ -54440,7 +54442,7 @@ function createPrompt(view) {
|
|
|
54440
54442
|
output
|
|
54441
54443
|
});
|
|
54442
54444
|
const screen = new ScreenManager(rl);
|
|
54443
|
-
const { promise, resolve:
|
|
54445
|
+
const { promise, resolve: resolve39, reject } = PromisePolyfill.withResolver();
|
|
54444
54446
|
const cancel = () => reject(new CancelPromptError());
|
|
54445
54447
|
if (signal) {
|
|
54446
54448
|
const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
|
|
@@ -54467,7 +54469,7 @@ function createPrompt(view) {
|
|
|
54467
54469
|
cycle(() => {
|
|
54468
54470
|
try {
|
|
54469
54471
|
const nextView = view(config2, (value) => {
|
|
54470
|
-
setImmediate(() =>
|
|
54472
|
+
setImmediate(() => resolve39(value));
|
|
54471
54473
|
});
|
|
54472
54474
|
if (nextView === void 0) {
|
|
54473
54475
|
const callerFilename = callSites[1]?.getFileName();
|
|
@@ -55278,13 +55280,13 @@ var init_promise_polyfill2 = __esm({
|
|
|
55278
55280
|
// Available starting from Node 22
|
|
55279
55281
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers
|
|
55280
55282
|
static withResolver() {
|
|
55281
|
-
let
|
|
55283
|
+
let resolve39;
|
|
55282
55284
|
let reject;
|
|
55283
55285
|
const promise = new Promise((res, rej) => {
|
|
55284
|
-
|
|
55286
|
+
resolve39 = res;
|
|
55285
55287
|
reject = rej;
|
|
55286
55288
|
});
|
|
55287
|
-
return { promise, resolve:
|
|
55289
|
+
return { promise, resolve: resolve39, reject };
|
|
55288
55290
|
}
|
|
55289
55291
|
};
|
|
55290
55292
|
}
|
|
@@ -55322,7 +55324,7 @@ function createPrompt2(view) {
|
|
|
55322
55324
|
output
|
|
55323
55325
|
});
|
|
55324
55326
|
const screen = new ScreenManager2(rl);
|
|
55325
|
-
const { promise, resolve:
|
|
55327
|
+
const { promise, resolve: resolve39, reject } = PromisePolyfill2.withResolver();
|
|
55326
55328
|
const cancel = () => reject(new CancelPromptError2());
|
|
55327
55329
|
if (signal) {
|
|
55328
55330
|
const abort = () => reject(new AbortPromptError2({ cause: signal.reason }));
|
|
@@ -55349,7 +55351,7 @@ function createPrompt2(view) {
|
|
|
55349
55351
|
cycle(() => {
|
|
55350
55352
|
try {
|
|
55351
55353
|
const nextView = view(config2, (value) => {
|
|
55352
|
-
setImmediate(() =>
|
|
55354
|
+
setImmediate(() => resolve39(value));
|
|
55353
55355
|
});
|
|
55354
55356
|
if (nextView === void 0) {
|
|
55355
55357
|
const callerFilename = callSites[1]?.getFileName();
|
|
@@ -56133,13 +56135,13 @@ var init_promise_polyfill3 = __esm({
|
|
|
56133
56135
|
// Available starting from Node 22
|
|
56134
56136
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers
|
|
56135
56137
|
static withResolver() {
|
|
56136
|
-
let
|
|
56138
|
+
let resolve39;
|
|
56137
56139
|
let reject;
|
|
56138
56140
|
const promise = new Promise((res, rej) => {
|
|
56139
|
-
|
|
56141
|
+
resolve39 = res;
|
|
56140
56142
|
reject = rej;
|
|
56141
56143
|
});
|
|
56142
|
-
return { promise, resolve:
|
|
56144
|
+
return { promise, resolve: resolve39, reject };
|
|
56143
56145
|
}
|
|
56144
56146
|
};
|
|
56145
56147
|
}
|
|
@@ -56177,7 +56179,7 @@ function createPrompt3(view) {
|
|
|
56177
56179
|
output
|
|
56178
56180
|
});
|
|
56179
56181
|
const screen = new ScreenManager3(rl);
|
|
56180
|
-
const { promise, resolve:
|
|
56182
|
+
const { promise, resolve: resolve39, reject } = PromisePolyfill3.withResolver();
|
|
56181
56183
|
const cancel = () => reject(new CancelPromptError3());
|
|
56182
56184
|
if (signal) {
|
|
56183
56185
|
const abort = () => reject(new AbortPromptError3({ cause: signal.reason }));
|
|
@@ -56204,7 +56206,7 @@ function createPrompt3(view) {
|
|
|
56204
56206
|
cycle(() => {
|
|
56205
56207
|
try {
|
|
56206
56208
|
const nextView = view(config2, (value) => {
|
|
56207
|
-
setImmediate(() =>
|
|
56209
|
+
setImmediate(() => resolve39(value));
|
|
56208
56210
|
});
|
|
56209
56211
|
if (nextView === void 0) {
|
|
56210
56212
|
const callerFilename = callSites[1]?.getFileName();
|
|
@@ -69583,7 +69585,7 @@ var init_protocol = __esm({
|
|
|
69583
69585
|
return;
|
|
69584
69586
|
}
|
|
69585
69587
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
69586
|
-
await new Promise((
|
|
69588
|
+
await new Promise((resolve39) => setTimeout(resolve39, pollInterval));
|
|
69587
69589
|
options?.signal?.throwIfAborted();
|
|
69588
69590
|
}
|
|
69589
69591
|
} catch (error2) {
|
|
@@ -69600,7 +69602,7 @@ var init_protocol = __esm({
|
|
|
69600
69602
|
*/
|
|
69601
69603
|
request(request, resultSchema, options) {
|
|
69602
69604
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
69603
|
-
return new Promise((
|
|
69605
|
+
return new Promise((resolve39, reject) => {
|
|
69604
69606
|
const earlyReject = (error2) => {
|
|
69605
69607
|
reject(error2);
|
|
69606
69608
|
};
|
|
@@ -69678,7 +69680,7 @@ var init_protocol = __esm({
|
|
|
69678
69680
|
if (!parseResult.success) {
|
|
69679
69681
|
reject(parseResult.error);
|
|
69680
69682
|
} else {
|
|
69681
|
-
|
|
69683
|
+
resolve39(parseResult.data);
|
|
69682
69684
|
}
|
|
69683
69685
|
} catch (error2) {
|
|
69684
69686
|
reject(error2);
|
|
@@ -69939,12 +69941,12 @@ var init_protocol = __esm({
|
|
|
69939
69941
|
}
|
|
69940
69942
|
} catch {
|
|
69941
69943
|
}
|
|
69942
|
-
return new Promise((
|
|
69944
|
+
return new Promise((resolve39, reject) => {
|
|
69943
69945
|
if (signal.aborted) {
|
|
69944
69946
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
69945
69947
|
return;
|
|
69946
69948
|
}
|
|
69947
|
-
const timeoutId = setTimeout(
|
|
69949
|
+
const timeoutId = setTimeout(resolve39, interval);
|
|
69948
69950
|
signal.addEventListener("abort", () => {
|
|
69949
69951
|
clearTimeout(timeoutId);
|
|
69950
69952
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -72971,7 +72973,7 @@ var require_compile = __commonJS({
|
|
|
72971
72973
|
const schOrFunc = root.refs[ref];
|
|
72972
72974
|
if (schOrFunc)
|
|
72973
72975
|
return schOrFunc;
|
|
72974
|
-
let _sch =
|
|
72976
|
+
let _sch = resolve39.call(this, root, ref);
|
|
72975
72977
|
if (_sch === void 0) {
|
|
72976
72978
|
const schema2 = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
72977
72979
|
const { schemaId } = this.opts;
|
|
@@ -72998,7 +73000,7 @@ var require_compile = __commonJS({
|
|
|
72998
73000
|
function sameSchemaEnv(s1, s2) {
|
|
72999
73001
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
73000
73002
|
}
|
|
73001
|
-
function
|
|
73003
|
+
function resolve39(root, ref) {
|
|
73002
73004
|
let sch;
|
|
73003
73005
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
73004
73006
|
ref = sch;
|
|
@@ -73573,7 +73575,7 @@ var require_fast_uri = __commonJS({
|
|
|
73573
73575
|
}
|
|
73574
73576
|
return uri;
|
|
73575
73577
|
}
|
|
73576
|
-
function
|
|
73578
|
+
function resolve39(baseURI, relativeURI, options) {
|
|
73577
73579
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
73578
73580
|
const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
73579
73581
|
schemelessOptions.skipEscape = true;
|
|
@@ -73800,7 +73802,7 @@ var require_fast_uri = __commonJS({
|
|
|
73800
73802
|
var fastUri = {
|
|
73801
73803
|
SCHEMES,
|
|
73802
73804
|
normalize,
|
|
73803
|
-
resolve:
|
|
73805
|
+
resolve: resolve39,
|
|
73804
73806
|
resolveComponent,
|
|
73805
73807
|
equal,
|
|
73806
73808
|
serialize,
|
|
@@ -77919,7 +77921,7 @@ var init_mcp = __esm({
|
|
|
77919
77921
|
let task = createTaskResult.task;
|
|
77920
77922
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
77921
77923
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
77922
|
-
await new Promise((
|
|
77924
|
+
await new Promise((resolve39) => setTimeout(resolve39, pollInterval));
|
|
77923
77925
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
77924
77926
|
if (!updatedTask) {
|
|
77925
77927
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -78513,12 +78515,12 @@ var init_stdio2 = __esm({
|
|
|
78513
78515
|
this.onclose?.();
|
|
78514
78516
|
}
|
|
78515
78517
|
send(message) {
|
|
78516
|
-
return new Promise((
|
|
78518
|
+
return new Promise((resolve39) => {
|
|
78517
78519
|
const json2 = serializeMessage(message);
|
|
78518
78520
|
if (this._stdout.write(json2)) {
|
|
78519
|
-
|
|
78521
|
+
resolve39();
|
|
78520
78522
|
} else {
|
|
78521
|
-
this._stdout.once("drain",
|
|
78523
|
+
this._stdout.once("drain", resolve39);
|
|
78522
78524
|
}
|
|
78523
78525
|
});
|
|
78524
78526
|
}
|
|
@@ -83249,8 +83251,8 @@ var init_debug_controller = __esm({
|
|
|
83249
83251
|
async pause(nodeId, phase, ctx) {
|
|
83250
83252
|
const state = this.buildState(nodeId, phase, ctx);
|
|
83251
83253
|
this._pauseResolve?.(state);
|
|
83252
|
-
return new Promise((
|
|
83253
|
-
this._gateResolve = (action) =>
|
|
83254
|
+
return new Promise((resolve39) => {
|
|
83255
|
+
this._gateResolve = (action) => resolve39(action);
|
|
83254
83256
|
});
|
|
83255
83257
|
}
|
|
83256
83258
|
applyAction(action) {
|
|
@@ -83311,8 +83313,8 @@ var init_debug_controller = __esm({
|
|
|
83311
83313
|
return outputs;
|
|
83312
83314
|
}
|
|
83313
83315
|
_createPausePromise() {
|
|
83314
|
-
return new Promise((
|
|
83315
|
-
this._pauseResolve =
|
|
83316
|
+
return new Promise((resolve39) => {
|
|
83317
|
+
this._pauseResolve = resolve39;
|
|
83316
83318
|
});
|
|
83317
83319
|
}
|
|
83318
83320
|
};
|
|
@@ -83511,8 +83513,8 @@ var init_agent_channel = __esm({
|
|
|
83511
83513
|
*/
|
|
83512
83514
|
async request(agentRequest) {
|
|
83513
83515
|
this._pauseResolve?.(agentRequest);
|
|
83514
|
-
return new Promise((
|
|
83515
|
-
this._resolve =
|
|
83516
|
+
return new Promise((resolve39, reject) => {
|
|
83517
|
+
this._resolve = resolve39;
|
|
83516
83518
|
this._reject = reject;
|
|
83517
83519
|
});
|
|
83518
83520
|
}
|
|
@@ -83542,8 +83544,8 @@ var init_agent_channel = __esm({
|
|
|
83542
83544
|
this._pausePromise = this._createPausePromise();
|
|
83543
83545
|
}
|
|
83544
83546
|
_createPausePromise() {
|
|
83545
|
-
return new Promise((
|
|
83546
|
-
this._pauseResolve =
|
|
83547
|
+
return new Promise((resolve39) => {
|
|
83548
|
+
this._pauseResolve = resolve39;
|
|
83547
83549
|
});
|
|
83548
83550
|
}
|
|
83549
83551
|
};
|
|
@@ -84900,7 +84902,7 @@ async function runCommandInner(input, options) {
|
|
|
84900
84902
|
let executionOrder = resumeExecutionOrder;
|
|
84901
84903
|
if (!executionOrder) {
|
|
84902
84904
|
const source = fs36.readFileSync(filePath, "utf8");
|
|
84903
|
-
const parsed = await parseWorkflow(source, { workflowName: options.workflow });
|
|
84905
|
+
const parsed = await parseWorkflow(source, { workflowName: options.workflow, projectDir: path40.dirname(filePath) });
|
|
84904
84906
|
if (parsed.errors.length === 0) {
|
|
84905
84907
|
executionOrder = getTopologicalOrder(parsed.ast);
|
|
84906
84908
|
} else {
|
|
@@ -85113,7 +85115,7 @@ async function validateMockConfig(mocks, filePath, workflowName) {
|
|
|
85113
85115
|
}
|
|
85114
85116
|
}
|
|
85115
85117
|
try {
|
|
85116
|
-
const result = await parseWorkflow(filePath, { workflowName });
|
|
85118
|
+
const result = await parseWorkflow(filePath, { workflowName, projectDir: path40.dirname(filePath) });
|
|
85117
85119
|
if (result.errors.length > 0 || !result.ast?.instances) return;
|
|
85118
85120
|
const usedNodeTypes = new Set(result.ast.instances.map((i) => i.nodeType));
|
|
85119
85121
|
for (const [section, nodeType] of Object.entries(MOCK_SECTION_TO_NODE)) {
|
|
@@ -85175,13 +85177,13 @@ async function runDebugRepl(controller, execPromise, agentChannel, options) {
|
|
|
85175
85177
|
output: process.stderr,
|
|
85176
85178
|
prompt: "> "
|
|
85177
85179
|
});
|
|
85178
|
-
return new Promise((
|
|
85180
|
+
return new Promise((resolve39, reject) => {
|
|
85179
85181
|
let resolved = false;
|
|
85180
85182
|
function finish(value) {
|
|
85181
85183
|
if (resolved) return;
|
|
85182
85184
|
resolved = true;
|
|
85183
85185
|
rl.close();
|
|
85184
|
-
|
|
85186
|
+
resolve39(value);
|
|
85185
85187
|
}
|
|
85186
85188
|
function fail(err) {
|
|
85187
85189
|
if (resolved) return;
|
|
@@ -85393,7 +85395,7 @@ Workflow completed in ${execResult.executionTime}ms`);
|
|
|
85393
85395
|
});
|
|
85394
85396
|
}
|
|
85395
85397
|
function promptForInput(question) {
|
|
85396
|
-
return new Promise((
|
|
85398
|
+
return new Promise((resolve39) => {
|
|
85397
85399
|
const rl = readline8.createInterface({
|
|
85398
85400
|
input: process.stdin,
|
|
85399
85401
|
output: process.stderr
|
|
@@ -85401,7 +85403,7 @@ function promptForInput(question) {
|
|
|
85401
85403
|
});
|
|
85402
85404
|
rl.question(question, (answer) => {
|
|
85403
85405
|
rl.close();
|
|
85404
|
-
|
|
85406
|
+
resolve39(answer.trim());
|
|
85405
85407
|
});
|
|
85406
85408
|
});
|
|
85407
85409
|
}
|
|
@@ -85877,6 +85879,15 @@ __export(serve_exports, {
|
|
|
85877
85879
|
import * as path41 from "path";
|
|
85878
85880
|
import * as fs38 from "fs";
|
|
85879
85881
|
async function serveCommand(dir, options) {
|
|
85882
|
+
try {
|
|
85883
|
+
await import("fastify");
|
|
85884
|
+
} catch {
|
|
85885
|
+
logger.error("The serve command requires fastify. Install it with:");
|
|
85886
|
+
logger.newline();
|
|
85887
|
+
logger.log(" npm install fastify");
|
|
85888
|
+
logger.newline();
|
|
85889
|
+
process.exit(1);
|
|
85890
|
+
}
|
|
85880
85891
|
const workflowDir = path41.resolve(dir || ".");
|
|
85881
85892
|
if (!fs38.existsSync(workflowDir)) {
|
|
85882
85893
|
throw new Error(`Directory not found: ${workflowDir}`);
|
|
@@ -86761,131 +86772,6 @@ var init_implement = __esm({
|
|
|
86761
86772
|
}
|
|
86762
86773
|
});
|
|
86763
86774
|
|
|
86764
|
-
// src/cli/commands/changelog.ts
|
|
86765
|
-
var changelog_exports = {};
|
|
86766
|
-
__export(changelog_exports, {
|
|
86767
|
-
changelogCommand: () => changelogCommand
|
|
86768
|
-
});
|
|
86769
|
-
import { execSync as execSync6 } from "child_process";
|
|
86770
|
-
function categorize(files) {
|
|
86771
|
-
for (const category of CATEGORIES2) {
|
|
86772
|
-
if (files.some(category.match)) {
|
|
86773
|
-
return category.name;
|
|
86774
|
-
}
|
|
86775
|
-
}
|
|
86776
|
-
return "Other";
|
|
86777
|
-
}
|
|
86778
|
-
function getGitRange(options) {
|
|
86779
|
-
if (options.range) {
|
|
86780
|
-
return options.range;
|
|
86781
|
-
}
|
|
86782
|
-
if (options.lastTag) {
|
|
86783
|
-
try {
|
|
86784
|
-
const lastTag = execSync6("git describe --tags --abbrev=0", {
|
|
86785
|
-
encoding: "utf8"
|
|
86786
|
-
}).trim();
|
|
86787
|
-
return `${lastTag}..HEAD`;
|
|
86788
|
-
} catch {
|
|
86789
|
-
logger.warn("No git tags found, showing all commits");
|
|
86790
|
-
return "HEAD";
|
|
86791
|
-
}
|
|
86792
|
-
}
|
|
86793
|
-
if (options.since) {
|
|
86794
|
-
return `--since="${options.since}"`;
|
|
86795
|
-
}
|
|
86796
|
-
return "-20";
|
|
86797
|
-
}
|
|
86798
|
-
function getCommits(rangeArg) {
|
|
86799
|
-
const isSinceArg = rangeArg.startsWith("--since");
|
|
86800
|
-
const isCountArg = rangeArg.startsWith("-");
|
|
86801
|
-
let logCmd;
|
|
86802
|
-
if (isSinceArg) {
|
|
86803
|
-
logCmd = `git log ${rangeArg} --format="%H %s" --no-merges`;
|
|
86804
|
-
} else if (isCountArg) {
|
|
86805
|
-
logCmd = `git log ${rangeArg} --format="%H %s" --no-merges`;
|
|
86806
|
-
} else {
|
|
86807
|
-
logCmd = `git log ${rangeArg} --format="%H %s" --no-merges`;
|
|
86808
|
-
}
|
|
86809
|
-
const logOutput = execSync6(logCmd, { encoding: "utf8" }).trim();
|
|
86810
|
-
if (!logOutput) {
|
|
86811
|
-
return [];
|
|
86812
|
-
}
|
|
86813
|
-
const entries = [];
|
|
86814
|
-
for (const line of logOutput.split(/\r?\n/)) {
|
|
86815
|
-
if (!line.trim()) continue;
|
|
86816
|
-
const spaceIdx = line.indexOf(" ");
|
|
86817
|
-
const hash = line.slice(0, spaceIdx);
|
|
86818
|
-
const message = line.slice(spaceIdx + 1);
|
|
86819
|
-
let files;
|
|
86820
|
-
try {
|
|
86821
|
-
const filesOutput = execSync6(`git diff-tree --no-commit-id --name-only -r ${hash}`, {
|
|
86822
|
-
encoding: "utf8"
|
|
86823
|
-
}).trim();
|
|
86824
|
-
files = filesOutput ? filesOutput.split(/\r?\n/) : [];
|
|
86825
|
-
} catch {
|
|
86826
|
-
files = [];
|
|
86827
|
-
}
|
|
86828
|
-
entries.push({ hash: hash.slice(0, 7), message, files });
|
|
86829
|
-
}
|
|
86830
|
-
return entries;
|
|
86831
|
-
}
|
|
86832
|
-
async function changelogCommand(options = {}) {
|
|
86833
|
-
const rangeArg = getGitRange(options);
|
|
86834
|
-
const rangeLabel = options.range || (options.lastTag ? "last tag" : options.since ? `since ${options.since}` : "recent");
|
|
86835
|
-
const commits = getCommits(rangeArg);
|
|
86836
|
-
if (commits.length === 0) {
|
|
86837
|
-
logger.info("No commits found in the specified range.");
|
|
86838
|
-
return;
|
|
86839
|
-
}
|
|
86840
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
86841
|
-
for (const commit of commits) {
|
|
86842
|
-
const category = categorize(commit.files);
|
|
86843
|
-
if (!grouped.has(category)) {
|
|
86844
|
-
grouped.set(category, []);
|
|
86845
|
-
}
|
|
86846
|
-
grouped.get(category).push(commit);
|
|
86847
|
-
}
|
|
86848
|
-
console.log(`## Changes (${rangeLabel})
|
|
86849
|
-
`);
|
|
86850
|
-
const categoryOrder = CATEGORIES2.map((c) => c.name);
|
|
86851
|
-
const sortedCategories = [...grouped.keys()].sort((a, b) => {
|
|
86852
|
-
const idxA = categoryOrder.indexOf(a);
|
|
86853
|
-
const idxB = categoryOrder.indexOf(b);
|
|
86854
|
-
if (idxA === -1 && idxB === -1) return a.localeCompare(b);
|
|
86855
|
-
if (idxA === -1) return 1;
|
|
86856
|
-
if (idxB === -1) return -1;
|
|
86857
|
-
return idxA - idxB;
|
|
86858
|
-
});
|
|
86859
|
-
for (const category of sortedCategories) {
|
|
86860
|
-
const categoryCommits = grouped.get(category);
|
|
86861
|
-
console.log(`### ${category} (${categoryCommits.length} commit${categoryCommits.length !== 1 ? "s" : ""})
|
|
86862
|
-
`);
|
|
86863
|
-
for (const commit of categoryCommits) {
|
|
86864
|
-
console.log(`- ${commit.hash} ${commit.message}`);
|
|
86865
|
-
}
|
|
86866
|
-
console.log("");
|
|
86867
|
-
}
|
|
86868
|
-
}
|
|
86869
|
-
var CATEGORIES2;
|
|
86870
|
-
var init_changelog = __esm({
|
|
86871
|
-
"src/cli/commands/changelog.ts"() {
|
|
86872
|
-
"use strict";
|
|
86873
|
-
init_logger();
|
|
86874
|
-
CATEGORIES2 = [
|
|
86875
|
-
{ name: "Grammar", match: (f) => /parser|chevrotain|grammar/.test(f) },
|
|
86876
|
-
{ name: "Code Generation", match: (f) => /generator|body-generator|generate/.test(f) },
|
|
86877
|
-
{ name: "Differ", match: (f) => f.includes("diff/") },
|
|
86878
|
-
{ name: "CLI", match: (f) => f.includes("cli/commands/") },
|
|
86879
|
-
{ name: "MCP Tools", match: (f) => f.includes("mcp/") },
|
|
86880
|
-
{ name: "Deployment", match: (f) => /deployment|export/.test(f) },
|
|
86881
|
-
{ name: "Runtime", match: (f) => f.includes("runtime/") },
|
|
86882
|
-
{ name: "Migration", match: (f) => f.includes("migration/") },
|
|
86883
|
-
{ name: "Tests", match: (f) => f.includes("tests/") || f.includes(".test.") },
|
|
86884
|
-
{ name: "Documentation", match: (f) => /doc|readme|changelog/i.test(f) }
|
|
86885
|
-
];
|
|
86886
|
-
}
|
|
86887
|
-
});
|
|
86888
|
-
|
|
86889
86775
|
// src/cli/commands/docs.ts
|
|
86890
86776
|
var docs_exports = {};
|
|
86891
86777
|
__export(docs_exports, {
|
|
@@ -87036,7 +86922,7 @@ __export(market_exports, {
|
|
|
87036
86922
|
});
|
|
87037
86923
|
import * as fs45 from "fs";
|
|
87038
86924
|
import * as path48 from "path";
|
|
87039
|
-
import { execSync as
|
|
86925
|
+
import { execSync as execSync6 } from "child_process";
|
|
87040
86926
|
async function marketInitCommand(name, options = {}) {
|
|
87041
86927
|
if (!name.startsWith("flow-weaver-pack-")) {
|
|
87042
86928
|
const suggested = `flow-weaver-pack-${name}`;
|
|
@@ -87265,7 +87151,7 @@ async function marketPublishCommand(directory, options = {}) {
|
|
|
87265
87151
|
if (tag) npmArgs.push("--tag", tag);
|
|
87266
87152
|
try {
|
|
87267
87153
|
logger.newline();
|
|
87268
|
-
|
|
87154
|
+
execSync6(`npm ${npmArgs.join(" ")}`, { cwd: dir, stdio: "inherit" });
|
|
87269
87155
|
if (!dryRun) {
|
|
87270
87156
|
logger.newline();
|
|
87271
87157
|
logger.success(`Published ${pkg.name}@${pkg.version} to npm`);
|
|
@@ -87282,7 +87168,7 @@ async function marketInstallCommand(packageSpec, options = {}) {
|
|
|
87282
87168
|
logger.newline();
|
|
87283
87169
|
}
|
|
87284
87170
|
try {
|
|
87285
|
-
|
|
87171
|
+
execSync6(`npm install ${packageSpec}`, { stdio: json2 ? "pipe" : "inherit" });
|
|
87286
87172
|
} catch (err) {
|
|
87287
87173
|
if (json2) {
|
|
87288
87174
|
console.log(JSON.stringify({ success: false, error: getErrorMessage(err) }));
|
|
@@ -87840,15 +87726,15 @@ function readLine(prompt2) {
|
|
|
87840
87726
|
return Promise.resolve(null);
|
|
87841
87727
|
}
|
|
87842
87728
|
const rl = readline9.createInterface({ input: process.stdin, output: process.stderr });
|
|
87843
|
-
return new Promise((
|
|
87729
|
+
return new Promise((resolve39) => {
|
|
87844
87730
|
let answered = false;
|
|
87845
87731
|
rl.question(prompt2, (answer) => {
|
|
87846
87732
|
answered = true;
|
|
87847
87733
|
rl.close();
|
|
87848
|
-
|
|
87734
|
+
resolve39(answer.trim());
|
|
87849
87735
|
});
|
|
87850
87736
|
rl.on("close", () => {
|
|
87851
|
-
if (!answered)
|
|
87737
|
+
if (!answered) resolve39(null);
|
|
87852
87738
|
});
|
|
87853
87739
|
});
|
|
87854
87740
|
}
|
|
@@ -88102,7 +87988,7 @@ async function authStatusCommand() {
|
|
|
88102
87988
|
}
|
|
88103
87989
|
function prompt(message, hidden = false) {
|
|
88104
87990
|
if (hidden && process.stdin.isTTY) {
|
|
88105
|
-
return new Promise((
|
|
87991
|
+
return new Promise((resolve39) => {
|
|
88106
87992
|
process.stderr.write(message);
|
|
88107
87993
|
process.stdin.setRawMode(true);
|
|
88108
87994
|
process.stdin.resume();
|
|
@@ -88114,7 +88000,7 @@ function prompt(message, hidden = false) {
|
|
|
88114
88000
|
process.stdin.pause();
|
|
88115
88001
|
process.stdin.removeListener("data", handler);
|
|
88116
88002
|
process.stderr.write("\n");
|
|
88117
|
-
|
|
88003
|
+
resolve39(input);
|
|
88118
88004
|
} else if (ch === "") {
|
|
88119
88005
|
process.stdin.setRawMode(false);
|
|
88120
88006
|
process.exit(1);
|
|
@@ -88127,11 +88013,11 @@ function prompt(message, hidden = false) {
|
|
|
88127
88013
|
process.stdin.on("data", handler);
|
|
88128
88014
|
});
|
|
88129
88015
|
}
|
|
88130
|
-
return new Promise((
|
|
88016
|
+
return new Promise((resolve39) => {
|
|
88131
88017
|
const rl = readline10.createInterface({ input: process.stdin, output: process.stderr });
|
|
88132
88018
|
rl.question(message, (answer) => {
|
|
88133
88019
|
rl.close();
|
|
88134
|
-
|
|
88020
|
+
resolve39(answer);
|
|
88135
88021
|
});
|
|
88136
88022
|
});
|
|
88137
88023
|
}
|
|
@@ -88645,7 +88531,7 @@ var init_device_connection = __esm({
|
|
|
88645
88531
|
const wsUrl = this.options.platformUrl.replace(/^http/, "ws").replace(/\/$/, "") + "/ws/device";
|
|
88646
88532
|
this.log(`Connecting to ${wsUrl}...`);
|
|
88647
88533
|
this.shouldReconnect = true;
|
|
88648
|
-
return new Promise((
|
|
88534
|
+
return new Promise((resolve39, reject) => {
|
|
88649
88535
|
try {
|
|
88650
88536
|
this.ws = new WebSocket(`${wsUrl}?token=${encodeURIComponent(this.options.token)}`);
|
|
88651
88537
|
} catch (err) {
|
|
@@ -88662,7 +88548,7 @@ var init_device_connection = __esm({
|
|
|
88662
88548
|
}
|
|
88663
88549
|
}, 3e4);
|
|
88664
88550
|
this.options.onConnect?.();
|
|
88665
|
-
|
|
88551
|
+
resolve39();
|
|
88666
88552
|
});
|
|
88667
88553
|
this.ws.addEventListener("message", async (event) => {
|
|
88668
88554
|
try {
|
|
@@ -88768,12 +88654,12 @@ import * as path52 from "node:path";
|
|
|
88768
88654
|
import * as os5 from "node:os";
|
|
88769
88655
|
import * as readline11 from "node:readline";
|
|
88770
88656
|
function promptYesNo(message) {
|
|
88771
|
-
return new Promise((
|
|
88657
|
+
return new Promise((resolve39) => {
|
|
88772
88658
|
const rl = readline11.createInterface({ input: process.stdin, output: process.stderr });
|
|
88773
88659
|
rl.question(message, (answer) => {
|
|
88774
88660
|
rl.close();
|
|
88775
88661
|
const normalized = answer.trim().toLowerCase();
|
|
88776
|
-
|
|
88662
|
+
resolve39(normalized === "" || normalized === "y" || normalized === "yes");
|
|
88777
88663
|
});
|
|
88778
88664
|
});
|
|
88779
88665
|
}
|
|
@@ -88894,15 +88780,15 @@ async function handleConnect(projectDir) {
|
|
|
88894
88780
|
try {
|
|
88895
88781
|
await conn.connect();
|
|
88896
88782
|
console.log(" \x1B[2mPress Ctrl+C to disconnect.\x1B[0m\n");
|
|
88897
|
-
await new Promise((
|
|
88783
|
+
await new Promise((resolve39) => {
|
|
88898
88784
|
process.on("SIGINT", () => {
|
|
88899
88785
|
console.log("\n \x1B[2mDisconnecting...\x1B[0m");
|
|
88900
88786
|
conn.disconnect();
|
|
88901
|
-
|
|
88787
|
+
resolve39();
|
|
88902
88788
|
});
|
|
88903
88789
|
process.on("SIGTERM", () => {
|
|
88904
88790
|
conn.disconnect();
|
|
88905
|
-
|
|
88791
|
+
resolve39();
|
|
88906
88792
|
});
|
|
88907
88793
|
});
|
|
88908
88794
|
} catch (err) {
|
|
@@ -88960,7 +88846,7 @@ function parseIntStrict(value) {
|
|
|
88960
88846
|
// src/cli/index.ts
|
|
88961
88847
|
init_logger();
|
|
88962
88848
|
init_error_utils();
|
|
88963
|
-
var version2 = true ? "0.30.
|
|
88849
|
+
var version2 = true ? "0.30.1" : "0.0.0-dev";
|
|
88964
88850
|
var program2 = new Command();
|
|
88965
88851
|
program2.name("fw").description("Flow Weaver Annotations - Compile and validate workflow files").option("-v, --version", "Output the current version").option("--no-color", "Disable colors").option("--color", "Force colors").on("option:version", () => {
|
|
88966
88852
|
logger.banner(version2);
|
|
@@ -89156,10 +89042,6 @@ program2.command("implement <input> [node]").description("Replace a stub node wi
|
|
|
89156
89042
|
if (options.workflow) options.workflowName = options.workflow;
|
|
89157
89043
|
await implementCommand2(input, nodeName, options);
|
|
89158
89044
|
}));
|
|
89159
|
-
program2.command("changelog").description("Generate changelog from git history, categorized by file path").option("--last-tag", "From last git tag to HEAD", false).option("--since <date>", 'Date-based range (e.g., "2024-01-01")').option("-r, --range <range>", 'Custom git range (e.g., "v0.1.0..HEAD")').action(wrapAction(async (options) => {
|
|
89160
|
-
const { changelogCommand: changelogCommand2 } = await Promise.resolve().then(() => (init_changelog(), changelog_exports));
|
|
89161
|
-
await changelogCommand2(options);
|
|
89162
|
-
}));
|
|
89163
89045
|
program2.command("docs [args...]").description("Browse reference documentation").option("--json", "Output as JSON", false).option("--compact", "Return compact LLM-friendly version", false).action(wrapAction(async (args, options) => {
|
|
89164
89046
|
const { docsListCommand: docsListCommand2, docsReadCommand: docsReadCommand2, docsSearchCommand: docsSearchCommand2 } = await Promise.resolve().then(() => (init_docs2(), docs_exports));
|
|
89165
89047
|
if (args.length === 0 || args[0] === "list") {
|
package/dist/cli/index.js
CHANGED
|
@@ -531,17 +531,6 @@ program
|
|
|
531
531
|
options.workflowName = options.workflow;
|
|
532
532
|
await implementCommand(input, nodeName, options);
|
|
533
533
|
}));
|
|
534
|
-
// Changelog command
|
|
535
|
-
program
|
|
536
|
-
.command('changelog')
|
|
537
|
-
.description('Generate changelog from git history, categorized by file path')
|
|
538
|
-
.option('--last-tag', 'From last git tag to HEAD', false)
|
|
539
|
-
.option('--since <date>', 'Date-based range (e.g., "2024-01-01")')
|
|
540
|
-
.option('-r, --range <range>', 'Custom git range (e.g., "v0.1.0..HEAD")')
|
|
541
|
-
.action(wrapAction(async (options) => {
|
|
542
|
-
const { changelogCommand } = await import('./commands/changelog.js');
|
|
543
|
-
await changelogCommand(options);
|
|
544
|
-
}));
|
|
545
534
|
// Docs command: fw docs [topic] | fw docs search <query>
|
|
546
535
|
program
|
|
547
536
|
.command('docs [args...]')
|
|
@@ -316,16 +316,6 @@ export const CLI_COMMANDS = [
|
|
|
316
316
|
{ flags: '--diff', description: 'Show semantic diff before/after' },
|
|
317
317
|
],
|
|
318
318
|
},
|
|
319
|
-
{
|
|
320
|
-
name: 'changelog',
|
|
321
|
-
syntax: 'fw changelog [options]',
|
|
322
|
-
description: 'Generate changelog from git history, categorized by file path',
|
|
323
|
-
options: [
|
|
324
|
-
{ flags: '--last-tag', description: 'From last git tag to HEAD', exclusive: 'range' },
|
|
325
|
-
{ flags: '--since', arg: '<date>', description: 'Date-based range (e.g., "2024-01-01")', exclusive: 'range' },
|
|
326
|
-
{ flags: '-r, --range', arg: '<range>', description: 'Custom git range (e.g., "v0.1.0..HEAD")', exclusive: 'range' },
|
|
327
|
-
],
|
|
328
|
-
},
|
|
329
319
|
];
|
|
330
320
|
/**
|
|
331
321
|
* Extract CLI command documentation
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.30.
|
|
1
|
+
export declare const VERSION = "0.30.1";
|
|
2
2
|
//# sourceMappingURL=generated-version.d.ts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: CLI Reference
|
|
3
3
|
description: Complete reference for all Flow Weaver CLI commands, flags, and options
|
|
4
|
-
keywords: [cli, commands, compile, validate, strip, run, watch, dev, serve, export, diagram, diff, doctor, init, migrate, marketplace, plugin, grammar,
|
|
4
|
+
keywords: [cli, commands, compile, validate, strip, run, watch, dev, serve, export, diagram, diff, doctor, init, migrate, marketplace, plugin, grammar, openapi, pattern, create, templates, context, modify, implement, status]
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# CLI Reference
|
|
@@ -33,7 +33,6 @@ Complete reference for all `fw` CLI commands.
|
|
|
33
33
|
| `openapi` | Generate OpenAPI specification |
|
|
34
34
|
| `migrate` | Migrate to current syntax |
|
|
35
35
|
| `grammar` | Output annotation grammar |
|
|
36
|
-
| `changelog` | Generate changelog from git |
|
|
37
36
|
| `market` | Marketplace packages |
|
|
38
37
|
| `plugin` | External plugins |
|
|
39
38
|
| `modify` | Add/remove/rename nodes, connections, positions, and labels |
|
|
@@ -1023,29 +1022,6 @@ fw mcp-server [options]
|
|
|
1023
1022
|
|
|
1024
1023
|
---
|
|
1025
1024
|
|
|
1026
|
-
### changelog
|
|
1027
|
-
|
|
1028
|
-
Generate changelog from git history, categorized by file path.
|
|
1029
|
-
|
|
1030
|
-
```bash
|
|
1031
|
-
fw changelog [options]
|
|
1032
|
-
```
|
|
1033
|
-
|
|
1034
|
-
| Flag | Description | Default |
|
|
1035
|
-
|------|-------------|---------|
|
|
1036
|
-
| `--last-tag` | From last git tag to HEAD | `false` |
|
|
1037
|
-
| `--since <date>` | Date-based range | — |
|
|
1038
|
-
| `-r, --range <range>` | Custom git range | — |
|
|
1039
|
-
|
|
1040
|
-
**Examples:**
|
|
1041
|
-
```bash
|
|
1042
|
-
fw changelog --last-tag
|
|
1043
|
-
fw changelog --range v0.1.0..HEAD
|
|
1044
|
-
fw changelog --since 2024-01-01
|
|
1045
|
-
```
|
|
1046
|
-
|
|
1047
|
-
---
|
|
1048
|
-
|
|
1049
1025
|
## Global Flag
|
|
1050
1026
|
|
|
1051
1027
|
| Flag | Description |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synergenius/flow-weaver",
|
|
3
|
-
"version": "0.30.
|
|
3
|
+
"version": "0.30.1",
|
|
4
4
|
"description": "Flow Weaver: deterministic TypeScript workflow compiler. Define workflows with JSDoc annotations, compile to standalone functions with zero runtime dependencies.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Changelog command - generates changelog from git history
|
|
3
|
-
*
|
|
4
|
-
* Categorizes commits by changed file paths — no conventional commits needed.
|
|
5
|
-
* Works with any commit message style.
|
|
6
|
-
*/
|
|
7
|
-
export interface ChangelogOptions {
|
|
8
|
-
lastTag?: boolean;
|
|
9
|
-
since?: string;
|
|
10
|
-
range?: string;
|
|
11
|
-
}
|
|
12
|
-
export declare function changelogCommand(options?: ChangelogOptions): Promise<void>;
|
|
13
|
-
//# sourceMappingURL=changelog.d.ts.map
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Changelog command - generates changelog from git history
|
|
3
|
-
*
|
|
4
|
-
* Categorizes commits by changed file paths — no conventional commits needed.
|
|
5
|
-
* Works with any commit message style.
|
|
6
|
-
*/
|
|
7
|
-
import { execSync } from 'child_process';
|
|
8
|
-
import { logger } from '../utils/logger.js';
|
|
9
|
-
const CATEGORIES = [
|
|
10
|
-
{ name: 'Grammar', match: (f) => /parser|chevrotain|grammar/.test(f) },
|
|
11
|
-
{ name: 'Code Generation', match: (f) => /generator|body-generator|generate/.test(f) },
|
|
12
|
-
{ name: 'Differ', match: (f) => f.includes('diff/') },
|
|
13
|
-
{ name: 'CLI', match: (f) => f.includes('cli/commands/') },
|
|
14
|
-
{ name: 'MCP Tools', match: (f) => f.includes('mcp/') },
|
|
15
|
-
{ name: 'Deployment', match: (f) => /deployment|export/.test(f) },
|
|
16
|
-
{ name: 'Runtime', match: (f) => f.includes('runtime/') },
|
|
17
|
-
{ name: 'Migration', match: (f) => f.includes('migration/') },
|
|
18
|
-
{ name: 'Tests', match: (f) => f.includes('tests/') || f.includes('.test.') },
|
|
19
|
-
{ name: 'Documentation', match: (f) => /doc|readme|changelog/i.test(f) },
|
|
20
|
-
];
|
|
21
|
-
function categorize(files) {
|
|
22
|
-
for (const category of CATEGORIES) {
|
|
23
|
-
if (files.some(category.match)) {
|
|
24
|
-
return category.name;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return 'Other';
|
|
28
|
-
}
|
|
29
|
-
function getGitRange(options) {
|
|
30
|
-
if (options.range) {
|
|
31
|
-
return options.range;
|
|
32
|
-
}
|
|
33
|
-
if (options.lastTag) {
|
|
34
|
-
try {
|
|
35
|
-
const lastTag = execSync('git describe --tags --abbrev=0', {
|
|
36
|
-
encoding: 'utf8',
|
|
37
|
-
}).trim();
|
|
38
|
-
return `${lastTag}..HEAD`;
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
logger.warn('No git tags found, showing all commits');
|
|
42
|
-
return 'HEAD';
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
if (options.since) {
|
|
46
|
-
return `--since="${options.since}"`;
|
|
47
|
-
}
|
|
48
|
-
// Default: last 20 commits
|
|
49
|
-
return '-20';
|
|
50
|
-
}
|
|
51
|
-
function getCommits(rangeArg) {
|
|
52
|
-
const isSinceArg = rangeArg.startsWith('--since');
|
|
53
|
-
const isCountArg = rangeArg.startsWith('-');
|
|
54
|
-
let logCmd;
|
|
55
|
-
if (isSinceArg) {
|
|
56
|
-
logCmd = `git log ${rangeArg} --format="%H %s" --no-merges`;
|
|
57
|
-
}
|
|
58
|
-
else if (isCountArg) {
|
|
59
|
-
logCmd = `git log ${rangeArg} --format="%H %s" --no-merges`;
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
logCmd = `git log ${rangeArg} --format="%H %s" --no-merges`;
|
|
63
|
-
}
|
|
64
|
-
const logOutput = execSync(logCmd, { encoding: 'utf8' }).trim();
|
|
65
|
-
if (!logOutput) {
|
|
66
|
-
return [];
|
|
67
|
-
}
|
|
68
|
-
const entries = [];
|
|
69
|
-
for (const line of logOutput.split(/\r?\n/)) {
|
|
70
|
-
if (!line.trim())
|
|
71
|
-
continue;
|
|
72
|
-
const spaceIdx = line.indexOf(' ');
|
|
73
|
-
const hash = line.slice(0, spaceIdx);
|
|
74
|
-
const message = line.slice(spaceIdx + 1);
|
|
75
|
-
// Get changed files for this commit
|
|
76
|
-
let files;
|
|
77
|
-
try {
|
|
78
|
-
const filesOutput = execSync(`git diff-tree --no-commit-id --name-only -r ${hash}`, {
|
|
79
|
-
encoding: 'utf8',
|
|
80
|
-
}).trim();
|
|
81
|
-
files = filesOutput ? filesOutput.split(/\r?\n/) : [];
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
files = [];
|
|
85
|
-
}
|
|
86
|
-
entries.push({ hash: hash.slice(0, 7), message, files });
|
|
87
|
-
}
|
|
88
|
-
return entries;
|
|
89
|
-
}
|
|
90
|
-
export async function changelogCommand(options = {}) {
|
|
91
|
-
const rangeArg = getGitRange(options);
|
|
92
|
-
const rangeLabel = options.range || (options.lastTag ? 'last tag' : options.since ? `since ${options.since}` : 'recent');
|
|
93
|
-
const commits = getCommits(rangeArg);
|
|
94
|
-
if (commits.length === 0) {
|
|
95
|
-
logger.info('No commits found in the specified range.');
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
// Group by category
|
|
99
|
-
const grouped = new Map();
|
|
100
|
-
for (const commit of commits) {
|
|
101
|
-
const category = categorize(commit.files);
|
|
102
|
-
if (!grouped.has(category)) {
|
|
103
|
-
grouped.set(category, []);
|
|
104
|
-
}
|
|
105
|
-
grouped.get(category).push(commit);
|
|
106
|
-
}
|
|
107
|
-
// Output as markdown
|
|
108
|
-
// eslint-disable-next-line no-console
|
|
109
|
-
console.log(`## Changes (${rangeLabel})\n`);
|
|
110
|
-
// Sort categories: defined order first, then "Other"
|
|
111
|
-
const categoryOrder = CATEGORIES.map((c) => c.name);
|
|
112
|
-
const sortedCategories = [...grouped.keys()].sort((a, b) => {
|
|
113
|
-
const idxA = categoryOrder.indexOf(a);
|
|
114
|
-
const idxB = categoryOrder.indexOf(b);
|
|
115
|
-
if (idxA === -1 && idxB === -1)
|
|
116
|
-
return a.localeCompare(b);
|
|
117
|
-
if (idxA === -1)
|
|
118
|
-
return 1;
|
|
119
|
-
if (idxB === -1)
|
|
120
|
-
return -1;
|
|
121
|
-
return idxA - idxB;
|
|
122
|
-
});
|
|
123
|
-
for (const category of sortedCategories) {
|
|
124
|
-
const categoryCommits = grouped.get(category);
|
|
125
|
-
// eslint-disable-next-line no-console
|
|
126
|
-
console.log(`### ${category} (${categoryCommits.length} commit${categoryCommits.length !== 1 ? 's' : ''})\n`);
|
|
127
|
-
for (const commit of categoryCommits) {
|
|
128
|
-
// eslint-disable-next-line no-console
|
|
129
|
-
console.log(`- ${commit.hash} ${commit.message}`);
|
|
130
|
-
}
|
|
131
|
-
// eslint-disable-next-line no-console
|
|
132
|
-
console.log('');
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
//# sourceMappingURL=changelog.js.map
|