@synergenius/flow-weaver 0.30.5 → 0.30.7

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.
@@ -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.5";
5990
+ VERSION = "0.30.7";
5991
5991
  }
5992
5992
  });
5993
5993
 
@@ -88935,7 +88935,7 @@ function parseIntStrict(value) {
88935
88935
  // src/cli/index.ts
88936
88936
  init_logger();
88937
88937
  init_error_utils();
88938
- var version2 = true ? "0.30.5" : "0.0.0-dev";
88938
+ var version2 = true ? "0.30.7" : "0.0.0-dev";
88939
88939
  var program2 = new Command();
88940
88940
  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", () => {
88941
88941
  logger.banner(version2);
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.30.5";
1
+ export declare const VERSION = "0.30.7";
2
2
  //# sourceMappingURL=generated-version.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Auto-generated by scripts/generate-version.ts — do not edit manually
2
- export const VERSION = '0.30.5';
2
+ export const VERSION = '0.30.7';
3
3
  //# sourceMappingURL=generated-version.js.map
@@ -15,6 +15,8 @@ export type TNpmPackagePort = {
15
15
  type: TDataType;
16
16
  direction: 'INPUT' | 'OUTPUT';
17
17
  scope?: string;
18
+ defaultOrder?: number;
19
+ failure?: boolean;
18
20
  };
19
21
  /**
20
22
  * Node type for npm package functions
@@ -46,12 +48,16 @@ export declare function getTypedPackages(workdir: string, nodeModulesOverride?:
46
48
  }>;
47
49
  };
48
50
  /**
49
- * Get function exports from a package's .d.ts file and return as TNodeType[].
51
+ * Get callable exports from a package's .d.ts file and return as TNodeType[].
52
+ *
53
+ * Uses ts-morph's symbol-based export enumeration to handle all export
54
+ * patterns: declare function, declare const with function types,
55
+ * re-exports from submodules, star exports, etc.
50
56
  *
51
57
  * @param packageName - The npm package name
52
58
  * @param workdir - Directory to start searching from
53
59
  * @param nodeModulesOverride - Optional explicit node_modules path (for testing)
54
- * @returns Array of node types for the package's exported functions
60
+ * @returns Array of node types for the package's callable exports
55
61
  */
56
62
  export declare function getPackageExports(packageName: string, workdir: string, nodeModulesOverride?: string): TNpmNodeType[];
57
63
  //# sourceMappingURL=npm-packages.d.ts.map
@@ -115,6 +115,7 @@ function inferNodeTypeFromDtsFunction(fn, packageName) {
115
115
  reference: 'execute',
116
116
  type: 'STEP',
117
117
  direction: 'INPUT',
118
+ defaultOrder: 0,
118
119
  });
119
120
  // Infer inputs from parameters
120
121
  for (const param of fn.getParameters()) {
@@ -184,6 +185,7 @@ function inferNodeTypeFromDtsFunction(fn, packageName) {
184
185
  reference: 'onSuccess',
185
186
  type: 'STEP',
186
187
  direction: 'OUTPUT',
188
+ defaultOrder: 100,
187
189
  });
188
190
  ports.push({
189
191
  name: 'onFailure',
@@ -191,6 +193,8 @@ function inferNodeTypeFromDtsFunction(fn, packageName) {
191
193
  reference: 'onFailure',
192
194
  type: 'STEP',
193
195
  direction: 'OUTPUT',
196
+ defaultOrder: 101,
197
+ failure: true,
194
198
  });
195
199
  return {
196
200
  name: `npm/${packageName}/${fnName}`,
@@ -205,12 +209,16 @@ function inferNodeTypeFromDtsFunction(fn, packageName) {
205
209
  };
206
210
  }
207
211
  /**
208
- * Get function exports from a package's .d.ts file and return as TNodeType[].
212
+ * Get callable exports from a package's .d.ts file and return as TNodeType[].
213
+ *
214
+ * Uses ts-morph's symbol-based export enumeration to handle all export
215
+ * patterns: declare function, declare const with function types,
216
+ * re-exports from submodules, star exports, etc.
209
217
  *
210
218
  * @param packageName - The npm package name
211
219
  * @param workdir - Directory to start searching from
212
220
  * @param nodeModulesOverride - Optional explicit node_modules path (for testing)
213
- * @returns Array of node types for the package's exported functions
221
+ * @returns Array of node types for the package's callable exports
214
222
  */
215
223
  export function getPackageExports(packageName, workdir, nodeModulesOverride) {
216
224
  const typesPath = resolvePackageTypesPath(packageName, workdir, nodeModulesOverride);
@@ -220,25 +228,194 @@ export function getPackageExports(packageName, workdir, nodeModulesOverride) {
220
228
  try {
221
229
  const project = getSharedProject();
222
230
  const dtsContent = fs.readFileSync(typesPath, 'utf-8');
223
- // Create source file with unique path to avoid conflicts
224
- const virtualPath = `__npm_exports__/${packageName}/${Date.now()}.d.ts`;
225
- const dtsFile = project.createSourceFile(virtualPath, dtsContent, { overwrite: true });
226
- const functions = extractFunctionLikes(dtsFile);
231
+ // Add the .d.ts file and nearby declaration files to the project so
232
+ // ts-morph can resolve re-exports (including `export * from './submodule'`).
233
+ const pkgDir = path.dirname(typesPath);
234
+ const addedFiles = [];
235
+ try {
236
+ const globPattern = path.join(pkgDir, '**/*.d.{ts,cts,mts}');
237
+ for (const file of project.addSourceFilesAtPaths(globPattern)) {
238
+ addedFiles.push(file.getFilePath());
239
+ }
240
+ }
241
+ catch {
242
+ // Glob may fail on some filesystems; fall back to single file
243
+ }
244
+ let dtsFile = project.getSourceFile(typesPath);
245
+ if (!dtsFile) {
246
+ dtsFile = project.addSourceFileAtPath(typesPath);
247
+ }
227
248
  const nodeTypes = [];
228
249
  const seenFunctionNames = new Set();
229
- for (const fn of functions) {
230
- const fnName = fn.getName();
231
- // Skip duplicates (can happen with re-exports or declaration merging)
232
- if (!fnName || seenFunctionNames.has(fnName))
250
+ // First pass: try symbol-based enumeration (handles re-exports, declare const, etc.)
251
+ const fileSymbol = dtsFile.getSymbol();
252
+ if (fileSymbol) {
253
+ for (const exportSymbol of fileSymbol.getExports()) {
254
+ const exportName = exportSymbol.getName();
255
+ if (seenFunctionNames.has(exportName))
256
+ continue;
257
+ // Check if this export is callable (has call signatures)
258
+ const exportType = exportSymbol.getTypeAtLocation(dtsFile);
259
+ const callSignatures = exportType.getCallSignatures();
260
+ if (callSignatures.length === 0)
261
+ continue;
262
+ seenFunctionNames.add(exportName);
263
+ // Use the first call signature to infer ports
264
+ const sig = callSignatures[0];
265
+ const ports = [];
266
+ // Execute input port
267
+ ports.push({
268
+ name: 'execute', defaultLabel: 'Execute', reference: 'execute',
269
+ type: 'STEP', direction: 'INPUT', defaultOrder: 0,
270
+ });
271
+ // Input ports from parameters
272
+ let inputOrder = 1;
273
+ for (const param of sig.getParameters()) {
274
+ const paramName = param.getName();
275
+ const paramType = param.getTypeAtLocation(dtsFile);
276
+ const dataType = inferDataTypeFromTS(paramType.getText());
277
+ ports.push({
278
+ name: paramName, defaultLabel: capitalize(paramName), reference: paramName,
279
+ type: dataType, direction: 'INPUT', defaultOrder: inputOrder++,
280
+ });
281
+ }
282
+ // Output ports from return type
283
+ let returnType = sig.getReturnType();
284
+ const returnText = returnType.getText();
285
+ let isAsync = false;
286
+ if (returnText.startsWith('Promise<')) {
287
+ isAsync = true;
288
+ const typeArgs = returnType.getTypeArguments();
289
+ if (typeArgs.length > 0)
290
+ returnType = typeArgs[0];
291
+ }
292
+ let outputOrder = 0;
293
+ const unwrapped = returnType.getText();
294
+ if (unwrapped !== 'void' && unwrapped !== 'undefined') {
295
+ const isPrimitive = PRIMITIVE_TYPES.has(unwrapped);
296
+ const isArray = unwrapped.endsWith('[]') || unwrapped.startsWith('Array<');
297
+ const properties = returnType.getProperties();
298
+ const isObjectLike = !isPrimitive && !isArray && returnType.isObject() && properties.length > 0;
299
+ if (isObjectLike) {
300
+ for (const prop of properties) {
301
+ const propName = prop.getName();
302
+ if (propName === 'onSuccess' || propName === 'onFailure')
303
+ continue;
304
+ const propType = prop.getTypeAtLocation(dtsFile);
305
+ ports.push({
306
+ name: propName, defaultLabel: capitalize(propName), reference: propName,
307
+ type: inferDataTypeFromTS(propType.getText()), direction: 'OUTPUT', defaultOrder: outputOrder++,
308
+ });
309
+ }
310
+ }
311
+ else {
312
+ ports.push({
313
+ name: 'result', defaultLabel: 'Result', reference: 'result',
314
+ type: inferDataTypeFromTS(unwrapped), direction: 'OUTPUT', defaultOrder: outputOrder++,
315
+ });
316
+ }
317
+ }
318
+ ports.push({
319
+ name: 'onSuccess', defaultLabel: 'On Success', reference: 'onSuccess',
320
+ type: 'STEP', direction: 'OUTPUT', defaultOrder: 100,
321
+ });
322
+ ports.push({
323
+ name: 'onFailure', defaultLabel: 'On Failure', reference: 'onFailure',
324
+ type: 'STEP', direction: 'OUTPUT', defaultOrder: 101, failure: true,
325
+ });
326
+ nodeTypes.push({
327
+ name: `npm/${packageName}/${exportName}`,
328
+ variant: 'FUNCTION',
329
+ category: 'NPM Packages',
330
+ function: exportName,
331
+ label: exportName,
332
+ importSource: packageName,
333
+ ports,
334
+ synchronicity: isAsync ? 'ASYNC' : 'SYNC',
335
+ description: `${exportName} from ${packageName}`,
336
+ });
337
+ }
338
+ }
339
+ // Follow star re-exports (`export * from './submodule'`) which the symbol
340
+ // API surfaces as a single __export pseudo-symbol instead of individual names.
341
+ for (const exportDecl of dtsFile.getExportDeclarations()) {
342
+ if (!exportDecl.isNamespaceExport())
233
343
  continue;
234
- seenFunctionNames.add(fnName);
235
- const nodeType = inferNodeTypeFromDtsFunction(fn, packageName);
236
- if (nodeType) {
237
- nodeTypes.push(nodeType);
344
+ const targetFile = exportDecl.getModuleSpecifierSourceFile();
345
+ if (!targetFile)
346
+ continue;
347
+ const targetSymbol = targetFile.getSymbol();
348
+ if (!targetSymbol)
349
+ continue;
350
+ for (const exportSymbol of targetSymbol.getExports()) {
351
+ const exportName = exportSymbol.getName();
352
+ if (seenFunctionNames.has(exportName))
353
+ continue;
354
+ const exportType = exportSymbol.getTypeAtLocation(targetFile);
355
+ const callSignatures = exportType.getCallSignatures();
356
+ if (callSignatures.length === 0)
357
+ continue;
358
+ seenFunctionNames.add(exportName);
359
+ const sig = callSignatures[0];
360
+ const ports = [];
361
+ ports.push({ name: 'execute', defaultLabel: 'Execute', reference: 'execute', type: 'STEP', direction: 'INPUT', defaultOrder: 0 });
362
+ let starInputOrder = 1;
363
+ for (const param of sig.getParameters()) {
364
+ const paramName = param.getName();
365
+ const paramType = param.getTypeAtLocation(targetFile);
366
+ ports.push({
367
+ name: paramName, defaultLabel: capitalize(paramName), reference: paramName,
368
+ type: inferDataTypeFromTS(paramType.getText()), direction: 'INPUT', defaultOrder: starInputOrder++,
369
+ });
370
+ }
371
+ let returnType = sig.getReturnType();
372
+ const returnText = returnType.getText();
373
+ let isAsync = false;
374
+ if (returnText.startsWith('Promise<')) {
375
+ isAsync = true;
376
+ const typeArgs = returnType.getTypeArguments();
377
+ if (typeArgs.length > 0)
378
+ returnType = typeArgs[0];
379
+ }
380
+ const unwrapped = returnType.getText();
381
+ if (unwrapped !== 'void' && unwrapped !== 'undefined') {
382
+ ports.push({ name: 'result', defaultLabel: 'Result', reference: 'result', type: inferDataTypeFromTS(unwrapped), direction: 'OUTPUT', defaultOrder: 0 });
383
+ }
384
+ ports.push({ name: 'onSuccess', defaultLabel: 'On Success', reference: 'onSuccess', type: 'STEP', direction: 'OUTPUT', defaultOrder: 100 });
385
+ ports.push({ name: 'onFailure', defaultLabel: 'On Failure', reference: 'onFailure', type: 'STEP', direction: 'OUTPUT', defaultOrder: 101, failure: true });
386
+ nodeTypes.push({
387
+ name: `npm/${packageName}/${exportName}`,
388
+ variant: 'FUNCTION',
389
+ category: 'NPM Packages',
390
+ function: exportName,
391
+ label: exportName,
392
+ importSource: packageName,
393
+ ports,
394
+ synchronicity: isAsync ? 'ASYNC' : 'SYNC',
395
+ description: `${exportName} from ${packageName}`,
396
+ });
238
397
  }
239
398
  }
240
- // Clean up the temporary source file
241
- project.removeSourceFile(dtsFile);
399
+ // Fallback: if symbol-based enumeration found nothing, try extractFunctionLikes
400
+ // (handles edge cases where symbols aren't available)
401
+ if (nodeTypes.length === 0) {
402
+ const functions = extractFunctionLikes(dtsFile);
403
+ for (const fn of functions) {
404
+ const fnName = fn.getName();
405
+ if (!fnName || seenFunctionNames.has(fnName))
406
+ continue;
407
+ seenFunctionNames.add(fnName);
408
+ const nodeType = inferNodeTypeFromDtsFunction(fn, packageName);
409
+ if (nodeType)
410
+ nodeTypes.push(nodeType);
411
+ }
412
+ }
413
+ // Clean up added source files to avoid project bloat
414
+ for (const filePath of addedFiles) {
415
+ const sf = project.getSourceFile(filePath);
416
+ if (sf)
417
+ project.removeSourceFile(sf);
418
+ }
242
419
  return nodeTypes;
243
420
  }
244
421
  catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synergenius/flow-weaver",
3
- "version": "0.30.5",
3
+ "version": "0.30.7",
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",