deepline 0.1.123 → 0.1.124

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.
@@ -211,6 +211,93 @@ function stripCommentsToSpaces(source) {
211
211
  (match, prefix) => prefix + " ".repeat(Math.max(0, match.length - prefix.length))
212
212
  );
213
213
  }
214
+ function previousSignificantToken(source, index) {
215
+ let cursor = index - 1;
216
+ while (cursor >= 0 && /\s/.test(source[cursor])) cursor -= 1;
217
+ if (cursor < 0) return "";
218
+ const char = source[cursor];
219
+ if (!/[A-Za-z0-9_$]/.test(char)) return char;
220
+ let start = cursor;
221
+ while (start > 0 && /[A-Za-z0-9_$]/.test(source[start - 1])) start -= 1;
222
+ return source.slice(start, cursor + 1);
223
+ }
224
+ function canStartRegexLiteral(source, slashIndex) {
225
+ const token = previousSignificantToken(source, slashIndex);
226
+ return !token || token === "return" || token === "throw" || token === "case" || token === "delete" || token === "typeof" || token === "void" || token === "instanceof" || /^(?:[({[=,:;!&|?+\-*~^<>%]|\.\.\.)$/.test(token);
227
+ }
228
+ function maskSourceForStructure(source) {
229
+ const chars = source.split("");
230
+ const maskRange = (start, end) => {
231
+ for (let cursor = start; cursor < end; cursor += 1) {
232
+ if (chars[cursor] !== "\n") chars[cursor] = " ";
233
+ }
234
+ };
235
+ for (let index = 0; index < source.length; index += 1) {
236
+ const char = source[index];
237
+ const next = source[index + 1];
238
+ if (char === "/" && next === "/") {
239
+ let end = index + 2;
240
+ while (end < source.length && source[end] !== "\n") end += 1;
241
+ maskRange(index, end);
242
+ index = end;
243
+ continue;
244
+ }
245
+ if (char === "/" && next === "*") {
246
+ const close = source.indexOf("*/", index + 2);
247
+ const end = close >= 0 ? close + 2 : source.length;
248
+ maskRange(index, end);
249
+ index = end - 1;
250
+ continue;
251
+ }
252
+ if (char === '"' || char === "'" || char === "`") {
253
+ const quote = char;
254
+ let end = index + 1;
255
+ let escaped = false;
256
+ while (end < source.length) {
257
+ const current = source[end];
258
+ if (escaped) {
259
+ escaped = false;
260
+ } else if (current === "\\") {
261
+ escaped = true;
262
+ } else if (current === quote) {
263
+ end += 1;
264
+ break;
265
+ }
266
+ end += 1;
267
+ }
268
+ maskRange(index, end);
269
+ index = end - 1;
270
+ continue;
271
+ }
272
+ if (char === "/" && canStartRegexLiteral(source, index)) {
273
+ let end = index + 1;
274
+ let escaped = false;
275
+ let inCharacterClass = false;
276
+ while (end < source.length) {
277
+ const current = source[end];
278
+ if (escaped) {
279
+ escaped = false;
280
+ } else if (current === "\\") {
281
+ escaped = true;
282
+ } else if (current === "[") {
283
+ inCharacterClass = true;
284
+ } else if (current === "]") {
285
+ inCharacterClass = false;
286
+ } else if (current === "/" && !inCharacterClass) {
287
+ end += 1;
288
+ while (/[A-Za-z]/.test(source[end] ?? "")) end += 1;
289
+ break;
290
+ } else if (current === "\n") {
291
+ break;
292
+ }
293
+ end += 1;
294
+ }
295
+ maskRange(index, end);
296
+ index = end - 1;
297
+ }
298
+ }
299
+ return chars.join("");
300
+ }
214
301
  function lineAndColumnAt(source, index) {
215
302
  const prefix = source.slice(0, index);
216
303
  const lines = prefix.split("\n");
@@ -280,9 +367,13 @@ function findSourceImportReferences(sourceCode) {
280
367
  function unquoteStringLiteral(literal) {
281
368
  const trimmed = literal.trim();
282
369
  const quote = trimmed[0];
283
- if (quote !== '"' && quote !== "'" || trimmed[trimmed.length - 1] !== quote) {
370
+ if (quote !== '"' && quote !== "'" && quote !== "`" || trimmed[trimmed.length - 1] !== quote) {
284
371
  return null;
285
372
  }
373
+ if (quote === "`") {
374
+ const value = trimmed.slice(1, -1);
375
+ return value.includes("${") ? null : value;
376
+ }
286
377
  try {
287
378
  return JSON.parse(
288
379
  quote === '"' ? trimmed : `"${trimmed.slice(1, -1).replace(/"/g, '\\"')}"`
@@ -292,25 +383,10 @@ function unquoteStringLiteral(literal) {
292
383
  }
293
384
  }
294
385
  function findMatchingBrace(source, openIndex) {
386
+ const structuralSource = maskSourceForStructure(source);
295
387
  let depth = 0;
296
- let quote = null;
297
- let escaped = false;
298
- for (let index = openIndex; index < source.length; index += 1) {
299
- const char = source[index];
300
- if (quote) {
301
- if (escaped) {
302
- escaped = false;
303
- } else if (char === "\\") {
304
- escaped = true;
305
- } else if (char === quote) {
306
- quote = null;
307
- }
308
- continue;
309
- }
310
- if (char === '"' || char === "'" || char === "`") {
311
- quote = char;
312
- continue;
313
- }
388
+ for (let index = openIndex; index < structuralSource.length; index += 1) {
389
+ const char = structuralSource[index];
314
390
  if (char === "{") depth += 1;
315
391
  if (char === "}") {
316
392
  depth -= 1;
@@ -319,35 +395,198 @@ function findMatchingBrace(source, openIndex) {
319
395
  }
320
396
  return -1;
321
397
  }
398
+ function findMatchingParen(source, openIndex) {
399
+ const structuralSource = maskSourceForStructure(source);
400
+ let depth = 0;
401
+ for (let index = openIndex; index < structuralSource.length; index += 1) {
402
+ const char = structuralSource[index];
403
+ if (char === "(") depth += 1;
404
+ if (char === ")") {
405
+ depth -= 1;
406
+ if (depth === 0) return index;
407
+ }
408
+ }
409
+ return -1;
410
+ }
411
+ function splitTopLevelArguments(source) {
412
+ const args = [];
413
+ const structuralSource = maskSourceForStructure(source);
414
+ let start = 0;
415
+ let parenDepth = 0;
416
+ let braceDepth = 0;
417
+ let bracketDepth = 0;
418
+ for (let index = 0; index < structuralSource.length; index += 1) {
419
+ const char = structuralSource[index];
420
+ if (char === "(") parenDepth += 1;
421
+ if (char === ")") parenDepth -= 1;
422
+ if (char === "{") braceDepth += 1;
423
+ if (char === "}") braceDepth -= 1;
424
+ if (char === "[") bracketDepth += 1;
425
+ if (char === "]") bracketDepth -= 1;
426
+ if (char === "," && parenDepth === 0 && braceDepth === 0 && bracketDepth === 0) {
427
+ args.push(source.slice(start, index).trim());
428
+ start = index + 1;
429
+ }
430
+ }
431
+ const finalArg = source.slice(start).trim();
432
+ if (finalArg) args.push(finalArg);
433
+ return args;
434
+ }
435
+ function extractStringProperty(objectSource, propertyName) {
436
+ for (const entry of splitTopLevelArguments(objectSource)) {
437
+ const structuralEntry = stripCommentsToSpaces(entry).trim();
438
+ const match = structuralEntry.match(
439
+ new RegExp(
440
+ `^(?:${propertyName}|['"]${propertyName}['"])\\s*:\\s*((['"\`])(?:\\\\.|(?!\\2)[\\s\\S])*\\2)\\s*$`
441
+ )
442
+ );
443
+ const value = match?.[1] ? unquoteStringLiteral(match[1]) : null;
444
+ if (value?.trim()) return value.trim();
445
+ }
446
+ return null;
447
+ }
322
448
  function extractDefinedPlayName(sourceCode) {
323
- const source = stripCommentsToSpaces(sourceCode);
449
+ for (const call of findDefinePlayCalls(sourceCode)) {
450
+ const name = nameFromDefinePlayArguments(sourceCode, call.arguments);
451
+ if (name) return name;
452
+ }
453
+ return null;
454
+ }
455
+ function extractDefinedPlayNameForExport(sourceCode, exportName) {
456
+ return findDefinedPlayMetadata(
457
+ sourceCode,
458
+ exportName,
459
+ nameFromDefinePlayArguments
460
+ );
461
+ }
462
+ function extractDefinedPlayDescription(sourceCode) {
463
+ return findDefinedPlayMetadata(
464
+ sourceCode,
465
+ null,
466
+ descriptionFromDefinePlayArguments
467
+ );
468
+ }
469
+ function extractDefinedPlayDescriptionForExport(sourceCode, exportName) {
470
+ return findDefinedPlayMetadata(
471
+ sourceCode,
472
+ exportName,
473
+ descriptionFromDefinePlayArguments
474
+ );
475
+ }
476
+ function findDefinedPlayMetadata(sourceCode, exportName, getMetadata) {
477
+ const resolvedExportName = exportName === "default" ? findDefaultExportIdentifier(sourceCode) ?? exportName : exportName;
478
+ for (const call of findDefinePlayCalls(sourceCode)) {
479
+ if (resolvedExportName && call.exportName !== resolvedExportName) {
480
+ continue;
481
+ }
482
+ const value = getMetadata(sourceCode, call.arguments);
483
+ if (value) return value;
484
+ }
485
+ return null;
486
+ }
487
+ function findDefinePlayCalls(sourceCode) {
488
+ const source = maskSourceForStructure(sourceCode);
324
489
  const callPattern = /(?:\b[A-Za-z_$][\w$]*\s*\.\s*)?\b(?:definePlay|defineWorkflow)\s*\(/g;
490
+ const calls = [];
325
491
  for (const match of source.matchAll(callPattern)) {
326
- const openParen = match.index + match[0].length - 1;
327
- const firstArgStart = openParen + 1;
328
- const firstNonSpace = source.slice(firstArgStart).search(/\S/);
329
- if (firstNonSpace < 0) continue;
330
- const argIndex = firstArgStart + firstNonSpace;
331
- const quote = source[argIndex];
332
- if (quote === '"' || quote === "'") {
333
- const literalMatch = source.slice(argIndex).match(/^(['"])(?:\\.|(?!\1)[\s\S])*\1/);
334
- const value = literalMatch ? unquoteStringLiteral(literalMatch[0]) : null;
335
- if (value?.trim()) return value.trim();
336
- }
337
- if (quote === "{") {
338
- const closeBrace = findMatchingBrace(source, argIndex);
339
- if (closeBrace < 0) continue;
340
- const objectSource = source.slice(argIndex + 1, closeBrace);
341
- const idMatch = objectSource.match(
342
- /(?:^|[,{\s])(?:id|['"]id['"])\s*:\s*(['"])([\s\S]*?)\1/
343
- );
344
- if (idMatch?.[2]?.trim()) {
345
- return idMatch[2].trim();
346
- }
347
- }
492
+ const callStart = match.index;
493
+ const openParen = callStart + match[0].length - 1;
494
+ const closeParen = findMatchingParen(sourceCode, openParen);
495
+ if (closeParen < 0) continue;
496
+ calls.push({
497
+ arguments: splitTopLevelArguments(
498
+ sourceCode.slice(openParen + 1, closeParen)
499
+ ),
500
+ exportName: exportNameForDefinePlayCall(sourceCode, callStart)
501
+ });
502
+ }
503
+ return calls;
504
+ }
505
+ function findDefaultExportIdentifier(sourceCode) {
506
+ const source = maskSourceForStructure(sourceCode);
507
+ const pattern = /\bexport\s+default\s+([A-Za-z_$][\w$]*)/g;
508
+ for (const match of source.matchAll(pattern)) {
509
+ const afterIdentifier = match.index + match[0].length;
510
+ const nextNonSpace = source.slice(afterIdentifier).match(/\S/)?.[0] ?? "";
511
+ if (nextNonSpace !== "(") return match[1] ?? null;
512
+ }
513
+ return null;
514
+ }
515
+ function nameFromDefinePlayArguments(sourceCode, args) {
516
+ const firstArg = args[0]?.trim();
517
+ if (!firstArg) return null;
518
+ if (/^(['"`])/.test(firstArg))
519
+ return unquoteStringLiteral(firstArg)?.trim() ?? null;
520
+ const objectSource = objectLiteralBodyFromArgument(sourceCode, firstArg);
521
+ if (objectSource) {
522
+ return extractStringProperty(objectSource, "id");
523
+ }
524
+ return null;
525
+ }
526
+ function descriptionFromDefinePlayArguments(sourceCode, args) {
527
+ const firstArgDescription = descriptionFromDefinePlayArgument(
528
+ sourceCode,
529
+ args[0]
530
+ );
531
+ if (firstArgDescription) return firstArgDescription;
532
+ for (let index = args.length - 1; index >= 2; index -= 1) {
533
+ const description = descriptionFromDefinePlayArgument(
534
+ sourceCode,
535
+ args[index]
536
+ );
537
+ if (description) return description;
348
538
  }
349
539
  return null;
350
540
  }
541
+ function descriptionFromDefinePlayArgument(sourceCode, arg) {
542
+ const trimmed = arg?.trim();
543
+ if (!trimmed) return null;
544
+ const objectSource = objectLiteralBodyFromArgument(sourceCode, trimmed);
545
+ if (!objectSource) return null;
546
+ return extractStringProperty(objectSource, "description");
547
+ }
548
+ function objectLiteralBodyFromArgument(sourceCode, arg) {
549
+ const trimmed = arg.trim();
550
+ if (trimmed.startsWith("{")) {
551
+ const closeBrace = findMatchingBrace(trimmed, 0);
552
+ return closeBrace >= 0 ? trimmed.slice(1, closeBrace) : trimmed.slice(1);
553
+ }
554
+ if (!/^[A-Za-z_$][\w$]*$/.test(trimmed)) return null;
555
+ return findTopLevelObjectLiteralBody(sourceCode, trimmed);
556
+ }
557
+ function escapeRegExp(value) {
558
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
559
+ }
560
+ function findTopLevelObjectLiteralBody(sourceCode, identifier) {
561
+ const source = maskSourceForStructure(sourceCode);
562
+ const pattern = new RegExp(
563
+ `(?:^|[;\\n])\\s*(?:export\\s+)?(?:const|let|var)\\s+${escapeRegExp(
564
+ identifier
565
+ )}(?:\\s*:[^=;]+)?\\s*=\\s*{`,
566
+ "g"
567
+ );
568
+ for (const match of source.matchAll(pattern)) {
569
+ const openBrace = source.indexOf("{", match.index);
570
+ if (openBrace < 0) continue;
571
+ const closeBrace = findMatchingBrace(sourceCode, openBrace);
572
+ if (closeBrace < 0) continue;
573
+ return sourceCode.slice(openBrace + 1, closeBrace);
574
+ }
575
+ return null;
576
+ }
577
+ function exportNameForDefinePlayCall(sourceCode, callStart) {
578
+ const source = maskSourceForStructure(sourceCode);
579
+ const structuralPrefix = source.slice(Math.max(0, callStart - 500), callStart).trimEnd();
580
+ if (/\bexport\s+default\s*$/.test(structuralPrefix)) return "default";
581
+ const variableMatch = structuralPrefix.match(
582
+ /\bexport\s+(?:declare\s+)?(?:const|let|var)\s+([A-Za-z_$][\w$]*)(?:\s*:[^=;]+)?\s*=\s*$/
583
+ );
584
+ if (variableMatch?.[1]) return variableMatch[1];
585
+ const localVariableMatch = structuralPrefix.match(
586
+ /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)(?:\s*:[^=;]+)?\s*=\s*$/
587
+ );
588
+ return localVariableMatch?.[1] ?? null;
589
+ }
351
590
  function canonicalizeRootPlayNameForWorkersRuntimeHash(sourceCode) {
352
591
  const source = stripCommentsToSpaces(sourceCode);
353
592
  const callPattern = /(?:\b[A-Za-z_$][\w$]*\s*\.\s*)?\b(?:definePlay|defineWorkflow)\s*\(/g;
@@ -748,7 +987,7 @@ function resolvePackageImport(specifier, fromFile, adapter) {
748
987
  version: readPackageVersionFromPackageJson(packageJsonPath, packageName)
749
988
  };
750
989
  }
751
- async function analyzeSourceGraph(entryFile, adapter) {
990
+ async function analyzeSourceGraph(entryFile, adapter, exportName) {
752
991
  const absoluteEntryFile = await normalizeLocalPath(entryFile);
753
992
  const workspace = createPlayWorkspace(absoluteEntryFile);
754
993
  const localFiles = /* @__PURE__ */ new Map();
@@ -849,7 +1088,8 @@ async function analyzeSourceGraph(entryFile, adapter) {
849
1088
  })).sort((left, right) => left.filePath.localeCompare(right.filePath))
850
1089
  })
851
1090
  );
852
- const playName = extractDefinedPlayName(sourceCode);
1091
+ const playName = extractDefinedPlayNameForExport(sourceCode, exportName) ?? (exportName === "default" ? extractDefinedPlayName(sourceCode) : null);
1092
+ const playDescription = extractDefinedPlayDescriptionForExport(sourceCode, exportName) ?? (exportName === "default" ? extractDefinedPlayDescription(sourceCode) : null);
853
1093
  return {
854
1094
  sourceCode,
855
1095
  sourceFiles: Object.fromEntries(
@@ -865,6 +1105,7 @@ async function analyzeSourceGraph(entryFile, adapter) {
865
1105
  packages: [...packages.entries()].map(([name, version]) => ({ name, version })).sort((left, right) => left.name.localeCompare(right.name))
866
1106
  },
867
1107
  playName,
1108
+ playDescription,
868
1109
  importedPlayDependencies: [...importedPlayDependencies.values()].sort(
869
1110
  (left, right) => left.filePath.localeCompare(right.filePath)
870
1111
  )
@@ -1144,7 +1385,11 @@ async function bundlePlayFile(filePath, options) {
1144
1385
  const absolutePath = await normalizeLocalPath(filePath);
1145
1386
  adapter.warnAboutNonDevelopmentBundling?.(absolutePath);
1146
1387
  try {
1147
- const analysis = await analyzeSourceGraph(absolutePath, adapter);
1388
+ const analysis = await analyzeSourceGraph(
1389
+ absolutePath,
1390
+ adapter,
1391
+ exportName
1392
+ );
1148
1393
  analysis.graphHash = target === PLAY_ARTIFACT_KINDS.esmWorkers ? buildWorkersRuntimeGraphHash({
1149
1394
  analysis,
1150
1395
  entryFile: absolutePath,
@@ -1216,6 +1461,7 @@ workers-harness:${harnessFingerprint}`
1216
1461
  sourceFiles: analysis.sourceFiles,
1217
1462
  filePath: absolutePath,
1218
1463
  playName: analysis.playName,
1464
+ playDescription: analysis.playDescription,
1219
1465
  packagedFiles: discoveredFiles.files,
1220
1466
  unresolvedFileReferences: discoveredFiles.unresolved,
1221
1467
  importedPlayDependencies: analysis.importedPlayDependencies
@@ -1282,6 +1528,7 @@ workers-harness:${harnessFingerprint}`
1282
1528
  sourceFiles: analysis.sourceFiles,
1283
1529
  filePath: absolutePath,
1284
1530
  playName: analysis.playName,
1531
+ playDescription: analysis.playDescription,
1285
1532
  packagedFiles: discoveredFiles.files,
1286
1533
  unresolvedFileReferences: discoveredFiles.unresolved,
1287
1534
  importedPlayDependencies: analysis.importedPlayDependencies
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.123",
3
+ "version": "0.1.124",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {