create-isotope-app 1.2.7 → 1.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-isotope-app",
3
- "version": "1.2.7",
3
+ "version": "1.2.8",
4
4
  "description": "Atomic-based PHP & React hybrid framework for ATOMS GAMING",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -11,4 +11,8 @@ DB_PASS=
11
11
  # Environment
12
12
  APP_ENV=development
13
13
  APP_DEBUG=true
14
+
15
+ # Isotope Bridge (Use for remote DB proxying)
16
+ # ISX_BRIDGE_URL=https://your-domain.jp/core/Bridge.php
17
+ # ISX_BRIDGE_TOKEN=your_secure_random_token
14
18
  `;
@@ -4,7 +4,7 @@ export const readmeMd = () => `<div align="center">
4
4
 
5
5
  # Isotope: Atomic Fusion
6
6
 
7
- [![npm version](https://img.shields.io/badge/version-1.0.0-blue.svg)](https://www.npmjs.com/package/create-isotope-app)
7
+ [![npm version](https://img.shields.io/badge/version-1.2.8-blue.svg)](https://www.npmjs.com/package/create-isotope-app)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
9
  [![Build Status](https://img.shields.io/badge/build-passing-brightgreen.svg)](https://github.com/atoms-gaming/isotope)
10
10
  [![PHP Version](https://img.shields.io/badge/PHP-%3E%3D8.0-777bb4.svg)](https://www.php.net/)
@@ -51,6 +51,21 @@ export default function Page({ message }) {
51
51
  }
52
52
  \`\`\`
53
53
 
54
+ ## 🌉 Isotope Bridge (Local Proxy)
55
+
56
+ Bypass remote database connection restrictions (e.g., Lolipop/Shared Hosting) by proxying SQL queries over HTTP(S).
57
+
58
+ ### Configuration (.env)
59
+
60
+ \`\`\`env
61
+ # Isotope Bridge Settings
62
+ ISX_BRIDGE_URL=https://your-production-domain.com/core/Bridge.php
63
+ ISX_BRIDGE_TOKEN=your_secure_random_token
64
+ \`\`\`
65
+
66
+ - **How it works**: When \`ISX_BRIDGE_URL\` is set, Isotope automatically proxies \`Database::query()\` calls to the production server.
67
+ - **Security**: Always use a strong \`ISX_BRIDGE_TOKEN\` and keep it secret.
68
+
54
69
  ### ⚛️ Quantum Fusion (SSR/CSR)
55
70
  - **Server Components (Default)**: Rendered by PHP. Zero JS overhead.
56
71
  - **Client Components**: Interactive UI using React hydration.
@@ -4,11 +4,24 @@ namespace Isotope;
4
4
  use PDO;
5
5
  use PDOException;
6
6
 
7
+ /**
8
+ * リモートからのレスポンスをPDOStatement風に扱うためのクラス
9
+ */
10
+ class RemoteStatement {
11
+ private $data;
12
+ public function __construct($data) { $this->data = $data; }
13
+ public function fetchAll() { return $this->data; }
14
+ public function execute() { return true; }
15
+ }
16
+
7
17
  class Database {
8
18
  private static $instance = null;
9
19
  private $connection;
10
20
 
11
21
  private function __construct() {
22
+ // ブリッジが有効な場合はPDO接続をスキップ
23
+ if ($this->shouldBridge()) return;
24
+
12
25
  $host = $_ENV['DB_HOST'] ?? 'localhost';
13
26
  $db = $_ENV['DB_NAME'] ?? 'isotope_db';
14
27
  $user = $_ENV['DB_USER'] ?? 'root';
@@ -26,11 +39,14 @@ class Database {
26
39
  try {
27
40
  $this->connection = new PDO($dsn, $user, $pass, $options);
28
41
  } catch (PDOException $e) {
29
- // In a real app, you might want to log this instead of throwing
30
42
  throw new PDOException($e->getMessage(), (int)$e->getCode());
31
43
  }
32
44
  }
33
45
 
46
+ private function shouldBridge() {
47
+ return !empty($_ENV['ISX_BRIDGE_URL']) && (isset($_ENV['DB_HOST']) && str_ends_with($_ENV['DB_HOST'], '.lan') || ($_ENV['APP_ENV'] ?? '') === 'development');
48
+ }
49
+
34
50
  public static function getInstance() {
35
51
  if (self::$instance === null) {
36
52
  self::$instance = new self();
@@ -38,14 +54,49 @@ class Database {
38
54
  return self::$instance->connection;
39
55
  }
40
56
 
41
- /**
42
- * Helper for quick queries
43
- */
57
+ private static function getInstanceInstance() {
58
+ if (self::$instance === null) {
59
+ self::$instance = new self();
60
+ }
61
+ return self::$instance;
62
+ }
63
+
44
64
  public static function query($sql, $params = []) {
45
- $db = self::getInstance();
65
+ $instance = self::getInstanceInstance();
66
+
67
+ // ブリッジ条件に合致する場合はHTTPリクエストを発行
68
+ if ($instance->shouldBridge()) {
69
+ return self::bridgeQuery($sql, $params);
70
+ }
71
+
72
+ $db = $instance->connection;
46
73
  $stmt = $db->prepare($sql);
47
74
  $stmt->execute($params);
48
75
  return $stmt;
49
76
  }
77
+
78
+ private static function bridgeQuery($sql, $params) {
79
+ $url = $_ENV['ISX_BRIDGE_URL'];
80
+ $token = $_ENV['ISX_BRIDGE_TOKEN'] ?? '';
81
+
82
+ $ch = curl_init($url);
83
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
84
+ curl_setopt($ch, CURLOPT_POST, true);
85
+ curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
86
+ 'action' => 'db_query',
87
+ 'params' => ['sql' => $sql, 'params' => $params],
88
+ 'token' => $token
89
+ ]));
90
+ curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
91
+
92
+ $response = curl_exec($ch);
93
+ $result = json_decode($response, true);
94
+
95
+ if (!$result || !($result['success'] ?? false)) {
96
+ throw new \\Exception("Bridge Error: " . ($result['error'] ?? 'Unknown error'));
97
+ }
98
+
99
+ return new RemoteStatement($result['data']);
100
+ }
50
101
  }
51
102
  `;
@@ -1,15 +1,37 @@
1
1
  export const bridgePhp = () => `<?php
2
2
  header('Content-Type: application/json');
3
+ require_once 'Kernel.php';
4
+ \\Isotope\\Kernel::loadEnv();
5
+
3
6
  if ($_SERVER['REQUEST_METHOD'] === 'POST') {
4
7
  $input = json_decode(file_get_contents('php://input'), true);
5
8
  $action = $input['action'] ?? null;
6
9
  $params = $input['params'] ?? [];
7
-
8
- if ($action && is_callable($action)) {
9
- $result = $action(...$params);
10
- echo json_encode(['success' => true, 'data' => $result]);
11
- } else {
12
- echo json_encode(['success' => false, 'error' => 'Action not found']);
10
+ $token = $input['token'] ?? null;
11
+
12
+ // トークンによる保護
13
+ $expectedToken = $_ENV['ISX_BRIDGE_TOKEN'] ?? '';
14
+ if ($expectedToken && $token !== $expectedToken) {
15
+ echo json_encode(['success' => false, 'error' => 'Unauthorized']);
16
+ exit;
17
+ }
18
+
19
+ try {
20
+ if ($action === 'db_query') {
21
+ $sql = $params['sql'];
22
+ $sqlParams = $params['params'] ?? [];
23
+ // サーバー内部ネットワークから本物のDBへクエリ実行
24
+ $result = \\Isotope\\Database::query($sql, $sqlParams)->fetchAll();
25
+ echo json_encode(['success' => true, 'data' => $result]);
26
+ } elseif ($action && is_callable($action)) {
27
+ // その他のRPC呼び出し
28
+ $result = $action(...$params);
29
+ echo json_encode(['success' => true, 'data' => $result]);
30
+ } else {
31
+ echo json_encode(['success' => false, 'error' => 'Action not found']);
32
+ }
33
+ } catch (\\Exception $e) {
34
+ echo json_encode(['success' => false, 'error' => $e->getMessage()]);
13
35
  }
14
36
  exit;
15
37
  }