From e23d2ef186077732ed30d4758874536fb766ddb5 Mon Sep 17 00:00:00 2001 From: Mark Reidenbach Date: Thu, 15 Aug 2024 13:41:05 -0500 Subject: [PATCH 1/8] Rename .js to .mjs and set type=module in package.json --- package.json | 7 ++++--- src/node-process/{Connection.js => Connection.mjs} | 0 .../{ConnectionDelegate.js => ConnectionDelegate.mjs} | 0 .../Data/{ResourceIdentity.js => ResourceIdentity.mjs} | 0 .../Data/{ResourceRepository.js => ResourceRepository.mjs} | 0 src/node-process/Data/{Serializer.js => Serializer.mjs} | 0 .../Data/{Unserializer.js => Unserializer.mjs} | 0 src/node-process/Data/{Value.js => Value.mjs} | 0 src/node-process/{Instruction.js => Instruction.mjs} | 0 src/node-process/{Logger.js => Logger.mjs} | 0 .../{ConsoleInterceptor.js => ConsoleInterceptor.mjs} | 0 ...treamsInterceptor.js => StandardStreamsInterceptor.mjs} | 0 src/node-process/{Server.js => Server.mjs} | 0 src/node-process/{index.js => index.mjs} | 0 src/node-process/{serve.js => serve.mjs} | 0 15 files changed, 4 insertions(+), 3 deletions(-) rename src/node-process/{Connection.js => Connection.mjs} (100%) rename src/node-process/{ConnectionDelegate.js => ConnectionDelegate.mjs} (100%) rename src/node-process/Data/{ResourceIdentity.js => ResourceIdentity.mjs} (100%) rename src/node-process/Data/{ResourceRepository.js => ResourceRepository.mjs} (100%) rename src/node-process/Data/{Serializer.js => Serializer.mjs} (100%) rename src/node-process/Data/{Unserializer.js => Unserializer.mjs} (100%) rename src/node-process/Data/{Value.js => Value.mjs} (100%) rename src/node-process/{Instruction.js => Instruction.mjs} (100%) rename src/node-process/{Logger.js => Logger.mjs} (100%) rename src/node-process/NodeInterceptors/{ConsoleInterceptor.js => ConsoleInterceptor.mjs} (100%) rename src/node-process/NodeInterceptors/{StandardStreamsInterceptor.js => StandardStreamsInterceptor.mjs} (100%) rename src/node-process/{Server.js => Server.mjs} (100%) rename src/node-process/{index.js => index.mjs} (100%) rename src/node-process/{serve.js => serve.mjs} (100%) diff --git a/package.json b/package.json index acdaa39..57c3131 100644 --- a/package.json +++ b/package.json @@ -16,10 +16,11 @@ "url": "https://johann.pardanaud.com/" }, "license": "MIT", - "repository": "github:zoonru/rialto", - "main": "src/node-process", + "repository": "github:mreiden/rialto", + "type": "module", + "main": "src/node-process/index.mjs", "engines": { - "node": ">=8.0.0" + "node": ">=18.0.0" }, "dependencies": { "lodash": "^4.17.10" diff --git a/src/node-process/Connection.js b/src/node-process/Connection.mjs similarity index 100% rename from src/node-process/Connection.js rename to src/node-process/Connection.mjs diff --git a/src/node-process/ConnectionDelegate.js b/src/node-process/ConnectionDelegate.mjs similarity index 100% rename from src/node-process/ConnectionDelegate.js rename to src/node-process/ConnectionDelegate.mjs diff --git a/src/node-process/Data/ResourceIdentity.js b/src/node-process/Data/ResourceIdentity.mjs similarity index 100% rename from src/node-process/Data/ResourceIdentity.js rename to src/node-process/Data/ResourceIdentity.mjs diff --git a/src/node-process/Data/ResourceRepository.js b/src/node-process/Data/ResourceRepository.mjs similarity index 100% rename from src/node-process/Data/ResourceRepository.js rename to src/node-process/Data/ResourceRepository.mjs diff --git a/src/node-process/Data/Serializer.js b/src/node-process/Data/Serializer.mjs similarity index 100% rename from src/node-process/Data/Serializer.js rename to src/node-process/Data/Serializer.mjs diff --git a/src/node-process/Data/Unserializer.js b/src/node-process/Data/Unserializer.mjs similarity index 100% rename from src/node-process/Data/Unserializer.js rename to src/node-process/Data/Unserializer.mjs diff --git a/src/node-process/Data/Value.js b/src/node-process/Data/Value.mjs similarity index 100% rename from src/node-process/Data/Value.js rename to src/node-process/Data/Value.mjs diff --git a/src/node-process/Instruction.js b/src/node-process/Instruction.mjs similarity index 100% rename from src/node-process/Instruction.js rename to src/node-process/Instruction.mjs diff --git a/src/node-process/Logger.js b/src/node-process/Logger.mjs similarity index 100% rename from src/node-process/Logger.js rename to src/node-process/Logger.mjs diff --git a/src/node-process/NodeInterceptors/ConsoleInterceptor.js b/src/node-process/NodeInterceptors/ConsoleInterceptor.mjs similarity index 100% rename from src/node-process/NodeInterceptors/ConsoleInterceptor.js rename to src/node-process/NodeInterceptors/ConsoleInterceptor.mjs diff --git a/src/node-process/NodeInterceptors/StandardStreamsInterceptor.js b/src/node-process/NodeInterceptors/StandardStreamsInterceptor.mjs similarity index 100% rename from src/node-process/NodeInterceptors/StandardStreamsInterceptor.js rename to src/node-process/NodeInterceptors/StandardStreamsInterceptor.mjs diff --git a/src/node-process/Server.js b/src/node-process/Server.mjs similarity index 100% rename from src/node-process/Server.js rename to src/node-process/Server.mjs diff --git a/src/node-process/index.js b/src/node-process/index.mjs similarity index 100% rename from src/node-process/index.js rename to src/node-process/index.mjs diff --git a/src/node-process/serve.js b/src/node-process/serve.mjs similarity index 100% rename from src/node-process/serve.js rename to src/node-process/serve.mjs From 37c9769f0fb0dc38acfc4fa94c8573ce5958411d Mon Sep 17 00:00:00 2001 From: Mark Reidenbach Date: Thu, 15 Aug 2024 13:59:59 -0500 Subject: [PATCH 2/8] Use import, export default, and .mjs for modules --- src/ProcessSupervisor.php | 5 +++-- src/node-process/Connection.mjs | 18 ++++++++---------- src/node-process/ConnectionDelegate.mjs | 4 +--- src/node-process/Data/ResourceIdentity.mjs | 4 +--- src/node-process/Data/ResourceRepository.mjs | 10 ++++------ src/node-process/Data/Serializer.mjs | 6 ++---- src/node-process/Data/Unserializer.mjs | 12 +++++------- src/node-process/Data/Value.mjs | 6 ++---- src/node-process/Instruction.mjs | 6 ++---- src/node-process/Logger.mjs | 4 +--- .../NodeInterceptors/ConsoleInterceptor.mjs | 6 ++---- .../StandardStreamsInterceptor.mjs | 8 +++----- src/node-process/Server.mjs | 8 +++----- src/node-process/index.mjs | 6 +++--- src/node-process/serve.mjs | 11 ++++++----- 15 files changed, 46 insertions(+), 68 deletions(-) diff --git a/src/ProcessSupervisor.php b/src/ProcessSupervisor.php index 7b765b7..25ce604 100644 --- a/src/ProcessSupervisor.php +++ b/src/ProcessSupervisor.php @@ -225,12 +225,13 @@ protected function getProcessScriptPath(): string { } // The script path in local development - $scriptPath = __DIR__.'/node-process/serve.js'; + $scriptPath = __DIR__.'/node-process/serve.mjs'; $process = new SymfonyProcess([ $this->options['executable_path'], '-e', - "process.stdout.write(require.resolve('@zoon/rialto/src/node-process/serve.js'))", + //"process.stdout.write(require.resolve('@zoon/rialto/src/node-process/serve.mjs'))", + $scriptPath, ]); $exitCode = $process->run(); diff --git a/src/node-process/Connection.mjs b/src/node-process/Connection.mjs index 685e37f..cd16501 100644 --- a/src/node-process/Connection.mjs +++ b/src/node-process/Connection.mjs @@ -1,17 +1,17 @@ 'use strict'; -const EventEmitter = require('events'), - ConnectionDelegate = require('./ConnectionDelegate'), - ResourceRepository = require('./Data/ResourceRepository'), - Instruction = require('./Instruction'), - DataSerializer = require('./Data/Serializer'), - DataUnserializer = require('./Data/Unserializer'), - Logger = require('./Logger'); +import EventEmitter from 'events'; +import ConnectionDelegate from './ConnectionDelegate.mjs'; +import ResourceRepository from './Data/ResourceRepository.mjs'; +import Instruction from './Instruction.mjs'; +import DataSerializer from './Data/Serializer.mjs'; +import DataUnserializer from './Data/Unserializer.mjs' +import Logger from './Logger.mjs'; /** * Handle a connection interacting with this process. */ -class Connection extends EventEmitter +export default class Connection extends EventEmitter { /** * Constructor. @@ -159,5 +159,3 @@ Connection.SOCKET_PACKET_SIZE = 1024; * @type {number} */ Connection.SOCKET_HEADER_SIZE = 5; - -module.exports = Connection; diff --git a/src/node-process/ConnectionDelegate.mjs b/src/node-process/ConnectionDelegate.mjs index 0b7753e..5c15844 100644 --- a/src/node-process/ConnectionDelegate.mjs +++ b/src/node-process/ConnectionDelegate.mjs @@ -13,7 +13,7 @@ /** * Handle the requests of a connection. */ -class ConnectionDelegate +export default class ConnectionDelegate { /** * Constructor. @@ -37,5 +37,3 @@ class ConnectionDelegate responseHandler(null); } } - -module.exports = ConnectionDelegate; diff --git a/src/node-process/Data/ResourceIdentity.mjs b/src/node-process/Data/ResourceIdentity.mjs index 32f553f..6c67f46 100644 --- a/src/node-process/Data/ResourceIdentity.mjs +++ b/src/node-process/Data/ResourceIdentity.mjs @@ -1,6 +1,6 @@ 'use strict'; -class ResourceIdentity +export default class ResourceIdentity { /** * Constructor. @@ -58,5 +58,3 @@ class ResourceIdentity }; } } - -module.exports = ResourceIdentity; diff --git a/src/node-process/Data/ResourceRepository.mjs b/src/node-process/Data/ResourceRepository.mjs index 77bf9c7..f88745f 100644 --- a/src/node-process/Data/ResourceRepository.mjs +++ b/src/node-process/Data/ResourceRepository.mjs @@ -1,15 +1,15 @@ 'use strict'; -const ResourceIdentity = require('./ResourceIdentity'); +import ResourceIdentity from './ResourceIdentity.mjs'; -class ResourceRepository +export default class ResourceRepository { /** * Constructor. */ constructor() { - this.resources = new Map; + this.resources = new Map(); } /** @@ -108,6 +108,4 @@ class ResourceRepository } } -ResourceRepository.globalResources = new Map; - -module.exports = ResourceRepository; +ResourceRepository.globalResources = new Map(); diff --git a/src/node-process/Data/Serializer.mjs b/src/node-process/Data/Serializer.mjs index ddd88dc..c5c9c78 100644 --- a/src/node-process/Data/Serializer.mjs +++ b/src/node-process/Data/Serializer.mjs @@ -1,8 +1,8 @@ 'use strict'; -const Value = require('./Value'); +import Value from './Value.mjs'; -class Serializer +export default class Serializer { /** * Serialize an error to JSON. @@ -48,5 +48,3 @@ class Serializer } } } - -module.exports = Serializer; diff --git a/src/node-process/Data/Unserializer.mjs b/src/node-process/Data/Unserializer.mjs index 802b774..b183f20 100644 --- a/src/node-process/Data/Unserializer.mjs +++ b/src/node-process/Data/Unserializer.mjs @@ -1,14 +1,14 @@ 'use strict'; -const _ = require('lodash'), - Value = require('./Value'), - ResourceIdentity = require('./ResourceIdentity'), - ResourceRepository = require('./ResourceRepository'); +import _ from 'lodash'; +import Value from './Value.mjs'; +import ResourceIdentity from './ResourceIdentity.mjs'; +import ResourceRepository from './ResourceRepository.mjs'; // Some unserialized functions require an access to the ResourceRepository class, so we must put it in the global scope. global.__rialto_ResourceRepository__ = ResourceRepository; -class Unserializer +export default class Unserializer { /** * Constructor. @@ -94,5 +94,3 @@ class Unserializer `)(); } } - -module.exports = Unserializer; diff --git a/src/node-process/Data/Value.mjs b/src/node-process/Data/Value.mjs index fcaf879..2ece356 100644 --- a/src/node-process/Data/Value.mjs +++ b/src/node-process/Data/Value.mjs @@ -1,8 +1,8 @@ 'use strict'; -const _ = require('lodash'); +import _ from 'lodash'; -class Value +export default class Value { /** * Determine if the value is a string, a number, a boolean, or null. @@ -59,5 +59,3 @@ class Value return !Value.isContainer(value) && !Value.isScalar(value); } } - -module.exports = Value; diff --git a/src/node-process/Instruction.mjs b/src/node-process/Instruction.mjs index d411b8b..75ee1ac 100644 --- a/src/node-process/Instruction.mjs +++ b/src/node-process/Instruction.mjs @@ -1,8 +1,8 @@ 'use strict'; -const ResourceIdentity = require('./Data/ResourceIdentity'); +import ResourceIdentity from './Data/ResourceIdentity.mjs'; -class Instruction +export default class Instruction { /** * Constructor. @@ -221,5 +221,3 @@ Object.assign(Instruction, { TYPE_GET: 'get', TYPE_SET: 'set', }); - -module.exports = Instruction; diff --git a/src/node-process/Logger.mjs b/src/node-process/Logger.mjs index cbbb190..44d6660 100644 --- a/src/node-process/Logger.mjs +++ b/src/node-process/Logger.mjs @@ -1,6 +1,6 @@ 'use strict'; -class Logger +export default class Logger { /** * Add a new log to the queue. @@ -26,5 +26,3 @@ class Logger } Logger.logsQueue = []; - -module.exports = Logger; diff --git a/src/node-process/NodeInterceptors/ConsoleInterceptor.mjs b/src/node-process/NodeInterceptors/ConsoleInterceptor.mjs index 6fc6e39..f69a761 100644 --- a/src/node-process/NodeInterceptors/ConsoleInterceptor.mjs +++ b/src/node-process/NodeInterceptors/ConsoleInterceptor.mjs @@ -1,6 +1,6 @@ 'use strict'; -const StandardStreamsInterceptor = require('./StandardStreamsInterceptor'); +import StandardStreamsInterceptor from './StandardStreamsInterceptor.mjs'; const SUPPORTED_CONSOLE_METHODS = { 'debug': 'DEBUG', @@ -13,7 +13,7 @@ const SUPPORTED_CONSOLE_METHODS = { 'warn': 'WARNING', }; -class ConsoleInterceptor +export default class ConsoleInterceptor { /** * Log interceptor. @@ -97,5 +97,3 @@ class ConsoleInterceptor } ConsoleInterceptor.originalConsole = console; - -module.exports = ConsoleInterceptor; diff --git a/src/node-process/NodeInterceptors/StandardStreamsInterceptor.mjs b/src/node-process/NodeInterceptors/StandardStreamsInterceptor.mjs index 1be17db..d406db5 100644 --- a/src/node-process/NodeInterceptors/StandardStreamsInterceptor.mjs +++ b/src/node-process/NodeInterceptors/StandardStreamsInterceptor.mjs @@ -1,10 +1,10 @@ 'use strict'; -const _ = require('lodash'); +import _ from 'lodash'; const STANDARD_STREAMS = [process.stdout, process.stderr]; -class StandardStreamsInterceptor +export default class StandardStreamsInterceptor { /** * Standard stream interceptor. @@ -49,6 +49,4 @@ class StandardStreamsInterceptor } } -StandardStreamsInterceptor.standardStreamWriters = new Map; - -module.exports = StandardStreamsInterceptor; +StandardStreamsInterceptor.standardStreamWriters = new Map(); diff --git a/src/node-process/Server.mjs b/src/node-process/Server.mjs index 236e2a2..6379ff2 100644 --- a/src/node-process/Server.mjs +++ b/src/node-process/Server.mjs @@ -1,12 +1,12 @@ 'use strict'; -const net = require('net'), - Connection = require('./Connection'); +import net from 'net'; +import Connection from './Connection.mjs'; /** * Listen for new socket connections. */ -class Server +export default class Server { /** * Constructor. @@ -70,5 +70,3 @@ class Server } } } - -module.exports = Server; diff --git a/src/node-process/index.mjs b/src/node-process/index.mjs index 03ac65b..af47353 100644 --- a/src/node-process/index.mjs +++ b/src/node-process/index.mjs @@ -1,5 +1,5 @@ 'use strict'; -module.exports = { - ConnectionDelegate: require('./ConnectionDelegate'), -}; +import ConnectionDelegate from './ConnectionDelegate.mjs'; + +export default ConnectionDelegate; diff --git a/src/node-process/serve.mjs b/src/node-process/serve.mjs index 89aab4b..d4a99cb 100644 --- a/src/node-process/serve.mjs +++ b/src/node-process/serve.mjs @@ -1,9 +1,9 @@ 'use strict'; -const ConsoleInterceptor = require('./NodeInterceptors/ConsoleInterceptor'), - Logger = require('./Logger'), - Server = require('./Server'), - DataSerializer = require('./Data/Serializer'); +import ConsoleInterceptor from './NodeInterceptors/ConsoleInterceptor.mjs'; +import Logger from './Logger.mjs'; +import Server from './Server.mjs'; +import DataSerializer from './Data/Serializer.mjs'; // Throw unhandled rejections process.on('unhandledRejection', error => { @@ -31,7 +31,8 @@ if (options.log_node_console === true) { } // Instanciate the custom connection delegate -const connectionDelegate = new (require(process.argv.slice(2)[0]))(options); +const connectionDelegateClass = (await import(`file://${process.argv[2]}`)).default; +const connectionDelegate = new connectionDelegateClass(options); // Start the server with the custom connection delegate const server = new Server(connectionDelegate, options); From a4e01d344953c2ba11f451948873b5b373b2e565 Mon Sep 17 00:00:00 2001 From: Mark Reidenbach Date: Fri, 16 Aug 2024 15:36:55 -0500 Subject: [PATCH 3/8] Rename tests/Implementation/FsConnectionDelegate.js to .mjs --- .../{FsConnectionDelegate.js => FsConnectionDelegate.mjs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/Implementation/{FsConnectionDelegate.js => FsConnectionDelegate.mjs} (100%) diff --git a/tests/Implementation/FsConnectionDelegate.js b/tests/Implementation/FsConnectionDelegate.mjs similarity index 100% rename from tests/Implementation/FsConnectionDelegate.js rename to tests/Implementation/FsConnectionDelegate.mjs From 866c1c2f410004b7b7a0504ff9df5fc4dee32ccc Mon Sep 17 00:00:00 2001 From: Mark Reidenbach Date: Fri, 16 Aug 2024 15:40:07 -0500 Subject: [PATCH 4/8] Update .gitattributes/.gitignore and add .editorconfig and .prettierrc.json5 --- .editorconfig | 12 ++++++++++++ .gitattributes | 2 ++ .gitignore | 4 ++-- .prettierrc.json5 | 15 +++++++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .prettierrc.json5 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..dc55f79 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# root of project EditorConfig file +root = true + +# All Files +[*] +charset = utf-8 +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = tab +tab_width = 4 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..47c6a6a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Use LF line endings only for all text (non-binary) files +* text=auto eol=lf diff --git a/.gitignore b/.gitignore index 7dc1fb2..d30f8ec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ /node_modules/ /vendor/ -composer.lock -package-lock.json +/.phpunit.cache/ +/.phpunit.result.cache diff --git a/.prettierrc.json5 b/.prettierrc.json5 new file mode 100644 index 0000000..80a159c --- /dev/null +++ b/.prettierrc.json5 @@ -0,0 +1,15 @@ +{ + "printWidth": 120, + "trailingComma": "all", + "plugins": ["@prettier/plugin-php", "prettier-plugin-organize-imports"], + "organizeImportsSkipDestructiveCodeActions": false, + "overrides": [ + { + "files": "**/*.php", + "options": { + "phpVersion": "8.3", + "singleQuote": true, + }, + }, + ], +} From 6211bafbebee6fcb4c488123afdc2633d12f1d6e Mon Sep 17 00:00:00 2001 From: Mark Reidenbach Date: Fri, 16 Aug 2024 15:47:07 -0500 Subject: [PATCH 5/8] Update composer.json and package.json to supported versions and add composer.lock --- composer.json | 12 +- composer.lock | 1935 +++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 3 files changed, 1942 insertions(+), 7 deletions(-) create mode 100644 composer.lock diff --git a/composer.json b/composer.json index e26320b..5ea7d59 100644 --- a/composer.json +++ b/composer.json @@ -18,14 +18,14 @@ } ], "require": { - "php": "^7.2 || ^8.0", - "clue/socket-raw": "^1.2", - "psr/log": "^1.0 || ^2.0 || ^3.0", - "symfony/process": "^3.3 || ^4.0 || ^5.0 || ^6.0 || ^7.0" + "php": "^8.2", + "clue/socket-raw": "^1.6", + "psr/log": "^2.0 || ^3.0", + "symfony/process": "^5.4 || ^6.0 || ^7.0" }, "require-dev": { - "monolog/monolog": "^1.0 || ^2.0 || ^3.0", - "phpunit/phpunit": "^8.0 || ^9.0 || ^10" + "monolog/monolog": "^2.4 || ^3.0", + "phpunit/phpunit": "^10 || ^11" }, "suggest": { "ext-weakref": "Required to run all the tests" diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..d45d445 --- /dev/null +++ b/composer.lock @@ -0,0 +1,1935 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "e7427d7fd0f6551a8535593d56a98f63", + "packages": [ + { + "name": "clue/socket-raw", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/clue/socket-raw.git", + "reference": "91e9f619f6769f931454a9882c21ffd7623d06cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/socket-raw/zipball/91e9f619f6769f931454a9882c21ffd7623d06cb", + "reference": "91e9f619f6769f931454a9882c21ffd7623d06cb", + "shasum": "" + }, + "require": { + "ext-sockets": "*", + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "Socket\\Raw\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "Simple and lightweight OOP wrapper for PHP's low-level sockets extension (ext-sockets).", + "homepage": "https://github.com/clue/socket-raw", + "keywords": [ + "Socket", + "client", + "datagram", + "dgram", + "icmp", + "ipv6", + "server", + "stream", + "tcp", + "udg", + "udp", + "unix" + ], + "support": { + "issues": "https://github.com/clue/socket-raw/issues", + "source": "https://github.com/clue/socket-raw/tree/v1.6.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-04-14T14:58:06+00:00" + }, + { + "name": "psr/log", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "symfony/process", + "version": "v7.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "7f2f542c668ad6c313dc4a5e9c3321f733197eca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/7f2f542c668ad6c313dc4a5e9c3321f733197eca", + "reference": "7f2f542c668ad6c313dc4a5e9c3321f733197eca", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v7.1.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-07-26T12:44:47+00:00" + } + ], + "packages-dev": [ + { + "name": "monolog/monolog", + "version": "3.7.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "f4393b648b78a5408747de94fca38beb5f7e9ef8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f4393b648b78a5408747de94fca38beb5f7e9ef8", + "reference": "f4393b648b78a5408747de94fca38beb5f7e9ef8", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-strict-rules": "^1.4", + "phpunit/phpunit": "^10.5.17", + "predis/predis": "^1.1 || ^2", + "ruflin/elastica": "^7", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/3.7.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2024-06-28T09:40:51+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.12.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2024-06-12T14:39:25+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.1.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" + }, + "time": "2024-07-01T20:03:41+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "11.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "19b6365ab8b59a64438c0c3f4241feeb480c9861" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/19b6365ab8b59a64438c0c3f4241feeb480c9861", + "reference": "19b6365ab8b59a64438c0c3f4241feeb480c9861", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.0", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.0", + "phpunit/php-text-template": "^4.0", + "sebastian/code-unit-reverse-lookup": "^4.0", + "sebastian/complexity": "^4.0", + "sebastian/environment": "^7.0", + "sebastian/lines-of-code": "^3.0", + "sebastian/version": "^5.0", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:05:37+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "6ed896bf50bbbfe4d504a33ed5886278c78e4a26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6ed896bf50bbbfe4d504a33ed5886278c78e4a26", + "reference": "6ed896bf50bbbfe4d504a33ed5886278c78e4a26", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:06:37+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:07:44+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:08:43+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "7.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:09:35+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "11.3.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "fe179875ef0c14e90b75617002767eae0a742641" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fe179875ef0c14e90b75617002767eae0a742641", + "reference": "fe179875ef0c14e90b75617002767eae0a742641", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.5", + "phpunit/php-file-iterator": "^5.0.1", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.1", + "sebastian/comparator": "^6.0.2", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.0", + "sebastian/exporter": "^6.1.3", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.0.1", + "sebastian/version": "^5.0.1" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.3-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.3.1" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2024-08-13T06:14:23+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:41:36+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "6bb7d09d6623567178cf54126afa9c2310114268" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/6bb7d09d6623567178cf54126afa9c2310114268", + "reference": "6bb7d09d6623567178cf54126afa9c2310114268", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:44:28+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:45:54+00:00" + }, + { + "name": "sebastian/comparator", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "450d8f237bd611c45b5acf0733ce43e6bb280f81" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/450d8f237bd611c45b5acf0733ce43e6bb280f81", + "reference": "450d8f237bd611c45b5acf0733ce43e6bb280f81", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-08-12T06:07:25+00:00" + }, + { + "name": "sebastian/complexity", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:49:50+00:00" + }, + { + "name": "sebastian/diff", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:53:05+00:00" + }, + { + "name": "sebastian/environment", + "version": "7.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:54:44+00:00" + }, + { + "name": "sebastian/exporter", + "version": "6.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", + "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/6.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:56:19+00:00" + }, + { + "name": "sebastian/global-state", + "version": "7.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:57:36+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:58:38+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:00:13+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:01:32+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:10:34+00:00" + }, + { + "name": "sebastian/type", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "fb6a6566f9589e86661291d13eba708cce5eb4aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb6a6566f9589e86661291d13eba708cce5eb4aa", + "reference": "fb6a6566f9589e86661291d13eba708cce5eb4aa", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:11:49+00:00" + }, + { + "name": "sebastian/version", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "45c9debb7d039ce9b97de2f749c2cf5832a06ac4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/45c9debb7d039ce9b97de2f749c2cf5832a06ac4", + "reference": "45c9debb7d039ce9b97de2f749c2cf5832a06ac4", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:13:08+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^8.2" + }, + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/package.json b/package.json index 57c3131..8edcc03 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,6 @@ "node": ">=18.0.0" }, "dependencies": { - "lodash": "^4.17.10" + "lodash": "^4.17.21" } } From b588370c444d148486a540cbdf1fb8f842bfef36 Mon Sep 17 00:00:00 2001 From: Mark Reidenbach Date: Fri, 16 Aug 2024 15:47:47 -0500 Subject: [PATCH 6/8] Run prettier on src/ directory --- src/AbstractEntryPoint.php | 6 +- src/Data/BasicResource.php | 2 + src/Data/JsFunction.php | 28 ++++--- src/Data/ResourceIdentity.php | 2 + src/Data/UnserializesData.php | 11 ++- src/Exceptions/IdentifiesProcess.php | 2 + src/Exceptions/IdleTimeoutException.php | 14 +++- src/Exceptions/Node/Exception.php | 2 + src/Exceptions/Node/FatalException.php | 2 + src/Exceptions/Node/HandlesNodeErrors.php | 4 +- ...ProcessUnexpectedlyTerminatedException.php | 2 + src/Exceptions/ReadSocketTimeoutException.php | 14 +++- src/Instruction.php | 19 ++--- ...ShouldCommunicateWithProcessSupervisor.php | 2 + .../ShouldHandleProcessDelegation.php | 2 + src/Interfaces/ShouldIdentifyResource.php | 2 + src/Logger.php | 37 ++++++--- src/ProcessSupervisor.php | 48 +++++++----- .../CommunicatesWithProcessSupervisor.php | 6 +- src/Traits/IdentifiesResource.php | 2 + src/Traits/UsesBasicResourceAsDefault.php | 2 + src/node-process/Connection.mjs | 78 +++++++++---------- src/node-process/ConnectionDelegate.mjs | 11 +-- src/node-process/Data/ResourceIdentity.mjs | 22 ++---- src/node-process/Data/ResourceRepository.mjs | 31 +++----- src/node-process/Data/Serializer.mjs | 16 ++-- src/node-process/Data/Unserializer.mjs | 35 ++++----- src/node-process/Data/Value.mjs | 19 ++--- src/node-process/Instruction.mjs | 70 +++++++---------- src/node-process/Logger.mjs | 7 +- .../NodeInterceptors/ConsoleInterceptor.mjs | 31 ++++---- .../StandardStreamsInterceptor.mjs | 11 ++- src/node-process/Server.mjs | 31 ++++---- src/node-process/index.mjs | 4 +- src/node-process/serve.mjs | 16 ++-- 35 files changed, 299 insertions(+), 292 deletions(-) diff --git a/src/AbstractEntryPoint.php b/src/AbstractEntryPoint.php index d3d7352..175ad22 100644 --- a/src/AbstractEntryPoint.php +++ b/src/AbstractEntryPoint.php @@ -1,5 +1,7 @@ consolidateOptions($implementationOptions, $userOptions) + $this->consolidateOptions($implementationOptions, $userOptions), ); $this->setProcessSupervisor($process); diff --git a/src/Data/BasicResource.php b/src/Data/BasicResource.php index 1801567..b72219e 100644 --- a/src/Data/BasicResource.php +++ b/src/Data/BasicResource.php @@ -1,5 +1,7 @@ parameters = $parameters; return $clone; @@ -70,7 +73,8 @@ public function parameters(array $parameters): self { /** * Return a new instance with the specified body. */ - public function body(string $body): self { + public function body(string $body): self + { $clone = clone $this; $clone->body = $body; return $clone; @@ -79,7 +83,8 @@ public function body(string $body): self { /** * Return a new instance with the specified scope. */ - public function scope(array $scope): self { + public function scope(array $scope): self + { $clone = clone $this; $clone->scope = $scope; return $clone; @@ -88,7 +93,8 @@ public function scope(array $scope): self { /** * Return a new instance with the specified async state. */ - public function async(bool $isAsync = true): self { + public function async(bool $isAsync = true): self + { $clone = clone $this; $clone->async = $isAsync; return $clone; @@ -116,9 +122,9 @@ public static function __callStatic(string $name, array $arguments) $name = lcfirst(substr($name, strlen('createWith'))); if ($name === 'jsonSerialize') { - throw new \BadMethodCallException; + throw new \BadMethodCallException(); } - return call_user_func([new self, $name], ...$arguments); + return call_user_func([new self(), $name], ...$arguments); } } diff --git a/src/Data/ResourceIdentity.php b/src/Data/ResourceIdentity.php index 3f6aed9..27ff78c 100644 --- a/src/Data/ResourceIdentity.php +++ b/src/Data/ResourceIdentity.php @@ -1,5 +1,7 @@ options['debug']); - } else if (($value['__rialto_resource__'] ?? false) === true) { + } elseif (($value['__rialto_resource__'] ?? false) === true) { if ($this->delegate instanceof ShouldHandleProcessDelegation) { - $classPath = $this->delegate->resourceFromOriginalClassName($value['class_name']) - ?: $this->delegate->defaultResource(); + $classPath = + $this->delegate->resourceFromOriginalClassName($value['class_name']) ?: + $this->delegate->defaultResource(); } else { $classPath = $this->defaultResource(); } - $resource = new $classPath; + $resource = new $classPath(); if ($resource instanceof ShouldIdentifyResource) { $resource->setResourceIdentity(new ResourceIdentity($value['class_name'], $value['id'])); diff --git a/src/Exceptions/IdentifiesProcess.php b/src/Exceptions/IdentifiesProcess.php index 8357eac..1f6665c 100644 --- a/src/Exceptions/IdentifiesProcess.php +++ b/src/Exceptions/IdentifiesProcess.php @@ -1,5 +1,7 @@ value = $type !== self::TYPE_CALL - ? $this->validateValue($value) - : array_map(function ($value) { - return $this->validateValue($value); - }, $value); + $this->value = + $type !== self::TYPE_CALL + ? $this->validateValue($value) + : array_map(fn($value) => $this->validateValue($value), $value); } /** @@ -132,7 +133,7 @@ protected function setValue($value, string $type) */ protected function validateValue($value) { - if (is_object($value) && ($value instanceof \Closure)) { + if (is_object($value) && $value instanceof \Closure) { throw new InvalidArgumentException('You must use JS function wrappers instead of PHP closures.'); } @@ -172,9 +173,9 @@ public static function __callStatic(string $name, array $arguments) $name = lcfirst(substr($name, strlen('with'))); if ($name === 'jsonSerialize') { - throw new BadMethodCallException; + throw new BadMethodCallException(); } - return call_user_func([new self, $name], ...$arguments); + return call_user_func([new self(), $name], ...$arguments); } } diff --git a/src/Interfaces/ShouldCommunicateWithProcessSupervisor.php b/src/Interfaces/ShouldCommunicateWithProcessSupervisor.php index 84f4774..922d8c5 100644 --- a/src/Interfaces/ShouldCommunicateWithProcessSupervisor.php +++ b/src/Interfaces/ShouldCommunicateWithProcessSupervisor.php @@ -1,5 +1,7 @@ logger = $logger; } @@ -26,7 +29,8 @@ public function __construct(?LoggerInterface $logger) { * * @param string $message */ - public function emergency($message, array $context = []): void { + public function emergency($message, array $context = []): void + { $this->log(LogLevel::EMERGENCY, $message, $context); } @@ -35,7 +39,8 @@ public function emergency($message, array $context = []): void { * * @param string $message */ - public function alert($message, array $context = []): void { + public function alert($message, array $context = []): void + { $this->log(LogLevel::ALERT, $message, $context); } @@ -44,7 +49,8 @@ public function alert($message, array $context = []): void { * * @param string $message */ - public function critical($message, array $context = []): void { + public function critical($message, array $context = []): void + { $this->log(LogLevel::CRITICAL, $message, $context); } @@ -53,7 +59,8 @@ public function critical($message, array $context = []): void { * * @param string $message */ - public function error($message, array $context = []): void { + public function error($message, array $context = []): void + { $this->log(LogLevel::ERROR, $message, $context); } @@ -62,7 +69,8 @@ public function error($message, array $context = []): void { * * @param string $message */ - public function warning($message, array $context = []): void { + public function warning($message, array $context = []): void + { $this->log(LogLevel::WARNING, $message, $context); } @@ -71,7 +79,8 @@ public function warning($message, array $context = []): void { * * @param string $message */ - public function notice($message, array $context = []): void { + public function notice($message, array $context = []): void + { $this->log(LogLevel::NOTICE, $message, $context); } @@ -80,7 +89,8 @@ public function notice($message, array $context = []): void { * * @param string $message */ - public function info($message, array $context = []): void { + public function info($message, array $context = []): void + { $this->log(LogLevel::INFO, $message, $context); } @@ -89,7 +99,8 @@ public function info($message, array $context = []): void { * * @param string $message */ - public function debug($message, array $context = []): void { + public function debug($message, array $context = []): void + { $this->log(LogLevel::DEBUG, $message, $context); } @@ -99,7 +110,8 @@ public function debug($message, array $context = []): void { * @param mixed $level * @param string $message */ - public function log($level, $message, array $context = []): void { + public function log($level, $message, array $context = []): void + { if ($this->logger instanceof LoggerInterface) { $message = $this->interpolate($message, $context); $this->logger->log($level, $message, $context); @@ -111,8 +123,9 @@ public function log($level, $message, array $context = []): void { * * @see https://www.php-fig.org/psr/psr-3/#12-message */ - protected function interpolate(string $message, array $context = []): string { - $replace = array(); + protected function interpolate(string $message, array $context = []): string + { + $replace = []; foreach ($context as $key => $val) { if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) { diff --git a/src/ProcessSupervisor.php b/src/ProcessSupervisor.php index 25ce604..da6ab99 100644 --- a/src/ProcessSupervisor.php +++ b/src/ProcessSupervisor.php @@ -1,5 +1,7 @@ logger = new Logger($options['logger'] ?? null); @@ -179,7 +185,7 @@ public function __destruct() */ protected function logProcessStandardStreams(): void { - if (!empty($output = $this->process->getIncrementalOutput())) { + if (!empty(($output = $this->process->getIncrementalOutput()))) { $this->logger->notice('Received data on stdout: {output}', [ 'pid' => $this->processPid, 'stream' => 'stdout', @@ -187,7 +193,7 @@ protected function logProcessStandardStreams(): void ]); } - if (!empty($errorOutput = $this->process->getIncrementalErrorOutput())) { + if (!empty(($errorOutput = $this->process->getIncrementalErrorOutput()))) { $this->logger->error('Received data on stderr: {output}', [ 'pid' => $this->processPid, 'stream' => 'stderr', @@ -217,7 +223,8 @@ protected function applyOptions(array $options): void * This avoids double declarations of some JS classes in production, due to a require with two different paths (one * with the NPM path, the other one with the Composer path). */ - protected function getProcessScriptPath(): string { + protected function getProcessScriptPath(): string + { static $scriptPath = null; if ($scriptPath !== null) { @@ -225,7 +232,7 @@ protected function getProcessScriptPath(): string { } // The script path in local development - $scriptPath = __DIR__.'/node-process/serve.mjs'; + $scriptPath = __DIR__ . '/node-process/serve.mjs'; $process = new SymfonyProcess([ $this->options['executable_path'], @@ -260,13 +267,15 @@ protected function createNewProcess(string $connectionDelegatePath): SymfonyProc // Remove useless options for the process $processOptions = array_diff_key($this->options, array_flip(self::USELESS_OPTIONS_FOR_PROCESS)); - return new SymfonyProcess(array_merge( - [$this->options['executable_path']], - $this->options['debug'] ? ['--inspect'] : [], - [$this->getProcessScriptPath()], - [$realConnectionDelegatePath], - [json_encode((object) $processOptions)] - )); + return new SymfonyProcess( + array_merge( + [$this->options['executable_path']], + $this->options['debug'] ? ['--inspect'] : [], + [$this->getProcessScriptPath()], + [$realConnectionDelegatePath], + [json_encode((object) $processOptions)], + ), + ); } /** @@ -302,9 +311,9 @@ protected function checkProcessStatus(): void if (IdleTimeoutException::exceptionApplies($process)) { throw new IdleTimeoutException( $this->options['idle_timeout'], - new NodeFatalException($process, $this->options['debug']) + new NodeFatalException($process, $this->options['debug']), ); - } else if (NodeFatalException::exceptionApplies($process)) { + } elseif (NodeFatalException::exceptionApplies($process)) { throw new NodeFatalException($process, $this->options['debug']); } elseif ($process->isTerminated() && !$process->isSuccessful()) { throw new ProcessFailedException($process); @@ -322,7 +331,8 @@ protected function checkProcessStatus(): void * The process might take a while to stop itself. So, before trying to check its status or reading its standard * streams, this method should be executed. */ - protected function waitForProcessTermination(): void { + protected function waitForProcessTermination(): void + { usleep(self::PROCESS_TERMINATION_DELAY * 1000); } @@ -351,9 +361,7 @@ protected function serverPort(): int protected function createNewClient(int $port): Socket { // Set the client as non-blocking to handle the exceptions thrown by the process - return (new SocketFactory) - ->createClient("tcp://127.0.0.1:$port") - ->setBlocking(false); + return (new SocketFactory())->createClient("tcp://127.0.0.1:$port")->setBlocking(false); } /** @@ -378,7 +386,7 @@ public function executeInstruction(Instruction $instruction, bool $instructionSh } $this->client->selectWrite(1); - + $packet = $serializedInstruction . chr(0); $packetSentByteCount = 0; while ($packetSentByteCount < strlen($packet)) { diff --git a/src/Traits/CommunicatesWithProcessSupervisor.php b/src/Traits/CommunicatesWithProcessSupervisor.php index ca2abc1..1cfa7d3 100644 --- a/src/Traits/CommunicatesWithProcessSupervisor.php +++ b/src/Traits/CommunicatesWithProcessSupervisor.php @@ -1,5 +1,7 @@ processSupervisor; diff --git a/src/Traits/IdentifiesResource.php b/src/Traits/IdentifiesResource.php index 95de901..22f04d1 100644 --- a/src/Traits/IdentifiesResource.php +++ b/src/Traits/IdentifiesResource.php @@ -1,5 +1,7 @@ { - this.emit('activity'); + let buffer = ""; + socket.on("data", (data) => { + this.emit("activity"); buffer += data; if (buffer.endsWith("\0")) { buffer = buffer.slice(0, -1); this.handleSocketData(buffer); - buffer = ''; + buffer = ""; } }); @@ -63,10 +60,9 @@ export default class Connection extends EventEmitter * * @param {string} data */ - handleSocketData(data) - { + handleSocketData(data) { const instruction = new Instruction(JSON.parse(data), this.resources, this.dataUnserializer), - {responseHandler, errorHandler} = this.createInstructionHandlers(); + { responseHandler, errorHandler } = this.createInstructionHandlers(); this.delegate.handleInstruction(instruction, responseHandler, errorHandler); } @@ -76,26 +72,27 @@ export default class Connection extends EventEmitter * * @return {Object} */ - createInstructionHandlers() - { + createInstructionHandlers() { let handlerHasBeenCalled = false; const handler = (serializingMethod, value) => { if (handlerHasBeenCalled) { - throw new Error('You can call only once the response/error handler.'); + throw new Error("You can call only once the response/error handler."); } handlerHasBeenCalled = true; - this.writeToSocket(JSON.stringify({ - logs: Logger.logs(), - value: this[serializingMethod](value), - })); + this.writeToSocket( + JSON.stringify({ + logs: Logger.logs(), + value: this[serializingMethod](value), + }), + ); }; return { - responseHandler: handler.bind(this, 'serializeValue'), - errorHandler: handler.bind(this, 'serializeError'), + responseHandler: handler.bind(this, "serializeValue"), + errorHandler: handler.bind(this, "serializeError"), }; } @@ -104,18 +101,17 @@ export default class Connection extends EventEmitter * * @param {string} str */ - writeToSocket(str) - { - const payload = Buffer.from(str).toString('base64'); + writeToSocket(str) { + const payload = Buffer.from(str).toString("base64"); const bodySize = Connection.SOCKET_PACKET_SIZE - Connection.SOCKET_HEADER_SIZE, chunkCount = Math.ceil(payload.length / bodySize); - for (let i = 0 ; i < chunkCount ; i++) { + for (let i = 0; i < chunkCount; i++) { const chunk = payload.substr(i * bodySize, bodySize); let chunksLeft = String(chunkCount - 1 - i); - chunksLeft = chunksLeft.padStart(Connection.SOCKET_HEADER_SIZE, '0'); + chunksLeft = chunksLeft.padStart(Connection.SOCKET_HEADER_SIZE, "0"); this.socket.write(`${chunksLeft}${chunk}`); } @@ -127,8 +123,7 @@ export default class Connection extends EventEmitter * @param {*} value * @return {Object} */ - serializeValue(value) - { + serializeValue(value) { return this.dataSerializer.serialize(value); } @@ -138,8 +133,7 @@ export default class Connection extends EventEmitter * @param {Error} error * @return {Object} */ - serializeError(error) - { + serializeError(error) { return DataSerializer.serializeError(error); } } @@ -149,7 +143,7 @@ export default class Connection extends EventEmitter * * @constant * @type {number} -*/ + */ Connection.SOCKET_PACKET_SIZE = 1024; /** diff --git a/src/node-process/ConnectionDelegate.mjs b/src/node-process/ConnectionDelegate.mjs index 5c15844..9869427 100644 --- a/src/node-process/ConnectionDelegate.mjs +++ b/src/node-process/ConnectionDelegate.mjs @@ -1,4 +1,4 @@ -'use strict'; +"use strict"; /** * @callback responseHandler @@ -13,15 +13,13 @@ /** * Handle the requests of a connection. */ -export default class ConnectionDelegate -{ +export default class ConnectionDelegate { /** * Constructor. * * @param {Object} options */ - constructor(options) - { + constructor(options) { this.options = options; } @@ -32,8 +30,7 @@ export default class ConnectionDelegate * @param {responseHandler} responseHandler * @param {errorHandler} errorHandler */ - handleInstruction(instruction, responseHandler, errorHandler) - { + handleInstruction(instruction, responseHandler, errorHandler) { responseHandler(null); } } diff --git a/src/node-process/Data/ResourceIdentity.mjs b/src/node-process/Data/ResourceIdentity.mjs index 6c67f46..623f2f2 100644 --- a/src/node-process/Data/ResourceIdentity.mjs +++ b/src/node-process/Data/ResourceIdentity.mjs @@ -1,16 +1,14 @@ -'use strict'; +"use strict"; -export default class ResourceIdentity -{ +export default class ResourceIdentity { /** * Constructor. * * @param {string} uniqueIdentifier * @param {string|null} className */ - constructor(uniqueIdentifier, className = null) - { - this.resource = {uniqueIdentifier, className}; + constructor(uniqueIdentifier, className = null) { + this.resource = { uniqueIdentifier, className }; } /** @@ -18,8 +16,7 @@ export default class ResourceIdentity * * @return {string} */ - uniqueIdentifier() - { + uniqueIdentifier() { return this.resource.uniqueIdentifier; } @@ -28,8 +25,7 @@ export default class ResourceIdentity * * @return {string|null} */ - className() - { + className() { return this.resource.className; } @@ -39,8 +35,7 @@ export default class ResourceIdentity * @param {Object} identity * @return {ResourceIdentity} */ - static unserialize(identity) - { + static unserialize(identity) { return new ResourceIdentity(identity.id, identity.class_name); } @@ -49,8 +44,7 @@ export default class ResourceIdentity * * @return {Object} */ - serialize() - { + serialize() { return { __rialto_resource__: true, id: this.uniqueIdentifier(), diff --git a/src/node-process/Data/ResourceRepository.mjs b/src/node-process/Data/ResourceRepository.mjs index f88745f..03990e8 100644 --- a/src/node-process/Data/ResourceRepository.mjs +++ b/src/node-process/Data/ResourceRepository.mjs @@ -1,14 +1,12 @@ -'use strict'; +"use strict"; -import ResourceIdentity from './ResourceIdentity.mjs'; +import ResourceIdentity from "./ResourceIdentity.mjs"; -export default class ResourceRepository -{ +export default class ResourceRepository { /** * Constructor. */ - constructor() - { + constructor() { this.resources = new Map(); } @@ -19,8 +17,7 @@ export default class ResourceRepository * @param {ResourceIdentity} identity * @return {*} */ - static retrieveFrom(storage, identity) - { + static retrieveFrom(storage, identity) { for (let [resource, id] of storage) { if (identity.uniqueIdentifier() === id) { return resource; @@ -36,8 +33,7 @@ export default class ResourceRepository * @param {ResourceIdentity} identity * @return {*} */ - retrieve(identity) - { + retrieve(identity) { return ResourceRepository.retrieveFrom(this.resources, identity); } @@ -47,8 +43,7 @@ export default class ResourceRepository * @param {string} uniqueIdentifier * @return {*} */ - static retrieveGlobal(uniqueIdentifier) - { + static retrieveGlobal(uniqueIdentifier) { const identity = new ResourceIdentity(uniqueIdentifier); return ResourceRepository.retrieveFrom(ResourceRepository.globalResources, identity); } @@ -60,8 +55,7 @@ export default class ResourceRepository * @param {*} resource * @return {ResourceIdentity} */ - static storeIn(storage, resource) - { + static storeIn(storage, resource) { if (storage.has(resource)) { return ResourceRepository.generateResourceIdentity(resource, storage.get(resource)); } @@ -79,8 +73,7 @@ export default class ResourceRepository * @param {*} resource * @return {ResourceIdentity} */ - store(resource) - { + store(resource) { return ResourceRepository.storeIn(this.resources, resource); } @@ -90,8 +83,7 @@ export default class ResourceRepository * @param {*} resource * @return {string} */ - static storeGlobal(resource) - { + static storeGlobal(resource) { return ResourceRepository.storeIn(ResourceRepository.globalResources, resource).uniqueIdentifier(); } @@ -102,8 +94,7 @@ export default class ResourceRepository * @param {string} uniqueIdentifier * @return {ResourceIdentity} */ - static generateResourceIdentity(resource, uniqueIdentifier) - { + static generateResourceIdentity(resource, uniqueIdentifier) { return new ResourceIdentity(uniqueIdentifier, resource.constructor.name); } } diff --git a/src/node-process/Data/Serializer.mjs b/src/node-process/Data/Serializer.mjs index c5c9c78..3a2c14d 100644 --- a/src/node-process/Data/Serializer.mjs +++ b/src/node-process/Data/Serializer.mjs @@ -1,17 +1,15 @@ -'use strict'; +"use strict"; -import Value from './Value.mjs'; +import Value from "./Value.mjs"; -export default class Serializer -{ +export default class Serializer { /** * Serialize an error to JSON. * * @param {Error} error * @return {Object} */ - static serializeError(error) - { + static serializeError(error) { return { __rialto_error__: true, message: error.message, @@ -24,8 +22,7 @@ export default class Serializer * * @param {ResourceRepository} resources */ - constructor(resources) - { + constructor(resources) { this.resources = resources; } @@ -35,8 +32,7 @@ export default class Serializer * @param {*} value * @return {*} */ - serialize(value) - { + serialize(value) { value = value === undefined ? null : value; if (Value.isContainer(value)) { diff --git a/src/node-process/Data/Unserializer.mjs b/src/node-process/Data/Unserializer.mjs index b183f20..bdd304c 100644 --- a/src/node-process/Data/Unserializer.mjs +++ b/src/node-process/Data/Unserializer.mjs @@ -1,22 +1,20 @@ -'use strict'; +"use strict"; -import _ from 'lodash'; -import Value from './Value.mjs'; -import ResourceIdentity from './ResourceIdentity.mjs'; -import ResourceRepository from './ResourceRepository.mjs'; +import _ from "lodash"; +import ResourceIdentity from "./ResourceIdentity.mjs"; +import ResourceRepository from "./ResourceRepository.mjs"; +import Value from "./Value.mjs"; // Some unserialized functions require an access to the ResourceRepository class, so we must put it in the global scope. global.__rialto_ResourceRepository__ = ResourceRepository; -export default class Unserializer -{ +export default class Unserializer { /** * Constructor. * * @param {ResourceRepository} resources */ - constructor(resources) - { + constructor(resources) { this.resources = resources; } @@ -26,11 +24,10 @@ export default class Unserializer * @param {*} value * @return {*} */ - unserialize(value) - { - if (_.get(value, '__rialto_resource__') === true) { + unserialize(value) { + if (_.get(value, "__rialto_resource__") === true) { return this.resources.retrieve(ResourceIdentity.unserialize(value)); - } else if (_.get(value, '__rialto_function__') === true) { + } else if (_.get(value, "__rialto_function__") === true) { return this.unserializeFunction(value); } else if (Value.isContainer(value)) { return Value.mapContainer(value, this.unserialize.bind(this)); @@ -45,8 +42,7 @@ export default class Unserializer * @param {*} value * @return {string} */ - embedFunctionValue(value) - { + embedFunctionValue(value) { value = this.unserialize(value); const valueUniqueIdentifier = ResourceRepository.storeGlobal(value); @@ -66,8 +62,7 @@ export default class Unserializer * @param {Object} value * @return {Function} */ - unserializeFunction(value) - { + unserializeFunction(value) { const scopedVariables = []; for (let [varName, varValue] of Object.entries(value.scope)) { @@ -84,11 +79,11 @@ export default class Unserializer } } - const asyncFlag = value.async ? 'async' : ''; + const asyncFlag = value.async ? "async" : ""; return new Function(` - return ${asyncFlag} function (${parameters.join(', ')}) { - ${scopedVariables.join('\n')} + return ${asyncFlag} function (${parameters.join(", ")}) { + ${scopedVariables.join("\n")} ${value.body} }; `)(); diff --git a/src/node-process/Data/Value.mjs b/src/node-process/Data/Value.mjs index 2ece356..3781d30 100644 --- a/src/node-process/Data/Value.mjs +++ b/src/node-process/Data/Value.mjs @@ -1,17 +1,15 @@ -'use strict'; +"use strict"; -import _ from 'lodash'; +import _ from "lodash"; -export default class Value -{ +export default class Value { /** * Determine if the value is a string, a number, a boolean, or null. * * @param {*} value * @return {boolean} */ - static isScalar(value) - { + static isScalar(value) { return _.isString(value) || _.isNumber(value) || _.isBoolean(value) || _.isNull(value); } @@ -21,8 +19,7 @@ export default class Value * @param {*} value * @return {boolean} */ - static isContainer(value) - { + static isContainer(value) { return _.isArray(value) || _.isPlainObject(value); } @@ -33,8 +30,7 @@ export default class Value * @param {callback} mapper * @return {array} */ - static mapContainer(container, mapper) - { + static mapContainer(container, mapper) { if (_.isArray(container)) { return container.map(mapper); } else if (_.isPlainObject(container)) { @@ -54,8 +50,7 @@ export default class Value * @param {*} value * @return {boolean} */ - static isResource(value) - { + static isResource(value) { return !Value.isContainer(value) && !Value.isScalar(value); } } diff --git a/src/node-process/Instruction.mjs b/src/node-process/Instruction.mjs index 75ee1ac..fc1e1fa 100644 --- a/src/node-process/Instruction.mjs +++ b/src/node-process/Instruction.mjs @@ -1,9 +1,8 @@ -'use strict'; +"use strict"; -import ResourceIdentity from './Data/ResourceIdentity.mjs'; +import ResourceIdentity from "./Data/ResourceIdentity.mjs"; -export default class Instruction -{ +export default class Instruction { /** * Constructor. * @@ -11,8 +10,7 @@ export default class Instruction * @param {ResourceRepository} resources * @param {DataUnserializer} dataUnserializer */ - constructor(serializedInstruction, resources, dataUnserializer) - { + constructor(serializedInstruction, resources, dataUnserializer) { this.instruction = serializedInstruction; this.resources = resources; this.dataUnserializer = dataUnserializer; @@ -24,8 +22,7 @@ export default class Instruction * * @return {instructionTypeEnum} */ - type() - { + type() { return this.instruction.type; } @@ -35,8 +32,7 @@ export default class Instruction * @param {instructionTypeEnum} type * @return {this} */ - overrideType(type) - { + overrideType(type) { this.instruction.type = type; return this; @@ -47,8 +43,7 @@ export default class Instruction * * @return {string} */ - name() - { + name() { return this.instruction.name; } @@ -58,8 +53,7 @@ export default class Instruction * @param {string} name * @return {this} */ - overrideName(name) - { + overrideName(name) { this.instruction.name = name; return this; @@ -70,9 +64,8 @@ export default class Instruction * * @return {*} */ - value() - { - const {value} = this.instruction; + value() { + const { value } = this.instruction; return value !== undefined ? value : null; } @@ -83,8 +76,7 @@ export default class Instruction * @param {*} value * @return {this} */ - overrideValue(value) - { + overrideValue(value) { this.instruction.value = value; return this; @@ -95,13 +87,10 @@ export default class Instruction * * @return {Object|null} */ - resource() - { - const {resource} = this.instruction; + resource() { + const { resource } = this.instruction; - return resource - ? this.resources.retrieve(ResourceIdentity.unserialize(resource)) - : null; + return resource ? this.resources.retrieve(ResourceIdentity.unserialize(resource)) : null; } /** @@ -110,8 +99,7 @@ export default class Instruction * @param {Object|null} resource * @return {this} */ - overrideResource(resource) - { + overrideResource(resource) { if (resource !== null) { this.instruction.resource = this.resources.store(resource); } @@ -125,8 +113,7 @@ export default class Instruction * @param {Object} resource * @return {this} */ - setDefaultResource(resource) - { + setDefaultResource(resource) { this.defaultResource = resource; return this; @@ -137,8 +124,7 @@ export default class Instruction * * @return {boolean} */ - shouldCatchErrors() - { + shouldCatchErrors() { return this.instruction.catched; } @@ -147,8 +133,7 @@ export default class Instruction * * @return {*} */ - execute() - { + execute() { const type = this.type(), name = this.name(), value = this.value(), @@ -180,15 +165,13 @@ export default class Instruction * @param {array} args * @return {*} */ - callResourceMethod(resource, methodName, args) - { + callResourceMethod(resource, methodName, args) { try { return resource[methodName](...args.map(this.unserializeValue.bind(this))); } catch (error) { - if (error.message === 'resource[methodName] is not a function') { - const resourceName = resource.constructor.name === 'Function' - ? resource.name - : resource.constructor.name; + if (error.message === "resource[methodName] is not a function") { + const resourceName = + resource.constructor.name === "Function" ? resource.name : resource.constructor.name; throw new Error(`"${resourceName}.${methodName} is not a function"`); } @@ -204,8 +187,7 @@ export default class Instruction * @param {Object} value * @return {*} */ - unserializeValue(value) - { + unserializeValue(value) { return this.dataUnserializer.unserialize(value); } } @@ -217,7 +199,7 @@ export default class Instruction * @readonly */ Object.assign(Instruction, { - TYPE_CALL: 'call', - TYPE_GET: 'get', - TYPE_SET: 'set', + TYPE_CALL: "call", + TYPE_GET: "get", + TYPE_SET: "set", }); diff --git a/src/node-process/Logger.mjs b/src/node-process/Logger.mjs index 44d6660..1f235f1 100644 --- a/src/node-process/Logger.mjs +++ b/src/node-process/Logger.mjs @@ -1,7 +1,6 @@ -'use strict'; +"use strict"; -export default class Logger -{ +export default class Logger { /** * Add a new log to the queue. * @@ -10,7 +9,7 @@ export default class Logger * @param {string} message */ static log(origin, level, message) { - this.logsQueue.push({origin, level, message}); + this.logsQueue.push({ origin, level, message }); } /** diff --git a/src/node-process/NodeInterceptors/ConsoleInterceptor.mjs b/src/node-process/NodeInterceptors/ConsoleInterceptor.mjs index f69a761..746ce9b 100644 --- a/src/node-process/NodeInterceptors/ConsoleInterceptor.mjs +++ b/src/node-process/NodeInterceptors/ConsoleInterceptor.mjs @@ -1,20 +1,19 @@ -'use strict'; +"use strict"; -import StandardStreamsInterceptor from './StandardStreamsInterceptor.mjs'; +import StandardStreamsInterceptor from "./StandardStreamsInterceptor.mjs"; const SUPPORTED_CONSOLE_METHODS = { - 'debug': 'DEBUG', - 'dir': 'DEBUG', - 'dirxml': 'INFO', - 'error': 'ERROR', - 'info': 'INFO', - 'log': 'INFO', - 'table': 'DEBUG', - 'warn': 'WARNING', + debug: "DEBUG", + dir: "DEBUG", + dirxml: "INFO", + error: "ERROR", + info: "INFO", + log: "INFO", + table: "DEBUG", + warn: "WARNING", }; -export default class ConsoleInterceptor -{ +export default class ConsoleInterceptor { /** * Log interceptor. * @@ -34,7 +33,7 @@ export default class ConsoleInterceptor }); // Define the property instead of directly setting the property, the latter is forbidden in some environments. - Object.defineProperty(global, 'console', {value: consoleProxy}); + Object.defineProperty(global, "console", { value: consoleProxy }); } /** @@ -52,7 +51,7 @@ export default class ConsoleInterceptor } return (...args) => { - StandardStreamsInterceptor.startInterceptingStrings(message => interceptor(type, message)); + StandardStreamsInterceptor.startInterceptingStrings((message) => interceptor(type, message)); originalMethod(...args); StandardStreamsInterceptor.stopInterceptingStrings(); }; @@ -87,10 +86,10 @@ export default class ConsoleInterceptor static formatMessage(message) { // Remove terminal colors written as escape sequences // See: https://stackoverflow.com/a/41407246/1513045 - message = message.replace(/\x1b\[\d+m/g, ''); + message = message.replace(/\x1b\[\d+m/g, ""); // Remove the final new line - message = message.endsWith('\n') ? message.slice(0, -1) : message; + message = message.endsWith("\n") ? message.slice(0, -1) : message; return message; } diff --git a/src/node-process/NodeInterceptors/StandardStreamsInterceptor.mjs b/src/node-process/NodeInterceptors/StandardStreamsInterceptor.mjs index d406db5..cf399c3 100644 --- a/src/node-process/NodeInterceptors/StandardStreamsInterceptor.mjs +++ b/src/node-process/NodeInterceptors/StandardStreamsInterceptor.mjs @@ -1,11 +1,10 @@ -'use strict'; +"use strict"; -import _ from 'lodash'; +import _ from "lodash"; const STANDARD_STREAMS = [process.stdout, process.stderr]; -export default class StandardStreamsInterceptor -{ +export default class StandardStreamsInterceptor { /** * Standard stream interceptor. * @@ -19,7 +18,7 @@ export default class StandardStreamsInterceptor * @param {standardStreamInterceptor} interceptor */ static startInterceptingStrings(interceptor) { - STANDARD_STREAMS.forEach(stream => { + STANDARD_STREAMS.forEach((stream) => { this.standardStreamWriters.set(stream, stream.write); stream.write = (chunk, encoding, callback) => { @@ -42,7 +41,7 @@ export default class StandardStreamsInterceptor * Stop intercepting data written on the standard streams. */ static stopInterceptingStrings() { - STANDARD_STREAMS.forEach(stream => { + STANDARD_STREAMS.forEach((stream) => { stream.write = this.standardStreamWriters.get(stream); this.standardStreamWriters.delete(stream); }); diff --git a/src/node-process/Server.mjs b/src/node-process/Server.mjs index 6379ff2..b968297 100644 --- a/src/node-process/Server.mjs +++ b/src/node-process/Server.mjs @@ -1,21 +1,19 @@ -'use strict'; +"use strict"; -import net from 'net'; -import Connection from './Connection.mjs'; +import net from "net"; +import Connection from "./Connection.mjs"; /** * Listen for new socket connections. */ -export default class Server -{ +export default class Server { /** * Constructor. * * @param {ConnectionDelegate} connectionDelegate * @param {Object} options */ - constructor(connectionDelegate, options = {}) - { + constructor(connectionDelegate, options = {}) { this.options = options; this.started = this.start(connectionDelegate); @@ -29,17 +27,16 @@ export default class Server * @param {ConnectionDelegate} connectionDelegate * @return {Promise} */ - start(connectionDelegate) - { - this.server = net.createServer(socket => { + start(connectionDelegate) { + this.server = net.createServer((socket) => { const connection = new Connection(socket, connectionDelegate); - connection.on('activity', () => this.resetIdleTimeout()); + connection.on("activity", () => this.resetIdleTimeout()); this.resetIdleTimeout(); }); - return new Promise(resolve => { + return new Promise((resolve) => { this.server.listen(() => resolve()); }); } @@ -47,8 +44,7 @@ export default class Server /** * Write the listening port on the process output. */ - writePortToOutput() - { + writePortToOutput() { process.stdout.write(`${this.server.address().port}\n`); } @@ -57,15 +53,14 @@ export default class Server * * @protected */ - resetIdleTimeout() - { + resetIdleTimeout() { clearTimeout(this.idleTimer); - const {idle_timeout: idleTimeout} = this.options; + const { idle_timeout: idleTimeout } = this.options; if (idleTimeout !== null) { this.idleTimer = setTimeout(() => { - throw new Error('The idle timeout has been reached.'); + throw new Error("The idle timeout has been reached."); }, idleTimeout * 1000); } } diff --git a/src/node-process/index.mjs b/src/node-process/index.mjs index af47353..54bdcf6 100644 --- a/src/node-process/index.mjs +++ b/src/node-process/index.mjs @@ -1,5 +1,5 @@ -'use strict'; +"use strict"; -import ConnectionDelegate from './ConnectionDelegate.mjs'; +import ConnectionDelegate from "./ConnectionDelegate.mjs"; export default ConnectionDelegate; diff --git a/src/node-process/serve.mjs b/src/node-process/serve.mjs index d4a99cb..49b35ff 100644 --- a/src/node-process/serve.mjs +++ b/src/node-process/serve.mjs @@ -1,17 +1,17 @@ -'use strict'; +"use strict"; -import ConsoleInterceptor from './NodeInterceptors/ConsoleInterceptor.mjs'; -import Logger from './Logger.mjs'; -import Server from './Server.mjs'; -import DataSerializer from './Data/Serializer.mjs'; +import DataSerializer from "./Data/Serializer.mjs"; +import Logger from "./Logger.mjs"; +import ConsoleInterceptor from "./NodeInterceptors/ConsoleInterceptor.mjs"; +import Server from "./Server.mjs"; // Throw unhandled rejections -process.on('unhandledRejection', error => { +process.on("unhandledRejection", (error) => { throw error; }); // Output the exceptions in JSON format -process.on('uncaughtException', error => { +process.on("uncaughtException", (error) => { process.stderr.write(JSON.stringify(DataSerializer.serializeError(error))); process.exit(1); }); @@ -26,7 +26,7 @@ if (options.log_node_console === true) { const level = ConsoleInterceptor.getLevelFromType(type); const message = ConsoleInterceptor.formatMessage(originalMessage); - Logger.log('Node', level, message); + Logger.log("Node", level, message); }); } From 6512a56573f8b4ba852b8dc1549d2dbe5f2b0f71 Mon Sep 17 00:00:00 2001 From: Mark Reidenbach Date: Fri, 16 Aug 2024 15:48:55 -0500 Subject: [PATCH 7/8] Update tests to run on phpunit 11.3 --- phpunit.xml | 29 +- tests/Implementation/FsConnectionDelegate.mjs | 31 +- tests/Implementation/FsProcessDelegate.php | 10 +- .../FsWithProcessDelegation.php | 7 +- .../FsWithoutProcessDelegation.php | 4 +- tests/Implementation/Resources/Stats.php | 2 + tests/ImplementationTest.php | 273 +++++++++--------- tests/TestCase.php | 64 ++-- 8 files changed, 219 insertions(+), 201 deletions(-) diff --git a/phpunit.xml b/phpunit.xml index 045036e..13db4c6 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,20 +1,23 @@ + failOnRisky="true" + failOnWarning="true" + colors="true"> + - tests + tests - - - - src - - + + + + src + + diff --git a/tests/Implementation/FsConnectionDelegate.mjs b/tests/Implementation/FsConnectionDelegate.mjs index 34eedb4..2d66b13 100644 --- a/tests/Implementation/FsConnectionDelegate.mjs +++ b/tests/Implementation/FsConnectionDelegate.mjs @@ -1,15 +1,13 @@ -'use strict'; +"use strict"; -const fs = require('fs'), - {ConnectionDelegate} = require('../../src/node-process'); +import fs from "fs"; +import ConnectionDelegate from "../../src/node-process/ConnectionDelegate.mjs"; /** * Handle the requests of a connection to control the "fs" module. */ -class FsConnectionDelegate extends ConnectionDelegate -{ - async handleInstruction(instruction, responseHandler, errorHandler) - { +export default class FsConnectionDelegate extends ConnectionDelegate { + async handleInstruction(instruction, responseHandler, errorHandler) { instruction.setDefaultResource(this.extendFsModule(fs)); let value = null; @@ -27,30 +25,27 @@ class FsConnectionDelegate extends ConnectionDelegate responseHandler(value); } - extendFsModule(fs) - { + extendFsModule(fs) { fs.multipleStatSync = (...paths) => paths.map(fs.statSync); - fs.multipleResourcesIsFile = resources => resources.map(resource => resource.isFile()); + fs.multipleResourcesIsFile = (resources) => resources.map((resource) => resource.isFile()); fs.getHeavyPayloadWithNonAsciiChars = () => { - let payload = ''; + let payload = ""; - for (let i = 0 ; i < 1024 ; i++) { - payload += 'a'; + for (let i = 0; i < 1024; i++) { + payload += "a"; } return `😘${payload}😘`; }; - fs.wait = ms => new Promise(resolve => setTimeout(resolve, ms)); + fs.wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); - fs.runCallback = cb => cb(fs); + fs.runCallback = (cb) => cb(fs); - fs.getOption = name => this.options[name]; + fs.getOption = (name) => this.options[name]; return fs; } } - -module.exports = FsConnectionDelegate; diff --git a/tests/Implementation/FsProcessDelegate.php b/tests/Implementation/FsProcessDelegate.php index a323836..d008281 100644 --- a/tests/Implementation/FsProcessDelegate.php +++ b/tests/Implementation/FsProcessDelegate.php @@ -1,9 +1,13 @@ dirPath = realpath(__DIR__.'/resources'); + $this->dirPath = realpath(__DIR__ . '/resources'); $this->filePath = "{$this->dirPath}/file"; - $this->fs = $this->canPopulateProperty('fs') ? new FsWithProcessDelegation : null; + $this->fs = $this->canPopulateProperty('fs') ? new FsWithProcessDelegation() : null; } protected function tearDown(): void @@ -29,7 +35,7 @@ protected function tearDown(): void $this->fs = null; } - /** @test */ + #[Test] public function can_call_method_and_get_its_return_value() { $content = $this->fs->readFileSync($this->filePath, 'utf8'); @@ -37,7 +43,7 @@ public function can_call_method_and_get_its_return_value() $this->assertEquals('Hello world!', $content); } - /** @test */ + #[Test] public function can_get_property() { $constants = $this->fs->constants; @@ -45,7 +51,7 @@ public function can_get_property() $this->assertIsArray($constants); } - /** @test */ + #[Test] public function can_set_property() { $this->fs->foo = 'bar'; @@ -55,7 +61,7 @@ public function can_set_property() $this->assertNull($this->fs->foo); } - /** @test */ + #[Test] public function can_return_basic_resources() { $resource = $this->fs->readFileSync($this->filePath); @@ -63,7 +69,7 @@ public function can_return_basic_resources() $this->assertInstanceOf(BasicResource::class, $resource); } - /** @test */ + #[Test] public function can_return_specific_resources() { $resource = $this->fs->statSync($this->filePath); @@ -71,7 +77,7 @@ public function can_return_specific_resources() $this->assertInstanceOf(Stats::class, $resource); } - /** @test */ + #[Test] public function can_cast_resources_to_string() { $resource = $this->fs->statSync($this->filePath); @@ -80,12 +86,12 @@ public function can_cast_resources_to_string() } /** - * @test * @dontPopulateProperties fs */ + #[Test] public function can_omit_process_delegation() { - $this->fs = new FsWithoutProcessDelegation; + $this->fs = new FsWithoutProcessDelegation(); $resource = $this->fs->statSync($this->filePath); @@ -93,7 +99,7 @@ public function can_omit_process_delegation() $this->assertNotInstanceOf(Stats::class, $resource); } - /** @test */ + #[Test] public function can_use_nested_resources() { $resources = $this->fs->multipleStatSync($this->dirPath, $this->filePath); @@ -107,7 +113,7 @@ public function can_use_nested_resources() $this->assertTrue($isFile[1]); } - /** @test */ + #[Test] public function can_use_multiple_resources_without_confusion() { $dirStats = $this->fs->statSync($this->dirPath); @@ -120,7 +126,7 @@ public function can_use_multiple_resources_without_confusion() $this->assertTrue($fileStats->isFile()); } - /** @test */ + #[Test] public function can_return_multiple_times_the_same_resource() { $stats1 = $this->fs->Stats; @@ -129,10 +135,8 @@ public function can_return_multiple_times_the_same_resource() $this->assertEquals($stats1, $stats2); } - /** - * @test - * @group js-functions - */ + #[Test] + #[Group('js-functions')] public function can_use_js_functions_with_a_body() { $functions = [ @@ -148,20 +152,22 @@ public function can_use_js_functions_with_a_body() } } - /** - * @test - * @group js-functions - */ + #[Test] + #[Group('js-functions')] public function can_use_js_functions_with_parameters() { $functions = [ $this->ignoreUserDeprecation(self::JS_FUNCTION_CREATE_DEPRECATION_PATTERN, function () { - return JsFunction::create(['fs'], " + return JsFunction::create( + ['fs'], + " return 'Callback using arguments: ' + fs.constructor.name; - "); + ", + ); }), - JsFunction::createWithParameters(['fs']) - ->body("return 'Callback using arguments: ' + fs.constructor.name;"), + JsFunction::createWithParameters(['fs'])->body( + "return 'Callback using arguments: ' + fs.constructor.name;", + ), ]; foreach ($functions as $function) { @@ -170,20 +176,20 @@ public function can_use_js_functions_with_parameters() } } - /** - * @test - * @group js-functions - */ + #[Test] + #[Group('js-functions')] public function can_use_js_functions_with_scope() { $functions = [ $this->ignoreUserDeprecation(self::JS_FUNCTION_CREATE_DEPRECATION_PATTERN, function () { - return JsFunction::create(" + return JsFunction::create( + " return 'Callback using scope: ' + foo; - ", ['foo' => 'bar']); + ", + ['foo' => 'bar'], + ); }), - JsFunction::createWithScope(['foo' => 'bar']) - ->body("return 'Callback using scope: ' + foo;"), + JsFunction::createWithScope(['foo' => 'bar'])->body("return 'Callback using scope: ' + foo;"), ]; foreach ($functions as $function) { @@ -192,19 +198,15 @@ public function can_use_js_functions_with_scope() } } - /** - * @test - * @group js-functions - */ + #[Test] + #[Group('js-functions')] public function can_use_resources_in_js_functions() { $fileStats = $this->fs->statSync($this->filePath); $functions = [ - JsFunction::createWithParameters(['fs', 'fileStats' => $fileStats]) - ->body("return fileStats.isFile();"), - JsFunction::createWithScope(['fileStats' => $fileStats]) - ->body("return fileStats.isFile();"), + JsFunction::createWithParameters(['fs', 'fileStats' => $fileStats])->body('return fileStats.isFile();'), + JsFunction::createWithScope(['fileStats' => $fileStats])->body('return fileStats.isFile();'), ]; foreach ($functions as $function) { @@ -213,14 +215,11 @@ public function can_use_resources_in_js_functions() } } - /** - * @test - * @group js-functions - */ + #[Test] + #[Group('js-functions')] public function can_use_async_with_js_functions() { - $function = JsFunction::createWithAsync() - ->body(" + $function = JsFunction::createWithAsync()->body(" await Promise.resolve(); return true; "); @@ -235,10 +234,8 @@ public function can_use_async_with_js_functions() $this->fs->runCallback($function); } - /** - * @test - * @group js-functions - */ + #[Test] + #[Group('js-functions')] public function js_functions_are_sync_by_default() { $function = JsFunction::createWithBody('await null'); @@ -249,7 +246,7 @@ public function js_functions_are_sync_by_default() $this->fs->runCallback($function); } - /** @test */ + #[Test] public function can_receive_heavy_payloads_with_non_ascii_chars() { $payload = $this->fs->getHeavyPayloadWithNonAsciiChars(); @@ -258,9 +255,7 @@ public function can_receive_heavy_payloads_with_non_ascii_chars() $this->assertStringEndsWith('😘', $payload); } - /** - * @test - */ + #[Test] public function node_crash_throws_a_fatal_exception() { self::expectException(\Nesk\Rialto\Exceptions\Node\FatalException::class); @@ -268,9 +263,7 @@ public function node_crash_throws_a_fatal_exception() $this->fs->__inexistantMethod__(); } - /** - * @test - */ + #[Test] public function can_catch_errors() { self::expectException(\Nesk\Rialto\Exceptions\Node\Exception::class); @@ -278,9 +271,7 @@ public function can_catch_errors() $this->fs->tryCatch->__inexistantMethod__(); } - /** - * @test - */ + #[Test] public function catching_a_node_exception_doesnt_catch_fatal_exceptions() { self::expectException(\Nesk\Rialto\Exceptions\Node\FatalException::class); @@ -293,9 +284,9 @@ public function catching_a_node_exception_doesnt_catch_fatal_exceptions() } /** - * @test * @dontPopulateProperties fs */ + #[Test] public function in_debug_mode_node_exceptions_contain_stack_trace_in_message() { $this->fs = new FsWithProcessDelegation(['debug' => true]); @@ -305,17 +296,17 @@ public function in_debug_mode_node_exceptions_contain_stack_trace_in_message() try { $this->fs->tryCatch->__inexistantMethod__(); } catch (Node\Exception $exception) { - $this->assertRegExp($regex, $exception->getMessage()); + $this->assertMatchesRegularExpression($regex, $exception->getMessage()); } try { $this->fs->__inexistantMethod__(); } catch (Node\FatalException $exception) { - $this->assertRegExp($regex, $exception->getMessage()); + $this->assertMatchesRegularExpression($regex, $exception->getMessage()); } } - /** @test */ + #[Test] public function node_current_working_directory_is_the_same_as_php() { $result = $this->fs->accessSync('tests/resources/file'); @@ -323,20 +314,21 @@ public function node_current_working_directory_is_the_same_as_php() $this->assertNull($result); } - /** - * @test - */ + #[Test] public function executable_path_option_changes_the_process_prefix() { self::expectException(\Symfony\Component\Process\Exception\ProcessFailedException::class); - self::expectExceptionMessageMatches('/Error Output:\n=+\n.*__inexistant_process__.*not found/'); + //self::expectExceptionMessageMatches('/Error Output:\n=+\n.*__inexistant_process__.*not found/'); + self::expectExceptionMessageMatches( + '/Error Output:\n=+\n.*__inexistant_process__.*is not recognized as an internal or external command/', + ); new FsWithProcessDelegation(['executable_path' => '__inexistant_process__']); } /** - * @test * @dontPopulateProperties fs */ + #[Test] public function idle_timeout_option_closes_node_once_timer_is_reached() { $this->fs = new FsWithProcessDelegation(['idle_timeout' => 0.5]); @@ -352,9 +344,9 @@ public function idle_timeout_option_closes_node_once_timer_is_reached() } /** - * @test * @dontPopulateProperties fs */ + #[Test] public function read_timeout_option_throws_an_exception_on_long_actions() { self::expectException(\Nesk\Rialto\Exceptions\ReadSocketTimeoutException::class); @@ -365,26 +357,42 @@ public function read_timeout_option_throws_an_exception_on_long_actions() } /** - * @test - * @group logs * @dontPopulateProperties fs */ + #[Test] + #[Group('logs')] public function forbidden_options_are_removed() { + // any, once, atLeastOnce, exactly, atMost + $matcher = $this->atLeast(2); $this->fs = new FsWithProcessDelegation([ 'logger' => $this->loggerMock( - $this->at(0), + $matcher, $this->isLogLevel(), - 'Applying options...', - $this->callback(function ($context) { - $this->assertArrayHasKey('read_timeout', $context['options']); - $this->assertArrayNotHasKey('stop_timeout', $context['options']); - $this->assertArrayNotHasKey('foo', $context['options']); - + $this->callback(function ($message) use ($matcher) { + $numberOfInvocations = $matcher->numberOfInvocations(); + if ($numberOfInvocations === 1) { + $this->assertSame('Applying options...', $message); + } elseif ($numberOfInvocations === 2) { + $this->assertSame('Options applied and merged with defaults', $message); + } + return true; + }), + $this->callback(function ($context) use ($matcher) { + $numberOfInvocations = $matcher->numberOfInvocations(); + if ($numberOfInvocations === 1) { + $this->assertArrayNotHasKey('foo', $context['options']); + $this->assertArrayHasKey('read_timeout', $context['options']); + $this->assertArrayNotHasKey('stop_timeout', $context['options']); + } elseif ($numberOfInvocations === 2) { + $this->assertArrayNotHasKey('foo', $context['options']); + $this->assertArrayHasKey('idle_timeout', $context['options']); + $this->assertArrayHasKey('read_timeout', $context['options']); + $this->assertArrayHasKey('stop_timeout', $context['options']); + } return true; - }) + }), ), - 'read_timeout' => 5, 'stop_timeout' => 0, 'foo' => 'bar', @@ -392,9 +400,9 @@ public function forbidden_options_are_removed() } /** - * @test * @dontPopulateProperties fs */ + #[Test] public function connection_delegate_receives_options() { $this->fs = new FsWithProcessDelegation([ @@ -408,21 +416,18 @@ public function connection_delegate_receives_options() } /** - * @test * @dontPopulateProperties fs */ + #[Test] + #[RequiresOperatingSystem("^(?!Win32|WINNT|Windows).*$")] public function process_status_is_tracked() { - if (PHP_OS === 'WINNT') { - $this->markTestSkipped('This test is not supported on Windows.'); - } - if ((new Process(['which', 'pgrep']))->run() !== 0) { $this->markTestSkipped('The "pgrep" command is not available.'); } $oldPids = $this->getPidsForProcessName('node'); - $this->fs = new FsWithProcessDelegation; + $this->fs = new FsWithProcessDelegation(); $newPids = $this->getPidsForProcessName('node'); $newNodeProcesses = array_values(array_diff($newPids, $oldPids)); @@ -430,14 +435,13 @@ public function process_status_is_tracked() $this->assertCount( 1, $newNodeProcesses, - "One Node process should have been created instead of $newNodeProcessesCount. Try running again." + "One Node process should have been created instead of $newNodeProcessesCount. Try running again.", ); $processKilled = posix_kill($newNodeProcesses[0], SIGKILL); $this->assertTrue($processKilled); - \usleep(10000); # To make sure the process had enough time to be killed. - + \usleep(10_000); # To make sure the process had enough time to be killed. $this->expectException(\Nesk\Rialto\Exceptions\ProcessUnexpectedlyTerminatedException::class); $this->expectExceptionMessage('The process has been unexpectedly terminated.'); @@ -445,70 +449,81 @@ public function process_status_is_tracked() } /** - * @test - * @group logs * @dontPopulateProperties fs */ + #[Test] + #[Group('logs')] public function logger_is_used_when_provided() { $this->fs = new FsWithProcessDelegation([ - 'logger' => $this->loggerMock( - $this->atLeastOnce(), - $this->isLogLevel(), - $this->isType('string') - ), + 'logger' => $this->loggerMock($this->atLeastOnce(), $this->isLogLevel(), $this->isType('string')), ]); } /** - * @test - * @group logs * @dontPopulateProperties fs */ + #[Test] + #[Group('logs')] public function node_console_calls_are_logged() { - $setups = [ - [false, 'Received data on stdout:'], - [true, 'Received a Node log:'], - ]; - + $consoleMessage = 'Hello World!'; + $setups = [[false, "Received data on stdout: $consoleMessage"], [true, "Received a Node log: $consoleMessage"]]; foreach ($setups as [$logNodeConsole, $startsWith]) { + $matcher = $this->atLeast(6); $this->fs = new FsWithProcessDelegation([ 'log_node_console' => $logNodeConsole, 'logger' => $this->loggerMock( - $this->at(5), + $matcher, $this->isLogLevel(), - $this->stringStartsWith($startsWith) + $this->callback(function ($message) use ($matcher, $startsWith) { + $numberOfInvocations = $matcher->numberOfInvocations(); + if ($numberOfInvocations === 6) { + $this->assertSame($startsWith, rtrim($message, "\r\n")); + } + return true; + }), ), ]); - $this->fs->runCallback(JsFunction::createWithBody("console.log('Hello World!')")); + $this->fs->runCallback(JsFunction::createWithBody("console.log('$consoleMessage')")); } } /** - * @test - * @group logs * @dontPopulateProperties fs */ + #[Test] + #[Group('logs')] public function delayed_node_console_calls_and_data_on_standard_streams_are_logged() { + $matcher = $this->atLeast(8); $this->fs = new FsWithProcessDelegation([ 'log_node_console' => true, - 'logger' => $this->loggerMock([ - [$this->at(6), $this->isLogLevel(), $this->stringStartsWith('Received data on stdout:')], - [$this->at(7), $this->isLogLevel(), $this->stringStartsWith('Received a Node log:')], - ]), + 'logger' => $this->loggerMock( + $matcher, + $this->isLogLevel(), + $this->callback(function ($message) use ($matcher) { + $numberOfInvocations = $matcher->numberOfInvocations(); + if ($numberOfInvocations === 7) { + $this->assertStringStartsWith('Received data on stdout: Hello', $message); + } elseif ($numberOfInvocations === 8) { + $this->assertStringStartsWith('Received a Node log:', $message); + } + return true; + }), + ), ]); - $this->fs->runCallback(JsFunction::createWithBody(" - setTimeout(() => { - process.stdout.write('Hello Stdout!'); - console.log('Hello Console!'); - }); - ")); + $javascript = <<<'JSFUNC' + setTimeout(() => { + process.stdout.write('Hello Stdout!'); + console.log('Hello Console!'); + }); + JSFUNC; + $this->fs->runCallback(JsFunction::createWithBody($javascript)); - usleep(10000); // 10ms, to be sure the delayed instructions just above are executed. + \usleep(10_000); // 10ms, to be sure the delayed instructions just above are executed. $this->fs = null; } } diff --git a/tests/TestCase.php b/tests/TestCase.php index 770153e..9a1c89d 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -1,15 +1,17 @@ getName()); + $testMethod = new \ReflectionMethod($this, $this->name()); $docComment = $testMethod->getDocComment(); - if (preg_match('/@dontPopulateProperties (.*)/', $docComment, $matches)) { + if (!empty($docComment) && preg_match('/@dontPopulateProperties (.*)/', $docComment, $matches)) { $this->dontPopulateProperties = array_values(array_filter(explode(' ', $matches[1]))); } } @@ -32,14 +34,15 @@ public function canPopulateProperty(string $propertyName): bool return !in_array($propertyName, $this->dontPopulateProperties); } - public function ignoreUserDeprecation(string $messagePattern, callable $callback) { - set_error_handler( - function (int $errorNumber, string $errorString, string $errorFile, int $errorLine) use ($messagePattern) { - if ($errorNumber !== E_USER_DEPRECATED || preg_match($messagePattern, $errorString) !== 1) { - (new ErrorHandler(true, true, true, true))($errorNumber, $errorString, $errorFile, $errorLine); - } + public function ignoreUserDeprecation(string $messagePattern, callable $callback) + { + set_error_handler(function (int $errorNumber, string $errorString, string $errorFile, int $errorLine) use ( + $messagePattern, + ) { + if ($errorNumber !== E_USER_DEPRECATED || preg_match($messagePattern, $errorString) !== 1) { + (new ErrorHandler(true, true, true, true))($errorNumber, $errorString, $errorFile, $errorLine); } - ); + }); $value = $callback(); @@ -48,24 +51,20 @@ function (int $errorNumber, string $errorString, string $errorFile, int $errorLi return $value; } - public function getPidsForProcessName(string $processName) { + public function getPidsForProcessName(string $processName) + { $pgrep = new Process(['pgrep', $processName]); $pgrep->run(); $pids = explode("\n", $pgrep->getOutput()); - - $pids = array_filter($pids, function ($pid) { - return !empty($pid); - }); - - $pids = array_map(function ($pid) { - return (int) $pid; - }, $pids); + $pids = array_filter($pids, fn($pid) => !empty($pid)); + $pids = array_map(fn($pid) => (int) $pid, $pids); return $pids; } - public function loggerMock($expectations) { + public function loggerMock(InvocationOrder|array $expectations) + { $loggerMock = $this->getMockBuilder(Logger::class) ->setConstructorArgs(['rialto']) ->onlyMethods(['log']) @@ -74,27 +73,24 @@ public function loggerMock($expectations) { $expectations = [func_get_args()]; } - foreach ($expectations as $expectation) { - [$matcher] = $expectation; - $with = array_slice($expectation, 1); - - $loggerMock->expects($matcher) - ->method('log') - ->with(...$with); + foreach ($expectations as $with) { + $matcher = array_shift($with); + $loggerMock->expects($matcher)->method('log')->with(...$with); } return $loggerMock; } - public function isLogLevel(): Callback { - $psrLogLevels = (new ReflectionClass(LogLevel::class))->getConstants(); - $monologLevels = (new ReflectionClass(Logger::class))->getConstants(); + public function isLogLevel(): Callback + { + $psrLogLevels = (new \ReflectionClass(LogLevel::class))->getConstants(); + $monologLevels = (new \ReflectionClass(Logger::class))->getConstants(); $monologLevels = array_intersect_key($monologLevels, $psrLogLevels); return $this->callback(function ($level) use ($psrLogLevels, $monologLevels) { if (is_string($level)) { return in_array($level, $psrLogLevels, true); - } else if (is_int($level)) { + } elseif (is_int($level)) { return in_array($level, $monologLevels, true); } From 005b40cfcc48687742d0e8dfe7923abed61fc7b1 Mon Sep 17 00:00:00 2001 From: Mark Reidenbach Date: Mon, 19 Aug 2024 08:58:31 -0500 Subject: [PATCH 8/8] Revert repository change to zoonru in package.json. Remove unused imports in ImplementationTest.php --- package.json | 5 ++++- tests/ImplementationTest.php | 4 +--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 8edcc03..b277975 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,10 @@ "url": "https://johann.pardanaud.com/" }, "license": "MIT", - "repository": "github:mreiden/rialto", + "repository": { + "type": "git", + "url": "https://github.com/zoonru/rialto.git", + }, "type": "module", "main": "src/node-process/index.mjs", "engines": { diff --git a/tests/ImplementationTest.php b/tests/ImplementationTest.php index 277f6a6..d788735 100644 --- a/tests/ImplementationTest.php +++ b/tests/ImplementationTest.php @@ -4,11 +4,9 @@ namespace Nesk\Rialto\Tests; -use Monolog\Level; -use Monolog\Logger; use Nesk\Rialto\{Data\JsFunction, Exceptions\Node, Data\BasicResource}; use Nesk\Rialto\Tests\Implementation\{FsWithProcessDelegation, FsWithoutProcessDelegation, Resources\Stats}; -use PHPUnit\Framework\Attributes\{Group, RequiresOperatingSystem, RequiresOperatingSystemFamily, Test}; +use PHPUnit\Framework\Attributes\{Group, RequiresOperatingSystem, Test}; use Symfony\Component\Process\Process; final class ImplementationTest extends TestCase