quidproquo-actionprocessor-node 0.1.3 → 0.1.4
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/index.js +1 -0
- package/lib/commonjs/actionProcessor/core/index.js.map +1 -0
- package/lib/commonjs/actionProcessor/core/inlineFunction/getInlineFunctionExecuteActionProcessor.js +1 -0
- package/lib/commonjs/actionProcessor/core/inlineFunction/getInlineFunctionExecuteActionProcessor.js.map +1 -0
- package/lib/commonjs/actionProcessor/core/inlineFunction/index.js +1 -0
- package/lib/commonjs/actionProcessor/core/inlineFunction/index.js.map +1 -0
- package/lib/commonjs/actionProcessor/core/stream/getStreamCloseActionProcessor.js +1 -0
- package/lib/commonjs/actionProcessor/core/stream/getStreamCloseActionProcessor.js.map +1 -0
- package/lib/commonjs/actionProcessor/core/stream/getStreamReadActionProcessor.js +1 -0
- package/lib/commonjs/actionProcessor/core/stream/getStreamReadActionProcessor.js.map +1 -0
- package/lib/commonjs/actionProcessor/core/stream/index.js +1 -0
- package/lib/commonjs/actionProcessor/core/stream/index.js.map +1 -0
- package/lib/commonjs/actionProcessor/index.js +1 -0
- package/lib/commonjs/actionProcessor/index.js.map +1 -0
- package/lib/commonjs/actionProcessor/webserver/index.js +1 -0
- package/lib/commonjs/actionProcessor/webserver/index.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileDeleteActionProcessor.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileDeleteActionProcessor.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileExistsActionProcessor.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileExistsActionProcessor.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileGenerateTemporarySecureUrlActionProcessor.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileGenerateTemporarySecureUrlActionProcessor.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileGenerateTemporaryUploadSecureUrlActionProcessor.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileGenerateTemporaryUploadSecureUrlActionProcessor.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileIsColdStorageActionProcessor.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileIsColdStorageActionProcessor.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileListDirectoryActionProcessor.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileListDirectoryActionProcessor.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileReadBinaryContentsActionProcessor.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileReadBinaryContentsActionProcessor.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileReadObjectJsonActionProcessor.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileReadObjectJsonActionProcessor.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileReadTextContentsActionProcessor.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileReadTextContentsActionProcessor.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileStreamOpenActionProcessor.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileStreamOpenActionProcessor.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileWriteBinaryContentsActionProcessor.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileWriteBinaryContentsActionProcessor.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileWriteObjectJsonActionProcessor.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileWriteObjectJsonActionProcessor.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileWriteTextContentsActionProcessor.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/getFileWriteTextContentsActionProcessor.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/index.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/index.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/secureUrlUtils.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/secureUrlUtils.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/types.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/types.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/utils.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/file/utils.js.map +1 -0
- package/lib/commonjs/dynamicActionProcessor/index.js +1 -0
- package/lib/commonjs/dynamicActionProcessor/index.js.map +1 -0
- package/lib/commonjs/index.d.ts +1 -0
- package/lib/commonjs/index.js +2 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/traceStoryExecution/controllerWorker.d.ts +11 -0
- package/lib/commonjs/traceStoryExecution/controllerWorker.js +409 -0
- package/lib/commonjs/traceStoryExecution/controllerWorker.js.map +1 -0
- package/lib/commonjs/traceStoryExecution/getSystemTraceStoryActionProcessor.d.ts +2 -0
- package/lib/commonjs/traceStoryExecution/getSystemTraceStoryActionProcessor.js +47 -0
- package/lib/commonjs/traceStoryExecution/getSystemTraceStoryActionProcessor.js.map +1 -0
- package/lib/commonjs/traceStoryExecution/index.d.ts +2 -0
- package/lib/commonjs/traceStoryExecution/index.js +19 -0
- package/lib/commonjs/traceStoryExecution/index.js.map +1 -0
- package/lib/commonjs/traceStoryExecution/resolveSourceMaps.d.ts +19 -0
- package/lib/commonjs/traceStoryExecution/resolveSourceMaps.js +159 -0
- package/lib/commonjs/traceStoryExecution/resolveSourceMaps.js.map +1 -0
- package/lib/commonjs/traceStoryExecution/traceStoryExecution.d.ts +17 -0
- package/lib/commonjs/traceStoryExecution/traceStoryExecution.js +140 -0
- package/lib/commonjs/traceStoryExecution/traceStoryExecution.js.map +1 -0
- package/lib/esm/actionProcessor/core/index.js +1 -0
- package/lib/esm/actionProcessor/core/index.js.map +1 -0
- package/lib/esm/actionProcessor/core/inlineFunction/getInlineFunctionExecuteActionProcessor.js +1 -0
- package/lib/esm/actionProcessor/core/inlineFunction/getInlineFunctionExecuteActionProcessor.js.map +1 -0
- package/lib/esm/actionProcessor/core/inlineFunction/index.js +1 -0
- package/lib/esm/actionProcessor/core/inlineFunction/index.js.map +1 -0
- package/lib/esm/actionProcessor/core/stream/getStreamCloseActionProcessor.js +1 -0
- package/lib/esm/actionProcessor/core/stream/getStreamCloseActionProcessor.js.map +1 -0
- package/lib/esm/actionProcessor/core/stream/getStreamReadActionProcessor.js +1 -0
- package/lib/esm/actionProcessor/core/stream/getStreamReadActionProcessor.js.map +1 -0
- package/lib/esm/actionProcessor/core/stream/index.js +1 -0
- package/lib/esm/actionProcessor/core/stream/index.js.map +1 -0
- package/lib/esm/actionProcessor/index.js +1 -0
- package/lib/esm/actionProcessor/index.js.map +1 -0
- package/lib/esm/actionProcessor/webserver/index.js +1 -0
- package/lib/esm/actionProcessor/webserver/index.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileDeleteActionProcessor.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileDeleteActionProcessor.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileExistsActionProcessor.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileExistsActionProcessor.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileGenerateTemporarySecureUrlActionProcessor.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileGenerateTemporarySecureUrlActionProcessor.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileGenerateTemporaryUploadSecureUrlActionProcessor.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileGenerateTemporaryUploadSecureUrlActionProcessor.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileIsColdStorageActionProcessor.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileIsColdStorageActionProcessor.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileListDirectoryActionProcessor.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileListDirectoryActionProcessor.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileReadBinaryContentsActionProcessor.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileReadBinaryContentsActionProcessor.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileReadObjectJsonActionProcessor.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileReadObjectJsonActionProcessor.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileReadTextContentsActionProcessor.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileReadTextContentsActionProcessor.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileStreamOpenActionProcessor.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileStreamOpenActionProcessor.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileWriteBinaryContentsActionProcessor.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileWriteBinaryContentsActionProcessor.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileWriteObjectJsonActionProcessor.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileWriteObjectJsonActionProcessor.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileWriteTextContentsActionProcessor.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/getFileWriteTextContentsActionProcessor.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/index.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/index.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/secureUrlUtils.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/secureUrlUtils.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/types.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/types.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/file/utils.js +1 -0
- package/lib/esm/dynamicActionProcessor/file/utils.js.map +1 -0
- package/lib/esm/dynamicActionProcessor/index.js +1 -0
- package/lib/esm/dynamicActionProcessor/index.js.map +1 -0
- package/lib/esm/index.d.ts +1 -0
- package/lib/esm/index.js +2 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/traceStoryExecution/controllerWorker.d.ts +11 -0
- package/lib/esm/traceStoryExecution/controllerWorker.js +406 -0
- package/lib/esm/traceStoryExecution/controllerWorker.js.map +1 -0
- package/lib/esm/traceStoryExecution/getSystemTraceStoryActionProcessor.d.ts +2 -0
- package/lib/esm/traceStoryExecution/getSystemTraceStoryActionProcessor.js +32 -0
- package/lib/esm/traceStoryExecution/getSystemTraceStoryActionProcessor.js.map +1 -0
- package/lib/esm/traceStoryExecution/index.d.ts +2 -0
- package/lib/esm/traceStoryExecution/index.js +3 -0
- package/lib/esm/traceStoryExecution/index.js.map +1 -0
- package/lib/esm/traceStoryExecution/resolveSourceMaps.d.ts +19 -0
- package/lib/esm/traceStoryExecution/resolveSourceMaps.js +118 -0
- package/lib/esm/traceStoryExecution/resolveSourceMaps.js.map +1 -0
- package/lib/esm/traceStoryExecution/traceStoryExecution.d.ts +17 -0
- package/lib/esm/traceStoryExecution/traceStoryExecution.js +126 -0
- package/lib/esm/traceStoryExecution/traceStoryExecution.js.map +1 -0
- package/package.json +7 -5
|
@@ -18,3 +18,4 @@ const getProcessFileReadTextContents = (qpqConfig, config) => {
|
|
|
18
18
|
export const getFileReadTextContentsActionProcessor = (config) => async (qpqConfig) => ({
|
|
19
19
|
[FileActionType.ReadTextContents]: getProcessFileReadTextContents(qpqConfig, config),
|
|
20
20
|
});
|
|
21
|
+
//# sourceMappingURL=getFileReadTextContentsActionProcessor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getFileReadTextContentsActionProcessor.js","sourceRoot":"","sources":["../../../../src/dynamicActionProcessor/file/getFileReadTextContentsActionProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,YAAY,EACZ,iBAAiB,EACjB,gCAAgC,EAChC,aAAa,EACb,cAAc,GAGf,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAGlC,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE1C,MAAM,8BAA8B,GAAG,CAAC,SAAoB,EAAE,MAAyB,EAAuC,EAAE;IAC9H,OAAO,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE;QACnC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;YACrE,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACpD,OAAO,YAAY,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,gCAAgC,CAAC,KAAK,EAAE;gBAC7C,MAAM,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,aAAa,CAAC,QAAQ,EAAE,mBAAmB,QAAQ,EAAE,CAAC,EAAE,eAAe;aACxG,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,sCAAsC,GACjD,CAAC,MAAyB,EAA+B,EAAE,CAC3D,KAAK,EAAE,SAAoB,EAAgC,EAAE,CAAC,CAAC;IAC7D,CAAC,cAAc,CAAC,gBAAgB,CAAC,EAAE,8BAA8B,CAAC,SAAS,EAAE,MAAM,CAAC;CACrF,CAAC,CAAC","sourcesContent":["import {\n ActionProcessorList,\n ActionProcessorListResolver,\n actionResult,\n actionResultError,\n actionResultErrorFromCaughtError,\n ErrorTypeEnum,\n FileActionType,\n FileReadTextContentsActionProcessor,\n QPQConfig,\n} from 'quidproquo-core';\n\nimport * as fs from 'fs/promises';\n\nimport { FileStorageConfig } from './types';\nimport { resolveFilePath } from './utils';\n\nconst getProcessFileReadTextContents = (qpqConfig: QPQConfig, config: FileStorageConfig): FileReadTextContentsActionProcessor => {\n return async ({ drive, filepath }) => {\n try {\n const fullPath = resolveFilePath(config, qpqConfig, drive, filepath);\n const content = await fs.readFile(fullPath, 'utf8');\n return actionResult(content);\n } catch (error: unknown) {\n return actionResultErrorFromCaughtError(error, {\n ENOENT: () => actionResultError(ErrorTypeEnum.NotFound, `File not found: ${filepath}`), // node fs code\n });\n }\n };\n};\n\nexport const getFileReadTextContentsActionProcessor =\n (config: FileStorageConfig): ActionProcessorListResolver =>\n async (qpqConfig: QPQConfig): Promise<ActionProcessorList> => ({\n [FileActionType.ReadTextContents]: getProcessFileReadTextContents(qpqConfig, config),\n });\n"]}
|
|
@@ -35,3 +35,4 @@ const getProcessFileStreamOpen = (qpqConfig, config) => {
|
|
|
35
35
|
export const getFileStreamOpenActionProcessor = (config) => async (qpqConfig) => ({
|
|
36
36
|
[FileActionType.StreamOpen]: getProcessFileStreamOpen(qpqConfig, config),
|
|
37
37
|
});
|
|
38
|
+
//# sourceMappingURL=getFileStreamOpenActionProcessor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getFileStreamOpenActionProcessor.js","sourceRoot":"","sources":["../../../../src/dynamicActionProcessor/file/getFileStreamOpenActionProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,YAAY,EACZ,iBAAiB,EACjB,gCAAgC,EAChC,cAAc,EAEd,2BAA2B,GAE5B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAIzB,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE1C,KAAK,SAAS,CAAC,CAAC,kBAAkB,CAAC,MAAgB;IACjD,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACjC,MAAM,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAE,KAAgB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC;AAED,KAAK,SAAS,CAAC,CAAC,oBAAoB,CAAC,MAAgB;IACnD,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,KAAgB,CAAC;QAClF,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED,MAAM,wBAAwB,GAAG,CAAC,SAAoB,EAAE,MAAyB,EAAiC,EAAE;IAClH,OAAO,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,aAAa,EAAE,mBAAmB,EAAE,cAAc,EAAE,EAAE;QAC/I,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,QAAQ,KAAK,MAAM,CAAC;YACnC,MAAM,aAAa,GAAG,SAAS,IAAI,KAAK,CAAC;YACzC,MAAM,UAAU,GAAG,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC;YACnH,MAAM,QAAQ,GAAG,QAAQ,UAAU,EAAE,EAAE,CAAC;YAExC,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;YAC5F,cAAc,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAE5C,OAAO,YAAY,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,gCAAgC,CAAC,KAAK,EAAE;gBAC7C,MAAM,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,2BAA2B,CAAC,YAAY,EAAE,mBAAmB,QAAQ,EAAE,CAAC,EAAE,eAAe;aAC1H,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,gCAAgC,GAC3C,CAAC,MAAyB,EAA+B,EAAE,CAC3D,KAAK,EAAE,SAAoB,EAAgC,EAAE,CAAC,CAAC;IAC7D,CAAC,cAAc,CAAC,UAAU,CAAC,EAAE,wBAAwB,CAAC,SAAS,EAAE,MAAM,CAAC;CACzE,CAAC,CAAC","sourcesContent":["import {\n ActionProcessorList,\n ActionProcessorListResolver,\n actionResult,\n actionResultError,\n actionResultErrorFromCaughtError,\n FileActionType,\n FileStreamOpenActionProcessor,\n FileStreamOpenErrorTypeEnum,\n QPQConfig,\n} from 'quidproquo-core';\n\nimport { randomUUID } from 'crypto';\nimport * as fs from 'fs';\nimport { Readable } from 'stream';\n\nimport { FileStorageConfig } from './types';\nimport { resolveFilePath } from './utils';\n\nasync function* textStreamIterator(stream: Readable): AsyncIterableIterator<string> {\n for await (const chunk of stream) {\n yield typeof chunk === 'string' ? chunk : (chunk as Buffer).toString('utf8');\n }\n}\n\nasync function* binaryStreamIterator(stream: Readable): AsyncIterableIterator<string> {\n for await (const chunk of stream) {\n const buffer = typeof chunk === 'string' ? Buffer.from(chunk) : (chunk as Buffer);\n yield buffer.toString('base64');\n }\n}\n\nconst getProcessFileStreamOpen = (qpqConfig: QPQConfig, config: FileStorageConfig): FileStreamOpenActionProcessor => {\n return async ({ drive, filepath, encoding, chunkSize }, session, actionProcessors, logger, updateSession, dynamicModuleLoader, streamRegistry) => {\n try {\n const fullPath = resolveFilePath(config, qpqConfig, drive, filepath);\n const isText = encoding === 'text';\n const highWaterMark = chunkSize ?? 65536;\n const readStream = fs.createReadStream(fullPath, isText ? { encoding: 'utf8', highWaterMark } : { highWaterMark });\n const streamId = `file-${randomUUID()}`;\n\n const iterator = isText ? textStreamIterator(readStream) : binaryStreamIterator(readStream);\n streamRegistry.register(streamId, iterator);\n\n return actionResult({ id: streamId, encoding });\n } catch (error: unknown) {\n return actionResultErrorFromCaughtError(error, {\n ENOENT: () => actionResultError(FileStreamOpenErrorTypeEnum.FileNotFound, `File not found: ${filepath}`), // node fs code\n });\n }\n };\n};\n\nexport const getFileStreamOpenActionProcessor =\n (config: FileStorageConfig): ActionProcessorListResolver =>\n async (qpqConfig: QPQConfig): Promise<ActionProcessorList> => ({\n [FileActionType.StreamOpen]: getProcessFileStreamOpen(qpqConfig, config),\n });\n"]}
|
|
@@ -27,3 +27,4 @@ const getProcessFileWriteBinaryContents = (config) => (qpqConfig) => {
|
|
|
27
27
|
export const getFileWriteBinaryContentsActionProcessor = (config) => async (qpqConfig) => ({
|
|
28
28
|
[FileActionType.WriteBinaryContents]: getProcessFileWriteBinaryContents(config)(qpqConfig),
|
|
29
29
|
});
|
|
30
|
+
//# sourceMappingURL=getFileWriteBinaryContentsActionProcessor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getFileWriteBinaryContentsActionProcessor.js","sourceRoot":"","sources":["../../../../src/dynamicActionProcessor/file/getFileWriteBinaryContentsActionProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,YAAY,EACZ,iBAAiB,EACjB,gCAAgC,EAChC,cAAc,EAEd,oCAAoC,GAErC,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAGlC,OAAO,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEvE,MAAM,iCAAiC,GACrC,CAAC,MAAyB,EAAE,EAAE,CAC9B,CAAC,SAAoB,EAA0C,EAAE;IAC/D,OAAO,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE;QACzC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;YACrE,MAAM,2BAA2B,CAAC,QAAQ,CAAC,CAAC;YAE5C,kCAAkC;YAClC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YACtD,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAErC,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBAC7C,MAAM,EAAE,CAAC,SAAS,CAChB,GAAG,QAAQ,eAAe,EAC1B,IAAI,CAAC,SAAS,CAAC;oBACb,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;iBAC5C,CAAC,CACH,CAAC;YACJ,CAAC;YAED,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,gCAAgC,CAAC,KAAK,EAAE;gBAC7C,MAAM,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,oCAAoC,CAAC,YAAY,EAAE,+BAA+B,QAAQ,EAAE,CAAC,EAAE,eAAe;aAC/I,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC,CAAC;AAEJ,MAAM,CAAC,MAAM,yCAAyC,GACpD,CAAC,MAAyB,EAA+B,EAAE,CAC3D,KAAK,EAAE,SAAoB,EAAgC,EAAE,CAAC,CAAC;IAC7D,CAAC,cAAc,CAAC,mBAAmB,CAAC,EAAE,iCAAiC,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC;CAC3F,CAAC,CAAC","sourcesContent":["import {\n ActionProcessorList,\n ActionProcessorListResolver,\n actionResult,\n actionResultError,\n actionResultErrorFromCaughtError,\n FileActionType,\n FileWriteBinaryContentsActionProcessor,\n FileWriteBinaryContentsErrorTypeEnum,\n QPQConfig,\n} from 'quidproquo-core';\n\nimport * as fs from 'fs/promises';\n\nimport { FileStorageConfig } from './types';\nimport { ensureParentDirectoryExists, resolveFilePath } from './utils';\n\nconst getProcessFileWriteBinaryContents =\n (config: FileStorageConfig) =>\n (qpqConfig: QPQConfig): FileWriteBinaryContentsActionProcessor => {\n return async ({ drive, filepath, data }) => {\n try {\n const fullPath = resolveFilePath(config, qpqConfig, drive, filepath);\n await ensureParentDirectoryExists(fullPath);\n\n // Convert QPQBinaryData to Buffer\n const buffer = Buffer.from(data.base64Data, 'base64');\n await fs.writeFile(fullPath, buffer);\n\n if (data.mimetype || data.contentDisposition) {\n await fs.writeFile(\n `${fullPath}.qpqmeta.json`,\n JSON.stringify({\n mimetype: data.mimetype,\n contentDisposition: data.contentDisposition,\n }),\n );\n }\n\n return actionResult(void 0);\n } catch (error: unknown) {\n return actionResultErrorFromCaughtError(error, {\n EACCES: () => actionResultError(FileWriteBinaryContentsErrorTypeEnum.AccessDenied, `Access denied writing file: ${filepath}`), // node fs code\n });\n }\n };\n };\n\nexport const getFileWriteBinaryContentsActionProcessor =\n (config: FileStorageConfig): ActionProcessorListResolver =>\n async (qpqConfig: QPQConfig): Promise<ActionProcessorList> => ({\n [FileActionType.WriteBinaryContents]: getProcessFileWriteBinaryContents(config)(qpqConfig),\n });\n"]}
|
|
@@ -20,3 +20,4 @@ const getProcessFileWriteObjectJson = (config) => (qpqConfig) => {
|
|
|
20
20
|
export const getFileWriteObjectJsonActionProcessor = (config) => async (qpqConfig) => ({
|
|
21
21
|
[FileActionType.WriteObjectJson]: getProcessFileWriteObjectJson(config)(qpqConfig),
|
|
22
22
|
});
|
|
23
|
+
//# sourceMappingURL=getFileWriteObjectJsonActionProcessor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getFileWriteObjectJsonActionProcessor.js","sourceRoot":"","sources":["../../../../src/dynamicActionProcessor/file/getFileWriteObjectJsonActionProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,YAAY,EACZ,iBAAiB,EACjB,gCAAgC,EAChC,cAAc,EAEd,gCAAgC,GAEjC,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAGlC,OAAO,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEvE,MAAM,6BAA6B,GACjC,CAAC,MAAyB,EAAE,EAAE,CAC9B,CAAC,SAAoB,EAA2C,EAAE;IAChE,OAAO,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE;QACzC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;YACrE,MAAM,2BAA2B,CAAC,QAAQ,CAAC,CAAC;YAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACjD,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;YACjD,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,gCAAgC,CAAC,KAAK,EAAE;gBAC7C,MAAM,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,gCAAgC,CAAC,YAAY,EAAE,+BAA+B,QAAQ,EAAE,CAAC,EAAE,eAAe;aAC3I,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC,CAAC;AAEJ,MAAM,CAAC,MAAM,qCAAqC,GAChD,CAAC,MAAyB,EAA+B,EAAE,CAC3D,KAAK,EAAE,SAAoB,EAAgC,EAAE,CAAC,CAAC;IAC7D,CAAC,cAAc,CAAC,eAAe,CAAC,EAAE,6BAA6B,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC;CACnF,CAAC,CAAC","sourcesContent":["import {\n ActionProcessorList,\n ActionProcessorListResolver,\n actionResult,\n actionResultError,\n actionResultErrorFromCaughtError,\n FileActionType,\n FileWriteObjectJsonActionProcessor,\n FileWriteObjectJsonErrorTypeEnum,\n QPQConfig,\n} from 'quidproquo-core';\n\nimport * as fs from 'fs/promises';\n\nimport { FileStorageConfig } from './types';\nimport { ensureParentDirectoryExists, resolveFilePath } from './utils';\n\nconst getProcessFileWriteObjectJson =\n (config: FileStorageConfig) =>\n (qpqConfig: QPQConfig): FileWriteObjectJsonActionProcessor<any> => {\n return async ({ drive, filepath, data }) => {\n try {\n const fullPath = resolveFilePath(config, qpqConfig, drive, filepath);\n await ensureParentDirectoryExists(fullPath);\n const jsonString = JSON.stringify(data, null, 2);\n await fs.writeFile(fullPath, jsonString, 'utf8');\n return actionResult(void 0);\n } catch (error: unknown) {\n return actionResultErrorFromCaughtError(error, {\n EACCES: () => actionResultError(FileWriteObjectJsonErrorTypeEnum.AccessDenied, `Access denied writing file: ${filepath}`), // node fs code\n });\n }\n };\n };\n\nexport const getFileWriteObjectJsonActionProcessor =\n (config: FileStorageConfig): ActionProcessorListResolver =>\n async (qpqConfig: QPQConfig): Promise<ActionProcessorList> => ({\n [FileActionType.WriteObjectJson]: getProcessFileWriteObjectJson(config)(qpqConfig),\n });\n"]}
|
|
@@ -19,3 +19,4 @@ const getProcessFileWriteTextContents = (qpqConfig, config) => {
|
|
|
19
19
|
export const getFileWriteTextContentsActionProcessor = (config) => async (qpqConfig) => ({
|
|
20
20
|
[FileActionType.WriteTextContents]: getProcessFileWriteTextContents(qpqConfig, config),
|
|
21
21
|
});
|
|
22
|
+
//# sourceMappingURL=getFileWriteTextContentsActionProcessor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getFileWriteTextContentsActionProcessor.js","sourceRoot":"","sources":["../../../../src/dynamicActionProcessor/file/getFileWriteTextContentsActionProcessor.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,YAAY,EACZ,iBAAiB,EACjB,gCAAgC,EAChC,cAAc,EAEd,kCAAkC,GAEnC,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAGlC,OAAO,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEvE,MAAM,+BAA+B,GAAG,CAAC,SAAoB,EAAE,MAAyB,EAAwC,EAAE;IAChI,OAAO,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE;QACzC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;YACrE,MAAM,2BAA2B,CAAC,QAAQ,CAAC,CAAC;YAC5C,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAC3C,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,gCAAgC,CAAC,KAAK,EAAE;gBAC7C,MAAM,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,kCAAkC,CAAC,YAAY,EAAE,+BAA+B,QAAQ,EAAE,CAAC,EAAE,eAAe;aAC7I,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,uCAAuC,GAClD,CAAC,MAAyB,EAA+B,EAAE,CAC3D,KAAK,EAAE,SAAoB,EAAgC,EAAE,CAAC,CAAC;IAC7D,CAAC,cAAc,CAAC,iBAAiB,CAAC,EAAE,+BAA+B,CAAC,SAAS,EAAE,MAAM,CAAC;CACvF,CAAC,CAAC","sourcesContent":["import {\n ActionProcessorList,\n ActionProcessorListResolver,\n actionResult,\n actionResultError,\n actionResultErrorFromCaughtError,\n FileActionType,\n FileWriteTextContentsActionProcessor,\n FileWriteTextContentsErrorTypeEnum,\n QPQConfig,\n} from 'quidproquo-core';\n\nimport * as fs from 'fs/promises';\n\nimport { FileStorageConfig } from './types';\nimport { ensureParentDirectoryExists, resolveFilePath } from './utils';\n\nconst getProcessFileWriteTextContents = (qpqConfig: QPQConfig, config: FileStorageConfig): FileWriteTextContentsActionProcessor => {\n return async ({ drive, filepath, data }) => {\n try {\n const fullPath = resolveFilePath(config, qpqConfig, drive, filepath);\n await ensureParentDirectoryExists(fullPath);\n await fs.writeFile(fullPath, data, 'utf8');\n return actionResult(void 0);\n } catch (error: unknown) {\n return actionResultErrorFromCaughtError(error, {\n EACCES: () => actionResultError(FileWriteTextContentsErrorTypeEnum.AccessDenied, `Access denied writing file: ${filepath}`), // node fs code\n });\n }\n };\n};\n\nexport const getFileWriteTextContentsActionProcessor =\n (config: FileStorageConfig): ActionProcessorListResolver =>\n async (qpqConfig: QPQConfig): Promise<ActionProcessorList> => ({\n [FileActionType.WriteTextContents]: getProcessFileWriteTextContents(qpqConfig, config),\n });\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/dynamicActionProcessor/file/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,EAAE,gDAAgD,EAAE,MAAM,oDAAoD,CAAC;AACtH,OAAO,EAAE,sDAAsD,EAAE,MAAM,0DAA0D,CAAC;AAClI,OAAO,EAAE,mCAAmC,EAAE,MAAM,uCAAuC,CAAC;AAC5F,OAAO,EAAE,mCAAmC,EAAE,MAAM,uCAAuC,CAAC;AAC5F,OAAO,EAAE,wCAAwC,EAAE,MAAM,4CAA4C,CAAC;AACtG,OAAO,EAAE,oCAAoC,EAAE,MAAM,wCAAwC,CAAC;AAC9F,OAAO,EAAE,sCAAsC,EAAE,MAAM,0CAA0C,CAAC;AAClG,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,EAAE,yCAAyC,EAAE,MAAM,6CAA6C,CAAC;AACxG,OAAO,EAAE,qCAAqC,EAAE,MAAM,yCAAyC,CAAC;AAChG,OAAO,EAAE,uCAAuC,EAAE,MAAM,2CAA2C,CAAC;AAGpG,cAAc,SAAS,CAAC;AAExB,yCAAyC;AACzC,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,iBAAoC,EAA+B,EAAE;IAC1G,OAAO,KAAK,EAAE,SAAoB,EAAE,mBAAwC,EAAgC,EAAE,CAAC,CAAC;QAC9G,GAAG,CAAC,MAAM,sCAAsC,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;QACpG,GAAG,CAAC,MAAM,uCAAuC,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;QACrG,GAAG,CAAC,MAAM,oCAAoC,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;QAClG,GAAG,CAAC,MAAM,qCAAqC,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;QACnG,GAAG,CAAC,MAAM,wCAAwC,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;QACtG,GAAG,CAAC,MAAM,yCAAyC,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;QACvG,GAAG,CAAC,MAAM,mCAAmC,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;QACjG,GAAG,CAAC,MAAM,4BAA4B,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;QAC1F,GAAG,CAAC,MAAM,4BAA4B,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;QAC1F,GAAG,CAAC,MAAM,gDAAgD,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;QAC9G,GAAG,CAAC,MAAM,sDAAsD,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;QACpH,GAAG,CAAC,MAAM,mCAAmC,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;QACjG,GAAG,CAAC,MAAM,gCAAgC,CAAC,iBAAiB,CAAC,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;KAC/F,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,cAAc,kBAAkB,CAAC;AACjC,cAAc,SAAS,CAAC","sourcesContent":["import { ActionProcessorList, ActionProcessorListResolver, DynamicModuleLoader, QPQConfig } from 'quidproquo-core';\n\nimport { getFileDeleteActionProcessor } from './getFileDeleteActionProcessor';\nimport { getFileExistsActionProcessor } from './getFileExistsActionProcessor';\nimport { getFileGenerateTemporarySecureUrlActionProcessor } from './getFileGenerateTemporarySecureUrlActionProcessor';\nimport { getFileGenerateTemporaryUploadSecureUrlActionProcessor } from './getFileGenerateTemporaryUploadSecureUrlActionProcessor';\nimport { getFileIsColdStorageActionProcessor } from './getFileIsColdStorageActionProcessor';\nimport { getFileListDirectoryActionProcessor } from './getFileListDirectoryActionProcessor';\nimport { getFileReadBinaryContentsActionProcessor } from './getFileReadBinaryContentsActionProcessor';\nimport { getFileReadObjectJsonActionProcessor } from './getFileReadObjectJsonActionProcessor';\nimport { getFileReadTextContentsActionProcessor } from './getFileReadTextContentsActionProcessor';\nimport { getFileStreamOpenActionProcessor } from './getFileStreamOpenActionProcessor';\nimport { getFileWriteBinaryContentsActionProcessor } from './getFileWriteBinaryContentsActionProcessor';\nimport { getFileWriteObjectJsonActionProcessor } from './getFileWriteObjectJsonActionProcessor';\nimport { getFileWriteTextContentsActionProcessor } from './getFileWriteTextContentsActionProcessor';\nimport { FileStorageConfig } from './types';\n\nexport * from './types';\n\n// Main export that accepts configuration\nexport const getFileActionProcessor = (fileStorageConfig: FileStorageConfig): ActionProcessorListResolver => {\n return async (qpqConfig: QPQConfig, dynamicModuleLoader: DynamicModuleLoader): Promise<ActionProcessorList> => ({\n ...(await getFileReadTextContentsActionProcessor(fileStorageConfig)(qpqConfig, dynamicModuleLoader)),\n ...(await getFileWriteTextContentsActionProcessor(fileStorageConfig)(qpqConfig, dynamicModuleLoader)),\n ...(await getFileReadObjectJsonActionProcessor(fileStorageConfig)(qpqConfig, dynamicModuleLoader)),\n ...(await getFileWriteObjectJsonActionProcessor(fileStorageConfig)(qpqConfig, dynamicModuleLoader)),\n ...(await getFileReadBinaryContentsActionProcessor(fileStorageConfig)(qpqConfig, dynamicModuleLoader)),\n ...(await getFileWriteBinaryContentsActionProcessor(fileStorageConfig)(qpqConfig, dynamicModuleLoader)),\n ...(await getFileListDirectoryActionProcessor(fileStorageConfig)(qpqConfig, dynamicModuleLoader)),\n ...(await getFileExistsActionProcessor(fileStorageConfig)(qpqConfig, dynamicModuleLoader)),\n ...(await getFileDeleteActionProcessor(fileStorageConfig)(qpqConfig, dynamicModuleLoader)),\n ...(await getFileGenerateTemporarySecureUrlActionProcessor(fileStorageConfig)(qpqConfig, dynamicModuleLoader)),\n ...(await getFileGenerateTemporaryUploadSecureUrlActionProcessor(fileStorageConfig)(qpqConfig, dynamicModuleLoader)),\n ...(await getFileIsColdStorageActionProcessor(fileStorageConfig)(qpqConfig, dynamicModuleLoader)),\n ...(await getFileStreamOpenActionProcessor(fileStorageConfig)(qpqConfig, dynamicModuleLoader)),\n });\n};\n\nexport * from './secureUrlUtils';\nexport * from './utils';\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secureUrlUtils.js","sourceRoot":"","sources":["../../../../src/dynamicActionProcessor/file/secureUrlUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAWjC,wCAAwC;AACxC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAqB,EAAE,MAAc,EAAU,EAAE;IACpF,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAEjE,wBAAwB;IACxB,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAEhG,oCAAoC;IACpC,OAAO,GAAG,aAAa,IAAI,SAAS,EAAE,CAAC;AACzC,CAAC,CAAC;AAEF,mCAAmC;AACnC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,WAAmB,EAAE,MAAc,EAAyB,EAAE;IACjG,IAAI,CAAC;QACH,MAAM,CAAC,aAAa,EAAE,SAAS,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAE1D,IAAI,CAAC,aAAa,IAAI,CAAC,SAAS,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,mBAAmB;QACnB,MAAM,iBAAiB,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAExG,IAAI,SAAS,KAAK,iBAAiB,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,iBAAiB;QACjB,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC,QAAQ,EAAE,CAAC;QACnE,MAAM,KAAK,GAAmB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAElD,mBAAmB;QACnB,IAAI,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,8BAA8B;AAC9B,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAAyB,EAAU,EAAE;IACvE,OAAO,UAAU,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;AAClE,CAAC,CAAC","sourcesContent":["import * as crypto from 'crypto';\n\nimport { FileStorageConfig } from './types';\n\nexport interface SecureUrlToken {\n fullFilepath: string;\n operation: 'download' | 'upload';\n expiresAt: number;\n contentType?: string;\n}\n\n// Create a signed token for secure URLs\nexport const createSecureUrlToken = (token: SecureUrlToken, secret: string): string => {\n const payload = JSON.stringify(token);\n const payloadBase64 = Buffer.from(payload).toString('base64url');\n\n // Create HMAC signature\n const signature = crypto.createHmac('sha256', secret).update(payloadBase64).digest('base64url');\n\n // Return token as payload.signature\n return `${payloadBase64}.${signature}`;\n};\n\n// Verify and decode a signed token\nexport const verifySecureUrlToken = (tokenString: string, secret: string): SecureUrlToken | null => {\n try {\n const [payloadBase64, signature] = tokenString.split('.');\n\n if (!payloadBase64 || !signature) {\n return null;\n }\n\n // Verify signature\n const expectedSignature = crypto.createHmac('sha256', secret).update(payloadBase64).digest('base64url');\n\n if (signature !== expectedSignature) {\n return null;\n }\n\n // Decode payload\n const payload = Buffer.from(payloadBase64, 'base64url').toString();\n const token: SecureUrlToken = JSON.parse(payload);\n\n // Check expiration\n if (token.expiresAt < Date.now()) {\n return null;\n }\n\n return token;\n } catch (error) {\n return null;\n }\n};\n\n// Get the secure URL base URL\nexport const getSecureUrlBaseUrl = (config: FileStorageConfig): string => {\n return `http://${config.secureUrlHost}:${config.secureUrlPort}`;\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/dynamicActionProcessor/file/types.ts"],"names":[],"mappings":"","sourcesContent":["// Required config with all fields filled by the dev server\nexport interface FileStorageConfig {\n storagePath: string;\n secureUrlPort: number;\n secureUrlHost: string;\n secureUrlSecret: string;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/dynamicActionProcessor/file/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAI7B,4CAA4C;AAC5C,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,KAAa,EAAE,SAAoB,EAAW,EAAE;IACtF,MAAM,YAAY,GAAG,YAAY,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,KAAK,CAAC,CAAC;IAEpG,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,iFAAiF;AACjF,8EAA8E;AAC9E,6EAA6E;AAC7E,MAAM,UAAU,uBAAuB,CAAC,KAAa,EAAE,SAAoB;IACzE,MAAM,YAAY,GAAG,YAAY,CAAC,qBAAqB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAC1E,OAAO,YAAY,EAAE,KAAK,EAAE,MAAM,IAAI,YAAY,CAAC,wBAAwB,CAAC,SAAS,CAAC,CAAC;AACzF,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,iBAAoC,EAAE,SAAoB,EAAE,KAAa,EAAE,QAAgB;IACzH,MAAM,OAAO,GAAG,uBAAuB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,WAAW,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IAEzE,+CAA+C;IAC/C,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IAED,uEAAuE;IACvE,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IACnC,CAAC;IAED,kDAAkD;IAClD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAEzC,2BAA2B;IAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAE3C,kCAAkC;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,IAAI,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QACnE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;AAC5D,CAAC;AAED,4BAA4B;AAC5B,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EAAE,OAAe,EAAiB,EAAE;IAC5E,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC/C,CAAC,CAAC;AAEF,+CAA+C;AAC/C,MAAM,CAAC,MAAM,2BAA2B,GAAG,KAAK,EAAE,QAAgB,EAAiB,EAAE;IACnF,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,qBAAqB,CAAC,SAAS,CAAC,CAAC;AACzC,CAAC,CAAC","sourcesContent":["import { QPQConfig, qpqCoreUtils } from 'quidproquo-core';\n\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\n\nimport { FileStorageConfig } from './types';\n\n// Resolve a drive name to a filesystem path\nexport const isStorageDriveNameValid = (drive: string, qpqConfig: QPQConfig): boolean => {\n const storageDrive = qpqCoreUtils.getStorageDrives(qpqConfig).find((d) => d.storageDrive === drive);\n\n if (!storageDrive) {\n return false;\n }\n\n return true;\n};\n\n// Resolve the service that owns a drive's on-disk location. Drives declared with\n// `owner.module` are shared across services, so every caller reads and writes\n// under the owner's folder — mirroring how AWS resolves the bucket by owner.\nexport function resolveDriveServiceName(drive: string, qpqConfig: QPQConfig): string {\n const storageDrive = qpqCoreUtils.getStorageDriveByName(drive, qpqConfig);\n return storageDrive?.owner?.module ?? qpqCoreUtils.getApplicationModuleName(qpqConfig);\n}\n\nexport function resolveFilePath(fileStorageConfig: FileStorageConfig, qpqConfig: QPQConfig, drive: string, filepath: string): string {\n const service = resolveDriveServiceName(drive, qpqConfig);\n const root = path.resolve(fileStorageConfig.storagePath, service, drive);\n\n // Block absolute paths and null bytes outright\n if (path.isAbsolute(filepath)) {\n throw new Error('Absolute paths are not allowed.');\n }\n\n // Check for null to prevent directory traversal attacks in native libs\n if (filepath.includes('\\0')) {\n throw new Error('Invalid path.');\n }\n\n // Normalize user input (collapses ., .., slashes)\n const cleaned = path.normalize(filepath);\n\n // Resolve against the root\n const target = path.resolve(root, cleaned);\n\n // Ensure target stays within root\n const rel = path.relative(root, target);\n if (rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel))) {\n return target;\n }\n\n throw new Error('Invalid file path: escapes drive root.');\n}\n\n// Ensure a directory exists\nexport const ensureDirectoryExists = async (dirPath: string): Promise<void> => {\n await fs.mkdir(dirPath, { recursive: true });\n};\n\n// Ensure the parent directory of a file exists\nexport const ensureParentDirectoryExists = async (filePath: string): Promise<void> => {\n const parentDir = path.dirname(filePath);\n await ensureDirectoryExists(parentDir);\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/dynamicActionProcessor/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC","sourcesContent":["export * from './file';\n"]}
|
package/lib/esm/index.d.ts
CHANGED
package/lib/esm/index.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC","sourcesContent":["export * from './actionProcessor';\nexport * from './dynamicActionProcessor';\nexport * from './traceStoryExecution';\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface TraceControllerWorkerData {
|
|
2
|
+
scriptPatterns: string[];
|
|
3
|
+
onlyOwnCode: boolean;
|
|
4
|
+
maxSteps: number;
|
|
5
|
+
maxTraceMs: number;
|
|
6
|
+
maxValueLength: number;
|
|
7
|
+
maxProperties: number;
|
|
8
|
+
maxValueDepth: number;
|
|
9
|
+
maxSerializedLength: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function traceControllerWorkerMain(): void;
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
// The debug controller — runs on a WORKER THREAD and drives the V8 inspector against
|
|
2
|
+
// the MAIN thread, which is executing the story replay (see traceStoryExecution).
|
|
3
|
+
//
|
|
4
|
+
// Strategy (chosen by the phase-0 spike, see trace-replay-plan.md): set a breakpoint on
|
|
5
|
+
// every statement position of the traced scripts up front (getPossibleBreakpoints), then
|
|
6
|
+
// plain resume between hits. This survives the yield -> await -> reader.next() chain of
|
|
7
|
+
// the replay loop regardless of async task boundaries, and wastes no pauses on node
|
|
8
|
+
// internals (unlike blackbox + stepInto).
|
|
9
|
+
//
|
|
10
|
+
// SHIPPING CONSTRAINT: lambdas are single-file webpack bundles, so this can't be loaded
|
|
11
|
+
// as a worker FILE — traceStoryExecution serializes this function with
|
|
12
|
+
// Function.prototype.toString() and runs it via new Worker(source, { eval: true }).
|
|
13
|
+
// It must therefore be fully self-contained:
|
|
14
|
+
// - builtin require()s only, nothing captured from module scope
|
|
15
|
+
// - no syntax tsc would downlevel with module-scope helpers under the ES6 target:
|
|
16
|
+
// no async/await (__awaiter), no generators (__generator), no object spread (__assign)
|
|
17
|
+
//
|
|
18
|
+
// Protocol with the parent (traceStoryExecution):
|
|
19
|
+
// worker -> parent: { type: 'ready', tracedScriptUrls } breakpoints armed, start the replay
|
|
20
|
+
// { type: 'trace', steps, scripts, stats } reply to 'done'
|
|
21
|
+
// { type: 'filterLocations', requestId, scriptUrl, locations } onlyOwnCode: map these through the source map
|
|
22
|
+
// { type: 'fatal', error }
|
|
23
|
+
// parent -> worker: { type: 'done' } replay finished, send the trace
|
|
24
|
+
// { type: 'filteredLocations', requestId, locations } reply to 'filterLocations'
|
|
25
|
+
//
|
|
26
|
+
// The story function is located via globalThis.__qpqTraceStoryFunction (set by the
|
|
27
|
+
// parent before spawning): Runtime.evaluate -> [[FunctionLocation]] -> scriptId. Extra
|
|
28
|
+
// scripts (other bundle chunks, dynamically loaded ones) are matched by scriptPatterns.
|
|
29
|
+
export function traceControllerWorkerMain() {
|
|
30
|
+
// require, not import: this function body is the ENTIRE worker source (eval mode) —
|
|
31
|
+
// imports at module scope wouldn't exist when it runs. And eval('require'), not a
|
|
32
|
+
// bare require: bundlers rewrite require() calls at build time (webpack lambda builds
|
|
33
|
+
// turn them into __webpack_require__, which doesn't exist when this string is eval'd
|
|
34
|
+
// in the worker) — eval is opaque to them, so the worker's REAL cjs require survives.
|
|
35
|
+
const dynamicRequire = eval('require');
|
|
36
|
+
const inspector = dynamicRequire('node:inspector');
|
|
37
|
+
const workerThreads = dynamicRequire('node:worker_threads');
|
|
38
|
+
const parentPort = workerThreads.parentPort;
|
|
39
|
+
const options = workerThreads.workerData;
|
|
40
|
+
const session = new inspector.Session();
|
|
41
|
+
session.connectToMainThread();
|
|
42
|
+
const post = (method, params) => new Promise((resolve, reject) => session.post(method, params || {}, (error, result) => error ? reject(new Error(method + ': ' + error.message)) : resolve(result)));
|
|
43
|
+
const fatal = (error) => {
|
|
44
|
+
parentPort.postMessage({ type: 'fatal', error: String((error && error.stack) || error) });
|
|
45
|
+
};
|
|
46
|
+
const scriptPatterns = options.scriptPatterns.map((pattern) => new RegExp(pattern));
|
|
47
|
+
const scriptUrlsById = new Map();
|
|
48
|
+
const instrumentedScriptIds = new Set();
|
|
49
|
+
// The directory of the story function's own script (set during init). Bundles are
|
|
50
|
+
// chunk-SPLIT: a story exported through a factory wrapper (export const x = wrap(story))
|
|
51
|
+
// has its function object created in the FACTORY's chunk, while the code it runs lives
|
|
52
|
+
// in sibling chunks — so every script in the same directory is traced too. This covers
|
|
53
|
+
// any bundle layout (federated /tmp cache, lambda shell, dev-server dist) without
|
|
54
|
+
// needing an environment-specific pattern.
|
|
55
|
+
let storyScriptDirUrl = '';
|
|
56
|
+
// CJS require() scripts get plain-path urls, ESM imports get file:// urls — the same
|
|
57
|
+
// directory can appear both ways in one process, so compare scheme-stripped.
|
|
58
|
+
const normalizeScriptUrl = (url) => url.replace(/^file:\/\//, '').replace(/\\/g, '/');
|
|
59
|
+
const isTraceTargetUrl = (url) => !!url && (scriptPatterns.some((pattern) => pattern.test(url)) || (!!storyScriptDirUrl && normalizeScriptUrl(url).startsWith(storyScriptDirUrl)));
|
|
60
|
+
const steps = [];
|
|
61
|
+
let pauses = 0;
|
|
62
|
+
let breakpoints = 0;
|
|
63
|
+
let truncated = false;
|
|
64
|
+
let localsCaptureMs = 0;
|
|
65
|
+
let instrumentMs = 0;
|
|
66
|
+
let firstPauseAt = 0;
|
|
67
|
+
let ready = false;
|
|
68
|
+
// ── Value summarization ─────────────────────────────────────────────────────
|
|
69
|
+
// RemoteObject -> short display string. Depth comes from generatePreview (one level);
|
|
70
|
+
// the caps keep pathological values from exploding the trace.
|
|
71
|
+
const clampText = (text) => (text.length > options.maxValueLength ? text.slice(0, options.maxValueLength) + '…' : text);
|
|
72
|
+
const summarizeValue = (remoteObject) => {
|
|
73
|
+
if (!remoteObject)
|
|
74
|
+
return 'undefined';
|
|
75
|
+
if (remoteObject.type === 'undefined')
|
|
76
|
+
return 'undefined';
|
|
77
|
+
if (remoteObject.subtype === 'null')
|
|
78
|
+
return 'null';
|
|
79
|
+
if (remoteObject.unserializableValue)
|
|
80
|
+
return remoteObject.unserializableValue;
|
|
81
|
+
if (remoteObject.type === 'string' || remoteObject.type === 'number' || remoteObject.type === 'boolean') {
|
|
82
|
+
return clampText(JSON.stringify(remoteObject.value));
|
|
83
|
+
}
|
|
84
|
+
if (remoteObject.preview) {
|
|
85
|
+
const parts = [];
|
|
86
|
+
const previewProperties = remoteObject.preview.properties || [];
|
|
87
|
+
for (let i = 0; i < previewProperties.length && i < options.maxProperties; i += 1) {
|
|
88
|
+
const property = previewProperties[i];
|
|
89
|
+
const value = property.type === 'string' ? "'" + property.value + "'" : property.value;
|
|
90
|
+
parts.push(remoteObject.preview.subtype === 'array' ? value : property.name + ': ' + value);
|
|
91
|
+
}
|
|
92
|
+
const overflow = remoteObject.preview.overflow || previewProperties.length > options.maxProperties ? ', …' : '';
|
|
93
|
+
const body = parts.join(', ') + overflow;
|
|
94
|
+
return clampText(remoteObject.preview.subtype === 'array' ? '[' + body + ']' : '{' + body + '}');
|
|
95
|
+
}
|
|
96
|
+
return clampText(remoteObject.description || remoteObject.type);
|
|
97
|
+
};
|
|
98
|
+
// ── Deep serialization ──────────────────────────────────────────────────────
|
|
99
|
+
// Runs IN THE DEBUGGEE (Runtime.callFunctionOn with `this` = the value) at the pause,
|
|
100
|
+
// returning a JSON string of the value walked to the caps — what powers expandable
|
|
101
|
+
// object inspection in the viewer. Property reads are try/catch'd (getters can throw);
|
|
102
|
+
// circular refs and overflow become «...» placeholder strings. Same serialization
|
|
103
|
+
// constraints as this whole file: no async/generators/spread (it ships via toString).
|
|
104
|
+
function qpqSerializeValue(maxDepth, maxString, maxProps, maxTotal) {
|
|
105
|
+
const seen = [];
|
|
106
|
+
const walk = (value, depth) => {
|
|
107
|
+
if (value === null || typeof value === 'number' || typeof value === 'boolean')
|
|
108
|
+
return value;
|
|
109
|
+
if (typeof value === 'string')
|
|
110
|
+
return value.length > maxString ? value.slice(0, maxString) + '…' : value;
|
|
111
|
+
if (typeof value === 'undefined')
|
|
112
|
+
return '«undefined»';
|
|
113
|
+
if (typeof value === 'function')
|
|
114
|
+
return '«function ' + (value.name || '') + '»';
|
|
115
|
+
if (typeof value === 'bigint')
|
|
116
|
+
return value.toString() + 'n';
|
|
117
|
+
if (typeof value === 'symbol')
|
|
118
|
+
return value.toString();
|
|
119
|
+
if (value instanceof Date)
|
|
120
|
+
return value.toISOString();
|
|
121
|
+
if (value instanceof Error)
|
|
122
|
+
return '«' + (value.name || 'Error') + ': ' + value.message + '»';
|
|
123
|
+
if (value instanceof Map)
|
|
124
|
+
return '«Map(' + value.size + ')»';
|
|
125
|
+
if (value instanceof Set)
|
|
126
|
+
return '«Set(' + value.size + ')»';
|
|
127
|
+
if (depth >= maxDepth)
|
|
128
|
+
return Array.isArray(value) ? '«array[' + value.length + ']»' : '«object»';
|
|
129
|
+
if (seen.indexOf(value) >= 0)
|
|
130
|
+
return '«circular»';
|
|
131
|
+
seen.push(value);
|
|
132
|
+
let result;
|
|
133
|
+
if (Array.isArray(value)) {
|
|
134
|
+
result = [];
|
|
135
|
+
for (let i = 0; i < value.length && i < maxProps; i += 1) {
|
|
136
|
+
try {
|
|
137
|
+
result.push(walk(value[i], depth + 1));
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
result.push('«threw»');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (value.length > maxProps)
|
|
144
|
+
result.push('«+' + (value.length - maxProps) + ' more»');
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
result = {};
|
|
148
|
+
const keys = Object.keys(value);
|
|
149
|
+
for (let i = 0; i < keys.length && i < maxProps; i += 1) {
|
|
150
|
+
try {
|
|
151
|
+
result[keys[i]] = walk(value[keys[i]], depth + 1);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
result[keys[i]] = '«threw»';
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (keys.length > maxProps)
|
|
158
|
+
result['«more»'] = '+' + (keys.length - maxProps) + ' properties';
|
|
159
|
+
}
|
|
160
|
+
seen.pop();
|
|
161
|
+
return result;
|
|
162
|
+
};
|
|
163
|
+
try {
|
|
164
|
+
const json = JSON.stringify(walk(this, 0));
|
|
165
|
+
return json && json.length <= maxTotal ? json : null;
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const isDeepSerializable = (remoteObject) => !!remoteObject && remoteObject.type === 'object' && remoteObject.subtype !== 'null' && !!remoteObject.objectId;
|
|
172
|
+
// ── Value capture ───────────────────────────────────────────────────────────
|
|
173
|
+
// Every value gets a short preview; object values also get a deep JSON serialization
|
|
174
|
+
// (in the debuggee, see qpqSerializeValue). Never fails — a value that can't be
|
|
175
|
+
// serialized keeps its preview.
|
|
176
|
+
const captureRemoteValue = (remoteObject) => {
|
|
177
|
+
const captured = { preview: summarizeValue(remoteObject) };
|
|
178
|
+
if (!isDeepSerializable(remoteObject)) {
|
|
179
|
+
return { captured, work: Promise.resolve() };
|
|
180
|
+
}
|
|
181
|
+
const work = post('Runtime.callFunctionOn', {
|
|
182
|
+
objectId: remoteObject.objectId,
|
|
183
|
+
functionDeclaration: qpqSerializeValue.toString(),
|
|
184
|
+
arguments: [
|
|
185
|
+
{ value: options.maxValueDepth },
|
|
186
|
+
{ value: options.maxValueLength },
|
|
187
|
+
{ value: options.maxProperties },
|
|
188
|
+
{ value: options.maxSerializedLength },
|
|
189
|
+
],
|
|
190
|
+
returnByValue: true,
|
|
191
|
+
}).then((result) => {
|
|
192
|
+
if (result && result.result && typeof result.result.value === 'string') {
|
|
193
|
+
captured.json = result.result.value;
|
|
194
|
+
}
|
|
195
|
+
}, () => undefined);
|
|
196
|
+
return { captured, work };
|
|
197
|
+
};
|
|
198
|
+
// Local + block scopes only, outermost first so inner scopes win name collisions.
|
|
199
|
+
// At a return break position the frame also carries the value being returned.
|
|
200
|
+
const captureStepValues = (frame) => {
|
|
201
|
+
const startedAt = Date.now();
|
|
202
|
+
const values = { locals: {} };
|
|
203
|
+
const scopes = frame.scopeChain
|
|
204
|
+
.filter((scope) => (scope.type === 'local' || scope.type === 'block') && scope.object && scope.object.objectId)
|
|
205
|
+
.reverse();
|
|
206
|
+
let chain = Promise.resolve();
|
|
207
|
+
scopes.forEach((scope) => {
|
|
208
|
+
chain = chain
|
|
209
|
+
.then(() => post('Runtime.getProperties', { objectId: scope.object.objectId, ownProperties: true, generatePreview: true }))
|
|
210
|
+
.then((response) => {
|
|
211
|
+
let valueChain = Promise.resolve();
|
|
212
|
+
(response.result || []).forEach((property) => {
|
|
213
|
+
const capture = captureRemoteValue(property.value);
|
|
214
|
+
values.locals[property.name] = capture.captured;
|
|
215
|
+
valueChain = valueChain.then(() => capture.work);
|
|
216
|
+
});
|
|
217
|
+
return valueChain;
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
if (frame.returnValue) {
|
|
221
|
+
const returnCapture = captureRemoteValue(frame.returnValue);
|
|
222
|
+
values.returnValue = returnCapture.captured;
|
|
223
|
+
chain = chain.then(() => returnCapture.work);
|
|
224
|
+
}
|
|
225
|
+
return chain.then(() => {
|
|
226
|
+
localsCaptureMs += Date.now() - startedAt;
|
|
227
|
+
return values;
|
|
228
|
+
});
|
|
229
|
+
};
|
|
230
|
+
// ── Script instrumentation ──────────────────────────────────────────────────
|
|
231
|
+
// onlyOwnCode: the parent (traceStoryExecution) filters candidate locations through
|
|
232
|
+
// the script's source map — only positions originating in the service's own code
|
|
233
|
+
// (not node_modules) get breakpoints. Round-tripped over parentPort because this
|
|
234
|
+
// worker can't load the source-map library (see the shipping constraint above).
|
|
235
|
+
let filterRequestSeq = 0;
|
|
236
|
+
const pendingFilterRequests = new Map();
|
|
237
|
+
const filterLocationsViaParent = (scriptId, locations) => {
|
|
238
|
+
if (!options.onlyOwnCode || locations.length === 0)
|
|
239
|
+
return Promise.resolve(locations);
|
|
240
|
+
filterRequestSeq += 1;
|
|
241
|
+
const requestId = filterRequestSeq;
|
|
242
|
+
return new Promise((resolve) => {
|
|
243
|
+
pendingFilterRequests.set(requestId, resolve);
|
|
244
|
+
parentPort.postMessage({ type: 'filterLocations', requestId, scriptUrl: scriptUrlsById.get(scriptId) || '', locations });
|
|
245
|
+
});
|
|
246
|
+
};
|
|
247
|
+
// getPossibleBreakpoints CAPS its response (~1000 locations) when the range is large —
|
|
248
|
+
// on a real bundle chunk (tens of thousands of lines) a single call covers only the
|
|
249
|
+
// top of the file and everything below it silently gets no breakpoints. Page through
|
|
250
|
+
// the script, restarting just past the last returned location, until a page comes back
|
|
251
|
+
// empty or stops advancing.
|
|
252
|
+
const getAllPossibleBreakpoints = (scriptId) => {
|
|
253
|
+
const allLocations = [];
|
|
254
|
+
const readPage = (startLine, startColumn) => post('Debugger.getPossibleBreakpoints', { start: { scriptId, lineNumber: startLine, columnNumber: startColumn } }).then((response) => {
|
|
255
|
+
const locations = response.locations || [];
|
|
256
|
+
if (locations.length === 0)
|
|
257
|
+
return allLocations;
|
|
258
|
+
locations.forEach((location) => allLocations.push(location));
|
|
259
|
+
const last = locations[locations.length - 1];
|
|
260
|
+
const nextLine = last.lineNumber;
|
|
261
|
+
const nextColumn = (last.columnNumber || 0) + 1;
|
|
262
|
+
if (nextLine < startLine || (nextLine === startLine && nextColumn <= startColumn))
|
|
263
|
+
return allLocations;
|
|
264
|
+
return readPage(nextLine, nextColumn);
|
|
265
|
+
});
|
|
266
|
+
return readPage(0, 0);
|
|
267
|
+
};
|
|
268
|
+
const instrumentScript = (scriptId) => {
|
|
269
|
+
if (instrumentedScriptIds.has(scriptId))
|
|
270
|
+
return Promise.resolve();
|
|
271
|
+
instrumentedScriptIds.add(scriptId);
|
|
272
|
+
return getAllPossibleBreakpoints(scriptId)
|
|
273
|
+
.then((locations) => filterLocationsViaParent(scriptId, locations))
|
|
274
|
+
.then((locations) => {
|
|
275
|
+
// PIPELINED, not chained: a service's chunks can hold tens of thousands of
|
|
276
|
+
// statement positions, and awaiting each setBreakpoint round-trip serially made
|
|
277
|
+
// instrumentation the dominant setup cost (it blew the ready timeout on real
|
|
278
|
+
// services). The session queues the posts; the backend processes them in order.
|
|
279
|
+
// Per-location failures are tolerated: nearby candidate positions can RESOLVE to
|
|
280
|
+
// the same actual breakpoint ("already exists") — one lost position must not
|
|
281
|
+
// abort the whole trace.
|
|
282
|
+
return Promise.all(locations.map((location) => post('Debugger.setBreakpoint', { location }).then(() => {
|
|
283
|
+
breakpoints += 1;
|
|
284
|
+
}, () => undefined))).then(() => undefined);
|
|
285
|
+
});
|
|
286
|
+
};
|
|
287
|
+
session.on('Debugger.scriptParsed', (message) => {
|
|
288
|
+
const url = message.params.url || '';
|
|
289
|
+
scriptUrlsById.set(message.params.scriptId, url);
|
|
290
|
+
// A traced bundle chunk loaded mid-story (async-node chunk loading) — instrument it
|
|
291
|
+
// as it appears so its statements are traced too.
|
|
292
|
+
if (ready && isTraceTargetUrl(url)) {
|
|
293
|
+
instrumentScript(message.params.scriptId).catch(fatal);
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
// ── Pause loop ──────────────────────────────────────────────────────────────
|
|
297
|
+
const onPaused = (message) => {
|
|
298
|
+
pauses += 1;
|
|
299
|
+
if (!firstPauseAt)
|
|
300
|
+
firstPauseAt = Date.now();
|
|
301
|
+
const frame = message.params.callFrames[0];
|
|
302
|
+
// Non-traced pause (e.g. the debugger; statement in qpqExecuteLog) — just resume.
|
|
303
|
+
if (!instrumentedScriptIds.has(frame.location.scriptId)) {
|
|
304
|
+
return post('Debugger.resume');
|
|
305
|
+
}
|
|
306
|
+
// Step budget AND wall-clock budget: locals capture costs several CDP round trips
|
|
307
|
+
// per step, so a big story can take MINUTES against maxSteps alone — long-running
|
|
308
|
+
// invocations stress their whole sandbox (a >5min trace exposed a 300s long-poll
|
|
309
|
+
// timeout bug in the qpq-log-extension, killing the lambda). Past either budget,
|
|
310
|
+
// stop pausing entirely so the replay finishes at full speed.
|
|
311
|
+
if (steps.length >= options.maxSteps || Date.now() - firstPauseAt > options.maxTraceMs) {
|
|
312
|
+
truncated = true;
|
|
313
|
+
return post('Debugger.setBreakpointsActive', { active: false }).then(() => post('Debugger.resume'));
|
|
314
|
+
}
|
|
315
|
+
return captureStepValues(frame)
|
|
316
|
+
.then((values) => {
|
|
317
|
+
const step = {
|
|
318
|
+
scriptId: frame.location.scriptId,
|
|
319
|
+
line: frame.location.lineNumber,
|
|
320
|
+
column: frame.location.columnNumber,
|
|
321
|
+
functionName: frame.functionName || '',
|
|
322
|
+
locals: values.locals,
|
|
323
|
+
};
|
|
324
|
+
if (values.returnValue) {
|
|
325
|
+
step.returnValue = values.returnValue;
|
|
326
|
+
}
|
|
327
|
+
steps.push(step);
|
|
328
|
+
})
|
|
329
|
+
.then(() => post('Debugger.resume'));
|
|
330
|
+
};
|
|
331
|
+
session.on('Debugger.paused', (message) => {
|
|
332
|
+
onPaused(message).catch(fatal);
|
|
333
|
+
});
|
|
334
|
+
// ── Parent protocol (also keeps the worker's event loop alive — an inspector
|
|
335
|
+
// session alone does not, the worker would silently exit) ────────────────────
|
|
336
|
+
parentPort.on('message', (message) => {
|
|
337
|
+
if (message && message.type === 'filteredLocations') {
|
|
338
|
+
const resolveFilter = pendingFilterRequests.get(message.requestId);
|
|
339
|
+
if (resolveFilter) {
|
|
340
|
+
pendingFilterRequests.delete(message.requestId);
|
|
341
|
+
resolveFilter(message.locations || []);
|
|
342
|
+
}
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
if (message && message.type === 'done') {
|
|
346
|
+
const scripts = {};
|
|
347
|
+
scriptUrlsById.forEach((url, scriptId) => {
|
|
348
|
+
scripts[scriptId] = url;
|
|
349
|
+
});
|
|
350
|
+
const instrumentedScriptUrls = [];
|
|
351
|
+
instrumentedScriptIds.forEach((scriptId) => {
|
|
352
|
+
instrumentedScriptUrls.push(scriptUrlsById.get(scriptId) || scriptId);
|
|
353
|
+
});
|
|
354
|
+
parentPort.postMessage({
|
|
355
|
+
type: 'trace',
|
|
356
|
+
steps,
|
|
357
|
+
scripts,
|
|
358
|
+
stats: { pauses, breakpoints, localsCaptureMs, truncated, instrumentMs, instrumentedScriptUrls },
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
// ── Init: enable domains, find the story function's script, arm breakpoints ──
|
|
363
|
+
const initStartedAt = Date.now();
|
|
364
|
+
post('Runtime.enable')
|
|
365
|
+
.then(() => post('Debugger.enable'))
|
|
366
|
+
.then(() => post('Runtime.evaluate', { expression: 'globalThis.__qpqTraceStoryFunction' }))
|
|
367
|
+
.then((evaluation) => {
|
|
368
|
+
const objectId = evaluation && evaluation.result && evaluation.result.objectId;
|
|
369
|
+
if (!objectId)
|
|
370
|
+
return null;
|
|
371
|
+
return post('Runtime.getProperties', { objectId, ownProperties: true }).then((response) => {
|
|
372
|
+
const functionLocation = (response.internalProperties || []).find((property) => property.name === '[[FunctionLocation]]');
|
|
373
|
+
const location = functionLocation && functionLocation.value && functionLocation.value.value;
|
|
374
|
+
return location ? location.scriptId : null;
|
|
375
|
+
});
|
|
376
|
+
})
|
|
377
|
+
.then((storyFunctionScriptId) => {
|
|
378
|
+
const targetScriptIds = new Set();
|
|
379
|
+
if (storyFunctionScriptId) {
|
|
380
|
+
targetScriptIds.add(storyFunctionScriptId);
|
|
381
|
+
const storyScriptUrl = normalizeScriptUrl(scriptUrlsById.get(storyFunctionScriptId) || '');
|
|
382
|
+
storyScriptDirUrl = storyScriptUrl.slice(0, storyScriptUrl.lastIndexOf('/') + 1);
|
|
383
|
+
}
|
|
384
|
+
scriptUrlsById.forEach((url, scriptId) => {
|
|
385
|
+
if (isTraceTargetUrl(url))
|
|
386
|
+
targetScriptIds.add(scriptId);
|
|
387
|
+
});
|
|
388
|
+
if (targetScriptIds.size === 0) {
|
|
389
|
+
throw new Error('trace controller found no scripts to trace (no story function location, no scriptPatterns match)');
|
|
390
|
+
}
|
|
391
|
+
const instrumentations = [];
|
|
392
|
+
targetScriptIds.forEach((scriptId) => {
|
|
393
|
+
instrumentations.push(instrumentScript(scriptId));
|
|
394
|
+
});
|
|
395
|
+
return Promise.all(instrumentations).then(() => targetScriptIds);
|
|
396
|
+
})
|
|
397
|
+
.then((targetScriptIds) => {
|
|
398
|
+
ready = true;
|
|
399
|
+
instrumentMs = Date.now() - initStartedAt;
|
|
400
|
+
const tracedScriptUrls = [];
|
|
401
|
+
targetScriptIds.forEach((scriptId) => tracedScriptUrls.push(scriptUrlsById.get(scriptId) || scriptId));
|
|
402
|
+
parentPort.postMessage({ type: 'ready', tracedScriptUrls });
|
|
403
|
+
})
|
|
404
|
+
.catch(fatal);
|
|
405
|
+
}
|
|
406
|
+
//# sourceMappingURL=controllerWorker.js.map
|