454 lines
23 KiB
PHP
454 lines
23 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Regenerates the canonical Postman collection from Laravel's registered routes.
|
|
*
|
|
* Run from the backend root with:
|
|
* php postman/generate-shopit-collection.php
|
|
*/
|
|
$root = dirname(__DIR__);
|
|
chdir($root);
|
|
|
|
$command = escapeshellarg(PHP_BINARY).' artisan route:list --path=api --json';
|
|
$routeJson = shell_exec($command);
|
|
|
|
if (! is_string($routeJson) || trim($routeJson) === '') {
|
|
fwrite(STDERR, "Unable to read Laravel routes.\n");
|
|
exit(1);
|
|
}
|
|
|
|
$routes = json_decode($routeJson, true, flags: JSON_THROW_ON_ERROR);
|
|
|
|
const TINY_PNG = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==';
|
|
|
|
/** @return array<string, mixed> */
|
|
function jsonBody(array $payload): array
|
|
{
|
|
$raw = json_encode($payload, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
|
$raw = preg_replace('/"\{\{([a-z_]+_id)\}\}"/', '{{$1}}', $raw);
|
|
|
|
return [
|
|
'mode' => 'raw',
|
|
'raw' => $raw,
|
|
'options' => ['raw' => ['language' => 'json']],
|
|
];
|
|
}
|
|
|
|
/** @param array<string, string> $fields
|
|
* @return array<string, mixed>
|
|
*/
|
|
function formDataBody(array $fields, array $fileFields = []): array
|
|
{
|
|
$formData = [];
|
|
|
|
foreach ($fields as $key => $value) {
|
|
$formData[] = ['key' => $key, 'value' => $value, 'type' => 'text'];
|
|
}
|
|
|
|
foreach ($fileFields as $key) {
|
|
$formData[] = ['key' => $key, 'type' => 'file', 'src' => []];
|
|
}
|
|
|
|
return ['mode' => 'formdata', 'formdata' => $formData];
|
|
}
|
|
|
|
/** @return array<string, mixed>|null */
|
|
function bodyFor(string $method, string $uri): ?array
|
|
{
|
|
$key = $method.' '.$uri;
|
|
|
|
$exact = [
|
|
'POST api/auth/google/exchange' => ['oauth_code' => '{{oauth_code}}', 'tenant_codigo' => '{{tenant_code}}'],
|
|
'POST api/register' => ['tenant_codigo' => '{{tenant_code}}', 'nombre_apellido' => 'Usuario Demo', 'email' => '{{user_email}}', 'password' => '{{user_password}}', 'password_confirmation' => '{{user_password}}', 'dni' => '30123456', 'telefono' => '+5491112345678'],
|
|
'POST api/login' => ['email' => '{{user_email}}', 'password' => '{{user_password}}', 'tenant_codigo' => '{{tenant_code}}'],
|
|
'PUT api/me' => ['nombre_apellido' => 'Usuario Demo Actualizado', 'email' => '{{user_email}}', 'dni' => '30123456', 'telefono' => '+5491112345678'],
|
|
'POST api/password/reset-attempts' => ['tenant_codigo' => '{{tenant_code}}', 'email' => '{{user_email}}'],
|
|
'POST api/password/reset-attempts/validate' => ['email' => '{{user_email}}', 'codigo' => '{{reset_code}}'],
|
|
'POST api/password/reset' => ['email' => '{{user_email}}', 'codigo' => '{{reset_code}}', 'password' => '{{user_password}}', 'password_confirmation' => '{{user_password}}'],
|
|
'POST api/clients' => ['code' => 'cliente-demo', 'name' => 'Cliente Demo'],
|
|
'PUT api/clients/{client}' => ['code' => 'cliente-demo', 'name' => 'Cliente Demo Actualizado'],
|
|
'PATCH api/clients/{client}' => ['name' => 'Cliente Demo Actualizado'],
|
|
'POST api/integrations' => ['integration_code' => 'telepagos', 'name' => 'Telepagos', 'url' => 'https://api.example.com', 'integration_data_schema' => ['api_key' => ['required', 'string']], 'requires_client_configuration' => true],
|
|
'PUT api/integrations/{integration}' => ['name' => 'Telepagos', 'url' => 'https://api.example.com', 'requires_client_configuration' => true],
|
|
'PUT api/clients/{client}/integrations/{integration_code}' => ['integration_data' => ['api_key' => 'replace-me']],
|
|
'POST api/menues' => ['code' => 'demo', 'label' => 'Demo', 'parent_menu_code' => null, 'content_type' => 'static', 'static_content_schema' => ['title' => ['required', 'string']], 'route' => '/demo'],
|
|
'PUT api/menues/{menue}' => ['label' => 'Demo actualizado', 'route' => '/demo'],
|
|
'PATCH api/menues/{menue}' => ['label' => 'Demo actualizado'],
|
|
'POST api/{tenant_code}/menues/{menu_code}' => ['static_content' => ['title' => 'Contenido demo']],
|
|
'POST api/webhooks/telepagos/{client}' => ['id' => 'payment-id-demo'],
|
|
'POST api/{tenant_code}/mail-test/send' => ['to' => 'destinatario@example.com', 'subject' => 'Prueba ShopIt', 'message' => 'Correo de prueba enviado desde Postman.'],
|
|
'POST api/tenants/{tenant:codigo}/cart/items' => ['catalog_item_id' => '{{catalog_item_id}}', 'variant_id' => '{{variant_id}}', 'cantidad' => 1],
|
|
'PATCH api/tenants/{tenant:codigo}/cart/items/{cartItem}' => ['cantidad' => 2, 'variant_id' => '{{variant_id}}'],
|
|
'POST api/tenants/{tenant:codigo}/catalog-items/{catalogItem}/variant-options' => ['selected_values' => ['color' => 'azul'], 'cart_item_id' => '{{cart_item_id}}'],
|
|
'POST api/tenants/{tenant:codigo}/compras/start-checkout' => ['cart_id' => '{{cart_id}}'],
|
|
'PATCH api/tenants/{tenant:codigo}/compras/{compra}/customer-data' => ['dni' => '30123456', 'telefono' => '+5491112345678', 'nombre_apellido' => 'Usuario Demo', 'email' => '{{user_email}}'],
|
|
'PATCH api/tenants/{tenant:codigo}/checkout-carts/{cart}/items/{cartItem}' => ['cantidad' => 2],
|
|
'POST api/tenants/{tenant:codigo}/checkout-carts/{cart}/edit' => [],
|
|
'POST api/tenants/{tenant:codigo}/compras/{compra}/payment-intent' => ['method' => 'transfer', 'transfer_payer_dni' => '30123456'],
|
|
'POST api/tenants/{tenant:codigo}/tickets/pdf' => ['ticket_ids' => [1]],
|
|
'POST api/v1/adminapp/login' => ['email' => '{{admin_email}}', 'password' => '{{admin_password}}'],
|
|
'POST api/v1/adminapp/password/reset-attempts' => ['email' => '{{admin_email}}'],
|
|
'POST api/v1/adminapp/password/reset-attempts/validate' => ['email' => '{{admin_email}}', 'codigo' => '{{reset_code}}'],
|
|
'POST api/v1/adminapp/password/reset' => ['email' => '{{admin_email}}', 'codigo' => '{{reset_code}}', 'password' => '{{admin_password}}', 'password_confirmation' => '{{admin_password}}'],
|
|
'PUT api/v1/adminapp/tenant/event' => ['title' => 'Evento Demo', 'location' => 'Buenos Aires', 'dates' => [['date' => '2026-12-01', 'start_time' => '18:00', 'end_time' => '23:00']], 'social_media' => [['code' => 'instagram', 'url' => 'https://instagram.com/example', 'orden' => 0]]],
|
|
'POST api/v1/adminapp/tenant/featured-groups' => ['category_name' => 'Destacados', 'is_featured' => true],
|
|
'PUT api/v1/adminapp/tenant/featured-groups/{featuredGroup}' => ['category_name' => 'Destacados', 'is_featured' => true],
|
|
'POST api/v1/adminapp/tenant/staff' => ['nombre_apellido' => 'Operador Demo', 'dni' => '30123456', 'email' => 'operador@example.com', 'category_ids' => [1]],
|
|
'PUT api/v1/adminapp/tenant/staff/{staff}' => ['nombre_apellido' => 'Operador Demo', 'dni' => '30123456', 'email' => 'operador@example.com', 'category_ids' => [1]],
|
|
'PATCH api/v1/adminapp/tenant/staff/{staff}' => ['nombre_apellido' => 'Operador Demo', 'dni' => '30123456', 'email' => 'operador@example.com', 'category_ids' => [1]],
|
|
'PUT api/v1/adminapp/tenant/website-extras/{websiteExtraCode}' => ['enabled' => true, 'content' => ['title' => 'Contenido demo']],
|
|
'PATCH api/v1/adminapp/tenant/website-extras/{websiteExtraCode}/toggle' => ['enabled' => true],
|
|
'POST api/v1/adminapp/tenant/accommodations' => ['variants' => [['title' => 'Habitación doble', 'description' => 'Dos personas', 'stock' => 10, 'price' => 100000]]],
|
|
'POST api/v1/adminapp/tenant/entries' => ['entries' => [['title' => 'Entrada general', 'description' => 'Acceso general', 'event_date_ids' => [1], 'stock' => 100, 'price' => 25000]]],
|
|
'POST api/v1/adminapp/tenant/foods' => ['variants' => [['event_date_id' => 1, 'schedule' => '21:00', 'service' => 'Cena', 'description' => 'Menú completo', 'stock' => 100, 'price' => 15000]]],
|
|
'POST api/v1/adminapp/tenant/merchandise' => ['items' => [['title' => 'Camiseta', 'description' => 'Camiseta oficial', 'max_units_per_user' => 2, 'variants' => [['color' => 'Azul', 'size' => 'M', 'stock' => 20, 'price' => 30000]]]]],
|
|
'PUT api/v1/adminapp/tenant/desfile/entries' => ['rows' => [['type' => 'General', 'sector' => 'A', 'row' => 1, 'max_seat' => 20, 'price' => 25000]]],
|
|
'PATCH api/v1/adminapp/tenant/desfile/entries/image' => ['is_enabled' => true],
|
|
'POST api/v1/scanner/login' => ['email' => '{{scanner_email}}', 'password' => '{{scanner_password}}'],
|
|
'POST api/v1/scanner/password/reset-attempts' => ['email' => '{{scanner_email}}'],
|
|
'POST api/v1/scanner/password/reset-attempts/validate' => ['email' => '{{scanner_email}}', 'codigo' => '{{reset_code}}'],
|
|
'POST api/v1/scanner/password/reset' => ['email' => '{{scanner_email}}', 'codigo' => '{{reset_code}}', 'password' => '{{scanner_password}}', 'password_confirmation' => '{{scanner_password}}'],
|
|
];
|
|
|
|
if (isset($exact[$key])) {
|
|
return jsonBody($exact[$key]);
|
|
}
|
|
|
|
if ($key === 'POST api/tenants') {
|
|
return jsonBody([
|
|
'client_id' => '{{client_id}}',
|
|
'codigo' => '{{tenant_code}}',
|
|
'nombre' => 'Tenant Demo',
|
|
'dominio' => '{{tenant_domain}}',
|
|
'site_title' => 'ShopIt Demo',
|
|
'primary_color' => '#111827',
|
|
'secondary_color' => '#2563EB',
|
|
'danger_color' => '#DC2626',
|
|
'success_color' => '#16A34A',
|
|
'header_bg_color' => '#FFFFFF',
|
|
'footer_bg_color' => '#111827',
|
|
'header_logo' => TINY_PNG,
|
|
'footer_logo' => TINY_PNG,
|
|
'search_product_layout' => 'column_with_image',
|
|
'search_group_layout' => 'paginated',
|
|
'search_items_per_page' => 12,
|
|
'display_categories' => true,
|
|
'display_seach_bar' => true,
|
|
'display_cart' => true,
|
|
'cart_editing_enabled' => true,
|
|
'website_type_code' => 'shopit',
|
|
]);
|
|
}
|
|
|
|
if (in_array($key, ['PUT api/tenants/{tenant}', 'PATCH api/tenants/{tenant}'], true)) {
|
|
return jsonBody(['nombre' => 'Tenant Demo Actualizado', 'site_title' => 'ShopIt Demo', 'primary_color' => '#111827', 'cart_editing_enabled' => true]);
|
|
}
|
|
|
|
if ($key === 'POST api/tenants/{tenant:codigo}/catalog-items') {
|
|
return jsonBody([
|
|
'type' => 'standard',
|
|
'category_id' => '{{category_id}}',
|
|
'slug' => 'producto-demo',
|
|
'nombre' => 'Producto Demo',
|
|
'descripcion' => 'Producto creado desde Postman',
|
|
'precio' => 10000,
|
|
'inventory_policy' => 'tracked',
|
|
'inventory_subject' => 'product',
|
|
'max_units_per_user' => 5,
|
|
'has_tickets' => false,
|
|
'real_stock' => 100,
|
|
'images' => [TINY_PNG],
|
|
]);
|
|
}
|
|
|
|
if ($key === 'POST api/storage-test/s3/upload') {
|
|
return formDataBody(['path' => 'postman/test-file.png', 'expires_in_minutes' => '60'], ['file']);
|
|
}
|
|
|
|
if ($key === 'POST api/v1/adminapp/tenant/desfile/entries/image') {
|
|
return formDataBody(['is_enabled' => '1'], ['image']);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/** @return array<int, array{key: string, value: string, disabled?: bool}> */
|
|
function queryFor(string $uri): array
|
|
{
|
|
return match ($uri) {
|
|
'api/tenants/bootstrap' => [['key' => 'dominio', 'value' => '{{tenant_domain}}'], ['key' => 'path', 'value' => '/']],
|
|
'api/v1/adminapp/bootstrap/{dominio}', 'api/v1/scanner/bootstrap/{dominio}' => [['key' => 'path', 'value' => '/']],
|
|
'api/tenants/{tenant:codigo}/catalog-items' => [['key' => 'q', 'value' => 'demo'], ['key' => 'page', 'value' => '1']],
|
|
'api/tenants/{tenant:codigo}/catalog-items/{catalogItem}' => [['key' => 'variant_id', 'value' => '{{variant_id}}', 'disabled' => true]],
|
|
'api/tenants/{tenant:codigo}/catalog/featured-groups/{featuredGroup}/items',
|
|
'api/tenants/{tenant:codigo}/categories/{category}' => [['key' => 'page', 'value' => '1']],
|
|
'api/tenants/{tenant:codigo}/compras' => [['key' => 'status', 'value' => 'pending_payment', 'disabled' => true], ['key' => 'page', 'value' => '1']],
|
|
'api/v1/adminapp/tenant/sales', 'api/v1/adminapp/tenant/sales/pdf' => [
|
|
['key' => 'q', 'value' => '', 'disabled' => true],
|
|
['key' => 'status', 'value' => 'confirmed', 'disabled' => true],
|
|
['key' => 'sale_date', 'value' => '2026-12-01', 'disabled' => true],
|
|
['key' => 'sort_by', 'value' => 'date'],
|
|
['key' => 'sort_direction', 'value' => 'desc'],
|
|
['key' => 'page', 'value' => '1'],
|
|
['key' => 'per_page', 'value' => '20'],
|
|
],
|
|
'api/v1/scanner/tickets' => [['key' => 'q', 'value' => '', 'disabled' => true], ['key' => 'page', 'value' => '1'], ['key' => 'per_page', 'value' => '20']],
|
|
'api/storage-test/s3/temporary-url' => [['key' => 'path', 'value' => '{{s3_path}}'], ['key' => 'expires_in_minutes', 'value' => '60']],
|
|
default => [],
|
|
};
|
|
}
|
|
|
|
/** @return array{0: string, 1: string} */
|
|
function folderFor(string $uri, string $action): array
|
|
{
|
|
preg_match('/App\\\\Domains\\\\([^\\\\]+)/', $action, $matches);
|
|
$domain = $matches[1] ?? 'Other';
|
|
|
|
if (str_starts_with($uri, 'api/v1/adminapp/')) {
|
|
return ['Admin App API', $domain];
|
|
}
|
|
|
|
if (str_starts_with($uri, 'api/v1/scanner/')) {
|
|
return ['Scanner API', $domain];
|
|
}
|
|
|
|
if (str_starts_with($uri, 'api/webhooks/')) {
|
|
return ['Webhooks', $domain];
|
|
}
|
|
|
|
if (in_array($domain, ['StorageTest', 'MailTest'], true)) {
|
|
return ['Developer Utilities', $domain];
|
|
}
|
|
|
|
if (in_array($domain, ['Client', 'Integration', 'Menu', 'Tenant'], true) && ! str_contains($uri, '{tenant:codigo}')) {
|
|
return ['Platform Management', $domain];
|
|
}
|
|
|
|
return ['Storefront API', $domain];
|
|
}
|
|
|
|
function humanize(string $value): string
|
|
{
|
|
$value = preg_replace('/Controller$/', '', $value);
|
|
$value = preg_replace('/(?<!^)[A-Z]/', ' $0', (string) $value);
|
|
|
|
return trim(str_replace(['_', '-'], ' ', (string) $value));
|
|
}
|
|
|
|
function requestName(string $method, string $action, bool $multiMethod): string
|
|
{
|
|
$parts = explode('\\', explode('@', $action)[0]);
|
|
$controller = humanize(end($parts));
|
|
$handler = str_contains($action, '@') ? explode('@', $action)[1] : '__invoke';
|
|
$verbs = [
|
|
'index' => 'List', 'store' => 'Create', 'show' => 'Get', 'update' => 'Update',
|
|
'destroy' => 'Delete', 'addItem' => 'Add Item', 'updateItemQuantity' => 'Update Item Quantity',
|
|
'updateCheckoutItem' => 'Update Checkout Cart Item',
|
|
'prepareCheckoutEditing' => 'Prepare Checkout Cart Editing',
|
|
'removeItem' => 'Remove Item', 'search' => 'Search', 'category' => 'Get Category',
|
|
'featuredGroupItems' => 'List Featured Group Items', 'variantOptions' => 'Get Variant Options',
|
|
'startCheckout' => 'Start Checkout', 'updateCustomerData' => 'Update Customer Data',
|
|
'paymentIntent' => 'Create Payment Intent',
|
|
'submitForReview' => 'Submit for Review', 'cancel' => 'Cancel', 'complete' => 'Complete',
|
|
'downloadPdf' => 'Download PDF', 'downloadModificationsPdf' => 'Download Modifications PDF',
|
|
'modifications' => 'List Modifications', 'tickets' => 'List Tickets', 'confirm' => 'Confirm',
|
|
'temporaryUrl' => 'Generate Temporary URL', 'replaceImage' => 'Replace Image',
|
|
'updateImage' => 'Update Image', 'destroyImage' => 'Delete Image', 'showExtra' => 'Get Extra',
|
|
'toggle' => 'Toggle', 'scan' => 'Scan', 'handle' => 'Receive',
|
|
];
|
|
|
|
$name = $handler === '__invoke'
|
|
? $controller
|
|
: (($verbs[$handler] ?? humanize($handler)).' '.$controller);
|
|
|
|
return $multiMethod ? $name.' ('.$method.')' : $name;
|
|
}
|
|
|
|
function pathFor(string $uri): string
|
|
{
|
|
$variables = [
|
|
'tenant:codigo' => 'tenant_code', 'tenant' => 'tenant_id', 'client' => 'client_id',
|
|
'integration_code' => 'integration_code', 'integration' => 'integration_id', 'menue' => 'menu_id',
|
|
'menu_code' => 'menu_code', 'tenant_code' => 'tenant_code', 'catalogItem' => 'catalog_item_id',
|
|
'featuredGroup' => 'featured_group_id', 'category' => 'category_id', 'cartItem' => 'cart_item_id',
|
|
'compra' => 'purchase_id', 'item' => 'purchase_item_id', 'dominio' => 'tenant_domain',
|
|
'sale' => 'sale_id', 'staff' => 'staff_id', 'websiteExtraCode' => 'website_extra_code',
|
|
'accommodation' => 'accommodation_id', 'entry' => 'entry_id', 'food' => 'food_id',
|
|
'merchandise' => 'merchandise_id', 'ticketUuid' => 'ticket_uuid',
|
|
];
|
|
|
|
return preg_replace_callback('/\{([^}]+)\}/', function (array $matches) use ($variables): string {
|
|
$variable = $variables[$matches[1]] ?? strtolower((string) preg_replace('/(?<!^)[A-Z]/', '_$0', $matches[1]));
|
|
|
|
return '{{'.$variable.'}}';
|
|
}, $uri);
|
|
}
|
|
|
|
/** @return array<string, mixed> */
|
|
function authFor(string $uri, array $middleware): ?array
|
|
{
|
|
$protected = count(array_filter(
|
|
$middleware,
|
|
fn (string $item): bool => str_contains($item, 'Authenticate:sanctum'),
|
|
)) > 0;
|
|
|
|
if (! $protected) {
|
|
return null;
|
|
}
|
|
|
|
$variable = str_starts_with($uri, 'api/v1/adminapp/')
|
|
? 'admin_token'
|
|
: (str_starts_with($uri, 'api/v1/scanner/') ? 'scanner_token' : 'token');
|
|
|
|
return ['type' => 'bearer', 'bearer' => [['key' => 'token', 'value' => '{{'.$variable.'}}', 'type' => 'string']]];
|
|
}
|
|
|
|
/** @return array<string, mixed> */
|
|
function tokenCaptureEvent(string $uri): array
|
|
{
|
|
$variable = $uri === 'api/v1/adminapp/login' ? 'admin_token' : ($uri === 'api/v1/scanner/login' ? 'scanner_token' : 'token');
|
|
|
|
return [
|
|
'listen' => 'test',
|
|
'script' => [
|
|
'type' => 'text/javascript',
|
|
'exec' => [
|
|
'if (pm.response.code >= 200 && pm.response.code < 300) {',
|
|
' const payload = pm.response.json();',
|
|
" if (payload.token) pm.collectionVariables.set('{$variable}', payload.token);",
|
|
'}',
|
|
],
|
|
],
|
|
];
|
|
}
|
|
|
|
$tree = [];
|
|
$registeredOperations = 0;
|
|
|
|
foreach ($routes as $route) {
|
|
$methods = array_values(array_filter(explode('|', $route['method']), fn (string $method): bool => $method !== 'HEAD'));
|
|
$multiMethod = count($methods) > 1;
|
|
|
|
foreach ($methods as $method) {
|
|
[$section, $folder] = folderFor($route['uri'], $route['action']);
|
|
$path = pathFor($route['uri']);
|
|
$query = queryFor($route['uri']);
|
|
$enabledQuery = array_values(array_filter($query, fn (array $item): bool => ! ($item['disabled'] ?? false)));
|
|
$queryString = $enabledQuery === [] ? '' : '?'.implode('&', array_map(
|
|
fn (array $item): string => rawurlencode($item['key']).'='.$item['value'],
|
|
$enabledQuery,
|
|
));
|
|
$body = bodyFor($method, $route['uri']);
|
|
$auth = authFor($route['uri'], $route['middleware']);
|
|
$headers = [['key' => 'Accept', 'value' => 'application/json', 'type' => 'text']];
|
|
|
|
if (($body['mode'] ?? null) === 'raw') {
|
|
$headers[] = ['key' => 'Content-Type', 'value' => 'application/json', 'type' => 'text'];
|
|
}
|
|
|
|
$request = [
|
|
'method' => $method,
|
|
'header' => $headers,
|
|
'description' => sprintf(
|
|
"Ruta Laravel: `%s /%s`\n\nControlador: `%s`%s",
|
|
$method,
|
|
$route['uri'],
|
|
$route['action'],
|
|
$auth === null ? '' : "\n\nRequiere autenticación Sanctum.",
|
|
),
|
|
'url' => [
|
|
'raw' => '{{base_url}}/'.$path.$queryString,
|
|
'host' => ['{{base_url}}'],
|
|
'path' => explode('/', $path),
|
|
],
|
|
];
|
|
|
|
if ($query !== []) {
|
|
$request['url']['query'] = $query;
|
|
}
|
|
|
|
if ($body !== null) {
|
|
$request['body'] = $body;
|
|
}
|
|
|
|
if ($auth !== null) {
|
|
$request['auth'] = $auth;
|
|
}
|
|
|
|
$item = [
|
|
'name' => requestName($method, $route['action'], $multiMethod),
|
|
'request' => $request,
|
|
'response' => [],
|
|
];
|
|
|
|
if (in_array($route['uri'], ['api/login', 'api/v1/adminapp/login', 'api/v1/scanner/login'], true)) {
|
|
$item['event'] = [tokenCaptureEvent($route['uri'])];
|
|
}
|
|
|
|
$tree[$section][$folder][] = $item;
|
|
$registeredOperations++;
|
|
}
|
|
}
|
|
|
|
$sectionDescriptions = [
|
|
'Storefront API' => 'API pública y autenticada consumida por el storefront: autenticación, catálogo, carrito, compras y tickets.',
|
|
'Admin App API' => 'Operaciones de administración del tenant. Ejecutá Login primero para completar `admin_token`.',
|
|
'Scanner API' => 'Operaciones de la aplicación de escaneo. Ejecutá Login primero para completar `scanner_token`.',
|
|
'Platform Management' => 'CRUD y configuración de tenants, clientes, menús e integraciones.',
|
|
'Webhooks' => 'Entradas públicas para notificaciones de proveedores externos.',
|
|
'Developer Utilities' => 'Endpoints de diagnóstico de correo y almacenamiento. No deberían exponerse en producción.',
|
|
];
|
|
|
|
$items = [];
|
|
foreach ($tree as $section => $folders) {
|
|
$children = [];
|
|
foreach ($folders as $folder => $requests) {
|
|
$children[] = ['name' => humanize($folder), 'item' => $requests];
|
|
}
|
|
|
|
$items[] = [
|
|
'name' => $section,
|
|
'description' => $sectionDescriptions[$section] ?? '',
|
|
'item' => $children,
|
|
];
|
|
}
|
|
|
|
$variables = [
|
|
'base_url' => 'http://localhost:8000',
|
|
'token' => '', 'admin_token' => '', 'scanner_token' => '',
|
|
'user_email' => 'usuario@example.com', 'user_password' => 'Password!123',
|
|
'admin_email' => 'admin@example.com', 'admin_password' => 'Password!123',
|
|
'scanner_email' => 'scanner@example.com', 'scanner_password' => 'Password!123',
|
|
'tenant_code' => 'demo', 'tenant_id' => '1', 'tenant_domain' => 'demo.test',
|
|
'client_id' => '1', 'integration_id' => '1', 'integration_code' => 'telepagos',
|
|
'menu_id' => '1', 'menu_code' => 'demo', 'catalog_item_id' => '1', 'variant_id' => '1',
|
|
'category_id' => '1', 'featured_group_id' => '1', 'cart_id' => '1', 'cart_item_id' => '1',
|
|
'purchase_id' => '1', 'purchase_item_id' => '1', 'sale_id' => '1', 'staff_id' => '1',
|
|
'website_extra_code' => 'hero', 'accommodation_id' => '1', 'entry_id' => '1', 'food_id' => '1',
|
|
'merchandise_id' => '1', 'ticket_uuid' => '00000000-0000-0000-0000-000000000000',
|
|
'oauth_code' => '00000000-0000-0000-0000-000000000000', 'reset_code' => '1234',
|
|
's3_path' => 'postman/test-file.png',
|
|
];
|
|
|
|
$collection = [
|
|
'info' => [
|
|
'_postman_id' => '76fd6fd2-53b9-4d92-8e02-1ddcc6207fa2',
|
|
'name' => 'ShopIt API — Complete',
|
|
'description' => "Colección canónica generada desde las rutas reales de Laravel. Incluye {$registeredOperations} operaciones HTTP, ejemplos de payload, filtros, archivos y tokens separados para Storefront, Admin App y Scanner.\n\nUso rápido:\n1. Ajustá `base_url` y las credenciales.\n2. Ejecutá el Login de la aplicación correspondiente; el token se guarda automáticamente.\n3. Ajustá los IDs y códigos de las variables de colección.\n\nRegeneración: `php postman/generate-shopit-collection.php`.",
|
|
'schema' => 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json',
|
|
],
|
|
'item' => $items,
|
|
'variable' => array_map(
|
|
fn (string $key, string $value): array => ['key' => $key, 'value' => $value, 'type' => 'string'],
|
|
array_keys($variables),
|
|
array_values($variables),
|
|
),
|
|
];
|
|
|
|
$output = $root.DIRECTORY_SEPARATOR.'ShopIt_API_Postman_Collection.json';
|
|
file_put_contents($output, json_encode($collection, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE).PHP_EOL);
|
|
|
|
fwrite(STDOUT, "Generated {$registeredOperations} operations in {$output}\n");
|