routesync 1.0.41 → 1.0.43
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/dist/cli.js +130 -219
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -8363,180 +8363,18 @@ var LaravelRouteParser = class {
|
|
|
8363
8363
|
const projectRoot = import_path.default.resolve(import_path.default.dirname(filePath), "..");
|
|
8364
8364
|
const extractModels = options.extractModels ? "true" : "false";
|
|
8365
8365
|
const phpScript = `<?php
|
|
8366
|
+
error_reporting(0);
|
|
8366
8367
|
require __DIR__.'/vendor/autoload.php';
|
|
8367
8368
|
$app = require_once __DIR__.'/bootstrap/app.php';
|
|
8368
|
-
$kernel = $app->make(
|
|
8369
|
+
$kernel = $app->make(Illuminate\\Contracts\\Console\\Kernel::class);
|
|
8369
8370
|
$kernel->bootstrap();
|
|
8370
8371
|
|
|
8371
|
-
$result = [
|
|
8372
|
-
|
|
8373
|
-
|
|
8374
|
-
|
|
8375
|
-
function rsync_get_source(ReflectionFunctionAbstract $ref): ?string {
|
|
8376
|
-
$file = $ref->getFileName();
|
|
8377
|
-
$start = $ref->getStartLine();
|
|
8378
|
-
$end = $ref->getEndLine();
|
|
8379
|
-
if (!$file || $start === false || $end === false) return null;
|
|
8380
|
-
return implode('', array_slice(file($file), $start - 1, $end - $start + 1));
|
|
8381
|
-
}
|
|
8382
|
-
|
|
8383
|
-
/**
|
|
8384
|
-
* Try to resolve responseMetadata from a Resource class.
|
|
8385
|
-
* Checks (in order):
|
|
8386
|
-
* 1. PHP 8 #[RouteSyncResponse] attribute on class
|
|
8387
|
-
* 2. @mixin docblock
|
|
8388
|
-
* 3. Constructor parameter type hint \u2190 NEW
|
|
8389
|
-
* 4. $this->resource @var docblock \u2190 NEW
|
|
8390
|
-
* 5. Strip Resource suffix \u2192 match AppModels*
|
|
8391
|
-
* 6. toArray() field vs DB column intersection
|
|
8392
|
-
*/
|
|
8393
|
-
function rsync_infer_from_resource(string $resourceClass, bool $collection): ?array {
|
|
8394
|
-
if (!class_exists($resourceClass)) return null;
|
|
8395
|
-
$resRef = new ReflectionClass($resourceClass);
|
|
8396
|
-
|
|
8397
|
-
// 1. PHP 8 attribute
|
|
8398
|
-
foreach ($resRef->getAttributes() as $attr) {
|
|
8399
|
-
$short = class_basename($attr->getName());
|
|
8400
|
-
if (in_array($short, ['Response', 'RouteSyncResponse'])) {
|
|
8401
|
-
$args = $attr->getArguments();
|
|
8402
|
-
$type = $args[0] ?? $args['type'] ?? $args['model'] ?? $args['response'] ?? null;
|
|
8403
|
-
if ($type) return ['type' => class_basename($type), 'collection' => $collection];
|
|
8404
|
-
}
|
|
8405
|
-
}
|
|
8406
|
-
|
|
8407
|
-
// 2. @mixin docblock
|
|
8408
|
-
$doc = $resRef->getDocComment();
|
|
8409
|
-
if ($doc && preg_match('/@mixins+([\\\\w]+)/', $doc, $m)) {
|
|
8410
|
-
return ['type' => class_basename($m[1]), 'collection' => $collection];
|
|
8411
|
-
}
|
|
8412
|
-
|
|
8413
|
-
// 3. Constructor parameter type hint: __construct(User $user)
|
|
8414
|
-
if ($resRef->hasMethod('__construct')) {
|
|
8415
|
-
$ctor = $resRef->getMethod('__construct');
|
|
8416
|
-
foreach ($ctor->getParameters() as $param) {
|
|
8417
|
-
$ptype = $param->getType();
|
|
8418
|
-
if ($ptype && !$ptype->isBuiltin()) {
|
|
8419
|
-
$cn = $ptype->getName();
|
|
8420
|
-
if (is_subclass_of($cn, 'IlluminateDatabaseEloquentModel')) {
|
|
8421
|
-
return ['type' => class_basename($cn), 'collection' => $collection];
|
|
8422
|
-
}
|
|
8423
|
-
}
|
|
8424
|
-
}
|
|
8425
|
-
}
|
|
8426
|
-
|
|
8427
|
-
// 4. $this->resource @var docblock in class body or toArray()
|
|
8428
|
-
$classDoc = $resRef->getDocComment() ?: '';
|
|
8429
|
-
foreach (['toArray', 'toResponse'] as $mname) {
|
|
8430
|
-
if ($resRef->hasMethod($mname)) {
|
|
8431
|
-
$src = rsync_get_source($resRef->getMethod($mname)) ?? '';
|
|
8432
|
-
$classDoc .= $src;
|
|
8433
|
-
}
|
|
8434
|
-
}
|
|
8435
|
-
if (preg_match('/@vars+([\\\\w]+)s+$(?:resource|model)/', $classDoc, $m)) {
|
|
8436
|
-
$cn = ltrim($m[1], '\\');
|
|
8437
|
-
$fqcn = str_contains($cn, '\\') ? $cn : 'App\\Models\\' . $cn;
|
|
8438
|
-
if (class_exists($fqcn)) {
|
|
8439
|
-
return ['type' => class_basename($fqcn), 'collection' => $collection];
|
|
8440
|
-
}
|
|
8441
|
-
}
|
|
8442
|
-
|
|
8443
|
-
// 5. Strip Resource suffix \u2192 AppModels<Name>
|
|
8444
|
-
$inferredName = preg_replace('/Resource$/', '', class_basename($resourceClass));
|
|
8445
|
-
if ($inferredName) {
|
|
8446
|
-
$mc = 'App\\Models\\' . $inferredName;
|
|
8447
|
-
if (class_exists($mc)) {
|
|
8448
|
-
return ['type' => $inferredName, 'collection' => $collection];
|
|
8449
|
-
}
|
|
8450
|
-
}
|
|
8451
|
-
|
|
8452
|
-
// 6. toArray() field vs DB column intersection
|
|
8453
|
-
if ($resRef->hasMethod('toArray')) {
|
|
8454
|
-
$src = rsync_get_source($resRef->getMethod('toArray')) ?? '';
|
|
8455
|
-
preg_match_all('/['"]([a-zA-Z0-9_]+)['"]s*=>/', $src, $km);
|
|
8456
|
-
$resFields = array_unique($km[1] ?? []);
|
|
8457
|
-
if (!empty($resFields)) {
|
|
8458
|
-
$bestModel = null; $bestScore = 0;
|
|
8459
|
-
$modelsPath = app_path('Models');
|
|
8460
|
-
if (is_dir($modelsPath)) {
|
|
8461
|
-
foreach (IlluminateSupportFacadesFile::allFiles($modelsPath) as $mf) {
|
|
8462
|
-
$mn = preg_replace('/.php$/', '', $mf->getFilename());
|
|
8463
|
-
$mc = 'App\\Models\\' . $mn;
|
|
8464
|
-
if (!class_exists($mc)) continue;
|
|
8465
|
-
try {
|
|
8466
|
-
$mi = new $mc();
|
|
8467
|
-
$cols = array_column(IlluminateSupportFacadesSchema::getColumns($mi->getTable()), 'name');
|
|
8468
|
-
$score = count(array_intersect($resFields, $cols));
|
|
8469
|
-
if ($score > $bestScore) { $bestScore = $score; $bestModel = $mn; }
|
|
8470
|
-
} catch (Exception $e) {}
|
|
8471
|
-
}
|
|
8472
|
-
}
|
|
8473
|
-
if ($bestModel && $bestScore > 0) {
|
|
8474
|
-
return ['type' => $bestModel, 'collection' => $collection];
|
|
8475
|
-
}
|
|
8476
|
-
}
|
|
8477
|
-
}
|
|
8478
|
-
|
|
8479
|
-
return null;
|
|
8480
|
-
}
|
|
8481
|
-
|
|
8482
|
-
/**
|
|
8483
|
-
* Try to resolve responseMetadata directly from controller method source.
|
|
8484
|
-
* Handles cases where no Resource class is used at all.
|
|
8485
|
-
*/
|
|
8486
|
-
function rsync_infer_from_source(?string $source): ?array {
|
|
8487
|
-
if (!$source) return null;
|
|
8488
|
-
|
|
8489
|
-
// return new SomeResource($x)
|
|
8490
|
-
if (preg_match('/returns+news+([a-zA-Z0-9_]+Resource)s*(/', $source, $m)) {
|
|
8491
|
-
$rc = 'App\\Http\\Resources\\' . $m[1];
|
|
8492
|
-
$result = rsync_infer_from_resource($rc, false);
|
|
8493
|
-
if ($result) return $result;
|
|
8494
|
-
}
|
|
8495
|
-
|
|
8496
|
-
// SomeResource::collection(...)
|
|
8497
|
-
if (preg_match('/([a-zA-Z0-9_]+Resource)::collections*(/', $source, $m)) {
|
|
8498
|
-
$rc = 'App\\Http\\Resources\\' . $m[1];
|
|
8499
|
-
$result = rsync_infer_from_resource($rc, true);
|
|
8500
|
-
if ($result) return $result;
|
|
8501
|
-
}
|
|
8502
|
-
|
|
8503
|
-
// ->paginate() or ->simplePaginate() with Resource
|
|
8504
|
-
if (preg_match('/([a-zA-Z0-9_]+Resource)::collection.*paginate/s', $source, $m)) {
|
|
8505
|
-
$rc = 'App\\Http\\Resources\\' . $m[1];
|
|
8506
|
-
$result = rsync_infer_from_resource($rc, true);
|
|
8507
|
-
if ($result) { $result['paginated'] = true; return $result; }
|
|
8508
|
-
}
|
|
8509
|
-
|
|
8510
|
-
// response()->json(['token' => ..., 'user' => ...]) \u2014 inline array
|
|
8511
|
-
// Extract top-level keys and try to match a model
|
|
8512
|
-
if (preg_match('/response()s*->s*jsons*(s*[([^]]{0,800})]/', $source, $jsonMatch)) {
|
|
8513
|
-
preg_match_all('/['"]([a-zA-Z0-9_]+)['"]s*=>/', $jsonMatch[1], $km);
|
|
8514
|
-
$keys = array_unique($km[1] ?? []);
|
|
8515
|
-
if (!empty($keys)) {
|
|
8516
|
-
$bestModel = null; $bestScore = 0;
|
|
8517
|
-
foreach (IlluminateSupportFacadesFile::allFiles(app_path('Models')) as $mf) {
|
|
8518
|
-
$mn = preg_replace('/.php$/', '', $mf->getFilename());
|
|
8519
|
-
$mc = 'App\\Models\\' . $mn;
|
|
8520
|
-
if (!class_exists($mc)) continue;
|
|
8521
|
-
try {
|
|
8522
|
-
$mi = new $mc();
|
|
8523
|
-
$cols = array_column(IlluminateSupportFacadesSchema::getColumns($mi->getTable()), 'name');
|
|
8524
|
-
$camelCols = array_map(fn($c) => lcfirst(str_replace('_', '', ucwords($c, '_'))), $cols);
|
|
8525
|
-
$score = count(array_intersect($keys, array_merge($cols, $camelCols)));
|
|
8526
|
-
if ($score > $bestScore) { $bestScore = $score; $bestModel = $mn; }
|
|
8527
|
-
} catch (Exception $e) {}
|
|
8528
|
-
}
|
|
8529
|
-
if ($bestModel && $bestScore >= 2) {
|
|
8530
|
-
return ['type' => $bestModel, 'collection' => false];
|
|
8531
|
-
}
|
|
8532
|
-
}
|
|
8533
|
-
}
|
|
8534
|
-
|
|
8535
|
-
return null;
|
|
8536
|
-
}
|
|
8537
|
-
|
|
8538
|
-
// \u2500\u2500\u2500 Main Route Loop \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
8372
|
+
$result = [
|
|
8373
|
+
'routes' => [],
|
|
8374
|
+
'models' => []
|
|
8375
|
+
];
|
|
8539
8376
|
|
|
8377
|
+
// Extract Routes
|
|
8540
8378
|
$routes = app('router')->getRoutes();
|
|
8541
8379
|
foreach ($routes as $route) {
|
|
8542
8380
|
if (!str_starts_with($route->uri(), 'api/')) continue;
|
|
@@ -8552,21 +8390,17 @@ foreach ($routes as $route) {
|
|
|
8552
8390
|
}
|
|
8553
8391
|
|
|
8554
8392
|
$schema = [];
|
|
8555
|
-
$responseMetadata = null;
|
|
8556
8393
|
$action = $route->getAction();
|
|
8557
|
-
|
|
8558
8394
|
if (isset($action['uses']) && is_string($action['uses']) && str_contains($action['uses'], '@')) {
|
|
8559
8395
|
list($controller, $method) = explode('@', $action['uses']);
|
|
8560
8396
|
if (class_exists($controller)) {
|
|
8561
8397
|
try {
|
|
8562
8398
|
$reflector = new ReflectionMethod($controller, $method);
|
|
8563
|
-
|
|
8564
|
-
// \u2500\u2500 Request schema from FormRequest \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
8565
8399
|
foreach ($reflector->getParameters() as $param) {
|
|
8566
8400
|
$type = $param->getType();
|
|
8567
8401
|
if ($type && !$type->isBuiltin()) {
|
|
8568
8402
|
$className = $type->getName();
|
|
8569
|
-
if (is_subclass_of($className, '
|
|
8403
|
+
if (is_subclass_of($className, 'Illuminate\\\\Foundation\\\\Http\\\\FormRequest')) {
|
|
8570
8404
|
$request = new $className();
|
|
8571
8405
|
if (method_exists($request, 'rules')) {
|
|
8572
8406
|
$schema = $request->rules();
|
|
@@ -8575,96 +8409,170 @@ foreach ($routes as $route) {
|
|
|
8575
8409
|
}
|
|
8576
8410
|
}
|
|
8577
8411
|
|
|
8578
|
-
//
|
|
8579
|
-
|
|
8580
|
-
|
|
8581
|
-
|
|
8412
|
+
// Parse PHP 8 Attributes for Response Metadata
|
|
8413
|
+
$responseMetadata = null;
|
|
8414
|
+
$attributes = $reflector->getAttributes();
|
|
8415
|
+
foreach ($attributes as $attr) {
|
|
8416
|
+
$attrName = $attr->getName();
|
|
8417
|
+
$shortName = class_basename($attrName);
|
|
8418
|
+
|
|
8419
|
+
if (in_array($shortName, ['Response', 'RouteSyncResponse'])) {
|
|
8582
8420
|
$args = $attr->getArguments();
|
|
8583
|
-
|
|
8421
|
+
|
|
8422
|
+
$type = null;
|
|
8423
|
+
if (isset($args[0])) {
|
|
8424
|
+
$type = $args[0];
|
|
8425
|
+
} elseif (isset($args['type'])) {
|
|
8426
|
+
$type = $args['type'];
|
|
8427
|
+
} elseif (isset($args['model'])) {
|
|
8428
|
+
$type = $args['model'];
|
|
8429
|
+
} elseif (isset($args['response'])) {
|
|
8430
|
+
$type = $args['response'];
|
|
8431
|
+
}
|
|
8432
|
+
|
|
8433
|
+
$collection = false;
|
|
8434
|
+
if (isset($args[1])) {
|
|
8435
|
+
$collection = (bool) $args[1];
|
|
8436
|
+
} elseif (isset($args['collection'])) {
|
|
8437
|
+
$collection = (bool) $args['collection'];
|
|
8438
|
+
}
|
|
8439
|
+
|
|
8584
8440
|
if ($type) {
|
|
8585
|
-
$
|
|
8586
|
-
|
|
8441
|
+
$responseMetadata = [
|
|
8442
|
+
'type' => class_basename($type),
|
|
8443
|
+
'collection' => $collection
|
|
8444
|
+
];
|
|
8587
8445
|
break;
|
|
8588
8446
|
}
|
|
8589
8447
|
}
|
|
8590
8448
|
}
|
|
8591
8449
|
|
|
8592
|
-
$
|
|
8450
|
+
$fileName = $reflector->getFileName();
|
|
8451
|
+
$startLine = $reflector->getStartLine();
|
|
8452
|
+
$endLine = $reflector->getEndLine();
|
|
8453
|
+
$methodSource = null;
|
|
8593
8454
|
|
|
8594
|
-
|
|
8595
|
-
|
|
8596
|
-
$
|
|
8455
|
+
if ($fileName && $startLine !== false && $endLine !== false) {
|
|
8456
|
+
$lines = file($fileName);
|
|
8457
|
+
$methodSource = implode("", array_slice($lines, $startLine - 1, $endLine - $startLine + 1));
|
|
8597
8458
|
}
|
|
8598
8459
|
|
|
8599
|
-
//
|
|
8600
|
-
if (
|
|
8601
|
-
|
|
8602
|
-
|
|
8603
|
-
|
|
8604
|
-
|
|
8460
|
+
// Resource Discovery
|
|
8461
|
+
if (!$responseMetadata && $methodSource) {
|
|
8462
|
+
$resourceName = null;
|
|
8463
|
+
$collection = false;
|
|
8464
|
+
|
|
8465
|
+
if (preg_match('/return\\s+new\\s+([a-zA-Z0-9_]+Resource)/', $methodSource, $matches)) {
|
|
8466
|
+
$resourceName = $matches[1];
|
|
8467
|
+
} elseif (preg_match('/return\\s+([a-zA-Z0-9_]+Resource)::collection/', $methodSource, $matches)) {
|
|
8468
|
+
$resourceName = $matches[1];
|
|
8469
|
+
$collection = true;
|
|
8470
|
+
}
|
|
8471
|
+
|
|
8472
|
+
if ($resourceName) {
|
|
8473
|
+
$resourceClass = 'App\\\\Http\\\\Resources\\\\' . $resourceName;
|
|
8474
|
+
if (class_exists($resourceClass)) {
|
|
8475
|
+
$resReflector = new ReflectionClass($resourceClass);
|
|
8476
|
+
$resAttrs = $resReflector->getAttributes();
|
|
8477
|
+
foreach ($resAttrs as $attr) {
|
|
8478
|
+
$shortName = class_basename($attr->getName());
|
|
8479
|
+
if (in_array($shortName, ['Response', 'RouteSyncResponse'])) {
|
|
8480
|
+
$args = $attr->getArguments();
|
|
8481
|
+
$type = $args[0] ?? $args['type'] ?? $args['model'] ?? $args['response'] ?? null;
|
|
8482
|
+
if ($type) {
|
|
8483
|
+
$responseMetadata = [
|
|
8484
|
+
'type' => class_basename($type),
|
|
8485
|
+
'collection' => $collection
|
|
8486
|
+
];
|
|
8487
|
+
}
|
|
8488
|
+
}
|
|
8489
|
+
}
|
|
8490
|
+
|
|
8491
|
+
if (!$responseMetadata) {
|
|
8492
|
+
$docComment = $resReflector->getDocComment();
|
|
8493
|
+
if ($docComment && preg_match('/@mixin\\s+([\\\\a-zA-Z0-9_]+)/', $docComment, $mixinMatches)) {
|
|
8494
|
+
$responseMetadata = [
|
|
8495
|
+
'type' => class_basename($mixinMatches[1]),
|
|
8496
|
+
'collection' => $collection
|
|
8497
|
+
];
|
|
8498
|
+
}
|
|
8499
|
+
}
|
|
8605
8500
|
}
|
|
8606
8501
|
}
|
|
8607
8502
|
}
|
|
8608
8503
|
|
|
8609
|
-
|
|
8504
|
+
// Fallback: Try to parse $request->validate([...]) from source code
|
|
8505
|
+
if (empty($schema) && $methodSource) {
|
|
8506
|
+
if (preg_match('/\\$request->validate\\s*\\(\\s*\\[(.*?)\\]\\s*\\)/s', $methodSource, $matches)) {
|
|
8507
|
+
$rulesString = $matches[1];
|
|
8508
|
+
preg_match_all('/[\\'"]([a-zA-Z0-9_.*]+)[\\'"]\\s*=>\\s*[\\'"](.*?)[\\'"]/', $rulesString, $ruleMatches);
|
|
8509
|
+
if (!empty($ruleMatches[1])) {
|
|
8510
|
+
foreach ($ruleMatches[1] as $index => $field) {
|
|
8511
|
+
$schema[$field] = $ruleMatches[2][$index];
|
|
8512
|
+
}
|
|
8513
|
+
}
|
|
8514
|
+
}
|
|
8515
|
+
}
|
|
8516
|
+
} catch (\\Exception $e) {}
|
|
8610
8517
|
}
|
|
8611
8518
|
}
|
|
8612
8519
|
|
|
8613
8520
|
foreach ($methods as $method) {
|
|
8614
|
-
$nameParts = explode('/', preg_replace('/^api
|
|
8615
|
-
$resource = preg_replace('
|
|
8521
|
+
$nameParts = explode('/', preg_replace('/^api\\//', '', $route->uri()));
|
|
8522
|
+
$resource = preg_replace('/\\{.*\\}/', '', $nameParts[0]);
|
|
8616
8523
|
if (empty($resource)) $resource = 'api';
|
|
8617
8524
|
|
|
8525
|
+
$name = $resource . '.' . strtolower($method);
|
|
8526
|
+
|
|
8618
8527
|
$result['routes'][] = [
|
|
8619
|
-
'name'
|
|
8620
|
-
'method'
|
|
8621
|
-
'path'
|
|
8622
|
-
'auth'
|
|
8528
|
+
'name' => $route->getName() ?: $name,
|
|
8529
|
+
'method' => $method,
|
|
8530
|
+
'path' => '/' . preg_replace('/^api\\//', '', $route->uri()),
|
|
8531
|
+
'auth' => $auth,
|
|
8623
8532
|
'middleware' => $middlewares,
|
|
8624
|
-
'schema'
|
|
8625
|
-
'response'
|
|
8533
|
+
'schema' => empty($schema) ? null : ['rules' => $schema],
|
|
8534
|
+
'response' => $responseMetadata
|
|
8626
8535
|
];
|
|
8627
8536
|
}
|
|
8628
8537
|
}
|
|
8629
8538
|
|
|
8630
|
-
//
|
|
8631
|
-
|
|
8539
|
+
// Extract Models if requested
|
|
8632
8540
|
$extractModels = ${extractModels};
|
|
8633
8541
|
if ($extractModels) {
|
|
8634
8542
|
$modelsPath = app_path('Models');
|
|
8635
8543
|
if (is_dir($modelsPath)) {
|
|
8636
|
-
$files =
|
|
8544
|
+
$files = \\Illuminate\\Support\\Facades\\File::allFiles($modelsPath);
|
|
8637
8545
|
foreach ($files as $file) {
|
|
8638
|
-
$class = 'App
|
|
8639
|
-
$class = preg_replace('
|
|
8546
|
+
$class = 'App\\\\Models\\\\' . str_replace('/', '\\\\', $file->getRelativePathname());
|
|
8547
|
+
$class = preg_replace('/\\.php$/', '', $class);
|
|
8640
8548
|
|
|
8641
|
-
if (class_exists($class) && is_subclass_of($class, 'Illuminate
|
|
8549
|
+
if (class_exists($class) && is_subclass_of($class, 'Illuminate\\\\Database\\\\Eloquent\\\\Model')) {
|
|
8642
8550
|
try {
|
|
8643
8551
|
$reflection = new ReflectionClass($class);
|
|
8644
8552
|
if ($reflection->isAbstract()) continue;
|
|
8645
8553
|
|
|
8646
|
-
$model
|
|
8647
|
-
$table
|
|
8648
|
-
$columns
|
|
8554
|
+
$model = new $class();
|
|
8555
|
+
$table = $model->getTable();
|
|
8556
|
+
$columns = \\Illuminate\\Support\\Facades\\Schema::getColumns($table);
|
|
8649
8557
|
|
|
8650
8558
|
$parsedColumns = [];
|
|
8651
8559
|
foreach ($columns as $col) {
|
|
8652
8560
|
$parsedColumns[] = [
|
|
8653
|
-
'name'
|
|
8654
|
-
'type'
|
|
8655
|
-
'nullable' => $col['nullable']
|
|
8561
|
+
'name' => $col['name'],
|
|
8562
|
+
'type' => $col['type'],
|
|
8563
|
+
'nullable' => $col['nullable']
|
|
8656
8564
|
];
|
|
8657
8565
|
}
|
|
8658
8566
|
|
|
8659
8567
|
$result['models'][] = [
|
|
8660
|
-
'name'
|
|
8661
|
-
'table'
|
|
8568
|
+
'name' => class_basename($class),
|
|
8569
|
+
'table' => $table,
|
|
8662
8570
|
'columns' => $parsedColumns,
|
|
8663
|
-
'hidden'
|
|
8571
|
+
'hidden' => $model->getHidden(),
|
|
8664
8572
|
'appends' => $model->getAppends(),
|
|
8665
|
-
'casts'
|
|
8573
|
+
'casts' => $model->getCasts()
|
|
8666
8574
|
];
|
|
8667
|
-
} catch (Exception $e) {}
|
|
8575
|
+
} catch (\\Exception $e) {}
|
|
8668
8576
|
}
|
|
8669
8577
|
}
|
|
8670
8578
|
}
|
|
@@ -8675,13 +8583,16 @@ echo json_encode($result);
|
|
|
8675
8583
|
const scriptPath = import_path.default.join(projectRoot, "routesync-extractor-temp.php");
|
|
8676
8584
|
try {
|
|
8677
8585
|
await import_fs_extra.default.writeFile(scriptPath, phpScript);
|
|
8678
|
-
const stdout = (0, import_child_process.execSync)(`php routesync-extractor-temp.php`, {
|
|
8586
|
+
const stdout = (0, import_child_process.execSync)(`php routesync-extractor-temp.php 2>/dev/null`, {
|
|
8679
8587
|
cwd: projectRoot,
|
|
8680
8588
|
encoding: "utf-8",
|
|
8681
8589
|
maxBuffer: 1024 * 1024 * 10
|
|
8682
8590
|
});
|
|
8683
8591
|
await import_fs_extra.default.remove(scriptPath);
|
|
8684
|
-
const
|
|
8592
|
+
const trimmed = stdout.trim();
|
|
8593
|
+
const jsonStart = trimmed.indexOf("{");
|
|
8594
|
+
if (jsonStart === -1) throw new Error("No JSON output from PHP script");
|
|
8595
|
+
const parsed = JSON.parse(trimmed.slice(jsonStart));
|
|
8685
8596
|
return {
|
|
8686
8597
|
routes: parsed.routes || [],
|
|
8687
8598
|
models: parsed.models || []
|