quidproquo-actionprocessor-node 0.1.7 → 0.1.8
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/lib/commonjs/actionProcessor/core/inlineFunction/getInlineFunctionExecuteActionProcessor.js +4 -0
- package/lib/commonjs/actionProcessor/core/inlineFunction/getInlineFunctionExecuteActionProcessor.js.map +1 -1
- package/lib/commonjs/dynamicActionProcessor/file/getFileDeleteActionProcessor.js +10 -2
- package/lib/commonjs/dynamicActionProcessor/file/getFileDeleteActionProcessor.js.map +1 -1
- package/lib/commonjs/dynamicActionProcessor/file/getFileExistsActionProcessor.js +7 -3
- package/lib/commonjs/dynamicActionProcessor/file/getFileExistsActionProcessor.js.map +1 -1
- package/lib/commonjs/dynamicActionProcessor/file/getFileGenerateTemporarySecureUrlActionProcessor.js +13 -3
- package/lib/commonjs/dynamicActionProcessor/file/getFileGenerateTemporarySecureUrlActionProcessor.js.map +1 -1
- package/lib/commonjs/dynamicActionProcessor/file/getFileGenerateTemporaryUploadSecureUrlActionProcessor.js +13 -3
- package/lib/commonjs/dynamicActionProcessor/file/getFileGenerateTemporaryUploadSecureUrlActionProcessor.js.map +1 -1
- package/lib/commonjs/dynamicActionProcessor/file/getFileListDirectoryActionProcessor.js +3 -2
- package/lib/commonjs/dynamicActionProcessor/file/getFileListDirectoryActionProcessor.js.map +1 -1
- package/lib/commonjs/dynamicActionProcessor/file/getFileReadBinaryContentsActionProcessor.js +3 -2
- package/lib/commonjs/dynamicActionProcessor/file/getFileReadBinaryContentsActionProcessor.js.map +1 -1
- package/lib/commonjs/dynamicActionProcessor/file/getFileReadObjectJsonActionProcessor.js +5 -4
- package/lib/commonjs/dynamicActionProcessor/file/getFileReadObjectJsonActionProcessor.js.map +1 -1
- package/lib/commonjs/dynamicActionProcessor/file/getFileReadTextContentsActionProcessor.js +4 -3
- package/lib/commonjs/dynamicActionProcessor/file/getFileReadTextContentsActionProcessor.js.map +1 -1
- package/lib/commonjs/dynamicActionProcessor/file/getFileStreamOpenActionProcessor.js +3 -2
- package/lib/commonjs/dynamicActionProcessor/file/getFileStreamOpenActionProcessor.js.map +1 -1
- package/lib/commonjs/dynamicActionProcessor/file/getFileWriteBinaryContentsActionProcessor.js +3 -2
- package/lib/commonjs/dynamicActionProcessor/file/getFileWriteBinaryContentsActionProcessor.js.map +1 -1
- package/lib/commonjs/dynamicActionProcessor/file/getFileWriteObjectJsonActionProcessor.js +3 -2
- package/lib/commonjs/dynamicActionProcessor/file/getFileWriteObjectJsonActionProcessor.js.map +1 -1
- package/lib/commonjs/dynamicActionProcessor/file/getFileWriteTextContentsActionProcessor.js +3 -2
- package/lib/commonjs/dynamicActionProcessor/file/getFileWriteTextContentsActionProcessor.js.map +1 -1
- package/lib/commonjs/dynamicActionProcessor/file/utils.d.ts +1 -1
- package/lib/commonjs/dynamicActionProcessor/file/utils.js +9 -2
- package/lib/commonjs/dynamicActionProcessor/file/utils.js.map +1 -1
- package/lib/commonjs/traceStoryExecution/getSystemTraceStoryActionProcessor.d.ts +3 -2
- package/lib/commonjs/traceStoryExecution/getSystemTraceStoryActionProcessor.js +4 -3
- package/lib/commonjs/traceStoryExecution/getSystemTraceStoryActionProcessor.js.map +1 -1
- package/lib/commonjs/traceStoryExecution/index.d.ts +1 -0
- package/lib/commonjs/traceStoryExecution/index.js +1 -0
- package/lib/commonjs/traceStoryExecution/index.js.map +1 -1
- package/lib/commonjs/traceStoryExecution/resolveSourceMaps.d.ts +2 -1
- package/lib/commonjs/traceStoryExecution/resolveSourceMaps.js +24 -3
- package/lib/commonjs/traceStoryExecution/resolveSourceMaps.js.map +1 -1
- package/lib/commonjs/traceStoryExecution/traceStoryExecution.d.ts +1 -0
- package/lib/commonjs/traceStoryExecution/traceStoryExecution.js +1 -1
- package/lib/commonjs/traceStoryExecution/traceStoryExecution.js.map +1 -1
- package/lib/esm/actionProcessor/core/inlineFunction/getInlineFunctionExecuteActionProcessor.js +4 -0
- package/lib/esm/actionProcessor/core/inlineFunction/getInlineFunctionExecuteActionProcessor.js.map +1 -1
- package/lib/esm/dynamicActionProcessor/file/getFileDeleteActionProcessor.js +10 -2
- package/lib/esm/dynamicActionProcessor/file/getFileDeleteActionProcessor.js.map +1 -1
- package/lib/esm/dynamicActionProcessor/file/getFileExistsActionProcessor.js +8 -4
- package/lib/esm/dynamicActionProcessor/file/getFileExistsActionProcessor.js.map +1 -1
- package/lib/esm/dynamicActionProcessor/file/getFileGenerateTemporarySecureUrlActionProcessor.js +14 -4
- package/lib/esm/dynamicActionProcessor/file/getFileGenerateTemporarySecureUrlActionProcessor.js.map +1 -1
- package/lib/esm/dynamicActionProcessor/file/getFileGenerateTemporaryUploadSecureUrlActionProcessor.js +14 -4
- package/lib/esm/dynamicActionProcessor/file/getFileGenerateTemporaryUploadSecureUrlActionProcessor.js.map +1 -1
- package/lib/esm/dynamicActionProcessor/file/getFileListDirectoryActionProcessor.js +3 -2
- package/lib/esm/dynamicActionProcessor/file/getFileListDirectoryActionProcessor.js.map +1 -1
- package/lib/esm/dynamicActionProcessor/file/getFileReadBinaryContentsActionProcessor.js +3 -2
- package/lib/esm/dynamicActionProcessor/file/getFileReadBinaryContentsActionProcessor.js.map +1 -1
- package/lib/esm/dynamicActionProcessor/file/getFileReadObjectJsonActionProcessor.js +6 -5
- package/lib/esm/dynamicActionProcessor/file/getFileReadObjectJsonActionProcessor.js.map +1 -1
- package/lib/esm/dynamicActionProcessor/file/getFileReadTextContentsActionProcessor.js +5 -4
- package/lib/esm/dynamicActionProcessor/file/getFileReadTextContentsActionProcessor.js.map +1 -1
- package/lib/esm/dynamicActionProcessor/file/getFileStreamOpenActionProcessor.js +3 -2
- package/lib/esm/dynamicActionProcessor/file/getFileStreamOpenActionProcessor.js.map +1 -1
- package/lib/esm/dynamicActionProcessor/file/getFileWriteBinaryContentsActionProcessor.js +3 -2
- package/lib/esm/dynamicActionProcessor/file/getFileWriteBinaryContentsActionProcessor.js.map +1 -1
- package/lib/esm/dynamicActionProcessor/file/getFileWriteObjectJsonActionProcessor.js +3 -2
- package/lib/esm/dynamicActionProcessor/file/getFileWriteObjectJsonActionProcessor.js.map +1 -1
- package/lib/esm/dynamicActionProcessor/file/getFileWriteTextContentsActionProcessor.js +3 -2
- package/lib/esm/dynamicActionProcessor/file/getFileWriteTextContentsActionProcessor.js.map +1 -1
- package/lib/esm/dynamicActionProcessor/file/utils.d.ts +1 -1
- package/lib/esm/dynamicActionProcessor/file/utils.js +10 -3
- package/lib/esm/dynamicActionProcessor/file/utils.js.map +1 -1
- package/lib/esm/traceStoryExecution/getSystemTraceStoryActionProcessor.d.ts +3 -2
- package/lib/esm/traceStoryExecution/getSystemTraceStoryActionProcessor.js +4 -3
- package/lib/esm/traceStoryExecution/getSystemTraceStoryActionProcessor.js.map +1 -1
- package/lib/esm/traceStoryExecution/index.d.ts +1 -0
- package/lib/esm/traceStoryExecution/index.js +1 -0
- package/lib/esm/traceStoryExecution/index.js.map +1 -1
- package/lib/esm/traceStoryExecution/resolveSourceMaps.d.ts +2 -1
- package/lib/esm/traceStoryExecution/resolveSourceMaps.js +22 -2
- package/lib/esm/traceStoryExecution/resolveSourceMaps.js.map +1 -1
- package/lib/esm/traceStoryExecution/traceStoryExecution.d.ts +1 -0
- package/lib/esm/traceStoryExecution/traceStoryExecution.js +1 -1
- package/lib/esm/traceStoryExecution/traceStoryExecution.js.map +1 -1
- package/package.json +6 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveSourceMaps.js","sourceRoot":"","sources":["../../../src/traceStoryExecution/resolveSourceMaps.ts"],"names":[],"mappings":"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","sourcesContent":["// Post-processing: map the controller's raw steps (generated script positions) back to\n// original sources via the .map files sitting next to the traced scripts on disk —\n// the same files the federated store syncs to /tmp alongside the code. When a map\n// carries sourcesContent (the federated remote build embeds it), the original source\n// text is embedded in the trace so viewers need no access to the repo.\n\nimport { QpqExecutionTraceSource, QpqExecutionTraceStep, QpqExecutionTraceValue } from 'quidproquo-core';\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\nimport { originalPositionFor, sourceContentFor, TraceMap } from '@jridgewell/trace-mapping';\n\ninterface RawTraceStep {\n scriptId: string;\n line: number; // 0-based (CDP)\n column: number;\n functionName: string;\n locals: Record<string, QpqExecutionTraceValue>;\n returnValue?: QpqExecutionTraceValue;\n}\n\nconst scriptUrlToPath = (scriptUrl: string): string => (scriptUrl.startsWith('file://') ? fileURLToPath(scriptUrl) : scriptUrl);\n\n// The LAST sourceMappingURL comment wins (bundles can contain earlier ones from inlined\n// third-party code).\nconst findSourceMappingUrl = (scriptText: string): string | null => {\n const matches = scriptText.match(/\\/\\/[#@] sourceMappingURL=(\\S+)/g);\n if (!matches || matches.length === 0) return null;\n return matches[matches.length - 1].replace(/\\/\\/[#@] sourceMappingURL=/, '');\n};\n\nconst loadTraceMap = (scriptPath: string): TraceMap | null => {\n try {\n const scriptText = fs.readFileSync(scriptPath, 'utf8');\n const sourceMappingUrl = findSourceMappingUrl(scriptText);\n if (!sourceMappingUrl) return null;\n\n if (sourceMappingUrl.startsWith('data:')) {\n const base64Match = sourceMappingUrl.match(/^data:application\\/json[^,]*;base64,(.*)$/);\n const json = base64Match\n ? Buffer.from(base64Match[1], 'base64').toString('utf8')\n : decodeURIComponent(sourceMappingUrl.replace(/^data:[^,]*,/, ''));\n return new TraceMap(json);\n }\n\n const mapPath = path.resolve(path.dirname(scriptPath), sourceMappingUrl);\n return new TraceMap(fs.readFileSync(mapPath, 'utf8'));\n } catch {\n // No map is a degraded trace, not a failure — generated positions still tell the story\n return null;\n }\n};\n\n// Which candidate breakpoint positions land in the service's OWN code — answers the\n// controller worker's filterLocations request when onlyOwnCode tracing is on (the eval\n// worker can't load trace-mapping itself). Positions mapping into node_modules\n// (framework/deps) or not mapping at all (webpack runtime glue) are dropped. No map\n// means the bundle can't be classified — everything stays traced.\nexport const filterOwnCodeLocations = <TLocation extends { lineNumber: number; columnNumber?: number }>(\n scriptUrl: string,\n locations: TLocation[],\n): TLocation[] => {\n const traceMap = scriptUrl ? loadTraceMap(scriptUrlToPath(scriptUrl)) : null;\n if (!traceMap) {\n return locations;\n }\n\n return locations.filter((location) => {\n const original = originalPositionFor(traceMap, { line: location.lineNumber + 1, column: location.columnNumber ?? 0 });\n return !!original.source && !original.source.includes('node_modules');\n });\n};\n\nexport interface ResolvedTraceSteps {\n sources: QpqExecutionTraceSource[];\n steps: QpqExecutionTraceStep[];\n}\n\nexport const resolveSourceMappedSteps = (rawSteps: RawTraceStep[], scriptUrlsById: Record<string, string>): ResolvedTraceSteps => {\n const traceMapsByScriptId = new Map<string, TraceMap | null>();\n const sourceIndexByPath = new Map<string, number>();\n const sources: QpqExecutionTraceSource[] = [];\n\n const getTraceMap = (scriptId: string): TraceMap | null => {\n if (!traceMapsByScriptId.has(scriptId)) {\n const scriptUrl = scriptUrlsById[scriptId];\n traceMapsByScriptId.set(scriptId, scriptUrl ? loadTraceMap(scriptUrlToPath(scriptUrl)) : null);\n }\n return traceMapsByScriptId.get(scriptId) ?? null;\n };\n\n const getSourceIndex = (sourcePath: string, content?: string): number => {\n const existing = sourceIndexByPath.get(sourcePath);\n if (existing !== undefined) return existing;\n\n const index = sources.length;\n sources.push(content !== undefined ? { path: sourcePath, content } : { path: sourcePath });\n sourceIndexByPath.set(sourcePath, index);\n return index;\n };\n\n // Unmapped fallback: the generated script itself becomes the source, content included\n // so the viewer can still render something.\n const getGeneratedSourceIndex = (scriptId: string): number => {\n const scriptUrl = scriptUrlsById[scriptId] || scriptId;\n const existing = sourceIndexByPath.get(scriptUrl);\n if (existing !== undefined) return existing;\n\n let content: string | undefined;\n try {\n content = fs.readFileSync(scriptUrlToPath(scriptUrl), 'utf8');\n } catch {\n content = undefined;\n }\n return getSourceIndex(scriptUrl, content);\n };\n\n const steps = rawSteps.map((rawStep): QpqExecutionTraceStep => {\n const traceMap = getTraceMap(rawStep.scriptId);\n\n if (traceMap) {\n const original = originalPositionFor(traceMap, { line: rawStep.line + 1, column: rawStep.column });\n if (original.source) {\n const content = sourceContentFor(traceMap, original.source) ?? undefined;\n return {\n sourceIndex: getSourceIndex(original.source, content),\n line: original.line ?? rawStep.line + 1,\n column: original.column ?? rawStep.column,\n functionName: rawStep.functionName,\n locals: rawStep.locals,\n returnValue: rawStep.returnValue,\n };\n }\n }\n\n return {\n sourceIndex: getGeneratedSourceIndex(rawStep.scriptId),\n line: rawStep.line + 1,\n column: rawStep.column,\n functionName: rawStep.functionName,\n locals: rawStep.locals,\n returnValue: rawStep.returnValue,\n };\n });\n\n return { sources, steps };\n};\n"]}
|
|
1
|
+
{"version":3,"file":"resolveSourceMaps.js","sourceRoot":"","sources":["../../../src/traceStoryExecution/resolveSourceMaps.ts"],"names":[],"mappings":"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","sourcesContent":["// Post-processing: map the controller's raw steps (generated script positions) back to\n// original sources via the .map files sitting next to the traced scripts on disk —\n// the same files the federated store syncs to /tmp alongside the code. When a map\n// carries sourcesContent (the federated remote build embeds it), the original source\n// text is embedded in the trace so viewers need no access to the repo.\n\nimport { QpqExecutionTraceSource, QpqExecutionTraceStep, QpqExecutionTraceValue } from 'quidproquo-core';\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\nimport { originalPositionFor, sourceContentFor, TraceMap } from '@jridgewell/trace-mapping';\n\ninterface RawTraceStep {\n scriptId: string;\n line: number; // 0-based (CDP)\n column: number;\n functionName: string;\n locals: Record<string, QpqExecutionTraceValue>;\n returnValue?: QpqExecutionTraceValue;\n}\n\nconst scriptUrlToPath = (scriptUrl: string): string => (scriptUrl.startsWith('file://') ? fileURLToPath(scriptUrl) : scriptUrl);\n\n// The LAST sourceMappingURL comment wins (bundles can contain earlier ones from inlined\n// third-party code).\nconst findSourceMappingUrl = (scriptText: string): string | null => {\n const matches = scriptText.match(/\\/\\/[#@] sourceMappingURL=(\\S+)/g);\n if (!matches || matches.length === 0) return null;\n return matches[matches.length - 1].replace(/\\/\\/[#@] sourceMappingURL=/, '');\n};\n\nconst loadTraceMap = (scriptPath: string): TraceMap | null => {\n try {\n const scriptText = fs.readFileSync(scriptPath, 'utf8');\n const sourceMappingUrl = findSourceMappingUrl(scriptText);\n if (!sourceMappingUrl) return null;\n\n if (sourceMappingUrl.startsWith('data:')) {\n const base64Match = sourceMappingUrl.match(/^data:application\\/json[^,]*;base64,(.*)$/);\n const json = base64Match\n ? Buffer.from(base64Match[1], 'base64').toString('utf8')\n : decodeURIComponent(sourceMappingUrl.replace(/^data:[^,]*,/, ''));\n return new TraceMap(json);\n }\n\n const mapPath = path.resolve(path.dirname(scriptPath), sourceMappingUrl);\n return new TraceMap(fs.readFileSync(mapPath, 'utf8'));\n } catch {\n // No map is a degraded trace, not a failure — generated positions still tell the story\n return null;\n }\n};\n\n// Which candidate breakpoint positions land in the service's OWN code — answers the\n// controller worker's filterLocations request when onlyOwnCode tracing is on (the eval\n// worker can't load trace-mapping itself). Positions mapping into node_modules\n// (framework/deps) or not mapping at all (webpack runtime glue) are dropped. No map\n// means the bundle can't be classified — everything stays traced.\n//\n// ownCodeMarkers is a second, opt-in signal: substrings identifying the traced story's\n// own source root. The node_modules check alone assumes framework/deps are bundled from\n// real node_modules — true for lambda's federated remotes, but not for hosts (the dev\n// server) that bundle workspace framework packages from source alongside every hosted\n// service in one script, where framework code never lands in node_modules either. When\n// markers are given, a location must ALSO map into one of them to count as own code.\nexport const filterOwnCodeLocations = <TLocation extends { lineNumber: number; columnNumber?: number }>(\n scriptUrl: string,\n locations: TLocation[],\n ownCodeMarkers?: string[],\n): TLocation[] => {\n const traceMap = scriptUrl ? loadTraceMap(scriptUrlToPath(scriptUrl)) : null;\n if (!traceMap) {\n return locations;\n }\n\n return locations.filter((location) => {\n const original = originalPositionFor(traceMap, { line: location.lineNumber + 1, column: location.columnNumber ?? 0 });\n if (!original.source || original.source.includes('node_modules')) return false;\n\n return !ownCodeMarkers?.length || ownCodeMarkers.some((marker) => original.source!.includes(marker));\n });\n};\n\n// Derives own-code markers from a service's absolute source root (QpqFunctionRuntimeAdvanced.basePath,\n// or getApplicationConfigRoot(qpqConfig) for the relative-string runtime form). Bundlers emit\n// source-map `source` entries as either real filesystem paths or webpack://<namespace>/./<path\n// relative to the build context> pseudo urls — both preserve the original directory names\n// verbatim, so matching on the root's own trailing segments works for either form without\n// needing to know the bundler's exact context/namespace.\nexport const getOwnCodeMarkersFromRoot = (root: string): string[] => {\n const normalized = root.replace(/\\\\/g, '/').replace(/\\/+$/, '');\n const tailSegments = normalized.split('/').filter(Boolean).slice(-3).join('/');\n\n return tailSegments && tailSegments !== normalized ? [normalized, tailSegments] : [normalized];\n};\n\nexport interface ResolvedTraceSteps {\n sources: QpqExecutionTraceSource[];\n steps: QpqExecutionTraceStep[];\n}\n\nexport const resolveSourceMappedSteps = (rawSteps: RawTraceStep[], scriptUrlsById: Record<string, string>): ResolvedTraceSteps => {\n const traceMapsByScriptId = new Map<string, TraceMap | null>();\n const sourceIndexByPath = new Map<string, number>();\n const sources: QpqExecutionTraceSource[] = [];\n\n const getTraceMap = (scriptId: string): TraceMap | null => {\n if (!traceMapsByScriptId.has(scriptId)) {\n const scriptUrl = scriptUrlsById[scriptId];\n traceMapsByScriptId.set(scriptId, scriptUrl ? loadTraceMap(scriptUrlToPath(scriptUrl)) : null);\n }\n return traceMapsByScriptId.get(scriptId) ?? null;\n };\n\n const getSourceIndex = (sourcePath: string, content?: string): number => {\n const existing = sourceIndexByPath.get(sourcePath);\n if (existing !== undefined) return existing;\n\n const index = sources.length;\n sources.push(content !== undefined ? { path: sourcePath, content } : { path: sourcePath });\n sourceIndexByPath.set(sourcePath, index);\n return index;\n };\n\n // Unmapped fallback: the generated script itself becomes the source, content included\n // so the viewer can still render something.\n const getGeneratedSourceIndex = (scriptId: string): number => {\n const scriptUrl = scriptUrlsById[scriptId] || scriptId;\n const existing = sourceIndexByPath.get(scriptUrl);\n if (existing !== undefined) return existing;\n\n let content: string | undefined;\n try {\n content = fs.readFileSync(scriptUrlToPath(scriptUrl), 'utf8');\n } catch {\n content = undefined;\n }\n return getSourceIndex(scriptUrl, content);\n };\n\n const steps = rawSteps.map((rawStep): QpqExecutionTraceStep => {\n const traceMap = getTraceMap(rawStep.scriptId);\n\n if (traceMap) {\n const original = originalPositionFor(traceMap, { line: rawStep.line + 1, column: rawStep.column });\n if (original.source) {\n const content = sourceContentFor(traceMap, original.source) ?? undefined;\n return {\n sourceIndex: getSourceIndex(original.source, content),\n line: original.line ?? rawStep.line + 1,\n column: original.column ?? rawStep.column,\n functionName: rawStep.functionName,\n locals: rawStep.locals,\n returnValue: rawStep.returnValue,\n };\n }\n }\n\n return {\n sourceIndex: getGeneratedSourceIndex(rawStep.scriptId),\n line: rawStep.line + 1,\n column: rawStep.column,\n functionName: rawStep.functionName,\n locals: rawStep.locals,\n returnValue: rawStep.returnValue,\n };\n });\n\n return { sources, steps };\n};\n"]}
|
|
@@ -2,6 +2,7 @@ import { ActionProcessorList, QpqExecutionTrace, StoryResult } from 'quidproquo-
|
|
|
2
2
|
export interface TraceStoryExecutionOptions {
|
|
3
3
|
scriptPatterns?: string[];
|
|
4
4
|
onlyOwnCode?: boolean;
|
|
5
|
+
ownCodeMarkers?: string[];
|
|
5
6
|
maxSteps?: number;
|
|
6
7
|
maxTraceMs?: number;
|
|
7
8
|
maxValueLength?: number;
|
|
@@ -86,7 +86,7 @@ export const traceStoryExecution = async (storyResult, runtime, options = {}) =>
|
|
|
86
86
|
controller.postMessage({
|
|
87
87
|
type: 'filteredLocations',
|
|
88
88
|
requestId: message.requestId,
|
|
89
|
-
locations: filterOwnCodeLocations(message.scriptUrl, message.locations || []),
|
|
89
|
+
locations: filterOwnCodeLocations(message.scriptUrl, message.locations || [], options.ownCodeMarkers),
|
|
90
90
|
});
|
|
91
91
|
}
|
|
92
92
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"traceStoryExecution.js","sourceRoot":"","sources":["../../../src/traceStoryExecution/traceStoryExecution.ts"],"names":[],"mappings":"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","sourcesContent":["// traceStoryExecution — replay a StoryResult log against real story code and record a\n// line-by-line execution trace: every statement executed, with local variable values.\n//\n// Wraps qpqExecuteLog (deterministic replay: every impure action is answered from the\n// log's history), while a worker-thread debug controller (see controllerWorker.ts)\n// drives the V8 inspector against this thread and captures each statement + locals.\n// Because the replay is deterministic, the recorded trace carries the same information\n// an interactive debug session would. See trace-replay-plan.md.\n//\n// The CALLER must run on the process MAIN THREAD (lambda handlers and the dev server\n// do) — inspector.Session.connectToMainThread only targets the main thread.\n\nimport { ActionProcessorList, getQpqIsoDateTimeFromDate, qpqExecuteLog, QpqExecutionTrace, StoryResult } from 'quidproquo-core';\n\nimport { Worker } from 'worker_threads';\n\nimport { TraceControllerWorkerData, traceControllerWorkerMain } from './controllerWorker';\nimport { filterOwnCodeLocations, resolveSourceMappedSteps } from './resolveSourceMaps';\n\nexport interface TraceStoryExecutionOptions {\n // Regex sources matched against script urls to trace IN ADDITION to the story\n // function's own script (auto-detected via [[FunctionLocation]]). Use for bundles\n // split across chunks, e.g. ['/tmp/qpq-federated-code/'].\n scriptPatterns?: string[];\n\n // Only break on statements whose source-mapped origin is the service's own code —\n // node_modules positions get no breakpoints, so the step/time budgets are spent\n // entirely on user statements. Scripts without a source map stay fully traced.\n onlyOwnCode?: boolean;\n\n // Step budget and wall-clock budget: past either, the replay finishes untraced and\n // the trace is marked truncated. The wall clock is what bounds total runtime — locals\n // capture makes per-step cost variable, so step count alone doesn't bound time.\n maxSteps?: number;\n maxTraceMs?: number;\n\n // Serialization caps for captured locals: string length, properties per object level,\n // object walk depth for the deep json capture, and total json size per value.\n maxValueLength?: number;\n maxProperties?: number;\n maxValueDepth?: number;\n maxSerializedLength?: number;\n\n // Passed through to qpqExecuteLog — lets specific action types execute for real\n // instead of being answered from the log.\n overrides?: ActionProcessorList;\n}\n\nexport interface TraceStoryExecutionResult {\n trace: QpqExecutionTrace;\n\n // The replay's own StoryResult (result/error of re-running the story)\n replay: StoryResult<any>;\n}\n\n// Ready covers domain enable + breakpoint installation across every traced chunk —\n// generous because the service function running this has minutes of budget, and an\n// abort here wastes a replay that would have succeeded (instrumentMs in the trace stats\n// shows the real cost).\nconst READY_TIMEOUT_MS = 120_000;\nconst TRACE_TIMEOUT_MS = 60_000;\n\n// One trace at a time per process: the controller owns process-wide debugger state\n// (breakpoints, pause handling), and the story function handoff is a global.\nlet traceInFlight = false;\n\nconst waitForControllerMessage = (controller: Worker, type: string, timeoutMs: number): Promise<any> =>\n new Promise((resolve, reject) => {\n const cleanUp = () => {\n controller.off('message', onMessage);\n controller.off('error', onError);\n controller.off('exit', onExit);\n clearTimeout(timeout);\n };\n const onMessage = (message: any) => {\n if (message?.type === type) {\n cleanUp();\n resolve(message);\n } else if (message?.type === 'fatal') {\n cleanUp();\n reject(new Error(`trace controller failed: ${message.error}`));\n }\n };\n const onError = (error: Error) => {\n cleanUp();\n reject(error);\n };\n const onExit = (code: number) => {\n cleanUp();\n reject(new Error(`trace controller exited early with code [${code}]`));\n };\n const timeout = setTimeout(() => {\n cleanUp();\n reject(new Error(`timed out after ${timeoutMs}ms waiting for trace controller [${type}]`));\n }, timeoutMs);\n\n controller.on('message', onMessage);\n controller.on('error', onError);\n controller.on('exit', onExit);\n });\n\nexport const traceStoryExecution = async (\n storyResult: StoryResult<any>,\n runtime: any,\n options: TraceStoryExecutionOptions = {},\n): Promise<TraceStoryExecutionResult> => {\n if (traceInFlight) {\n throw new Error('a story trace is already in progress in this process');\n }\n traceInFlight = true;\n\n // The controller locates the story's script through this global ([[FunctionLocation]])\n (globalThis as any).__qpqTraceStoryFunction = runtime;\n\n const workerData: TraceControllerWorkerData = {\n scriptPatterns: options.scriptPatterns ?? [],\n onlyOwnCode: options.onlyOwnCode ?? false,\n maxSteps: options.maxSteps ?? 20_000,\n maxTraceMs: options.maxTraceMs ?? 120_000,\n maxValueLength: options.maxValueLength ?? 1_000,\n maxProperties: options.maxProperties ?? 32,\n maxValueDepth: options.maxValueDepth ?? 4,\n maxSerializedLength: options.maxSerializedLength ?? 30_000,\n };\n\n // Lambdas ship as single-file webpack bundles, so the controller can't be a worker\n // FILE on disk — it's serialized and run as an eval worker (see controllerWorker.ts).\n const controller = new Worker(`(${traceControllerWorkerMain.toString()})()`, {\n eval: true,\n workerData,\n });\n\n // onlyOwnCode: the worker can't load trace-mapping (eval worker, builtin requires\n // only), so it round-trips candidate breakpoint locations here for source-map\n // filtering. Attached before the ready-wait — instrumentation happens during init.\n controller.on('message', (message: any) => {\n if (message?.type === 'filterLocations') {\n controller.postMessage({\n type: 'filteredLocations',\n requestId: message.requestId,\n locations: filterOwnCodeLocations(message.scriptUrl, message.locations || []),\n });\n }\n });\n\n try {\n await waitForControllerMessage(controller, 'ready', READY_TIMEOUT_MS);\n\n const replayStartedAt = Date.now();\n const replay = await qpqExecuteLog(storyResult, runtime, options.overrides);\n const replayMs = Date.now() - replayStartedAt;\n\n const tracePromise = waitForControllerMessage(controller, 'trace', TRACE_TIMEOUT_MS);\n controller.postMessage({ type: 'done' });\n const rawTrace = await tracePromise;\n\n const { sources, steps } = resolveSourceMappedSteps(rawTrace.steps, rawTrace.scripts);\n\n const trace: QpqExecutionTrace = {\n correlation: storyResult.correlation,\n moduleName: storyResult.moduleName,\n tracedAt: getQpqIsoDateTimeFromDate(new Date()),\n truncated: rawTrace.stats.truncated,\n sources,\n steps,\n stats: {\n pauses: rawTrace.stats.pauses,\n breakpoints: rawTrace.stats.breakpoints,\n replayMs,\n localsCaptureMs: rawTrace.stats.localsCaptureMs,\n instrumentMs: rawTrace.stats.instrumentMs,\n instrumentedScriptUrls: rawTrace.stats.instrumentedScriptUrls,\n },\n };\n\n return { trace, replay };\n } finally {\n delete (globalThis as any).__qpqTraceStoryFunction;\n traceInFlight = false;\n await controller.terminate();\n }\n};\n"]}
|
|
1
|
+
{"version":3,"file":"traceStoryExecution.js","sourceRoot":"","sources":["../../../src/traceStoryExecution/traceStoryExecution.ts"],"names":[],"mappings":"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","sourcesContent":["// traceStoryExecution — replay a StoryResult log against real story code and record a\n// line-by-line execution trace: every statement executed, with local variable values.\n//\n// Wraps qpqExecuteLog (deterministic replay: every impure action is answered from the\n// log's history), while a worker-thread debug controller (see controllerWorker.ts)\n// drives the V8 inspector against this thread and captures each statement + locals.\n// Because the replay is deterministic, the recorded trace carries the same information\n// an interactive debug session would. See trace-replay-plan.md.\n//\n// The CALLER must run on the process MAIN THREAD (lambda handlers and the dev server\n// do) — inspector.Session.connectToMainThread only targets the main thread.\n\nimport { ActionProcessorList, getQpqIsoDateTimeFromDate, qpqExecuteLog, QpqExecutionTrace, StoryResult } from 'quidproquo-core';\n\nimport { Worker } from 'worker_threads';\n\nimport { TraceControllerWorkerData, traceControllerWorkerMain } from './controllerWorker';\nimport { filterOwnCodeLocations, resolveSourceMappedSteps } from './resolveSourceMaps';\n\nexport interface TraceStoryExecutionOptions {\n // Regex sources matched against script urls to trace IN ADDITION to the story\n // function's own script (auto-detected via [[FunctionLocation]]). Use for bundles\n // split across chunks, e.g. ['/tmp/qpq-federated-code/'].\n scriptPatterns?: string[];\n\n // Only break on statements whose source-mapped origin is the service's own code —\n // node_modules positions get no breakpoints, so the step/time budgets are spent\n // entirely on user statements. Scripts without a source map stay fully traced.\n onlyOwnCode?: boolean;\n\n // Extra own-code markers beyond the built-in \"not node_modules\" check — see\n // resolveSourceMaps.filterOwnCodeLocations. Only takes effect when onlyOwnCode is set.\n ownCodeMarkers?: string[];\n\n // Step budget and wall-clock budget: past either, the replay finishes untraced and\n // the trace is marked truncated. The wall clock is what bounds total runtime — locals\n // capture makes per-step cost variable, so step count alone doesn't bound time.\n maxSteps?: number;\n maxTraceMs?: number;\n\n // Serialization caps for captured locals: string length, properties per object level,\n // object walk depth for the deep json capture, and total json size per value.\n maxValueLength?: number;\n maxProperties?: number;\n maxValueDepth?: number;\n maxSerializedLength?: number;\n\n // Passed through to qpqExecuteLog — lets specific action types execute for real\n // instead of being answered from the log.\n overrides?: ActionProcessorList;\n}\n\nexport interface TraceStoryExecutionResult {\n trace: QpqExecutionTrace;\n\n // The replay's own StoryResult (result/error of re-running the story)\n replay: StoryResult<any>;\n}\n\n// Ready covers domain enable + breakpoint installation across every traced chunk —\n// generous because the service function running this has minutes of budget, and an\n// abort here wastes a replay that would have succeeded (instrumentMs in the trace stats\n// shows the real cost).\nconst READY_TIMEOUT_MS = 120_000;\nconst TRACE_TIMEOUT_MS = 60_000;\n\n// One trace at a time per process: the controller owns process-wide debugger state\n// (breakpoints, pause handling), and the story function handoff is a global.\nlet traceInFlight = false;\n\nconst waitForControllerMessage = (controller: Worker, type: string, timeoutMs: number): Promise<any> =>\n new Promise((resolve, reject) => {\n const cleanUp = () => {\n controller.off('message', onMessage);\n controller.off('error', onError);\n controller.off('exit', onExit);\n clearTimeout(timeout);\n };\n const onMessage = (message: any) => {\n if (message?.type === type) {\n cleanUp();\n resolve(message);\n } else if (message?.type === 'fatal') {\n cleanUp();\n reject(new Error(`trace controller failed: ${message.error}`));\n }\n };\n const onError = (error: Error) => {\n cleanUp();\n reject(error);\n };\n const onExit = (code: number) => {\n cleanUp();\n reject(new Error(`trace controller exited early with code [${code}]`));\n };\n const timeout = setTimeout(() => {\n cleanUp();\n reject(new Error(`timed out after ${timeoutMs}ms waiting for trace controller [${type}]`));\n }, timeoutMs);\n\n controller.on('message', onMessage);\n controller.on('error', onError);\n controller.on('exit', onExit);\n });\n\nexport const traceStoryExecution = async (\n storyResult: StoryResult<any>,\n runtime: any,\n options: TraceStoryExecutionOptions = {},\n): Promise<TraceStoryExecutionResult> => {\n if (traceInFlight) {\n throw new Error('a story trace is already in progress in this process');\n }\n traceInFlight = true;\n\n // The controller locates the story's script through this global ([[FunctionLocation]])\n (globalThis as any).__qpqTraceStoryFunction = runtime;\n\n const workerData: TraceControllerWorkerData = {\n scriptPatterns: options.scriptPatterns ?? [],\n onlyOwnCode: options.onlyOwnCode ?? false,\n maxSteps: options.maxSteps ?? 20_000,\n maxTraceMs: options.maxTraceMs ?? 120_000,\n maxValueLength: options.maxValueLength ?? 1_000,\n maxProperties: options.maxProperties ?? 32,\n maxValueDepth: options.maxValueDepth ?? 4,\n maxSerializedLength: options.maxSerializedLength ?? 30_000,\n };\n\n // Lambdas ship as single-file webpack bundles, so the controller can't be a worker\n // FILE on disk — it's serialized and run as an eval worker (see controllerWorker.ts).\n const controller = new Worker(`(${traceControllerWorkerMain.toString()})()`, {\n eval: true,\n workerData,\n });\n\n // onlyOwnCode: the worker can't load trace-mapping (eval worker, builtin requires\n // only), so it round-trips candidate breakpoint locations here for source-map\n // filtering. Attached before the ready-wait — instrumentation happens during init.\n controller.on('message', (message: any) => {\n if (message?.type === 'filterLocations') {\n controller.postMessage({\n type: 'filteredLocations',\n requestId: message.requestId,\n locations: filterOwnCodeLocations(message.scriptUrl, message.locations || [], options.ownCodeMarkers),\n });\n }\n });\n\n try {\n await waitForControllerMessage(controller, 'ready', READY_TIMEOUT_MS);\n\n const replayStartedAt = Date.now();\n const replay = await qpqExecuteLog(storyResult, runtime, options.overrides);\n const replayMs = Date.now() - replayStartedAt;\n\n const tracePromise = waitForControllerMessage(controller, 'trace', TRACE_TIMEOUT_MS);\n controller.postMessage({ type: 'done' });\n const rawTrace = await tracePromise;\n\n const { sources, steps } = resolveSourceMappedSteps(rawTrace.steps, rawTrace.scripts);\n\n const trace: QpqExecutionTrace = {\n correlation: storyResult.correlation,\n moduleName: storyResult.moduleName,\n tracedAt: getQpqIsoDateTimeFromDate(new Date()),\n truncated: rawTrace.stats.truncated,\n sources,\n steps,\n stats: {\n pauses: rawTrace.stats.pauses,\n breakpoints: rawTrace.stats.breakpoints,\n replayMs,\n localsCaptureMs: rawTrace.stats.localsCaptureMs,\n instrumentMs: rawTrace.stats.instrumentMs,\n instrumentedScriptUrls: rawTrace.stats.instrumentedScriptUrls,\n },\n };\n\n return { trace, replay };\n } finally {\n delete (globalThis as any).__qpqTraceStoryFunction;\n traceInFlight = false;\n await controller.terminate();\n }\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quidproquo-actionprocessor-node",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./lib/commonjs/index.js",
|
|
6
6
|
"module": "./lib/esm/index.js",
|
|
@@ -34,14 +34,15 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@anthropic-ai/sdk": "^0.19.1",
|
|
36
36
|
"@jridgewell/trace-mapping": "^0.3.25",
|
|
37
|
-
"quidproquo-actionprocessor-js": "0.1.
|
|
38
|
-
"quidproquo-core": "0.1.
|
|
39
|
-
"quidproquo-webserver": "0.1.
|
|
37
|
+
"quidproquo-actionprocessor-js": "0.1.8",
|
|
38
|
+
"quidproquo-core": "0.1.8",
|
|
39
|
+
"quidproquo-webserver": "0.1.8",
|
|
40
40
|
"uuidv7": "^1.0.1"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
+
"@jridgewell/gen-mapping": "^0.3.13",
|
|
43
44
|
"@types/node": "^22.13.13",
|
|
44
|
-
"quidproquo-tsconfig": "0.1.
|
|
45
|
+
"quidproquo-tsconfig": "0.1.8",
|
|
45
46
|
"typescript": "^5.8.2"
|
|
46
47
|
}
|
|
47
48
|
}
|