From 50cb2cfe822dbf166323c407e942dc6aa1fc0dce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A0=EC=B0=BD=EC=9A=B1?= Date: Sat, 11 Jul 2026 23:16:13 +0900 Subject: [PATCH] =?UTF-8?q?feat(cloud):=20P1-B=20scaffold=20=E2=80=94=20co?= =?UTF-8?q?mposer=20autoload=20+=20Config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cloud/.gitignore | 4 ++++ cloud/composer.json | 8 ++++++++ cloud/config.example.php | 9 +++++++++ cloud/phpunit.xml | 7 +++++++ cloud/src/Config.php | 18 ++++++++++++++++++ cloud/tests/ConfigTest.php | 24 ++++++++++++++++++++++++ 6 files changed, 70 insertions(+) create mode 100644 cloud/.gitignore create mode 100644 cloud/composer.json create mode 100644 cloud/config.example.php create mode 100644 cloud/phpunit.xml create mode 100644 cloud/src/Config.php create mode 100644 cloud/tests/ConfigTest.php diff --git a/cloud/.gitignore b/cloud/.gitignore new file mode 100644 index 0000000..4cdb9f8 --- /dev/null +++ b/cloud/.gitignore @@ -0,0 +1,4 @@ +/vendor/ +/config.php +/storage/snapshots/* +!/storage/snapshots/.gitkeep diff --git a/cloud/composer.json b/cloud/composer.json new file mode 100644 index 0000000..3115b33 --- /dev/null +++ b/cloud/composer.json @@ -0,0 +1,8 @@ +{ + "name": "move-detect/cloud", + "type": "project", + "require": { "php": ">=8.2" }, + "require-dev": { "phpunit/phpunit": "^11" }, + "autoload": { "psr-4": { "App\\": "src/" } }, + "autoload-dev": { "psr-4": { "App\\Tests\\": "tests/" } } +} diff --git a/cloud/config.example.php b/cloud/config.example.php new file mode 100644 index 0000000..4fc4034 --- /dev/null +++ b/cloud/config.example.php @@ -0,0 +1,9 @@ + 'mysql:host=localhost;dbname=move_detect;charset=utf8mb4', + 'db_user' => 'CHANGEME', + 'db_pass' => 'CHANGEME', + 'snapshot_dir' => __DIR__ . '/storage/snapshots', + 'timestamp_window' => 300, + 'rate_limit_per_min' => 60, +]; diff --git a/cloud/phpunit.xml b/cloud/phpunit.xml new file mode 100644 index 0000000..b08c6a5 --- /dev/null +++ b/cloud/phpunit.xml @@ -0,0 +1,7 @@ + + + + tests + + diff --git a/cloud/src/Config.php b/cloud/src/Config.php new file mode 100644 index 0000000..61fee96 --- /dev/null +++ b/cloud/src/Config.php @@ -0,0 +1,18 @@ +a['db_dsn'] ?? ''); } + public function dbUser(): string { return (string)($this->a['db_user'] ?? ''); } + public function dbPass(): string { return (string)($this->a['db_pass'] ?? ''); } + public function snapshotDir(): string { return (string)($this->a['snapshot_dir'] ?? __DIR__ . '/../storage/snapshots'); } + public function nonceTtl(): int { return (int)($this->a['nonce_ttl'] ?? 86400); } + public function timestampWindow(): int { return (int)($this->a['timestamp_window'] ?? 300); } + public function rateLimitPerMin(): int { return (int)($this->a['rate_limit_per_min'] ?? 60); } +} diff --git a/cloud/tests/ConfigTest.php b/cloud/tests/ConfigTest.php new file mode 100644 index 0000000..c5562bc --- /dev/null +++ b/cloud/tests/ConfigTest.php @@ -0,0 +1,24 @@ + 'sqlite::memory:']); + $this->assertSame('sqlite::memory:', $c->dbDsn()); + $this->assertSame(300, $c->timestampWindow()); + $this->assertSame(60, $c->rateLimitPerMin()); + $this->assertSame(86400, $c->nonceTtl()); + } + + public function testOverrides(): void + { + $c = Config::fromArray(['db_dsn' => 'x', 'timestamp_window' => 120, 'rate_limit_per_min' => 30]); + $this->assertSame(120, $c->timestampWindow()); + $this->assertSame(30, $c->rateLimitPerMin()); + } +}